Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gnulib-local / lib / libxml / entities.c
index 91a3978..a72afb3 100644 (file)
 #include <libxml/globals.h>
 #include <libxml/dict.h>
 
+#include "save.h"
+
 /*
  * The XML predefined entities.
  */
 
 static xmlEntity xmlEntityLt = {
     NULL, XML_ENTITY_DECL, BAD_CAST "lt",
-    NULL, NULL, NULL, NULL, NULL, NULL, 
+    NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "<", BAD_CAST "<", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
     NULL, NULL, NULL, NULL, 0, 1
 };
 static xmlEntity xmlEntityGt = {
     NULL, XML_ENTITY_DECL, BAD_CAST "gt",
-    NULL, NULL, NULL, NULL, NULL, NULL, 
+    NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST ">", BAD_CAST ">", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
     NULL, NULL, NULL, NULL, 0, 1
 };
 static xmlEntity xmlEntityAmp = {
     NULL, XML_ENTITY_DECL, BAD_CAST "amp",
-    NULL, NULL, NULL, NULL, NULL, NULL, 
+    NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "&", BAD_CAST "&", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
     NULL, NULL, NULL, NULL, 0, 1
 };
 static xmlEntity xmlEntityQuot = {
     NULL, XML_ENTITY_DECL, BAD_CAST "quot",
-    NULL, NULL, NULL, NULL, NULL, NULL, 
+    NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "\"", BAD_CAST "\"", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
     NULL, NULL, NULL, NULL, 0, 1
 };
 static xmlEntity xmlEntityApos = {
     NULL, XML_ENTITY_DECL, BAD_CAST "apos",
-    NULL, NULL, NULL, NULL, NULL, NULL, 
+    NULL, NULL, NULL, NULL, NULL, NULL,
     BAD_CAST "'", BAD_CAST "'", 1,
     XML_INTERNAL_PREDEFINED_ENTITY,
     NULL, NULL, NULL, NULL, 0, 1
@@ -139,45 +141,19 @@ xmlFreeEntity(xmlEntityPtr entity)
 }
 
 /*
- * xmlAddEntity : register a new entity for an entities table.
+ * xmlCreateEntity:
+ *
+ * internal routine doing the entity node strutures allocations
  */
 static xmlEntityPtr
-xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
-         const xmlChar *ExternalID, const xmlChar *SystemID,
-         const xmlChar *content) {
-    xmlDictPtr dict = NULL;
-    xmlEntitiesTablePtr table = NULL;
+xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
+               const xmlChar *ExternalID, const xmlChar *SystemID,
+               const xmlChar *content) {
     xmlEntityPtr ret;
 
-    if (name == NULL)
-       return(NULL);
-    if (dtd == NULL)
-       return(NULL);
-    if (dtd->doc != NULL)
-        dict = dtd->doc->dict;
-
-    switch (type) {
-        case XML_INTERNAL_GENERAL_ENTITY:
-        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
-        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
-           if (dtd->entities == NULL)
-               dtd->entities = xmlHashCreateDict(0, dict);
-           table = dtd->entities;
-           break;
-        case XML_INTERNAL_PARAMETER_ENTITY:
-        case XML_EXTERNAL_PARAMETER_ENTITY:
-           if (dtd->pentities == NULL)
-               dtd->pentities = xmlHashCreateDict(0, dict);
-           table = dtd->pentities;
-           break;
-        case XML_INTERNAL_PREDEFINED_ENTITY:
-           return(NULL);
-    }
-    if (table == NULL)
-       return(NULL);
     ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
     if (ret == NULL) {
-        xmlEntitiesErrMemory("xmlAddEntity:: malloc failed");
+        xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
        return(NULL);
     }
     memset(ret, 0, sizeof(xmlEntity));
@@ -216,6 +192,50 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
                        the defining entity */
     ret->orig = NULL;
     ret->owner = 0;
+
+    return(ret);
+}
+
+/*
+ * xmlAddEntity : register a new entity for an entities table.
+ */
+static xmlEntityPtr
+xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
+         const xmlChar *ExternalID, const xmlChar *SystemID,
+         const xmlChar *content) {
+    xmlDictPtr dict = NULL;
+    xmlEntitiesTablePtr table = NULL;
+    xmlEntityPtr ret;
+
+    if (name == NULL)
+       return(NULL);
+    if (dtd == NULL)
+       return(NULL);
+    if (dtd->doc != NULL)
+        dict = dtd->doc->dict;
+
+    switch (type) {
+        case XML_INTERNAL_GENERAL_ENTITY:
+        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
+        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
+           if (dtd->entities == NULL)
+               dtd->entities = xmlHashCreateDict(0, dict);
+           table = dtd->entities;
+           break;
+        case XML_INTERNAL_PARAMETER_ENTITY:
+        case XML_EXTERNAL_PARAMETER_ENTITY:
+           if (dtd->pentities == NULL)
+               dtd->pentities = xmlHashCreateDict(0, dict);
+           table = dtd->pentities;
+           break;
+        case XML_INTERNAL_PREDEFINED_ENTITY:
+           return(NULL);
+    }
+    if (table == NULL)
+       return(NULL);
+    ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
+    if (ret == NULL)
+        return(NULL);
     ret->doc = dtd->doc;
 
     if (xmlHashAddEntry(table, name, ret)) {
@@ -363,6 +383,44 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
 }
 
 /**
+ * xmlNewEntity:
+ * @doc:  the document
+ * @name:  the entity name
+ * @type:  the entity type XML_xxx_yyy_ENTITY
+ * @ExternalID:  the entity external ID if available
+ * @SystemID:  the entity system ID if available
+ * @content:  the entity content
+ *
+ * Create a new entity, this differs from xmlAddDocEntity() that if
+ * the document is NULL or has no internal subset defined, then an
+ * unlinked entity structure will be returned, it is then the responsability
+ * of the caller to link it to the document later or free it when not needed
+ * anymore.
+ *
+ * Returns a pointer to the entity or NULL in case of error
+ */
+xmlEntityPtr
+xmlNewEntity(xmlDocPtr doc, const xmlChar *name, int type,
+            const xmlChar *ExternalID, const xmlChar *SystemID,
+            const xmlChar *content) {
+    xmlEntityPtr ret;
+    xmlDictPtr dict;
+
+    if ((doc != NULL) && (doc->intSubset != NULL)) {
+       return(xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content));
+    }
+    if (doc != NULL)
+        dict = doc->dict;
+    else
+        dict = NULL;
+    ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
+    if (ret == NULL)
+        return(NULL);
+    ret->doc = doc;
+    return(ret);
+}
+
+/**
  * xmlGetEntityFromTable:
  * @table:  an entity table
  * @name:  the entity name
@@ -370,7 +428,7 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
  *
  * Do an entity lookup in the table.
  * returns the corresponding parameter entity, if found.
- * 
+ *
  * Returns A pointer to the entity structure or NULL if not found.
  */
 static xmlEntityPtr
@@ -385,7 +443,7 @@ xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) {
  *
  * Do an entity lookup in the internal and external subsets and
  * returns the corresponding parameter entity, if found.
- * 
+ *
  * Returns A pointer to the entity structure or NULL if not found.
  */
 xmlEntityPtr
@@ -416,7 +474,7 @@ xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
  * Do an entity lookup in the DTD entity hash table and
  * returns the corresponding entity, if found.
  * Note: the first argument is the document node, not the DTD node.
- * 
+ *
  * Returns A pointer to the entity structure or NULL if not found.
  */
 xmlEntityPtr
@@ -440,11 +498,11 @@ xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
  * Do an entity lookup in the document entity hash table and
  * returns the corresponding entity, otherwise a lookup is done
  * in the predefined entities too.
- * 
+ *
  * Returns A pointer to the entity structure or NULL if not found.
  */
 xmlEntityPtr
-xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
+xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name) {
     xmlEntityPtr cur;
     xmlEntitiesTablePtr table;
 
@@ -472,20 +530,20 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
  * Macro used to grow the current buffer.
  */
 #define growBufferReentrant() {                                                \
-    buffer_size *= 2;                                                  \
-    buffer = (xmlChar *)                                               \
-               xmlRealloc(buffer, buffer_size * sizeof(xmlChar));      \
-    if (buffer == NULL) {                                              \
-        xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\
-       return(NULL);                                                   \
-    }                                                                  \
+    xmlChar *tmp;                                                       \
+    size_t new_size = buffer_size * 2;                                  \
+    if (new_size < buffer_size) goto mem_error;                         \
+    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                    \
+    if (tmp == NULL) goto mem_error;                                    \
+    buffer = tmp;                                                      \
+    buffer_size = new_size;                                            \
 }
 
-
 /**
- * xmlEncodeEntitiesReentrant:
+ * xmlEncodeEntitiesInternal:
  * @doc:  the document containing the string
  * @input:  A string to convert to XML.
+ * @attr: are we handling an atrbute value
  *
  * Do a global encoding of a string, replacing the predefined entities
  * and non ASCII values with their entities and CharRef counterparts.
@@ -494,12 +552,12 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
  *
  * Returns A newly allocated string with the substitution done.
  */
-xmlChar *
-xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
+static xmlChar *
+xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
     const xmlChar *cur = input;
     xmlChar *buffer = NULL;
     xmlChar *out = NULL;
-    int buffer_size = 0;
+    size_t buffer_size = 0;
     int html = 0;
 
     if (input == NULL) return(NULL);
@@ -512,14 +570,14 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
     buffer_size = 1000;
     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
     if (buffer == NULL) {
-        xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: malloc failed");
+        xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed");
        return(NULL);
     }
     out = buffer;
 
     while (*cur != '\0') {
-        if (out - buffer > buffer_size - 100) {
-           int indx = out - buffer;
+        size_t indx = out - buffer;
+        if (indx + 100 > buffer_size) {
 
            growBufferReentrant();
            out = &buffer[indx];
@@ -529,6 +587,27 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
         * By default one have to encode at least '<', '>', '"' and '&' !
         */
        if (*cur == '<') {
+           const xmlChar *end;
+
+           /*
+            * Special handling of server side include in HTML attributes
+            */
+           if (html && attr &&
+               (cur[1] == '!') && (cur[2] == '-') && (cur[3] == '-') &&
+               ((end = xmlStrstr(cur, BAD_CAST "-->")) != NULL)) {
+               while (cur != end) {
+                   *out++ = *cur++;
+                   indx = out - buffer;
+                   if (indx + 100 > buffer_size) {
+                       growBufferReentrant();
+                       out = &buffer[indx];
+                   }
+               }
+               *out++ = *cur++;
+               *out++ = *cur++;
+               *out++ = *cur++;
+               continue;
+           }
            *out++ = '&';
            *out++ = 'l';
            *out++ = 't';
@@ -539,6 +618,23 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
            *out++ = 't';
            *out++ = ';';
        } else if (*cur == '&') {
+           /*
+            * Special handling of &{...} construct from HTML 4, see
+            * http://www.w3.org/TR/html401/appendix/notes.html#h-B.7.1
+            */
+           if (html && attr && (cur[1] == '{') &&
+               (strchr((const char *) cur, '}'))) {
+               while (*cur != '}') {
+                   *out++ = *cur++;
+                   indx = out - buffer;
+                   if (indx + 100 > buffer_size) {
+                       growBufferReentrant();
+                       out = &buffer[indx];
+                   }
+               }
+               *out++ = *cur++;
+               continue;
+           }
            *out++ = '&';
            *out++ = 'a';
            *out++ = 'm';
@@ -553,7 +649,7 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
        } else if (*cur >= 0x80) {
            if (((doc != NULL) && (doc->encoding != NULL)) || (html)) {
                /*
-                * Bjørn Reese <br@sseusa.com> provided the patch
+                * Bjørn Reese <br@sseusa.com> provided the patch
                xmlChar xc;
                xc = (*cur & 0x3F) << 6;
                if (cur[1] != 0) {
@@ -571,7 +667,7 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
 
                if (*cur < 0xC0) {
                    xmlEntitiesErr(XML_CHECK_NOT_UTF8,
-                           "xmlEncodeEntitiesReentrant : input not UTF-8");
+                           "xmlEncodeEntities: input not UTF-8");
                    if (doc != NULL)
                        doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    snprintf(buf, sizeof(buf), "&#%d;", *cur);
@@ -604,7 +700,7 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
                }
                if ((l == 1) || (!IS_CHAR(val))) {
                    xmlEntitiesErr(XML_ERR_INVALID_CHAR,
-                       "xmlEncodeEntitiesReentrant : char out of range\n");
+                       "xmlEncodeEntities: char out of range\n");
                    if (doc != NULL)
                        doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    snprintf(buf, sizeof(buf), "&#%d;", *cur);
@@ -634,8 +730,46 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
        }
        cur++;
     }
-    *out++ = 0;
+    *out = 0;
     return(buffer);
+
+mem_error:
+    xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed");
+    xmlFree(buffer);
+    return(NULL);
+}
+
+/**
+ * xmlEncodeAttributeEntities:
+ * @doc:  the document containing the string
+ * @input:  A string to convert to XML.
+ *
+ * Do a global encoding of a string, replacing the predefined entities
+ * and non ASCII values with their entities and CharRef counterparts for
+ * attribute values.
+ *
+ * Returns A newly allocated string with the substitution done.
+ */
+xmlChar *
+xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input) {
+    return xmlEncodeEntitiesInternal(doc, input, 1);
+}
+
+/**
+ * xmlEncodeEntitiesReentrant:
+ * @doc:  the document containing the string
+ * @input:  A string to convert to XML.
+ *
+ * Do a global encoding of a string, replacing the predefined entities
+ * and non ASCII values with their entities and CharRef counterparts.
+ * Contrary to xmlEncodeEntities, this routine is reentrant, and result
+ * must be deallocated.
+ *
+ * Returns A newly allocated string with the substitution done.
+ */
+xmlChar *
+xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
+    return xmlEncodeEntitiesInternal(doc, input, 0);
 }
 
 /**
@@ -649,11 +783,11 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
  * Returns A newly allocated string with the substitution done.
  */
 xmlChar *
-xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
+xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input) {
     const xmlChar *cur = input;
     xmlChar *buffer = NULL;
     xmlChar *out = NULL;
-    int buffer_size = 0;
+    size_t buffer_size = 0;
     if (input == NULL) return(NULL);
 
     /*
@@ -668,8 +802,8 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
     out = buffer;
 
     while (*cur != '\0') {
-        if (out - buffer > buffer_size - 10) {
-           int indx = out - buffer;
+        size_t indx = out - buffer;
+        if (indx + 10 > buffer_size) {
 
            growBufferReentrant();
            out = &buffer[indx];
@@ -716,8 +850,13 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
        }
        cur++;
     }
-    *out++ = 0;
+    *out = 0;
     return(buffer);
+
+mem_error:
+    xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
+    xmlFree(buffer);
+    return(NULL);
 }
 
 /**
@@ -764,7 +903,7 @@ xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
  * @ent:  An entity
  *
  * Build a copy of an entity
- * 
+ *
  * Returns the new xmlEntitiesPtr or NULL in case of error.
  */
 static xmlEntityPtr
@@ -800,7 +939,7 @@ xmlCopyEntity(xmlEntityPtr ent) {
  * @table:  An entity table
  *
  * Build a copy of an entity table.
- * 
+ *
  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
  */
 xmlEntitiesTablePtr
@@ -949,7 +1088,7 @@ static void
 xmlDumpEntityDeclScan(xmlEntityPtr ent, xmlBufferPtr buf) {
     xmlDumpEntityDecl(buf, ent);
 }
-      
+
 /**
  * xmlDumpEntitiesTable:
  * @buf:  An XML buffer.