MagickCore 7.0.10
xml-tree.c
Go to the documentation of this file.
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X M M L %
7% X X MM MM L %
8% X M M M L %
9% X X M M L %
10% X X M M LLLLL %
11% %
12% TTTTT RRRR EEEEE EEEEE %
13% T R R E E %
14% T RRRR EEE EEE %
15% T R R E E %
16% T R R EEEEE EEEEE %
17% %
18% %
19% XML Tree Methods %
20% %
21% Software Design %
22% Cristy %
23% December 2004 %
24% %
25% %
26% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
27% dedicated to making software imaging solutions freely available. %
28% %
29% You may not use this file except in compliance with the License. You may %
30% obtain a copy of the License at %
31% %
32% https://imagemagick.org/script/license.php %
33% %
34% Unless required by applicable law or agreed to in writing, software %
35% distributed under the License is distributed on an "AS IS" BASIS, %
36% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
37% See the License for the specific language governing permissions and %
38% limitations under the License. %
39% %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42% This module implements the standard handy xml-tree methods for storing and
43% retrieving nodes and attributes from an XML string.
44%
45*/
46
47/*
48 Include declarations.
49*/
50#include "wizard/studio.h"
51#include "wizard/blob.h"
52#include "wizard/exception.h"
54#include "wizard/log.h"
55#include "wizard/memory_.h"
56#include "wizard/semaphore.h"
57#include "wizard/splay-tree.h"
58#include "wizard/string_.h"
60#include "wizard/xml-tree.h"
62#include "wizard/utility.h"
64
65/*
66 Define declarations.
67*/
68#define NumberPredefinedEntities 10
69#define XMLWhitespace "\t\r\n "
70
71/*
72 Typedef declarations.
73*/
75{
76 char
80
81 size_t
83
90
93
96
97 size_t
99};
100
101typedef struct _XMLTreeRoot
103
105{
106 struct _XMLTreeInfo
108
111
114
115 char
119
122
125
126 size_t
128};
129
130/*
131 Global declarations.
132*/
133static char
134 *sentinel[] = { (char *) NULL };
135
136/*
137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138% %
139% %
140% %
141% A d d C h i l d T o X M L T r e e %
142% %
143% %
144% %
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146%
147% AddChildToXMLTree() adds a child tag at an offset relative to the start of
148% the parent tag's character content. Return the child tag.
149%
150% The format of the AddChildToXMLTree method is:
151%
152% XMLTreeInfo *AddChildToXMLTree(XMLTreeInfo *xml_info,const char *tag,
153% const size_t offset)
154%
155% A description of each parameter follows:
156%
157% o xml_info: the xml info.
158%
159% o tag: the tag.
160%
161% o offset: the tag offset.
162%
163*/
165 const char *tag,const size_t offset)
166{
168 *child;
169
170 if (xml_info == (XMLTreeInfo *) NULL)
171 return((XMLTreeInfo *) NULL);
173 if (child == (XMLTreeInfo *) NULL)
174 return((XMLTreeInfo *) NULL);
175 (void) memset(child,0,sizeof(*child));
181 return(InsertTagIntoXMLTree(xml_info,child,offset));
182}
183
184/*
185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186% %
187% %
188% %
189% A d d P a t h T o X M L T r e e %
190% %
191% %
192% %
193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194%
195% AddPathToXMLTree() adds a child tag at an offset relative to the start of
196% the parent tag's character content. This method returns the child tag.
197%
198% The format of the AddPathToXMLTree method is:
199%
200% XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info,const char *path,
201% const size_t offset)
202%
203% A description of each parameter follows:
204%
205% o xml_info: the xml info.
206%
207% o path: the path.
208%
209% o offset: the tag offset.
210%
211*/
213 const char *path,const size_t offset)
214{
215 char
216 **components,
217 subnode[WizardPathExtent],
219
220 ssize_t
221 i;
222
223 size_t
224 number_components;
225
226 ssize_t
227 j;
228
230 *child,
231 *node;
232
233 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
235 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
237 node=xml_info;
238 components=GetPathComponents(path,&number_components);
239 if (components == (char **) NULL)
240 return((XMLTreeInfo *) NULL);
241 for (i=0; i < (ssize_t) number_components; i++)
242 {
243 GetPathComponent(components[i],SubnodePath,subnode);
244 GetPathComponent(components[i],CanonicalPath,tag);
246 if (child == (XMLTreeInfo *) NULL)
248 node=child;
249 if (node == (XMLTreeInfo *) NULL)
250 break;
251 for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--)
252 {
253 node=GetXMLTreeOrdered(node);
254 if (node == (XMLTreeInfo *) NULL)
255 break;
256 }
257 if (node == (XMLTreeInfo *) NULL)
258 break;
259 components[i]=DestroyString(components[i]);
260 }
261 for ( ; i < (ssize_t) number_components; i++)
262 components[i]=DestroyString(components[i]);
263 components=(char **) RelinquishWizardMemory(components);
264 return(node);
265}
266
267/*
268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269% %
270% %
271% %
272% C a n o n i c a l X M L C o n t e n t %
273% %
274% %
275% %
276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277%
278% CanonicalXMLContent() converts text to canonical XML content by converting
279% to UTF-8, substituting predefined entities, wrapping as CDATA, or encoding
280% as base-64 as required.
281%
282% The format of the CanonicalXMLContent method is:
283%
284% char *CanonicalXMLContent(const char *content,
285% const WizardBooleanType pedantic)
286%
287% A description of each parameter follows:
288%
289% o content: the content.
290%
291% o pedantic: if true, replace newlines and tabs with their respective
292% entities.
293%
294*/
295
296static unsigned char *ConvertLatin1ToUTF8(const unsigned char *content)
297{
298 const unsigned char
299 *p;
300
301 unsigned char
302 *q;
303
304 size_t
305 length;
306
307 unsigned char
308 *utf8;
309
310 unsigned int
311 c;
312
313 length=0;
314 for (p=content; *p != '\0'; p++)
315 length+=(*p & 0x80) != 0 ? 2 : 1;
316 utf8=(unsigned char *) NULL;
317 if (~length >= 1)
318 utf8=(unsigned char *) AcquireQuantumMemory(length+1UL,sizeof(*utf8));
319 if (utf8 == (unsigned char *) NULL)
320 return((unsigned char *) NULL);
321 q=utf8;
322 for (p=content; *p != '\0'; p++)
323 {
324 c=(*p);
325 if ((c & 0x80) == 0)
326 *q++=c;
327 else
328 {
329 *q++=0xc0 | ((c >> 6) & 0x3f);
330 *q++=0x80 | (c & 0x3f);
331 }
332 }
333 *q='\0';
334 return(utf8);
335}
336
338 const WizardBooleanType pedantic)
339{
340 char
341 *base64,
342 *canonical_content;
343
344 const unsigned char
345 *p;
346
347 ssize_t
348 i;
349
350 size_t
351 extent,
352 length;
353
354 unsigned char
355 *utf8;
356
357 utf8=ConvertLatin1ToUTF8((const unsigned char *) content);
358 if (utf8 == (unsigned char *) NULL)
359 return((char *) NULL);
360 for (p=utf8; *p != '\0'; p++)
361 if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d))
362 break;
363 if (*p != '\0')
364 {
365 /*
366 String is binary, base64-encode it.
367 */
368 base64=Base64Encode(utf8,strlen((char *) utf8),&length);
369 utf8=(unsigned char *) RelinquishWizardMemory(utf8);
370 if (base64 == (char *) NULL)
371 return((char *) NULL);
372 canonical_content=AcquireString("<base64>");
373 (void) ConcatenateString(&canonical_content,base64);
374 base64=DestroyString(base64);
375 (void) ConcatenateString(&canonical_content,"</base64>");
376 return(canonical_content);
377 }
378 /*
379 Substitute predefined entities.
380 */
381 i=0;
382 canonical_content=AcquireString((char *) NULL);
383 extent=WizardPathExtent;
384 for (p=utf8; *p != '\0'; p++)
385 {
386 if ((i+WizardPathExtent) > (ssize_t) extent)
387 {
388 extent+=WizardPathExtent;
389 canonical_content=(char *) ResizeQuantumMemory(canonical_content,extent,
390 sizeof(*canonical_content));
391 if (canonical_content == (char *) NULL)
392 return(canonical_content);
393 }
394 switch (*p)
395 {
396 case '&':
397 {
398 i+=FormatLocaleString(canonical_content+i,extent,"&amp;");
399 break;
400 }
401 case '<':
402 {
403 i+=FormatLocaleString(canonical_content+i,extent,"&lt;");
404 break;
405 }
406 case '>':
407 {
408 i+=FormatLocaleString(canonical_content+i,extent,"&gt;");
409 break;
410 }
411 case '"':
412 {
413 i+=FormatLocaleString(canonical_content+i,extent,"&quot;");
414 break;
415 }
416 case '\n':
417 {
418 if (pedantic == WizardFalse)
419 {
420 canonical_content[i++]=(char) (*p);
421 break;
422 }
423 i+=FormatLocaleString(canonical_content+i,extent,"&#xA;");
424 break;
425 }
426 case '\t':
427 {
428 if (pedantic == WizardFalse)
429 {
430 canonical_content[i++]=(char) (*p);
431 break;
432 }
433 i+=FormatLocaleString(canonical_content+i,extent,"&#x9;");
434 break;
435 }
436 case '\r':
437 {
438 i+=FormatLocaleString(canonical_content+i,extent,"&#xD;");
439 break;
440 }
441 default:
442 {
443 canonical_content[i++]=(char) (*p);
444 break;
445 }
446 }
447 }
448 canonical_content[i]='\0';
449 utf8=(unsigned char *) RelinquishWizardMemory(utf8);
450 return(canonical_content);
451}
452
453/*
454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455% %
456% %
457% %
458% D e s t r o y X M L T r e e %
459% %
460% %
461% %
462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463%
464% DestroyXMLTree() destroys the xml-tree.
465%
466% The format of the DestroyXMLTree method is:
467%
468% XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info)
469%
470% A description of each parameter follows:
471%
472% o xml_info: the xml info.
473%
474*/
475
477{
478 ssize_t
479 i;
480
481 /*
482 Destroy a tag attribute list.
483 */
484 if ((attributes == (char **) NULL) || (attributes == sentinel))
485 return((char **) NULL);
486 for (i=0; attributes[i] != (char *) NULL; i+=2)
487 {
488 /*
489 Destroy attribute tag and value.
490 */
491 if (attributes[i] != (char *) NULL)
493 if (attributes[i+1] != (char *) NULL)
495 }
497 return((char **) NULL);
498}
499
500static void DestroyXMLTreeChild(XMLTreeInfo *xml_info)
501{
503 *child,
504 *node;
505
506 child=xml_info->child;
507 while(child != (XMLTreeInfo *) NULL)
508 {
509 node=child;
510 child=node->child;
511 node->child=(XMLTreeInfo *) NULL;
512 (void) DestroyXMLTree(node);
513 }
514}
515
516static void DestroyXMLTreeOrdered(XMLTreeInfo *xml_info)
517{
519 *node,
520 *ordered;
521
522 ordered=xml_info->ordered;
523 while(ordered != (XMLTreeInfo *) NULL)
524 {
525 node=ordered;
526 ordered=node->ordered;
527 node->ordered=(XMLTreeInfo *) NULL;
528 (void) DestroyXMLTree(node);
529 }
530}
531
532static void DestroyXMLTreeRoot(XMLTreeInfo *xml_info)
533{
534 char
535 **attributes;
536
537 ssize_t
538 i;
539
540 ssize_t
541 j;
542
544 *root;
545
546 assert(xml_info != (XMLTreeInfo *) NULL);
547 assert((xml_info->signature == WizardSignature) ||
548 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
549 if (xml_info->parent != (XMLTreeInfo *) NULL)
550 return;
551 /*
552 Free root tag allocations.
553 */
554 root=(XMLTreeRoot *) xml_info;
555 for (i=NumberPredefinedEntities; root->entities[i] != (char *) NULL; i+=2)
556 root->entities[i+1]=DestroyString(root->entities[i+1]);
557 root->entities=(char **) RelinquishWizardMemory(root->entities);
558 for (i=0; root->attributes[i] != (char **) NULL; i++)
559 {
560 attributes=root->attributes[i];
561 if (attributes[0] != (char *) NULL)
563 for (j=1; attributes[j] != (char *) NULL; j+=3)
564 {
565 if (attributes[j] != (char *) NULL)
567 if (attributes[j+1] != (char *) NULL)
569 if (attributes[j+2] != (char *) NULL)
571 }
573 }
574 if (root->attributes[0] != (char **) NULL)
575 root->attributes=(char ***) RelinquishWizardMemory(root->attributes);
576 if (root->processing_instructions[0] != (char **) NULL)
577 {
578 for (i=0; root->processing_instructions[i] != (char **) NULL; i++)
579 {
580 for (j=0; root->processing_instructions[i][j] != (char *) NULL; j++)
582 root->processing_instructions[i][j]);
584 root->processing_instructions[i][j+1]);
586 root->processing_instructions[i]);
587 }
590 }
591}
592
594{
595 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
597 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
599 DestroyXMLTreeChild(xml_info);
600 DestroyXMLTreeOrdered(xml_info);
601 DestroyXMLTreeRoot(xml_info);
603 xml_info->content=DestroyString(xml_info->content);
604 xml_info->tag=DestroyString(xml_info->tag);
605 xml_info=(XMLTreeInfo *) RelinquishWizardMemory(xml_info);
606 return((XMLTreeInfo *) NULL);
607}
608
609/*
610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611% %
612% %
613% %
614% F i l e T o X M L %
615% %
616% %
617% %
618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619%
620% FileToXML() returns the contents of a file as a XML string.
621%
622% The format of the FileToXML method is:
623%
624% char *FileToXML(const char *filename,const size_t extent)
625%
626% A description of each parameter follows:
627%
628% o filename: the filename.
629%
630% o extent: Maximum length of the string.
631%
632*/
633WizardPrivate char *FileToXML(const char *filename,const size_t extent)
634{
635 char
636 *xml;
637
638 int
639 file;
640
642 offset;
643
644 size_t
645 i;
646
647 size_t
648 length;
649
650 ssize_t
651 count;
652
653 void
654 *map;
655
656 assert(filename != (const char *) NULL);
657 length=0;
658 file=fileno(stdin);
659 if (LocaleCompare(filename,"-") != 0)
660 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
661 if (file == -1)
662 return((char *) NULL);
663 offset=(WizardOffsetType) lseek(file,0,SEEK_END);
664 count=0;
665 if ((file == fileno(stdin)) || (offset < 0) ||
666 (offset != (WizardOffsetType) ((ssize_t) offset)))
667 {
668 size_t
669 quantum;
670
671 struct stat
672 file_stats;
673
674 /*
675 Stream is not seekable.
676 */
677 offset=(WizardOffsetType) lseek(file,0,SEEK_SET);
678 quantum=(size_t) WizardMaxBufferExtent;
679 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
680 quantum=(size_t) WizardMin(file_stats.st_size,WizardMaxBufferExtent);
681 xml=(char *) AcquireQuantumMemory(quantum,sizeof(*xml));
682 for (i=0; xml != (char *) NULL; i+=count)
683 {
684 count=read(file,xml+i,quantum);
685 if (count <= 0)
686 {
687 count=0;
688 if (errno != EINTR)
689 break;
690 }
691 if (~((size_t) i) < (quantum+1))
692 {
693 xml=(char *) RelinquishWizardMemory(xml);
694 break;
695 }
696 xml=(char *) ResizeQuantumMemory(xml,i+quantum+1,sizeof(*xml));
697 if ((size_t) (i+count) >= extent)
698 break;
699 }
700 if (LocaleCompare(filename,"-") != 0)
701 file=close(file);
702 if (xml == (char *) NULL)
703 return((char *) NULL);
704 if (file == -1)
705 {
706 xml=(char *) RelinquishWizardMemory(xml);
707 return((char *) NULL);
708 }
709 length=(size_t) WizardMin(i+count,extent);
710 xml[length]='\0';
711 return(xml);
712 }
713 length=(size_t) WizardMin(offset,(WizardOffsetType) extent);
714 xml=(char *) NULL;
715 if (~length >= (WizardPathExtent-1))
716 xml=(char *) AcquireQuantumMemory(length+WizardPathExtent,sizeof(*xml));
717 if (xml == (char *) NULL)
718 {
719 file=close(file);
720 return((char *) NULL);
721 }
722 map=MapBlob(file,ReadMode,0,length);
723 if (map != (char *) NULL)
724 {
725 (void) memcpy(xml,map,length);
726 (void) UnmapBlob(map,length);
727 }
728 else
729 {
730 (void) lseek(file,0,SEEK_SET);
731 for (i=0; i < length; i+=count)
732 {
733 count=read(file,xml+i,(size_t) WizardMin(length-i,(ssize_t) SSIZE_MAX));
734 if (count <= 0)
735 {
736 count=0;
737 if (errno != EINTR)
738 break;
739 }
740 }
741 if (i < length)
742 {
743 file=close(file)-1;
744 xml=(char *) RelinquishWizardMemory(xml);
745 return((char *) NULL);
746 }
747 }
748 xml[length]='\0';
749 if (LocaleCompare(filename,"-") != 0)
750 file=close(file);
751 if (file == -1)
752 xml=(char *) RelinquishWizardMemory(xml);
753 return(xml);
754}
755
756/*
757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758% %
759% %
760% %
761% G e t N e x t X M L T r e e T a g %
762% %
763% %
764% %
765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766%
767% GetNextXMLTreeTag() returns the next tag or NULL if not found.
768%
769% The format of the GetNextXMLTreeTag method is:
770%
771% XMLTreeInfo *GetNextXMLTreeTag(XMLTreeInfo *xml_info)
772%
773% A description of each parameter follows:
774%
775% o xml_info: the xml info.
776%
777*/
779{
780 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
782 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
784 return(xml_info->next);
785}
786
787/*
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789% %
790% %
791% %
792% G e t X M L T r e e A t t r i b u t e %
793% %
794% %
795% %
796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797%
798% GetXMLTreeAttribute() returns the value of the attribute tag with the
799% specified tag if found, otherwise NULL.
800%
801% The format of the GetXMLTreeAttribute method is:
802%
803% const char *GetXMLTreeAttribute(XMLTreeInfo *xml_info,const char *tag)
804%
805% A description of each parameter follows:
806%
807% o xml_info: the xml info.
808%
809% o tag: the attribute tag.
810%
811*/
813 const char *tag)
814{
815 ssize_t
816 i;
817
818 ssize_t
819 j;
820
822 *root;
823
824 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
826 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
828 if (xml_info->attributes == (char **) NULL)
829 return((const char *) NULL);
830 i=0;
831 while ((xml_info->attributes[i] != (char *) NULL) &&
832 (strcmp(xml_info->attributes[i],tag) != 0))
833 i+=2;
834 if (xml_info->attributes[i] != (char *) NULL)
835 return(xml_info->attributes[i+1]);
836 root=(XMLTreeRoot*) xml_info;
837 while (root->root.parent != (XMLTreeInfo *) NULL)
838 root=(XMLTreeRoot *) root->root.parent;
839 i=0;
840 while ((root->attributes[i] != (char **) NULL) &&
841 (strcmp(root->attributes[i][0],xml_info->tag) != 0))
842 i++;
843 if (root->attributes[i] == (char **) NULL)
844 return((const char *) NULL);
845 j=1;
846 while ((root->attributes[i][j] != (char *) NULL) &&
847 (strcmp(root->attributes[i][j],tag) != 0))
848 j+=3;
849 if (root->attributes[i][j] == (char *) NULL)
850 return((const char *) NULL);
851 return(root->attributes[i][j+1]);
852}
853
854/*
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856% %
857% %
858% %
859% G e t X M L T r e e A t t r i b u t e s %
860% %
861% %
862% %
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864%
865% GetXMLTreeAttributes() injects all attributes associated with the current
866% tag in the specified splay-tree.
867%
868% The format of the GetXMLTreeAttributes method is:
869%
870% WizardBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info,
871% SplayTreeInfo *attributes)
872%
873% A description of each parameter follows:
874%
875% o xml_info: the xml info.
876%
877% o attributes: the attribute splay-tree.
878%
879*/
881 SplayTreeInfo *attributes)
882{
883 ssize_t
884 i;
885
886 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
888 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
890 WizardAssert(ResourceDomain,attributes != (SplayTreeInfo *) NULL);
891 if (xml_info->attributes == (char **) NULL)
892 return(WizardTrue);
893 i=0;
894 while (xml_info->attributes[i] != (char *) NULL)
895 {
896 (void) AddValueToSplayTree(attributes,
897 ConstantString(xml_info->attributes[i]),
898 ConstantString(xml_info->attributes[i+1]));
899 i+=2;
900 }
901 return(WizardTrue);
902}
903
904/*
905%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
906% %
907% %
908% %
909% G e t X M L T r e e C h i l d %
910% %
911% %
912% %
913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
914%
915% GetXMLTreeChild() returns the first child tag with the specified tag if
916% found, otherwise NULL.
917%
918% The format of the GetXMLTreeChild method is:
919%
920% XMLTreeInfo *GetXMLTreeChild(XMLTreeInfo *xml_info,const char *tag)
921%
922% A description of each parameter follows:
923%
924% o xml_info: the xml info.
925%
926*/
928{
930 *child;
931
932 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
934 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
936 child=xml_info->child;
937 if (tag != (const char *) NULL)
938 while ((child != (XMLTreeInfo *) NULL) && (strcmp(child->tag,tag) != 0))
939 child=child->sibling;
940 return(child);
941}
942
943/*
944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945% %
946% %
947% %
948% G e t X M L T r e e C o n t e n t %
949% %
950% %
951% %
952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953%
954% GetXMLTreeContent() returns any content associated with specified
955% xml-tree node.
956%
957% The format of the GetXMLTreeContent method is:
958%
959% const char *GetXMLTreeContent(XMLTreeInfo *xml_info)
960%
961% A description of each parameter follows:
962%
963% o xml_info: the xml info.
964%
965*/
967{
968 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
970 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
972 return(xml_info->content);
973}
974
975/*
976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977% %
978% %
979% %
980% G e t X M L T r e e O r d e r e d %
981% %
982% %
983% %
984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985%
986% GetXMLTreeOrdered() returns the next ordered node if found, otherwise NULL.
987%
988% The format of the GetXMLTreeOrdered method is:
989%
990% XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info)
991%
992% A description of each parameter follows:
993%
994% o xml_info: the xml info.
995%
996*/
998{
999 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
1001 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
1003 return(xml_info->ordered);
1004}
1005
1006/*
1007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008% %
1009% %
1010% %
1011% G e t X M L T r e e P a t h %
1012% %
1013% %
1014% %
1015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016%
1017% GetXMLTreePath() traverses the XML-tree as defined by the specified path
1018% and returns the node if found, otherwise NULL.
1019%
1020% The format of the GetXMLTreePath method is:
1021%
1022% XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info,const char *path)
1023%
1024% A description of each parameter follows:
1025%
1026% o xml_info: the xml info.
1027%
1028% o path: the path (e.g. property/elapsed-time).
1029%
1030*/
1032{
1033 char
1034 **components,
1035 subnode[WizardPathExtent],
1036 tag[WizardPathExtent];
1037
1038 ssize_t
1039 i;
1040
1041 ssize_t
1042 j;
1043
1045 *node;
1046
1047 size_t
1048 number_components;
1049
1050 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
1052 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
1054 node=xml_info;
1055 components=GetPathComponents(path,&number_components);
1056 if (components == (char **) NULL)
1057 return((XMLTreeInfo *) NULL);
1058 for (i=0; i < (ssize_t) number_components; i++)
1059 {
1060 GetPathComponent(components[i],SubnodePath,subnode);
1061 GetPathComponent(components[i],CanonicalPath,tag);
1062 node=GetXMLTreeChild(node,tag);
1063 if (node == (XMLTreeInfo *) NULL)
1064 break;
1065 for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--)
1066 {
1067 node=GetXMLTreeOrdered(node);
1068 if (node == (XMLTreeInfo *) NULL)
1069 break;
1070 }
1071 if (node == (XMLTreeInfo *) NULL)
1072 break;
1073 components[i]=DestroyString(components[i]);
1074 }
1075 for ( ; i < (ssize_t) number_components; i++)
1076 components[i]=DestroyString(components[i]);
1077 components=(char **) RelinquishWizardMemory(components);
1078 return(node);
1079}
1080
1081/*
1082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083% %
1084% %
1085% %
1086% G e t X M L T r e e P r o c e s s i n g I n s t r u c t i o n s %
1087% %
1088% %
1089% %
1090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091%
1092% GetXMLTreeProcessingInstructions() returns a null terminated array of
1093% processing instructions for the given target.
1094%
1095% The format of the GetXMLTreeProcessingInstructions method is:
1096%
1097% const char **GetXMLTreeProcessingInstructions(XMLTreeInfo *xml_info,
1098% const char *target)
1099%
1100% A description of each parameter follows:
1101%
1102% o xml_info: the xml info.
1103%
1104*/
1106 XMLTreeInfo *xml_info,const char *target)
1107{
1108 ssize_t
1109 i;
1110
1112 *root;
1113
1114 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
1116 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
1118 root=(XMLTreeRoot *) xml_info;
1119 while (root->root.parent != (XMLTreeInfo *) NULL)
1120 root=(XMLTreeRoot *) root->root.parent;
1121 i=0;
1122 while ((root->processing_instructions[i] != (char **) NULL) &&
1123 (strcmp(root->processing_instructions[i][0],target) != 0))
1124 i++;
1125 if (root->processing_instructions[i] == (char **) NULL)
1126 return((const char **) sentinel);
1127 return((const char **) (root->processing_instructions[i]+1));
1128}
1129
1130/*
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132% %
1133% %
1134% %
1135% G e t X M L T r e e S i b l i n g %
1136% %
1137% %
1138% %
1139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140%
1141% GetXMLTreeSibling() returns the node sibling if found, otherwise NULL.
1142%
1143% The format of the GetXMLTreeSibling method is:
1144%
1145% XMLTreeInfo *GetXMLTreeSibling(XMLTreeInfo *xml_info)
1146%
1147% A description of each parameter follows:
1148%
1149% o xml_info: the xml info.
1150%
1151*/
1153{
1154 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
1156 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
1158 return(xml_info->sibling);
1159}
1160
1161/*
1162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163% %
1164% %
1165% %
1166% G e t X M L T r e e T a g %
1167% %
1168% %
1169% %
1170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1171%
1172% GetXMLTreeTag() returns the tag associated with specified xml-tree node.
1173%
1174% The format of the GetXMLTreeTag method is:
1175%
1176% const char *GetXMLTreeTag(XMLTreeInfo *xml_info)
1177%
1178% A description of each parameter follows:
1179%
1180% o xml_info: the xml info.
1181%
1182*/
1184{
1185 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
1187 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
1189 return(xml_info->tag);
1190}
1191
1192/*
1193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1194% %
1195% %
1196% %
1197% I n s e r t I n t o T a g X M L T r e e %
1198% %
1199% %
1200% %
1201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202%
1203% InsertTagIntoXMLTree() inserts a tag at an offset relative to the start of
1204% the parent tag's character content. This method returns the child tag.
1205%
1206% The format of the InsertTagIntoXMLTree method is:
1207%
1208% XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info,
1209% XMLTreeInfo *child,const size_t offset)
1210%
1211% A description of each parameter follows:
1212%
1213% o xml_info: the xml info.
1214%
1215% o child: the child tag.
1216%
1217% o offset: the tag offset.
1218%
1219*/
1221 XMLTreeInfo *child,const size_t offset)
1222{
1224 *head,
1225 *node,
1226 *previous;
1227
1228 child->ordered=(XMLTreeInfo *) NULL;
1229 child->sibling=(XMLTreeInfo *) NULL;
1230 child->next=(XMLTreeInfo *) NULL;
1231 child->offset=offset;
1232 child->parent=xml_info;
1233 if (xml_info->child == (XMLTreeInfo *) NULL)
1234 {
1235 xml_info->child=child;
1236 return(child);
1237 }
1238 head=xml_info->child;
1239 if (head->offset > offset)
1240 {
1241 child->ordered=head;
1242 xml_info->child=child;
1243 }
1244 else
1245 {
1246 node=head;
1247 while ((node->ordered != (XMLTreeInfo *) NULL) &&
1248 (node->ordered->offset <= offset))
1249 node=node->ordered;
1250 child->ordered=node->ordered;
1251 node->ordered=child;
1252 }
1253 previous=(XMLTreeInfo *) NULL;
1254 node=head;
1255 while ((node != (XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0))
1256 {
1257 previous=node;
1258 node=node->sibling;
1259 }
1260 if ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset))
1261 {
1262 while ((node->next != (XMLTreeInfo *) NULL) &&
1263 (node->next->offset <= offset))
1264 node=node->next;
1265 child->next=node->next;
1266 node->next=child;
1267 }
1268 else
1269 {
1270 if ((previous != (XMLTreeInfo *) NULL) && (node != (XMLTreeInfo *) NULL))
1271 previous->sibling=node->sibling;
1272 child->next=node;
1273 previous=(XMLTreeInfo *) NULL;
1274 node=head;
1275 while ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset))
1276 {
1277 previous=node;
1278 node=node->sibling;
1279 }
1280 child->sibling=node;
1281 if (previous != (XMLTreeInfo *) NULL)
1282 previous->sibling=child;
1283 }
1284 return(child);
1285}
1286
1287/*
1288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289% %
1290% %
1291% %
1292% N e w X M L T r e e %
1293% %
1294% %
1295% %
1296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1297%
1298% NewXMLTree() returns a XMLTreeInfo xml-tree as defined by the specified
1299% XML string.
1300%
1301% The format of the NewXMLTree method is:
1302%
1303% XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
1304%
1305% A description of each parameter follows:
1306%
1307% o xml: The XML string.
1308%
1309% o exception: return any errors or warnings in this structure.
1310%
1311*/
1312
1313static char *ConvertUTF16ToUTF8(const char *content,size_t *length)
1314{
1315 char
1316 *utf8;
1317
1318 int
1319 bits,
1320 byte,
1321 c,
1322 encoding;
1323
1324 ssize_t
1325 i;
1326
1327 size_t
1328 extent;
1329
1330 ssize_t
1331 j;
1332
1333 utf8=(char *) AcquireQuantumMemory(*length+1,sizeof(*utf8));
1334 if (utf8 == (char *) NULL)
1335 return((char *) NULL);
1336 encoding=(*content == '\xFE') ? 1 : (*content == '\xFF') ? 0 : -1;
1337 if (encoding == -1)
1338 {
1339 /*
1340 Already UTF-8.
1341 */
1342 (void) memcpy(utf8,content,*length*sizeof(*utf8));
1343 utf8[*length]='\0';
1344 return(utf8);
1345 }
1346 j=0;
1347 extent=(*length);
1348 for (i=2; i < (ssize_t) (*length-1); i+=2)
1349 {
1350 c=(encoding != 0) ? ((content[i] & 0xff) << 8) | (content[i+1] & 0xff) :
1351 ((content[i+1] & 0xff) << 8) | (content[i] & 0xff);
1352 if ((c >= 0xd800) && (c <= 0xdfff) && ((i+=2) < (ssize_t) (*length-1)))
1353 {
1354 byte=(encoding != 0) ? ((content[i] & 0xff) << 8) |
1355 (content[i+1] & 0xff) : ((content[i+1] & 0xff) << 8) |
1356 (content[i] & 0xff);
1357 c=(((c & 0x3ff) << 10) | (byte & 0x3ff))+0x10000;
1358 }
1359 if ((size_t) (j+WizardPathExtent) > extent)
1360 {
1361 extent=(size_t) j+WizardPathExtent;
1362 utf8=(char *) ResizeQuantumMemory(utf8,extent,sizeof(*utf8));
1363 if (utf8 == (char *) NULL)
1364 return(utf8);
1365 }
1366 if (c < 0x80)
1367 {
1368 utf8[j]=c;
1369 j++;
1370 continue;
1371 }
1372 /*
1373 Multi-byte UTF-8 sequence.
1374 */
1375 byte=c;
1376 for (bits=0; byte != 0; byte/=2)
1377 bits++;
1378 bits=(bits-2)/5;
1379 utf8[j++]=(0xFF << (7-bits)) | (c >> (6*bits));
1380 while (bits != 0)
1381 {
1382 bits--;
1383 utf8[j]=0x80 | ((c >> (6*bits)) & 0x3f);
1384 j++;
1385 }
1386 }
1387 *length=(size_t) j;
1388 utf8=(char *) ResizeQuantumMemory(utf8,*length,sizeof(*utf8));
1389 if (utf8 != (char *) NULL)
1390 utf8[*length]='\0';
1391 return(utf8);
1392}
1393
1394static char *ParseEntities(char *xml,char **entities,int state)
1395{
1396 char
1397 *entity;
1398
1399 int
1400 byte,
1401 c;
1402
1403 char
1404 *p,
1405 *q;
1406
1407 ssize_t
1408 i;
1409
1410 size_t
1411 extent,
1412 length;
1413
1414 ssize_t
1415 offset;
1416
1417 /*
1418 Normalize line endings.
1419 */
1420 p=xml;
1421 q=xml;
1422 for ( ; *xml != '\0'; xml++)
1423 while (*xml == '\r')
1424 {
1425 *(xml++)='\n';
1426 if (*xml == '\n')
1427 (void) memmove(xml,xml+1,strlen(xml));
1428 }
1429 for (xml=p; ; )
1430 {
1431 while ((*xml != '\0') && (*xml != '&') && ((*xml != '%') ||
1432 (state != '%')) && (isspace((int) ((unsigned char) *xml)) == 0))
1433 xml++;
1434 if (*xml == '\0')
1435 break;
1436 /*
1437 States include:
1438 '&' for general entity decoding
1439 '%' for parameter entity decoding
1440 'c' for CDATA sections
1441 ' ' for attributes normalization
1442 '*' for non-CDATA attributes normalization
1443 */
1444 if ((state != 'c') && (strncmp(xml,"&#",2) == 0))
1445 {
1446 /*
1447 Character reference.
1448 */
1449 if (xml[2] != 'x')
1450 c=strtol(xml+2,&entity,10); /* base 10 */
1451 else
1452 c=strtol(xml+3,&entity,16); /* base 16 */
1453 if ((c == 0) || (*entity != ';'))
1454 {
1455 /*
1456 Not a character reference.
1457 */
1458 xml++;
1459 continue;
1460 }
1461 if (c < 0x80)
1462 *(xml++)=c;
1463 else
1464 {
1465 /*
1466 Multi-byte UTF-8 sequence.
1467 */
1468 byte=c;
1469 for (i=0; byte != 0; byte/=2)
1470 i++;
1471 i=(i-2)/5;
1472 *xml=(char) ((0xFF << (7-i)) | (c >> (6*i)));
1473 xml++;
1474 while (i != 0)
1475 {
1476 i--;
1477 *xml=(char) (0x80 | ((c >> (6*i)) & 0x3F));
1478 xml++;
1479 }
1480 }
1481 (void) memmove(xml,strchr(xml,';')+1,strlen(strchr(xml,';')));
1482 }
1483 else
1484 if (((*xml == '&') && ((state == '&') || (state == ' ') ||
1485 (state == '*'))) || ((state == '%') && (*xml == '%')))
1486 {
1487 /*
1488 Find entity in the list.
1489 */
1490 i=0;
1491 while ((entities[i] != (char *) NULL) &&
1492 (strncmp(xml+1,entities[i],strlen(entities[i])) != 0))
1493 i+=2;
1494 if (entities[i++] == (char *) NULL)
1495 xml++;
1496 else
1497 if (entities[i] != (char *) NULL)
1498 {
1499 /*
1500 Found a match.
1501 */
1502 length=strlen(entities[i]);
1503 entity=strchr(xml,';');
1504 if ((entity != (char *) NULL) &&
1505 ((length-1L) >= (size_t) (entity-xml)))
1506 {
1507 offset=(ssize_t) (xml-p);
1508 extent=(size_t) (offset+length+strlen(entity));
1509 if (p != q)
1510 {
1511 p=(char *) ResizeQuantumMemory(p,extent+1,sizeof(*p));
1512 p[extent]='\0';
1513 }
1514 else
1515 {
1516 char
1517 *extent_xml;
1518
1519 extent_xml=(char *) AcquireQuantumMemory(extent+1,
1520 sizeof(*extent_xml));
1521 if (extent_xml != (char *) NULL)
1522 {
1523 memset(extent_xml,0,extent*
1524 sizeof(*extent_xml));
1525 (void) CopyWizardString(extent_xml,p,extent*
1526 sizeof(*extent_xml));
1527 }
1528 p=extent_xml;
1529 }
1530 if (p == (char *) NULL)
1532 "unable to acquire string `%s'");
1533 xml=p+offset;
1534 entity=strchr(xml,';');
1535 }
1536 if (entity != (char *) NULL)
1537 (void) memmove(xml+length,entity+1,strlen(entity));
1538 (void) strncpy(xml,entities[i],length);
1539 }
1540 }
1541 else
1542 if (((state == ' ') || (state == '*')) &&
1543 (isspace((int) ((unsigned char) *xml)) != 0))
1544 *(xml++)=' ';
1545 else
1546 xml++;
1547 }
1548 if (state == '*')
1549 {
1550 /*
1551 Normalize spaces for non-CDATA attributes.
1552 */
1553 for (xml=p; *xml != '\0'; xml++)
1554 {
1555 char
1556 accept[] = " ";
1557
1558 i=(ssize_t) strspn(xml,accept);
1559 if (i != 0)
1560 (void) memmove(xml,xml+i,strlen(xml+i)+1);
1561 while ((*xml != '\0') && (*xml != ' '))
1562 xml++;
1563 if (*xml == '\0')
1564 break;
1565 }
1566 xml--;
1567 if ((xml >= p) && (*xml == ' '))
1568 *xml='\0';
1569 }
1570 return(p == q ? ConstantString(p) : p);
1571}
1572
1573void ParseCharacterContent(XMLTreeRoot *root,char *xml,const size_t length,
1574 const char state)
1575{
1577 *xml_info;
1578
1579 xml_info=root->node;
1580 if ((xml_info == (XMLTreeInfo *) NULL) || (xml_info->tag == (char *) NULL) ||
1581 (length == 0))
1582 return;
1583 xml[length]='\0';
1584 xml=ParseEntities(xml,root->entities,state);
1585 if ((xml_info->content != (char *) NULL) && (*xml_info->content != '\0'))
1586 {
1587 (void) ConcatenateString(&xml_info->content,xml);
1588 xml=DestroyString(xml);
1589 }
1590 else
1591 {
1592 if (xml_info->content != (char *) NULL)
1593 xml_info->content=DestroyString(xml_info->content);
1594 xml_info->content=xml;
1595 }
1596}
1597
1598static XMLTreeInfo *ParseCloseTag(XMLTreeRoot *root,char *tag,
1599 ExceptionInfo *exception)
1600{
1601 if ((root->node == (XMLTreeInfo *) NULL) ||
1602 (root->node->tag == (char *) NULL) || (strcmp(tag,root->node->tag) != 0))
1603 {
1605 "unexpected closing tag </%s>",tag);
1606 return(&root->root);
1607 }
1608 root->node=root->node->parent;
1609 return((XMLTreeInfo *) NULL);
1610}
1611
1612static WizardBooleanType ValidateEntities(char *tag,char *xml,
1613 const size_t depth,char **entities)
1614{
1615 ssize_t
1616 i;
1617
1618 /*
1619 Check for circular entity references.
1620 */
1621 if (depth > WizardMaxRecursionDepth)
1622 return(WizardFalse);
1623 for ( ; ; xml++)
1624 {
1625 while ((*xml != '\0') && (*xml != '&'))
1626 xml++;
1627 if (*xml == '\0')
1628 return(WizardTrue);
1629 if (strncmp(xml+1,tag,strlen(tag)) == 0)
1630 return(WizardFalse);
1631 i=0;
1632 while ((entities[i] != (char *) NULL) &&
1633 (strncmp(entities[i],xml+1,strlen(entities[i])) == 0))
1634 i+=2;
1635 if ((entities[i] != (char *) NULL) &&
1636 (ValidateEntities(tag,entities[i+1],depth+1,entities) == 0))
1637 return(WizardFalse);
1638 }
1639 return(WizardTrue);
1640}
1641
1642static void ParseProcessingInstructions(XMLTreeRoot *root,char *xml,
1643 size_t length)
1644{
1645 char
1646 *target;
1647
1648 ssize_t
1649 i;
1650
1651 ssize_t
1652 j;
1653
1654 target=xml;
1655 xml[length]='\0';
1656 xml+=strcspn(xml,XMLWhitespace);
1657 if (*xml != '\0')
1658 {
1659 *xml='\0';
1660 xml+=strspn(xml+1,XMLWhitespace)+1;
1661 }
1662 if (strcmp(target,"xml") == 0)
1663 {
1664 xml=strstr(xml,"standalone");
1665 if ((xml != (char *) NULL) &&
1666 (strncmp(xml+strspn(xml+10,XMLWhitespace "='\"")+10,"yes",3) == 0))
1667 root->standalone=WizardTrue;
1668 return;
1669 }
1670 if (root->processing_instructions[0] == (char **) NULL)
1671 {
1672 root->processing_instructions=(char ***) AcquireWizardMemory(sizeof(
1673 *root->processing_instructions));
1674 if (root->processing_instructions ==(char ***) NULL)
1675 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
1676 *root->processing_instructions=(char **) NULL;
1677 }
1678 i=0;
1679 while ((root->processing_instructions[i] != (char **) NULL) &&
1680 (strcmp(target,root->processing_instructions[i][0]) != 0))
1681 i++;
1682 if (root->processing_instructions[i] == (char **) NULL)
1683 {
1685 root->processing_instructions,(size_t) (i+2),
1686 sizeof(*root->processing_instructions));
1687 if (root->processing_instructions == (char ***) NULL)
1688 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
1689 root->processing_instructions[i]=(char **) AcquireQuantumMemory(3,
1690 sizeof(**root->processing_instructions));
1691 if (root->processing_instructions[i] == (char **) NULL)
1692 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
1693 root->processing_instructions[i+1]=(char **) NULL;
1694 root->processing_instructions[i][0]=ConstantString(target);
1695 root->processing_instructions[i][1]=(char *)
1696 root->processing_instructions[i+1];
1697 root->processing_instructions[i+1]=(char **) NULL;
1699 }
1700 j=1;
1701 while (root->processing_instructions[i][j] != (char *) NULL)
1702 j++;
1704 root->processing_instructions[i],(size_t) (j+3),
1705 sizeof(**root->processing_instructions));
1706 if (root->processing_instructions[i] == (char **) NULL)
1707 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
1708 root->processing_instructions[i][j+2]=(char *) ResizeQuantumMemory(
1709 root->processing_instructions[i][j+1],(size_t) (j+1),
1710 sizeof(***root->processing_instructions));
1711 if (root->processing_instructions[i][j+2] == (char *) NULL)
1712 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
1713 (void) CopyWizardString(root->processing_instructions[i][j+2]+j-1,
1714 root->root.tag != (char *) NULL ? ">" : "<",2);
1715 root->processing_instructions[i][j]=ConstantString(xml);
1716 root->processing_instructions[i][j+1]=(char *) NULL;
1717}
1718
1720 size_t length,ExceptionInfo *exception)
1721{
1722 char
1723 *c,
1724 **entities,
1725 *n,
1726 **predefined_entitites,
1727 q,
1728 *t,
1729 *v;
1730
1731 ssize_t
1732 i;
1733
1734 ssize_t
1735 j;
1736
1737 n=(char *) NULL;
1738 predefined_entitites=(char **) AcquireWizardMemory(sizeof(sentinel));
1739 if (predefined_entitites == (char **) NULL)
1740 {
1742 "memory allocation failed `%s'",strerror(errno));
1743 return(WizardFalse);
1744 }
1745 (void) memcpy(predefined_entitites,sentinel,sizeof(sentinel));
1746 for (xml[length]='\0'; xml != (char *) NULL; )
1747 {
1748 while ((*xml != '\0') && (*xml != '<') && (*xml != '%'))
1749 xml++;
1750 if (*xml == '\0')
1751 break;
1752 if ((strlen(xml) > 9) && (strncmp(xml,"<!ENTITY",8) == 0))
1753 {
1754 /*
1755 Parse entity definitions.
1756 */
1757 if (strspn(xml+8,XMLWhitespace) == 0)
1758 break;
1759 xml+=strspn(xml+8,XMLWhitespace)+8;
1760 c=xml;
1761 n=xml+strspn(xml,XMLWhitespace "%");
1762 if ((isalpha((int) ((unsigned char) *n)) == 0) && (*n != '_'))
1763 break;
1764 xml=n+strcspn(n,XMLWhitespace);
1765 if (*xml == '\0')
1766 break;
1767 *xml=';';
1768 v=xml+strspn(xml+1,XMLWhitespace)+1;
1769 q=(*v);
1770 v++;
1771 if ((q != '"') && (q != '\''))
1772 {
1773 /*
1774 Skip externals.
1775 */
1776 xml=strchr(xml,'>');
1777 continue;
1778 }
1779 entities=(*c == '%') ? predefined_entitites : root->entities;
1780 for (i=0; entities[i] != (char *) NULL; i++) ;
1781 entities=(char **) ResizeQuantumMemory(entities,(size_t) (i+3),
1782 sizeof(*entities));
1783 if (entities == (char **) NULL)
1785 "unable to acquire string `%s'");
1786 if (*c == '%')
1787 predefined_entitites=entities;
1788 else
1789 root->entities=entities;
1790 xml++;
1791 *xml='\0';
1792 xml=strchr(v,q);
1793 if (xml != (char *) NULL)
1794 {
1795 *xml='\0';
1796 xml++;
1797 }
1798 entities[i+1]=ParseEntities(v,predefined_entitites,'%');
1799 entities[i+2]=(char *) NULL;
1800 if (ValidateEntities(n,entities[i+1],0,entities) != WizardFalse)
1801 entities[i]=n;
1802 else
1803 {
1804 if (entities[i+1] != v)
1805 entities[i+1]=DestroyString(entities[i+1]);
1806 (void) ThrowWizardException(exception,GetWizardModule(),
1807 OptionWarning,"circular entity declaration &%s",n);
1808 predefined_entitites=(char **) RelinquishWizardMemory(
1809 predefined_entitites);
1810 return(WizardFalse);
1811 }
1812 }
1813 else
1814 if (strncmp(xml,"<!ATTLIST",9) == 0)
1815 {
1816 /*
1817 Parse default attributes.
1818 */
1819 t=xml+strspn(xml+9,XMLWhitespace)+9;
1820 if (*t == '\0')
1821 {
1822 (void) ThrowWizardException(exception,GetWizardModule(),
1823 OptionWarning,"unclosed <!ATTLIST");
1824 predefined_entitites=(char **) RelinquishWizardMemory(
1825 predefined_entitites);
1826 return(WizardFalse);
1827 }
1828 xml=t+strcspn(t,XMLWhitespace ">");
1829 if (*xml == '>')
1830 continue;
1831 *xml='\0';
1832 i=0;
1833 while ((root->attributes[i] != (char **) NULL) &&
1834 (n != (char *) NULL) &&
1835 (strcmp(n,root->attributes[i][0]) != 0))
1836 i++;
1837 while ((*(n=xml+strspn(xml+1,XMLWhitespace)+1) != '\0') &&
1838 (*n != '>'))
1839 {
1840 xml=n+strcspn(n,XMLWhitespace);
1841 if (*xml != '\0')
1842 *xml='\0';
1843 else
1844 {
1845 (void) ThrowWizardException(exception,GetWizardModule(),
1846 OptionWarning,"malformed <!ATTLIST");
1847 predefined_entitites=(char **) RelinquishWizardMemory(
1848 predefined_entitites);
1849 return(WizardFalse);
1850 }
1851 xml+=strspn(xml+1,XMLWhitespace)+1;
1852 c=(char *) (strncmp(xml,"CDATA",5) != 0 ? "*" : " ");
1853 if (strncmp(xml,"NOTATION",8) == 0)
1854 xml+=strspn(xml+8,XMLWhitespace)+8;
1855 xml=(*xml == '(') ? strchr(xml,')') : xml+
1856 strcspn(xml,XMLWhitespace);
1857 if (xml == (char *) NULL)
1858 {
1859 (void) ThrowWizardException(exception,GetWizardModule(),
1860 OptionWarning,"malformed <!ATTLIST");
1861 predefined_entitites=(char **) RelinquishWizardMemory(
1862 predefined_entitites);
1863 return(WizardFalse);
1864 }
1865 xml+=strspn(xml,XMLWhitespace ")");
1866 if (strncmp(xml,"#FIXED",6) == 0)
1867 xml+=strspn(xml+6,XMLWhitespace)+6;
1868 if (*xml == '#')
1869 {
1870 xml+=strcspn(xml,XMLWhitespace ">")-1;
1871 if (*c == ' ')
1872 continue;
1873 v=(char *) NULL;
1874 }
1875 else
1876 if (((*xml == '"') || (*xml == '\'')) &&
1877 ((xml=strchr(v=xml+1,*xml)) != (char *) NULL))
1878 *xml='\0';
1879 else
1880 {
1881 (void) ThrowWizardException(exception,GetWizardModule(),
1882 OptionWarning,"malformed <!ATTLIST");
1883 predefined_entitites=(char **) RelinquishWizardMemory(
1884 predefined_entitites);
1885 return(WizardFalse);
1886 }
1887 if (root->attributes[i] == (char **) NULL)
1888 {
1889 /*
1890 New attribute tag.
1891 */
1892 if (i == 0)
1893 root->attributes=(char ***) AcquireQuantumMemory(2,
1894 sizeof(*root->attributes));
1895 else
1896 root->attributes=(char ***) ResizeQuantumMemory(
1897 root->attributes,(size_t) (i+2),
1898 sizeof(*root->attributes));
1899 if (root->attributes == (char ***) NULL)
1901 "unable to acquire string `%s'");
1902 root->attributes[i]=(char **) AcquireQuantumMemory(2,
1903 sizeof(**root->attributes));
1904 if (root->attributes[i] == (char **) NULL)
1906 "unable to acquire string `%s'");
1907 root->attributes[i][0]=ConstantString(t);
1908 root->attributes[i][1]=(char *) NULL;
1909 root->attributes[i+1]=(char **) NULL;
1910 }
1911 for (j=1; root->attributes[i][j] != (char *) NULL; j+=3) ;
1912 root->attributes[i]=(char **) ResizeQuantumMemory(
1913 root->attributes[i],(size_t) (j+4),sizeof(**root->attributes));
1914 if (root->attributes[i] == (char **) NULL)
1916 "unable to acquire string `%s'");
1917 root->attributes[i][j+3]=(char *) NULL;
1918 root->attributes[i][j+2]=ConstantString(c);
1919 root->attributes[i][j+1]=(char *) NULL;
1920 if (v != (char *) NULL)
1921 root->attributes[i][j+1]=ParseEntities(v,root->entities,*c);
1922 root->attributes[i][j]=ConstantString(n);
1923 }
1924 }
1925 else
1926 if (strncmp(xml, "<!--", 4) == 0)
1927 xml=strstr(xml+4,"-->");
1928 else
1929 if (strncmp(xml,"<?", 2) == 0)
1930 {
1931 c=xml+2;
1932 xml=strstr(c,"?>");
1933 if (xml != (char *) NULL)
1934 {
1935 ParseProcessingInstructions(root,c,(size_t) (xml-c));
1936 xml++;
1937 }
1938 }
1939 else
1940 if (*xml == '<')
1941 xml=strchr(xml,'>');
1942 else
1943 if ((*(xml++) == '%') && (root->standalone == WizardFalse))
1944 break;
1945 }
1946 predefined_entitites=(char **) RelinquishWizardMemory(predefined_entitites);
1947 return(WizardTrue);
1948}
1949
1950static void ParseOpenTag(XMLTreeRoot *root,char *tag,char **attributes)
1951{
1953 *xml_info;
1954
1955 xml_info=root->node;
1956 if (xml_info->tag == (char *) NULL)
1957 xml_info->tag=ConstantString(tag);
1958 else
1959 xml_info=AddChildToXMLTree(xml_info,tag,strlen(xml_info->content));
1960 if (xml_info != (XMLTreeInfo *) NULL)
1961 xml_info->attributes=attributes;
1962 root->node=xml_info;
1963}
1964
1965static const char
1967 {
1968 "rdf:Bag",
1969 "rdf:Seq",
1970 (const char *) NULL
1971 };
1972
1973static inline WizardBooleanType IsSkipTag(const char *tag)
1974{
1975 ssize_t
1976 i;
1977
1978 i=0;
1979 while (ignore_tags[i] != (const char *) NULL)
1980 {
1981 if (LocaleCompare(tag,ignore_tags[i]) == 0)
1982 return(WizardTrue);
1983 i++;
1984 }
1985 return(WizardFalse);
1986}
1987
1989{
1990 char
1991 **attribute,
1992 **attributes,
1993 *tag,
1994 *utf8;
1995
1996 int
1997 c,
1998 terminal;
1999
2000 char
2001 *p;
2002
2003 ssize_t
2004 i;
2005
2006 size_t
2007 ignore_depth,
2008 length;
2009
2010 ssize_t
2011 j,
2012 l;
2013
2015 status;
2016
2018 *root;
2019
2020 /*
2021 Convert xml-string to UTF8.
2022 */
2023 if ((xml == (const char *) NULL) || (strlen(xml) == 0))
2024 {
2026 "root tag missing");
2027 return((XMLTreeInfo *) NULL);
2028 }
2029 root=(XMLTreeRoot *) NewXMLTreeTag((char *) NULL);
2030 length=strlen(xml);
2031 utf8=ConvertUTF16ToUTF8(xml,&length);
2032 if (utf8 == (char *) NULL)
2033 {
2035 "memory allocation failed `%s'",strerror(errno));
2036 return((XMLTreeInfo *) NULL);
2037 }
2038 terminal=utf8[length-1];
2039 utf8[length-1]='\0';
2040 p=utf8;
2041 while ((*p != '\0') && (*p != '<'))
2042 p++;
2043 if (*p == '\0')
2044 {
2046 "root tag missing");
2047 utf8=DestroyString(utf8);
2048 return((XMLTreeInfo *) NULL);
2049 }
2050 attribute=(char **) NULL;
2051 l=0;
2052 ignore_depth=0;
2053 for (p++; ; p++)
2054 {
2055 attributes=(char **) sentinel;
2056 tag=p;
2057 c=(*p);
2058 if ((isalpha((int) ((unsigned char) *p)) != 0) || (*p == '_') ||
2059 (*p == ':') || (c < '\0'))
2060 {
2061 /*
2062 Tag.
2063 */
2064 if (root->node == (XMLTreeInfo *) NULL)
2065 {
2066 (void) ThrowWizardException(exception,GetWizardModule(),
2067 OptionWarning,"root tag missing");
2068 utf8=DestroyString(utf8);
2069 return(&root->root);
2070 }
2071 p+=strcspn(p,XMLWhitespace "/>");
2072 while (isspace((int) ((unsigned char) *p)) != 0)
2073 *p++='\0';
2074 if (((isalpha((int) ((unsigned char) *p)) != 0) || (*p == '_')) &&
2075 (ignore_depth == 0))
2076 {
2077 if ((*p != '\0') && (*p != '/') && (*p != '>'))
2078 {
2079 /*
2080 Find tag in default attributes list.
2081 */
2082 i=0;
2083 while ((root->attributes[i] != (char **) NULL) &&
2084 (strcmp(root->attributes[i][0],tag) != 0))
2085 i++;
2086 attribute=root->attributes[i];
2087 }
2088 for (l=0; (*p != '\0') && (*p != '/') && (*p != '>'); l+=2)
2089 {
2090 /*
2091 Attribute.
2092 */
2093 if (l == 0)
2094 attributes=(char **) AcquireQuantumMemory(4,
2095 sizeof(*attributes));
2096 else
2097 attributes=(char **) ResizeQuantumMemory(attributes,(size_t)
2098 (l+4),sizeof(*attributes));
2099 if (attributes == (char **) NULL)
2100 {
2101 (void) ThrowWizardException(exception,GetWizardModule(),
2102 ResourceError,"memory allocation failed `%s'",
2103 strerror(errno));
2104 utf8=DestroyString(utf8);
2105 return(&root->root);
2106 }
2107 attributes[l+2]=(char *) NULL;
2108 attributes[l+1]=(char *) NULL;
2109 attributes[l]=p;
2110 p+=strcspn(p,XMLWhitespace "=/>");
2111 if ((*p != '=') && (isspace((int) ((unsigned char) *p)) == 0))
2112 attributes[l]=ConstantString("");
2113 else
2114 {
2115 *p++='\0';
2116 p+=strspn(p,XMLWhitespace "=");
2117 c=(*p);
2118 if ((c == '"') || (c == '\''))
2119 {
2120 /*
2121 Attributes value.
2122 */
2123 p++;
2124 attributes[l+1]=p;
2125 while ((*p != '\0') && (*p != c))
2126 p++;
2127 if (*p != '\0')
2128 *p++='\0';
2129 else
2130 {
2131 attributes[l]=ConstantString("");
2132 attributes[l+1]=ConstantString("");
2133 (void) DestroyXMLTreeAttributes(attributes);
2134 (void) ThrowWizardException(exception,
2135 GetWizardModule(),OptionWarning,"missing %c",c);
2136 utf8=DestroyString(utf8);
2137 return(&root->root);
2138 }
2139 j=1;
2140 while ((attribute != (char **) NULL) &&
2141 (attribute[j] != (char *) NULL) &&
2142 (strcmp(attribute[j],attributes[l]) != 0))
2143 j+=3;
2144 attributes[l+1]=ParseEntities(attributes[l+1],
2145 root->entities,(attribute != (char **) NULL) &&
2146 (attribute[j] != (char *) NULL) ? *attribute[j+2] :
2147 ' ');
2148 }
2149 attributes[l]=ConstantString(attributes[l]);
2150 }
2151 while (isspace((int) ((unsigned char) *p)) != 0)
2152 p++;
2153 }
2154 }
2155 else
2156 {
2157 while((*p != '\0') && (*p != '/') && (*p != '>'))
2158 p++;
2159 }
2160 if (*p == '/')
2161 {
2162 /*
2163 Self closing tag.
2164 */
2165 *p++='\0';
2166 if (((*p != '\0') && (*p != '>')) ||
2167 ((*p == '\0') && (terminal != '>')))
2168 {
2169 if (l != 0)
2170 (void) DestroyXMLTreeAttributes(attributes);
2171 (void) ThrowWizardException(exception,GetWizardModule(),
2172 OptionWarning,"missing >");
2173 utf8=DestroyString(utf8);
2174 return(&root->root);
2175 }
2176 if ((ignore_depth != 0) || (IsSkipTag(tag) != WizardFalse))
2177 (void) DestroyXMLTreeAttributes(attributes);
2178 else
2179 {
2180 ParseOpenTag(root,tag,attributes);
2181 (void) ParseCloseTag(root,tag,exception);
2182 }
2183 }
2184 else
2185 {
2186 c=(*p);
2187 if ((*p == '>') || ((*p == '\0') && (terminal == '>')))
2188 {
2189 *p='\0';
2190 if ((ignore_depth == 0) && (IsSkipTag(tag) == WizardFalse))
2191 ParseOpenTag(root,tag,attributes);
2192 else
2193 {
2194 ignore_depth++;
2195 (void) DestroyXMLTreeAttributes(attributes);
2196 }
2197 *p=c;
2198 }
2199 else
2200 {
2201 if (l != 0)
2202 (void) DestroyXMLTreeAttributes(attributes);
2203 (void) ThrowWizardException(exception,GetWizardModule(),
2204 OptionWarning,"missing >");
2205 utf8=DestroyString(utf8);
2206 return(&root->root);
2207 }
2208 }
2209 }
2210 else
2211 if (*p == '/')
2212 {
2213 /*
2214 Close tag.
2215 */
2216 tag=p+1;
2217 p+=strcspn(tag,XMLWhitespace ">")+1;
2218 c=(*p);
2219 if ((c == '\0') && (terminal != '>'))
2220 {
2221 (void) ThrowWizardException(exception,GetWizardModule(),
2222 OptionWarning,"missing >");
2223 utf8=DestroyString(utf8);
2224 return(&root->root);
2225 }
2226 *p='\0';
2227 if ((ignore_depth == 0) &&
2228 (ParseCloseTag(root,tag,exception) != (XMLTreeInfo *) NULL))
2229 {
2230 utf8=DestroyString(utf8);
2231 return(&root->root);
2232 }
2233 if (ignore_depth > 0)
2234 ignore_depth--;
2235 *p=c;
2236 if (isspace((int) ((unsigned char) *p)) != 0)
2237 p+=strspn(p,XMLWhitespace);
2238 }
2239 else
2240 if (strncmp(p,"!--",3) == 0)
2241 {
2242 /*
2243 Comment.
2244 */
2245 p=strstr(p+3,"--");
2246 if ((p == (char *) NULL) || ((*(p+=2) != '>') && (*p != '\0')) ||
2247 ((*p == '\0') && (terminal != '>')))
2248 {
2249 (void) ThrowWizardException(exception,GetWizardModule(),
2250 OptionWarning,"unclosed <!--");
2251 utf8=DestroyString(utf8);
2252 return(&root->root);
2253 }
2254 }
2255 else
2256 if (strncmp(p,"![CDATA[",8) == 0)
2257 {
2258 /*
2259 Cdata.
2260 */
2261 p=strstr(p,"]]>");
2262 if (p != (char *) NULL)
2263 {
2264 p+=2;
2265 if (ignore_depth == 0)
2266 ParseCharacterContent(root,tag+8,(size_t) (p-tag-10),'c');
2267 }
2268 else
2269 {
2270 (void) ThrowWizardException(exception,GetWizardModule(),
2271 OptionWarning,"unclosed <![CDATA[");
2272 utf8=DestroyString(utf8);
2273 return(&root->root);
2274 }
2275 }
2276 else
2277 if (strncmp(p,"!DOCTYPE",8) == 0)
2278 {
2279 /*
2280 DTD.
2281 */
2282 for (l=0; (*p != '\0') && (((l == 0) && (*p != '>')) ||
2283 ((l != 0) && ((*p != ']') ||
2284 (*(p+strspn(p+1,XMLWhitespace)+1) != '>'))));
2285 l=(ssize_t) ((*p == '[') ? 1 : l))
2286 p+=strcspn(p+1,"[]>")+1;
2287 if ((*p == '\0') && (terminal != '>'))
2288 {
2289 (void) ThrowWizardException(exception,GetWizardModule(),
2290 OptionWarning,"unclosed <!DOCTYPE");
2291 utf8=DestroyString(utf8);
2292 return(&root->root);
2293 }
2294 if (l != 0)
2295 tag=strchr(tag,'[')+1;
2296 if (l != 0)
2297 {
2298 status=ParseInternalDoctype(root,tag,(size_t) (p-tag),
2299 exception);
2300 if (status == WizardFalse)
2301 {
2302 utf8=DestroyString(utf8);
2303 return(&root->root);
2304 }
2305 p++;
2306 }
2307 }
2308 else
2309 if (*p == '?')
2310 {
2311 /*
2312 Processing instructions.
2313 */
2314 do
2315 {
2316 p=strchr(p,'?');
2317 if (p == (char *) NULL)
2318 break;
2319 p++;
2320 } while ((*p != '\0') && (*p != '>'));
2321 if ((p == (char *) NULL) || ((*p == '\0') &&
2322 (terminal != '>')))
2323 {
2324 (void) ThrowWizardException(exception,GetWizardModule(),
2325 OptionWarning,"unclosed <?");
2326 utf8=DestroyString(utf8);
2327 return(&root->root);
2328 }
2329 ParseProcessingInstructions(root,tag+1,(size_t) (p-tag-2));
2330 }
2331 else
2332 {
2333 (void) ThrowWizardException(exception,GetWizardModule(),
2334 OptionWarning,"unexpected <");
2335 utf8=DestroyString(utf8);
2336 return(&root->root);
2337 }
2338 if ((p == (char *) NULL) || (*p == '\0'))
2339 break;
2340 *p++='\0';
2341 tag=p;
2342 if ((*p != '\0') && (*p != '<'))
2343 {
2344 /*
2345 Tag character content.
2346 */
2347 while ((*p != '\0') && (*p != '<'))
2348 p++;
2349 if (*p == '\0')
2350 break;
2351 if (ignore_depth == 0)
2352 ParseCharacterContent(root,tag,(size_t) (p-tag),'&');
2353 }
2354 else
2355 if (*p == '\0')
2356 break;
2357 }
2358 utf8=DestroyString(utf8);
2359 if (root->node == (XMLTreeInfo *) NULL)
2360 return(&root->root);
2361 if (root->node->tag == (char *) NULL)
2362 {
2364 "root tag missing");
2365 return(&root->root);
2366 }
2368 "unclosed tag: `%s'",root->node->tag);
2369 return(&root->root);
2370}
2371
2372/*
2373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2374% %
2375% %
2376% %
2377% N e w X M L T r e e T a g %
2378% %
2379% %
2380% %
2381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2382%
2383% NewXMLTreeTag() returns a new empty xml structure for the xml-tree tag.
2384%
2385% The format of the NewXMLTreeTag method is:
2386%
2387% XMLTreeInfo *NewXMLTreeTag(const char *tag)
2388%
2389% A description of each parameter follows:
2390%
2391% o tag: the tag.
2392%
2393*/
2395{
2396 static const char
2397 *predefined_entities[NumberPredefinedEntities+1] =
2398 {
2399 "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
2400 "apos;", "&#39;", "amp;", "&#38;", (char *) NULL
2401 };
2402
2404 *root;
2405
2406 root=(XMLTreeRoot *) AcquireWizardMemory(sizeof(*root));
2407 if (root == (XMLTreeRoot *) NULL)
2408 return((XMLTreeInfo *) NULL);
2409 (void) memset(root,0,sizeof(*root));
2410 root->root.tag=(char *) NULL;
2411 if (tag != (char *) NULL)
2412 root->root.tag=ConstantString(tag);
2413 root->node=(&root->root);
2414 root->root.content=ConstantString("");
2415 root->entities=(char **) AcquireWizardMemory(sizeof(predefined_entities));
2416 if (root->entities == (char **) NULL)
2417 return((XMLTreeInfo *) NULL);
2418 (void) memcpy(root->entities,predefined_entities,sizeof(predefined_entities));
2419 root->root.attributes=sentinel;
2420 root->attributes=(char ***) root->root.attributes;
2421 root->processing_instructions=(char ***) root->root.attributes;
2422 root->debug=IsEventLogging();
2424 return(&root->root);
2425}
2426
2427/*
2428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2429% %
2430% %
2431% %
2432% P r u n e T a g F r o m X M L T r e e %
2433% %
2434% %
2435% %
2436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2437%
2438% PruneTagFromXMLTree() prunes a tag from the xml-tree along with all its
2439% subtags.
2440%
2441% The format of the PruneTagFromXMLTree method is:
2442%
2443% XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info)
2444%
2445% A description of each parameter follows:
2446%
2447% o xml_info: the xml info.
2448%
2449*/
2451{
2453 *node;
2454
2455 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
2457 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
2459 if (xml_info->next != (XMLTreeInfo *) NULL)
2460 xml_info->next->sibling=xml_info->sibling;
2461 if (xml_info->parent != (XMLTreeInfo *) NULL)
2462 {
2463 node=xml_info->parent->child;
2464 if (node == xml_info)
2465 xml_info->parent->child=xml_info->ordered;
2466 else
2467 {
2468 while (node->ordered != xml_info)
2469 node=node->ordered;
2470 node->ordered=node->ordered->ordered;
2471 node=xml_info->parent->child;
2472 if (strcmp(node->tag,xml_info->tag) != 0)
2473 {
2474 while (strcmp(node->sibling->tag,xml_info->tag) != 0)
2475 node=node->sibling;
2476 if (node->sibling != xml_info)
2477 node=node->sibling;
2478 else
2479 node->sibling=(xml_info->next != (XMLTreeInfo *) NULL) ?
2480 xml_info->next : node->sibling->sibling;
2481 }
2482 while ((node->next != (XMLTreeInfo *) NULL) &&
2483 (node->next != xml_info))
2484 node=node->next;
2485 if (node->next != (XMLTreeInfo *) NULL)
2486 node->next=node->next->next;
2487 }
2488 }
2489 xml_info->ordered=(XMLTreeInfo *) NULL;
2490 xml_info->sibling=(XMLTreeInfo *) NULL;
2491 xml_info->next=(XMLTreeInfo *) NULL;
2492 return(xml_info);
2493}
2494
2495/*
2496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2497% %
2498% %
2499% %
2500% S e t X M L T r e e A t t r i b u t e %
2501% %
2502% %
2503% %
2504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2505%
2506% SetXMLTreeAttribute() sets the tag attributes or adds a new attribute if not
2507% found. A value of NULL removes the specified attribute.
2508%
2509% The format of the SetXMLTreeAttribute method is:
2510%
2511% XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,const char *tag,
2512% const char *value)
2513%
2514% A description of each parameter follows:
2515%
2516% o xml_info: the xml info.
2517%
2518% o tag: The attribute tag.
2519%
2520% o value: The attribute value.
2521%
2522*/
2524 const char *tag,const char *value)
2525{
2526 ssize_t
2527 i;
2528
2529 ssize_t
2530 j;
2531
2532 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
2534 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
2536 i=0;
2537 while ((xml_info->attributes[i] != (char *) NULL) &&
2538 (strcmp(xml_info->attributes[i],tag) != 0))
2539 i+=2;
2540 if (xml_info->attributes[i] == (char *) NULL)
2541 {
2542 /*
2543 Add new attribute tag.
2544 */
2545 if (value == (const char *) NULL)
2546 return(xml_info);
2547 if (xml_info->attributes != sentinel)
2548 xml_info->attributes=(char **) ResizeQuantumMemory(
2549 xml_info->attributes,(size_t) (i+4),sizeof(*xml_info->attributes));
2550 else
2551 {
2552 xml_info->attributes=(char **) AcquireQuantumMemory(4,
2553 sizeof(*xml_info->attributes));
2554 if (xml_info->attributes != (char **) NULL)
2555 xml_info->attributes[1]=ConstantString("");
2556 }
2557 if (xml_info->attributes == (char **) NULL)
2558 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
2559 xml_info->attributes[i]=ConstantString(tag);
2560 xml_info->attributes[i+2]=(char *) NULL;
2561 (void) strlen(xml_info->attributes[i+1]);
2562 }
2563 /*
2564 Add new value to an existing attribute.
2565 */
2566 for (j=i; xml_info->attributes[j] != (char *) NULL; j+=2) ;
2567 if (xml_info->attributes[i+1] != (char *) NULL)
2568 xml_info->attributes[i+1]=DestroyString(xml_info->attributes[i+1]);
2569 if (value != (const char *) NULL)
2570 {
2571 xml_info->attributes[i+1]=ConstantString(value);
2572 return(xml_info);
2573 }
2574 if (xml_info->attributes[i] != (char *) NULL)
2575 xml_info->attributes[i]=DestroyString(xml_info->attributes[i]);
2576 (void) memmove(xml_info->attributes+i,xml_info->attributes+i+2,(size_t)
2577 (j-i)*sizeof(*xml_info->attributes));
2578 xml_info->attributes=(char **) ResizeQuantumMemory(xml_info->attributes,
2579 (size_t) (j+2),sizeof(*xml_info->attributes));
2580 if (xml_info->attributes == (char **) NULL)
2581 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'");
2582 j-=2;
2583 (void) memmove(xml_info->attributes[j+1]+(i/2),xml_info->attributes[j+1]+
2584 (i/2)+1,(size_t) (((j+2)/2)-(i/2))*sizeof(**xml_info->attributes));
2585 return(xml_info);
2586}
2587
2588/*
2589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2590% %
2591% %
2592% %
2593% S e t X M L T r e e C o n t e n t %
2594% %
2595% %
2596% %
2597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2598%
2599% SetXMLTreeContent() sets the character content for the given tag and
2600% returns the tag.
2601%
2602% The format of the SetXMLTreeContent method is:
2603%
2604% XMLTreeInfo *SetXMLTreeContent(XMLTreeInfo *xml_info,
2605% const char *content)
2606%
2607% A description of each parameter follows:
2608%
2609% o xml_info: the xml info.
2610%
2611% o content: The content.
2612%
2613*/
2615 const char *content)
2616{
2617 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
2619 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
2621 if (xml_info->content != (char *) NULL)
2622 xml_info->content=DestroyString(xml_info->content);
2623 xml_info->content=(char *) ConstantString(content);
2624 return(xml_info);
2625}
2626
2627/*
2628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2629% %
2630% %
2631% %
2632% X M L T r e e I n f o T o X M L %
2633% %
2634% %
2635% %
2636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2637%
2638% XMLTreeInfoToXML() converts an xml-tree to an XML string.
2639%
2640% The format of the XMLTreeInfoToXML method is:
2641%
2642% char *XMLTreeInfoToXML(XMLTreeInfo *xml_info)
2643%
2644% A description of each parameter follows:
2645%
2646% o xml_info: the xml info.
2647%
2648*/
2649
2650static char *EncodePredefinedEntities(const char *source,ssize_t offset,
2651 char **destination,size_t *length,size_t *extent,WizardBooleanType pedantic)
2652{
2653 char
2654 *canonical_content;
2655
2656 if (offset < 0)
2657 canonical_content=CanonicalXMLContent(source,pedantic);
2658 else
2659 {
2660 char
2661 *content;
2662
2663 content=AcquireString(source);
2664 content[offset]='\0';
2665 canonical_content=CanonicalXMLContent(content,pedantic);
2666 content=DestroyString(content);
2667 }
2668 if (canonical_content == (char *) NULL)
2669 return(*destination);
2670 if ((*length+strlen(canonical_content)+WizardPathExtent) > *extent)
2671 {
2672 *extent=(*length)+strlen(canonical_content)+WizardPathExtent;
2673 *destination=(char *) ResizeQuantumMemory(*destination,*extent,
2674 sizeof(**destination));
2675 if (*destination == (char *) NULL)
2676 return(*destination);
2677 }
2678 *length+=FormatLocaleString(*destination+(*length),*extent,"%s",
2679 canonical_content);
2680 canonical_content=DestroyString(canonical_content);
2681 return(*destination);
2682}
2683
2684static char *XMLTreeTagToXML(XMLTreeInfo *xml_info,char **source,size_t *length,
2685 size_t *extent,size_t start,char ***attributes)
2686{
2687 char
2688 *content;
2689
2690 const char
2691 *attribute;
2692
2693 ssize_t
2694 i;
2695
2696 size_t
2697 offset;
2698
2699 ssize_t
2700 j;
2701
2702 content=(char *) "";
2703 if (xml_info->parent != (XMLTreeInfo *) NULL)
2704 content=xml_info->parent->content;
2705 offset=0;
2706 *source=EncodePredefinedEntities(content+start,(ssize_t) (xml_info->offset-
2707 start),source,length,extent,WizardFalse);
2708 if ((*length+strlen(xml_info->tag)+WizardPathExtent) > *extent)
2709 {
2710 *extent=(*length)+strlen(xml_info->tag)+WizardPathExtent;
2711 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source));
2712 if (*source == (char *) NULL)
2713 return(*source);
2714 }
2715 *length+=FormatLocaleString(*source+(*length),*extent,"<%s",xml_info->tag);
2716 for (i=0; xml_info->attributes[i]; i+=2)
2717 {
2718 attribute=GetXMLTreeAttribute(xml_info,xml_info->attributes[i]);
2719 if (attribute != xml_info->attributes[i+1])
2720 continue;
2721 if ((*length+strlen(xml_info->attributes[i])+WizardPathExtent) > *extent)
2722 {
2723 *extent=(*length)+strlen(xml_info->attributes[i])+WizardPathExtent;
2724 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source));
2725 if (*source == (char *) NULL)
2726 return((char *) NULL);
2727 }
2728 *length+=FormatLocaleString(*source+(*length),*extent," %s=\"",
2729 xml_info->attributes[i]);
2730 (void) EncodePredefinedEntities(xml_info->attributes[i+1],-1,source,length,
2731 extent,WizardTrue);
2732 *length+=FormatLocaleString(*source+(*length),*extent,"\"");
2733 }
2734 i=0;
2735 while ((attributes[i] != (char **) NULL) &&
2736 (strcmp(attributes[i][0],xml_info->tag) != 0))
2737 i++;
2738 j=1;
2739 while ((attributes[i] != (char **) NULL) &&
2740 (attributes[i][j] != (char *) NULL))
2741 {
2742 if ((attributes[i][j+1] == (char *) NULL) ||
2743 (GetXMLTreeAttribute(xml_info,attributes[i][j]) != attributes[i][j+1]))
2744 {
2745 j+=3;
2746 continue;
2747 }
2748 if ((*length+strlen(attributes[i][j])+WizardPathExtent) > *extent)
2749 {
2750 *extent=(*length)+strlen(attributes[i][j])+WizardPathExtent;
2751 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source));
2752 if (*source == (char *) NULL)
2753 return((char *) NULL);
2754 }
2755 *length+=FormatLocaleString(*source+(*length),*extent," %s=\"",
2756 attributes[i][j]);
2757 (void) EncodePredefinedEntities(attributes[i][j+1],-1,source,length,extent,
2758 WizardTrue);
2759 *length+=FormatLocaleString(*source+(*length),*extent,"\"");
2760 j+=3;
2761 }
2762 *length+=FormatLocaleString(*source+(*length),*extent,*xml_info->content ?
2763 ">" : "/>");
2764 if (xml_info->child != (XMLTreeInfo *) NULL)
2765 *source=XMLTreeTagToXML(xml_info->child,source,length,extent,0,attributes);
2766 else
2767 *source=EncodePredefinedEntities(xml_info->content,-1,source,length,extent,
2768 WizardFalse);
2769 if ((*length+strlen(xml_info->tag)+WizardPathExtent) > *extent)
2770 {
2771 *extent=(*length)+strlen(xml_info->tag)+WizardPathExtent;
2772 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source));
2773 if (*source == (char *) NULL)
2774 return((char *) NULL);
2775 }
2776 if (*xml_info->content != '\0')
2777 *length+=FormatLocaleString(*source+(*length),*extent,"</%s>",
2778 xml_info->tag);
2779 while ((offset < xml_info->offset) && (content[offset] != '\0'))
2780 offset++;
2781 if (xml_info->ordered != (XMLTreeInfo *) NULL)
2782 content=XMLTreeTagToXML(xml_info->ordered,source,length,extent,offset,
2783 attributes);
2784 else
2785 content=EncodePredefinedEntities(content+offset,-1,source,length,extent,
2786 WizardFalse);
2787 return(content);
2788}
2789
2791{
2792 char
2793 *xml;
2794
2795 char
2796 *p,
2797 *q;
2798
2799 ssize_t
2800 i;
2801
2802 size_t
2803 extent,
2804 length;
2805
2806 ssize_t
2807 j,
2808 k;
2809
2811 *ordered,
2812 *parent;
2813
2815 *root;
2816
2817 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL);
2819 (((XMLTreeRoot *) xml_info)->signature == WizardSignature));
2821 if (xml_info->tag == (char *) NULL)
2822 return((char *) NULL);
2823 xml=AcquireString((char *) NULL);
2824 length=0;
2825 extent=WizardPathExtent;
2826 root=(XMLTreeRoot *) xml_info;
2827 while (root->root.parent != (XMLTreeInfo *) NULL)
2828 root=(XMLTreeRoot *) root->root.parent;
2829 parent=xml_info->parent;
2830 if (parent == (XMLTreeInfo *) NULL)
2831 for (i=0; root->processing_instructions[i] != (char **) NULL; i++)
2832 {
2833 /*
2834 Pre-root processing instructions.
2835 */
2836 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2837 p=root->processing_instructions[i][1];
2838 for (j=1; p != (char *) NULL; j++)
2839 {
2840 if (root->processing_instructions[i][k][j-1] == '>')
2841 {
2842 p=root->processing_instructions[i][j];
2843 continue;
2844 }
2845 q=root->processing_instructions[i][0];
2846 if ((length+strlen(p)+strlen(q)+WizardPathExtent) > extent)
2847 {
2848 extent=length+strlen(p)+strlen(q)+WizardPathExtent;
2849 xml=(char *) ResizeQuantumMemory(xml,extent,sizeof(*xml));
2850 if (xml == (char *) NULL)
2851 return(xml);
2852 }
2853 length+=FormatLocaleString(xml+length,extent,"<?%s%s%s?>\n",q,
2854 *p != '\0' ? " " : "",p);
2855 p=root->processing_instructions[i][j];
2856 }
2857 }
2858 ordered=xml_info->ordered;
2859 xml_info->parent=(XMLTreeInfo *) NULL;
2860 xml_info->ordered=(XMLTreeInfo *) NULL;
2861 xml=XMLTreeTagToXML(xml_info,&xml,&length,&extent,0,root->attributes);
2862 xml_info->parent=parent;
2863 xml_info->ordered=ordered;
2864 if (parent == (XMLTreeInfo *) NULL)
2865 for (i=0; root->processing_instructions[i] != (char **) NULL; i++)
2866 {
2867 /*
2868 Post-root processing instructions.
2869 */
2870 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2871 p=root->processing_instructions[i][1];
2872 for (j=1; p != (char *) NULL; j++)
2873 {
2874 if (root->processing_instructions[i][k][j-1] == '<')
2875 {
2876 p=root->processing_instructions[i][j];
2877 continue;
2878 }
2879 q=root->processing_instructions[i][0];
2880 if ((length+strlen(p)+strlen(q)+WizardPathExtent) > extent)
2881 {
2882 extent=length+strlen(p)+strlen(q)+WizardPathExtent;
2883 xml=(char *) ResizeQuantumMemory(xml,extent,sizeof(*xml));
2884 if (xml == (char *) NULL)
2885 return(xml);
2886 }
2887 length+=FormatLocaleString(xml+length,extent,"\n<?%s%s%s?>",q,
2888 *p != '\0' ? " " : "",p);
2889 p=root->processing_instructions[i][j];
2890 }
2891 }
2892 return((char *) ResizeQuantumMemory(xml,length+1,sizeof(*xml)));
2893}
WizardExport WizardBooleanType UnmapBlob(void *map, const size_t length)
Definition blob.c:1841
WizardExport void * MapBlob(int file, const MapMode mode, const WizardOffsetType offset, const size_t length)
Definition blob.c:920
#define WizardMaxBufferExtent
Definition blob.h:28
@ ReadMode
Definition blob.h:33
#define WizardAssert(domain, predicate)
#define ThrowFatalException(severity, tag)
WizardExport WizardBooleanType ThrowWizardException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *format,...)
Definition exception.c:1029
@ ResourceDomain
Definition exception.h:43
@ OptionWarning
Definition exception.h:63
@ ResourceFatalError
Definition exception.h:121
@ ResourceError
Definition exception.h:101
WizardExport ssize_t FormatLocaleString(char *string, const size_t length, const char *format,...)
Definition locale.c:465
WizardBooleanType LogWizardEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition log.c:1390
WizardExport WizardBooleanType IsEventLogging(void)
Definition log.c:688
@ TraceEvent
Definition log.h:39
#define GetWizardModule()
Definition log.h:30
WizardExport void * AcquireWizardMemory(const size_t size)
Definition memory.c:586
WizardExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition memory.c:657
WizardExport void * RelinquishWizardMemory(void *memory)
Definition memory.c:1039
WizardExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition memory.c:1236
#define WizardPrivate
#define WizardExport
#define WizardPathExtent
#define WizardSignature
WizardExport WizardBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree, const void *key, const void *value)
Definition splay-tree.c:152
static long StringToLong(const char *value)
WizardExport char * DestroyString(char *string)
Definition string.c:830
WizardExport int LocaleCompare(const char *p, const char *q)
Definition string.c:1510
WizardExport char * ConstantString(const char *source)
Definition string.c:655
WizardExport char * AcquireString(const char *source)
Definition string.c:133
WizardExport WizardBooleanType ConcatenateString(char **destination, const char *source)
Definition string.c:417
WizardExport size_t CopyWizardString(char *destination, const char *source, const size_t length)
Definition string.c:762
XMLTreeInfo * ordered
Definition xml-tree.c:88
size_t offset
Definition xml-tree.c:82
char * tag
Definition xml-tree.c:77
XMLTreeInfo * next
Definition xml-tree.c:86
SemaphoreInfo * semaphore
Definition xml-tree.c:95
char ** attributes
Definition xml-tree.c:78
XMLTreeInfo * sibling
Definition xml-tree.c:87
char * content
Definition xml-tree.c:79
size_t signature
Definition xml-tree.c:98
WizardBooleanType debug
Definition xml-tree.c:92
XMLTreeInfo * parent
Definition xml-tree.c:85
XMLTreeInfo * child
Definition xml-tree.c:89
size_t signature
Definition xml-tree.c:127
char *** attributes
Definition xml-tree.c:118
WizardBooleanType standalone
Definition xml-tree.c:113
SemaphoreInfo * semaphore
Definition xml-tree.c:124
char ** entities
Definition xml-tree.c:117
char *** processing_instructions
Definition xml-tree.c:116
WizardBooleanType debug
Definition xml-tree.c:121
struct _XMLTreeInfo root
Definition xml-tree.c:106
XMLTreeInfo * node
Definition xml-tree.c:110
#define O_BINARY
Definition studio.h:326
#define WizardMaxRecursionDepth
Definition studio.h:304
static int open_utf8(const char *path, int flags, mode_t mode)
#define WizardMin(x, y)
WizardExport char ** GetPathComponents(const char *, size_t *)
Definition utility.c:576
WizardExport void GetPathComponent(const char *path, PathType type, char *component)
Definition utility.c:415
WizardExport char * Base64Encode(const unsigned char *blob, const size_t blob_length, size_t *encode_length)
Definition utility.c:292
@ SubnodePath
Definition utility.h:34
@ CanonicalPath
Definition utility.h:35
ssize_t WizardOffsetType
Definition wizard-type.h:50
WizardBooleanType
Definition wizard-type.h:26
@ WizardTrue
Definition wizard-type.h:28
@ WizardFalse
Definition wizard-type.h:27
static char * ConvertUTF16ToUTF8(const char *content, size_t *length)
Definition xml-tree.c:1313
WizardExport const char * GetXMLTreeTag(XMLTreeInfo *xml_info)
Definition xml-tree.c:1183
static void ParseProcessingInstructions(XMLTreeRoot *root, char *xml, size_t length)
Definition xml-tree.c:1642
WizardExport XMLTreeInfo * SetXMLTreeAttribute(XMLTreeInfo *xml_info, const char *tag, const char *value)
Definition xml-tree.c:2523
static WizardBooleanType ValidateEntities(char *tag, char *xml, const size_t depth, char **entities)
Definition xml-tree.c:1612
WizardExport const char * GetXMLTreeContent(XMLTreeInfo *xml_info)
Definition xml-tree.c:966
WizardExport XMLTreeInfo * SetXMLTreeContent(XMLTreeInfo *xml_info, const char *content)
Definition xml-tree.c:2614
static void DestroyXMLTreeOrdered(XMLTreeInfo *xml_info)
Definition xml-tree.c:516
void ParseCharacterContent(XMLTreeRoot *root, char *xml, const size_t length, const char state)
Definition xml-tree.c:1573
WizardExport const char ** GetXMLTreeProcessingInstructions(XMLTreeInfo *xml_info, const char *target)
Definition xml-tree.c:1105
WizardExport XMLTreeInfo * DestroyXMLTree(XMLTreeInfo *xml_info)
Definition xml-tree.c:593
WizardExport XMLTreeInfo * InsertTagIntoXMLTree(XMLTreeInfo *xml_info, XMLTreeInfo *child, const size_t offset)
Definition xml-tree.c:1220
#define NumberPredefinedEntities
Definition xml-tree.c:68
static void ParseOpenTag(XMLTreeRoot *root, char *tag, char **attributes)
Definition xml-tree.c:1950
WizardExport XMLTreeInfo * AddPathToXMLTree(XMLTreeInfo *xml_info, const char *path, const size_t offset)
Definition xml-tree.c:212
static void DestroyXMLTreeRoot(XMLTreeInfo *xml_info)
Definition xml-tree.c:532
static char ** DestroyXMLTreeAttributes(char **attributes)
Definition xml-tree.c:476
WizardExport XMLTreeInfo * GetXMLTreeSibling(XMLTreeInfo *xml_info)
Definition xml-tree.c:1152
static char * XMLTreeTagToXML(XMLTreeInfo *xml_info, char **source, size_t *length, size_t *extent, size_t start, char ***attributes)
Definition xml-tree.c:2684
WizardExport XMLTreeInfo * NewXMLTreeTag(const char *tag)
Definition xml-tree.c:2394
WizardExport char * XMLTreeInfoToXML(XMLTreeInfo *xml_info)
Definition xml-tree.c:2790
static unsigned char * ConvertLatin1ToUTF8(const unsigned char *content)
Definition xml-tree.c:296
WizardExport XMLTreeInfo * PruneTagFromXMLTree(XMLTreeInfo *xml_info)
Definition xml-tree.c:2450
static WizardBooleanType ParseInternalDoctype(XMLTreeRoot *root, char *xml, size_t length, ExceptionInfo *exception)
Definition xml-tree.c:1719
#define XMLWhitespace
Definition xml-tree.c:69
static WizardBooleanType IsSkipTag(const char *tag)
Definition xml-tree.c:1973
WizardExport XMLTreeInfo * AddChildToXMLTree(XMLTreeInfo *xml_info, const char *tag, const size_t offset)
Definition xml-tree.c:164
WizardExport XMLTreeInfo * GetXMLTreePath(XMLTreeInfo *xml_info, const char *path)
Definition xml-tree.c:1031
WizardPrivate char * FileToXML(const char *filename, const size_t extent)
Definition xml-tree.c:633
static char * ParseEntities(char *xml, char **entities, int state)
Definition xml-tree.c:1394
WizardExport char * CanonicalXMLContent(const char *content, const WizardBooleanType pedantic)
Definition xml-tree.c:337
WizardExport const char * GetXMLTreeAttribute(XMLTreeInfo *xml_info, const char *tag)
Definition xml-tree.c:812
WizardExport XMLTreeInfo * GetXMLTreeOrdered(XMLTreeInfo *xml_info)
Definition xml-tree.c:997
static XMLTreeInfo * ParseCloseTag(XMLTreeRoot *root, char *tag, ExceptionInfo *exception)
Definition xml-tree.c:1598
WizardExport XMLTreeInfo * NewXMLTree(const char *xml, ExceptionInfo *exception)
Definition xml-tree.c:1988
WizardExport XMLTreeInfo * GetNextXMLTreeTag(XMLTreeInfo *xml_info)
Definition xml-tree.c:778
WizardExport WizardBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info, SplayTreeInfo *attributes)
Definition xml-tree.c:880
WizardExport XMLTreeInfo * GetXMLTreeChild(XMLTreeInfo *xml_info, const char *tag)
Definition xml-tree.c:927
static const char * ignore_tags[3]
Definition xml-tree.c:1966
static char * sentinel[]
Definition xml-tree.c:134
static char * EncodePredefinedEntities(const char *source, ssize_t offset, char **destination, size_t *length, size_t *extent, WizardBooleanType pedantic)
Definition xml-tree.c:2650
static void DestroyXMLTreeChild(XMLTreeInfo *xml_info)
Definition xml-tree.c:500