| /* |
| * entities.c : implementation for the XML entities handking |
| * |
| * See Copyright for the status of this software. |
| * |
| * Daniel.Veillard@w3.org |
| */ |
| |
| #ifdef WIN32 |
| #include "win32config.h" |
| #else |
| #include "config.h" |
| #endif |
| |
| #include <stdio.h> |
| #include <string.h> |
| #ifdef HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #include "xmlmemory.h" |
| #include "entities.h" |
| #include "parser.h" |
| |
| /* |
| * The XML predefined entities. |
| */ |
| |
| struct xmlPredefinedEntityValue { |
| const char *name; |
| const char *value; |
| }; |
| struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = { |
| { "lt", "<" }, |
| { "gt", ">" }, |
| { "apos", "'" }, |
| { "quot", "\"" }, |
| { "amp", "&" } |
| }; |
| |
| xmlEntitiesTablePtr xmlPredefinedEntities = NULL; |
| |
| /* |
| * xmlFreeEntity : clean-up an entity record. |
| */ |
| void xmlFreeEntity(xmlEntityPtr entity) { |
| if (entity == NULL) return; |
| |
| if (entity->name != NULL) |
| xmlFree((char *) entity->name); |
| if (entity->ExternalID != NULL) |
| xmlFree((char *) entity->ExternalID); |
| if (entity->SystemID != NULL) |
| xmlFree((char *) entity->SystemID); |
| if (entity->content != NULL) |
| xmlFree((char *) entity->content); |
| if (entity->orig != NULL) |
| xmlFree((char *) entity->orig); |
| memset(entity, -1, sizeof(xmlEntity)); |
| } |
| |
| /* |
| * xmlAddEntity : register a new entity for an entities table. |
| */ |
| static void |
| xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type, |
| const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { |
| int i; |
| xmlEntityPtr cur; |
| int len; |
| |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if (!xmlStrcmp(cur->name, name)) { |
| /* |
| * The entity is already defined in this Dtd, the spec says to NOT |
| * override it ... Is it worth a Warning ??? !!! |
| * Not having a cprinting context this seems hard ... |
| */ |
| if (((type == XML_INTERNAL_PARAMETER_ENTITY) || |
| (type == XML_EXTERNAL_PARAMETER_ENTITY)) && |
| ((cur->type == XML_INTERNAL_PARAMETER_ENTITY) || |
| (cur->type == XML_EXTERNAL_PARAMETER_ENTITY))) |
| return; |
| else |
| if (((type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (type != XML_EXTERNAL_PARAMETER_ENTITY)) && |
| ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (cur->type != XML_EXTERNAL_PARAMETER_ENTITY))) |
| return; |
| } |
| } |
| if (table->nb_entities >= table->max_entities) { |
| /* |
| * need more elements. |
| */ |
| table->max_entities *= 2; |
| table->table = (xmlEntityPtr) |
| xmlRealloc(table->table, table->max_entities * sizeof(xmlEntity)); |
| if (table->table == NULL) { |
| perror("realloc failed"); |
| return; |
| } |
| } |
| cur = &table->table[table->nb_entities]; |
| cur->name = xmlStrdup(name); |
| for (len = 0;name[0] != 0;name++)len++; |
| cur->len = len; |
| cur->type = type; |
| if (ExternalID != NULL) |
| cur->ExternalID = xmlStrdup(ExternalID); |
| else |
| cur->ExternalID = NULL; |
| if (SystemID != NULL) |
| cur->SystemID = xmlStrdup(SystemID); |
| else |
| cur->SystemID = NULL; |
| if (content != NULL) { |
| cur->length = xmlStrlen(content); |
| cur->content = xmlStrndup(content, cur->length); |
| } else { |
| cur->length = 0; |
| cur->content = NULL; |
| } |
| cur->orig = NULL; |
| table->nb_entities++; |
| } |
| |
| /** |
| * xmlInitializePredefinedEntities: |
| * |
| * Set up the predefined entities. |
| */ |
| void xmlInitializePredefinedEntities(void) { |
| int i; |
| xmlChar name[50]; |
| xmlChar value[50]; |
| const char *in; |
| xmlChar *out; |
| |
| if (xmlPredefinedEntities != NULL) return; |
| |
| xmlPredefinedEntities = xmlCreateEntitiesTable(); |
| for (i = 0;i < sizeof(xmlPredefinedEntityValues) / |
| sizeof(xmlPredefinedEntityValues[0]);i++) { |
| in = xmlPredefinedEntityValues[i].name; |
| out = &name[0]; |
| for (;(*out++ = (xmlChar) *in);)in++; |
| in = xmlPredefinedEntityValues[i].value; |
| out = &value[0]; |
| for (;(*out++ = (xmlChar) *in);)in++; |
| xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0], |
| XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL, |
| &value[0]); |
| } |
| } |
| |
| /** |
| * xmlCleanupPredefinedEntities: |
| * |
| * Cleanup up the predefined entities table. |
| */ |
| void xmlCleanupPredefinedEntities(void) { |
| if (xmlPredefinedEntities == NULL) return; |
| |
| xmlFreeEntitiesTable(xmlPredefinedEntities); |
| xmlPredefinedEntities = NULL; |
| } |
| |
| /** |
| * xmlGetPredefinedEntity: |
| * @name: the entity name |
| * |
| * Check whether this name is an predefined entity. |
| * |
| * Returns NULL if not, othervise the entity |
| */ |
| xmlEntityPtr |
| xmlGetPredefinedEntity(const xmlChar *name) { |
| int i; |
| xmlEntityPtr cur; |
| |
| if (xmlPredefinedEntities == NULL) |
| xmlInitializePredefinedEntities(); |
| for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) { |
| cur = &xmlPredefinedEntities->table[i]; |
| if (!xmlStrcmp(cur->name, name)) return(cur); |
| } |
| return(NULL); |
| } |
| |
| /** |
| * xmlAddDtdEntity: |
| * @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 |
| * |
| * Register a new entity for this document DTD. |
| */ |
| void |
| xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type, |
| const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { |
| xmlEntitiesTablePtr table; |
| |
| if (doc->extSubset == NULL) { |
| fprintf(stderr, |
| "xmlAddDtdEntity: document without external subset !\n"); |
| return; |
| } |
| table = (xmlEntitiesTablePtr) doc->extSubset->entities; |
| if (table == NULL) { |
| table = xmlCreateEntitiesTable(); |
| doc->extSubset->entities = table; |
| } |
| xmlAddEntity(table, name, type, ExternalID, SystemID, content); |
| } |
| |
| /** |
| * xmlAddDocEntity: |
| * @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 |
| * |
| * Register a new entity for this document. |
| */ |
| void |
| xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type, |
| const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { |
| xmlEntitiesTablePtr table; |
| |
| if (doc == NULL) { |
| fprintf(stderr, |
| "xmlAddDocEntity: document is NULL !\n"); |
| return; |
| } |
| if (doc->intSubset == NULL) { |
| fprintf(stderr, |
| "xmlAddDtdEntity: document without internal subset !\n"); |
| return; |
| } |
| table = (xmlEntitiesTablePtr) doc->intSubset->entities; |
| if (table == NULL) { |
| table = xmlCreateEntitiesTable(); |
| doc->intSubset->entities = table; |
| } |
| xmlAddEntity(table, name, type, ExternalID, SystemID, content); |
| } |
| |
| /** |
| * xmlGetParameterEntity: |
| * @doc: the document referencing the entity |
| * @name: the entity 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 |
| xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) { |
| int i; |
| xmlEntityPtr cur; |
| xmlEntitiesTablePtr table; |
| |
| if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->intSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) || |
| (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->extSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) || |
| (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->extSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) || |
| (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| return(NULL); |
| } |
| |
| /** |
| * xmlGetDtdEntity: |
| * @doc: the document referencing the entity |
| * @name: the entity name |
| * |
| * Do an entity lookup in the Dtd entity hash table and |
| * returns the corresponding entity, if found. |
| * |
| * Returns A pointer to the entity structure or NULL if not found. |
| */ |
| xmlEntityPtr |
| xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) { |
| int i; |
| xmlEntityPtr cur; |
| xmlEntitiesTablePtr table; |
| |
| if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->extSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| return(NULL); |
| } |
| |
| /** |
| * xmlGetDocEntity: |
| * @doc: the document referencing the entity |
| * @name: the entity name |
| * |
| * Do an entity lookup in the document entity hash table and |
| * returns the corrsponding 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) { |
| int i; |
| xmlEntityPtr cur; |
| xmlEntitiesTablePtr table; |
| |
| if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->intSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) { |
| table = (xmlEntitiesTablePtr) doc->extSubset->entities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| } |
| if (xmlPredefinedEntities == NULL) |
| xmlInitializePredefinedEntities(); |
| table = xmlPredefinedEntities; |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) && |
| (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) && |
| (!xmlStrcmp(cur->name, name))) return(cur); |
| } |
| |
| return(NULL); |
| } |
| |
| /* |
| * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
| * | [#x10000-#x10FFFF] |
| * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. |
| */ |
| #define IS_CHAR(c) \ |
| (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \ |
| (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF))) |
| |
| /* |
| * A buffer used for converting entities to their equivalent and back. |
| */ |
| static int buffer_size = 0; |
| static xmlChar *buffer = NULL; |
| |
| int growBuffer(void) { |
| buffer_size *= 2; |
| buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); |
| if (buffer == NULL) { |
| perror("realloc failed"); |
| return(-1); |
| } |
| return(0); |
| } |
| |
| |
| /** |
| * xmlEncodeEntities: |
| * @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. |
| * |
| * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary |
| * compatibility |
| * |
| * People must migrate their code to xmlEncodeEntitiesReentrant ! |
| * This routine will issue a warning when encountered. |
| * |
| * Returns A newly allocated string with the substitution done. |
| */ |
| const xmlChar * |
| xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) { |
| const xmlChar *cur = input; |
| xmlChar *out = buffer; |
| static int warning = 1; |
| int html = 0; |
| |
| |
| if (warning) { |
| fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n"); |
| fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n"); |
| warning = 0; |
| } |
| |
| if (input == NULL) return(NULL); |
| if (doc != NULL) |
| html = (doc->type == XML_HTML_DOCUMENT_NODE); |
| |
| if (buffer == NULL) { |
| buffer_size = 1000; |
| buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); |
| if (buffer == NULL) { |
| perror("malloc failed"); |
| return(NULL); |
| } |
| out = buffer; |
| } |
| while (*cur != '\0') { |
| if (out - buffer > buffer_size - 100) { |
| int index = out - buffer; |
| |
| growBuffer(); |
| out = &buffer[index]; |
| } |
| |
| /* |
| * By default one have to encode at least '<', '>', '"' and '&' ! |
| */ |
| if (*cur == '<') { |
| *out++ = '&'; |
| *out++ = 'l'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if (*cur == '>') { |
| *out++ = '&'; |
| *out++ = 'g'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if (*cur == '&') { |
| *out++ = '&'; |
| *out++ = 'a'; |
| *out++ = 'm'; |
| *out++ = 'p'; |
| *out++ = ';'; |
| } else if (*cur == '"') { |
| *out++ = '&'; |
| *out++ = 'q'; |
| *out++ = 'u'; |
| *out++ = 'o'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if ((*cur == '\'') && (!html)) { |
| *out++ = '&'; |
| *out++ = 'a'; |
| *out++ = 'p'; |
| *out++ = 'o'; |
| *out++ = 's'; |
| *out++ = ';'; |
| } else if (((*cur >= 0x20) && (*cur < 0x80)) || |
| (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) { |
| /* |
| * default case, just copy ! |
| */ |
| *out++ = *cur; |
| #ifndef USE_UTF_8 |
| } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) { |
| char buf[10], *ptr; |
| #ifdef HAVE_SNPRINTF |
| snprintf(buf, 9, "&#%d;", *cur); |
| #else |
| sprintf(buf, "&#%d;", *cur); |
| #endif |
| ptr = buf; |
| while (*ptr != 0) *out++ = *ptr++; |
| #endif |
| } else if (IS_CHAR(*cur)) { |
| char buf[10], *ptr; |
| |
| #ifdef HAVE_SNPRINTF |
| snprintf(buf, 9, "&#%d;", *cur); |
| #else |
| sprintf(buf, "&#%d;", *cur); |
| #endif |
| ptr = buf; |
| while (*ptr != 0) *out++ = *ptr++; |
| } |
| #if 0 |
| else { |
| /* |
| * default case, this is not a valid char ! |
| * Skip it... |
| */ |
| fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur); |
| } |
| #endif |
| cur++; |
| } |
| *out++ = 0; |
| return(buffer); |
| } |
| |
| /* |
| * Macro used to grow the current buffer. |
| */ |
| #define growBufferReentrant() { \ |
| buffer_size *= 2; \ |
| buffer = (xmlChar *) \ |
| xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \ |
| if (buffer == NULL) { \ |
| perror("realloc failed"); \ |
| return(NULL); \ |
| } \ |
| } |
| |
| |
| /** |
| * 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. |
| * |
| * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii |
| * get erroneous. |
| * |
| * Returns A newly allocated string with the substitution done. |
| */ |
| xmlChar * |
| xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) { |
| const xmlChar *cur = input; |
| xmlChar *buffer = NULL; |
| xmlChar *out = NULL; |
| int buffer_size = 0; |
| int html = 0; |
| |
| if (input == NULL) return(NULL); |
| if (doc != NULL) |
| html = (doc->type == XML_HTML_DOCUMENT_NODE); |
| |
| /* |
| * allocate an translation buffer. |
| */ |
| buffer_size = 1000; |
| buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); |
| if (buffer == NULL) { |
| perror("malloc failed"); |
| return(NULL); |
| } |
| out = buffer; |
| |
| while (*cur != '\0') { |
| if (out - buffer > buffer_size - 100) { |
| int index = out - buffer; |
| |
| growBufferReentrant(); |
| out = &buffer[index]; |
| } |
| |
| /* |
| * By default one have to encode at least '<', '>', '"' and '&' ! |
| */ |
| if (*cur == '<') { |
| *out++ = '&'; |
| *out++ = 'l'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if (*cur == '>') { |
| *out++ = '&'; |
| *out++ = 'g'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if (*cur == '&') { |
| *out++ = '&'; |
| *out++ = 'a'; |
| *out++ = 'm'; |
| *out++ = 'p'; |
| *out++ = ';'; |
| } else if (*cur == '"') { |
| *out++ = '&'; |
| *out++ = 'q'; |
| *out++ = 'u'; |
| *out++ = 'o'; |
| *out++ = 't'; |
| *out++ = ';'; |
| } else if ((*cur == '\'') && (!html)) { |
| *out++ = '&'; |
| *out++ = 'a'; |
| *out++ = 'p'; |
| *out++ = 'o'; |
| *out++ = 's'; |
| *out++ = ';'; |
| } else if (((*cur >= 0x20) && (*cur < 0x80)) || |
| (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) { |
| /* |
| * default case, just copy ! |
| */ |
| *out++ = *cur; |
| #ifndef USE_UTF_8 |
| } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) { |
| char buf[10], *ptr; |
| #ifdef HAVE_SNPRINTF |
| snprintf(buf, 9, "&#%d;", *cur); |
| #else |
| sprintf(buf, "&#%d;", *cur); |
| #endif |
| ptr = buf; |
| while (*ptr != 0) *out++ = *ptr++; |
| #endif |
| } else if (IS_CHAR(*cur)) { |
| char buf[10], *ptr; |
| |
| #ifdef HAVE_SNPRINTF |
| snprintf(buf, 9, "&#%d;", *cur); |
| #else |
| sprintf(buf, "&#%d;", *cur); |
| #endif |
| ptr = buf; |
| while (*ptr != 0) *out++ = *ptr++; |
| } |
| #if 0 |
| else { |
| /* |
| * default case, this is not a valid char ! |
| * Skip it... |
| */ |
| fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur); |
| } |
| #endif |
| cur++; |
| } |
| *out++ = 0; |
| return(buffer); |
| } |
| |
| /** |
| * xmlCreateEntitiesTable: |
| * |
| * create and initialize an empty entities hash table. |
| * |
| * Returns the xmlEntitiesTablePtr just created or NULL in case of error. |
| */ |
| xmlEntitiesTablePtr |
| xmlCreateEntitiesTable(void) { |
| xmlEntitiesTablePtr ret; |
| |
| ret = (xmlEntitiesTablePtr) |
| xmlMalloc(sizeof(xmlEntitiesTable)); |
| if (ret == NULL) { |
| fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n", |
| (long)sizeof(xmlEntitiesTable)); |
| return(NULL); |
| } |
| ret->max_entities = XML_MIN_ENTITIES_TABLE; |
| ret->nb_entities = 0; |
| ret->table = (xmlEntityPtr ) |
| xmlMalloc(ret->max_entities * sizeof(xmlEntity)); |
| if (ret == NULL) { |
| fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n", |
| ret->max_entities * (long)sizeof(xmlEntity)); |
| xmlFree(ret); |
| return(NULL); |
| } |
| return(ret); |
| } |
| |
| /** |
| * xmlFreeEntitiesTable: |
| * @table: An entity table |
| * |
| * Deallocate the memory used by an entities hash table. |
| */ |
| void |
| xmlFreeEntitiesTable(xmlEntitiesTablePtr table) { |
| int i; |
| |
| if (table == NULL) return; |
| |
| for (i = 0;i < table->nb_entities;i++) { |
| xmlFreeEntity(&table->table[i]); |
| } |
| xmlFree(table->table); |
| xmlFree(table); |
| } |
| |
| /** |
| * xmlCopyEntitiesTable: |
| * @table: An entity table |
| * |
| * Build a copy of an entity table. |
| * |
| * Returns the new xmlEntitiesTablePtr or NULL in case of error. |
| */ |
| xmlEntitiesTablePtr |
| xmlCopyEntitiesTable(xmlEntitiesTablePtr table) { |
| xmlEntitiesTablePtr ret; |
| xmlEntityPtr cur, ent; |
| int i; |
| |
| ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable)); |
| if (ret == NULL) { |
| fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n"); |
| return(NULL); |
| } |
| ret->table = (xmlEntityPtr) xmlMalloc(table->max_entities * |
| sizeof(xmlEntity)); |
| if (ret->table == NULL) { |
| fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n"); |
| xmlFree(ret); |
| return(NULL); |
| } |
| ret->max_entities = table->max_entities; |
| ret->nb_entities = table->nb_entities; |
| for (i = 0;i < ret->nb_entities;i++) { |
| cur = &ret->table[i]; |
| ent = &table->table[i]; |
| cur->len = ent->len; |
| cur->type = ent->type; |
| if (ent->name != NULL) |
| cur->name = xmlStrdup(ent->name); |
| else |
| cur->name = NULL; |
| if (ent->ExternalID != NULL) |
| cur->ExternalID = xmlStrdup(ent->ExternalID); |
| else |
| cur->ExternalID = NULL; |
| if (ent->SystemID != NULL) |
| cur->SystemID = xmlStrdup(ent->SystemID); |
| else |
| cur->SystemID = NULL; |
| if (ent->content != NULL) |
| cur->content = xmlStrdup(ent->content); |
| else |
| cur->content = NULL; |
| if (ent->orig != NULL) |
| cur->orig = xmlStrdup(ent->orig); |
| else |
| cur->orig = NULL; |
| } |
| return(ret); |
| } |
| |
| /** |
| * xmlDumpEntitiesTable: |
| * @buf: An XML buffer. |
| * @table: An entity table |
| * |
| * This will dump the content of the entity table as an XML DTD definition |
| */ |
| void |
| xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) { |
| int i; |
| xmlEntityPtr cur; |
| |
| if (table == NULL) return; |
| |
| for (i = 0;i < table->nb_entities;i++) { |
| cur = &table->table[i]; |
| switch (cur->type) { |
| case XML_INTERNAL_GENERAL_ENTITY: |
| xmlBufferWriteChar(buf, "<!ENTITY "); |
| xmlBufferWriteCHAR(buf, cur->name); |
| xmlBufferWriteChar(buf, " "); |
| if (cur->orig != NULL) |
| xmlBufferWriteQuotedString(buf, cur->orig); |
| else |
| xmlBufferWriteQuotedString(buf, cur->content); |
| xmlBufferWriteChar(buf, ">\n"); |
| break; |
| case XML_EXTERNAL_GENERAL_PARSED_ENTITY: |
| xmlBufferWriteChar(buf, "<!ENTITY "); |
| xmlBufferWriteCHAR(buf, cur->name); |
| if (cur->ExternalID != NULL) { |
| xmlBufferWriteChar(buf, " PUBLIC "); |
| xmlBufferWriteQuotedString(buf, cur->ExternalID); |
| xmlBufferWriteChar(buf, " "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } else { |
| xmlBufferWriteChar(buf, " SYSTEM "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } |
| xmlBufferWriteChar(buf, ">\n"); |
| break; |
| case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: |
| xmlBufferWriteChar(buf, "<!ENTITY "); |
| xmlBufferWriteCHAR(buf, cur->name); |
| if (cur->ExternalID != NULL) { |
| xmlBufferWriteChar(buf, " PUBLIC "); |
| xmlBufferWriteQuotedString(buf, cur->ExternalID); |
| xmlBufferWriteChar(buf, " "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } else { |
| xmlBufferWriteChar(buf, " SYSTEM "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } |
| if (cur->content != NULL) { /* Should be true ! */ |
| xmlBufferWriteChar(buf, " NDATA "); |
| if (cur->orig != NULL) |
| xmlBufferWriteCHAR(buf, cur->orig); |
| else |
| xmlBufferWriteCHAR(buf, cur->content); |
| } |
| xmlBufferWriteChar(buf, ">\n"); |
| break; |
| case XML_INTERNAL_PARAMETER_ENTITY: |
| xmlBufferWriteChar(buf, "<!ENTITY % "); |
| xmlBufferWriteCHAR(buf, cur->name); |
| xmlBufferWriteChar(buf, " "); |
| if (cur->orig == NULL) |
| xmlBufferWriteQuotedString(buf, cur->content); |
| else |
| xmlBufferWriteQuotedString(buf, cur->orig); |
| xmlBufferWriteChar(buf, ">\n"); |
| break; |
| case XML_EXTERNAL_PARAMETER_ENTITY: |
| xmlBufferWriteChar(buf, "<!ENTITY % "); |
| xmlBufferWriteCHAR(buf, cur->name); |
| if (cur->ExternalID != NULL) { |
| xmlBufferWriteChar(buf, " PUBLIC "); |
| xmlBufferWriteQuotedString(buf, cur->ExternalID); |
| xmlBufferWriteChar(buf, " "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } else { |
| xmlBufferWriteChar(buf, " SYSTEM "); |
| xmlBufferWriteQuotedString(buf, cur->SystemID); |
| } |
| xmlBufferWriteChar(buf, ">\n"); |
| break; |
| default: |
| fprintf(stderr, |
| "xmlDumpEntitiesTable: internal: unknown type %d\n", |
| cur->type); |
| } |
| } |
| } |