Giter Site home page Giter Site logo

go-plist's Introduction

plist - A pure Go property list transcoder coverage report

INSTALL

$ go get howett.net/plist

FEATURES

  • Supports encoding/decoding property lists (Apple XML, Apple Binary, OpenStep and GNUStep) from/to arbitrary Go types

USE

package main
import (
	"howett.net/plist"
	"os"
)
func main() {
	encoder := plist.NewEncoder(os.Stdout)
	encoder.Encode(map[string]string{"hello": "world"})
}

go-plist's People

Contributors

artoria2e5 avatar bobrnor avatar dhowett avatar fwal avatar grahammiln avatar kenjitakahashi avatar lpusok avatar marsoft avatar tomsellers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-plist's Issues

How to decode bplist?

I'm trying to write a universal bplist decode for windows by go-list.

But It seems that it doesn't work:

package main
import (
    "github.com/DHowett/go-plist"
    "os"
    "fmt"
    "io/ioutil"
    "bytes"
)
func main() {
    if len(os.Args) != 2 {
        fmt.Println("decoder.exe [Info.plist]")
        return
    }
    filename := os.Args[1]
    filebuf,err := ioutil.ReadFile(filename)
    if err != nil{
        fmt.Println(err)
        return
    }
    var bval interface{}
    reader := bytes.NewReader(filebuf)
    decoder := plist.NewDecoder(reader)
    decoder.Decode(bval)
    fmt.Println(bval)
}

bval will be nil.

Should I know the plist file content?

Such as

package main
import (
    "github.com/DHowett/go-plist"
    "os"
    "fmt"
    "io/ioutil"
    "bytes"
)
func main() {
    if len(os.Args) != 2 {
        fmt.Println("decoder.exe [Info.plist]")
        return
    }
    filename := os.Args[1]
    filebuf,err := ioutil.ReadFile(filename)
    if err != nil{
        fmt.Println(err)
        return
    }

    type sparseBundleHeader struct {
        CFBundleName        string `plist:"CFBundleName"`
        CFBundleExecuteable string `plist:"CFBundleExecuteable"`
    }
    var bval sparseBundleHeader
    reader := bytes.NewReader(filebuf)
    decoder := plist.NewDecoder(reader)
    decoder.Decode(bval)
    fmt.Println(bval)
}

will crash:

panic: reflect: reflect.Value.SetString using unaddressable value [recovered]
        panic: interface conversion: string is not error: missing method Error

More lenient unmarshal type rules

I'm playing with using this package to unmarshal plist files output by the Day One app. They are a bit quirky in that the data types in their plist file change depending on the data. So for example, in one file a value might be <integer> but in another <real>.

I tried to handle this by making my struct fields float64 thinking that the less specific integer should unmarshal into this just fine. Alas, it did not.

list: type mismatch: tried to decode integer into value of type float64

I'd rather not fall back to unmarshalling this as generic XML. Any chance there is a workaround or some change that could be made to your package to support this scenario? Open to any recommendations you have.

Cannot parse a plist containing a key with an empty string

My first attempt with this pkg was trying to parse Apple's Software Update feed at https://swscan.apple.com/content/catalogs/others/index-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.

It's a dictionary plist, containing a dict called Products, and all of its items are dictionaries keyed by an identifier. There are several hundred entries in this list, and one of them (041-4728) contains a key that is empty, ie. <key></key>

You can see it by grepping:
curl https://swscan.apple.com/content/catalogs/others/index-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog | grep -C 20 \<key\>\<\/key\>

Trying to parse this plist I get a 0 returned for the format and the error: plist: error parsing XML property list: missing key in dictionary:

go-plist/xml.go

Lines 268 to 270 in c619543

if key == "" {
panic(errors.New("missing key in dictionary"))
}

