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/****************************************************************************/
178/*
179 * Always return a valid static const string, if the CFSTR is not valid, then we return ""
180 */
181static const char * CfsToCs(CFStringRef inRef)
182{
183static char buffer[512]="";
184if(CFStringGetFileSystemRepresentation (inRef, buffer, sizeof(buffer)))
185 return buffer;
186return "";
187}
188
189/****************************************************************************/
190/**
191 * Creates a PropertyList Incstance
192 */
193PropertyList::~PropertyList()
194{
195if (_CFURLRef) CFRelease(_CFURLRef);
196if (_proplistRef) CFRelease(_proplistRef);
197
198}
199bool PropertyList::chmodFile(const char * path, const char * chmodMask,
200 AuthorizationRef auth, AuthorizationFlags flags)
201{
202if (!path || !*path) return false;
203
204if (auth)
205{ // give write temporary write rights to the file
206std::string args = chmodMask;
207args += ' ';
208args += path;
209if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
210return false;
211}
212return true;
213
214}
215
216/****************************************************************************/
217/**
218 * Open a properlist from a path name
219 */
220bool PropertyList::open(const char * path, CFStringRef * errorString, AuthorizationRef auth, AuthorizationFlags flags)
221{
222bool ret = false;
223
224if (!path || !*path) return false;
225struct stat st;
226if(stat(path,&st) != 0) return false; // file does not exist;
227
228// give write temporary write rights to the file
229if (!chmodFile(path,"0777", auth, flags)) return false;
230
231_propFilePath = path;
232
233CFStringRef cfPath = CFStringCreateWithCString (kCFAllocatorDefault, path, kCFStringEncodingUTF8);
234CFURLRef inURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
235cfPath,
236kCFURLPOSIXPathStyle, // interpret as POSIX path
237false ); // is it a directory?
238CFRelease(cfPath);
239if (_CFURLRef) CFRelease(_CFURLRef);
240_CFURLRef = inURL;
241
242if (_CFURLRef)
243{
244CFRetain(_CFURLRef);
245_proplistRef = CreatePropertyListFromFile(inURL, errorString);
246
247if (_proplistRef) {
248CFRetain(_proplistRef);
249ret= true;
250}
251}
252// restore rights
253ret= chmodFile(path,"0644", auth, flags);
254
255return ret;
256}
257
258/****************************************************************************/
259/**
260 * Save the current property list
261 */
262bool PropertyList::save(AuthorizationRef auth, AuthorizationFlags flags)
263{
264bool ret=false;
265if (auth)
266{ // give write temporary write rights to the file
267std::string args = " 0777 "+ _propFilePath;
268if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
269return false;
270}
271if (_proplistRef && _CFURLRef)
272ret= WritePropertyListToFile(_proplistRef,_CFURLRef);
273if (auth)
274{ // give write temporary write rights to the file
275std::string args = " 0644 "+ _propFilePath;
276if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags))
277return false;
278}
279return ret;
280}
281
282/****************************************************************************/
283/**
284 * Extract a sring value from a property list key,
285 * value returned is not owned by caller, copy it necessary.
286 */
287const char * PropertyList::getStringForKey(const char *key)
288{
289if (!_proplistRef) return NULL;
290CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
291CFStringRef myString;
292
293if (_proplistRef && CFDictionaryGetValueIfPresent((CFMutableDictionaryRef)_proplistRef,
294 cfKey, (const void **) &myString))
295{
296CFRelease(cfKey);
297return CfsToCs(myString);
298}
299
300if(cfKey) CFRelease(cfKey);
301return NULL;
302}
303/****************************************************************************/
304/**
305 * replace a sring value from a property list key,
306 * value returned is not owned by caller, copy it necessary.
307 */
308bool PropertyList::setStringForKey(const char *key, const char * value)
309{
310if (!_proplistRef) return false;
311bool ret = false;
312CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
313CFStringRef myString = CFStringCreateWithCString (kCFAllocatorDefault, value, kCFStringEncodingUTF8);
314CFMutableDictionaryRef myDict = (CFMutableDictionaryRef) _proplistRef;
315
316if (myDict)
317{
318CFDictionarySetValue(myDict, cfKey, myString);
319ret=true;
320}
321if(cfKey) CFRelease(cfKey);
322//if(myString) CFRelease(myString);
323return ret;
324}
325
326/****************************************************************************/
327/**
328 * delete a key and its value from the dictionary
329 */
330bool PropertyList::removeKeyAndValue(const char *key)
331{
332if (!_proplistRef) return false;
333bool ret = false;
334
335CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8);
336
337if (_proplistRef) {
338CFDictionaryRemoveValue((CFMutableDictionaryRef) _proplistRef, cfKey);
339ret=true;
340}
341if(cfKey) CFRelease(cfKey);
342return ret;
343}
344
345

Archive Download this file

Revision: 49