50#include "MagickCore/studio.h"
51#include "MagickCore/blob.h"
52#include "MagickCore/blob-private.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/image-private.h"
56#include "MagickCore/log.h"
57#include "MagickCore/memory_.h"
58#include "MagickCore/memory-private.h"
59#include "MagickCore/semaphore.h"
60#include "MagickCore/string_.h"
61#include "MagickCore/string-private.h"
62#include "MagickCore/token-private.h"
63#include "MagickCore/xml-tree.h"
64#include "MagickCore/xml-tree-private.h"
65#include "MagickCore/utility.h"
66#include "MagickCore/utility-private.h"
71#define NumberPredefinedEntities 10
72#define XMLWhitespace "\t\r\n "
119 ***processing_instructions,
138 *sentinel[] = { (
char *) NULL };
180 child->offset=offset;
181 child->parent=xml_info;
184 xml_info->child=child;
187 head=xml_info->child;
188 if (head->offset > offset)
191 xml_info->child=child;
197 (node->ordered->offset <= offset))
199 child->ordered=node->ordered;
204 while ((node != (
XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0))
209 if ((node != (
XMLTreeInfo *) NULL) && (node->offset <= offset))
212 (node->next->offset <= offset))
214 child->next=node->next;
220 previous->sibling=node->sibling;
224 while ((node != (
XMLTreeInfo *) NULL) && (node->offset <= offset))
231 previous->sibling=child;
237 const char *tag,
const size_t offset)
244 child=(
XMLTreeInfo *) AcquireMagickMemory(
sizeof(*child));
247 (void) memset(child,0,
sizeof(*child));
248 child->tag=ConstantString(tag);
249 child->attributes=sentinel;
250 child->content=ConstantString(
"");
251 child->debug=IsEventLogging();
252 child->signature=MagickCoreSignature;
253 return(InsertTagIntoXMLTree(xml_info,child,offset));
285static char *CanonicalXMLContent(
const char *content,
286 const MagickBooleanType pedantic)
301 utf8=ConvertLatin1ToUTF8((
const unsigned char *) content);
302 if (utf8 == (
unsigned char *) NULL)
303 return((
char *) NULL);
304 for (p=utf8; *p !=
'\0'; p++)
305 if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d))
312 base64=Base64Encode(utf8,strlen((
char *) utf8),&length);
313 utf8=(
unsigned char *) RelinquishMagickMemory(utf8);
314 if (base64 == (
char *) NULL)
315 return((
char *) NULL);
316 canonical_content=AcquireString(
"<base64>");
317 (void) ConcatenateString(&canonical_content,base64);
318 base64=DestroyString(base64);
319 (void) ConcatenateString(&canonical_content,
"</base64>");
320 return(canonical_content);
322 canonical_content=SubstituteXMLEntities((
const char *) utf8,pedantic);
323 utf8=(
unsigned char *) RelinquishMagickMemory(utf8);
324 return(canonical_content);
328 const char *path,
const size_t offset)
332 subnode[MagickPathExtent],
333 tag[MagickPathExtent];
347 assert((xml_info->signature == MagickCoreSignature) ||
348 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
349 if (IsEventLogging() != MagickFalse)
350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
352 components=GetPathComponents(path,&number_components);
353 if (components == (
char **) NULL)
355 for (i=0; i < (ssize_t) number_components; i++)
357 GetPathComponent(components[i],SubimagePath,subnode);
358 GetPathComponent(components[i],CanonicalPath,tag);
359 child=GetXMLTreeChild(node,tag);
361 child=AddChildToXMLTree(node,tag,offset);
365 for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--)
373 components[i]=DestroyString(components[i]);
375 for ( ; i < (ssize_t) number_components; i++)
376 components[i]=DestroyString(components[i]);
377 components=(
char **) RelinquishMagickMemory(components);
404static char **DestroyXMLTreeAttributes(
char **attributes)
412 if ((attributes == (
char **) NULL) || (attributes == sentinel))
413 return((
char **) NULL);
414 for (i=0; attributes[i] != (
char *) NULL; i+=2)
419 if (attributes[i] != (
char *) NULL)
420 attributes[i]=DestroyString(attributes[i]);
421 if (attributes[i+1] != (
char *) NULL)
422 attributes[i+1]=DestroyString(attributes[i+1]);
424 attributes=(
char **) RelinquishMagickMemory(attributes);
425 return((
char **) NULL);
428static void DestroyXMLTreeChild(
XMLTreeInfo *xml_info)
434 child=xml_info->child;
440 (void) DestroyXMLTree(node);
444static void DestroyXMLTreeOrdered(
XMLTreeInfo *xml_info)
450 ordered=xml_info->ordered;
454 ordered=node->ordered;
456 (void) DestroyXMLTree(node);
460static void DestroyXMLTreeRoot(
XMLTreeInfo *xml_info)
473 assert((xml_info->signature == MagickCoreSignature) ||
474 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
475 if (IsEventLogging() != MagickFalse)
476 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
483 for (i=NumberPredefinedEntities; root->entities[i] != (
char *) NULL; i+=2)
484 root->entities[i+1]=DestroyString(root->entities[i+1]);
485 root->entities=(
char **) RelinquishMagickMemory(root->entities);
486 for (i=0; root->attributes[i] != (
char **) NULL; i++)
488 attributes=root->attributes[i];
489 if (attributes[0] != (
char *) NULL)
490 attributes[0]=DestroyString(attributes[0]);
491 for (j=1; attributes[j] != (
char *) NULL; j+=3)
493 if (attributes[j] != (
char *) NULL)
494 attributes[j]=DestroyString(attributes[j]);
495 if (attributes[j+1] != (
char *) NULL)
496 attributes[j+1]=DestroyString(attributes[j+1]);
497 if (attributes[j+2] != (
char *) NULL)
498 attributes[j+2]=DestroyString(attributes[j+2]);
500 attributes=(
char **) RelinquishMagickMemory(attributes);
502 if (root->attributes[0] != (
char **) NULL)
503 root->attributes=(
char ***) RelinquishMagickMemory(root->attributes);
504 if (root->processing_instructions[0] != (
char **) NULL)
506 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
508 for (j=0; root->processing_instructions[i][j] != (
char *) NULL; j++)
509 root->processing_instructions[i][j]=DestroyString(
510 root->processing_instructions[i][j]);
511 root->processing_instructions[i][j+1]=DestroyString(
512 root->processing_instructions[i][j+1]);
513 root->processing_instructions[i]=(
char **) RelinquishMagickMemory(
514 root->processing_instructions[i]);
516 root->processing_instructions=(
char ***) RelinquishMagickMemory(
517 root->processing_instructions);
524 assert((xml_info->signature == MagickCoreSignature) ||
525 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
526 if (IsEventLogging() != MagickFalse)
527 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
528 DestroyXMLTreeChild(xml_info);
529 DestroyXMLTreeOrdered(xml_info);
530 DestroyXMLTreeRoot(xml_info);
531 xml_info->attributes=DestroyXMLTreeAttributes(xml_info->attributes);
532 xml_info->content=DestroyString(xml_info->content);
533 xml_info->tag=DestroyString(xml_info->tag);
534 xml_info=(
XMLTreeInfo *) RelinquishMagickMemory(xml_info);
562MagickPrivate
char *FileToXML(
const char *filename,
const size_t extent)
583 assert(filename != (
const char *) NULL);
586 if (LocaleCompare(filename,
"-") != 0)
587 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
589 return((
char *) NULL);
590 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
592 if ((file == fileno(stdin)) || (offset < 0) ||
593 (offset != (MagickOffsetType) ((ssize_t) offset)))
604 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
605 quantum=(size_t) MagickMaxBufferExtent;
606 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
607 quantum=(
size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
608 xml=(
char *) AcquireQuantumMemory(quantum,
sizeof(*xml));
609 for (i=0; xml != (
char *) NULL; i+=(size_t) count)
611 count=read(file,xml+i,quantum);
618 if (~((
size_t) i) < (quantum+1))
620 xml=(
char *) RelinquishMagickMemory(xml);
623 xml=(
char *) ResizeQuantumMemory(xml,i+quantum+1,
sizeof(*xml));
624 if ((i+(
size_t) count) >= extent)
627 if (LocaleCompare(filename,
"-") != 0)
628 file=close_utf8(file);
629 if (xml == (
char *) NULL)
630 return((
char *) NULL);
633 xml=(
char *) RelinquishMagickMemory(xml);
634 return((
char *) NULL);
636 length=MagickMin(i+(
size_t) count,extent);
640 length=(size_t) MagickMin(offset,(MagickOffsetType) extent);
642 if (~length >= (MagickPathExtent-1))
643 xml=(
char *) AcquireQuantumMemory(length+MagickPathExtent,
sizeof(*xml));
644 if (xml == (
char *) NULL)
646 file=close_utf8(file);
647 return((
char *) NULL);
649 map=MapBlob(file,ReadMode,0,length);
650 if (map != (
char *) NULL)
652 (void) memcpy(xml,map,length);
653 (void) UnmapBlob(map,length);
657 (void) lseek(file,0,SEEK_SET);
658 for (i=0; i < length; i+=(size_t) count)
660 count=read(file,xml+i,(
size_t) MagickMin(length-i,(
size_t)
661 MagickMaxBufferExtent));
671 file=close_utf8(file)-1;
672 xml=(
char *) RelinquishMagickMemory(xml);
673 return((
char *) NULL);
677 if (LocaleCompare(filename,
"-") != 0)
678 file=close_utf8(file);
680 xml=(
char *) RelinquishMagickMemory(xml);
709 assert((xml_info->signature == MagickCoreSignature) ||
710 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
711 if (IsEventLogging() != MagickFalse)
712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
713 return(xml_info->next);
741MagickExport
const char *GetXMLTreeAttribute(
XMLTreeInfo *xml_info,
752 assert((xml_info->signature == MagickCoreSignature) ||
753 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
754 if (IsEventLogging() != MagickFalse)
755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
756 if (xml_info->attributes == (
char **) NULL)
757 return((
const char *) NULL);
759 while ((xml_info->attributes[i] != (
char *) NULL) &&
760 (strcmp(xml_info->attributes[i],tag) != 0))
762 if (xml_info->attributes[i] != (
char *) NULL)
763 return(xml_info->attributes[i+1]);
768 while ((root->attributes[i] != (
char **) NULL) &&
769 (strcmp(root->attributes[i][0],xml_info->tag) != 0))
771 if (root->attributes[i] == (
char **) NULL)
772 return((
const char *) NULL);
774 while ((root->attributes[i][j] != (
char *) NULL) &&
775 (strcmp(root->attributes[i][j],tag) != 0))
777 if (root->attributes[i][j] == (
char *) NULL)
778 return((
const char *) NULL);
779 return(root->attributes[i][j+1]);
811 assert((xml_info->signature == MagickCoreSignature) ||
812 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
813 if (IsEventLogging() != MagickFalse)
814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
815 child=xml_info->child;
816 if (tag != (
const char *) NULL)
817 while ((child != (
XMLTreeInfo *) NULL) && (strcmp(child->tag,tag) != 0))
818 child=child->sibling;
845MagickExport
const char *GetXMLTreeContent(
XMLTreeInfo *xml_info)
848 assert((xml_info->signature == MagickCoreSignature) ||
849 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
850 if (IsEventLogging() != MagickFalse)
851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
852 return(xml_info->content);
880 assert((xml_info->signature == MagickCoreSignature) ||
881 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
882 if (IsEventLogging() != MagickFalse)
883 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
884 return(xml_info->sibling);
909MagickExport
const char *GetXMLTreeTag(
XMLTreeInfo *xml_info)
912 assert((xml_info->signature == MagickCoreSignature) ||
913 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
914 if (IsEventLogging() != MagickFalse)
915 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
916 return(xml_info->tag);
945static char *ConvertUTF16ToUTF8(
const char *content,
size_t *length)
963 utf8=(
char *) AcquireQuantumMemory(*length+1,
sizeof(*utf8));
964 if (utf8 == (
char *) NULL)
965 return((
char *) NULL);
966 encoding=(*content ==
'\xFE') ? 1 : (*content ==
'\xFF') ? 0 : -1;
972 (void) memcpy(utf8,content,*length*
sizeof(*utf8));
978 for (i=2; i < (ssize_t) (*length-1); i+=2)
980 c=(encoding != 0) ? ((content[i] & 0xff) << 8) | (content[i+1] & 0xff) :
981 ((content[i+1] & 0xff) << 8) | (content[i] & 0xff);
982 if ((c >= 0xd800) && (c <= 0xdfff) && ((i+=2) < (ssize_t) (*length-1)))
984 byte=(encoding != 0) ? ((content[i] & 0xff) << 8) |
985 (content[i+1] & 0xff) : ((content[i+1] & 0xff) << 8) |
987 c=(((c & 0x3ff) << 10) | (
byte & 0x3ff))+0x10000;
989 if ((
size_t) (j+MagickPathExtent) > extent)
991 extent=(size_t) j+MagickPathExtent;
992 utf8=(
char *) ResizeQuantumMemory(utf8,extent,
sizeof(*utf8));
993 if (utf8 == (
char *) NULL)
1006 for (bits=0;
byte != 0;
byte/=2)
1009 utf8[j++]=(0xFF << (7-bits)) | (c >> (6*bits));
1013 utf8[j]=(char) (0x80 | ((c >> (6*bits)) & 0x3f));
1018 utf8=(
char *) ResizeQuantumMemory(utf8,(*length+1),
sizeof(*utf8));
1019 if (utf8 != (
char *) NULL)
1024static char *ParseEntities(
char *xml,
char **entities,
int state,
1049 for ( ; *xml !=
'\0'; xml++)
1050 while (*xml ==
'\r')
1054 (void) memmove(xml,xml+1,strlen(xml));
1058 while ((*xml !=
'\0') && (*xml !=
'&') && ((*xml !=
'%') ||
1059 (state !=
'%')) && (isspace((
int) ((
unsigned char) *xml)) == 0))
1071 if ((state !=
'c') && (strncmp(xml,
"&#",2) == 0))
1077 c=(int) strtol(xml+2,&entity,10);
1079 c=(int) strtol(xml+3,&entity,16);
1080 if ((c == 0) || (*entity !=
';'))
1096 for (i=0;
byte != 0;
byte/=2)
1099 *xml=(char) ((0xFF << (7-i)) | (c >> (6*i)));
1104 *xml=(char) (0x80 | ((c >> (6*i)) & 0x3F));
1108 (void) memmove(xml,strchr(xml,
';')+1,strlen(strchr(xml,
';')));
1111 if (((*xml ==
'&') && ((state ==
'&') || (state ==
' ') ||
1112 (state ==
'*'))) || ((state ==
'%') && (*xml ==
'%')))
1118 while ((entities[i] != (
char *) NULL) &&
1119 (strncmp(xml+1,entities[i],strlen(entities[i])) != 0))
1121 if (entities[i++] == (
char *) NULL)
1124 if (entities[i] != (
char *) NULL)
1129 length=strlen(entities[i]);
1130 entity=strchr(xml,
';');
1131 if ((entity != (
char *) NULL) &&
1132 ((length-1L) >= (
size_t) (entity-xml)))
1134 offset=(ssize_t) (xml-p);
1135 extent=((size_t) offset+length+strlen(entity));
1138 p=(
char *) ResizeQuantumMemory(p,extent+1,
sizeof(*p));
1139 if (p == (
char *) NULL)
1140 ThrowFatalException(ResourceLimitFatalError,
1141 "MemoryAllocationFailed");
1149 extent_xml=(
char *) AcquireQuantumMemory(extent+1,
1150 sizeof(*extent_xml));
1151 if (extent_xml != (
char *) NULL)
1153 memset(extent_xml,0,extent*
sizeof(*extent_xml));
1154 (void) CopyMagickString(extent_xml,p,extent*
1155 sizeof(*extent_xml));
1159 if (p == (
char *) NULL)
1161 (void) ThrowMagickException(exception,GetMagickModule(),
1162 OptionWarning,
"ParseError",
1163 "memory allocation failed");
1166 if (strlen(p) > GetMaxProfileSize())
1168 (void) ThrowMagickException(exception,GetMagickModule(),
1169 ResourceLimitError,
"ProfileSizeExceedsLimit",
1170 "`%.17g'",(double) strlen(p));
1171 return(p == q ? ConstantString(p) : p);
1174 entity=strchr(xml,
';');
1176 if (entity != (
char *) NULL)
1177 (void) memmove(xml+length,entity+1,strlen(entity));
1178 (void) memcpy(xml,entities[i],length);
1182 if (((state ==
' ') || (state ==
'*')) &&
1183 (isspace((
int) ((
unsigned char) *xml)) != 0))
1193 for (xml=p; *xml !=
'\0'; xml++)
1198 i=(ssize_t) strspn(xml,accept);
1200 (void) memmove(xml,xml+i,strlen(xml+i)+1);
1201 while ((*xml !=
'\0') && (*xml !=
' '))
1207 if ((xml >= p) && (*xml ==
' '))
1210 return(p == q ? ConstantString(p) : p);
1213static void ParseCharacterContent(
XMLTreeRoot *root,
char *xml,
1214 const size_t length,
const char state,
ExceptionInfo *exception)
1219 xml_info=root->node;
1220 if ((xml_info == (
XMLTreeInfo *) NULL) || (xml_info->tag == (
char *) NULL) ||
1224 xml=ParseEntities(xml,root->entities,state,exception);
1225 if ((xml_info->content != (
char *) NULL) && (*xml_info->content !=
'\0'))
1227 (void) ConcatenateString(&xml_info->content,xml);
1228 xml=DestroyString(xml);
1232 if (xml_info->content != (
char *) NULL)
1233 xml_info->content=DestroyString(xml_info->content);
1234 xml_info->content=xml;
1242 (root->node->tag == (
char *) NULL) || (strcmp(tag,root->node->tag) != 0))
1244 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1245 "ParseError",
"unexpected closing tag </%s>",tag);
1246 return(&root->root);
1248 root->node=root->node->parent;
1253static MagickBooleanType ValidateEntities(
char *tag,
char *xml,
1254 const int delimiter,
const size_t depth,
char **entities)
1262 if (depth >= MagickMaxRecursionDepth)
1263 return(MagickFalse);
1266 while ((*xml !=
'\0') && (*xml != delimiter))
1270 if (strncmp(xml+1,tag,strlen(tag)) == 0)
1271 return(MagickFalse);
1273 while ((entities[i] != (
char *) NULL) &&
1274 (strncmp(entities[i],xml+1,strlen(entities[i])) == 0))
1276 if ((entities[i] != (
char *) NULL) &&
1277 (ValidateEntities(tag,entities[i+1],delimiter,depth+1,entities) == MagickFalse))
1278 return(MagickFalse);
1282static void ParseProcessingInstructions(
XMLTreeRoot *root,
char *xml,
1294 xml+=strcspn(xml,XMLWhitespace);
1298 xml+=strspn(xml+1,XMLWhitespace)+1;
1300 if (strcmp(target,
"xml") == 0)
1302 xml=strstr(xml,
"standalone");
1303 if ((xml != (
char *) NULL) &&
1304 (strncmp(xml+strspn(xml+10,XMLWhitespace
"='\"")+10,
"yes",3) == 0))
1305 root->standalone=MagickTrue;
1308 if (root->processing_instructions[0] == (
char **) NULL)
1310 root->processing_instructions=(
char ***) AcquireCriticalMemory(
sizeof(
1311 *root->processing_instructions));
1312 *root->processing_instructions=(
char **) NULL;
1315 while ((root->processing_instructions[i] != (
char **) NULL) &&
1316 (strcmp(target,root->processing_instructions[i][0]) != 0))
1318 if (root->processing_instructions[i] == (
char **) NULL)
1320 root->processing_instructions=(
char ***) ResizeQuantumMemory(
1321 root->processing_instructions,(
size_t) (i+2),
1322 sizeof(*root->processing_instructions));
1323 if (root->processing_instructions == (
char ***) NULL)
1324 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1325 root->processing_instructions[i]=(
char **) AcquireQuantumMemory(3,
1326 sizeof(**root->processing_instructions));
1327 if (root->processing_instructions[i] == (
char **) NULL)
1328 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1329 root->processing_instructions[i+1]=(
char **) NULL;
1330 root->processing_instructions[i][0]=ConstantString(target);
1331 root->processing_instructions[i][1]=(
char *)
1332 root->processing_instructions[i+1];
1333 root->processing_instructions[i+1]=(
char **) NULL;
1334 root->processing_instructions[i][2]=ConstantString(
"");
1337 while (root->processing_instructions[i][j] != (
char *) NULL)
1339 root->processing_instructions[i]=(
char **) ResizeQuantumMemory(
1340 root->processing_instructions[i],(
size_t) (j+3),
1341 sizeof(**root->processing_instructions));
1342 if (root->processing_instructions[i] == (
char **) NULL)
1343 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1344 root->processing_instructions[i][j+2]=(
char *) ResizeQuantumMemory(
1345 root->processing_instructions[i][j+1],(
size_t) (j+1),
1346 sizeof(***root->processing_instructions));
1347 if (root->processing_instructions[i][j+2] == (
char *) NULL)
1348 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1349 (void) CopyMagickString(root->processing_instructions[i][j+2]+j-1,
1350 root->root.tag != (
char *) NULL ?
">" :
"<",2);
1351 root->processing_instructions[i][j]=ConstantString(xml);
1352 root->processing_instructions[i][j+1]=(
char *) NULL;
1355static MagickBooleanType ParseInternalDoctype(
XMLTreeRoot *root,
char *xml,
1358#define DestroyXMLEntities(predefined_entities) \
1361 for (k=0; predefined_entities[k] != (char *) NULL; k++) \
1362 if ((k & 0x01) != 0) \
1363 predefined_entities[k]=DestroyString(predefined_entities[k]); \
1364 predefined_entities=(char **) RelinquishMagickMemory(predefined_entities); \
1371 **predefined_entities,
1381 predefined_entities=(
char **) AcquireMagickMemory(
sizeof(sentinel));
1382 if (predefined_entities == (
char **) NULL)
1383 ThrowFatalException(ResourceLimitError,
"MemoryAllocationFailed");
1384 (void) memcpy(predefined_entities,sentinel,
sizeof(sentinel));
1385 for (xml[length]=
'\0'; xml != (
char *) NULL; )
1387 while ((*xml !=
'\0') && (*xml !=
'<') && (*xml !=
'%'))
1391 if ((strlen(xml) > 9) && (strncmp(xml,
"<!ENTITY",8) == 0))
1396 if (strspn(xml+8,XMLWhitespace) == 0)
1398 xml+=strspn(xml+8,XMLWhitespace)+8;
1400 n=xml+strspn(xml,XMLWhitespace
"%");
1401 if ((isalpha((
int) ((
unsigned char) *n)) == 0) && (*n !=
'_'))
1403 xml=n+strcspn(n,XMLWhitespace);
1407 v=xml+strspn(xml+1,XMLWhitespace)+1;
1410 if ((q !=
'"') && (q !=
'\''))
1415 xml=strchr(xml,
'>');
1418 entities=(*c ==
'%') ? predefined_entities : root->entities;
1419 for (i=0; entities[i] != (
char *) NULL; i++) ;
1420 entities=(
char **) ResizeQuantumMemory(entities,(
size_t) (i+3),
1422 if (entities == (
char **) NULL)
1423 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1425 predefined_entities=entities;
1427 root->entities=entities;
1431 if (xml != (
char *) NULL)
1436 entities[i+1]=ParseEntities(v,predefined_entities,
'%',exception);
1437 entities[i+2]=(
char *) NULL;
1438 if ((ValidateEntities(n,entities[i+1],
'%',0,entities) != MagickFalse) &&
1439 (ValidateEntities(n,entities[i+1],
'&',0,entities) != MagickFalse))
1443 if (entities[i+1] != v)
1444 entities[i+1]=DestroyString(entities[i+1]);
1445 (void) ThrowMagickException(exception,GetMagickModule(),
1446 OptionWarning,
"ParseError",
"circular entity declaration %s",n);
1447 DestroyXMLEntities(predefined_entities);
1448 return(MagickFalse);
1452 if (strncmp(xml,
"<!ATTLIST",9) == 0)
1457 t=xml+strspn(xml+9,XMLWhitespace)+9;
1460 (void) ThrowMagickException(exception,GetMagickModule(),
1461 OptionWarning,
"ParseError",
"unclosed <!ATTLIST");
1462 DestroyXMLEntities(predefined_entities);
1463 return(MagickFalse);
1465 xml=t+strcspn(t,XMLWhitespace
">");
1470 while ((root->attributes[i] != (
char **) NULL) &&
1471 (n != (
char *) NULL) &&
1472 (strcmp(n,root->attributes[i][0]) != 0))
1474 while ((*(n=xml+strspn(xml+1,XMLWhitespace)+1) !=
'\0') &&
1477 xml=n+strcspn(n,XMLWhitespace);
1482 (void) ThrowMagickException(exception,GetMagickModule(),
1483 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1484 DestroyXMLEntities(predefined_entities);
1485 return(MagickFalse);
1487 xml+=strspn(xml+1,XMLWhitespace)+1;
1488 c=(
char *) (strncmp(xml,
"CDATA",5) != 0 ?
"*" :
" ");
1489 if (strncmp(xml,
"NOTATION",8) == 0)
1490 xml+=strspn(xml+8,XMLWhitespace)+8;
1491 xml=(*xml ==
'(') ? strchr(xml,
')') : xml+
1492 strcspn(xml,XMLWhitespace);
1493 if (xml == (
char *) NULL)
1495 (void) ThrowMagickException(exception,GetMagickModule(),
1496 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1497 DestroyXMLEntities(predefined_entities);
1498 return(MagickFalse);
1500 xml+=strspn(xml,XMLWhitespace
")");
1501 if (strncmp(xml,
"#FIXED",6) == 0)
1502 xml+=strspn(xml+6,XMLWhitespace)+6;
1505 xml+=strcspn(xml,XMLWhitespace
">")-1;
1511 if (((*xml ==
'"') || (*xml ==
'\'')) &&
1512 ((xml=strchr(v=xml+1,*xml)) != (
char *) NULL))
1516 (void) ThrowMagickException(exception,GetMagickModule(),
1517 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1518 DestroyXMLEntities(predefined_entities);
1519 return(MagickFalse);
1521 if (root->attributes[i] == (
char **) NULL)
1527 root->attributes=(
char ***) AcquireQuantumMemory(2,
1528 sizeof(*root->attributes));
1530 root->attributes=(
char ***) ResizeQuantumMemory(
1531 root->attributes,(
size_t) (i+2),
1532 sizeof(*root->attributes));
1533 if (root->attributes == (
char ***) NULL)
1534 ThrowFatalException(ResourceLimitFatalError,
1535 "MemoryAllocationFailed");
1536 root->attributes[i]=(
char **) AcquireQuantumMemory(2,
1537 sizeof(**root->attributes));
1538 if (root->attributes[i] == (
char **) NULL)
1539 ThrowFatalException(ResourceLimitFatalError,
1540 "MemoryAllocationFailed");
1541 root->attributes[i][0]=ConstantString(t);
1542 root->attributes[i][1]=(
char *) NULL;
1543 root->attributes[i+1]=(
char **) NULL;
1545 for (j=1; root->attributes[i][j] != (
char *) NULL; j+=3) ;
1546 root->attributes[i]=(
char **) ResizeQuantumMemory(
1547 root->attributes[i],(
size_t) (j+4),
sizeof(**root->attributes));
1548 if (root->attributes[i] == (
char **) NULL)
1549 ThrowFatalException(ResourceLimitFatalError,
1550 "MemoryAllocationFailed");
1551 root->attributes[i][j+3]=(
char *) NULL;
1552 root->attributes[i][j+2]=ConstantString(c);
1553 root->attributes[i][j+1]=(
char *) NULL;
1554 if (v != (
char *) NULL)
1555 root->attributes[i][j+1]=ParseEntities(v,root->entities,*c,
1557 root->attributes[i][j]=ConstantString(n);
1561 if (strncmp(xml,
"<!--", 4) == 0)
1562 xml=strstr(xml+4,
"-->");
1564 if (strncmp(xml,
"<?", 2) == 0)
1568 if (xml != (
char *) NULL)
1570 ParseProcessingInstructions(root,c,(
size_t) (xml-c));
1576 xml=strchr(xml,
'>');
1578 if ((*(xml++) ==
'%') && (root->standalone == MagickFalse))
1581 DestroyXMLEntities(predefined_entities);
1585static MagickBooleanType ParseOpenTag(
XMLTreeRoot *root,
char *tag,
1591 if (root->depth >= MagickMaxRecursionDepth)
1593 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1594 "ParseError",
"unexpected open tag </%s>",tag);
1595 return(MagickFalse);
1597 xml_info=root->node;
1598 if (xml_info->tag == (
char *) NULL)
1599 xml_info->tag=ConstantString(tag);
1601 xml_info=AddChildToXMLTree(xml_info,tag,strlen(xml_info->content));
1603 xml_info->attributes=attributes;
1604 root->node=xml_info;
1617static inline MagickBooleanType IsSkipTag(
const char *tag)
1623 while (ignore_tags[i] != (
const char *) NULL)
1625 if (LocaleCompare(tag,ignore_tags[i]) == 0)
1629 return(MagickFalse);
1663 if ((xml == (
const char *) NULL) || (strlen(xml) == 0))
1665 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1666 "ParseError",
"root tag missing");
1669 root=(
XMLTreeRoot *) NewXMLTreeTag((
char *) NULL);
1671 utf8=ConvertUTF16ToUTF8(xml,&length);
1672 if (utf8 == (
char *) NULL)
1674 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1675 "ParseError",
"UTF16 to UTF8 failed");
1678 terminal=utf8[MagickMax(length-1,0)];
1679 utf8[MagickMax(length-1,0)]=
'\0';
1681 while ((*p !=
'\0') && (*p !=
'<'))
1685 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1686 "ParseError",
"root tag missing");
1687 utf8=DestroyString(utf8);
1690 attribute=(
char **) NULL;
1695 attributes=(
char **) sentinel;
1698 if ((isalpha((
int) ((
unsigned char) *p)) != 0) || (*p ==
'_') ||
1699 (*p ==
':') || (c <
'\0'))
1706 (void) ThrowMagickException(exception,GetMagickModule(),
1707 OptionWarning,
"ParseError",
"root tag missing");
1708 utf8=DestroyString(utf8);
1709 return(&root->root);
1711 p+=(ptrdiff_t) strcspn(p,XMLWhitespace
"/>");
1712 while (isspace((
int) ((
unsigned char) *p)) != 0)
1714 if (((isalpha((
int) ((
unsigned char) *p)) != 0) || (*p ==
'_')) &&
1715 (ignore_depth == 0))
1717 if ((*p !=
'\0') && (*p !=
'/') && (*p !=
'>'))
1723 while ((root->attributes[i] != (
char **) NULL) &&
1724 (strcmp(root->attributes[i][0],tag) != 0))
1726 attribute=root->attributes[i];
1728 for (l=0; (*p !=
'\0') && (*p !=
'/') && (*p !=
'>'); l+=2)
1734 attributes=(
char **) AcquireQuantumMemory(4,
1735 sizeof(*attributes));
1737 attributes=(
char **) ResizeQuantumMemory(attributes,(
size_t)
1738 (l+4),
sizeof(*attributes));
1739 if (attributes == (
char **) NULL)
1741 (void) ThrowMagickException(exception,GetMagickModule(),
1742 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
1743 utf8=DestroyString(utf8);
1744 return(&root->root);
1746 attributes[l+2]=(
char *) NULL;
1747 attributes[l+1]=(
char *) NULL;
1749 p+=(ptrdiff_t) strcspn(p,XMLWhitespace
"=/>");
1750 if ((*p !=
'=') && (isspace((
int) ((
unsigned char) *p)) == 0))
1751 attributes[l]=ConstantString(
"");
1755 p+=(ptrdiff_t) strspn(p,XMLWhitespace
"=");
1757 if ((c ==
'"') || (c ==
'\''))
1764 while ((*p !=
'\0') && (*p != c))
1770 attributes[l]=ConstantString(
"");
1771 attributes[l+1]=ConstantString(
"");
1772 (void) DestroyXMLTreeAttributes(attributes);
1773 (void) ThrowMagickException(exception,
1774 GetMagickModule(),OptionWarning,
"ParseError",
1776 utf8=DestroyString(utf8);
1777 return(&root->root);
1780 while ((attribute != (
char **) NULL) &&
1781 (attribute[j] != (
char *) NULL) &&
1782 (strcmp(attribute[j],attributes[l]) != 0))
1784 attributes[l+1]=ParseEntities(attributes[l+1],
1785 root->entities,(attribute != (
char **) NULL) &&
1786 (attribute[j] != (
char *) NULL) ? *attribute[j+2] :
1789 attributes[l]=ConstantString(attributes[l]);
1791 while (isspace((
int) ((
unsigned char) *p)) != 0)
1797 while ((*p !=
'\0') && (*p !=
'/') && (*p !=
'>'))
1806 if (((*p !=
'\0') && (*p !=
'>')) ||
1807 ((*p ==
'\0') && (terminal !=
'>')))
1810 (void) DestroyXMLTreeAttributes(attributes);
1811 (void) ThrowMagickException(exception,GetMagickModule(),
1812 OptionWarning,
"ParseError",
"missing >");
1813 utf8=DestroyString(utf8);
1814 return(&root->root);
1816 if ((ignore_depth != 0) || (IsSkipTag(tag) != MagickFalse))
1817 (void) DestroyXMLTreeAttributes(attributes);
1820 status=ParseOpenTag(root,tag,attributes,exception);
1821 if (status == MagickFalse)
1824 (void) DestroyXMLTreeAttributes(attributes);
1825 utf8=DestroyString(utf8);
1826 return(&root->root);
1828 (void) ParseCloseTag(root,tag,exception);
1834 if ((*p ==
'>') || ((*p ==
'\0') && (terminal ==
'>')))
1837 if ((ignore_depth == 0) && (IsSkipTag(tag) == MagickFalse))
1839 status=ParseOpenTag(root,tag,attributes,exception);
1840 if (status == MagickFalse)
1843 (void) DestroyXMLTreeAttributes(attributes);
1844 utf8=DestroyString(utf8);
1845 return(&root->root);
1851 (void) DestroyXMLTreeAttributes(attributes);
1858 (void) DestroyXMLTreeAttributes(attributes);
1859 (void) ThrowMagickException(exception,GetMagickModule(),
1860 OptionWarning,
"ParseError",
"missing >");
1861 utf8=DestroyString(utf8);
1862 return(&root->root);
1873 p+=(ptrdiff_t) strcspn(tag,XMLWhitespace
">")+1;
1875 if ((c ==
'\0') && (terminal !=
'>'))
1877 (void) ThrowMagickException(exception,GetMagickModule(),
1878 OptionWarning,
"ParseError",
"missing >");
1879 utf8=DestroyString(utf8);
1880 return(&root->root);
1883 if ((ignore_depth == 0) &&
1884 (ParseCloseTag(root,tag,exception) != (
XMLTreeInfo *) NULL))
1886 utf8=DestroyString(utf8);
1887 return(&root->root);
1889 if (ignore_depth > 0)
1892 if (isspace((
int) ((
unsigned char) *p)) != 0)
1893 p+=(ptrdiff_t) strspn(p,XMLWhitespace);
1896 if (strncmp(p,
"!--",3) == 0)
1902 if ((p == (
char *) NULL) || ((*(p+=2) !=
'>') && (*p !=
'\0')) ||
1903 ((*p ==
'\0') && (terminal !=
'>')))
1905 (void) ThrowMagickException(exception,GetMagickModule(),
1906 OptionWarning,
"ParseError",
"unclosed <!--");
1907 utf8=DestroyString(utf8);
1908 return(&root->root);
1912 if (strncmp(p,
"![CDATA[",8) == 0)
1918 if (p != (
char *) NULL)
1921 if (ignore_depth == 0)
1922 ParseCharacterContent(root,tag+8,(
size_t) (p-tag-10),
'c',
1927 (void) ThrowMagickException(exception,GetMagickModule(),
1928 OptionWarning,
"ParseError",
"unclosed <![CDATA[");
1929 utf8=DestroyString(utf8);
1930 return(&root->root);
1934 if (strncmp(p,
"!DOCTYPE",8) == 0)
1939 for (l=0; (*p !=
'\0') && (((l == 0) && (*p !=
'>')) ||
1940 ((l != 0) && ((*p !=
']') ||
1941 (*(p+strspn(p+1,XMLWhitespace)+1) !=
'>'))));
1942 l=(ssize_t) ((*p ==
'[') ? 1 : l))
1943 p+=(ptrdiff_t) strcspn(p+1,
"[]>")+1;
1944 if ((*p ==
'\0') && (terminal !=
'>'))
1946 (void) ThrowMagickException(exception,GetMagickModule(),
1947 OptionWarning,
"ParseError",
"unclosed <!DOCTYPE");
1948 utf8=DestroyString(utf8);
1949 return(&root->root);
1952 tag=strchr(tag,
'[')+1;
1955 status=ParseInternalDoctype(root,tag,(
size_t) (p-tag),
1957 if (status == MagickFalse)
1959 utf8=DestroyString(utf8);
1960 return(&root->root);
1974 if (p == (
char *) NULL)
1977 }
while ((*p !=
'\0') && (*p !=
'>'));
1978 if ((p == (
char *) NULL) || ((*p ==
'\0') &&
1981 (void) ThrowMagickException(exception,GetMagickModule(),
1982 OptionWarning,
"ParseError",
"unclosed <?");
1983 utf8=DestroyString(utf8);
1984 return(&root->root);
1986 ParseProcessingInstructions(root,tag+1,(
size_t) (p-tag-2));
1990 (void) ThrowMagickException(exception,GetMagickModule(),
1991 OptionWarning,
"ParseError",
"unexpected <");
1992 utf8=DestroyString(utf8);
1993 return(&root->root);
1995 if ((p == (
char *) NULL) || (*p ==
'\0'))
1999 if ((*p !=
'\0') && (*p !=
'<'))
2004 while ((*p !=
'\0') && (*p !=
'<'))
2008 if (ignore_depth == 0)
2009 ParseCharacterContent(root,tag,(
size_t) (p-tag),
'&',exception);
2015 utf8=DestroyString(utf8);
2017 return(&root->root);
2018 if (root->node->tag == (
char *) NULL)
2020 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
2021 "ParseError",
"root tag missing");
2022 return(&root->root);
2024 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
2025 "ParseError",
"unclosed tag: '%s'",root->node->tag);
2026 return(&root->root);
2051MagickExport
XMLTreeInfo *NewXMLTreeTag(
const char *tag)
2054 *predefined_entities[NumberPredefinedEntities+1] =
2056 "lt;",
"<",
"gt;",
">",
"quot;",
""",
2057 "apos;",
"'",
"amp;",
"&", (
char *) NULL
2063 root=(
XMLTreeRoot *) AcquireMagickMemory(
sizeof(*root));
2066 (void) memset(root,0,
sizeof(*root));
2067 root->root.tag=(
char *) NULL;
2068 if (tag != (
char *) NULL)
2069 root->root.tag=ConstantString(tag);
2070 root->node=(&root->root);
2071 root->root.content=ConstantString(
"");
2072 root->entities=(
char **) AcquireMagickMemory(
sizeof(predefined_entities));
2073 if (root->entities == (
char **) NULL)
2075 (void) memcpy(root->entities,predefined_entities,
sizeof(predefined_entities));
2076 root->root.attributes=sentinel;
2077 root->attributes=(
char ***) root->root.attributes;
2078 root->processing_instructions=(
char ***) root->root.attributes;
2079 root->debug=IsEventLogging();
2080 root->signature=MagickCoreSignature;
2081 return(&root->root);
2111 const char *content)
2114 assert((xml_info->signature == MagickCoreSignature) ||
2115 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2116 if (IsEventLogging() != MagickFalse)
2117 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2118 if (xml_info->content != (
char *) NULL)
2119 xml_info->content=DestroyString(xml_info->content);
2120 xml_info->content=(
char *) ConstantString(content);
2139MagickPrivate MagickBooleanType SkipXMLComment(
const char **xml)
2146 while (isspace((
int) ((
unsigned char) *p)) != 0)
2148 if (strncmp(p,
"<!--",4) != 0)
2151 p=strstr(p+4,
"-->");
2152 if (p == (
const char *) NULL)
2153 return(MagickFalse);
2174MagickPrivate MagickBooleanType SkipXMLDocType(
const char **xml)
2185 for (p=*xml; *p !=
'\0'; )
2187 if ((quote == 0) && (strncmp(p,
"<!--",4) == 0))
2189 if (SkipXMLComment(&p) == MagickFalse)
2200 if ((*p ==
'"') || (*p ==
'\''))
2208 if (bracket_depth > 0)
2212 if ((*p ==
'>') && (bracket_depth == 0))
2221 return(MagickFalse);
2238MagickExport
char *SubstituteXMLEntities(
const char *content,
2239 const MagickBooleanType pedantic)
2257 canonical_content=AcquireString((
char *) NULL);
2258 extent=MagickPathExtent;
2259 for (p=content; *p !=
'\0'; p++)
2261 if ((i+MagickPathExtent) > (ssize_t) extent)
2263 extent+=MagickPathExtent;
2264 canonical_content=(
char *) ResizeQuantumMemory(canonical_content,extent,
2265 sizeof(*canonical_content));
2266 if (canonical_content == (
char *) NULL)
2267 return(canonical_content);
2273 i+=FormatLocaleString(canonical_content+i,extent,
"&");
2278 i+=FormatLocaleString(canonical_content+i,extent,
"<");
2283 i+=FormatLocaleString(canonical_content+i,extent,
">");
2288 i+=FormatLocaleString(canonical_content+i,extent,
""");
2293 if (pedantic == MagickFalse)
2295 canonical_content[i++]=(char) (*p);
2298 i+=FormatLocaleString(canonical_content+i,extent,
"
");
2303 if (pedantic == MagickFalse)
2305 canonical_content[i++]=(char) (*p);
2308 i+=FormatLocaleString(canonical_content+i,extent,
"	");
2313 i+=FormatLocaleString(canonical_content+i,extent,
"
");
2318 canonical_content[i++]=(char) (*p);
2323 canonical_content[i]=
'\0';
2324 return(canonical_content);
2350static char *EncodePredefinedEntities(
const char *source,ssize_t offset,
2351 char **destination,
size_t *length,
size_t *extent,MagickBooleanType pedantic)
2357 canonical_content=CanonicalXMLContent(source,pedantic);
2363 content=AcquireString(source);
2364 content[offset]=
'\0';
2365 canonical_content=CanonicalXMLContent(content,pedantic);
2366 content=DestroyString(content);
2368 if (canonical_content == (
char *) NULL)
2369 return(*destination);
2370 if ((*length+strlen(canonical_content)+MagickPathExtent) > *extent)
2372 *extent=(*length)+strlen(canonical_content)+MagickPathExtent;
2373 *destination=(
char *) ResizeQuantumMemory(*destination,*extent,
2374 sizeof(**destination));
2375 if (*destination == (
char *) NULL)
2376 return(*destination);
2378 *length+=(size_t) FormatLocaleString(*destination+(*length),*extent,
"%s",
2380 canonical_content=DestroyString(canonical_content);
2381 return(*destination);
2384static char *XMLTreeTagToXML(
XMLTreeInfo *xml_info,
char **source,
size_t *length,
2385 size_t *extent,
size_t start,
char ***attributes)
2400 content=(
char *)
"";
2402 content=xml_info->parent->content;
2404 *source=EncodePredefinedEntities(content+start,(ssize_t) (xml_info->offset-
2405 start),source,length,extent,MagickFalse);
2406 if ((*length+strlen(xml_info->tag)+MagickPathExtent) > *extent)
2408 *extent=(*length)+strlen(xml_info->tag)+MagickPathExtent;
2409 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2410 if (*source == (
char *) NULL)
2413 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
2414 "<%s",xml_info->tag);
2415 for (i=0; xml_info->attributes[i]; i+=2)
2417 attribute=GetXMLTreeAttribute(xml_info,xml_info->attributes[i]);
2418 if (attribute != xml_info->attributes[i+1])
2420 if ((*length+strlen(xml_info->attributes[i])+MagickPathExtent) > *extent)
2422 *extent=(*length)+strlen(xml_info->attributes[i])+MagickPathExtent;
2423 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2424 if (*source == (
char *) NULL)
2425 return((
char *) NULL);
2427 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
" %s=\"",
2428 xml_info->attributes[i]);
2429 (void) EncodePredefinedEntities(xml_info->attributes[i+1],-1,source,length,
2431 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"\"");
2434 while ((attributes[i] != (
char **) NULL) &&
2435 (strcmp(attributes[i][0],xml_info->tag) != 0))
2438 while ((attributes[i] != (
char **) NULL) &&
2439 (attributes[i][j] != (
char *) NULL))
2441 if ((attributes[i][j+1] == (
char *) NULL) ||
2442 (GetXMLTreeAttribute(xml_info,attributes[i][j]) != attributes[i][j+1]))
2447 if ((*length+strlen(attributes[i][j])+MagickPathExtent) > *extent)
2449 *extent=(*length)+strlen(attributes[i][j])+MagickPathExtent;
2450 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2451 if (*source == (
char *) NULL)
2452 return((
char *) NULL);
2454 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
" %s=\"",
2456 (void) EncodePredefinedEntities(attributes[i][j+1],-1,source,length,extent,
2458 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"\"");
2461 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
2462 *xml_info->content ?
">" :
"/>");
2464 *source=XMLTreeTagToXML(xml_info->child,source,length,extent,0,attributes);
2466 *source=EncodePredefinedEntities(xml_info->content,-1,source,length,extent,
2468 if ((*length+strlen(xml_info->tag)+MagickPathExtent) > *extent)
2470 *extent=(*length)+strlen(xml_info->tag)+MagickPathExtent;
2471 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2472 if (*source == (
char *) NULL)
2473 return((
char *) NULL);
2475 if (*xml_info->content !=
'\0')
2476 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"</%s>",
2478 while ((offset < xml_info->offset) && (content[offset] !=
'\0'))
2481 content=XMLTreeTagToXML(xml_info->ordered,source,length,extent,offset,
2484 content=EncodePredefinedEntities(content+offset,-1,source,length,extent,
2489MagickExport
char *XMLTreeInfoToXML(
XMLTreeInfo *xml_info)
2513 assert((xml_info->signature == MagickCoreSignature) ||
2514 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2515 if (IsEventLogging() != MagickFalse)
2516 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2517 if (xml_info->tag == (
char *) NULL)
2518 return((
char *) NULL);
2519 xml=AcquireString((
char *) NULL);
2521 extent=MagickPathExtent;
2525 parent=xml_info->parent;
2527 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
2532 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2533 p=root->processing_instructions[i][1];
2534 for (j=1; p != (
char *) NULL; j++)
2536 if (root->processing_instructions[i][k][j-1] ==
'>')
2538 p=root->processing_instructions[i][j];
2541 q=root->processing_instructions[i][0];
2542 if ((length+strlen(p)+strlen(q)+MagickPathExtent) > extent)
2544 extent=length+strlen(p)+strlen(q)+MagickPathExtent;
2545 xml=(
char *) ResizeQuantumMemory(xml,extent,
sizeof(*xml));
2546 if (xml == (
char *) NULL)
2549 length+=(size_t) FormatLocaleString(xml+length,extent,
"<?%s%s%s?>\n",q,
2550 *p !=
'\0' ?
" " :
"",p);
2551 p=root->processing_instructions[i][j];
2554 ordered=xml_info->ordered;
2557 xml=XMLTreeTagToXML(xml_info,&xml,&length,&extent,0,root->attributes);
2558 xml_info->parent=parent;
2559 xml_info->ordered=ordered;
2561 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
2566 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2567 p=root->processing_instructions[i][1];
2568 for (j=1; p != (
char *) NULL; j++)
2570 if (root->processing_instructions[i][k][j-1] ==
'<')
2572 p=root->processing_instructions[i][j];
2575 q=root->processing_instructions[i][0];
2576 if ((length+strlen(p)+strlen(q)+MagickPathExtent) > extent)
2578 extent=length+strlen(p)+strlen(q)+MagickPathExtent;
2579 xml=(
char *) ResizeQuantumMemory(xml,extent,
sizeof(*xml));
2580 if (xml == (
char *) NULL)
2583 length+=(size_t) FormatLocaleString(xml+length,extent,
"\n<?%s%s%s?>",q,
2584 *p !=
'\0' ?
" " :
"",p);
2585 p=root->processing_instructions[i][j];
2588 return((
char *) ResizeQuantumMemory(xml,length+1,
sizeof(*xml)));