#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
}
/*
- * 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));
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)) {
}
/**
+ * 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
*
* 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
*
* 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
* 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
* 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;
* 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.
*
* 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);
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];
* 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';
*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';
} 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) {
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);
}
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);
}
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);
}
/**
* 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);
/*
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];
}
cur++;
}
- *out++ = 0;
+ *out = 0;
return(buffer);
+
+mem_error:
+ xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
+ xmlFree(buffer);
+ return(NULL);
}
/**
* @ent: An entity
*
* Build a copy of an entity
- *
+ *
* Returns the new xmlEntitiesPtr or NULL in case of error.
*/
static xmlEntityPtr
* @table: An entity table
*
* Build a copy of an entity table.
- *
+ *
* Returns the new xmlEntitiesTablePtr or NULL in case of error.
*/
xmlEntitiesTablePtr
xmlDumpEntityDeclScan(xmlEntityPtr ent, xmlBufferPtr buf) {
xmlDumpEntityDecl(buf, ent);
}
-
+
/**
* xmlDumpEntitiesTable:
* @buf: An XML buffer.