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

Archive Download this file

Revision: 57