Having dealt heavily with plists as a sysadmin for years, this if the first "empty key" I've ever encountered. I've been able to use Python's plistlib and Objective-C's Foundation libs to parse this same plist (even though I can't actually "get to" the data in this key). While I realize it's inane to have an empty key in a plist, is there a way that go-plist could handle this bizarre situation?

Go source missing

$ go get github.com/DHowett/go-plist
gopkg/src/github.com/DHowett/go-plist/marshal.go:4:2: no Go source files in /usr/local/go/src/pkg/encoding

It seems a go path searching problem?

Go 1.1.2 darwin x86_64

add flag to flatten a single-value array

I'm currently using this library to create plists for launchd. In a couple of locations, the specification says <dictionary [of something] or array of dictionaries [of the same thing]>. I can't imagine launchd is the only place to do this. It would be nice to be able to have a flag flattensingle such that, given

type Foo map[string]string

type Dict struct {
    Bar []Foo `plist:",omitempty,flattensingle"`
}

func main() {
    d := Dict{
        Bar: []Foo{
            Foo{
                "name": "one",
                "num":  "two",
            },
        },
    }

    o, e := plist.MarshalIndent(d, plist.XMLFormat, "    ")
    fmt.Println(e)
    fmt.Println(string(o))
}

The output would be

<plist version="1.0">
    <dict>
        <key>Bar</key>
        <dict>
            <key>name</key>
            <string>one</string>
            <key>num</key>
            <string>two</string>
        </dict>
    </dict>
</plist>

Rather than what it is now:

<plist version="1.0">
    <dict>
        <key>Bar</key>
        <array>
            <dict>
                <key>name</key>
                <string>one</string>
                <key>num</key>
                <string>two</string>
            </dict>
        </array>
    </dict>
</plist>

Module naming in go.mod uses the module "howett.net/plist" instead of "github.com/DHowett/go-plist"

Summary:
The go.mod defines the module name as "howett.net/plist". The code is hosted and viewable at github.com/DHowett/go-plist , but a "go get" from the Github address will not work due to the discrepancy.

The readme does say to use the personal website instead of Github.com, but this is somewhat of a security issue: It would be easy to have a completely different codebase on howett.net, due to a compromise or other issue. It would take very conscientious users to make sure that the code gotten from that address always matches the expected code from Github.

Expected behavior:
Code available on Github is usable from Github.

Observed behavior:
The code is available, but not usable, from Github. In order to use the module, it must be gotten from a 3rd site.

gitlab.howett.net down?

Looks like the site is down and go get is failing.
Error:

go: howett.net/[email protected]: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/*
fatal: unable to access 'https://gitlab.howett.net/go/plist.git/': Failed to connect to gitlab.howett.net port 443: Connection timed out

@DHowett Can you please help me out here?

XMLFormat encoded boolean values are not self-closing tags

I'm using go-plist to generate a LaunchAgent plist. The struct definition for this plist is as follows:

type Application struct {
	Name      string   `plist:"Label"`
	Arguments []string `plist:"ProgramArguments"`
	RunAtLoad bool     `plist:"RunAtLoad"`
}

Given some example application data, the following plist is generated:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>Label</key>
		<string>com.example.app</string>
		<key>ProgramArguments</key>
		<array>
			<string>/some/path/to/running/the/app</string>
		</array>
		<key>RunAtLoad</key>
		<true></true>
	</dict>
</plist>

When running launchctl load to test this setup, an invalid plist error is returned.

$ launchctl load -w ~/Library/LaunchAgents/com.example.app.plist
$HOME/Library/LaunchAgents/com.example.app.plist: Invalid property list

Changing the plist to:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>Label</key>
		<string>com.example.app</string>
		<key>ProgramArguments</key>
		<array>
			<string>/some/path/to/running/the/app</string>
		</array>
		<key>RunAtLoad</key>
		<true/>
	</dict>
</plist>

(self closing <true/> tag), makes the above command succeed.

I've had a quick look into xml_generator.go, and I have a feeling this is related to golang/go#21399.

Decode nested arrays

Thank you for this useful package. I try to decode this plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>time</key>
        <integer>0</integer>
        <key>level</key>
        <integer>0</integer>
        <key>pose</key>
        <integer>3</integer>
        <key>asanas</key>
        <array>
            <dict>
                <key>folderName</key>
                <string>033</string>
                <key>time</key>
                <integer>45</integer>
            </dict>
            <dict>
                <key>folderName</key>
                <string>017</string>
                <key>time</key>
                <integer>45</integer>
            </dict>
        </array>
    </dict>
</array>
</plist>

I have structs:

type workoutAsana struct {
    Id          string  `plist:"folderName"`
    Duration    int     `plist:"time"`
}

type workout struct {
    IsLong      int `plist:"time"`
    Level       int `plist:"level"`
    PoseType    int `plist:"pose"`
    Asanas      []workoutAsana `plist:"asanas"`
}

When I decode input file, I get:

plist: type mismatch: tried to decode string into value of type int

Problem is in decoding Asanas

Asanas      []workoutAsana `plist:"asanas"`

How I can do it? Thanks in advance.

Int key value

Hi! It's a pity, but it does not work in my case ...
I have source bplist structure like this:

<key>DictionaryRes</key>
	<dict>
		<key>1</key>
         		<integer>10023</integer>
		<key>2</key>
	        	<integer>20234</integer>
		<key>3</key>
			<integer>350023</integer>
	</dict>

xml bool not working properly

In xml, bool types are encoded as string. If i set go type to bool. It doesn't work, always returns false. But if i set go type to string, it returns yes as string. But i want it to decode to bool type. Also it seems like plist.Unmarshal doesn't call the struct's UnmarshalPlist method either. I could use a auxiliary struct to fix this inside UnmarshalPlist method.

Cannot 'go get' using go 1.11 modules

Dear Go-plist, I hit a slight bump using GO111MODULE=on go get github.com/dhowett/go-plist:

go: finding github.com/dhowett/go-plist latest
go: github.com/dhowett/[email protected]: parsing go.mod: unexpected module path "howett.net/plist"
go: error loading module requirements

Have you an idea on what is causing that? 😃

how to define nested structure

I got a nested structure that formed like <dict><dict><array><dict></dict></array></dict></dict>, and I can't get the innermost dict parsed appropriately, how do I define the struct while parsing this structure?

Unmarshal plist with duplicate keys results in panic

When attempting to unmarshal a plist that contains duplicate keys, a panic is hit.

Example code:

package main

import (
	"fmt"

	plist "github.com/DHowett/go-plist"
)

var duplicateKeyPlist = `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PayloadIdentifier</key>
	<string>foo</string>
	<key>PayloadIdentifier</key>
	<string>bar</string>
</dict>
</plist>
`

func main() {

	unmarshaledPlist := make(map[string]interface{})
	_, err := plist.Unmarshal([]byte(duplicateKeyPlist), &unmarshaledPlist)
	if err != nil {
		fmt.Printf("Error: %+v\n", err)
		return
	}

	return
}

The following panic stack trace is returned:

panic: reflect: reflect.Value.Set using unaddressable value [recovered]
	panic: interface conversion: string is not error: missing method Error

goroutine 1 [running]:
plistbug/vendor/github.com/DHowett/go-plist.(*Decoder).Decode.func1(0xc420045ef0)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/decode.go:32 +0x8f
panic(0x10db060, 0xc42000e3a0)
	/usr/local/Cellar/go/1.10.1/libexec/src/runtime/panic.go:502 +0x229
reflect.flag.mustBeAssignable(0x94)
	/usr/local/Cellar/go/1.10.1/libexec/src/reflect/value.go:234 +0x15c
reflect.Value.Set(0x10e2760, 0xc42000e380, 0x94, 0x10db060, 0xc42000e390, 0x98)
	/usr/local/Cellar/go/1.10.1/libexec/src/reflect/value.go:1367 +0x2f
plistbug/vendor/github.com/DHowett/go-plist.(*Decoder).unmarshal(0xc42000a0c0, 0x111ad80, 0xc42000e330, 0x10e2760, 0xc42000e380, 0x94)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/unmarshal.go:107 +0xbc9
plistbug/vendor/github.com/DHowett/go-plist.(*Decoder).unmarshalDictionary(0xc42000a0c0, 0xc42007a390, 0x10e4660, 0xc42000c028, 0x195)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/unmarshal.go:265 +0x127
plistbug/vendor/github.com/DHowett/go-plist.(*Decoder).unmarshal(0xc42000a0c0, 0x111ab00, 0xc42007a390, 0x10d5cc0, 0xc42000c028, 0x16)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/unmarshal.go:196 +0x8a9
plistbug/vendor/github.com/DHowett/go-plist.(*Decoder).Decode(0xc42000a0c0, 0x10d5cc0, 0xc42000c028, 0x0, 0x0)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/decode.go:76 +0x27f
plistbug/vendor/github.com/DHowett/go-plist.Unmarshal(0xc42009c000, 0x125, 0x140, 0x10d5cc0, 0xc42000c028, 0x140, 0x0, 0x0)
	/Users/<myname>/Go/src/plistbug/vendor/github.com/DHowett/go-plist/decode.go:116 +0xd0
main.main()
	/Users/<myname>/Go/src/plistbug/main.go:25 +0xb7
exit status 2

Disappearing commits?

It seems that my changes from #19 went into abyss.

You're not --force pushing to master, are you :-)?

The text parser is difficult to follow and does not emit good error messages.

Consider re-implementing as a true lexer/parser pair.

<document> ::= <element>

<element> ::= <dictionary> | <array> | <data> | <extension> | <string>

<dictionary> ::= "{" <dictionary-body> "}"
<dictionary-body> ::= <dictionary-pair> | <dictionary-pair> <dictionary-body>
<dictionary-pair> ::= <string> "=" <element> ";"

<array> ::= "(" <array-body> ")"
<array-body> ::= <element> <opt-comma> | <element> "," <array-body>
<opt-comma> ::= "," | ""

<data> ::= "<" <base64-string> ">"
<base64-character> ::= "A" | "B" | ...
<base64-string> ::= <base64-character> | <base64-character> <base64-string>

<extension> ::= "<" "*" <extension-body> ">"
<extension-body> ::= "I" <extended-integer> | "R" <extended-real> | "B" <extended-bool> | "D" <extended-date>

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<integer> ::= <digit> | <digit> <integer>
<extended-integer> ::= <integer> | "-" <integer>

<extended-real> ::= <some floating point rules>

<extended-bool> ::= "Y" | "N"

<extended-date> ::= ...

<string> ::= '"' <quoted-string> '"' | <unquoted-string>
<quoted-character> ::= "A" | "B" | "'"
<quoted-string> ::= <quoted-character> | <quoted-character> <quoted-string>
<unquoted-character> ::= "A" | "B" | ...
<unquoted-string> ::= <unquoted-character> | <unquoted-character> <unquoted-string>

Missing support for GNUstep <[ base64data ]>

GNUstep plists have a more efficient data encoding, and it is the <[ base64data ]> format:

GNUstep source that emits the format:
https://github.com/gnustep/libs-base/blob/753c907938c2a8c4d00cf0fbe01b7e0d020f0064/Source/NSPropertyList.m#L1951-L1956

GNUstep source that parses the format:
https://github.com/gnustep/libs-base/blob/753c907938c2a8c4d00cf0fbe01b7e0d020f0064/Source/NSPropertyList.m#L1202-L1277

(I wish there is a newer documentation page for the GNUstep format, but I have been unable to locate it.)

howett.net serves an invalid cert.

With Go 1.5, I get:

$ go get howett.net/plist
package howett.net/plist: unrecognized import path "howett.net/plist"

and running go get with -v shows that there is an invalid cert served at howett.net.

The only solution is to go get -insecure but this is not done by many automated tools.. so it really blocks automatic acquisition of the package. Can this be fixed ? :)

thanks!

Release v1.0

Evaluate what plist needs to do to reach 1.0.

  • Consider looking at the XML parser and bringing it in line with the text parser.
  • Look at the number of buffer copies and full reads we're doing for text and binary
    • Only XML needs a streaming buffer; binary and text now need to read the whole document and retain references to it.

marshal byte array failed

import (
	"log"
	"testing"

	dhplist "howett.net/plist"
)

type ObjectInfo struct {
	ID [12]byte
}

func TestMarshal(t *testing.T) {
	var Object ObjectInfo
	body, err := dhplist.MarshalIndent(&Object, dhplist.XMLFormat, "")
	if err != nil {
		log.Printf("error %+v", err)
		t.Error("error marshal")
	} else {
		log.Printf("body %s", body)
	}
}

test result
error reflect: call of reflect.Value.Bytes on array Value
--- FAIL: TestMarshal (0.00s)
app_test.go:19: error marshal

Canonical howett.net/plist package is not "go gettable"

I am running into an issue with dep ensure in which dep expects the howett.net/plist package to be "go gettable", in other words, that it follows the same "Remote import paths" lookup rules expected by go get. It turns out this package is not following these rules properly.

The end result is that dep ensure returns the following error:

$ dep ensure
...
✗ unable to deduce repository and source type for "howett.net/plist": unable to read metadata: go-import metadata not found

Which is a cryptic version of the more understandable error printed by go get howett.net/plist:

$ go get howett.net/plist
package howett.net/plist: unrecognized import path "howett.net/plist" (parse https://howett.net/plist?go-get=1: no go-import meta tags ())

Unfortunately this means I can't use howett.net/plist as my canonical import with dep right now, since dep currently does not support custom package names in its constraint solver; a detailed discussion can be found at golang/dep#1267 but tl;dr, it doesn't seem like dep plans on supporting packages that are not "go gettable".

Fortunately this is fairly easily resolved by adding a /plist URI to howett.net that responds with something (HTML?) containing:

<meta name="go-import" content="howett.net/plist git https://github.com/DHowett/go-plist">

I'm not sure if that used to be there and disappeared or if dep changed its behavior, but could this be added (back?) to your domain?

The only other option I have is to move over to github.com/DHowett/go-plist, but I read in #22 that you explicitly do not want that name to be used.

How to handle unknown types?

Apple's Provisioning Profile plists sometimes contain variable types. E.g., AssociatedDomains for an app are sometimes Arrays and sometimes Strings. So if we have an interface:

type Profile struct {
 AssociatedDomains []string `plist:com.apple.associated.domains`
}

We will get an error if we try to decode this and the AssociatedDomains are a string.

Is there some way to handle this case?

Various panics found through go-fuzz

Hi,

Just wanted to let you that I tested go-plist using go-fuzz and the following code snippet:

func Fuzz(data []byte) int {
    buf := bytes.NewReader(data)

    var obj interface{}
    if err := NewDecoder(buf).Decode(&obj); err != nil {
        return 0
    }
    return 1
}

The tool found several panics. In order to reproduce this, you can find the files here in my Google Drive: https://drive.google.com/file/d/0B8eVqk16QdZ6Y21mTm8zZnVGZlE/view

The .output files contain the respective stack traces. The file without any suffix contains the actual data fed to the Fuzz function. The .quoted file contains the file content as string that is usable in unit tests.

plist to xml

Is the an easy way to dump a generic plist to an xml file?

Nested array - CustomURL - CFBundleURLSchemes

Unable to reach to the custom URL values as seen below.

Screen Shot 2019-08-15 at 10 14 40 PM

Is there any way to capture them? I've reached to this result: [{[myapp myapp2]}] but i'll need to strip it and it's not efficient.

type CFBundleURLTypes struct {
	URLS []string `plist:"CFBundleURLSchemes"`
}

type iosPlist struct {
	CFBundleName         string             `plist:"CFBundleName"`
	CFBundleDisplayName  string             `plist:"CFBundleDisplayName"`
	CFBundleVersion      string             `plist:"CFBundleVersion"`
	CFBundleShortVersion string             `plist:"CFBundleShortVersionString"`
	CFBundleIdentifier   string             `plist:"CFBundleIdentifier"`
	CFBundleURLSchemes   []CFBundleURLTypes `plist:"CFBundleURLTypes"`
}

Handle <data> elements

I don't believe I am able to parse tags.

An example.

...
myItem
3483984-8dfjk===
...

Edit: Let me be more clear... I am able to parse into a []byte, however, when I string() and then fmt.Println() the item, it is illegible. The original text is base64.

Set line length of base64 data

I want to write a mobileconfig configuration profile using this library. In particular I want to add a few Certificate Payloads to a configuration profile. The specifications (page 19) for PayloadContent says that the certificate should be base64 encoded with a line length of 52. Unfortunately if I use a byte slice for the certificate data, the library just outputs everything on a single line.

Would you see a way how we could make this possible?

Marshalling happens in reverse order.

Hello. This is my data structure:

type FileVault2EnablePlist struct {
	FileVaultCredentials
	AdditionalUsers []FileVaultCredentials `plist:"AdditionalUsers,omitempty"`
}

type FileVaultCredentials struct {
	Username string `plist:"Username"`
	Password string `plist:"Password"`
}

This is the code that adds the data to it:

       rootUser := FileVaultCredentials{
		Username: supportUsername,
		Password: supportPassword,
	}

	additionalUser := FileVaultCredentials{
		Username: userToAddUsername,
		Password: userToAddPassword,
	}

	var additionalUsers []FileVaultCredentials
	additionalUsers = append(additionalUsers, additionalUser)

	usersToEnablePlist := &FileVault2EnablePlist{
		FileVaultCredentials: rootUser,
		AdditionalUsers:      additionalUsers,
	}

This is how I marshal it:

plistMacOS, err := plist.MarshalIndent(usersToEnablePlist, plist.XMLFormat, "\t")

When I print it, I get the plist with the data in the reverse order.

	fmt.Println("FileVaultEnablePlist:", string(plistMacOS))

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>AdditionalUsers</key>
		<array>
			<dict>
				<key>Password</key>
				<string>standardUserPassword</string>
				<key>Username</key>
				<string>standardUser</string>
			</dict>
		</array>
		<key>Password</key>
		<string>supportPassword</string>
		<key>Username</key>
		<string>support</string>
	</dict>
</plist>

Hopefully I'm doing something obviously wrong.

Here is my data structure simply printed with Println:

fmt.Println("DEBUG PLIST:", usersToEnablePlist)
DEBUG PLIST: &{{support supportPassword} [{standardUser standardUserPassword}]}

Everything looks in the correct order in the data structure.

Reversing it from my data structure makes zero difference in the output.

type FileVault2EnablePlist struct {
	AdditionalUsers []FileVaultCredentials `plist:"AdditionalUsers,omitempty"`
	FileVaultCredentials
}
type FileVaultCredentials struct {
	Password string `plist:"Password"`
	Username string `plist:"Username"`
}

Println will correctly print the data structure elements in the reverse order:

fmt.Println("DEBUG PLIST:", usersToEnablePlist)
DEBUG PLIST: &{[{standardUserPassword standardUser}] {supportPassword support}}

Which makes no difference to Marshal:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>AdditionalUsers</key>
		<array>
			<dict>
				<key>Password</key>
				<string>standardUserPassword</string>
				<key>Username</key>
				<string>standardUser</string>
			</dict>
		</array>
		<key>Password</key>
		<string>supportPassword</string>
		<key>Username</key>
		<string>support</string>
	</dict>
</plist>

Thanks for the library, first of all.
Do you have any ideas? Am I screwing up something?

unmarshal into map with int keys results in panic

Unmarshaling into a map with int keys will result in a panic.
Although this key type is expressly forbidden, it would be more friendly to return an error in this case, or at least produce a panic message that's clearer than this:

panic: reflect.Value.Convert: value of type string cannot be converted to type int [recovered]
	panic: interface conversion: string is not error: missing method Error

Example code:

https://play.golang.org/p/Qd8TRd2C0LV

Interface-unmarshaling a self-referential array/dict will overflow the stack

Found via fuzzing;

	"bplist00\xd6\x01\x02\x03\x04\x05\x06\a\n\v\f\x0f" +
	"\x1aX0o0leansTdataTdate" +
	"VfloatsXintarrayWstr" +
	"ings\xa2\b\t\t\bD\x01\x02\x03\x043A\xb8Eux" +
	"\x00\x00\x00\xa2\r\x0e\"B\x00\x00\x00#@P\x00\x00\x00\x00\x00\x00" +
	"\xaa\x10\x11\x12\x13\x14\x00\x10\x00\x00\x19\x10\x01\x10\b\x10\x10\x10 \x10" +
	"@\x10\x02\x10\t\x10\x11\x10!\x10A\xa2\x1b\x1c\\Hello" +
	", ASCIIi\x00H\x00e\x00l\x00l\x00o\x00," +
	"\x00 N\x16uL\b\x15\x1e#(/8@CDEJSV" +
	"[doqsuwy{}\u007f\x81\x83\x86\x93\x01\x01\x00\x00\x00" +
	"\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
	"\xa6"

Byte summary case isn't handled

When parsing the output of the command defaults read this parser breaks when going over what I'm calling "byte summaries"

It looks like this:

keyName = {length = 1163, bytes = 0x62706c69 73743030 d4010203 04050607 ... 00000000 00000397 };

I think it would be sufficient to parse this as a dictionary, and treat the bytes key as a string.
What do you think? Happy to build this functionality, but will wait for your feedback :)

Thanks!

OpenStepFormat parsing can't handle escaped quotations

OPXBrowserSignature = "designated => identifier \\"com.apple.Safari\\" and anchor apple\\n";
As soon as it parses the escaped quotation, it incorrectly looks for a semicolon.
I'm going to try and get a PR up for this in the next couple days.

Cannot handle empty <integer />

I'm trying to parse the __PRELINK_INFO.__info section on an iOS kernelcache and the embedded plist gives the above error.

Here is a snippet.

<key>UIDeviceFamily</key>
<array>
    <integer IDREF="2"/>
</array>

I know this isn't valid plist/xml, but Apple seems to think it is?

Is there anything I/we can do?

Thanks!!

parse bplist file result is error

The plist file is a binary plist file, it's struct is like this:

test.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>$archiver</key>
    <string>NSKeyedArchiver</string>
    <key>$top</key>
    <dict>
        <key>ViewController2</key>
        <dict>
            <key>CF$UID</key>
            <integer>1</integer>
        </dict>
    </dict>
    <key>$version</key>
    <integer>100000</integer>
</dict>
</plist>

and I use this code to parse it:

package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/DHowett/go-plist"
)

func main() {
    f, err := os.Open(`test.plist`)
    if err != nil {
        fmt.Println("error:", err.Error())
        return
    }
    d := plist.NewDecoder(f)
    datas := make(map[string]interface{})
    err = d.Decode(datas)
    if err != nil {
        fmt.Println("error:", err.Error())
        return
    }
    buf, _ := json.Marshal(datas)
    fmt.Println("data:", string(buf))
}

but the output is this:

data: {"$archiver":"NSKeyedArchiver","$top":{"ViewController2":1},"$version":100000}

module name error

please replace DHowett/go-plist with github.com/DHowett/go-plist in go.mod file

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.