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

Archive Download this file

Revision: 51