📄 entities.c
字号:
/* * entities.c : implementation for the XML entities handking * * See Copyright for the status of this software. * * Daniel.Veillard@w3.org */#include "global.h"#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 <libxml/xmlmemory.h>#include <libxml/entities.h>#include <libxml/parser.h>#define DEBUG_ENT_REF /* debugging of cross entities dependancies *//* * 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->children) xmlFreeNodeList(entity->children); 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);#ifdef WITH_EXTRA_ENT_DETECT if (entity->entTab != NULL) { int i; for (i = 0; i < entity->entNr; i++) xmlFree(entity->entTab[i]); xmlFree(entity->entTab); }#endif memset(entity, -1, sizeof(xmlEntity)); xmlFree(entity);}/* * xmlAddEntity : register a new entity for an entities table. */static xmlEntityPtrxmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { int i; xmlEntityPtr ret; for (i = 0;i < table->nb_entities;i++) { ret = table->table[i]; if (!xmlStrcmp(ret->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)) && ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) || (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY))) return(NULL); else if (((type != XML_INTERNAL_PARAMETER_ENTITY) && (type != XML_EXTERNAL_PARAMETER_ENTITY)) && ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) && (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY))) return(NULL); } } if (table->nb_entities >= table->max_entities) { /* * need more elements. */ table->max_entities *= 2; table->table = (xmlEntityPtr *) xmlRealloc(table->table, table->max_entities * sizeof(xmlEntityPtr)); if (table->table == NULL) { perror("realloc failed"); return(NULL); } } ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); if (ret == NULL) { fprintf(stderr, "xmlAddEntity: out of memory\n"); return(NULL); } memset(ret, 0, sizeof(xmlEntity)); ret->type = XML_ENTITY_DECL; table->table[table->nb_entities] = ret; /* * fill the structure. */ ret->name = xmlStrdup(name); ret->etype = type; if (ExternalID != NULL) ret->ExternalID = xmlStrdup(ExternalID); if (SystemID != NULL) ret->SystemID = xmlStrdup(SystemID); if (content != NULL) { ret->length = xmlStrlen(content); ret->content = xmlStrndup(content, ret->length); } else { ret->length = 0; ret->content = NULL; } ret->orig = NULL; table->nb_entities++; return(ret);}/** * 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 */xmlEntityPtrxmlGetPredefinedEntity(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 external subset. * * Returns a pointer to the entity or NULL in case of error */xmlEntityPtrxmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { xmlEntitiesTablePtr table; xmlEntityPtr ret; xmlDtdPtr dtd; if (doc == NULL) { fprintf(stderr, "xmlAddDtdEntity: doc == NULL !\n"); return(NULL); } if (doc->extSubset == NULL) { fprintf(stderr, "xmlAddDtdEntity: document without external subset !\n"); return(NULL); } dtd = doc->extSubset; table = (xmlEntitiesTablePtr) dtd->entities; if (table == NULL) { table = xmlCreateEntitiesTable(); dtd->entities = table; } ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content); if (ret == NULL) return(NULL); /* * Link it to the Dtd */ ret->parent = dtd; ret->doc = dtd->doc; if (dtd->last == NULL) { dtd->children = dtd->last = (xmlNodePtr) ret; } else { dtd->last->next = (xmlNodePtr) ret; ret->prev = dtd->last; dtd->last = (xmlNodePtr) ret; } return(ret);}/** * 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. * * Returns a pointer to the entity or NULL in case of error */xmlEntityPtrxmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { xmlEntitiesTablePtr table; xmlEntityPtr ret; xmlDtdPtr dtd; if (doc == NULL) { fprintf(stderr, "xmlAddDocEntity: document is NULL !\n"); return(NULL); } if (doc->intSubset == NULL) { fprintf(stderr, "xmlAddDtdEntity: document without internal subset !\n"); return(NULL); } dtd = doc->intSubset; table = (xmlEntitiesTablePtr) doc->intSubset->entities; if (table == NULL) { table = xmlCreateEntitiesTable(); doc->intSubset->entities = table; } ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content); if (ret == NULL) return(NULL); /* * Link it to the Dtd */ ret->parent = dtd; ret->doc = dtd->doc; if (dtd->last == NULL) { dtd->children = dtd->last = (xmlNodePtr) ret; } else { dtd->last->next = (xmlNodePtr) ret; ret->prev = dtd->last; dtd->last = (xmlNodePtr) ret; } return(ret);}#ifdef WITH_EXTRA_ENT_DETECT/** * xmlEntityCheckReference: * @ent: an existing entity * @to: the entity name it's referencing * * Function to keep track of references and detect cycles (well formedness * errors !). * * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop * detection. */intxmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) { int i; xmlDocPtr doc; if (ent == NULL) return(-1); if (to == NULL) return(-1); doc = ent->doc; if (doc == NULL) return(-1);#ifdef DEBUG_ENT_REF printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);#endif /* * Do a recursive checking */ for (i = 0;i < ent->entNr;i++) { xmlEntityPtr indir = NULL; if (!xmlStrcmp(to, ent->entTab[i])) return(1); switch (ent->etype) { case XML_INTERNAL_GENERAL_ENTITY: case XML_EXTERNAL_GENERAL_PARSED_ENTITY: indir = xmlGetDocEntity(doc, ent->entTab[i]); break; case XML_INTERNAL_PARAMETER_ENTITY: case XML_EXTERNAL_PARAMETER_ENTITY: indir = xmlGetDtdEntity(doc, ent->entTab[i]); break; case XML_INTERNAL_PREDEFINED_ENTITY: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: break; } if (xmlEntityCheckReference(indir, to) == 1) return(1); } return(0);}/** * xmlEntityAddReference: * @ent: an existing entity * @to: the entity name it's referencing * * Function to register reuse of an existing entity from a (new) one * Used to keep track of references and detect cycles (well formedness * errors !). * * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop * detection. */intxmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) { int i; xmlDocPtr doc; xmlEntityPtr indir = NULL; if (ent == NULL) return(-1); if (to == NULL) return(-1); doc = ent->doc; if (doc == NULL) return(-1);#ifdef DEBUG_ENT_REF printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);#endif if (ent->entTab == NULL) { ent->entNr = 0; ent->entMax = 5; ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *)); if (ent->entTab == NULL) { fprintf(stderr, "xmlEntityAddReference: out of memory !\n"); return(-1); } } for (i = 0;i < ent->entNr;i++) { if (!xmlStrcmp(to, ent->entTab[i])) return(0); } /* * Do a recursive checking */ switch (ent->etype) { case XML_INTERNAL_GENERAL_ENTITY: case XML_EXTERNAL_GENERAL_PARSED_ENTITY: indir = xmlGetDocEntity(doc, to); break; case XML_INTERNAL_PARAMETER_ENTITY: case XML_EXTERNAL_PARAMETER_ENTITY: indir = xmlGetDtdEntity(doc, to); break; case XML_INTERNAL_PREDEFINED_ENTITY: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: break; } if ((indir != NULL) && (xmlEntityCheckReference(indir, ent->name) == 1)) return(1); /* * Add this to the list */ if (ent->entMax <= ent->entNr) { ent->entMax *= 2; ent->entTab = (xmlChar **) xmlRealloc(ent->entTab, ent->entMax * sizeof(xmlChar *)); if (ent->entTab == NULL) { fprintf(stderr, "xmlEntityAddReference: out of memory !\n"); return(-1); } } ent->entTab[ent->entNr++] = xmlStrdup(to); return(0);}#endif/** * 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. */xmlEntityPtrxmlGetParameterEntity(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->etype == XML_INTERNAL_PARAMETER_ENTITY) || (cur->etype == 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->etype == XML_INTERNAL_PARAMETER_ENTITY) || (cur->etype == 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->etype == XML_INTERNAL_PARAMETER_ENTITY) || (cur->etype == 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. */xmlEntityPtrxmlGetDtdEntity(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->etype != XML_INTERNAL_PARAMETER_ENTITY) && (cur->etype != 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. */xmlEntityPtrxmlGetDocEntity(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->etype != XML_INTERNAL_PARAMETER_ENTITY) && (cur->etype != 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->etype != XML_INTERNAL_PARAMETER_ENTITY) && (cur->etype != 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->etype != XML_INTERNAL_PARAMETER_ENTITY) && (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) && (!xmlStrcmp(cur->name, name))) return(cur); } return(NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -