1// 2// main.m 3// kdd command 4// 5// Created by Lawrence D'Anna on 11/9/15. 6// Copyright © 2015 Apple Inc. All rights reserved. 7// 8 9#import <Foundation/Foundation.h> 10#include <stdio.h> 11#include <unistd.h> 12#include <zlib.h> 13#import "kdd.h" 14 15void usage(char *const* argv) { 16 fprintf(stderr, "usage: %s [-p] FILE\n", argv[0]); 17 exit(1); 18} 19 20int main(int argc, char *const*argv) { 21 22 int c ; 23 int plist = 0; 24 25 while ((c = getopt(argc, argv, "p")) != EOF) { 26 switch(c) { 27 case 'p': 28 plist = TRUE; 29 break; 30 case '?': 31 case 'h': 32 default: 33 usage(argv); 34 break; 35 } 36 } 37 38 if (optind != argc -1) { 39 usage(argv); 40 } 41 42 NSError *error = nil; 43 NSData *data; 44 45 if (0 == strcmp(argv[optind], "-")) { 46 data = [[NSFileHandle fileHandleWithStandardInput] readDataToEndOfFile]; 47 } else { 48 data = [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:argv[optind]] 49 options:NSDataReadingMappedIfSafe 50 error:&error]; 51 } 52 53 if (!data || error) { 54 NSLog(@"couldn't read data: %@", error); 55 return 1; 56 } 57 58 if (data.length > UINT32_MAX) { 59 NSLog(@"data too big"); 60 return 1; 61 } 62 63 NSDictionary *dict = parseKCDataBuffer((void*)data.bytes, (uint32_t)data.length, &error); 64 65 if (error && error.code == KERN_INVALID_VALUE) { 66 uint8_t buffer[100]; 67 z_stream stream; 68 bzero(&stream, sizeof(stream)); 69 stream.next_in = (void*) data.bytes; 70 stream.avail_in = data.length; 71 stream.next_out = buffer; 72 stream.avail_out = sizeof(buffer); 73 inflateInit2(&stream, 16+MAX_WBITS); 74 NSMutableData *inflated = [[NSMutableData alloc] init]; 75 while (1) { 76 int z = inflate(&stream, Z_NO_FLUSH); 77 if (z == Z_OK || z == Z_STREAM_END) { 78 [inflated appendBytes:buffer length:sizeof(buffer) - stream.avail_out]; 79 stream.avail_out = sizeof(buffer); 80 stream.next_out = buffer; 81 if (z == Z_STREAM_END) { 82 break; 83 } 84 } else { 85 inflated = nil; 86 break; 87 } 88 } 89 if (inflated) { 90 error = nil; 91 dict = parseKCDataBuffer((void*)inflated.bytes, (uint32_t)inflated.length, &error); 92 } 93 } 94 95 if (error && error.code == KERN_INVALID_VALUE) { 96 NSData *decoded = [[NSData alloc] initWithBase64EncodedData:data options:NSDataBase64DecodingIgnoreUnknownCharacters]; 97 if (decoded) { 98 error = nil; 99 dict = parseKCDataBuffer((void*)decoded.bytes, (uint32_t)decoded.length, &error); 100 } 101 } 102 103 if (!dict || error) { 104 NSLog(@"error parsing kcdata: %@", error); 105 return 1; 106 } 107 108 if (plist) { 109 NSData *plist = [NSPropertyListSerialization dataWithPropertyList:dict 110 format:NSPropertyListXMLFormat_v1_0 111 options:0 112 error:&error]; 113 if (!plist || error) { 114 NSLog(@"couldn't write plist: %@", error); 115 return 1; 116 } 117 118 fwrite(plist.bytes, plist.length, 1, stdout); 119 120 } else { 121 puts([[NSString stringWithFormat: @"%@", dict] UTF8String]); 122 } 123 124 125 return 0; 126} 127