1/*
2 * Copyright (c) 2000-2005, 2009-2011, 2013 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 follow */
107			argv++; argc--;
108			break;
109		} else if (strcmp(argv[0], "?") == 0) {
110			/* if boolean values requested */
111			doBoolean = TRUE;
112		} else if (strcmp(argv[0], "%") == 0) {
113			/* if [hex] data values requested */
114			doData = TRUE;
115		} else if (strcmp(argv[0], "#") == 0) {
116			/* if numeric values requested */
117			doNumeric = TRUE;
118		} else {
119			/* it's not a special flag */
120			break;
121		}
122		argv++; argc--;
123	}
124
125	if (argc > 1) {
126		doArray = TRUE;
127	} else if (!doArray && (argc == 0)) {
128		SCPrint(TRUE, stdout, CFSTR("d.add: no values.\n"));
129		CFRelease(key);
130		return;
131	}
132
133	if (doArray) {
134		array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
135	}
136
137	while (argc > 0) {
138		if (doBoolean) {
139			if         ((strcasecmp(argv[0], "true") == 0) ||
140				    (strcasecmp(argv[0], "t"   ) == 0) ||
141				    (strcasecmp(argv[0], "yes" ) == 0) ||
142				    (strcasecmp(argv[0], "y"   ) == 0) ||
143				    (strcmp    (argv[0], "1"   ) == 0)) {
144				val = CFRetain(kCFBooleanTrue);
145			} else if ((strcasecmp(argv[0], "false") == 0) ||
146				   (strcasecmp(argv[0], "f"    ) == 0) ||
147				   (strcasecmp(argv[0], "no"   ) == 0) ||
148				   (strcasecmp(argv[0], "n"    ) == 0) ||
149				   (strcmp    (argv[0], "0"    ) == 0)) {
150				val = CFRetain(kCFBooleanFalse);
151			} else {
152				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
153				if (doArray) CFRelease(array);
154				CFRelease(key);
155				return;
156			}
157		} else if (doData) {
158			uint8_t			*bytes;
159			CFMutableDataRef	data;
160			int			i;
161			int			j;
162			int			n;
163
164			n = (int)strlen(argv[0]);
165			if ((n % 2) == 1) {
166				SCPrint(TRUE, stdout, CFSTR("d.add: not enough bytes.\n"));
167				if (doArray) CFRelease(array);
168				CFRelease(key);
169				return;
170			}
171
172			data = CFDataCreateMutable(NULL, (n / 2));
173			CFDataSetLength(data, (n / 2));
174
175			bytes = (uint8_t *)CFDataGetBytePtr(data);
176			for (i = 0, j = 0; i < n; i += 2, j++) {
177				unsigned long	byte;
178				char		*end;
179				char		str[3]	= { 0 };
180
181				str[0] = argv[0][i];
182				str[1] = argv[0][i + 1];
183				errno = 0;
184				byte = strtoul(str, &end, 16);
185				if ((*end != '\0') || (errno != 0)) {
186					CFRelease(data);
187					data = NULL;
188					break;
189				}
190
191				bytes[j] = byte;
192			}
193
194			if (data == NULL) {
195				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
196				if (doArray) CFRelease(array);
197				CFRelease(key);
198				return;
199			}
200
201			val = data;
202		} else if (doNumeric) {
203			int	intValue;
204
205			if (sscanf(argv[0], "%d", &intValue) == 1) {
206				val = CFNumberCreate(NULL, kCFNumberIntType, &intValue);
207			} else {
208				SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n"));
209				if (doArray) CFRelease(array);
210				CFRelease(key);
211				return;
212			}
213		} else {
214			val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
215		}
216
217		if (doArray) {
218			CFArrayAppendValue(array, val);
219			CFRelease(val);
220			argv++; argc--;
221		} else {
222			break;
223		}
224	}
225
226	newValue = CFDictionaryCreateMutableCopy(NULL, 0, value);
227	if (doArray) {
228		CFDictionarySetValue(newValue, key, array);
229		CFRelease(array);
230	} else if (val != NULL) {
231		CFDictionarySetValue(newValue, key, val);
232		CFRelease(val);
233	}
234	CFRelease(key);
235	CFRelease(value);
236	value = newValue;
237
238	return;
239}
240
241
242__private_extern__
243void
244do_dictRemoveKey(int argc, char **argv)
245{
246	CFStringRef		key;
247	CFMutableDictionaryRef	val;
248
249	if (value == NULL) {
250		SCPrint(TRUE, stdout, CFSTR("d.remove: dictionary must be initialized.\n"));
251		return;
252	}
253
254	if (!isA_CFDictionary(value)) {
255		SCPrint(TRUE, stdout, CFSTR("d.remove: data (fetched from configuration server) is not a dictionary.\n"));
256		return;
257	}
258
259	val = CFDictionaryCreateMutableCopy(NULL, 0, value);
260	CFRelease(value);
261	value = val;
262
263	key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
264	CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
265	CFRelease(key);
266
267	return;
268}
269