Chameleon Applications

Chameleon Applications Svn Source Tree

Root/trunk/ChameleonPrefPane/Sources/PropertyList.cpp

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

Archive Download this file

Revision: 47