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 : will wait for execution termination
104// by calling wait()
105//--------------------------------------------------------------------------
106 bool executePrivilegedCmd(AuthorizationRef auth,
107 const char* pathToTool,
108 const char* args,
109 AuthorizationFlags flags)
110{
111const char * argv[16];
112
113parseArgs(args, argv, sizeof(argv)/sizeof(const char*));
114
115// Execute Cmd
116OSStatus status = AuthorizationExecuteWithPrivileges(auth, pathToTool,flags, (char**)argv, NULL);
117// Wait for the child process of AEWP to terminate:
118int wait_status=0;
119/* pid_t pid = */
120wait(&wait_status);
121// usleep(10000); // 10 ms
122// Cleanup mem
123for (int i=0; argv[i]; i++) free ((void*) argv[i]);
124
125 return status ? false : true;
126}
127
128//--------------------------------------------------------------------------
129// Execute priviledged chmod for accessing system files
130//--------------------------------------------------------------------------
131bool PropertyList::chmodFile(const char * path, const char * chmodMask,
132 AuthorizationRef auth, AuthorizationFlags flags)
133{
134if (!path || !*path) return false;
135
136if (auth)
137{ // give write temporary write rights to the file
138std::string args = chmodMask;
139args += ' ';
140args += path;
141struct stat st;
142if (stat(path,&st)!=0)
143executePrivilegedCmd(auth, "/usr/bin/touch", path, flags);
144if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
145return false;
146}
147return true;
148
149}
150
151//--------------------------------------------------------------------------
152// Write a property list from a file
153//--------------------------------------------------------------------------
154bool WritePropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL )
155{
156CFDataRef xmlData;
157Boolean status;
158SInt32 errorCode;
159
160// Convert the property list into XML data.
161xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList );
162
163// Write the XML data to the file.
164status = CFURLWriteDataAndPropertiesToResource (
165fileURL, // URL to use
166xmlData, // data to write
167NULL,
168&errorCode);
169CFRelease(xmlData);
170
171return status ? true: false;
172}
173
174//--------------------------------------------------------------------------
175// Read a property list from a file
176//--------------------------------------------------------------------------
177static CFPropertyListRef CreatePropertyListFromFile( CFURLRef fileURL,
178const std::string& filePath,
179CFStringRef * errorString,
180bool createIfNotExist) {
181CFPropertyListRef propertyList;
182CFDataRef resourceData;
183Boolean status;
184SInt32 errorCode;
185//
186if (!fileExists(filePath))
187{
188if (createIfNotExist)
189{
190CFMutableDictionaryRef dict =
191 CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
192 &kCFTypeDictionaryKeyCallBacks,
193 &kCFTypeDictionaryValueCallBacks );
194WritePropertyListToFile(dict, fileURL);
195}
196
197}
198// Read the XML file.
199status = CFURLCreateDataAndPropertiesFromResource(
200 kCFAllocatorDefault,
201 fileURL,
202 &resourceData, // place to put file data
203 NULL,
204 NULL,
205 &errorCode);
206if (!status) return NULL;
207
208// Reconstitute the dictionary using the XML data.
209propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
210 resourceData,
211 kCFPropertyListMutableContainersAndLeaves,
212 errorString);
213
214
215CFRelease( resourceData );
216return propertyList;
217}
218
219//--------------------------------------------------------------------------
220// Always return a valid static const string,
221// if the CFSTR is not valid, then we return ""
222//--------------------------------------------------------------------------
223static const char * CfsToCs(CFStringRef inRef)
224{
225static char *buffer=NULL;
226CFIndex len = CFStringGetLength(inRef);
227if (buffer) {
228delete[] buffer;
229}
230buffer = new char[len+1];
231if(CFStringGetFileSystemRepresentation (inRef, buffer, len+1))
232return buffer;
233return "";
234}
235
236//--------------------------------------------------------------------------
237// Destruct a PropertyList Instance
238//--------------------------------------------------------------------------
239PropertyList::~PropertyList()
240{
241if (_CFURLRef) CFRelease(_CFURLRef);
242if (_proplistRef) CFRelease(_proplistRef);
243
244}
245
246//--------------------------------------------------------------------------
247// Open a property list from a path name with auth
248//--------------------------------------------------------------------------
249bool PropertyList::open(const char * path, bool createIfNotExist, AuthorizationRef auth, AuthorizationFlags flags)
250{
251bool ret = false;
252
253if (!path || !*path) return false;
254_propFilePath = path;
255
256CFStringRef cfPath = CFStringCreateWithCString (kCFAllocatorDefault, path, kCFStringEncodingUTF8);
257CFURLRef inURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
258cfPath,
259kCFURLPOSIXPathStyle, // interpret as POSIX path
260false ); // is it a directory?
261CFRelease(cfPath);
262if (_CFURLRef) CFRelease(_CFURLRef);
263_CFURLRef = inURL;
264
265if (_CFURLRef)
266{
267CFRetain(_CFURLRef);
268
269// give write temporary write rights to the file
270if (!chmodFile(path,"0777", auth, flags)) return false;
271
272_proplistRef = CreatePropertyListFromFile(inURL, _propFilePath, &_errorString, createIfNotExist);
273
274// restore rights
275ret= chmodFile(path,"0644", auth, flags);
276
277if (_proplistRef) {
278CFRetain(_proplistRef);
279ret= true;
280}
281}
282
283return ret;
284}
285
286//--------------------------------------------------------------------------
287// Save the current property list
288//--------------------------------------------------------------------------
289bool PropertyList::save(AuthorizationRef auth, AuthorizationFlags flags)
290{
291bool ret=false;
292if (auth)
293{ // give write temporary write rights to the file
294std::string args = " 0777 "+ _propFilePath;
295if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
296return false;
297}
298if (_proplistRef && _CFURLRef)
299ret= WritePropertyListToFile(_proplistRef,_CFURLRef);
300if (auth)
301{ // give write temporary write rights to the file
302std::string args = " 0644 "+ _propFilePath;
303if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
304return false;
305}
306return ret;
307}
308
309//--------------------------------------------------------------------------
310// Get a string value from a property list key,
311// value returned is not owned by caller, copy it necessary.
312//--------------------------------------------------------------------------
313const char * PropertyList::getStringForKey(const char *key)
314{
315if (!_proplistRef) return NULL;
316CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
317CFStringRef myString;
318
319if (_proplistRef && CFDictionaryGetValueIfPresent((CFMutableDictionaryRef)_proplistRef,
320 cfKey, (const void **) &myString))
321{
322CFRelease(cfKey);
323return CfsToCs(myString);
324}
325
326if(cfKey) CFRelease(cfKey);
327return NULL;
328}
329
330//--------------------------------------------------------------------------
331// Replace or add a string value from a property list key,
332// value returned is not owned by caller, copy it necessary.
333//--------------------------------------------------------------------------
334bool PropertyList::setStringForKey(const char *key, const char * value)
335{
336if (!_proplistRef) return false;
337bool ret = false;
338CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
339CFStringRef myString = CFStringCreateWithCString (kCFAllocatorDefault, value, kCFStringEncodingUTF8);
340CFMutableDictionaryRef myDict = (CFMutableDictionaryRef) _proplistRef;
341
342if (myDict)
343{
344CFDictionarySetValue(myDict, cfKey, myString);
345ret=true;
346}
347if(cfKey) CFRelease(cfKey);
348if(myString) CFRelease(myString);
349return ret;
350}
351
352//--------------------------------------------------------------------------
353// Delete a key and its value from the dictionary
354//--------------------------------------------------------------------------
355bool PropertyList::removeKeyAndValue(const char *key)
356{
357if (!_proplistRef) return false;
358bool ret = false;
359
360CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
361
362if (_proplistRef) {
363CFDictionaryRemoveValue((CFMutableDictionaryRef) _proplistRef, cfKey);
364ret=true;
365}
366if(cfKey) CFRelease(cfKey);
367return ret;
368}
369
370

Archive Download this file

Revision: 382