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,
137 *sentinel[] = { (
char *) NULL };
168 const char *tag,
const size_t offset)
175 child=(
XMLTreeInfo *) AcquireMagickMemory(
sizeof(*child));
178 (void) memset(child,0,
sizeof(*child));
179 child->tag=ConstantString(tag);
180 child->attributes=sentinel;
181 child->content=ConstantString(
"");
182 child->debug=IsEventLogging();
183 child->signature=MagickCoreSignature;
184 return(InsertTagIntoXMLTree(xml_info,child,offset));
216 const char *path,
const size_t offset)
220 subnode[MagickPathExtent],
221 tag[MagickPathExtent];
235 assert((xml_info->signature == MagickCoreSignature) ||
236 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
237 if (IsEventLogging() != MagickFalse)
238 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
240 components=GetPathComponents(path,&number_components);
241 if (components == (
char **) NULL)
243 for (i=0; i < (ssize_t) number_components; i++)
245 GetPathComponent(components[i],SubimagePath,subnode);
246 GetPathComponent(components[i],CanonicalPath,tag);
247 child=GetXMLTreeChild(node,tag);
249 child=AddChildToXMLTree(node,tag,offset);
253 for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--)
255 node=GetXMLTreeOrdered(node);
261 components[i]=DestroyString(components[i]);
263 for ( ; i < (ssize_t) number_components; i++)
264 components[i]=DestroyString(components[i]);
265 components=(
char **) RelinquishMagickMemory(components);
297MagickPrivate
char *CanonicalXMLContent(
const char *content,
298 const MagickBooleanType pedantic)
313 utf8=ConvertLatin1ToUTF8((
const unsigned char *) content);
314 if (utf8 == (
unsigned char *) NULL)
315 return((
char *) NULL);
316 for (p=utf8; *p !=
'\0'; p++)
317 if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d))
324 base64=Base64Encode(utf8,strlen((
char *) utf8),&length);
325 utf8=(
unsigned char *) RelinquishMagickMemory(utf8);
326 if (base64 == (
char *) NULL)
327 return((
char *) NULL);
328 canonical_content=AcquireString(
"<base64>");
329 (void) ConcatenateString(&canonical_content,base64);
330 base64=DestroyString(base64);
331 (void) ConcatenateString(&canonical_content,
"</base64>");
332 return(canonical_content);
334 canonical_content=SubstituteXMLEntities((
const char *) utf8,pedantic);
335 utf8=(
unsigned char *) RelinquishMagickMemory(utf8);
336 return(canonical_content);
362static char **DestroyXMLTreeAttributes(
char **attributes)
370 if ((attributes == (
char **) NULL) || (attributes == sentinel))
371 return((
char **) NULL);
372 for (i=0; attributes[i] != (
char *) NULL; i+=2)
377 if (attributes[i] != (
char *) NULL)
378 attributes[i]=DestroyString(attributes[i]);
379 if (attributes[i+1] != (
char *) NULL)
380 attributes[i+1]=DestroyString(attributes[i+1]);
382 attributes=(
char **) RelinquishMagickMemory(attributes);
383 return((
char **) NULL);
386static void DestroyXMLTreeChild(
XMLTreeInfo *xml_info)
392 child=xml_info->child;
398 (void) DestroyXMLTree(node);
402static void DestroyXMLTreeOrdered(
XMLTreeInfo *xml_info)
408 ordered=xml_info->ordered;
412 ordered=node->ordered;
414 (void) DestroyXMLTree(node);
418static void DestroyXMLTreeRoot(
XMLTreeInfo *xml_info)
431 assert((xml_info->signature == MagickCoreSignature) ||
432 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
433 if (IsEventLogging() != MagickFalse)
434 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
441 for (i=NumberPredefinedEntities; root->entities[i] != (
char *) NULL; i+=2)
442 root->entities[i+1]=DestroyString(root->entities[i+1]);
443 root->entities=(
char **) RelinquishMagickMemory(root->entities);
444 for (i=0; root->attributes[i] != (
char **) NULL; i++)
446 attributes=root->attributes[i];
447 if (attributes[0] != (
char *) NULL)
448 attributes[0]=DestroyString(attributes[0]);
449 for (j=1; attributes[j] != (
char *) NULL; j+=3)
451 if (attributes[j] != (
char *) NULL)
452 attributes[j]=DestroyString(attributes[j]);
453 if (attributes[j+1] != (
char *) NULL)
454 attributes[j+1]=DestroyString(attributes[j+1]);
455 if (attributes[j+2] != (
char *) NULL)
456 attributes[j+2]=DestroyString(attributes[j+2]);
458 attributes=(
char **) RelinquishMagickMemory(attributes);
460 if (root->attributes[0] != (
char **) NULL)
461 root->attributes=(
char ***) RelinquishMagickMemory(root->attributes);
462 if (root->processing_instructions[0] != (
char **) NULL)
464 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
466 for (j=0; root->processing_instructions[i][j] != (
char *) NULL; j++)
467 root->processing_instructions[i][j]=DestroyString(
468 root->processing_instructions[i][j]);
469 root->processing_instructions[i][j+1]=DestroyString(
470 root->processing_instructions[i][j+1]);
471 root->processing_instructions[i]=(
char **) RelinquishMagickMemory(
472 root->processing_instructions[i]);
474 root->processing_instructions=(
char ***) RelinquishMagickMemory(
475 root->processing_instructions);
482 assert((xml_info->signature == MagickCoreSignature) ||
483 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
484 if (IsEventLogging() != MagickFalse)
485 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
486 DestroyXMLTreeChild(xml_info);
487 DestroyXMLTreeOrdered(xml_info);
488 DestroyXMLTreeRoot(xml_info);
489 xml_info->attributes=DestroyXMLTreeAttributes(xml_info->attributes);
490 xml_info->content=DestroyString(xml_info->content);
491 xml_info->tag=DestroyString(xml_info->tag);
492 xml_info=(
XMLTreeInfo *) RelinquishMagickMemory(xml_info);
520MagickPrivate
char *FileToXML(
const char *filename,
const size_t extent)
541 assert(filename != (
const char *) NULL);
544 if (LocaleCompare(filename,
"-") != 0)
545 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
547 return((
char *) NULL);
548 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
550 if ((file == fileno(stdin)) || (offset < 0) ||
551 (offset != (MagickOffsetType) ((ssize_t) offset)))
562 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
563 quantum=(size_t) MagickMaxBufferExtent;
564 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
565 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
566 xml=(
char *) AcquireQuantumMemory(quantum,
sizeof(*xml));
567 for (i=0; xml != (
char *) NULL; i+=(size_t) count)
569 count=read(file,xml+i,quantum);
576 if (~((
size_t) i) < (quantum+1))
578 xml=(
char *) RelinquishMagickMemory(xml);
581 xml=(
char *) ResizeQuantumMemory(xml,i+quantum+1,
sizeof(*xml));
582 if ((i+(
size_t) count) >= extent)
585 if (LocaleCompare(filename,
"-") != 0)
587 if (xml == (
char *) NULL)
588 return((
char *) NULL);
591 xml=(
char *) RelinquishMagickMemory(xml);
592 return((
char *) NULL);
594 length=MagickMin(i+(
size_t) count,extent);
598 length=(size_t) MagickMin(offset,(MagickOffsetType) extent);
600 if (~length >= (MagickPathExtent-1))
601 xml=(
char *) AcquireQuantumMemory(length+MagickPathExtent,
sizeof(*xml));
602 if (xml == (
char *) NULL)
605 return((
char *) NULL);
607 map=MapBlob(file,ReadMode,0,length);
608 if (map != (
char *) NULL)
610 (void) memcpy(xml,map,length);
611 (void) UnmapBlob(map,length);
615 (void) lseek(file,0,SEEK_SET);
616 for (i=0; i < length; i+=(size_t) count)
618 count=read(file,xml+i,(
size_t) MagickMin(length-i,(
size_t)
619 MagickMaxBufferExtent));
630 xml=(
char *) RelinquishMagickMemory(xml);
631 return((
char *) NULL);
635 if (LocaleCompare(filename,
"-") != 0)
638 xml=(
char *) RelinquishMagickMemory(xml);
667 assert((xml_info->signature == MagickCoreSignature) ||
668 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
669 if (IsEventLogging() != MagickFalse)
670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
671 return(xml_info->next);
699MagickExport
const char *GetXMLTreeAttribute(
XMLTreeInfo *xml_info,
710 assert((xml_info->signature == MagickCoreSignature) ||
711 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
712 if (IsEventLogging() != MagickFalse)
713 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
714 if (xml_info->attributes == (
char **) NULL)
715 return((
const char *) NULL);
717 while ((xml_info->attributes[i] != (
char *) NULL) &&
718 (strcmp(xml_info->attributes[i],tag) != 0))
720 if (xml_info->attributes[i] != (
char *) NULL)
721 return(xml_info->attributes[i+1]);
726 while ((root->attributes[i] != (
char **) NULL) &&
727 (strcmp(root->attributes[i][0],xml_info->tag) != 0))
729 if (root->attributes[i] == (
char **) NULL)
730 return((
const char *) NULL);
732 while ((root->attributes[i][j] != (
char *) NULL) &&
733 (strcmp(root->attributes[i][j],tag) != 0))
735 if (root->attributes[i][j] == (
char *) NULL)
736 return((
const char *) NULL);
737 return(root->attributes[i][j+1]);
766MagickPrivate MagickBooleanType GetXMLTreeAttributes(
773 assert((xml_info->signature == MagickCoreSignature) ||
774 (((
const XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
776 if (IsEventLogging() != MagickFalse)
777 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
778 if (xml_info->attributes == (
char **) NULL)
781 while (xml_info->attributes[i] != (
char *) NULL)
783 (void) AddValueToSplayTree(attributes,
784 ConstantString(xml_info->attributes[i]),
785 ConstantString(xml_info->attributes[i+1]));
820 assert((xml_info->signature == MagickCoreSignature) ||
821 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
822 if (IsEventLogging() != MagickFalse)
823 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
824 child=xml_info->child;
825 if (tag != (
const char *) NULL)
826 while ((child != (
XMLTreeInfo *) NULL) && (strcmp(child->tag,tag) != 0))
827 child=child->sibling;
854MagickExport
const char *GetXMLTreeContent(
XMLTreeInfo *xml_info)
857 assert((xml_info->signature == MagickCoreSignature) ||
858 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
859 if (IsEventLogging() != MagickFalse)
860 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
861 return(xml_info->content);
889 assert((xml_info->signature == MagickCoreSignature) ||
890 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
891 if (IsEventLogging() != MagickFalse)
892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
893 return(xml_info->ordered);
926 subnode[MagickPathExtent],
927 tag[MagickPathExtent];
940 assert((xml_info->signature == MagickCoreSignature) ||
941 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
942 if (IsEventLogging() != MagickFalse)
943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
945 components=GetPathComponents(path,&number_components);
946 if (components == (
char **) NULL)
948 for (i=0; i < (ssize_t) number_components; i++)
950 GetPathComponent(components[i],SubimagePath,subnode);
951 GetPathComponent(components[i],CanonicalPath,tag);
952 node=GetXMLTreeChild(node,tag);
955 for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--)
957 node=GetXMLTreeOrdered(node);
963 components[i]=DestroyString(components[i]);
965 for ( ; i < (ssize_t) number_components; i++)
966 components[i]=DestroyString(components[i]);
967 components=(
char **) RelinquishMagickMemory(components);
995MagickPrivate
const char **GetXMLTreeProcessingInstructions(
1005 assert((xml_info->signature == MagickCoreSignature) ||
1006 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
1007 if (IsEventLogging() != MagickFalse)
1008 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1013 while ((root->processing_instructions[i] != (
char **) NULL) &&
1014 (strcmp(root->processing_instructions[i][0],target) != 0))
1016 if (root->processing_instructions[i] == (
char **) NULL)
1017 return((
const char **) sentinel);
1018 return((
const char **) (root->processing_instructions[i]+1));
1046 assert((xml_info->signature == MagickCoreSignature) ||
1047 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
1048 if (IsEventLogging() != MagickFalse)
1049 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1050 return(xml_info->sibling);
1075MagickExport
const char *GetXMLTreeTag(
XMLTreeInfo *xml_info)
1078 assert((xml_info->signature == MagickCoreSignature) ||
1079 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
1080 if (IsEventLogging() != MagickFalse)
1081 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1082 return(xml_info->tag);
1124 child->offset=offset;
1125 child->parent=xml_info;
1128 xml_info->child=child;
1131 head=xml_info->child;
1132 if (head->offset > offset)
1134 child->ordered=head;
1135 xml_info->child=child;
1141 (node->ordered->offset <= offset))
1143 child->ordered=node->ordered;
1144 node->ordered=child;
1148 while ((node != (
XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0))
1153 if ((node != (
XMLTreeInfo *) NULL) && (node->offset <= offset))
1156 (node->next->offset <= offset))
1158 child->next=node->next;
1164 previous->sibling=node->sibling;
1168 while ((node != (
XMLTreeInfo *) NULL) && (node->offset <= offset))
1173 child->sibling=node;
1175 previous->sibling=child;
1206static char *ConvertUTF16ToUTF8(
const char *content,
size_t *length)
1224 utf8=(
char *) AcquireQuantumMemory(*length+1,
sizeof(*utf8));
1225 if (utf8 == (
char *) NULL)
1226 return((
char *) NULL);
1227 encoding=(*content ==
'\xFE') ? 1 : (*content ==
'\xFF') ? 0 : -1;
1233 (void) memcpy(utf8,content,*length*
sizeof(*utf8));
1239 for (i=2; i < (ssize_t) (*length-1); i+=2)
1241 c=(encoding != 0) ? ((content[i] & 0xff) << 8) | (content[i+1] & 0xff) :
1242 ((content[i+1] & 0xff) << 8) | (content[i] & 0xff);
1243 if ((c >= 0xd800) && (c <= 0xdfff) && ((i+=2) < (ssize_t) (*length-1)))
1245 byte=(encoding != 0) ? ((content[i] & 0xff) << 8) |
1246 (content[i+1] & 0xff) : ((content[i+1] & 0xff) << 8) |
1247 (content[i] & 0xff);
1248 c=(((c & 0x3ff) << 10) | (
byte & 0x3ff))+0x10000;
1250 if ((
size_t) (j+MagickPathExtent) > extent)
1252 extent=(size_t) j+MagickPathExtent;
1253 utf8=(
char *) ResizeQuantumMemory(utf8,extent,
sizeof(*utf8));
1254 if (utf8 == (
char *) NULL)
1267 for (bits=0;
byte != 0;
byte/=2)
1270 utf8[j++]=(0xFF << (7-bits)) | (c >> (6*bits));
1274 utf8[j]=(char) (0x80 | ((c >> (6*bits)) & 0x3f));
1279 utf8=(
char *) ResizeQuantumMemory(utf8,*length,
sizeof(*utf8));
1280 if (utf8 != (
char *) NULL)
1285static char *ParseEntities(
char *xml,
char **entities,
int state)
1309 for ( ; *xml !=
'\0'; xml++)
1310 while (*xml ==
'\r')
1314 (void) memmove(xml,xml+1,strlen(xml));
1318 while ((*xml !=
'\0') && (*xml !=
'&') && ((*xml !=
'%') ||
1319 (state !=
'%')) && (isspace((
int) ((
unsigned char) *xml)) == 0))
1331 if ((state !=
'c') && (strncmp(xml,
"&#",2) == 0))
1337 c=strtol(xml+2,&entity,10);
1339 c=strtol(xml+3,&entity,16);
1340 if ((c == 0) || (*entity !=
';'))
1356 for (i=0;
byte != 0;
byte/=2)
1359 *xml=(char) ((0xFF << (7-i)) | (c >> (6*i)));
1364 *xml=(char) (0x80 | ((c >> (6*i)) & 0x3F));
1368 (void) memmove(xml,strchr(xml,
';')+1,strlen(strchr(xml,
';')));
1371 if (((*xml ==
'&') && ((state ==
'&') || (state ==
' ') ||
1372 (state ==
'*'))) || ((state ==
'%') && (*xml ==
'%')))
1378 while ((entities[i] != (
char *) NULL) &&
1379 (strncmp(xml+1,entities[i],strlen(entities[i])) != 0))
1381 if (entities[i++] == (
char *) NULL)
1384 if (entities[i] != (
char *) NULL)
1389 length=strlen(entities[i]);
1390 entity=strchr(xml,
';');
1391 if ((entity != (
char *) NULL) &&
1392 ((length-1L) >= (
size_t) (entity-xml)))
1394 offset=(ssize_t) (xml-p);
1395 extent=((size_t) offset+length+strlen(entity));
1398 p=(
char *) ResizeQuantumMemory(p,extent+1,
sizeof(*p));
1406 extent_xml=(
char *) AcquireQuantumMemory(extent+1,
1407 sizeof(*extent_xml));
1408 if (extent_xml != (
char *) NULL)
1410 memset(extent_xml,0,extent*
sizeof(*extent_xml));
1411 (void) CopyMagickString(extent_xml,p,extent*
1412 sizeof(*extent_xml));
1416 if (p == (
char *) NULL)
1417 ThrowFatalException(ResourceLimitFatalError,
1418 "MemoryAllocationFailed");
1420 entity=strchr(xml,
';');
1422 if (entity != (
char *) NULL)
1423 (void) memmove(xml+length,entity+1,strlen(entity));
1424 (void) memcpy(xml,entities[i],length);
1428 if (((state ==
' ') || (state ==
'*')) &&
1429 (isspace((
int) ((
unsigned char) *xml)) != 0))
1439 for (xml=p; *xml !=
'\0'; xml++)
1444 i=(ssize_t) strspn(xml,accept);
1446 (void) memmove(xml,xml+i,strlen(xml+i)+1);
1447 while ((*xml !=
'\0') && (*xml !=
' '))
1453 if ((xml >= p) && (*xml ==
' '))
1456 return(p == q ? ConstantString(p) : p);
1459static void ParseCharacterContent(
XMLTreeRoot *root,
char *xml,
1460 const size_t length,
const char state)
1465 xml_info=root->node;
1466 if ((xml_info == (
XMLTreeInfo *) NULL) || (xml_info->tag == (
char *) NULL) ||
1470 xml=ParseEntities(xml,root->entities,state);
1471 if ((xml_info->content != (
char *) NULL) && (*xml_info->content !=
'\0'))
1473 (void) ConcatenateString(&xml_info->content,xml);
1474 xml=DestroyString(xml);
1478 if (xml_info->content != (
char *) NULL)
1479 xml_info->content=DestroyString(xml_info->content);
1480 xml_info->content=xml;
1488 (root->node->tag == (
char *) NULL) || (strcmp(tag,root->node->tag) != 0))
1490 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1491 "ParseError",
"unexpected closing tag </%s>",tag);
1492 return(&root->root);
1494 root->node=root->node->parent;
1498static MagickBooleanType ValidateEntities(
char *tag,
char *xml,
1499 const size_t depth,
char **entities)
1507 if (depth > MagickMaxRecursionDepth)
1508 return(MagickFalse);
1511 while ((*xml !=
'\0') && (*xml !=
'&'))
1515 if (strncmp(xml+1,tag,strlen(tag)) == 0)
1516 return(MagickFalse);
1518 while ((entities[i] != (
char *) NULL) &&
1519 (strncmp(entities[i],xml+1,strlen(entities[i])) == 0))
1521 if ((entities[i] != (
char *) NULL) &&
1522 (ValidateEntities(tag,entities[i+1],depth+1,entities) == 0))
1523 return(MagickFalse);
1527static void ParseProcessingInstructions(
XMLTreeRoot *root,
char *xml,
1539 xml+=strcspn(xml,XMLWhitespace);
1543 xml+=strspn(xml+1,XMLWhitespace)+1;
1545 if (strcmp(target,
"xml") == 0)
1547 xml=strstr(xml,
"standalone");
1548 if ((xml != (
char *) NULL) &&
1549 (strncmp(xml+strspn(xml+10,XMLWhitespace
"='\"")+10,
"yes",3) == 0))
1550 root->standalone=MagickTrue;
1553 if (root->processing_instructions[0] == (
char **) NULL)
1555 root->processing_instructions=(
char ***) AcquireCriticalMemory(
sizeof(
1556 *root->processing_instructions));
1557 *root->processing_instructions=(
char **) NULL;
1560 while ((root->processing_instructions[i] != (
char **) NULL) &&
1561 (strcmp(target,root->processing_instructions[i][0]) != 0))
1563 if (root->processing_instructions[i] == (
char **) NULL)
1565 root->processing_instructions=(
char ***) ResizeQuantumMemory(
1566 root->processing_instructions,(
size_t) (i+2),
1567 sizeof(*root->processing_instructions));
1568 if (root->processing_instructions == (
char ***) NULL)
1569 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1570 root->processing_instructions[i]=(
char **) AcquireQuantumMemory(3,
1571 sizeof(**root->processing_instructions));
1572 if (root->processing_instructions[i] == (
char **) NULL)
1573 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1574 root->processing_instructions[i+1]=(
char **) NULL;
1575 root->processing_instructions[i][0]=ConstantString(target);
1576 root->processing_instructions[i][1]=(
char *)
1577 root->processing_instructions[i+1];
1578 root->processing_instructions[i+1]=(
char **) NULL;
1579 root->processing_instructions[i][2]=ConstantString(
"");
1582 while (root->processing_instructions[i][j] != (
char *) NULL)
1584 root->processing_instructions[i]=(
char **) ResizeQuantumMemory(
1585 root->processing_instructions[i],(
size_t) (j+3),
1586 sizeof(**root->processing_instructions));
1587 if (root->processing_instructions[i] == (
char **) NULL)
1588 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1589 root->processing_instructions[i][j+2]=(
char *) ResizeQuantumMemory(
1590 root->processing_instructions[i][j+1],(
size_t) (j+1),
1591 sizeof(***root->processing_instructions));
1592 if (root->processing_instructions[i][j+2] == (
char *) NULL)
1593 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1594 (void) CopyMagickString(root->processing_instructions[i][j+2]+j-1,
1595 root->root.tag != (
char *) NULL ?
">" :
"<",2);
1596 root->processing_instructions[i][j]=ConstantString(xml);
1597 root->processing_instructions[i][j+1]=(
char *) NULL;
1600static MagickBooleanType ParseInternalDoctype(
XMLTreeRoot *root,
char *xml,
1607 **predefined_entities,
1617 predefined_entities=(
char **) AcquireMagickMemory(
sizeof(sentinel));
1618 if (predefined_entities == (
char **) NULL)
1619 ThrowFatalException(ResourceLimitError,
"MemoryAllocationFailed");
1620 (void) memcpy(predefined_entities,sentinel,
sizeof(sentinel));
1621 for (xml[length]=
'\0'; xml != (
char *) NULL; )
1623 while ((*xml !=
'\0') && (*xml !=
'<') && (*xml !=
'%'))
1627 if ((strlen(xml) > 9) && (strncmp(xml,
"<!ENTITY",8) == 0))
1632 if (strspn(xml+8,XMLWhitespace) == 0)
1634 xml+=strspn(xml+8,XMLWhitespace)+8;
1636 n=xml+strspn(xml,XMLWhitespace
"%");
1637 if ((isalpha((
int) ((
unsigned char) *n)) == 0) && (*n !=
'_'))
1639 xml=n+strcspn(n,XMLWhitespace);
1643 v=xml+strspn(xml+1,XMLWhitespace)+1;
1646 if ((q !=
'"') && (q !=
'\''))
1651 xml=strchr(xml,
'>');
1654 entities=(*c ==
'%') ? predefined_entities : root->entities;
1655 for (i=0; entities[i] != (
char *) NULL; i++) ;
1656 entities=(
char **) ResizeQuantumMemory(entities,(
size_t) (i+3),
1658 if (entities == (
char **) NULL)
1659 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1661 predefined_entities=entities;
1663 root->entities=entities;
1667 if (xml != (
char *) NULL)
1672 entities[i+1]=ParseEntities(v,predefined_entities,
'%');
1673 entities[i+2]=(
char *) NULL;
1674 if (ValidateEntities(n,entities[i+1],0,entities) != MagickFalse)
1678 if (entities[i+1] != v)
1679 entities[i+1]=DestroyString(entities[i+1]);
1680 (void) ThrowMagickException(exception,GetMagickModule(),
1681 OptionWarning,
"ParseError",
"circular entity declaration &%s",n);
1682 predefined_entities=(
char **) RelinquishMagickMemory(
1683 predefined_entities);
1684 return(MagickFalse);
1688 if (strncmp(xml,
"<!ATTLIST",9) == 0)
1693 t=xml+strspn(xml+9,XMLWhitespace)+9;
1696 (void) ThrowMagickException(exception,GetMagickModule(),
1697 OptionWarning,
"ParseError",
"unclosed <!ATTLIST");
1698 predefined_entities=(
char **) RelinquishMagickMemory(
1699 predefined_entities);
1700 return(MagickFalse);
1702 xml=t+strcspn(t,XMLWhitespace
">");
1707 while ((root->attributes[i] != (
char **) NULL) &&
1708 (n != (
char *) NULL) &&
1709 (strcmp(n,root->attributes[i][0]) != 0))
1711 while ((*(n=xml+strspn(xml+1,XMLWhitespace)+1) !=
'\0') &&
1714 xml=n+strcspn(n,XMLWhitespace);
1719 (void) ThrowMagickException(exception,GetMagickModule(),
1720 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1721 predefined_entities=(
char **) RelinquishMagickMemory(
1722 predefined_entities);
1723 return(MagickFalse);
1725 xml+=strspn(xml+1,XMLWhitespace)+1;
1726 c=(
char *) (strncmp(xml,
"CDATA",5) != 0 ?
"*" :
" ");
1727 if (strncmp(xml,
"NOTATION",8) == 0)
1728 xml+=strspn(xml+8,XMLWhitespace)+8;
1729 xml=(*xml ==
'(') ? strchr(xml,
')') : xml+
1730 strcspn(xml,XMLWhitespace);
1731 if (xml == (
char *) NULL)
1733 (void) ThrowMagickException(exception,GetMagickModule(),
1734 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1735 predefined_entities=(
char **) RelinquishMagickMemory(
1736 predefined_entities);
1737 return(MagickFalse);
1739 xml+=strspn(xml,XMLWhitespace
")");
1740 if (strncmp(xml,
"#FIXED",6) == 0)
1741 xml+=strspn(xml+6,XMLWhitespace)+6;
1744 xml+=strcspn(xml,XMLWhitespace
">")-1;
1750 if (((*xml ==
'"') || (*xml ==
'\'')) &&
1751 ((xml=strchr(v=xml+1,*xml)) != (
char *) NULL))
1755 (void) ThrowMagickException(exception,GetMagickModule(),
1756 OptionWarning,
"ParseError",
"malformed <!ATTLIST");
1757 predefined_entities=(
char **) RelinquishMagickMemory(
1758 predefined_entities);
1759 return(MagickFalse);
1761 if (root->attributes[i] == (
char **) NULL)
1767 root->attributes=(
char ***) AcquireQuantumMemory(2,
1768 sizeof(*root->attributes));
1770 root->attributes=(
char ***) ResizeQuantumMemory(
1771 root->attributes,(
size_t) (i+2),
1772 sizeof(*root->attributes));
1773 if (root->attributes == (
char ***) NULL)
1774 ThrowFatalException(ResourceLimitFatalError,
1775 "MemoryAllocationFailed");
1776 root->attributes[i]=(
char **) AcquireQuantumMemory(2,
1777 sizeof(**root->attributes));
1778 if (root->attributes[i] == (
char **) NULL)
1779 ThrowFatalException(ResourceLimitFatalError,
1780 "MemoryAllocationFailed");
1781 root->attributes[i][0]=ConstantString(t);
1782 root->attributes[i][1]=(
char *) NULL;
1783 root->attributes[i+1]=(
char **) NULL;
1785 for (j=1; root->attributes[i][j] != (
char *) NULL; j+=3) ;
1786 root->attributes[i]=(
char **) ResizeQuantumMemory(
1787 root->attributes[i],(
size_t) (j+4),
sizeof(**root->attributes));
1788 if (root->attributes[i] == (
char **) NULL)
1789 ThrowFatalException(ResourceLimitFatalError,
1790 "MemoryAllocationFailed");
1791 root->attributes[i][j+3]=(
char *) NULL;
1792 root->attributes[i][j+2]=ConstantString(c);
1793 root->attributes[i][j+1]=(
char *) NULL;
1794 if (v != (
char *) NULL)
1795 root->attributes[i][j+1]=ParseEntities(v,root->entities,*c);
1796 root->attributes[i][j]=ConstantString(n);
1800 if (strncmp(xml,
"<!--", 4) == 0)
1801 xml=strstr(xml+4,
"-->");
1803 if (strncmp(xml,
"<?", 2) == 0)
1807 if (xml != (
char *) NULL)
1809 ParseProcessingInstructions(root,c,(
size_t) (xml-c));
1815 xml=strchr(xml,
'>');
1817 if ((*(xml++) ==
'%') && (root->standalone == MagickFalse))
1820 predefined_entities=(
char **) RelinquishMagickMemory(predefined_entities);
1824static void ParseOpenTag(
XMLTreeRoot *root,
char *tag,
char **attributes)
1829 xml_info=root->node;
1830 if (xml_info->tag == (
char *) NULL)
1831 xml_info->tag=ConstantString(tag);
1833 xml_info=AddChildToXMLTree(xml_info,tag,strlen(xml_info->content));
1835 xml_info->attributes=attributes;
1836 root->node=xml_info;
1847static inline MagickBooleanType IsSkipTag(
const char *tag)
1853 while (ignore_tags[i] != (
const char *) NULL)
1855 if (LocaleCompare(tag,ignore_tags[i]) == 0)
1859 return(MagickFalse);
1893 if ((xml == (
const char *) NULL) || (strlen(xml) == 0))
1895 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1896 "ParseError",
"root tag missing");
1899 root=(
XMLTreeRoot *) NewXMLTreeTag((
char *) NULL);
1901 utf8=ConvertUTF16ToUTF8(xml,&length);
1902 if (utf8 == (
char *) NULL)
1904 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1905 "ParseError",
"UTF16 to UTF8 failed");
1908 terminal=utf8[length-1];
1909 utf8[length-1]=
'\0';
1911 while ((*p !=
'\0') && (*p !=
'<'))
1915 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
1916 "ParseError",
"root tag missing");
1917 utf8=DestroyString(utf8);
1920 attribute=(
char **) NULL;
1925 attributes=(
char **) sentinel;
1928 if ((isalpha((
int) ((
unsigned char) *p)) != 0) || (*p ==
'_') ||
1929 (*p ==
':') || (c <
'\0'))
1936 (void) ThrowMagickException(exception,GetMagickModule(),
1937 OptionWarning,
"ParseError",
"root tag missing");
1938 utf8=DestroyString(utf8);
1939 return(&root->root);
1941 p+=(ptrdiff_t) strcspn(p,XMLWhitespace
"/>");
1942 while (isspace((
int) ((
unsigned char) *p)) != 0)
1944 if (((isalpha((
int) ((
unsigned char) *p)) != 0) || (*p ==
'_')) &&
1945 (ignore_depth == 0))
1947 if ((*p !=
'\0') && (*p !=
'/') && (*p !=
'>'))
1953 while ((root->attributes[i] != (
char **) NULL) &&
1954 (strcmp(root->attributes[i][0],tag) != 0))
1956 attribute=root->attributes[i];
1958 for (l=0; (*p !=
'\0') && (*p !=
'/') && (*p !=
'>'); l+=2)
1964 attributes=(
char **) AcquireQuantumMemory(4,
1965 sizeof(*attributes));
1967 attributes=(
char **) ResizeQuantumMemory(attributes,(
size_t)
1968 (l+4),
sizeof(*attributes));
1969 if (attributes == (
char **) NULL)
1971 (void) ThrowMagickException(exception,GetMagickModule(),
1972 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
1973 utf8=DestroyString(utf8);
1974 return(&root->root);
1976 attributes[l+2]=(
char *) NULL;
1977 attributes[l+1]=(
char *) NULL;
1979 p+=(ptrdiff_t) strcspn(p,XMLWhitespace
"=/>");
1980 if ((*p !=
'=') && (isspace((
int) ((
unsigned char) *p)) == 0))
1981 attributes[l]=ConstantString(
"");
1985 p+=(ptrdiff_t) strspn(p,XMLWhitespace
"=");
1987 if ((c ==
'"') || (c ==
'\''))
1994 while ((*p !=
'\0') && (*p != c))
2000 attributes[l]=ConstantString(
"");
2001 attributes[l+1]=ConstantString(
"");
2002 (void) DestroyXMLTreeAttributes(attributes);
2003 (void) ThrowMagickException(exception,
2004 GetMagickModule(),OptionWarning,
"ParseError",
2006 utf8=DestroyString(utf8);
2007 return(&root->root);
2010 while ((attribute != (
char **) NULL) &&
2011 (attribute[j] != (
char *) NULL) &&
2012 (strcmp(attribute[j],attributes[l]) != 0))
2014 attributes[l+1]=ParseEntities(attributes[l+1],
2015 root->entities,(attribute != (
char **) NULL) &&
2016 (attribute[j] != (
char *) NULL) ? *attribute[j+2] :
2019 attributes[l]=ConstantString(attributes[l]);
2021 while (isspace((
int) ((
unsigned char) *p)) != 0)
2027 while((*p !=
'\0') && (*p !=
'/') && (*p !=
'>'))
2036 if (((*p !=
'\0') && (*p !=
'>')) ||
2037 ((*p ==
'\0') && (terminal !=
'>')))
2040 (void) DestroyXMLTreeAttributes(attributes);
2041 (void) ThrowMagickException(exception,GetMagickModule(),
2042 OptionWarning,
"ParseError",
"missing >");
2043 utf8=DestroyString(utf8);
2044 return(&root->root);
2046 if ((ignore_depth != 0) || (IsSkipTag(tag) != MagickFalse))
2047 (void) DestroyXMLTreeAttributes(attributes);
2050 ParseOpenTag(root,tag,attributes);
2051 (void) ParseCloseTag(root,tag,exception);
2057 if ((*p ==
'>') || ((*p ==
'\0') && (terminal ==
'>')))
2060 if ((ignore_depth == 0) && (IsSkipTag(tag) == MagickFalse))
2061 ParseOpenTag(root,tag,attributes);
2065 (void) DestroyXMLTreeAttributes(attributes);
2072 (void) DestroyXMLTreeAttributes(attributes);
2073 (void) ThrowMagickException(exception,GetMagickModule(),
2074 OptionWarning,
"ParseError",
"missing >");
2075 utf8=DestroyString(utf8);
2076 return(&root->root);
2087 p+=(ptrdiff_t) strcspn(tag,XMLWhitespace
">")+1;
2089 if ((c ==
'\0') && (terminal !=
'>'))
2091 (void) ThrowMagickException(exception,GetMagickModule(),
2092 OptionWarning,
"ParseError",
"missing >");
2093 utf8=DestroyString(utf8);
2094 return(&root->root);
2097 if ((ignore_depth == 0) &&
2098 (ParseCloseTag(root,tag,exception) != (
XMLTreeInfo *) NULL))
2100 utf8=DestroyString(utf8);
2101 return(&root->root);
2103 if (ignore_depth > 0)
2106 if (isspace((
int) ((
unsigned char) *p)) != 0)
2107 p+=(ptrdiff_t) strspn(p,XMLWhitespace);
2110 if (strncmp(p,
"!--",3) == 0)
2116 if ((p == (
char *) NULL) || ((*(p+=2) !=
'>') && (*p !=
'\0')) ||
2117 ((*p ==
'\0') && (terminal !=
'>')))
2119 (void) ThrowMagickException(exception,GetMagickModule(),
2120 OptionWarning,
"ParseError",
"unclosed <!--");
2121 utf8=DestroyString(utf8);
2122 return(&root->root);
2126 if (strncmp(p,
"![CDATA[",8) == 0)
2132 if (p != (
char *) NULL)
2135 if (ignore_depth == 0)
2136 ParseCharacterContent(root,tag+8,(
size_t) (p-tag-10),
'c');
2140 (void) ThrowMagickException(exception,GetMagickModule(),
2141 OptionWarning,
"ParseError",
"unclosed <![CDATA[");
2142 utf8=DestroyString(utf8);
2143 return(&root->root);
2147 if (strncmp(p,
"!DOCTYPE",8) == 0)
2152 for (l=0; (*p !=
'\0') && (((l == 0) && (*p !=
'>')) ||
2153 ((l != 0) && ((*p !=
']') ||
2154 (*(p+strspn(p+1,XMLWhitespace)+1) !=
'>'))));
2155 l=(ssize_t) ((*p ==
'[') ? 1 : l))
2156 p+=(ptrdiff_t) strcspn(p+1,
"[]>")+1;
2157 if ((*p ==
'\0') && (terminal !=
'>'))
2159 (void) ThrowMagickException(exception,GetMagickModule(),
2160 OptionWarning,
"ParseError",
"unclosed <!DOCTYPE");
2161 utf8=DestroyString(utf8);
2162 return(&root->root);
2165 tag=strchr(tag,
'[')+1;
2168 status=ParseInternalDoctype(root,tag,(
size_t) (p-tag),
2170 if (status == MagickFalse)
2172 utf8=DestroyString(utf8);
2173 return(&root->root);
2187 if (p == (
char *) NULL)
2190 }
while ((*p !=
'\0') && (*p !=
'>'));
2191 if ((p == (
char *) NULL) || ((*p ==
'\0') &&
2194 (void) ThrowMagickException(exception,GetMagickModule(),
2195 OptionWarning,
"ParseError",
"unclosed <?");
2196 utf8=DestroyString(utf8);
2197 return(&root->root);
2199 ParseProcessingInstructions(root,tag+1,(
size_t) (p-tag-2));
2203 (void) ThrowMagickException(exception,GetMagickModule(),
2204 OptionWarning,
"ParseError",
"unexpected <");
2205 utf8=DestroyString(utf8);
2206 return(&root->root);
2208 if ((p == (
char *) NULL) || (*p ==
'\0'))
2212 if ((*p !=
'\0') && (*p !=
'<'))
2217 while ((*p !=
'\0') && (*p !=
'<'))
2221 if (ignore_depth == 0)
2222 ParseCharacterContent(root,tag,(
size_t) (p-tag),
'&');
2228 utf8=DestroyString(utf8);
2230 return(&root->root);
2231 if (root->node->tag == (
char *) NULL)
2233 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
2234 "ParseError",
"root tag missing");
2235 return(&root->root);
2237 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
2238 "ParseError",
"unclosed tag: '%s'",root->node->tag);
2239 return(&root->root);
2264MagickExport
XMLTreeInfo *NewXMLTreeTag(
const char *tag)
2267 *predefined_entities[NumberPredefinedEntities+1] =
2269 "lt;",
"<",
"gt;",
">",
"quot;",
""",
2270 "apos;",
"'",
"amp;",
"&", (
char *) NULL
2276 root=(
XMLTreeRoot *) AcquireMagickMemory(
sizeof(*root));
2279 (void) memset(root,0,
sizeof(*root));
2280 root->root.tag=(
char *) NULL;
2281 if (tag != (
char *) NULL)
2282 root->root.tag=ConstantString(tag);
2283 root->node=(&root->root);
2284 root->root.content=ConstantString(
"");
2285 root->entities=(
char **) AcquireMagickMemory(
sizeof(predefined_entities));
2286 if (root->entities == (
char **) NULL)
2288 (void) memcpy(root->entities,predefined_entities,
sizeof(predefined_entities));
2289 root->root.attributes=sentinel;
2290 root->attributes=(
char ***) root->root.attributes;
2291 root->processing_instructions=(
char ***) root->root.attributes;
2292 root->debug=IsEventLogging();
2293 root->signature=MagickCoreSignature;
2294 return(&root->root);
2326 assert((xml_info->signature == MagickCoreSignature) ||
2327 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2328 if (IsEventLogging() != MagickFalse)
2329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2331 xml_info->next->sibling=xml_info->sibling;
2334 node=xml_info->parent->child;
2335 if (node == xml_info)
2336 xml_info->parent->child=xml_info->ordered;
2339 while (node->ordered != xml_info)
2341 node->ordered=node->ordered->ordered;
2342 node=xml_info->parent->child;
2343 if (strcmp(node->tag,xml_info->tag) != 0)
2345 while (strcmp(node->sibling->tag,xml_info->tag) != 0)
2347 if (node->sibling != xml_info)
2350 node->sibling=(xml_info->next != (
XMLTreeInfo *) NULL) ?
2351 xml_info->next : node->sibling->sibling;
2354 (node->next != xml_info))
2357 node->next=node->next->next;
2395 const char *tag,
const char *value)
2402 assert((xml_info->signature == MagickCoreSignature) ||
2403 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2404 if (IsEventLogging() != MagickFalse)
2405 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2407 while ((xml_info->attributes[i] != (
char *) NULL) &&
2408 (strcmp(xml_info->attributes[i],tag) != 0))
2410 if (xml_info->attributes[i] == (
char *) NULL)
2415 if (value == (
const char *) NULL)
2417 if (xml_info->attributes != sentinel)
2418 xml_info->attributes=(
char **) ResizeQuantumMemory(
2419 xml_info->attributes,(
size_t) (i+4),
sizeof(*xml_info->attributes));
2422 xml_info->attributes=(
char **) AcquireQuantumMemory(4,
2423 sizeof(*xml_info->attributes));
2424 if (xml_info->attributes != (
char **) NULL)
2425 xml_info->attributes[1]=ConstantString(
"");
2427 if (xml_info->attributes == (
char **) NULL)
2428 ThrowFatalException(ResourceLimitFatalError,
"UnableToAcquireString");
2429 xml_info->attributes[i]=ConstantString(tag);
2430 xml_info->attributes[i+2]=(
char *) NULL;
2431 (void) strlen(xml_info->attributes[i+1]);
2436 for (j=i; xml_info->attributes[j] != (
char *) NULL; j+=2) ;
2437 if (xml_info->attributes[i+1] != (
char *) NULL)
2438 xml_info->attributes[i+1]=DestroyString(xml_info->attributes[i+1]);
2439 if (value != (
const char *) NULL)
2441 xml_info->attributes[i+1]=ConstantString(value);
2444 if (xml_info->attributes[i] != (
char *) NULL)
2445 xml_info->attributes[i]=DestroyString(xml_info->attributes[i]);
2446 (void) memmove(xml_info->attributes+i,xml_info->attributes+i+2,(
size_t)
2447 (j-i)*
sizeof(*xml_info->attributes));
2448 xml_info->attributes=(
char **) ResizeQuantumMemory(xml_info->attributes,
2449 (
size_t) (j+2),
sizeof(*xml_info->attributes));
2450 if (xml_info->attributes == (
char **) NULL)
2451 ThrowFatalException(ResourceLimitFatalError,
"UnableToAcquireString");
2453 (void) memmove(xml_info->attributes[j+1]+(i/2),xml_info->attributes[j+1]+
2454 (i/2)+1,(
size_t) (((j+2)/2)-(i/2))*
sizeof(**xml_info->attributes));
2485 const char *content)
2488 assert((xml_info->signature == MagickCoreSignature) ||
2489 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2490 if (IsEventLogging() != MagickFalse)
2491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2492 if (xml_info->content != (
char *) NULL)
2493 xml_info->content=DestroyString(xml_info->content);
2494 xml_info->content=(
char *) ConstantString(content);
2521static char *EncodePredefinedEntities(
const char *source,ssize_t offset,
2522 char **destination,
size_t *length,
size_t *extent,MagickBooleanType pedantic)
2528 canonical_content=CanonicalXMLContent(source,pedantic);
2534 content=AcquireString(source);
2535 content[offset]=
'\0';
2536 canonical_content=CanonicalXMLContent(content,pedantic);
2537 content=DestroyString(content);
2539 if (canonical_content == (
char *) NULL)
2540 return(*destination);
2541 if ((*length+strlen(canonical_content)+MagickPathExtent) > *extent)
2543 *extent=(*length)+strlen(canonical_content)+MagickPathExtent;
2544 *destination=(
char *) ResizeQuantumMemory(*destination,*extent,
2545 sizeof(**destination));
2546 if (*destination == (
char *) NULL)
2547 return(*destination);
2549 *length+=(size_t) FormatLocaleString(*destination+(*length),*extent,
"%s",
2551 canonical_content=DestroyString(canonical_content);
2552 return(*destination);
2555static char *XMLTreeTagToXML(
XMLTreeInfo *xml_info,
char **source,
size_t *length,
2556 size_t *extent,
size_t start,
char ***attributes)
2571 content=(
char *)
"";
2573 content=xml_info->parent->content;
2575 *source=EncodePredefinedEntities(content+start,(ssize_t) (xml_info->offset-
2576 start),source,length,extent,MagickFalse);
2577 if ((*length+strlen(xml_info->tag)+MagickPathExtent) > *extent)
2579 *extent=(*length)+strlen(xml_info->tag)+MagickPathExtent;
2580 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2581 if (*source == (
char *) NULL)
2584 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
2585 "<%s",xml_info->tag);
2586 for (i=0; xml_info->attributes[i]; i+=2)
2588 attribute=GetXMLTreeAttribute(xml_info,xml_info->attributes[i]);
2589 if (attribute != xml_info->attributes[i+1])
2591 if ((*length+strlen(xml_info->attributes[i])+MagickPathExtent) > *extent)
2593 *extent=(*length)+strlen(xml_info->attributes[i])+MagickPathExtent;
2594 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2595 if (*source == (
char *) NULL)
2596 return((
char *) NULL);
2598 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
" %s=\"",
2599 xml_info->attributes[i]);
2600 (void) EncodePredefinedEntities(xml_info->attributes[i+1],-1,source,length,
2602 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"\"");
2605 while ((attributes[i] != (
char **) NULL) &&
2606 (strcmp(attributes[i][0],xml_info->tag) != 0))
2609 while ((attributes[i] != (
char **) NULL) &&
2610 (attributes[i][j] != (
char *) NULL))
2612 if ((attributes[i][j+1] == (
char *) NULL) ||
2613 (GetXMLTreeAttribute(xml_info,attributes[i][j]) != attributes[i][j+1]))
2618 if ((*length+strlen(attributes[i][j])+MagickPathExtent) > *extent)
2620 *extent=(*length)+strlen(attributes[i][j])+MagickPathExtent;
2621 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2622 if (*source == (
char *) NULL)
2623 return((
char *) NULL);
2625 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
" %s=\"",
2627 (void) EncodePredefinedEntities(attributes[i][j+1],-1,source,length,extent,
2629 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"\"");
2632 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
2633 *xml_info->content ?
">" :
"/>");
2635 *source=XMLTreeTagToXML(xml_info->child,source,length,extent,0,attributes);
2637 *source=EncodePredefinedEntities(xml_info->content,-1,source,length,extent,
2639 if ((*length+strlen(xml_info->tag)+MagickPathExtent) > *extent)
2641 *extent=(*length)+strlen(xml_info->tag)+MagickPathExtent;
2642 *source=(
char *) ResizeQuantumMemory(*source,*extent,
sizeof(**source));
2643 if (*source == (
char *) NULL)
2644 return((
char *) NULL);
2646 if (*xml_info->content !=
'\0')
2647 *length+=(size_t) FormatLocaleString(*source+(*length),*extent,
"</%s>",
2649 while ((offset < xml_info->offset) && (content[offset] !=
'\0'))
2652 content=XMLTreeTagToXML(xml_info->ordered,source,length,extent,offset,
2655 content=EncodePredefinedEntities(content+offset,-1,source,length,extent,
2660MagickExport
char *XMLTreeInfoToXML(
XMLTreeInfo *xml_info)
2684 assert((xml_info->signature == MagickCoreSignature) ||
2685 (((
XMLTreeRoot *) xml_info)->signature == MagickCoreSignature));
2686 if (IsEventLogging() != MagickFalse)
2687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
2688 if (xml_info->tag == (
char *) NULL)
2689 return((
char *) NULL);
2690 xml=AcquireString((
char *) NULL);
2692 extent=MagickPathExtent;
2696 parent=xml_info->parent;
2698 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
2703 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2704 p=root->processing_instructions[i][1];
2705 for (j=1; p != (
char *) NULL; j++)
2707 if (root->processing_instructions[i][k][j-1] ==
'>')
2709 p=root->processing_instructions[i][j];
2712 q=root->processing_instructions[i][0];
2713 if ((length+strlen(p)+strlen(q)+MagickPathExtent) > extent)
2715 extent=length+strlen(p)+strlen(q)+MagickPathExtent;
2716 xml=(
char *) ResizeQuantumMemory(xml,extent,
sizeof(*xml));
2717 if (xml == (
char *) NULL)
2720 length+=(size_t) FormatLocaleString(xml+length,extent,
"<?%s%s%s?>\n",q,
2721 *p !=
'\0' ?
" " :
"",p);
2722 p=root->processing_instructions[i][j];
2725 ordered=xml_info->ordered;
2728 xml=XMLTreeTagToXML(xml_info,&xml,&length,&extent,0,root->attributes);
2729 xml_info->parent=parent;
2730 xml_info->ordered=ordered;
2732 for (i=0; root->processing_instructions[i] != (
char **) NULL; i++)
2737 for (k=2; root->processing_instructions[i][k-1]; k++) ;
2738 p=root->processing_instructions[i][1];
2739 for (j=1; p != (
char *) NULL; j++)
2741 if (root->processing_instructions[i][k][j-1] ==
'<')
2743 p=root->processing_instructions[i][j];
2746 q=root->processing_instructions[i][0];
2747 if ((length+strlen(p)+strlen(q)+MagickPathExtent) > extent)
2749 extent=length+strlen(p)+strlen(q)+MagickPathExtent;
2750 xml=(
char *) ResizeQuantumMemory(xml,extent,
sizeof(*xml));
2751 if (xml == (
char *) NULL)
2754 length+=(size_t) FormatLocaleString(xml+length,extent,
"\n<?%s%s%s?>",q,
2755 *p !=
'\0' ?
" " :
"",p);
2756 p=root->processing_instructions[i][j];
2759 return((
char *) ResizeQuantumMemory(xml,length+1,
sizeof(*xml)));