// Convert converts a CFTypeRef to a go instance. func Convert(ref C.CFTypeRef) (interface{}, error) { typeID := C.CFGetTypeID(ref) if typeID == C.CFStringGetTypeID() { return CFStringToString(C.CFStringRef(ref)), nil } else if typeID == C.CFDictionaryGetTypeID() { return ConvertCFDictionary(C.CFDictionaryRef(ref)) } else if typeID == C.CFArrayGetTypeID() { arr := CFArrayToArray(C.CFArrayRef(ref)) results := make([]interface{}, 0, len(arr)) for _, ref := range arr { v, err := Convert(ref) if err != nil { return nil, err } results = append(results, v) return results, nil } } else if typeID == C.CFDataGetTypeID() { b, err := CFDataToBytes(C.CFDataRef(ref)) if err != nil { return nil, err } return b, nil } else if typeID == C.CFNumberGetTypeID() { return CFNumberToInterface(C.CFNumberRef(ref)), nil } else if typeID == C.CFBooleanGetTypeID() { if C.CFBooleanGetValue(C.CFBooleanRef(ref)) != 0 { return true, nil } return false, nil } return nil, fmt.Errorf("Invalid type: %s", CFTypeDescription(ref)) }
// QueryItem returns a list of query results. func QueryItem(item Item) ([]QueryResult, error) { resultsRef, err := QueryItemRef(item) if err != nil { return nil, err } if resultsRef == nil { return nil, nil } defer Release(resultsRef) results := make([]QueryResult, 0, 1) typeID := C.CFGetTypeID(resultsRef) if typeID == C.CFArrayGetTypeID() { arr := CFArrayToArray(C.CFArrayRef(resultsRef)) for _, ref := range arr { typeID := C.CFGetTypeID(ref) if typeID == C.CFDictionaryGetTypeID() { item, err := convertResult(C.CFDictionaryRef(ref)) if err != nil { return nil, err } results = append(results, *item) } else { return nil, fmt.Errorf("Invalid result type (If you SetReturnRef(true) you should use QueryItemRef directly).") } } } else if typeID == C.CFDictionaryGetTypeID() { item, err := convertResult(C.CFDictionaryRef(resultsRef)) if err != nil { return nil, err } results = append(results, *item) } else if typeID == C.CFDataGetTypeID() { b, err := CFDataToBytes(C.CFDataRef(resultsRef)) if err != nil { return nil, err } item := QueryResult{Data: b} results = append(results, item) } else { return nil, fmt.Errorf("Invalid result type: %s", CFTypeDescription(resultsRef)) } return results, nil }
// QueryItem returns a list of query results. func QueryItem(item Item) ([]QueryResult, error) { cfDict, err := ConvertMapToCFDictionary(item.attr) if err != nil { return nil, err } defer Release(C.CFTypeRef(cfDict)) var resultsRef C.CFTypeRef errCode := C.SecItemCopyMatching(cfDict, &resultsRef) if Error(errCode) == ErrorItemNotFound { return nil, nil } err = checkError(errCode) if err != nil { return nil, err } defer Release(resultsRef) results := make([]QueryResult, 0, 1) typeID := C.CFGetTypeID(resultsRef) if typeID == C.CFArrayGetTypeID() { arr := CFArrayToArray(C.CFArrayRef(resultsRef)) for _, dictRef := range arr { item, err := convertResult(C.CFDictionaryRef(dictRef)) if err != nil { return nil, err } results = append(results, *item) } } else if typeID == C.CFDictionaryGetTypeID() { item, err := convertResult(C.CFDictionaryRef(resultsRef)) if err != nil { return nil, err } results = append(results, *item) } else if typeID == C.CFDataGetTypeID() { b, err := CFDataToBytes(C.CFDataRef(resultsRef)) if err != nil { return nil, err } item := QueryResult{Data: b} results = append(results, item) } else { return nil, fmt.Errorf("Invalid result type: %s", CFTypeDescription(resultsRef)) } return results, nil }
// we shouldn't ever get an error from this, but I'd rather not panic func convertCFTypeToInterface(cfType cfTypeRef) (interface{}, error) { typeId := C.CFGetTypeID(C.CFTypeRef(cfType)) switch typeId { case C.CFStringGetTypeID(): return convertCFStringToString(C.CFStringRef(cfType)), nil case C.CFNumberGetTypeID(): return convertCFNumberToInterface(C.CFNumberRef(cfType)), nil case C.CFBooleanGetTypeID(): return convertCFBooleanToBool(C.CFBooleanRef(cfType)), nil case C.CFDataGetTypeID(): return convertCFDataToBytes(C.CFDataRef(cfType)), nil case C.CFDateGetTypeID(): return convertCFDateToTime(C.CFDateRef(cfType)), nil case C.CFArrayGetTypeID(): ary, err := convertCFArrayToSlice(C.CFArrayRef(cfType)) return ary, err case C.CFDictionaryGetTypeID(): dict, err := convertCFDictionaryToMap(C.CFDictionaryRef(cfType)) return dict, err } return nil, &UnknownCFTypeError{typeId} }
if err := state.unmarshalValue(cfObj, rv); err != nil { return format, err } return format, state.err } type unmarshalState struct { err error } var ( cfArrayTypeID = C.CFArrayGetTypeID() cfBooleanTypeID = C.CFBooleanGetTypeID() cfDataTypeID = C.CFDataGetTypeID() cfDateTypeID = C.CFDateGetTypeID() cfDictionaryTypeID = C.CFDictionaryGetTypeID() cfNumberTypeID = C.CFNumberGetTypeID() cfStringTypeID = C.CFStringGetTypeID() ) var cfTypeMap = map[C.CFTypeID]reflect.Type{ cfArrayTypeID: reflect.TypeOf([]interface{}(nil)), cfBooleanTypeID: reflect.TypeOf(false), cfDataTypeID: reflect.TypeOf([]byte(nil)), cfDateTypeID: reflect.TypeOf(time.Time{}), cfDictionaryTypeID: reflect.TypeOf(map[string]interface{}(nil)), cfStringTypeID: reflect.TypeOf(""), } var cfTypeNames = map[C.CFTypeID]string{ cfArrayTypeID: "CFArray",