Imported Upstream version 2.9.1
[platform/upstream/libxml2.git] / xinclude.c
index d01f978..ace005b 100644 (file)
@@ -26,6 +26,7 @@
 #ifdef LIBXML_XINCLUDE_ENABLED
 #include <libxml/xinclude.h>
 
+#include "buf.h"
 
 #define XINCLUDE_MAX_DEPTH 40
 
@@ -92,7 +93,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
 
 /************************************************************************
  *                                                                     *
- *                     XInclude error handler                          *
+ *                     XInclude error handler                          *
  *                                                                     *
  ************************************************************************/
 
@@ -412,7 +413,7 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
  * xmlXIncludeParseFile:
  * @ctxt:  the XInclude context
  * @URL:  the URL or file path
- * 
+ *
  * parse a document for XInclude
  */
 static xmlDocPtr
@@ -433,7 +434,7 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
      * pass in the application data to the parser context.
      */
     pctxt->_private = ctxt->_private;
-    
+
     /*
      * try to ensure that new documents included are actually
      * built with the same dictionary as the including document.
@@ -446,7 +447,7 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
     }
 
     xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
-    
+
     inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
     if (inputStream == NULL) {
        xmlFreeParserCtxt(pctxt);
@@ -472,7 +473,7 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
         pctxt->myDoc = NULL;
     }
     xmlFreeParserCtxt(pctxt);
-    
+
     return(ret);
 }
 
@@ -480,7 +481,7 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
  * xmlXIncludeAddNode:
  * @ctxt:  the XInclude context
  * @cur:  the new node
- * 
+ *
  * Add a new node to process to an XInclude context
  */
 static int
@@ -511,7 +512,7 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
     href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
     if (href == NULL) {
        href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
-       if (href == NULL) 
+       if (href == NULL)
            return(-1);
     }
     if ((href[0] == '#') || (href[0] == 0))
@@ -655,7 +656,7 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
  * @ctxt:  the XInclude context
  * @doc:  the new document
  * @url:  the associated URL
- * 
+ *
  * The XInclude recursive nature is handled at this point.
  */
 static void
@@ -684,7 +685,7 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
        /*
         * Copy the private user data
         */
-       newctxt->_private = ctxt->_private;     
+       newctxt->_private = ctxt->_private;
        /*
         * Copy the existing document set
         */
@@ -749,7 +750,7 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
  * @ctxt:  the XInclude context
  * @txt:  the new text node
  * @url:  the associated URL
- * 
+ *
  * Add a new txtument to the list
  */
 static void
@@ -808,7 +809,7 @@ xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
  * @target:  the document target
  * @source:  the document source
  * @elem:  the element
- * 
+ *
  * Make a copy of the node while preserving the XInclude semantic
  * of the Infoset copy
  */
@@ -835,7 +836,7 @@ xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
  * @target:  the document target
  * @source:  the document source
  * @elem:  the element list
- * 
+ *
  * Make a copy of the node list while preserving the XInclude semantic
  * of the Infoset copy
  */
@@ -874,11 +875,11 @@ xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
 static xmlNodePtr
 xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
     int i;
