Skip to content

Instantly share code, notes, and snippets.

@clburlison
Last active June 14, 2018 00:26
Show Gist options
  • Save clburlison/62394d6b0950040ac95586642413f684 to your computer and use it in GitHub Desktop.
Save clburlison/62394d6b0950040ac95586642413f684 to your computer and use it in GitHub Desktop.
playing with cgo and CFPreferencesCopyAppValue. Currently supports reading Strings, NSData, and Booleans.
package main // import "gitlab.com/clburlison/cfprefs"
import (
"fmt"
"unsafe"
)
/*
#cgo LDFLAGS: -framework CoreFoundation
#include <CoreFoundation/CoreFoundation.h>
*/
import "C"
// Convert a Go string to a CFString
// Make sure to release the CFString when finished
func stringToCFString(s string) C.CFStringRef {
return C.CFStringCreateWithCString(C.kCFAllocatorDefault, C.CString(s), C.kCFStringEncodingUTF8)
}
// Convert a CFString to a Go string
func cfstringToString(s C.CFStringRef) string {
return C.GoString(C.CFStringGetCStringPtr(s, C.kCFStringEncodingUTF8))
}
// Convert a CFBoolean to a Go bool
func cfbooleanToBoolean(s C.CFBooleanRef) bool {
// fmt.Println(reflect.TypeOf(C.CFBooleanGetValue(s)))
if C.CFBooleanGetValue(s) == 1 {
return true
}
return false
}
// Convert a CFData to a Go byte
func cfdataToData(s C.CFDataRef) []uint8 {
d := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(s)), C.int(C.CFDataGetLength(s)))
return d
}
// CFPreferencesCopyAppValue - Return a value from a preference
func CFPreferencesCopyAppValue(key string, domain string) interface{} {
k := stringToCFString(key)
defer release(C.CFTypeRef(k))
d := stringToCFString(domain)
defer release(C.CFTypeRef(d))
if ret := C.CFPreferencesCopyAppValue(k, d); ret != 0 && C.CFGetTypeID(ret) == C.CFStringGetTypeID() {
defer release(ret)
return cfstringToString(C.CFStringRef(ret))
}
if ret := C.CFPreferencesCopyAppValue(k, d); ret != 0 && C.CFGetTypeID(ret) == C.CFBooleanGetTypeID() {
defer release(ret)
return cfbooleanToBoolean(C.CFBooleanRef(ret))
}
if ret := C.CFPreferencesCopyAppValue(k, d); ret != 0 && C.CFGetTypeID(ret) == C.CFDataGetTypeID() {
defer release(ret)
return cfdataToData(C.CFDataRef(ret))
}
return ""
}
func release(ref C.CFTypeRef) {
if ref != 0 {
C.CFRelease(ref)
}
}
func main() {
fmt.Printf("%s\n", CFPreferencesCopyAppValue("aData", "com.clburlison.test"))
fmt.Printf("%v\n", CFPreferencesCopyAppValue("aString", "com.clburlison.test"))
fmt.Printf("%v\n", CFPreferencesCopyAppValue("aBool", "com.clburlison.test"))
fmt.Println(C.CFArrayGetTypeID()) // 19
fmt.Println(C.CFBooleanGetTypeID()) // 21
fmt.Println(C.CFBundleGetTypeID()) // 31
fmt.Println(C.CFDataGetTypeID()) // 20
fmt.Println(C.CFDateGetTypeID()) // 42
fmt.Println(C.CFDictionaryGetTypeID()) // 18
fmt.Println(C.CFNullGetTypeID()) // 16
fmt.Println(C.CFNumberGetTypeID()) // 22
fmt.Println(C.CFSetGetTypeID()) // 17
fmt.Println(C.CFStringGetTypeID()) // 7
}
#!/usr/bin/python
# Yes I am being lazy and shelling out to defaults :shrug:
import binascii
import subprocess
from Foundation import CFPreferencesCopyAppValue
#filename = "somefile_here"
#with open(filename, 'rb') as f:
# content = f.read()
content = "asdlfkjasldfihaisygdfkhjawekuyrg1uyg23bkja89c7gd6aikuwherbuy1f46879y8ohjahvsdftya8gisuhdkfbvwuatef87aiuhsdfbyaus687d9f8hubhagsvdufyguihabhsdgvfy78uhabsgvdhfuyiuohjkbgvc123guybhjkijgo897s6tyvg"
hexdata = binascii.hexlify(content)
cmd = [
"defaults",
"write",
"com.clburlison.test",
"aData",
"-data",
hexdata
]
subprocess.check_output(cmd)
cmd = [
"defaults",
"write",
"com.clburlison.test",
"aString",
"-string",
"Hello World"
]
subprocess.check_output(cmd)
cmd = [
"defaults",
"write",
"com.clburlison.test",
"aBool",
"-bool",
"FALSE"
]
subprocess.check_output(cmd)
aData = CFPreferencesCopyAppValue("cert", "com.clburlison.test")
print(aData)
aString = CFPreferencesCopyAppValue("aString", "com.clburlison.test")
print(aString)
aBool = CFPreferencesCopyAppValue("aBool", "com.clburlison.test")
print(aBool)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment