1 | /*␊ |
2 | * property_list.cpp␊ |
3 | *␊ |
4 | * Created by Rekursor on 1/17/10.␊ |
5 | *␊ |
6 | */␊ |
7 | ␊ |
8 | #include "property_list.h"␊ |
9 | #include <string.h>␊ |
10 | ␊ |
11 | /****************************************************************************/␊ |
12 | /**␊ |
13 | * Simple parsing and splitting args function, does handle env. vars ␊ |
14 | */␊ |
15 | static void parseArgs(const char * args, const char* argv[], int argvlen)␊ |
16 | {␊ |
17 | ␉// Create a list of args fron the space delimited args parameters␊ |
18 | ␉int n=0;␊ |
19 | ␉if (args && *args) ␊ |
20 | ␉{␊ |
21 | ␉␉bool skipSpaces = true;␊ |
22 | ␉␉bool prevCharwasDelim =false;␊ |
23 | ␉␉char * buf = strdup(args);␊ |
24 | ␉␉char lastPriorityDelim=' ';␊ |
25 | ␉␉␊ |
26 | ␉␉printf("Parsing <%s>\n", args);␊ |
27 | ␉␉␊ |
28 | ␉␉int k=0;␊ |
29 | ␉␉for (int i=0; i< strlen(args); i++)␊ |
30 | ␉␉{␊ |
31 | ␉␉␉switch (args[i]) ␊ |
32 | ␉␉␉{␊ |
33 | ␉␉␉␉case ' ': case '\t':␊ |
34 | ␉␉␉␉␉if(!skipSpaces) {␊ |
35 | ␉␉␉␉␉␉buf[k++]=args[i];␊ |
36 | ␉␉␉␉␉}␊ |
37 | ␉␉␉␉␉else {␊ |
38 | ␉␉␉␉␉␉prevCharwasDelim = true; // // keep a track of delim to further split tokens␊ |
39 | ␉␉␉␉␉}␊ |
40 | ␉␉␉␉␉break;␊ |
41 | ␉␉␉␉case '\0':␊ |
42 | ␉␉␉␉case '\'': ␊ |
43 | ␉␉␉␉case '"': ␊ |
44 | ␉␉␉␉␉if (!skipSpaces &&lastPriorityDelim!=args[i])␊ |
45 | ␉␉␉␉␉{ // consider the imbricated delim as a simple char␊ |
46 | ␉␉␉␉␉␉buf[k++]=args[i];␊ |
47 | ␉␉␉␉␉␉break;␊ |
48 | ␉␉␉␉␉}␊ |
49 | ␉␉␉␉␉␊ |
50 | ␉␉␉␉␉if (!skipSpaces) // end of priority substr␊ |
51 | ␉␉␉␉␉{␊ |
52 | ␉␉␉␉␉␉skipSpaces = true;␊ |
53 | ␉␉␉␉␉␉lastPriorityDelim=' ';␊ |
54 | ␉␉␉␉␉␉buf[k]='\0'; ␊ |
55 | ␉␉␉␉␉␉argv[n++]=strdup(buf); // copy the priority substr␊ |
56 | ␉␉␉␉␉␉k=0; // reset the buf index for next token␊ |
57 | ␉␉␉␉␉␉buf[0]='\0';␊ |
58 | ␉␉␉␉␉}␊ |
59 | ␉␉␉␉␉else␊ |
60 | ␉␉␉␉␉{ // start of priority substr␊ |
61 | ␉␉␉␉␉␉skipSpaces=false;␊ |
62 | ␉␉␉␉␉␉lastPriorityDelim=args[i];␊ |
63 | ␉␉␉␉␉␉if(k>0) // previous string to store first␊ |
64 | ␉␉␉␉␉␉{␊ |
65 | ␉␉␉␉␉␉␉buf[k++]='\0'; // finish the substr␊ |
66 | ␉␉␉␉␉␉␉argv[n++]=strdup(buf); // copy the substr␊ |
67 | ␉␉␉␉␉␉␉k=0; // rest the index for next token␊ |
68 | ␉␉␉␉␉␉␉buf[0]='\0';␊ |
69 | ␉␉␉␉␉␉}␊ |
70 | ␉␉␉␉␉␉//if (args[i] !='\0') buf[k++] = args[i]; // start the new priority substr␊ |
71 | ␉␉␉␉␉}␊ |
72 | ␉␉␉␉␉break;␊ |
73 | ␉␉␉␉default: // non delimiters chars␊ |
74 | ␉␉␉␉␉if(skipSpaces && prevCharwasDelim)␊ |
75 | ␉␉␉␉␉{␊ |
76 | ␉␉␉␉␉␉if(k>0) // a previous substr was before the space␊ |
77 | ␉␉␉␉␉␉{ // store previous token␊ |
78 | ␉␉␉␉␉␉␉buf[k++]='\0'; // finish the substr␊ |
79 | ␉␉␉␉␉␉␉argv[n++]=strdup(buf); // copy the substr␊ |
80 | ␉␉␉␉␉␉␉k=0; // rest the index for next token␊ |
81 | ␉␉␉␉␉␉␉buf[0]='\0';␊ |
82 | ␉␉␉␉␉␉}␊ |
83 | ␉␉␉␉␉}␊ |
84 | ␉␉␉␉␉prevCharwasDelim = false;␊ |
85 | ␉␉␉␉␉buf[k++]=args[i];␊ |
86 | ␉␉␉␉␉break;␊ |
87 | ␉␉␉}␊ |
88 | ␉␉}␊ |
89 | ␉␉␊ |
90 | ␉␉if(*buf) ␊ |
91 | ␉␉{␊ |
92 | ␉␉␉buf[k]='\0';␊ |
93 | ␉␉␉argv[n++]=strdup(buf); // copy the last buffer␉␊ |
94 | ␉␉}␊ |
95 | ␉␉free((void*) buf);␊ |
96 | ␉}␊ |
97 | ␉argv[n]=NULL;␊ |
98 | }␊ |
99 | ␊ |
100 | /****************************************************************************/␊ |
101 | bool executePrivilegedCmd(AuthorizationRef auth, ␊ |
102 | ␉␉␉␉␉␉␉␉ const char* pathToTool, ␊ |
103 | ␉␉␉␉␉␉␉␉ const char* args, ␊ |
104 | ␉␉␉␉␉␉␉␉ AuthorizationFlags flags)␊ |
105 | {␊ |
106 | ␉const char * argv[16];␊ |
107 | ␊ |
108 | ␉parseArgs(args, argv, sizeof(argv)/sizeof(const char*));␊ |
109 | ␊ |
110 | ␉// Execute Cmd␊ |
111 | ␉OSStatus status = AuthorizationExecuteWithPrivileges(auth, pathToTool,flags, (char**)argv, NULL);␊ |
112 | ␉␊ |
113 | ␉␊ |
114 | ␉// Cleanup mem␊ |
115 | ␉for (int i=0; argv[i]; i++) free ((void*) argv[i]);␊ |
116 | ␊ |
117 | return status ? false : true;␊ |
118 | }␊ |
119 | ␊ |
120 | ␊ |
121 | /****************************************************************************/␊ |
122 | /**␊ |
123 | * Write a property list from a file␊ |
124 | */␊ |
125 | bool WritePropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL )␊ |
126 | {␊ |
127 | ␉CFDataRef xmlData;␊ |
128 | ␉Boolean status;␊ |
129 | ␉SInt32 errorCode;␊ |
130 | ␉␊ |
131 | ␉// Convert the property list into XML data.␊ |
132 | ␉xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList );␊ |
133 | ␉␊ |
134 | ␉// Write the XML data to the file.␊ |
135 | ␉status = CFURLWriteDataAndPropertiesToResource (␊ |
136 | ␉␉␉␉␉␉␉␉␉␉␉␉␉fileURL, // URL to use␊ |
137 | ␉␉␉␉␉␉␉␉␉␉␉␉␉xmlData, // data to write␊ |
138 | ␉␉␉␉␉␉␉␉␉␉␉␉␉NULL,␊ |
139 | ␉␉␉␉␉␉␉␉␉␉␉␉␉&errorCode);␊ |
140 | ␉CFRelease(xmlData);␊ |
141 | ␉␊ |
142 | ␉return status ? true: false;␊ |
143 | }␊ |
144 | ␊ |
145 | /****************************************************************************/␊ |
146 | /**␊ |
147 | * Read a property list from a file␊ |
148 | */␊ |
149 | static CFPropertyListRef CreatePropertyListFromFile( CFURLRef fileURL, CFStringRef * errorString ) {␊ |
150 | ␉CFPropertyListRef propertyList;␊ |
151 | ␉CFDataRef resourceData;␊ |
152 | ␉Boolean status;␊ |
153 | ␉SInt32 errorCode;␊ |
154 | ␉␊ |
155 | ␉// Read the XML file.␊ |
156 | ␉status = CFURLCreateDataAndPropertiesFromResource(␊ |
157 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ kCFAllocatorDefault,␊ |
158 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ fileURL,␊ |
159 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ &resourceData, // place to put file data␊ |
160 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ NULL,␊ |
161 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ NULL,␊ |
162 | ␉␉␉␉␉␉␉␉␉␉␉␉␉ &errorCode);␊ |
163 | ␉if (!status) return NULL;␊ |
164 | ␉␊ |
165 | ␉// Reconstitute the dictionary using the XML data.␊ |
166 | ␉propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,␊ |
167 | ␉␉␉␉␉␉␉␉␉␉␉␉ resourceData,␊ |
168 | ␉␉␉␉␉␉␉␉␉␉␉␉ kCFPropertyListMutableContainersAndLeaves,␊ |
169 | ␉␉␉␉␉␉␉␉␉␉␉␉ errorString);␊ |
170 | ␊ |
171 | ␉␉␉␉␉␉␊ |
172 | ␉CFRelease( resourceData );␊ |
173 | ␉return propertyList;␊ |
174 | }␊ |
175 | ␊ |
176 | /****************************************************************************/␊ |
177 | static void show(CFStringRef formatString, ...) {␊ |
178 | CFStringRef resultString;␊ |
179 | CFDataRef data;␊ |
180 | va_list argList;␊ |
181 | ␉␊ |
182 | va_start(argList, formatString);␊ |
183 | resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList);␊ |
184 | va_end(argList);␊ |
185 | ␉␊ |
186 | data = CFStringCreateExternalRepresentation(NULL, resultString, CFStringGetSystemEncoding(), '?');␊ |
187 | ␉␊ |
188 | if (data != NULL) {␊ |
189 | printf ("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data));␊ |
190 | CFRelease(data);␊ |
191 | }␊ |
192 | ␉␊ |
193 | CFRelease(resultString);␊ |
194 | }␊ |
195 | /****************************************************************************/␊ |
196 | /*␊ |
197 | * Always return a valid static const string, if the CFSTR is not valid, then we return ""␊ |
198 | */␊ |
199 | static const char * CfsToCs(CFStringRef inRef)␊ |
200 | {␊ |
201 | ␉static char buffer[512]="";␊ |
202 | ␉if(CFStringGetFileSystemRepresentation (inRef, buffer, sizeof(buffer)))␊ |
203 | ␉ return buffer;␊ |
204 | ␉return "";␊ |
205 | }␊ |
206 | ␉␊ |
207 | /****************************************************************************/␊ |
208 | /**␊ |
209 | * Creates a PropertyList Incstance␊ |
210 | */␊ |
211 | PropertyList::~PropertyList()␊ |
212 | {␊ |
213 | ␉if (_CFURLRef) CFRelease(_CFURLRef);␊ |
214 | ␉if (_proplistRef) CFRelease(_proplistRef);␊ |
215 | ␊ |
216 | }␊ |
217 | bool PropertyList::chmodFile(const char * path, const char * chmodMask,␊ |
218 | ␉␉␉␉␉␉␉␉␉ AuthorizationRef auth, AuthorizationFlags flags)␊ |
219 | {␊ |
220 | ␉if (!path || !*path) return false;␊ |
221 | ␉␊ |
222 | ␉if (auth)␊ |
223 | ␉{ // give write temporary write rights to the file␊ |
224 | ␉␉std::string args = chmodMask;␊ |
225 | ␉␉args += ' ';␊ |
226 | ␉␉args += path;␊ |
227 | ␉␉if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))␉␊ |
228 | ␉␉␉return false;␊ |
229 | ␉}␊ |
230 | ␉return true;␊ |
231 | ␉␊ |
232 | }␊ |
233 | ␊ |
234 | /****************************************************************************/␊ |
235 | /**␊ |
236 | * Open a properlist from a path name␊ |
237 | */␊ |
238 | bool PropertyList::open(const char * path, CFStringRef * errorString, AuthorizationRef auth, AuthorizationFlags flags)␊ |
239 | {␊ |
240 | ␉bool ret = false;␊ |
241 | ␉␊ |
242 | ␉if (!path || !*path) return false;␊ |
243 | ␊ |
244 | ␉// give write temporary write rights to the file␊ |
245 | ␉if (!chmodFile(path,"0777", auth, flags)) return false;␊ |
246 | ␊ |
247 | ␉_propFilePath = path;␊ |
248 | ␊ |
249 | ␉CFStringRef cfPath = CFStringCreateWithCString (kCFAllocatorDefault, path, kCFStringEncodingUTF8);␊ |
250 | ␉CFURLRef inURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,␊ |
251 | ␉␉␉␉␉␉␉␉␉␉␉cfPath, ␊ |
252 | ␉␉␉␉␉␉␉␉␉␉␉kCFURLPOSIXPathStyle, // interpret as POSIX path␊ |
253 | ␉␉␉␉␉␉␉␉␉␉␉false ); // is it a directory?␊ |
254 | ␉CFRelease(cfPath);␊ |
255 | ␉if (_CFURLRef) CFRelease(_CFURLRef);␊ |
256 | ␉_CFURLRef = inURL;␊ |
257 | ␉␊ |
258 | ␉if (_CFURLRef) ␊ |
259 | ␉{␊ |
260 | ␉␉_proplistRef = CreatePropertyListFromFile(inURL, errorString);␊ |
261 | ␉␉␊ |
262 | ␉␉if (_proplistRef) ␊ |
263 | ␉␉␉ret= true;␊ |
264 | ␉}␊ |
265 | ␉// restore rights␊ |
266 | ␉ret= chmodFile(path,"0644", auth, flags);␊ |
267 | ␉␊ |
268 | ␉return ret;␊ |
269 | }␊ |
270 | ␊ |
271 | /****************************************************************************/␊ |
272 | /**␊ |
273 | * Save the current property list␊ |
274 | */␊ |
275 | bool PropertyList::save(AuthorizationRef auth, AuthorizationFlags flags)␊ |
276 | {␊ |
277 | ␉bool ret=false;␊ |
278 | ␉if (auth)␊ |
279 | ␉{ // give write temporary write rights to the file␊ |
280 | ␉␉std::string args = " 0777 "+ _propFilePath;␊ |
281 | ␉␉if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))␊ |
282 | ␉␉␉return false;␊ |
283 | ␉}␊ |
284 | ␉if (_proplistRef && _CFURLRef) ␊ |
285 | ␉␉ret= WritePropertyListToFile(_proplistRef,_CFURLRef);␊ |
286 | ␉if (auth)␊ |
287 | ␉{ // give write temporary write rights to the file␊ |
288 | ␉␉std::string args = " 0644 "+ _propFilePath;␊ |
289 | ␉␉if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))␊ |
290 | ␉␉␉return false;␊ |
291 | ␉}␊ |
292 | ␉return ret;␊ |
293 | }␊ |
294 | ␊ |
295 | /****************************************************************************/␊ |
296 | /**␊ |
297 | * Extract a sring value from a property list key, ␊ |
298 | * value returned is not owned by caller, copy it necessary.␊ |
299 | */␊ |
300 | const char * PropertyList::getStringForKey(const char *key)␊ |
301 | {␊ |
302 | ␉if (!_proplistRef) ␉return 0;␊ |
303 | ␉CFDictionaryRef myDict = ␊ |
304 | ␉(CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFDictionaryRef) _proplistRef : NULL;␊ |
305 | ␉CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);␊ |
306 | ␉CFStringRef myString;␊ |
307 | ␉␊ |
308 | ␉if (myDict && CFDictionaryGetValueIfPresent(myDict, cfKey, (const void **) &myString))␊ |
309 | ␉{␊ |
310 | ␉␉// show(CFSTR("Key '%@' found , value = <%@>\n"), cfKey, !myString ? CFSTR("") : myString);␊ |
311 | ␉␉CFRelease(cfKey);␊ |
312 | ␉␉return CfsToCs(myString);␊ |
313 | ␉}␊ |
314 | ␉␊ |
315 | ␉if(cfKey) CFRelease(cfKey);␊ |
316 | ␉return NULL;␊ |
317 | }␊ |
318 | /****************************************************************************/␊ |
319 | /**␊ |
320 | * replace a sring value from a property list key, ␊ |
321 | * value returned is not owned by caller, copy it necessary.␊ |
322 | */␊ |
323 | bool PropertyList::setStringForKey(const char *key, const char * value)␊ |
324 | {␊ |
325 | ␉if (!_proplistRef) ␉return false;␊ |
326 | ␉bool ret = false;␊ |
327 | ␉CFMutableDictionaryRef myDict = ␊ |
328 | ␉(CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFMutableDictionaryRef) _proplistRef : NULL;␊ |
329 | ␉CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);␊ |
330 | ␉CFStringRef myString = CFStringCreateWithCString (kCFAllocatorDefault, value, kCFStringEncodingUTF8);␊ |
331 | ␉␊ |
332 | ␉if (myDict) {␊ |
333 | ␉␉CFDictionaryReplaceValue(myDict, cfKey, myString);␊ |
334 | ␉␉ret=true;␉␊ |
335 | ␉} ␊ |
336 | ␉if(cfKey) CFRelease(cfKey);␊ |
337 | ␉if(myString) CFRelease(myString);␊ |
338 | ␉return ret;␊ |
339 | }␊ |
340 | ␊ |
341 | |