-    if (cur == NULL) 
-       return(cur);
+    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
+        return(NULL);
     cur = cur->children;
     for (i = 0;i <= no;cur = cur->next) {
-       if (cur == NULL) 
+       if (cur == NULL)
            return(cur);
        if ((cur->type == XML_ELEMENT_NODE) ||
            (cur->type == XML_DOCUMENT_NODE) ||
@@ -922,11 +923,13 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
        return(NULL);
     start = (xmlNodePtr) range->user;
 
-    if (start == NULL)
+    if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
        return(NULL);
     end = range->user2;
     if (end == NULL)
        return(xmlDocCopyNode(start, target, 1));
+    if (end->type == XML_NAMESPACE_DECL)
+        return(NULL);
 
     cur = start;
     index1 = range->index;
@@ -985,7 +988,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                /* prune and return full set */
                if (level == lastLevel)
                    xmlAddNextSibling(last, tmp);
-               else 
+               else
                    xmlAddChild(last, tmp);
                return(list);
            } else {    /* ending node not a text node */
@@ -1289,7 +1292,7 @@ xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data,
        if (prev != NULL) {
            if (ent->etype != prev->etype)
                goto error;
-       
+
            if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
                if (!xmlStrEqual(ent->SystemID, prev->SystemID))
                    goto error;
@@ -1389,7 +1392,7 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
  * @ctxt:  the XInclude context
  * @url:  the associated URL
  * @nr:  the xinclude node number
- * 
+ *
  * Load the document, and store the result in the XInclude context
  *
  * Returns 0 in case of success, -1 in case of failure
@@ -1413,7 +1416,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
      */
     uri = xmlParseURI((const char *)url);
     if (uri == NULL) {
-       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                       XML_XINCLUDE_HREF_URI,
                       "invalid value URI %s\n", url);
        return(-1);
@@ -1431,7 +1434,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
     xmlFreeURI(uri);
     if (URL == NULL) {
         if (ctxt->incTab != NULL)
-           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                           XML_XINCLUDE_HREF_URI,
                           "invalid value URI %s\n", url);
        else
@@ -1550,7 +1553,7 @@ loaded:
            ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
                                                       doc, doc->children);
        }
-    } 
+    }
 #ifdef LIBXML_XPTR_ENABLED
     else {
        /*
@@ -1568,7 +1571,7 @@ loaded:
            xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
        }
        if (xptrctxt == NULL) {
-           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                           XML_XINCLUDE_XPTR_FAILED,
                           "could not create XPointer context\n", NULL);
            xmlFree(URL);
@@ -1594,7 +1597,7 @@ loaded:
            case XPATH_POINT:
            case XPATH_USERS:
            case XPATH_XSLT_TREE:
-               xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+               xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                               XML_XINCLUDE_XPTR_RESULT,
                               "XPointer is not a range: #%s\n",
                               fragment);
@@ -1636,14 +1639,14 @@ loaded:
                        continue;
 
                    case XML_ATTRIBUTE_NODE:
-                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                                       XML_XINCLUDE_XPTR_RESULT,
                                       "XPointer selects an attribute: #%s\n",
                                       fragment);
                        set->nodeTab[i] = NULL;
                        continue;
                    case XML_NAMESPACE_DECL:
-                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                                       XML_XINCLUDE_XPTR_RESULT,
                                       "XPointer selects a namespace: #%s\n",
                                       fragment);
@@ -1658,7 +1661,7 @@ loaded:
                    case XML_ENTITY_DECL:
                    case XML_XINCLUDE_START:
                    case XML_XINCLUDE_END:
-                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+                       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                                       XML_XINCLUDE_XPTR_RESULT,
                                   "XPointer selects unexpected nodes: #%s\n",
                                       fragment);
@@ -1704,7 +1707,7 @@ loaded:
             */
            curBase = xmlBuildRelativeURI(URL, ctxt->base);
            if (curBase == NULL) {      /* Error return */
-               xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+               xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                       XML_XINCLUDE_HREF_URI,
                       "trying to build relative URI from %s\n", URL);
            } else {
@@ -1745,7 +1748,7 @@ loaded:
                                xmlChar *relBase;
                                relBase = xmlBuildURI(xmlBase, base);
                                if (relBase == NULL) { /* error */
-                                   xmlXIncludeErr(ctxt, 
+                                   xmlXIncludeErr(ctxt,
                                                ctxt->incTab[nr]->ref,
                                                XML_XINCLUDE_HREF_URI,
                                        "trying to rebuild base from %s\n",
@@ -1782,7 +1785,7 @@ loaded:
  * @ctxt:  the XInclude context
  * @url:  the associated URL
  * @nr:  the xinclude node number
- * 
+ *
  * Load the content, and store the result in the XInclude context
  *
  * Returns 0 in case of success, -1 in case of failure
@@ -1798,6 +1801,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
     xmlCharEncoding enc = (xmlCharEncoding) 0;
     xmlParserCtxtPtr pctxt;
     xmlParserInputPtr inputStream;
+    int xinclude_multibyte_fallback_used = 0;
 
     /*
      * Check the URL and remove any fragment identifier
@@ -1828,7 +1832,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
      * directly through ctxt->doc.
      */
     if (URL[0] == 0) {
-       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                       XML_XINCLUDE_TEXT_DOCUMENT,
                       "text serialization of document not available\n", NULL);
        xmlFree(URL);
@@ -1894,30 +1898,39 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
     /*
      * Scan all chars from the resource and add the to the node
      */
+xinclude_multibyte_fallback:
     while (xmlParserInputBufferRead(buf, 128) > 0) {
        int len;
        const xmlChar *content;
 
-       content = xmlBufferContent(buf->buffer);
-       len = xmlBufferLength(buf->buffer);
+       content = xmlBufContent(buf->buffer);
+       len = xmlBufLength(buf->buffer);
        for (i = 0;i < len;) {
            int cur;
            int l;
 
            cur = xmlStringCurrentChar(NULL, &content[i], &l);
            if (!IS_CHAR(cur)) {
-               xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
-                              XML_XINCLUDE_INVALID_CHAR,
-                              "%s contains invalid char\n", URL);
-               xmlFreeParserInputBuffer(buf);
-               xmlFree(URL);
-               return(-1);
+               /* Handle splitted multibyte char at buffer boundary */
+               if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) {
+                   xinclude_multibyte_fallback_used = 1;
+                   xmlBufShrink(buf->buffer, i);
+                   goto xinclude_multibyte_fallback;
+               } else {
+                   xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
+                                  XML_XINCLUDE_INVALID_CHAR,
+                                  "%s contains invalid char\n", URL);
+                   xmlFreeParserInputBuffer(buf);
+                   xmlFree(URL);
+                   return(-1);
+               }
            } else {
+               xinclude_multibyte_fallback_used = 0;
                xmlNodeAddContentLen(node, &content[i], l);
            }
            i += l;
        }
-       xmlBufferShrink(buf->buffer, len);
+       xmlBufShrink(buf->buffer, len);
     }
     xmlFreeParserCtxt(pctxt);
     xmlXIncludeAddTxt(ctxt, node, URL);
@@ -1937,7 +1950,7 @@ loaded:
  * @ctxt:  the XInclude context
  * @fallback:  the fallback node
  * @nr:  the xinclude node number
- * 
+ *
  * Load the content of the fallback node, and store the result
  * in the XInclude context
  *
@@ -1947,8 +1960,9 @@ static int
 xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
     xmlXIncludeCtxtPtr newctxt;
     int ret = 0;
-    
-    if ((fallback == NULL) || (ctxt == NULL))
+
+    if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
+        (ctxt == NULL))
        return(-1);
     if (fallback->children != NULL) {
        /*
@@ -2033,7 +2047,7 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
     href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
     if (href == NULL) {
        href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
-       if (href == NULL) 
+       if (href == NULL)
            return(-1);
     }
     parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
@@ -2078,7 +2092,7 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
            xmlFree(eschref);
     }
     if (URI == NULL) {
-       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                       XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
        if (parse != NULL)
            xmlFree(parse);
@@ -2111,7 +2125,7 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
      * Restore the original base before checking for fallback
      */
     ctxt->base = oldBase;
-    
+
     if (ret < 0) {
        xmlNodePtr children;
 
@@ -2129,14 +2143,14 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
                ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
                 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
                ret = xmlXIncludeLoadFallback(ctxt, children, nr);
-               if (ret == 0) 
+               if (ret == 0)
                    break;
            }
            children = children->next;
        }
     }
     if (ret < 0) {
-       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+       xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                       XML_XINCLUDE_NO_FALLBACK,
                       "could not load %s, and no fallback was found\n",
                       URI);
