/* TODO: Use the shared version of this function in print_cert.c. */ static void print_line(CFStringRef line) { UInt8 buf[256]; CFRange range = { .location = 0 }; range.length = CFStringGetLength(line); while (range.length > 0) { CFIndex bytesUsed = 0; CFIndex converted = CFStringGetBytes(line, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); fwrite(buf, 1, bytesUsed, stdout); range.length -= converted; range.location += converted; } fputc('\n', stdout); } static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { CFIndex count = CFArrayGetCount(plist); CFIndex ix; for (ix = 0; ix < count ; ++ix) { CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, ix); CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyType); CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLabel); CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLocalizedLabel); CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, kSecPropertyKeyValue); bool isSection = CFEqual(pType, kSecPropertyTypeSection); CFMutableStringRef line = CFStringCreateMutable(NULL, 0); CFIndex jx = 0; for (jx = 0; jx < indent; ++jx) { CFStringAppend(line, CFSTR(" ")); } if (llabel) { CFStringAppend(line, llabel); if (!isSection) { for (jx = CFStringGetLength(llabel) + indent * 4; jx < maxWidth; ++jx) { CFStringAppend(line, CFSTR(" ")); } CFStringAppend(line, CFSTR(" : ")); } } if (CFEqual(pType, kSecPropertyTypeWarning)) { CFStringAppend(line, CFSTR("*WARNING* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeError)) { CFStringAppend(line, CFSTR("*ERROR* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { CFStringAppend(line, CFSTR("*OK* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeTitle)) { CFStringAppend(line, CFSTR("*")); CFStringAppend(line, (CFStringRef)value); CFStringAppend(line, CFSTR("*")); } else if (CFEqual(pType, kSecPropertyTypeSection)) { } else if (CFEqual(pType, kSecPropertyTypeData)) { CFDataRef data = (CFDataRef)value; CFIndex length = CFDataGetLength(data); if (length > 20) CFStringAppendFormat(line, NULL, CFSTR("[%" PRIdCFIndex " bytes] "), length); const UInt8 *bytes = CFDataGetBytePtr(data); for (jx = 0; jx < length; ++jx) { if (jx == 0) CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); else if (jx < 15 || length <= 20) CFStringAppendFormat(line, NULL, CFSTR(" %02X"), bytes[jx]); else { CFStringAppend(line, CFSTR(" ...")); break; } } } else if (CFEqual(pType, kSecPropertyTypeString)) { CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeDate)) { CFLocaleRef lc = CFLocaleCopyCurrent(); CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); //CFTimeZoneRef tz = CFTimeZoneCreateWithName(NULL, CFSTR("GMT"), false); //CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); //CFRelease(tz); CFDateRef date = (CFDateRef)value; CFStringRef ds = CFDateFormatterCreateStringWithDate(NULL, df, date); CFStringAppend(line, ds); CFRelease(ds); CFRelease(df); CFRelease(lc); } else if (CFEqual(pType, kSecPropertyTypeURL)) { CFURLRef url = (CFURLRef)value; CFStringAppend(line, CFSTR("<")); CFStringAppend(line, CFURLGetString(url)); CFStringAppend(line, CFSTR(">")); } else { CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), pType, value); } if (!isSection || label) print_line(line); CFRelease(line); if (isSection) { printPlist((CFArrayRef)value, indent + 1, maxWidth); } } }
static void print_plist(CFArrayRef plist) { if (plist) printPlist(plist, 0, maxLabelWidth(plist, 0)); else printf("NULL plist\n"); }
static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { CFIndex count = CFArrayGetCount(plist); CFIndex ix; for (ix = 0; ix < count ; ++ix) { CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, ix); CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyType); CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLabel); CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, kSecPropertyKeyLocalizedLabel); CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, kSecPropertyKeyValue); bool isSection = CFEqual(pType, kSecPropertyTypeSection); CFMutableStringRef line = CFStringCreateMutable(NULL, 0); CFIndex jx = 0; for (jx = 0; jx < indent; ++jx) { CFStringAppend(line, CFSTR(" ")); } if (llabel) { CFStringAppend(line, llabel); if (!isSection) { for (jx = CFStringGetLength(llabel) + indent * 4; jx < maxWidth; ++jx) { CFStringAppend(line, CFSTR(" ")); } CFStringAppend(line, CFSTR(" : ")); } } if (CFEqual(pType, kSecPropertyTypeWarning)) { CFStringAppend(line, CFSTR("*WARNING* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeError)) { CFStringAppend(line, CFSTR("*ERROR* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { CFStringAppend(line, CFSTR("*OK* ")); CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeTitle)) { CFStringAppend(line, CFSTR("*")); CFStringAppend(line, (CFStringRef)value); CFStringAppend(line, CFSTR("*")); } else if (CFEqual(pType, kSecPropertyTypeSection)) { } else if (CFEqual(pType, kSecPropertyTypeData)) { CFDataRef data = (CFDataRef)value; CFIndex length = CFDataGetLength(data); if (length > 20) CFStringAppendFormat(line, NULL, CFSTR("[%d bytes] "), length); const UInt8 *bytes = CFDataGetBytePtr(data); for (jx = 0; jx < length; ++jx) { if (jx == 0) CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); else if (jx < 15 || length <= 20) CFStringAppendFormat(line, NULL, CFSTR(" %02X"), bytes[jx]); else { CFStringAppend(line, CFSTR(" ...")); break; } } } else if (CFEqual(pType, kSecPropertyTypeString)) { CFStringAppend(line, (CFStringRef)value); } else if (CFEqual(pType, kSecPropertyTypeDate)) { CFDateRef date = (CFDateRef)value; CFLocaleRef lc = CFLocaleCopyCurrent(); CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle); CFStringRef ds; if (df) { CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0); CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); CFRelease(tz); ds = CFDateFormatterCreateStringWithDate(NULL, df, date); CFRelease(df); } else { ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date)); } CFStringAppend(line, ds); CFRelease(ds); CFRelease(lc); } else if (CFEqual(pType, kSecPropertyTypeURL)) { CFURLRef url = (CFURLRef)value; CFStringAppend(line, CFSTR("<")); CFStringAppend(line, CFURLGetString(url)); CFStringAppend(line, CFSTR(">")); } else { CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), pType, value); } if (!isSection || label) print_line(line); CFRelease(line); if (isSection) { printPlist((CFArrayRef)value, indent + 1, maxWidth); } } }