// CFArrayToArray converts a CFArrayRef to an array of CFTypes. func CFArrayToArray(cfArray C.CFArrayRef) (a []C.CFTypeRef) { count := C.CFArrayGetCount(cfArray) if count > 0 { a = make([]C.CFTypeRef, count) C.CFArrayGetValues(cfArray, C.CFRange{0, count}, (*unsafe.Pointer)(&a[0])) } return }
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/Reference/reference.html#jumpTo_8 func (s Stream) Paths() []string { cpaths := C.FSEventStreamCopyPathsBeingWatched(s.cstream) defer C.CFRelease(C.CFTypeRef(cpaths)) count := C.CFArrayGetCount(cpaths) paths := make([]string, count) var i C.CFIndex for ; i < count; i++ { cpath := C.CFStringRef(C.CFArrayGetValueAtIndex(cpaths, i)) paths[i] = fromCFString(cpath) } return paths }
func buildFont(f C.CTFontRef) []byte { ctags := C.CTFontCopyAvailableTables(f, C.kCTFontTableOptionExcludeSynthetic) tagsCount := C.CFArrayGetCount(ctags) var tags []uint32 var dataRefs []C.CFDataRef var dataLens []uint32 for i := C.CFIndex(0); i < tagsCount; i++ { tag := (C.CTFontTableTag)((uintptr)(C.CFArrayGetValueAtIndex(ctags, i))) dataRef := C.CTFontCopyTable(f, tag, 0) // retained tags = append(tags, uint32(tag)) dataRefs = append(dataRefs, dataRef) dataLens = append(dataLens, uint32(C.CFDataGetLength(dataRef))) } totalLen := 0 for _, l := range dataLens { totalLen += int(l) } // Big-endian output. buf := make([]byte, 0, 12+16*len(tags)+totalLen) write16 := func(x uint16) { buf = append(buf, byte(x>>8), byte(x)) } write32 := func(x uint32) { buf = append(buf, byte(x>>24), byte(x>>16), byte(x>>8), byte(x)) } // File format description: http://www.microsoft.com/typography/otspec/otff.htm write32(0x00010000) // version 1.0 write16(uint16(len(tags))) // numTables write16(0) // searchRange write16(0) // entrySelector write16(0) // rangeShift // Table tags, includes offsets into following data segments. offset := uint32(12 + 16*len(tags)) // offset starts after table tags for i, tag := range tags { write32(tag) write32(0) write32(offset) write32(dataLens[i]) offset += dataLens[i] } // Data segments. for i, dataRef := range dataRefs { data := (*[1<<31 - 2]byte)((unsafe.Pointer)(C.CFDataGetBytePtr(dataRef)))[:dataLens[i]] buf = append(buf, data...) C.CFRelease(C.CFTypeRef(dataRef)) } return buf }
func convertCFArrayToSliceHelper(cfArray C.CFArrayRef, helper func(elem cfTypeRef, idx, count int) (bool, error)) error { count := C.CFArrayGetCount(cfArray) if count == 0 { return nil } cfTypes := make([]cfTypeRef, int(count)) cfRange := C.CFRange{0, count} C.CFArrayGetValues(cfArray, cfRange, (*unsafe.Pointer)(&cfTypes[0])) for i, cfObj := range cfTypes { keepGoing, err := helper(cfObj, i, int(count)) if err != nil { return err } if !keepGoing { break } } return nil }
// FindIdentity ... // IMPORTANT: you have to C.CFRelease the returned items (one-by-one)!! // you can use the ReleaseIdentityWithRefList method to do that func FindIdentity(identityLabel string, isFullLabelMatch bool) ([]IdentityWithRefModel, error) { queryDict := C.CFDictionaryCreateMutable(nil, 0, nil, nil) defer C.CFRelease(C.CFTypeRef(queryDict)) C.CFDictionaryAddValue(queryDict, unsafe.Pointer(C.kSecClass), unsafe.Pointer(C.kSecClassIdentity)) C.CFDictionaryAddValue(queryDict, unsafe.Pointer(C.kSecMatchLimit), unsafe.Pointer(C.kSecMatchLimitAll)) C.CFDictionaryAddValue(queryDict, unsafe.Pointer(C.kSecReturnAttributes), unsafe.Pointer(C.kCFBooleanTrue)) C.CFDictionaryAddValue(queryDict, unsafe.Pointer(C.kSecReturnRef), unsafe.Pointer(C.kCFBooleanTrue)) var resultRefs C.CFTypeRef osStatusCode := C.SecItemCopyMatching(queryDict, &resultRefs) if osStatusCode != C.errSecSuccess { return nil, fmt.Errorf("Failed to call SecItemCopyMatch - OSStatus: %d", osStatusCode) } defer C.CFRelease(C.CFTypeRef(resultRefs)) identitiesArrRef := C.CFArrayRef(resultRefs) identitiesCount := C.CFArrayGetCount(identitiesArrRef) if identitiesCount < 1 { return nil, fmt.Errorf("No Identity (certificate + related private key) found in your Keychain!") } log.Debugf("identitiesCount: %d", identitiesCount) // filter the identities, by label retIdentityRefs := []IdentityWithRefModel{} for i := C.CFIndex(0); i < identitiesCount; i++ { aIdentityRef := C.CFArrayGetValueAtIndex(identitiesArrRef, i) log.Debugf("aIdentityRef: %#v", aIdentityRef) aIdentityDictRef := C.CFDictionaryRef(aIdentityRef) log.Debugf("aIdentityDictRef: %#v", aIdentityDictRef) lablCSting := C.CString("labl") defer C.free(unsafe.Pointer(lablCSting)) vrefCSting := C.CString("v_Ref") defer C.free(unsafe.Pointer(vrefCSting)) labl, err := getCFDictValueUTF8String(aIdentityDictRef, C.CFTypeRef(convertCStringToCFString(lablCSting))) if err != nil { return nil, fmt.Errorf("FindIdentity: failed to get 'labl' property: %s", err) } log.Debugf("labl: %#v", labl) if isFullLabelMatch { if labl != identityLabel { continue } } else { if !strings.Contains(labl, identityLabel) { continue } } log.Debugf("Found identity with label: %s", labl) vrefRef, err := getCFDictValueRef(aIdentityDictRef, C.CFTypeRef(convertCStringToCFString(vrefCSting))) if err != nil { return nil, fmt.Errorf("FindIdentity: failed to get 'v_Ref' property: %s", err) } log.Debugf("vrefRef: %#v", vrefRef) // retain the pointer vrefRef = C.CFRetain(vrefRef) // store it retIdentityRefs = append(retIdentityRefs, IdentityWithRefModel{ KeychainRef: vrefRef, Label: labl, }) } return retIdentityRefs, nil }