@@ -2174,7 +2188,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
     if ((nr < 0) || (nr >= ctxt->incNr))
        return(-1);
     cur = ctxt->incTab[nr]->ref;
-    if (cur == NULL)
+    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
        return(-1);
 
     /*
@@ -2205,7 +2219,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
            tmp = tmp->next;
        }
        if (nb_elem > 1) {
-           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 
+           xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                           XML_XINCLUDE_MULTIPLE_ROOT,
                       "XInclude error: would result in multiple root nodes\n",
                           NULL);
@@ -2252,7 +2266,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
        }
     }
 
-    
+
     return(0);
 }
 
@@ -2349,7 +2363,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
     int ret = 0;
     int i, start;
 
-    if ((doc == NULL) || (tree == NULL))
+    if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
        return(-1);
     if (ctxt == NULL)
        return(-1);
@@ -2463,7 +2477,8 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
     xmlXIncludeCtxtPtr ctxt;
     int ret = 0;
 
-    if ((tree == NULL) || (tree->doc == NULL))
+    if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
+        (tree->doc == NULL))
         return(-1);
 
     ctxt = xmlXIncludeNewContext(tree->doc);
@@ -2548,7 +2563,8 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
     xmlXIncludeCtxtPtr ctxt;
     int ret = 0;
 
-    if ((tree == NULL) || (tree->doc == NULL))
+    if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
+        (tree->doc == NULL))
        return(-1);
     ctxt = xmlXIncludeNewContext(tree->doc);
     if (ctxt == NULL)
@@ -2592,7 +2608,8 @@ int
 xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
     int ret = 0;
 
-    if ((node == NULL) || (node->doc == NULL) || (ctxt == NULL))
+    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
+        (node->doc == NULL) || (ctxt == NULL))
        return(-1);
     ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
     if ((ret >= 0) && (ctxt->nbErrors > 0))