1/*
2 * Copyright (c) 2000-2004, 2009-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Modification History
26 *
27 * June 1, 2001			Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * November 9, 2000		Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34#include "scutil.h"
35#include "dictionary.h"
36
37
38//#include <stdlib.h>
39//#include <limits.h>
40
41
42__private_extern__
43void
44do_dictInit(int argc, char **argv)
45{
46	if (value != NULL) {
47		CFRelease(value);
48	}
49
50	value = CFDictionaryCreateMutable(NULL
51					 ,0
52					 ,&kCFTypeDictionaryKeyCallBacks
53					 ,&kCFTypeDictionaryValueCallBacks
54					 );
55
56	return;
57}
58
59
60__private_extern__
61void
62do_dictShow(int argc, char **argv)
63{
64	if (value == NULL) {
65		SCPrint(TRUE, stdout, CFSTR("d.show: dictionary must be initialized.\n"));
66		return;
67	}
68
69	SCPrint(TRUE, stdout, CFSTR("%@\n"), value);
70
71	return;
72}
73
74
75__private_extern__
76void
77do_dictSetKey(int argc, char **argv)
78{
79	CFMutableArrayRef	array		= NULL;
80	Boolean			doArray		= FALSE;
81	Boolean			doBoolean	= FALSE;
82	Boolean			doData		= FALSE;
83	Boolean			doNumeric	= FALSE;
84	CFStringRef		key;
85	CFMutableDictionaryRef	newValue;
86	CFTypeRef		val		= NULL;
87
88	if (value == NULL) {
89		SCPrint(TRUE, stdout, CFSTR("d.add: dictionary must be initialized.\n"));
90		return;
91	}
92
93	if (!isA_CFDictionary(value)) {
94		SCPrint(TRUE, stdout, CFSTR("d.add: data (fetched from configuration server) is not a dictionary.\n"));
95		return;
96	}
97
98	key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
99	argv++; argc--;
100
101	while (argc > 0) {
102		if (strcmp(argv[0], "*") == 0) {
103			/* if array requested */
104			doArray = TRUE;
105		} else if (strcmp(argv[0], "-") == 0) {
106			/* if string values requested */
107		} else if (strcmp(argv[0], "?") == 0) {
108			/* if boolean values requested */
109			doBoolean = TRUE;
110		} else if (strcmp(argv[0], "%") == 0) {
111			/* if [hex] data values requested */
112			doData = TRUE;
113		} else if (strcmp(argv[0], "#") == 0) {
114			/* if numeric values requested */
115			doNumeric = TRUE;
116		} else {
117			/* it's not a special flag */
118			break;
119		}
120		argv++; argc--;
121	}
122
123	if (argc > 1) {
124		doArray = TRUE;
125	} else if (!doArray && (argc == 0)) {
126		SCPrint(TRUE, stdout, CFSTR("d.add: no values.\n"));
127		CFRelease(key);
128		return;
129	}
130
131	if (doArray) {
132		array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
133	}
134
135	while (argc > 0) {
136		if (doBoolean) {
137			if         ((strcasecmp(argv[0], "true") == 0) ||
138				    (strcasecmp(argv[0], "t"   ) == 0) ||
139				    (strcasecmp(argv[0], "yes" ) == 0) ||
140				    (strcasecmp(argv[0], "y"   ) == 0) ||
141				    (strcmp    (argv[0], "1"   ) == 0)) {
142				val = CFRetain(kCFBooleanTrue);
143			} else if ((strcasecmp(argv[0], "false") == 0) ||
144				   (strcasecmp(argv[0], "f"    ) == 0) ||
145				   (strcasecmp(argv[0], "no"   ) == 0) ||
146				   (strcasecmp(argv[0], "n"    ) == 0) ||
147				   (strcmp    (argv[0], "0"    ) == 0)) {
148				val = CFRetain(kCFBooleanFalse);
149			} else {
150				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
151				if (doArray) CFRelease(array);
152				CFRelease(key);
153				return;
154			}
155		} else if (doData) {
156			uint8_t			*bytes;
157			CFMutableDataRef	data;
158			int			i;
159			int			j;
160			int			n;
161
162			n = strlen(argv[0]);
163			if ((n % 2) == 1) {
164				SCPrint(TRUE, stdout, CFSTR("d.add: not enough bytes.\n"));
165				if (doArray) CFRelease(array);
166				CFRelease(key);
167				return;
168			}
169
170			data = CFDataCreateMutable(NULL, (n / 2));
171			CFDataSetLength(data, (n / 2));
172
173			bytes = (uint8_t *)CFDataGetBytePtr(data);
174			for (i = 0, j = 0; i < n; i += 2, j++) {
175				unsigned long	byte;
176				char		*end;
177				char		str[3]	= { 0 };
178
179				str[0] = argv[0][i];
180				str[1] = argv[0][i + 1];
181				errno = 0;
182				byte = strtoul(str, &end, 16);
183				if ((*end != '\0') || (errno != 0)) {
184					CFRelease(data);
185					data = NULL;
186					break;
187				}
188
189				bytes[j] = byte;
190			}
191
192			if (data == NULL) {
193				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
194				if (doArray) CFRelease(array);
195				CFRelease(key);
196				return;
197			}
198
199			val = data;
200		} else if (doNumeric) {
201			int	intValue;
202
203			if (sscanf(argv[0], "%d", &intValue) == 1) {
204				val = CFNumberCreate(NULL, kCFNumberIntType, &intValue);
205			} else {
206				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
207				if (doArray) CFRelease(array);
208				CFRelease(key);
209				return;
210			}
211		} else {
212			val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
213		}
214
215		if (doArray) {
216			CFArrayAppendValue(array, val);
217			CFRelease(val);
218			argv++; argc--;
219		} else {
220			break;
221		}
222	}
223
224	newValue = CFDictionaryCreateMutableCopy(NULL, 0, value);
225	if (doArray) {
226		CFDictionarySetValue(newValue, key, array);
227		CFRelease(array);
228	} else if (val != NULL) {
229		CFDictionarySetValue(newValue, key, val);
230		CFRelease(val);
231	}
232	CFRelease(key);
233	CFRelease(value);
234	value = newValue;
235
236	return;
237}
238
239
240__private_extern__
241void
242do_dictRemoveKey(int argc, char **argv)
243{
244	CFStringRef		key;
245	CFMutableDictionaryRef	val;
246
247	if (value == NULL) {
248		SCPrint(TRUE, stdout, CFSTR("d.remove: dictionary must be initialized.\n"));
249		return;
250	}
251
252	if (!isA_CFDictionary(value)) {
253		SCPrint(TRUE, stdout, CFSTR("d.remove: data (fetched from configuration server) is not a dictionary.\n"));
254		return;
255	}
256
257	val = CFDictionaryCreateMutableCopy(NULL, 0, value);
258	CFRelease(value);
259	value = val;
260
261	key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
262	CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
263	CFRelease(key);
264
265	return;
266}
267