Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/i386/libsaio/xml.c

1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights
7 * Reserved.
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 2.0 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
13 *
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include "config.h"
26#include "bootstruct.h"
27#include "libsaio.h"
28#include "sl.h"
29#include "xml.h"
30
31#if DEBUG_XML
32#define DBG(x...)printf(x)
33#else
34#define DBG(x...)
35#endif
36
37string_ref *ref_strings = NULL;
38string_ref *ref_integer = NULL;
39
40/// TODO: remove below
41static char *buffer_start = NULL;
42// TODO: redo the next two functions
43void SaveRefString(char *string, int id)
44{
45//printf("Adding Ref String %d (%s)\n", id, string);
46string_ref *tmp = ref_strings;
47while(tmp)
48{
49if(tmp->id == id)
50{
51tmp->string = malloc(strlen(string)+1);
52strncpy(tmp->string, string, strlen(string)+1);
53return;
54}
55tmp = tmp->next;
56}
57
58string_ref *new_ref = malloc(sizeof(string_ref));
59new_ref->string = malloc(strlen(string)+1);
60strncpy(new_ref->string, string, (strlen(string)+1)* sizeof(char));
61new_ref->id = id;
62new_ref->next = ref_strings;
63ref_strings = new_ref;
64}
65
66void SaveRefInteger(int integer, int id)
67{
68//printf("Adding Ref Integer %d (%s)\n", id, integer);
69string_ref *tmp = ref_integer;
70while(tmp)
71{
72if(tmp->id == id)
73{
74tmp->string = (char*)integer;
75return;
76}
77tmp = tmp->next;
78}
79
80string_ref *new_ref = malloc(sizeof(string_ref));
81new_ref->string = (char*)integer;
82new_ref->id = id;
83new_ref->next = ref_integer;
84ref_integer = new_ref;
85}
86
87char *GetRefString(int id)
88{
89string_ref *tmp = ref_strings;
90while(tmp)
91{
92if(tmp->id == id) return tmp->string;
93tmp = tmp->next;
94}
95//verbose("Unable to locate Ref String %d\n", id);
96return "Unknown";
97}
98
99int GetRefInteger(int id)
100{
101string_ref *tmp = ref_integer;
102while(tmp)
103{
104if(tmp->id == id) return (int)tmp->string;
105tmp = tmp->next;
106}
107//verbose("Unable to locate Ref String %d\n", id);
108return 0;
109}
110
111struct Module {
112struct Module *nextModule;
113longwillLoad;
114TagPtrdict;
115char*plistAddr;
116longplistLength;
117char*driverPath;
118};
119typedef struct Module Module, *ModulePtr;
120
121struct DriverInfo {
122char*plistAddr;
123longplistLength;
124void*moduleAddr;
125longmoduleLength;
126};
127typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
128
129#define kDriverPackageSignature1 'MKXT'
130#define kDriverPackageSignature2 'MOSX'
131
132struct DriversPackage {
133unsigned long signature1;
134unsigned long signature2;
135unsigned long length;
136unsigned long adler32;
137unsigned long version;
138unsigned long numDrivers;
139unsigned long reserved1;
140unsigned long reserved2;
141};
142typedef struct DriversPackage DriversPackage;
143
144enum {
145kCFBundleType2,
146kCFBundleType3
147};
148
149
150#define DOFREE 1
151
152static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
153static long ParseTagKey(char *buffer, TagPtr *tag);
154static long ParseTagString(char *buffer, TagPtr *tag);
155static long ParseTagInteger(char *buffer, TagPtr *tag);
156static long ParseTagData(char *buffer, TagPtr *tag);
157static long ParseTagDate(char *buffer, TagPtr *tag);
158//static long ParseTagBoolean(char *buffer, TagPtr *tag, long type);
159static long GetNextTag(char *buffer, char **tag, long *start);
160static long FixDataMatchingTag(char *buffer, char *tag);
161static TagPtr NewTag(void);
162static char *NewSymbol(char *string);
163#if DOFREE
164static void FreeSymbol(char *string);
165#endif
166
167//==========================================================================
168// XMLGetProperty
169TagPtr XMLGetProperty(TagPtr dict, const char *key)
170{
171TagPtr tagList, tag;
172
173if (dict->type != kTagTypeDict)
174{
175return NULL;
176}
177
178tag = 0;
179tagList = dict->tag;
180while (tagList) {
181tag = tagList;
182tagList = tag->tagNext;
183
184if ((tag->type != kTagTypeKey) || (tag->string == 0))
185{
186continue;
187}
188
189if (!strcmp(tag->string, key))
190{
191return tag->tag;
192}
193}
194return NULL;
195}
196
197//==========================================================================
198// XMLGetProperty
199TagPtr XMLGetKey( TagPtr dict, int id )
200{
201TagPtr tagList, tag;
202
203if (dict->type != kTagTypeDict)
204{
205return 0;
206}
207
208tag = 0;
209int element = 0;
210tagList = dict->tag;
211while (tagList && element != id)
212{
213tag = tagList;
214tagList = tag->tagNext;
215
216if ((tag->type != kTagTypeKey) || (tag->string == 0))
217{
218continue;
219}
220
221 element++;
222if(id == element)
223{
224return tag;
225}
226
227}
228return 0;
229}
230
231TagPtr XMLGetValueForKey(TagPtr key)
232{
233if (!key || key->type != kTagTypeKey)
234{
235return 0;
236}
237
238return key->tag;
239}
240
241// XMLGetTag(int index)
242
243// XMLTagCount( TagPtr dict )
244int XMLTagCount( TagPtr dict )
245{
246int count = 0;
247TagPtr tagList, tag;
248
249if (dict->type != kTagTypeDict && dict->type != kTagTypeArray)
250{
251return 0;
252}
253
254tag = 0;
255tagList = dict->tag;
256while (tagList)
257{
258tag = tagList;
259tagList = tag->tagNext;
260
261if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0)))
262&& (dict->type != kTagTypeArray)// If we are an array, any element is valid
263)
264{
265continue;
266}
267
268//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string);
269
270count++;
271}
272
273return count;
274}
275
276TagPtr XMLGetElement( TagPtr dict, int id )
277{
278if(dict->type != kTagTypeArray)
279{
280return 0;
281}
282
283int element = 0;
284TagPtr tmp = dict->tag;
285
286while(element < id)
287{
288element++;
289tmp = tmp->tagNext;
290}
291
292return tmp;
293}
294
295typedef const struct XMLEntity {
296const char *name;
297size_t nameLen;
298char value;
299} XMLEntity;
300
301/* This is ugly, but better than specifying the lengths by hand */
302
303#define _e(str,c) {str,sizeof(str)-1,c}
304const XMLEntity ents[] = {
305_e("quot;",'"'), // double quotation mark
306_e("apos;",'\''), // apostrophe (apostrophe-quote)
307_e("lt;", '<'), // less-than sign
308_e("gt;", '>'), // greater-than sign
309_e("amp;", '&') // ampersand
310};
311
312/* Function for basic XML character entities parsing */
313char *XMLDecode(const char *src)
314{
315size_t len;
316const char *s;
317char *out, *o;
318
319if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) )
320{
321return 0;
322}
323
324o = out;
325s = src;
326while (s <= src+len) /* Make sure the terminator is also copied */
327{
328if ( *s == '&' )
329{
330bool entFound = false;
331int i;
332
333s++;
334for ( i = 0; i < sizeof(ents)/sizeof(ents[0]); i++)
335{
336if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 )
337{
338entFound = true;
339break;
340}
341}
342if ( entFound )
343{
344*o++ = ents[i].value;
345s += ents[i].nameLen;
346
347continue;
348}
349}
350
351*o++ = *s++;
352}
353
354return out;
355}
356
357//==========================================================================
358// XMLParseFile
359// Expects to see one dictionary in the XML file, the final pos will be returned
360// If the pos is not equal to the strlen, then there are multiple dicts
361// Puts the first dictionary it finds in the
362// tag pointer and returns the end of the dic, or returns -1 if not found.
363//
364long XMLParseFile( char * buffer, TagPtr *dict )
365{
366longlength;
367longpos = 0;
368TagPtrtag;
369char*configBuffer;
370
371int strlength = strlen(buffer);
372configBuffer = malloc(strlength+1);
373bcopy(buffer, configBuffer, strlength);
374
375configBuffer[strlength] = 0;
376
377buffer_start = configBuffer;
378
379while (1)
380{
381length = XMLParseNextTag(configBuffer + pos, &tag);
382if (length == -1) break;
383
384pos += length;
385
386if (tag == 0)
387{
388continue;
389}
390
391if (tag->type == kTagTypeDict)
392{
393break;
394}
395
396XMLFreeTag(tag);
397}
398free(configBuffer);
399if (length < 0)
400{
401return -1;
402}
403*dict = tag;
404return pos;
405}
406
407//==========================================================================
408// ParseNextTag
409// TODO: cleanup
410long XMLParseNextTag( char *buffer, TagPtr *tag )
411{
412longlength = 0;
413longpos = 0;
414char*tagName = NULL;
415
416length = GetNextTag(buffer, &tagName, 0);
417if (length == -1)
418{
419return -1;
420}
421
422pos = length;
423if (!strncmp(tagName, kXMLTagPList, 6))
424{
425length = 0;
426// just a header; nothing to parse
427// return-via-reference tag should be left alone
428}
429/***** dict ****/
430else if (!strncmp(tagName, kXMLTagDict, sizeof(kXMLTagDict)))
431{
432length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
433}
434else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/')
435{
436length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);
437}
438else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " ")))
439{
440length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
441}
442/***** key ****/
443else if (!strncmp(tagName, kXMLTagKey, sizeof(kXMLTagKey)))
444{
445length = ParseTagKey(buffer + pos, tag);
446}
447
448/***** string ****/
449else if (!strncmp(tagName, kXMLTagString, sizeof(kXMLTagString)))
450{
451length = ParseTagString(buffer + pos, tag);
452}
453else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " ")))
454{
455// TODO: save tag if if found
456if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID)))
457{
458// ID=
459int id = 0;
460int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1;
461while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
462tagName[cnt] = 0;
463char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\"");
464while(*val)
465{
466if ((*val >= '0' && *val <= '9'))// 0 - 9
467{
468id = (id * 10) + (*val++ - '0');
469}
470else
471{
472printf("ParseStringID error (0x%x)\n", *val);
473getchar();
474return -1;
475}
476}
477length = ParseTagString(buffer + pos, tag);
478
479SaveRefString(buffer + pos, id);
480}
481else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
482{
483// IDREF=
484int id = 0;
485int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1;
486while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
487tagName[cnt] = 0;
488char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\"");
489while(*val)
490{
491if ((*val >= '0' && *val <= '9'))// 0 - 9
492{
493id = (id * 10) + (*val++ - '0');
494}
495else
496{
497printf("ParseStringIDREF error (0x%x)\n", *val);
498getchar();
499return -1;
500}
501}
502char* str = GetRefString(id);
503
504TagPtr tmpTag = NewTag();
505tmpTag->type = kTagTypeString;
506tmpTag->string = str;
507tmpTag->tag = 0;
508tmpTag->tagNext = 0;
509tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
510*tag = tmpTag;
511
512length = 0;
513//printf("Located IDREF, id = %d, string = %s\n", id, str);
514}
515}
516
517/***** integer ****/
518else if (!strncmp(tagName, kXMLTagInteger, sizeof(kXMLTagInteger)))
519{
520length = ParseTagInteger(buffer + pos, tag);
521}
522else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " ")))
523{
524if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID)))
525{
526// ID=
527int id = 0;
528int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1;
529while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
530tagName[cnt] = 0;
531char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\"");
532while(*val)
533{
534if ((*val >= '0' && *val <= '9'))// 0 - 9
535{
536id = (id * 10) + (*val++ - '0');
537}
538else
539{
540printf("ParseIntegerID error (0x%x)\n", *val);
541getchar();
542return -1;
543}
544}
545length = ParseTagInteger(buffer + pos, tag);
546
547SaveRefInteger((int)(*tag)->string, id);
548}
549else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
550{
551// IDREF=
552int id = 0;
553int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1;
554while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
555tagName[cnt] = 0;
556char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\"");
557while(*val)
558{
559if ((*val >= '0' && *val <= '9'))// 0 - 9
560{
561id = (id * 10) + (*val++ - '0');
562}
563else
564{
565printf("ParseStringIDREF error (0x%x)\n", *val);
566getchar();
567return -1;
568}
569}
570int integer = GetRefInteger(id);
571
572TagPtr tmpTag = NewTag();
573if (tmpTag == 0)
574{
575return -1;
576}
577
578tmpTag->type = kTagTypeInteger;
579tmpTag->string = (char*) integer;
580tmpTag->tag = 0;
581tmpTag->tagNext = 0;
582tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
583
584*tag = tmpTag;
585
586length = 0;
587//printf("Located IDREF, id = %d, string = %s\n", id, str);
588}
589else
590{
591length = ParseTagInteger(buffer + pos, tag);
592}
593}
594
595/***** data ****/
596else if (!strncmp(tagName, kXMLTagData, sizeof(kXMLTagData)))
597{
598length = ParseTagData(buffer + pos, tag);
599}
600else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))
601{
602length = ParseTagData(buffer + pos, tag);
603}
604
605else if (!strncmp(tagName, kXMLTagDate, sizeof(kXMLTagDate)))
606{
607length = ParseTagDate(buffer + pos, tag);
608}
609
610/***** date ****/
611else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))
612{
613length = ParseTagDate(buffer + pos, tag);
614}
615
616/***** false ****/
617else if (!strncmp(tagName, kXMLTagFalse, sizeof(kXMLTagFalse)))
618{
619length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
620}
621
622/***** true ****/
623else if (!strncmp(tagName, kXMLTagTrue, sizeof(kXMLTagTrue)))
624{
625length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
626}
627
628/***** array ****/
629else if (!strncmp(tagName, kXMLTagArray, sizeof(kXMLTagArray) ))
630{
631length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
632}
633else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))
634{
635length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
636}
637else if (!strncmp(tagName, kXMLTagArray "/", strlen(kXMLTagArray "/")))
638{
639length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
640}
641
642/***** unknown ****/
643else
644{
645// it wasn't parsed so we consumed no additional characters
646*tag = NULL;
647length = 0;
648}
649
650if (length == -1)
651{
652return -1;
653}
654
655return pos + length;
656}
657
658//==========================================================================
659// ParseTagList
660static long ParseTagList( char *buffer, TagPtr *tag, long type, long empty )
661{
662longpos = 0;
663longlength = 0;
664TagPtrtagList = NULL;
665TagPtrtmpTag;
666
667
668if (!empty)
669{
670while (1)
671{
672length = XMLParseNextTag(buffer + pos, &tmpTag);
673if (length == -1)
674{
675break;
676}
677
678pos += length;
679
680// detect end of list
681if (tmpTag == NULL)
682{
683break;
684}
685tmpTag->tagNext = tagList;
686tagList = tmpTag;
687}
688
689if (length == -1)
690{
691XMLFreeTag(tagList);
692return -1;
693}
694}
695
696tmpTag = NewTag();
697if (tmpTag == NULL)
698{
699XMLFreeTag(tagList);
700return -1;
701}
702
703tmpTag->type = type;
704tmpTag->string = 0;
705tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
706tmpTag->tag = tagList;
707tmpTag->tagNext = 0;
708
709*tag = tmpTag;
710
711return pos;
712}
713
714//==========================================================================
715// ParseTagKey
716static long ParseTagKey( char *buffer, TagPtr *tag )
717{
718longlength = 0;
719longlength2 = 0;
720char*string;
721TagPtrtmpTag;
722TagPtrsubTag;
723
724length = FixDataMatchingTag(buffer, kXMLTagKey);
725if (length == -1)
726{
727return -1;
728}
729
730length2 = XMLParseNextTag(buffer + length, &subTag);
731if (length2 == -1)
732{
733return -1;
734}
735
736tmpTag = NewTag();
737if (tmpTag == NULL)
738{
739XMLFreeTag(subTag);
740return -1;
741}
742
743string = NewSymbol(buffer);
744if (string == NULL)
745{
746XMLFreeTag(subTag);
747XMLFreeTag(tmpTag);
748return -1;
749}
750
751tmpTag->type = kTagTypeKey;
752tmpTag->string = string;
753tmpTag->tag = subTag;
754tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
755tmpTag->tagNext = 0;
756
757*tag = tmpTag;
758
759return length + length2;
760}
761
762//==========================================================================
763// ParseTagString
764static long ParseTagString( char *buffer, TagPtr *tag )
765{
766longlength = 0;
767char*string;
768
769length = FixDataMatchingTag(buffer, kXMLTagString);
770if (length == -1)
771{
772return -1;
773}
774
775TagPtr tmpTag = NewTag();
776if (tmpTag == NULL)
777{
778return -1;
779}
780
781string = NewSymbol(buffer);
782if (string == NULL)
783{
784XMLFreeTag(tmpTag);
785return -1;
786}
787
788tmpTag->type = kTagTypeString;
789tmpTag->string = string;
790tmpTag->tag = NULL;
791tmpTag->tagNext = NULL;
792tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
793
794*tag = tmpTag;
795return length;
796}
797
798//==========================================================================
799// ParseTagInteger
800static long ParseTagInteger( char *buffer, TagPtr *tag )
801{
802long length, integer;
803bool negative = false;
804TagPtr tmpTag;
805char* val = buffer;
806int size;
807
808if(buffer[0] == '<')
809{
810printf("Warning integer is non existant\n");
811getchar();
812tmpTag = NewTag();
813tmpTag->type = kTagTypeInteger;
814tmpTag->string = 0;
815tmpTag->tag = 0;
816tmpTag->offset = 0;
817tmpTag->tagNext = 0;
818
819*tag = tmpTag;
820
821return 0;
822}
823
824size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
825if (length == -1)
826{
827return -1;
828}
829
830tmpTag = NewTag();
831
832if (tmpTag == 0)
833{
834return -1;
835}
836integer = 0;
837
838if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
839{
840val += 2;
841while(*val)
842{
843if ((*val >= '0' && *val <= '9'))// 0 - 9
844{
845integer = (integer * 16) + (*val++ - '0');
846}
847else if ((*val >= 'a' && *val <= 'f'))// a - f
848{
849integer = (integer * 16) + (*val++ - 'a' + 10);
850}
851else if ((*val >= 'A' && *val <= 'F'))// A - F
852{
853integer = (integer * 16) + (*val++ - 'A' + 10);
854}
855else
856{
857printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
858getchar();
859XMLFreeTag(tmpTag);
860return -1;
861}
862}
863}
864else if ( size )// Decimal value
865{
866if (*val == '-')
867{
868negative = true;
869val++;
870size--;
871}
872
873for (integer = 0; size > 0; size--)
874{
875if(*val) // UGLY HACK, fix me.
876{
877if (*val < '0' || *val > '9')
878{
879printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
880getchar();
881return -1;
882}
883
884integer = (integer * 10) + (*val++ - '0');
885}
886}
887
888if (negative) {
889integer = -integer;
890}
891}
892
893tmpTag->type = kTagTypeInteger;
894tmpTag->string = (char *)integer;
895tmpTag->tag = NULL;
896tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
897tmpTag->tagNext = NULL;
898
899*tag = tmpTag;
900
901return length;
902}
903
904//==========================================================================
905// ParseTagData
906static long ParseTagData( char *buffer, TagPtr *tag)
907{
908//intactuallen = 0;
909int len = 0;
910long length = 0;
911TagPtrtmpTag;
912char*tmpString;
913
914length = FixDataMatchingTag(buffer, kXMLTagData);
915if (length == -1)
916{
917return -1;
918}
919
920tmpTag = NewTag();
921if (tmpTag == NULL)
922{
923return -1;
924}
925tmpString = NewSymbol(buffer);
926tmpTag->type = kTagTypeData;
927tmpTag->string = tmpString;
928tmpTag->data = (UInt8 *)BASE64Decode(buffer, strlen(buffer), &len);
929tmpTag->dataLen = len;
930
931tmpTag->tag = NULL;
932tmpTag->offset = /* actuallen; */ buffer_start ? buffer - buffer_start: 0;
933tmpTag->tagNext = NULL;
934
935*tag = tmpTag;
936
937return length;
938}
939
940//==========================================================================
941// ParseTagDate
942static long ParseTagDate( char *buffer, TagPtr *tag )
943{
944longlength = 0;
945TagPtrtmpTag;
946
947length = FixDataMatchingTag(buffer, kXMLTagDate);
948if (length == -1)
949{
950return -1;
951}
952
953tmpTag = NewTag();
954if (tmpTag == NULL)
955{
956return -1;
957}
958
959printf("ParseTagDate unimplimented\n");
960getchar();
961
962tmpTag->type = kTagTypeDate;
963tmpTag->string = NULL;
964tmpTag->tag = NULL;
965tmpTag->tagNext = NULL;
966tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
967
968*tag = tmpTag;
969
970return length;
971}
972
973//==========================================================================
974// ParseTagBoolean
975long ParseTagBoolean( char *buffer, TagPtr *tag, long type )
976{
977TagPtr tmpTag;
978
979tmpTag = NewTag();
980if (tmpTag == NULL)
981{
982return -1;
983}
984
985tmpTag->type = type;
986tmpTag->string = NULL;
987tmpTag->tag = NULL;
988tmpTag->tagNext = NULL;
989tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
990
991
992*tag = tmpTag;
993
994return 0;
995}
996
997//==========================================================================
998// GetNextTag
999static long GetNextTag( char *buffer, char **tag, long *start )
1000{
1001longcnt;
1002longcnt2;
1003
1004if (tag == NULL)
1005{
1006return -1;
1007}
1008
1009// Find the start of the tag.
1010cnt = 0;
1011while ((buffer[cnt] != '\0') && (buffer[cnt] != '<'))
1012{
1013cnt++;
1014}
1015
1016if (buffer[cnt] == '\0')
1017{
1018return -1;
1019}
1020// Find the end of the tag.
1021cnt2 = cnt + 1;
1022while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>'))
1023{
1024cnt2++;
1025}
1026
1027if (buffer[cnt2] == '\0')
1028{
1029return -1;
1030}
1031
1032// Fix the tag data.
1033*tag = buffer + cnt + 1;
1034buffer[cnt2] = '\0';
1035if (start)
1036{
1037*start = cnt;
1038}
1039
1040return cnt2 + 1;
1041}
1042
1043//==========================================================================
1044// FixDataMatchingTag
1045// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
1046// Returns the length of the data found, counting the end tag,
1047// or -1 if the end tag was not found.
1048static long FixDataMatchingTag( char *buffer, char *tag )
1049{
1050longlength;
1051longstart;
1052longstop;
1053char*endTag;
1054
1055start = 0;
1056while (1)
1057{
1058length = GetNextTag(buffer + start, &endTag, &stop);
1059if (length == -1)
1060{
1061return -1;
1062}
1063
1064if ((*endTag == '/') && !strcmp(endTag + 1, tag))
1065{
1066break;
1067}
1068
1069start += length;
1070}
1071
1072buffer[start + stop] = '\0';
1073
1074return start + length;
1075}
1076
1077//==========================================================================
1078// NewTag
1079#define kTagsPerBlock (0x1000)
1080
1081static TagPtr gTagsFree= NULL;
1082static TagPtr NewTag( void )
1083{
1084longcnt;
1085TagPtrtag;
1086
1087if (gTagsFree == NULL)
1088{
1089tag = (TagPtr)malloc(kTagsPerBlock *sizeof(Tag));
1090if (tag == NULL)
1091{
1092return NULL;
1093}
1094
1095// Initalize the new tags.
1096for (cnt = 0; cnt < kTagsPerBlock; cnt++)
1097{
1098tag[cnt].type = kTagTypeNone;
1099tag[cnt].string = 0;
1100tag[cnt].data = 0;
1101tag[cnt].dataLen = 0;
1102tag[cnt].tag = 0;
1103tag[cnt].tagNext = tag + cnt + 1;
1104}
1105tag[kTagsPerBlock - 1].tagNext = 0;
1106
1107gTagsFree = tag;
1108}
1109
1110tag = gTagsFree;
1111gTagsFree = tag->tagNext;
1112
1113return tag;
1114}
1115
1116//==========================================================================
1117// XMLFreeTag
1118void XMLFreeTag( TagPtr tag )
1119{
1120#if DOFREE
1121if (tag == NULL)
1122{
1123return;
1124}
1125
1126if (!XMLIsInteger(tag) && tag->string)
1127{
1128FreeSymbol(tag->string);
1129}
1130
1131XMLFreeTag(tag->tag);
1132XMLFreeTag(tag->tagNext);
1133
1134// Clear and free the tag.
1135tag->type = kTagTypeNone;
1136tag->string = NULL;
1137tag->data = NULL;
1138tag->dataLen = 0;
1139tag->tag = NULL;
1140tag->offset = 0;
1141tag->tagNext = gTagsFree;
1142gTagsFree = tag;
1143#else
1144return;
1145#endif
1146}
1147
1148//==========================================================================
1149// Symbol object.
1150struct Symbol
1151{
1152long refCount;
1153struct Symbol *next;
1154char string[];
1155};
1156typedef struct Symbol Symbol, *SymbolPtr;
1157
1158static SymbolPtr FindSymbol(char *string, SymbolPtr *prevSymbol);
1159
1160static SymbolPtr gSymbolsHead= NULL;
1161
1162//==========================================================================
1163// NewSymbol
1164static char *NewSymbol( char *string )
1165{
1166static SymbolPtr lastGuy = 0;
1167
1168SymbolPtrsymbol;
1169
1170// Look for string in the list of symbols.
1171symbol = FindSymbol(string, 0);
1172
1173// Add the new symbol.
1174if (symbol == NULL)
1175{
1176symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1177if (symbol == NULL)
1178{
1179stop("NULL symbol!");
1180return NULL;
1181}
1182
1183// Set the symbol's data.
1184symbol->refCount = 0;
1185strcpy(symbol->string, string);
1186
1187// Add the symbol to the list.
1188symbol->next = gSymbolsHead;
1189gSymbolsHead = symbol;
1190}
1191
1192// Update the refCount and return the string.
1193symbol->refCount++;
1194
1195if (lastGuy && lastGuy->next != 0)
1196{
1197stop("last guy not last!");
1198}
1199
1200return symbol->string;
1201}
1202
1203//==========================================================================
1204// FreeSymbol
1205#if DOFREE
1206static void FreeSymbol( char *string )
1207{
1208SymbolPtr symbol, prev;
1209prev = NULL;
1210
1211// Look for string in the list of symbols.
1212symbol = FindSymbol(string, &prev);
1213if (symbol == NULL)
1214{
1215return;
1216}
1217
1218// Update the refCount.
1219symbol->refCount--;
1220
1221if (symbol->refCount != 0)
1222{
1223return;
1224}
1225
1226// Remove the symbol from the list.
1227if (prev != NULL)
1228{
1229prev->next = symbol->next;
1230}
1231else
1232{
1233gSymbolsHead = symbol->next;
1234}
1235
1236// Free the symbol's memory.
1237free(symbol);
1238}
1239#endif
1240
1241//==========================================================================
1242// FindSymbol
1243static SymbolPtr FindSymbol( char *string, SymbolPtr *prevSymbol )
1244{
1245SymbolPtr symbol, prev;
1246
1247if (string == NULL)
1248{
1249return NULL;
1250}
1251
1252symbol = gSymbolsHead;
1253prev = NULL;
1254
1255while (symbol != NULL)
1256{
1257if (!strcmp(symbol->string, string))
1258{
1259break;
1260}
1261
1262prev = symbol;
1263symbol = symbol->next;
1264}
1265
1266if ((symbol != NULL) && (prevSymbol != NULL))
1267{
1268*prevSymbol = prev;
1269}
1270
1271return symbol;
1272}
1273
1274bool XMLIsType(TagPtr dict, enum xmltype type)
1275{
1276if(!dict)
1277{
1278return (type == kTagTypeNone);
1279}
1280return (dict->type == type);
1281}
1282
1283/*** Cast functions ***/
1284bool XMLIsArray(TagPtr entry)
1285{
1286return entry && (entry->type == kTagTypeArray);
1287}
1288
1289TagPtr XMLCastArray(TagPtr dict)
1290{
1291if(!dict)
1292{
1293return NULL;
1294}
1295
1296if(dict->type == kTagTypeArray)
1297{
1298return dict;
1299} else {
1300return NULL;
1301}
1302}
1303
1304bool XMLIsDict(TagPtr entry)
1305{
1306 return entry && (entry->type == kTagTypeDict);
1307}
1308
1309bool XMLIsData(TagPtr entry)
1310{
1311return entry && (entry->type == kTagTypeData);
1312}
1313
1314TagPtr XMLCastDict(TagPtr dict)
1315{
1316if(!dict)
1317{
1318return NULL;
1319}
1320
1321if(dict->type == kTagTypeDict)
1322{
1323return dict;
1324}
1325else
1326{
1327return NULL;
1328}
1329}
1330
1331bool XMLIsString(TagPtr entry)
1332{
1333 return entry && ((entry->type == kTagTypeString) || (entry->type == kTagTypeKey));
1334}
1335
1336char *XMLCastString(TagPtr dict)
1337{
1338if(!dict)
1339{
1340return NULL;
1341}
1342
1343if((dict->type == kTagTypeString) || (dict->type == kTagTypeKey))
1344{
1345return dict->string;
1346}
1347
1348return NULL;
1349}
1350
1351char *XMLCastData(TagPtr dict, int* length)
1352{
1353if(!dict)
1354{
1355return NULL;
1356}
1357
1358if((dict->type == kTagTypeData) || (dict->type == kTagTypeKey))
1359{
1360*length = dict->offset;
1361return dict->string;
1362}
1363*length = 0;
1364return NULL;
1365}
1366
1367
1368long XMLCastStringOffset(TagPtr dict)
1369{
1370if(dict && ((dict->type == kTagTypeString) || (dict->type == kTagTypeKey)))
1371{
1372return dict->offset;
1373}
1374else
1375{
1376return -1;
1377}
1378}
1379
1380bool XMLIsBoolean(TagPtr entry)
1381{
1382return entry && ((entry->type == kTagTypeTrue) || (entry->type == kTagTypeFalse));
1383}
1384
1385bool XMLCastBoolean(TagPtr dict)
1386{
1387if(!dict)
1388{
1389return false;
1390}
1391
1392if(dict->type == kTagTypeTrue)
1393{
1394return true;
1395}
1396return false;
1397}
1398
1399bool XMLIsInteger(TagPtr entry)
1400{
1401 return entry && (entry->type == kTagTypeInteger);
1402}
1403
1404int XMLCastInteger(TagPtr dict)
1405{
1406if(!dict)
1407{
1408//printf("XMLCastInteger: null dict\n");
1409return 0;
1410}
1411
1412if(dict->type == kTagTypeInteger)
1413{
1414return (int)(dict->string);
1415}
1416return 0;
1417}
1418
1419bool XMLAddTagToDictionary(TagPtr dict, char *key, TagPtr value)
1420{
1421if (!dict || dict->type != kTagTypeDict)
1422{
1423return false;
1424}
1425
1426TagPtr tmpTag;
1427char* string;
1428
1429tmpTag = NewTag();
1430if (tmpTag == 0)
1431{
1432return false;
1433}
1434
1435string = NewSymbol(key);
1436if (string == 0)
1437{
1438XMLFreeTag(tmpTag);
1439return false;
1440}
1441
1442tmpTag->type = kTagTypeKey;
1443tmpTag->string = string;
1444tmpTag->tag = value;
1445tmpTag->offset = 0;
1446tmpTag->tagNext = 0;
1447
1448TagPtr tagList = dict->tag;
1449if(!tagList)
1450{
1451// First tag
1452dict->tag = tmpTag;
1453return true;
1454}
1455while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1456if(tagList)
1457{
1458tagList->tagNext = tmpTag;
1459return true;
1460}
1461
1462XMLFreeTag(tmpTag);
1463return false;
1464}
1465//==========================================================================
1466// Micky1979
1467// XMLConvertTagPtrToXMLString
1468// convert back a TagPtr to a xml representation
1469// Here is still w/o header and footer
1470char *XMLConvertTagPtrToXMLString(TagPtr aDict, long parentType, int indent)
1471{
1472indent ++;
1473// TODO check if we can use a buffer for the booter stuff already reserved somewhere
1474char *string = "";
1475char *ind = "";
1476for (int i = 0; i < indent; i++)
1477{
1478char *ind2 = malloc(strlen(ind) + strlen("\t") +1);
1479strcpy(ind2, ind);
1480ind2[strlen(ind)] = '\t';
1481ind2[strlen(ind) +1] = '\0';
1482ind = ind2;
1483}
1484unsigned long length = 0;
1485int count = XMLTagCount(aDict);
1486
1487while(count)
1488{
1489// parsing only supported tags
1490char *key = NULL;
1491TagPtr sub = NULL;
1492if (!XMLIsArray(aDict))
1493{
1494key = XMLCastString(XMLGetKey(aDict, count));
1495sub = XMLGetProperty(aDict, key);
1496}
1497else
1498{
1499key = "";
1500sub = XMLGetElement( aDict, count-1);
1501}
1502
1503if(sub)
1504{
1505if(XMLIsData(sub))
1506{
1507char *temp;
1508if (parentType == kTagTypeArray)
1509{
1510length = (strlen(ind) +
1511strlen(sub->string ? sub->string : "") +
1512strlen("<data>") +
1513strlen("</data>\n") +
15141);
1515temp = malloc(strlen(string) + length);
1516snprintf(temp, length+strlen(string), "%s%s<data>%s</data>\n", string, ind, sub->string ? sub->string : "");
1517} else {
1518length = (strlen(ind) +
1519strlen(key) +
1520strlen("<key>") +
1521strlen("</key>\n") +
1522strlen(ind) +
1523strlen(sub->string ? sub->string : "") +
1524strlen("<data>") +
1525strlen("</data>\n") +
15261);
1527temp = malloc(strlen(string) + length);
1528snprintf(temp, length+strlen(string), "%s%s<key>%s</key>\n%s<data>%s</data>\n",
1529string, ind, key, ind, sub->string ? sub->string : "");
1530}
1531
1532temp[strlen(string) + length] = '\0';
1533string = temp;
1534}
1535else if(XMLIsString(sub))
1536{
1537char *temp;
1538if (parentType == kTagTypeArray)
1539{
1540length = (strlen(ind) +
1541strlen("<string>") +
1542strlen(XMLCastString(sub) ? XMLCastString(sub) : "") +
1543strlen("</string>\n") +
15441);
1545temp = malloc(strlen(string) + length);
1546snprintf(temp, length+strlen(string), "%s%s<string>%s</string>\n",
1547string, ind, XMLCastString(sub) ? XMLCastString(sub) : "");
1548} else {
1549length = (strlen(ind) +
1550strlen(key) +
1551strlen("<key>") +
1552strlen("</key>\n") +
1553strlen(ind) +
1554strlen("<string>") +
1555strlen(XMLCastString(sub) ? XMLCastString(sub) : "") +
1556strlen("</string>\n") +
15571);
1558temp = malloc(strlen(string) + length);
1559snprintf(temp, length+strlen(string), "%s%s<key>%s</key>\n%s<string>%s</string>\n",
1560string, ind, key, ind, XMLCastString(sub) ? XMLCastString(sub) : "");
1561}
1562
1563temp[strlen(string) + length] = '\0';
1564string = temp;
1565}
1566else if(XMLIsInteger(sub))
1567{
1568// 'real' (float/dowble) cannot be parsed. only integers
1569int x = XMLCastInteger(sub);
1570char xBuf[snprintf( NULL, 0, "%d", x )];
1571snprintf( xBuf, snprintf( NULL, 0, "%d", x ) +1, "%d", x );
1572char *temp;
1573if (parentType == kTagTypeArray)
1574{
1575length = (strlen(ind) +
1576strlen("<integer>") +
1577sizeof(xBuf) +
1578strlen("</integer>\n") +
15791);
1580temp = malloc(strlen(string) + length);
1581snprintf(temp, length+strlen(string), "%s%s<integer>%s</integer>\n", string, ind, (char *)xBuf);
1582} else {
1583length = (strlen(ind) +
1584strlen(key) +
1585strlen("<key>") +
1586strlen("</key>\n") +
1587strlen(ind) +
1588strlen("<integer>") +
1589sizeof(xBuf) +
1590strlen("</integer>\n") +
15911);
1592temp = malloc(strlen(string) + length);
1593snprintf(temp, length+strlen(string), "%s%s<key>%s</key>\n%s<integer>%s</integer>\n",
1594string, ind, key, ind, (char *)xBuf);
1595}
1596
1597temp[strlen(string) + length] = '\0';
1598string = temp;
1599}
1600else if(XMLIsBoolean(sub))
1601{
1602char *temp;
1603int v = XMLCastBoolean(sub);
1604
1605if (parentType == kTagTypeArray)
1606{
1607length = (strlen(ind) +
1608strlen(v ? "<true/>\n" : "<false/>\n") +
16091);
1610temp = malloc(strlen(string) + length);
1611snprintf(temp, length+strlen(string), "%s%s%s", string, ind, v ? "<true/>\n" : "<false/>\n");
1612} else {
1613length = (strlen(ind) +
1614strlen(key) +
1615strlen("<key>") +
1616strlen("</key>\n") +
1617strlen(ind) +
1618strlen(v ? "<true/>\n" : "<false/>\n") +
16191);
1620temp = malloc(strlen(string) + length);
1621snprintf(temp, length+strlen(string), "%s%s<key>%s</key>\n%s%s",
1622string, ind, key, ind, v ? "<true/>\n" : "<false/>\n");
1623}
1624
1625temp[strlen(string) + length] = '\0';
1626string = temp;
1627}
1628else if (XMLIsDict(sub) || XMLIsArray(sub)) // its a contenitor..
1629{
1630int subCount = XMLTagCount(sub);
1631char *otag = subCount <=0 ? "" : XMLIsDict(sub) ? "<dict>\n" : "<array>\n";
1632char *ctag = subCount <=0 ? XMLIsDict(sub) ? "<dict/>\n" :
1633"<array/>\n" : XMLIsDict(sub) ? "</dict>\n" : "</array>\n";
1634char *dict = NULL;
1635dict = NULL;
1636dict = XMLConvertTagPtrToXMLString(sub, sub->type, indent);
1637
1638length = (strlen(ind) +
1639strlen(key) +
1640strlen("<key>") +
1641strlen("</key>\n") +
1642strlen(ind) +
1643strlen(otag) +
1644strlen(dict) +
1645strlen(ind) +
1646strlen(ctag) +
16471);
1648
1649char *temp = malloc(strlen(string) + length);
1650snprintf(temp, length+strlen(string), "%s%s<key>%s</key>\n%s%s%s%s%s\n",
1651string, ind, key, ind, otag, dict, ind, ctag);
1652
1653temp[strlen(string) + length] = '\0';
1654string = temp;
1655}
1656}
1657count--;
1658}
1659
1660if(strlen(ind))
1661{
1662free(ind);
1663} // not mallocated if ""
1664
1665return string;
1666}
1667
1668// XMLConvertTagPtrToPropertyList_v1
1669// convert back a TagPtr to a xml representation
1670// with header and footer
1671char *XMLConvertTagPtrToPropertyList_v1(TagPtr aDict)
1672{
1673if (!aDict)
1674{
1675return NULL;
1676}
1677
1678char *s = XMLConvertTagPtrToXMLString(aDict, aDict->type, 1);
1679
1680if (s == NULL)
1681{
1682return NULL;
1683}
1684
1685unsigned long length = ((strlen(kXMLv1) -1 /* -1 for %s included */) +
1686strlen(s) +
16871);
1688
1689char *propertyList = malloc(length);
1690snprintf(propertyList, length, kXMLv1, s);
1691
1692if (strlen(s))
1693{
1694free(s);
1695}
1696
1697return (char *)propertyList;
1698}
1699
1700// XMLGenerateKextInjectorFromTag
1701// generate an full Info.plist to create a kext injector
1702// sDict should contains all the contents of IOKitPersonalities
1703// personalityName is a funcy name. Must not be a real kext name
1704
1705// OSBundleRequired should be the same of the real kext you want to hack (Root, Safe Boot, Network-Root etc.)
1706// can also be NULL or "" assuming the target kext does not have this key.
1707char * XMLGenerateKextInjectorFromTag(TagPtr aDict, char *personalityName, char *OSBundleRequired)
1708{
1709if (!aDict || personalityName == NULL)
1710{
1711return NULL;
1712}
1713
1714char *IOKitPersonalities = XMLConvertTagPtrToXMLString(aDict, aDict->type, 1);
1715
1716if (IOKitPersonalities == NULL)
1717{
1718return NULL;
1719}
1720
1721char *OBRkey = OSBundleRequired == NULL ? "" : OSBundleRequired;
1722char *propertyList;
1723unsigned long length = 0;
1724
1725if (strlen(OBRkey))
1726{
1727length = (strlen("\t<key>OSBundleRequired</key>\n\t<string>") +
1728strlen(OBRkey) +
1729strlen("</string>\n") +
17301);
1731char temp[length];
1732snprintf(temp, length, "\t<key>OSBundleRequired</key>\n\t<string>%s</string>\n", OBRkey);
1733unsigned long mlength = ((strlen(kFakeInjectorKext) -8 /* %s x 8 */) +
1734strlen(personalityName) +
1735strlen(personalityName) +
1736strlen(IOKitPersonalities) +
1737length +
17381);
1739propertyList = malloc(mlength);
1740snprintf(propertyList, mlength, kFakeInjectorKext, personalityName, personalityName, IOKitPersonalities, temp);
1741}
1742else
1743{
1744unsigned long mlength = ((strlen(kFakeInjectorKext) -8 /* %s x 8 */) +
1745strlen(personalityName) +
1746strlen(personalityName) +
1747strlen(IOKitPersonalities) +
17481);
1749propertyList = malloc(mlength);
1750snprintf(propertyList, mlength, kFakeInjectorKext, personalityName, personalityName, IOKitPersonalities, "");
1751}
1752
1753if (strlen(IOKitPersonalities))
1754{
1755free(IOKitPersonalities);
1756}
1757
1758return propertyList;
1759
1760}
1761

Archive Download this file

Revision: 2871