]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/xml-tree.c
(no commit message)
[imagemagick] / MagickCore / xml-tree.c
index 23f1a9443740629f5c8b60371473c7da414dbba5..9da9c725f2227fbeb45db54de864b7bf99759dcc 100644 (file)
 %                              XML Tree Methods                               %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                               December 2004                                 %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -49,6 +49,7 @@
 */
 #include "MagickCore/studio.h"
 #include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/log.h"
@@ -233,7 +234,8 @@ MagickPrivate XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info,
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   node=xml_info;
   components=GetPathComponents(path,&number_components);
   if (components == (char **) NULL)
@@ -456,7 +458,39 @@ static char **DestroyXMLTreeAttributes(char **attributes)
   return((char **) NULL);
 }
 
-MagickExport XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info)
+static void DestroyXMLTreeChild(XMLTreeInfo *xml_info)
+{
+  XMLTreeInfo
+    *child,
+    *node;
+
+  child=xml_info->child;
+  while(child != (XMLTreeInfo *) NULL)
+  {
+    node=child;
+    child=node->child;
+    node->child=(XMLTreeInfo *) NULL;
+    (void) DestroyXMLTree(node);
+  }
+}
+
+static void DestroyXMLTreeOrdered(XMLTreeInfo *xml_info)
+{
+  XMLTreeInfo
+    *node,
+    *ordered;
+
+  ordered=xml_info->ordered;
+  while(ordered != (XMLTreeInfo *) NULL)
+  {
+    node=ordered;
+    ordered=node->ordered;
+    node->ordered=(XMLTreeInfo *) NULL;
+    (void) DestroyXMLTree(node);
+  }
+}
+
+static void DestroyXMLTreeRoot(XMLTreeInfo *xml_info)
 {
   char
     **attributes;
@@ -473,59 +507,225 @@ MagickExport XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
-  if (xml_info->child != (XMLTreeInfo *) NULL)
-    xml_info->child=DestroyXMLTree(xml_info->child);
-  if (xml_info->ordered != (XMLTreeInfo *) NULL)
-    xml_info->ordered=DestroyXMLTree(xml_info->ordered);
-  if (xml_info->parent == (XMLTreeInfo *) NULL)
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->parent != (XMLTreeInfo *) NULL)
+    return;
+  /*
+    Free root tag allocations.
+  */
+  root=(XMLTreeRoot *) xml_info;
+  for (i=NumberPredefinedEntities; root->entities[i] != (char *) NULL; i+=2)
+    root->entities[i+1]=DestroyString(root->entities[i+1]);
+  root->entities=(char **) RelinquishMagickMemory(root->entities);
+  for (i=0; root->attributes[i] != (char **) NULL; i++)
+  {
+    attributes=root->attributes[i];
+    if (attributes[0] != (char *) NULL)
+      attributes[0]=DestroyString(attributes[0]);
+    for (j=1; attributes[j] != (char *) NULL; j+=3)
+    {
+      if (attributes[j] != (char *) NULL)
+        attributes[j]=DestroyString(attributes[j]);
+      if (attributes[j+1] != (char *) NULL)
+        attributes[j+1]=DestroyString(attributes[j+1]);
+      if (attributes[j+2] != (char *) NULL)
+        attributes[j+2]=DestroyString(attributes[j+2]);
+    }
+    attributes=(char **) RelinquishMagickMemory(attributes);
+  }
+  if (root->attributes[0] != (char **) NULL)
+    root->attributes=(char ***) RelinquishMagickMemory(root->attributes);
+  if (root->processing_instructions[0] != (char **) NULL)
     {
+      for (i=0; root->processing_instructions[i] != (char **) NULL; i++)
+      {
+        for (j=0; root->processing_instructions[i][j] != (char *) NULL; j++)
+          root->processing_instructions[i][j]=DestroyString(
+            root->processing_instructions[i][j]);
+        root->processing_instructions[i][j+1]=DestroyString(
+          root->processing_instructions[i][j+1]);
+        root->processing_instructions[i]=(char **) RelinquishMagickMemory(
+          root->processing_instructions[i]);
+      }
+      root->processing_instructions=(char ***) RelinquishMagickMemory(
+        root->processing_instructions);
+    }
+}
+
+MagickExport XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info)
+{
+  assert(xml_info != (XMLTreeInfo *) NULL);
+  assert((xml_info->signature == MagickSignature) ||
+         (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  DestroyXMLTreeChild(xml_info);
+  DestroyXMLTreeOrdered(xml_info);
+  DestroyXMLTreeRoot(xml_info);
+  xml_info->attributes=DestroyXMLTreeAttributes(xml_info->attributes);
+  xml_info->content=DestroyString(xml_info->content);
+  xml_info->tag=DestroyString(xml_info->tag);
+  xml_info=(XMLTreeInfo *) RelinquishMagickMemory(xml_info);
+  return((XMLTreeInfo *) NULL);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   F i l e T o X M L                                                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  FileToXML() returns the contents of a file as a XML string.
+%
+%  The format of the FileToXML method is:
+%
+%      char *FileToXML(const char *filename,const size_t extent)
+%
+%  A description of each parameter follows:
+%
+%    o filename: the filename.
+%
+%    o extent: Maximum length of the string.
+%
+*/
+
+static inline MagickSizeType MagickMin(const MagickSizeType x,
+  const MagickSizeType y)
+{
+  if (x < y)
+    return(x);
+  return(y);
+}
+
+MagickPrivate char *FileToXML(const char *filename,const size_t extent)
+{
+  char
+    *xml;
+
+  int
+    file;
+
+  MagickOffsetType
+    offset;
+
+  register size_t
+    i;
+
+  size_t
+    length;
+
+  ssize_t
+    count;
+
+  void
+    *map;
+
+  assert(filename != (const char *) NULL);
+  length=0;
+  file=fileno(stdin);
+  if (LocaleCompare(filename,"-") != 0)
+    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+  if (file == -1)
+    return((char *) NULL);
+  offset=(MagickOffsetType) lseek(file,0,SEEK_END);
+  count=0;
+  if ((file == fileno(stdin)) || (offset < 0) ||
+      (offset != (MagickOffsetType) ((ssize_t) offset)))
+    {
+      size_t
+        quantum;
+
+      struct stat
+        file_stats;
+
       /*
-        Free root tag allocations.
+        Stream is not seekable.
       */
-      root=(XMLTreeRoot *) xml_info;
-      for (i=NumberPredefinedEntities; root->entities[i]; i+=2)
-        root->entities[i+1]=DestroyString(root->entities[i+1]);
-      root->entities=(char **) RelinquishMagickMemory(root->entities);
-      for (i=0; root->attributes[i] != (char **) NULL; i++)
+      offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
+      quantum=(size_t) MagickMaxBufferExtent;
+      if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
+        quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
+          MagickMaxBufferExtent);
+      xml=(char *) AcquireQuantumMemory(quantum,sizeof(*xml));
+      for (i=0; xml != (char *) NULL; i+=count)
       {
-        attributes=root->attributes[i];
-        if (attributes[0] != (char *) NULL)
-          attributes[0]=DestroyString(attributes[0]);
-        for (j=1; attributes[j] != (char *) NULL; j+=3)
-        {
-          if (attributes[j] != (char *) NULL)
-            attributes[j]=DestroyString(attributes[j]);
-          if (attributes[j+1] != (char *) NULL)
-            attributes[j+1]=DestroyString(attributes[j+1]);
-          if (attributes[j+2] != (char *) NULL)
-            attributes[j+2]=DestroyString(attributes[j+2]);
-        }
-        attributes=(char **) RelinquishMagickMemory(attributes);
+        count=read(file,xml+i,quantum);
+        if (count <= 0)
+          {
+            count=0;
+            if (errno != EINTR)
+              break;
+          }
+        if (~((size_t) i) < (quantum+1))
+          {
+            xml=(char *) RelinquishMagickMemory(xml);
+            break;
+          }
+        xml=(char *) ResizeQuantumMemory(xml,i+quantum+1,sizeof(*xml));
+        if ((size_t) (i+count) >= extent)
+          break;
       }
-      if (root->attributes[0] != (char **) NULL)
-        root->attributes=(char ***) RelinquishMagickMemory(root->attributes);
-      if (root->processing_instructions[0] != (char **) NULL)
+      if (LocaleCompare(filename,"-") != 0)
+        file=close(file);
+      if (xml == (char *) NULL)
+        return((char *) NULL);
+      if (file == -1)
         {
-          for (i=0; root->processing_instructions[i] != (char **) NULL; i++)
+          xml=(char *) RelinquishMagickMemory(xml);
+          return((char *) NULL);
+        }
+      length=(size_t) MagickMin(i+count,extent);
+      xml[length]='\0';
+      return(xml);
+    }
+  length=(size_t) MagickMin((MagickSizeType) offset,extent);
+  xml=(char *) NULL;
+  if (~length >= (MaxTextExtent-1))
+    xml=(char *) AcquireQuantumMemory(length+MaxTextExtent,sizeof(*xml));
+  if (xml == (char *) NULL)
+    {
+      file=close(file);
+      return((char *) NULL);
+    }
+  map=MapBlob(file,ReadMode,0,length);
+  if (map != (char *) NULL)
+    {
+      (void) memcpy(xml,map,length);
+      (void) UnmapBlob(map,length);
+    }
+  else
+    {
+      (void) lseek(file,0,SEEK_SET);
+      for (i=0; i < length; i+=count)
+      {
+        count=read(file,xml+i,(size_t) MagickMin(length-i,(MagickSizeType)
+          SSIZE_MAX));
+        if (count <= 0)
           {
-            for (j=0; root->processing_instructions[i][j] != (char *) NULL; j++)
-              root->processing_instructions[i][j]=DestroyString(
-                root->processing_instructions[i][j]);
-            root->processing_instructions[i][j+1]=DestroyString(
-              root->processing_instructions[i][j+1]);
-            root->processing_instructions[i]=(char **) RelinquishMagickMemory(
-              root->processing_instructions[i]);
+            count=0;
+            if (errno != EINTR)
+              break;
           }
-          root->processing_instructions=(char ***) RelinquishMagickMemory(
-            root->processing_instructions);
+      }
+      if (i < length)
+        {
+          file=close(file)-1;
+          xml=(char *) RelinquishMagickMemory(xml);
+          return((char *) NULL);
         }
     }
-  xml_info->attributes=DestroyXMLTreeAttributes(xml_info->attributes);
-  xml_info->content=DestroyString(xml_info->content);
-  xml_info->tag=DestroyString(xml_info->tag);
-  xml_info=(XMLTreeInfo *) RelinquishMagickMemory(xml_info);
-  return((XMLTreeInfo *) NULL);
+  xml[length]='\0';
+  if (LocaleCompare(filename,"-") != 0)
+    file=close(file);
+  if (file == -1)
+    xml=(char *) RelinquishMagickMemory(xml);
+  return(xml);
 }
 \f
 /*
@@ -555,7 +755,8 @@ MagickExport XMLTreeInfo *GetNextXMLTreeTag(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   return(xml_info->next);
 }
 \f
@@ -599,7 +800,8 @@ MagickExport const char *GetXMLTreeAttribute(XMLTreeInfo *xml_info,
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   if (xml_info->attributes == (char **) NULL)
     return((const char *) NULL);
   i=0;
@@ -661,7 +863,8 @@ MagickPrivate MagickBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((const XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(attributes != (SplayTreeInfo *) NULL);
   if (xml_info->attributes == (char **) NULL)
     return(MagickTrue);
@@ -707,7 +910,8 @@ MagickExport XMLTreeInfo *GetXMLTreeChild(XMLTreeInfo *xml_info,const char *tag)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   child=xml_info->child;
   if (tag != (const char *) NULL)
     while ((child != (XMLTreeInfo *) NULL) && (strcmp(child->tag,tag) != 0))
@@ -743,7 +947,8 @@ MagickExport const char *GetXMLTreeContent(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   return(xml_info->content);
 }
 \f
@@ -774,7 +979,8 @@ MagickPrivate XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   return(xml_info->ordered);
 }
 \f
@@ -825,7 +1031,8 @@ MagickPrivate XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info,const char *path
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   node=xml_info;
   components=GetPathComponents(path,&number_components);
   if (components == (char **) NULL)
@@ -889,7 +1096,8 @@ MagickPrivate const char **GetXMLTreeProcessingInstructions(
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   root=(XMLTreeRoot *) xml_info;
   while (root->root.parent != (XMLTreeInfo *) NULL)
     root=(XMLTreeRoot *) root->root.parent;
@@ -929,7 +1137,8 @@ MagickExport XMLTreeInfo *GetXMLTreeSibling(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   return(xml_info->sibling);
 }
 \f
@@ -960,7 +1169,8 @@ MagickExport const char *GetXMLTreeTag(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   return(xml_info->tag);
 }
 \f
@@ -1265,39 +1475,42 @@ static char *ParseEntities(char *xml,char **entities,int state)
           if (entities[i++] == (char *) NULL)
             xml++;
           else
-            {
-              /*
-                Found a match.
-              */
-              length=strlen(entities[i]);
-              entity=strchr(xml,';');
-              if ((length-1L) >= (size_t) (entity-xml))
-                {
-                  offset=(ssize_t) (xml-p);
-                  extent=(size_t) (offset+length+strlen(entity));
-                  if (p != q)
-                    p=(char *) ResizeQuantumMemory(p,extent,sizeof(*p));
-                  else
-                    {
-                      char
-                        *xml;
-
-                      xml=(char *) AcquireQuantumMemory(extent,sizeof(*xml));
-                      if (xml != (char *) NULL)
-                        {
-                          (void) CopyMagickString(xml,p,extent*sizeof(*xml));
-                          p=xml;
-                        }
-                    }
-                  if (p == (char *) NULL)
-                    ThrowFatalException(ResourceLimitFatalError,
-                      "MemoryAllocationFailed");
-                  xml=p+offset;
-                  entity=strchr(xml,';');
-                }
-              (void) CopyMagickMemory(xml+length,entity+1,strlen(entity));
-              (void) strncpy(xml,entities[i],length);
-            }
+            if (entities[i] != (char *) NULL)
+              {
+                /*
+                  Found a match.
+                */
+                length=strlen(entities[i]);
+                entity=strchr(xml,';');
+                if ((entity != (char *) NULL) &&
+                    ((length-1L) >= (size_t) (entity-xml)))
+                  {
+                    offset=(ssize_t) (xml-p);
+                    extent=(size_t) (offset+length+strlen(entity));
+                    if (p != q)
+                      p=(char *) ResizeQuantumMemory(p,extent,sizeof(*p));
+                    else
+                      {
+                        char
+                          *xml;
+
+                        xml=(char *) AcquireQuantumMemory(extent,sizeof(*xml));
+                        if (xml != (char *) NULL)
+                          {
+                            (void) CopyMagickString(xml,p,extent*sizeof(*xml));
+                            p=xml;
+                          }
+                      }
+                    if (p == (char *) NULL)
+                      ThrowFatalException(ResourceLimitFatalError,
+                        "MemoryAllocationFailed");
+                    xml=p+offset;
+                    entity=strchr(xml,';');
+                  }
+                if (entity != (char *) NULL)
+                  (void) CopyMagickMemory(xml+length,entity+1,strlen(entity));
+                (void) strncpy(xml,entities[i],length);
+              }
         }
       else
         if (((state == ' ') || (state == '*')) &&
@@ -1338,7 +1551,7 @@ static void ParseCharacterContent(XMLTreeRoot *root,char *xml,
     return;
   xml[length]='\0';
   xml=ParseEntities(xml,root->entities,state);
-  if (*xml_info->content != '\0')
+  if ((xml_info->content != (char *) NULL) && (*xml_info->content != '\0'))
     {
       (void) ConcatenateString(&xml_info->content,xml);
       xml=DestroyString(xml);
@@ -1352,7 +1565,7 @@ static void ParseCharacterContent(XMLTreeRoot *root,char *xml,
 }
 
 static XMLTreeInfo *ParseCloseTag(XMLTreeRoot *root,char *tag,
-  char *magick_unused(xml),ExceptionInfo *exception)
+  ExceptionInfo *exception)
 {
   if ((root->node == (XMLTreeInfo *) NULL) ||
       (root->node->tag == (char *) NULL) || (strcmp(tag,root->node->tag) != 0))
@@ -1383,13 +1596,12 @@ static MagickBooleanType ValidateEntities(char *tag,char *xml,char **entities)
       return(MagickFalse);
     i=0;
     while ((entities[i] != (char *) NULL) &&
-           (strncmp(entities[i],xml+1,strlen(entities[i]) == 0)))
+           (strncmp(entities[i],xml+1,strlen(entities[i])) == 0))
       i+=2;
     if ((entities[i] != (char *) NULL) &&
         (ValidateEntities(tag,entities[i+1],entities) == 0))
       return(MagickFalse);
   }
-  return(MagickTrue);
 }
 
 static void ParseProcessingInstructions(XMLTreeRoot *root,char *xml,
@@ -1460,7 +1672,7 @@ static void ParseProcessingInstructions(XMLTreeRoot *root,char *xml,
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   root->processing_instructions[i][j+2]=(char *) ResizeQuantumMemory(
     root->processing_instructions[i][j+1],(size_t) (j+1),
-    sizeof(**root->processing_instructions));
+    sizeof(*root->processing_instructions));
   if (root->processing_instructions[i][j+2] == (char *) NULL)
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   (void) CopyMagickString(root->processing_instructions[i][j+2]+j-1,
@@ -1573,6 +1785,7 @@ static MagickBooleanType ParseInternalDoctype(XMLTreeRoot *root,char *xml,
             *xml='\0';
             i=0;
             while ((root->attributes[i] != (char **) NULL) &&
+                   (n != (char *) NULL) &&
                    (strcmp(n,root->attributes[i][0]) != 0))
               i++;
             while ((*(n=xml+strspn(xml+1,XMLWhitespace)+1) != '\0') &&
@@ -1698,10 +1911,34 @@ static void ParseOpenTag(XMLTreeRoot *root,char *tag,char **attributes)
     xml_info->tag=ConstantString(tag);
   else
     xml_info=AddChildToXMLTree(xml_info,tag,strlen(xml_info->content));
-  xml_info->attributes=attributes;
+  if (xml_info != (XMLTreeInfo *) NULL)
+    xml_info->attributes=attributes;
   root->node=xml_info;
 }
 
+static const char
+  *ignore_tags[3] =
+  {
+    "rdf:Bag",
+    "rdf:Seq",
+    (const char *) NULL
+  };
+
+static inline MagickBooleanType IsSkipTag(const char *tag)
+{
+  register ssize_t
+    i;
+
+  i=0;
+  while (ignore_tags[i] != (const char *) NULL)
+  {
+    if (LocaleCompare(tag,ignore_tags[i]) == 0)
+      return(MagickTrue);
+    i++;
+  }
+  return(MagickFalse);
+}
+
 MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
 {
   char
@@ -1724,6 +1961,7 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
     i;
 
   size_t
+    ignore_depth,
     length;
 
   ssize_t
@@ -1764,6 +2002,8 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
       return((XMLTreeInfo *) NULL);
     }
   attribute=(char **) NULL;
+  l=0;
+  ignore_depth=0;
   for (p++; ; p++)
   {
     attributes=(char **) sentinel;
@@ -1785,80 +2025,91 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
         p+=strcspn(p,XMLWhitespace "/>");
         while (isspace((int) ((unsigned char) *p)) != 0)
           *p++='\0';
-        if ((*p != '\0') && (*p != '/') && (*p != '>'))
+        if (ignore_depth == 0)
           {
-            /*
-              Find tag in default attributes list.
-            */
-            i=0;
-            while ((root->attributes[i] != (char **) NULL) &&
-                   (strcmp(root->attributes[i][0],tag) != 0))
-              i++;
-            attribute=root->attributes[i];
-          }
-        for (l=0; (*p != '\0') && (*p != '/') && (*p != '>'); l+=2)
-        {
-          /*
-            Attribute.
-          */
-          if (l == 0)
-            attributes=(char **) AcquireQuantumMemory(4,sizeof(*attributes));
-          else
-            attributes=(char **) ResizeQuantumMemory(attributes,(size_t) (l+4),
-              sizeof(*attributes));
-          if (attributes == (char **) NULL)
-            {
-              (void) ThrowMagickException(exception,GetMagickModule(),
-                ResourceLimitError,"MemoryAllocationFailed","`%s'","");
-              utf8=DestroyString(utf8);
-              return(&root->root);
-            }
-          attributes[l+2]=(char *) NULL;
-          attributes[l+1]=(char *) NULL;
-          attributes[l]=p;
-          p+=strcspn(p,XMLWhitespace "=/>");
-          if ((*p != '=') && (isspace((int) ((unsigned char) *p)) == 0))
-            attributes[l]=ConstantString("");
-          else
+            if ((*p != '\0') && (*p != '/') && (*p != '>'))
+              {
+                /*
+                  Find tag in default attributes list.
+                */
+                i=0;
+                while ((root->attributes[i] != (char **) NULL) &&
+                       (strcmp(root->attributes[i][0],tag) != 0))
+                  i++;
+                attribute=root->attributes[i];
+              }
+            for (l=0; (*p != '\0') && (*p != '/') && (*p != '>'); l+=2)
             {
-              *p++='\0';
-              p+=strspn(p,XMLWhitespace "=");
-              c=(*p);
-              if ((c == '"') || (c == '\''))
+              /*
+                Attribute.
+              */
+              if (l == 0)
+                attributes=(char **) AcquireQuantumMemory(4,
+                  sizeof(*attributes));
+              else
+                attributes=(char **) ResizeQuantumMemory(attributes,
+                  (size_t) (l+4),sizeof(*attributes));
+              if (attributes == (char **) NULL)
                 {
-                  /*
-                    Attributes value.
-                  */
-                  p++;
-                  attributes[l+1]=p;
-                  while ((*p != '\0') && (*p != c))
-                    p++;
-                  if (*p != '\0')
-                    *p++='\0';
-                  else
+                  (void) ThrowMagickException(exception,GetMagickModule(),
+                    ResourceLimitError,"MemoryAllocationFailed","`%s'","");
+                  utf8=DestroyString(utf8);
+                  return(&root->root);
+                }
+              attributes[l+2]=(char *) NULL;
+              attributes[l+1]=(char *) NULL;
+              attributes[l]=p;
+              p+=strcspn(p,XMLWhitespace "=/>");
+              if ((*p != '=') && (isspace((int) ((unsigned char) *p)) == 0))
+                attributes[l]=ConstantString("");
+              else
+                {
+                  *p++='\0';
+                  p+=strspn(p,XMLWhitespace "=");
+                  c=(*p);
+                  if ((c == '"') || (c == '\''))
                     {
-                      attributes[l]=ConstantString("");
-                      attributes[l+1]=ConstantString("");
-                      (void) DestroyXMLTreeAttributes(attributes);
-                      (void) ThrowMagickException(exception,GetMagickModule(),
-                        OptionWarning,"ParseError","missing %c",c);
-                      utf8=DestroyString(utf8);
-                      return(&root->root);
+                      /*
+                        Attributes value.
+                      */
+                      p++;
+                      attributes[l+1]=p;
+                      while ((*p != '\0') && (*p != c))
+                        p++;
+                      if (*p != '\0')
+                        *p++='\0';
+                      else
+                        {
+                          attributes[l]=ConstantString("");
+                          attributes[l+1]=ConstantString("");
+                          (void) DestroyXMLTreeAttributes(attributes);
+                          (void) ThrowMagickException(exception,
+                            GetMagickModule(),OptionWarning,"ParseError",
+                            "missing %c",c);
+                          utf8=DestroyString(utf8);
+                          return(&root->root);
+                        }
+                      j=1;
+                      while ((attribute != (char **) NULL) &&
+                             (attribute[j] != (char *) NULL) &&
+                             (strcmp(attribute[j],attributes[l]) != 0))
+                        j+=3;
+                      attributes[l+1]=ParseEntities(attributes[l+1],
+                        root->entities,(attribute != (char **) NULL) &&
+                        (attribute[j] != (char *) NULL) ? *attribute[j+2] :
+                        ' ');
                     }
-                  j=1;
-                  while ((attribute != (char **) NULL) &&
-                         (attribute[j] != (char *) NULL) &&
-                         (strcmp(attribute[j],attributes[l]) != 0))
-                    j+=3;
-                  attributes[l+1]=ParseEntities(attributes[l+1],root->entities,
-                    (attribute != (char **) NULL) && (attribute[j] !=
-                    (char *) NULL) ? *attribute[j+2] : ' ');
+                  attributes[l]=ConstantString(attributes[l]);
                 }
-              attributes[l]=ConstantString(attributes[l]);
+              while (isspace((int) ((unsigned char) *p)) != 0)
+                p++;
             }
-          while (isspace((int) ((unsigned char) *p)) != 0)
-            p++;
-        }
+          }
+        else
+          {
+            while((*p != '\0') && (*p != '/') && (*p != '>'))
+              p++;
+          }
         if (*p == '/')
           {
             /*
@@ -1875,8 +2126,11 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
                 utf8=DestroyString(utf8);
                 return(&root->root);
               }
-            ParseOpenTag(root,tag,attributes);
-            (void) ParseCloseTag(root,tag,p,exception);
+            if ((ignore_depth == 0) && (IsSkipTag(tag) == MagickFalse))
+              {
+                ParseOpenTag(root,tag,attributes);
+                (void) ParseCloseTag(root,tag,exception);
+              }
           }
         else
           {
@@ -1884,7 +2138,10 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
             if ((*p == '>') || ((*p == '\0') && (terminal == '>')))
               {
                 *p='\0';
-                ParseOpenTag(root,tag,attributes);
+                if ((ignore_depth == 0) && (IsSkipTag(tag) == MagickFalse))
+                  ParseOpenTag(root,tag,attributes);
+                else
+                  ignore_depth++;
                 *p=c;
               }
             else
@@ -1915,11 +2172,14 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
               return(&root->root);
             }
           *p='\0';
-          if (ParseCloseTag(root,tag,p,exception) != (XMLTreeInfo *) NULL)
+          if (ignore_depth == 0 && ParseCloseTag(root,tag,exception) !=
+              (XMLTreeInfo *) NULL)
             {
               utf8=DestroyString(utf8);
               return(&root->root);
             }
+          if (ignore_depth > 0)
+            ignore_depth--;
           *p=c;
           if (isspace((int) ((unsigned char) *p)) != 0)
             p+=strspn(p,XMLWhitespace);
@@ -1950,7 +2210,8 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
               if (p != (char *) NULL)
                 {
                   p+=2;
-                  ParseCharacterContent(root,tag+8,(size_t) (p-tag-10),'c');
+                  if (ignore_depth == 0)
+                    ParseCharacterContent(root,tag+8,(size_t) (p-tag-10),'c');
                 }
               else
                 {
@@ -2035,7 +2296,8 @@ MagickExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception)
           p++;
         if (*p == '\0')
           break;
-        ParseCharacterContent(root,tag,(size_t) (p-tag),'&');
+        if (ignore_depth == 0)
+          ParseCharacterContent(root,tag,(size_t) (p-tag),'&');
       }
     else
       if (*p == '\0')
@@ -2142,7 +2404,8 @@ MagickPrivate XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   if (xml_info->next != (XMLTreeInfo *) NULL)
     xml_info->next->sibling=xml_info->sibling;
   if (xml_info->parent != (XMLTreeInfo *) NULL)
@@ -2219,7 +2482,8 @@ MagickPrivate XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   i=0;
   while ((xml_info->attributes[i] != (char *) NULL) &&
          (strcmp(xml_info->attributes[i],tag) != 0))
@@ -2242,8 +2506,7 @@ MagickPrivate XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,
             xml_info->attributes[1]=ConstantString("");
         }
       if (xml_info->attributes == (char **) NULL)
-        ThrowFatalException(ResourceLimitFatalError,
-          "UnableToAcquireString");
+        ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
       xml_info->attributes[i]=ConstantString(tag);
       xml_info->attributes[i+2]=(char *) NULL;
       (void) strlen(xml_info->attributes[i+1]);
@@ -2263,14 +2526,14 @@ MagickPrivate XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,
     xml_info->attributes[i]=DestroyString(xml_info->attributes[i]);
   (void) CopyMagickMemory(xml_info->attributes+i,xml_info->attributes+i+2,
     (size_t) (j-i)*sizeof(*xml_info->attributes));
-  j-=2;
   xml_info->attributes=(char **) ResizeQuantumMemory(xml_info->attributes,
     (size_t) (j+2),sizeof(*xml_info->attributes));
   if (xml_info->attributes == (char **) NULL)
     ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
+  j-=2;
   (void) CopyMagickMemory(xml_info->attributes[j+1]+(i/2),
-    xml_info->attributes[j+1]+(i/2)+1,(size_t) ((j/2)-(i/2))*
-    sizeof(*xml_info->attributes));
+    xml_info->attributes[j+1]+(i/2)+1,(size_t) (((j+2)/2)-(i/2))*
+    sizeof(**xml_info->attributes));
   return(xml_info);
 }
 \f
@@ -2306,7 +2569,8 @@ MagickExport XMLTreeInfo *SetXMLTreeContent(XMLTreeInfo *xml_info,
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   if (xml_info->content != (char *) NULL)
     xml_info->content=DestroyString(xml_info->content);
   xml_info->content=(char *) ConstantString(content);
@@ -2397,7 +2661,7 @@ static char *XMLTreeTagToXML(XMLTreeInfo *xml_info,char **source,size_t *length,
   if ((*length+strlen(xml_info->tag)+MaxTextExtent) > *extent)
     {
       *extent=(*length)+strlen(xml_info->tag)+MaxTextExtent;
-      *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(*source));
+      *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source));
       if (*source == (char *) NULL)
         return(*source);
     }
@@ -2506,7 +2770,8 @@ MagickExport char *XMLTreeInfoToXML(XMLTreeInfo *xml_info)
   assert(xml_info != (XMLTreeInfo *) NULL);
   assert((xml_info->signature == MagickSignature) ||
          (((XMLTreeRoot *) xml_info)->signature == MagickSignature));
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  if (xml_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   if (xml_info->tag == (char *) NULL)
     return((char *) NULL);
   xml=AcquireString((char *) NULL);