1/*
2 *  misc.c
3 *  libsecurity_transform
4 *
5 *  Created by JOsborne on 3/14/10.
6 *  Copyright 2010 Apple. All rights reserved.
7 *
8 */
9
10#include "misc.h"
11
12
13// NOTE: the return may or allocate a fair bit more space then it needs.
14// Use it for short lived conversions (or strdup the result).
15char *utf8(CFStringRef s) {
16	CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
17	CFIndex used = 0;
18	UInt8 *buf = (UInt8 *)malloc(sz);
19	if (!buf) {
20		return NULL;
21	}
22	CFStringGetBytes(s, CFRangeMake(0, CFStringGetLength(s)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used);
23	buf[used] = 0;
24
25	return (char*)buf;
26}
27
28void CFfprintf(FILE *f, const char *format, ...) {
29	va_list ap;
30	va_start(ap, format);
31
32	CFStringRef fmt = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
33	CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, ap);
34	va_end(ap);
35	CFRelease(fmt);
36
37	CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
38	sz += 1;
39	CFIndex used = 0;
40	unsigned char *buf;
41	bool needs_free = false;
42	if (sz < 1024) {
43		buf = alloca(sz);
44	} else {
45		buf = malloc(sz);
46		needs_free = true;
47	}
48	if (buf) {
49		CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used);
50	} else {
51		buf = (unsigned char *)"malloc failue during CFfprintf\n";
52	}
53
54	fwrite(buf, 1, used, f);
55	if (needs_free) {
56		free(buf);
57	}
58
59	CFRelease(str);
60}
61
62CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description) {
63	const void *v_ekey = kCFErrorDescriptionKey;
64	const void *v_description = description;
65	CFErrorRef err = CFErrorCreateWithUserInfoKeysAndValues(NULL, domain, code, &v_ekey, &v_description, 1);
66
67	return err;
68}
69
70static
71void add_t2ca(CFMutableDictionaryRef t2ca, CFStringRef t, CFStringRef a) {
72	CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, t);
73	if (!ca) {
74		ca = CFSetCreateMutable(NULL, 0, &kCFCopyStringSetCallBacks);
75		CFDictionarySetValue(t2ca, t, ca);
76	}
77	CFSetAddValue(ca, a);
78}
79
80void CFSafeRelease(CFTypeRef object) {
81	if (object) {
82		CFRelease(object);
83	}
84}
85
86void graphviz(FILE *f, SecTransformRef tr) {
87	CFDictionaryRef d = SecTransformCopyExternalRepresentation(tr);
88
89	CFfprintf(f, "digraph TR {\n\tnode [shape=plaintext];\n\n");
90	CFIndex i, j;
91	CFArrayRef transforms = CFDictionaryGetValue(d, CFSTR("TRANSFORMS"));
92	CFArrayRef connections = CFDictionaryGetValue(d, CFSTR("ARRAY"));
93
94
95	// map transforms to connected attributes
96	CFMutableDictionaryRef t2ca = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
97	for(i = 0; i < CFArrayGetCount(connections); i++) {
98		CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i);
99
100		CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME"));
101		CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME"));
102		CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE"));
103		CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE"));
104
105		add_t2ca(t2ca, t_from, a_from);
106		add_t2ca(t2ca, t_to, a_to);
107	}
108
109
110	for(i = 0; i < CFArrayGetCount(transforms); i++) {
111		CFDictionaryRef t = CFArrayGetValueAtIndex(transforms, i);
112		// NAME STATE(dict) TYPE
113		CFStringRef name = CFDictionaryGetValue(t, CFSTR("NAME"));
114
115		CFfprintf(f, "\tsubgraph \"cluster_%@\"{\n", name);
116
117		CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, name);
118		if (ca) {
119			CFIndex cnt = CFSetGetCount(ca);
120			CFStringRef *attrs = malloc(cnt * sizeof(CFStringRef));
121			CFSetGetValues(ca, (const void **)attrs);
122
123			for(j = 0; j < cnt; j++) {
124				CFfprintf(f, "\t\t\"%@#%@\" [label=\"%@\"];\n", name, attrs[j], attrs[j]);
125			}
126			CFfprintf(f, "\t\t\"%@\" [fontcolor=blue, fontsize=20];\n\t}\n");
127		}
128	}
129
130	CFfprintf(f, "\n");
131
132	for(i = 0; i < CFArrayGetCount(connections); i++) {
133		CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i);
134
135		CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME"));
136		CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME"));
137		CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE"));
138		CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE"));
139
140		CFfprintf(f, "\t\"%@#%@\" -> \"%@#%@\";\n", t_from, a_from, t_to, a_to);
141	}
142
143	CFfprintf(f, "}\n");
144
145	CFfprintf(f, "\n/*\n%@\n/*\n", d);
146}