dhowett / go-plist Goto Github PK
View Code? Open in Web Editor NEWA pure Go Apple Property List transcoder
License: Other
A pure Go Apple Property List transcoder
License: Other
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.
Trying to use the package on AppEngine results in the following error:
composite struct literal encoding/xml.Name with unkeyed fields.
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
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.
Evaluate what plist needs to do to reach 1.0.
$ 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
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!
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
Please add a interface similar to UnmarshallJSON and MarshallJSON. An interface would lend itself better to work with custom types.
See this talk on JSON for usage: http://talks.golang.org/2015/json.slide#1
To give you a more concrete example, I would like to be able to do the following:
type Password string `plist:"pass"`
func(p *Password) MarshallPlist() ([]byte, error) {
// do something here
return
}
Strings documents do not need to contain a toplevel dictionary or even values for their keys.
These are both valid:
"X" = "Y";
"X";
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?
Is the an easy way to dump a generic plist to an xml file?
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!
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>
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?
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!!
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
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.)
When I try to access to howett.net/plist, it givce me a 404 error from apache
Greetings!
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"
It seems that my changes from #19 went into abyss.
You're not --force
pushing to master, are you :-)?
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
:
Lines 268 to 270 in c619543
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?
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? ๐
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>
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?
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.
go-plist currently does not interpret cfUID values for the text generator. This is different from the GNUstep behavior, which always generates CF$UID dictionaries so that they can be put into any plist. (Their binary encoder picks these out at write-time.)
Their NSKeyedUnarchiver seems tolerant of OpenStep-marshalled versions, since it performs an intValue:
call to coerce a potential string to int.
Do you have a tutorial or an example? I did not find the link
Apostrophes are not currently quoted properly, as they are not valid characters in strings unquoted. (https://github.com/opensource-apple/CF/blob/3cc41a76b1491f50813e28a4ec09954ffa359e6f/CFOldStylePList.c#L79)
Opened a PR:
#64
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}
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.
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.
We have a xcode project file where a key value pair looks like this: "shellPath = /bin/sh;".
When writing back the plist file, the key value pair becomes "shellPath = in/sh;".
I suspect there is a bug in the chugWhitespace function in the text.go file.
Unable to reach to the custom URL values as seen below.
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"`
}
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.
The ply
subdirectory still imports "howett.net/plist"
while there is a GitHub repo URL for it.
This keeps the problem mentioned in #16 around, which is currently a dealbreaker when using helper tools like dh-make-golang
(https://people.debian.org/~stapelberg/2015/07/27/dh-make-golang.html).
Please import the GitHub repo for plist in ply.
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.
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
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?
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?
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>
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.
please replace DHowett/go-plist with github.com/DHowett/go-plist in go.mod file
This will probably harm code coverage, but panic/recover shouldn't be used for flow control.
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.