blob: 0fc4e8eba99b9072d4efbe194d58513e090e6db2 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * entities.c : implementation for the XML entities handking
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard3c558c31999-12-22 11:30:41 +00009#ifdef WIN32
10#include "win32config.h"
11#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +000012#include "config.h"
13#endif
14
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <string.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000017#ifdef HAVE_STDLIB_H
18#include <stdlib.h>
19#endif
Daniel Veillard361d8452000-04-03 19:48:13 +000020#include <libxml/xmlmemory.h>
Daniel Veillard52afe802000-10-22 16:56:02 +000021#include <libxml/hash.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000022#include <libxml/entities.h>
23#include <libxml/parser.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000024#include <libxml/xmlerror.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000025
Daniel Veillardcf461992000-03-14 18:30:20 +000026#define DEBUG_ENT_REF /* debugging of cross entities dependancies */
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +000027#define ENTITY_HASH_SIZE 256 /* modify xmlEntityComputeHash accordingly */
28
29/*
30 * xmlEntityComputeHash:
31 *
32 * Computes the hash value for this given entity
33 */
34int
35xmlEntityComputeHash(const xmlChar *name) {
36 register const unsigned char *cur = (const unsigned char *) name;
37 register unsigned char val = 0;
38
39 if (name == NULL)
40 return(val);
41 while (*cur) val += *cur++;
42 return(val);
43}
Daniel Veillardcf461992000-03-14 18:30:20 +000044
Daniel Veillard260a68f1998-08-13 03:39:55 +000045/*
46 * The XML predefined entities.
47 */
48
49struct xmlPredefinedEntityValue {
50 const char *name;
51 const char *value;
52};
53struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
54 { "lt", "<" },
55 { "gt", ">" },
56 { "apos", "'" },
57 { "quot", "\"" },
58 { "amp", "&" }
59};
60
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +000061/*
62 * TODO: !!!!!!! This is GROSS, allocation of a 256 entry hash for
63 * a fixed number of 4 elements !
64 */
Daniel Veillard52afe802000-10-22 16:56:02 +000065xmlHashTablePtr xmlPredefinedEntities = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +000066
67/*
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 * xmlFreeEntity : clean-up an entity record.
69 */
Daniel Veillard260a68f1998-08-13 03:39:55 +000070void xmlFreeEntity(xmlEntityPtr entity) {
71 if (entity == NULL) return;
72
Daniel Veillardcf461992000-03-14 18:30:20 +000073 if (entity->children)
74 xmlFreeNodeList(entity->children);
Daniel Veillard260a68f1998-08-13 03:39:55 +000075 if (entity->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000076 xmlFree((char *) entity->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +000077 if (entity->ExternalID != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000078 xmlFree((char *) entity->ExternalID);
Daniel Veillard260a68f1998-08-13 03:39:55 +000079 if (entity->SystemID != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000080 xmlFree((char *) entity->SystemID);
Daniel Veillard39c7d712000-09-10 16:14:55 +000081 if (entity->URI != NULL)
82 xmlFree((char *) entity->URI);
Daniel Veillard260a68f1998-08-13 03:39:55 +000083 if (entity->content != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000084 xmlFree((char *) entity->content);
Daniel Veillard011b63c1999-06-02 17:44:04 +000085 if (entity->orig != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000086 xmlFree((char *) entity->orig);
Daniel Veillard260a68f1998-08-13 03:39:55 +000087 memset(entity, -1, sizeof(xmlEntity));
Daniel Veillardcf461992000-03-14 18:30:20 +000088 xmlFree(entity);
Daniel Veillard260a68f1998-08-13 03:39:55 +000089}
90
91/*
Daniel Veillardbe36afe1998-11-27 06:39:50 +000092 * xmlAddEntity : register a new entity for an entities table.
Daniel Veillard260a68f1998-08-13 03:39:55 +000093 */
Daniel Veillardcf461992000-03-14 18:30:20 +000094static xmlEntityPtr
Daniel Veillard52afe802000-10-22 16:56:02 +000095xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +000096 const xmlChar *ExternalID, const xmlChar *SystemID,
97 const xmlChar *content) {
Daniel Veillard52afe802000-10-22 16:56:02 +000098 xmlEntitiesTablePtr table = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +000099 xmlEntityPtr ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000100
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000101 if (name == NULL)
102 return(NULL);
Daniel Veillard52afe802000-10-22 16:56:02 +0000103 switch (type) {
104 case XML_INTERNAL_GENERAL_ENTITY:
105 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
106 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
107 if (dtd->entities == NULL)
108 dtd->entities = xmlHashCreate(0);
109 table = dtd->entities;
110 break;
111 case XML_INTERNAL_PARAMETER_ENTITY:
112 case XML_EXTERNAL_PARAMETER_ENTITY:
113 if (dtd->pentities == NULL)
114 dtd->pentities = xmlHashCreate(0);
115 table = dtd->pentities;
116 break;
117 case XML_INTERNAL_PREDEFINED_ENTITY:
118 if (xmlPredefinedEntities == NULL)
119 xmlPredefinedEntities = xmlHashCreate(8);
120 table = xmlPredefinedEntities;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000121 }
Daniel Veillard52afe802000-10-22 16:56:02 +0000122 if (table == NULL)
123 return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +0000124 ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
125 if (ret == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000126 xmlGenericError(xmlGenericErrorContext,
127 "xmlAddEntity: out of memory\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000128 return(NULL);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000129 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000130 memset(ret, 0, sizeof(xmlEntity));
131 ret->type = XML_ENTITY_DECL;
Daniel Veillardcf461992000-03-14 18:30:20 +0000132
133 /*
134 * fill the structure.
135 */
136 ret->name = xmlStrdup(name);
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000137 ret->etype = (xmlEntityType) type;
Daniel Veillardcf461992000-03-14 18:30:20 +0000138 if (ExternalID != NULL)
139 ret->ExternalID = xmlStrdup(ExternalID);
140 if (SystemID != NULL)
141 ret->SystemID = xmlStrdup(SystemID);
142 if (content != NULL) {
143 ret->length = xmlStrlen(content);
144 ret->content = xmlStrndup(content, ret->length);
145 } else {
146 ret->length = 0;
147 ret->content = NULL;
148 }
Daniel Veillard39c7d712000-09-10 16:14:55 +0000149 ret->URI = NULL; /* to be computed by the layer knowing
150 the defining entity */
Daniel Veillardcf461992000-03-14 18:30:20 +0000151 ret->orig = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +0000152
Daniel Veillard52afe802000-10-22 16:56:02 +0000153 if (xmlHashAddEntry(table, name, ret)) {
154 /*
155 * entity was already defined at another level.
156 */
157 xmlFreeEntity(ret);
Daniel Veillard126f2792000-10-24 17:10:12 +0000158 return(NULL);
Daniel Veillard52afe802000-10-22 16:56:02 +0000159 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000160 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000161}
162
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000163/**
164 * xmlInitializePredefinedEntities:
165 *
166 * Set up the predefined entities.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000167 */
168void xmlInitializePredefinedEntities(void) {
169 int i;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000170 xmlChar name[50];
171 xmlChar value[50];
Daniel Veillard260a68f1998-08-13 03:39:55 +0000172 const char *in;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000173 xmlChar *out;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000174
175 if (xmlPredefinedEntities != NULL) return;
176
177 xmlPredefinedEntities = xmlCreateEntitiesTable();
178 for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
179 sizeof(xmlPredefinedEntityValues[0]);i++) {
180 in = xmlPredefinedEntityValues[i].name;
181 out = &name[0];
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000182 for (;(*out++ = (xmlChar) *in);)in++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000183 in = xmlPredefinedEntityValues[i].value;
184 out = &value[0];
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000185 for (;(*out++ = (xmlChar) *in);)in++;
Daniel Veillard52afe802000-10-22 16:56:02 +0000186
187 xmlAddEntity(NULL, (const xmlChar *) &name[0],
Daniel Veillard25940b71998-10-29 05:51:30 +0000188 XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000189 &value[0]);
190 }
191}
192
Daniel Veillardccb09631998-10-27 06:21:04 +0000193/**
Daniel Veillarda594bf41999-12-01 09:51:45 +0000194 * xmlCleanupPredefinedEntities:
195 *
196 * Cleanup up the predefined entities table.
197 */
198void xmlCleanupPredefinedEntities(void) {
199 if (xmlPredefinedEntities == NULL) return;
200
201 xmlFreeEntitiesTable(xmlPredefinedEntities);
202 xmlPredefinedEntities = NULL;
203}
204
205/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000206 * xmlGetPredefinedEntity:
207 * @name: the entity name
208 *
209 * Check whether this name is an predefined entity.
210 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000211 * Returns NULL if not, othervise the entity
Daniel Veillardccb09631998-10-27 06:21:04 +0000212 */
213xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000214xmlGetPredefinedEntity(const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000215 if (xmlPredefinedEntities == NULL)
216 xmlInitializePredefinedEntities();
Daniel Veillard52afe802000-10-22 16:56:02 +0000217 return((xmlEntityPtr) xmlHashLookup(xmlPredefinedEntities, name));
Daniel Veillardccb09631998-10-27 06:21:04 +0000218}
219
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000220/**
221 * xmlAddDtdEntity:
222 * @doc: the document
223 * @name: the entity name
224 * @type: the entity type XML_xxx_yyy_ENTITY
225 * @ExternalID: the entity external ID if available
226 * @SystemID: the entity system ID if available
227 * @content: the entity content
228 *
Daniel Veillardcf461992000-03-14 18:30:20 +0000229 * Register a new entity for this document DTD external subset.
230 *
231 * Returns a pointer to the entity or NULL in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +0000232 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000233xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000234xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
Daniel Veillardcf461992000-03-14 18:30:20 +0000235 const xmlChar *ExternalID, const xmlChar *SystemID,
236 const xmlChar *content) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000237 xmlEntityPtr ret;
238 xmlDtdPtr dtd;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239
Daniel Veillardcf461992000-03-14 18:30:20 +0000240 if (doc == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000241 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardcf461992000-03-14 18:30:20 +0000242 "xmlAddDtdEntity: doc == NULL !\n");
243 return(NULL);
244 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000245 if (doc->extSubset == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000246 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000247 "xmlAddDtdEntity: document without external subset !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000248 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000250 dtd = doc->extSubset;
Daniel Veillard52afe802000-10-22 16:56:02 +0000251 ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000252 if (ret == NULL) return(NULL);
253
254 /*
255 * Link it to the Dtd
256 */
257 ret->parent = dtd;
258 ret->doc = dtd->doc;
259 if (dtd->last == NULL) {
260 dtd->children = dtd->last = (xmlNodePtr) ret;
261 } else {
262 dtd->last->next = (xmlNodePtr) ret;
263 ret->prev = dtd->last;
264 dtd->last = (xmlNodePtr) ret;
265 }
266 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000267}
268
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000269/**
270 * xmlAddDocEntity:
271 * @doc: the document
272 * @name: the entity name
273 * @type: the entity type XML_xxx_yyy_ENTITY
274 * @ExternalID: the entity external ID if available
275 * @SystemID: the entity system ID if available
276 * @content: the entity content
277 *
278 * Register a new entity for this document.
Daniel Veillardcf461992000-03-14 18:30:20 +0000279 *
280 * Returns a pointer to the entity or NULL in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +0000281 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000282xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000283xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
Daniel Veillardcf461992000-03-14 18:30:20 +0000284 const xmlChar *ExternalID, const xmlChar *SystemID,
285 const xmlChar *content) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000286 xmlEntityPtr ret;
287 xmlDtdPtr dtd;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000288
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000289 if (doc == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000290 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000291 "xmlAddDocEntity: document is NULL !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000292 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000293 }
294 if (doc->intSubset == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000295 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000296 "xmlAddDtdEntity: document without internal subset !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000297 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000298 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000299 dtd = doc->intSubset;
Daniel Veillard52afe802000-10-22 16:56:02 +0000300 ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000301 if (ret == NULL) return(NULL);
302
303 /*
304 * Link it to the Dtd
305 */
306 ret->parent = dtd;
307 ret->doc = dtd->doc;
308 if (dtd->last == NULL) {
309 dtd->children = dtd->last = (xmlNodePtr) ret;
310 } else {
311 dtd->last->next = (xmlNodePtr) ret;
312 ret->prev = dtd->last;
313 dtd->last = (xmlNodePtr) ret;
314 }
315 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316}
317
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000318/**
319 * xmlGetEntityFromTable:
320 * @table: an entity table
321 * @name: the entity name
322 * @parameter: look for parameter entities
323 *
324 * Do an entity lookup in the table.
325 * returns the corresponding parameter entity, if found.
326 *
327 * Returns A pointer to the entity structure or NULL if not found.
328 */
329xmlEntityPtr
Daniel Veillard52afe802000-10-22 16:56:02 +0000330xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) {
331 return((xmlEntityPtr) xmlHashLookup(table, name));
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000332}
333
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000334/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000335 * xmlGetParameterEntity:
336 * @doc: the document referencing the entity
337 * @name: the entity name
338 *
339 * Do an entity lookup in the internal and external subsets and
340 * returns the corresponding parameter entity, if found.
341 *
342 * Returns A pointer to the entity structure or NULL if not found.
343 */
344xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000345xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000346 xmlEntitiesTablePtr table;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000347 xmlEntityPtr ret;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000348
Daniel Veillard52afe802000-10-22 16:56:02 +0000349 if ((doc->intSubset != NULL) && (doc->intSubset->pentities != NULL)) {
350 table = (xmlEntitiesTablePtr) doc->intSubset->pentities;
351 ret = xmlGetEntityFromTable(table, name);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000352 if (ret != NULL)
353 return(ret);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000354 }
Daniel Veillard52afe802000-10-22 16:56:02 +0000355 if ((doc->extSubset != NULL) && (doc->extSubset->pentities != NULL)) {
356 table = (xmlEntitiesTablePtr) doc->extSubset->pentities;
357 return(xmlGetEntityFromTable(table, name));
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000358 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000359 return(NULL);
360}
361
362/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000363 * xmlGetDtdEntity:
364 * @doc: the document referencing the entity
365 * @name: the entity name
366 *
367 * Do an entity lookup in the Dtd entity hash table and
368 * returns the corresponding entity, if found.
369 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000370 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000371 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000372xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000373xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000374 xmlEntitiesTablePtr table;
375
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000376 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
377 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
Daniel Veillard52afe802000-10-22 16:56:02 +0000378 return(xmlGetEntityFromTable(table, name));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000379 }
380 return(NULL);
381}
382
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000383/**
384 * xmlGetDocEntity:
385 * @doc: the document referencing the entity
386 * @name: the entity name
387 *
388 * Do an entity lookup in the document entity hash table and
389 * returns the corrsponding entity, otherwise a lookup is done
390 * in the predefined entities too.
391 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000392 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000394xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000395xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000396 xmlEntityPtr cur;
397 xmlEntitiesTablePtr table;
398
Daniel Veillard4b5b80c2000-09-08 18:54:41 +0000399 if (doc != NULL) {
400 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
401 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
Daniel Veillard52afe802000-10-22 16:56:02 +0000402 cur = xmlGetEntityFromTable(table, name);
Daniel Veillard4b5b80c2000-09-08 18:54:41 +0000403 if (cur != NULL)
404 return(cur);
405 }
406 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
407 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
Daniel Veillard52afe802000-10-22 16:56:02 +0000408 cur = xmlGetEntityFromTable(table, name);
Daniel Veillard4b5b80c2000-09-08 18:54:41 +0000409 if (cur != NULL)
410 return(cur);
411 }
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000412 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413 if (xmlPredefinedEntities == NULL)
414 xmlInitializePredefinedEntities();
415 table = xmlPredefinedEntities;
Daniel Veillard52afe802000-10-22 16:56:02 +0000416 return(xmlGetEntityFromTable(table, name));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000417}
418
419/*
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000420 * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
421 * | [#x10000-#x10FFFF]
422 * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
423 */
424#define IS_CHAR(c) \
425 (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
426 (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
427
Daniel Veillard14fff061999-06-22 21:49:07 +0000428/*
429 * A buffer used for converting entities to their equivalent and back.
Daniel Veillard14fff061999-06-22 21:49:07 +0000430 */
431static int buffer_size = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000432static xmlChar *buffer = NULL;
Daniel Veillard14fff061999-06-22 21:49:07 +0000433
Daniel Veillard0142b842000-01-14 14:45:24 +0000434int growBuffer(void) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000435 buffer_size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000436 buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
Daniel Veillard14fff061999-06-22 21:49:07 +0000437 if (buffer == NULL) {
438 perror("realloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000439 return(-1);
Daniel Veillard14fff061999-06-22 21:49:07 +0000440 }
Daniel Veillard0142b842000-01-14 14:45:24 +0000441 return(0);
Daniel Veillard14fff061999-06-22 21:49:07 +0000442}
443
444
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000445/**
446 * xmlEncodeEntities:
447 * @doc: the document containing the string
448 * @input: A string to convert to XML.
449 *
450 * Do a global encoding of a string, replacing the predefined entities
451 * and non ASCII values with their entities and CharRef counterparts.
452 *
Daniel Veillardb96e6431999-08-29 21:02:19 +0000453 * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
454 * compatibility
Daniel Veillard14fff061999-06-22 21:49:07 +0000455 *
456 * People must migrate their code to xmlEncodeEntitiesReentrant !
Daniel Veillardb05deb71999-08-10 19:04:08 +0000457 * This routine will issue a warning when encountered.
Daniel Veillard14fff061999-06-22 21:49:07 +0000458 *
459 * Returns A newly allocated string with the substitution done.
460 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000461const xmlChar *
462xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
463 const xmlChar *cur = input;
464 xmlChar *out = buffer;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000465 static int warning = 1;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000466 int html = 0;
467
Daniel Veillardb05deb71999-08-10 19:04:08 +0000468
469 if (warning) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000470 xmlGenericError(xmlGenericErrorContext,
471 "Deprecated API xmlEncodeEntities() used\n");
472 xmlGenericError(xmlGenericErrorContext,
473 " change code to use xmlEncodeEntitiesReentrant()\n");
Daniel Veillardb05deb71999-08-10 19:04:08 +0000474 warning = 0;
475 }
Daniel Veillard14fff061999-06-22 21:49:07 +0000476
477 if (input == NULL) return(NULL);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000478 if (doc != NULL)
479 html = (doc->type == XML_HTML_DOCUMENT_NODE);
480
Daniel Veillard14fff061999-06-22 21:49:07 +0000481 if (buffer == NULL) {
482 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000483 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard14fff061999-06-22 21:49:07 +0000484 if (buffer == NULL) {
485 perror("malloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000486 return(NULL);
Daniel Veillard14fff061999-06-22 21:49:07 +0000487 }
488 out = buffer;
489 }
490 while (*cur != '\0') {
491 if (out - buffer > buffer_size - 100) {
492 int index = out - buffer;
493
494 growBuffer();
495 out = &buffer[index];
496 }
497
498 /*
499 * By default one have to encode at least '<', '>', '"' and '&' !
500 */
501 if (*cur == '<') {
502 *out++ = '&';
503 *out++ = 'l';
504 *out++ = 't';
505 *out++ = ';';
506 } else if (*cur == '>') {
507 *out++ = '&';
508 *out++ = 'g';
509 *out++ = 't';
510 *out++ = ';';
511 } else if (*cur == '&') {
512 *out++ = '&';
513 *out++ = 'a';
514 *out++ = 'm';
515 *out++ = 'p';
516 *out++ = ';';
517 } else if (*cur == '"') {
518 *out++ = '&';
519 *out++ = 'q';
520 *out++ = 'u';
521 *out++ = 'o';
522 *out++ = 't';
523 *out++ = ';';
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000524 } else if ((*cur == '\'') && (!html)) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000525 *out++ = '&';
526 *out++ = 'a';
527 *out++ = 'p';
528 *out++ = 'o';
529 *out++ = 's';
530 *out++ = ';';
531 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
532 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
533 /*
534 * default case, just copy !
535 */
536 *out++ = *cur;
537#ifndef USE_UTF_8
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000538 } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000539 char buf[10], *ptr;
Daniel Veillard39c7d712000-09-10 16:14:55 +0000540
Daniel Veillard14fff061999-06-22 21:49:07 +0000541#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000542 snprintf(buf, sizeof(buf), "&#%d;", *cur);
Daniel Veillard14fff061999-06-22 21:49:07 +0000543#else
544 sprintf(buf, "&#%d;", *cur);
545#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000546 buf[sizeof(buf) - 1] = 0;
Daniel Veillard14fff061999-06-22 21:49:07 +0000547 ptr = buf;
548 while (*ptr != 0) *out++ = *ptr++;
549#endif
550 } else if (IS_CHAR(*cur)) {
551 char buf[10], *ptr;
552
553#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000554 snprintf(buf, sizeof(buf), "&#%d;", *cur);
Daniel Veillard14fff061999-06-22 21:49:07 +0000555#else
556 sprintf(buf, "&#%d;", *cur);
557#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000558 buf[sizeof(buf) - 1] = 0;
Daniel Veillard14fff061999-06-22 21:49:07 +0000559 ptr = buf;
560 while (*ptr != 0) *out++ = *ptr++;
561 }
562#if 0
563 else {
564 /*
565 * default case, this is not a valid char !
566 * Skip it...
567 */
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000568 xmlGenericError(xmlGenericErrorContext,
569 "xmlEncodeEntities: invalid char %d\n", (int) *cur);
Daniel Veillard14fff061999-06-22 21:49:07 +0000570 }
571#endif
572 cur++;
573 }
574 *out++ = 0;
575 return(buffer);
576}
577
578/*
579 * Macro used to grow the current buffer.
580 */
581#define growBufferReentrant() { \
582 buffer_size *= 2; \
Daniel Veillard0142b842000-01-14 14:45:24 +0000583 buffer = (xmlChar *) \
584 xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
Daniel Veillard14fff061999-06-22 21:49:07 +0000585 if (buffer == NULL) { \
586 perror("realloc failed"); \
Daniel Veillard0142b842000-01-14 14:45:24 +0000587 return(NULL); \
Daniel Veillard14fff061999-06-22 21:49:07 +0000588 } \
589}
590
591
592/**
593 * xmlEncodeEntitiesReentrant:
594 * @doc: the document containing the string
595 * @input: A string to convert to XML.
596 *
597 * Do a global encoding of a string, replacing the predefined entities
598 * and non ASCII values with their entities and CharRef counterparts.
599 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
600 * must be deallocated.
601 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000602 * Returns A newly allocated string with the substitution done.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000603 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000604xmlChar *
605xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
606 const xmlChar *cur = input;
607 xmlChar *buffer = NULL;
608 xmlChar *out = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000609 int buffer_size = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000610 int html = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000611
Daniel Veillard242590e1998-11-13 18:04:35 +0000612 if (input == NULL) return(NULL);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000613 if (doc != NULL)
614 html = (doc->type == XML_HTML_DOCUMENT_NODE);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000615
616 /*
617 * allocate an translation buffer.
618 */
619 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000620 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000621 if (buffer == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000622 perror("malloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000623 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000624 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000625 out = buffer;
626
Daniel Veillard260a68f1998-08-13 03:39:55 +0000627 while (*cur != '\0') {
628 if (out - buffer > buffer_size - 100) {
629 int index = out - buffer;
630
Daniel Veillard14fff061999-06-22 21:49:07 +0000631 growBufferReentrant();
Daniel Veillard260a68f1998-08-13 03:39:55 +0000632 out = &buffer[index];
633 }
634
635 /*
636 * By default one have to encode at least '<', '>', '"' and '&' !
Daniel Veillard260a68f1998-08-13 03:39:55 +0000637 */
638 if (*cur == '<') {
639 *out++ = '&';
640 *out++ = 'l';
641 *out++ = 't';
642 *out++ = ';';
643 } else if (*cur == '>') {
644 *out++ = '&';
645 *out++ = 'g';
646 *out++ = 't';
647 *out++ = ';';
648 } else if (*cur == '&') {
649 *out++ = '&';
650 *out++ = 'a';
651 *out++ = 'm';
652 *out++ = 'p';
653 *out++ = ';';
654 } else if (*cur == '"') {
655 *out++ = '&';
656 *out++ = 'q';
657 *out++ = 'u';
658 *out++ = 'o';
659 *out++ = 't';
660 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000661#if 0
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000662 } else if ((*cur == '\'') && (!html)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000663 *out++ = '&';
664 *out++ = 'a';
665 *out++ = 'p';
666 *out++ = 'o';
667 *out++ = 's';
668 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000669#endif
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000670 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
671 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
672 /*
673 * default case, just copy !
674 */
675 *out++ = *cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000676 } else if (*cur >= 0x80) {
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000677 if ((doc->encoding != NULL) || (html)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000678 /*
Daniel Veillard39c7d712000-09-10 16:14:55 +0000679 * Bjørn Reese <br@sseusa.com> provided the patch
680 xmlChar xc;
681 xc = (*cur & 0x3F) << 6;
682 if (cur[1] != 0) {
683 xc += *(++cur) & 0x3F;
684 *out++ = xc;
685 } else
Daniel Veillardcf461992000-03-14 18:30:20 +0000686 */
Daniel Veillard39c7d712000-09-10 16:14:55 +0000687 *out++ = *cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000688 } else {
689 /*
690 * We assume we have UTF-8 input.
691 */
692 char buf[10], *ptr;
693 int val = 0, l = 1;
694
695 if (*cur < 0xC0) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000696 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardcf461992000-03-14 18:30:20 +0000697 "xmlEncodeEntitiesReentrant : input not UTF-8\n");
698 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
699#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000700 snprintf(buf, sizeof(buf), "&#%d;", *cur);
Daniel Veillardcf461992000-03-14 18:30:20 +0000701#else
702 sprintf(buf, "&#%d;", *cur);
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000703#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000704 buf[sizeof(buf) - 1] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000705 ptr = buf;
706 while (*ptr != 0) *out++ = *ptr++;
707 continue;
708 } else if (*cur < 0xE0) {
709 val = (cur[0]) & 0x1F;
710 val <<= 6;
711 val |= (cur[1]) & 0x3F;
712 l = 2;
713 } else if (*cur < 0xF0) {
714 val = (cur[0]) & 0x0F;
715 val <<= 6;
716 val |= (cur[1]) & 0x3F;
717 val <<= 6;
718 val |= (cur[2]) & 0x3F;
719 l = 3;
720 } else if (*cur < 0xF8) {
721 val = (cur[0]) & 0x07;
722 val <<= 6;
723 val |= (cur[1]) & 0x3F;
724 val <<= 6;
725 val |= (cur[2]) & 0x3F;
726 val <<= 6;
727 val |= (cur[3]) & 0x3F;
728 l = 4;
729 }
730 if ((l == 1) || (!IS_CHAR(val))) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000731 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardcf461992000-03-14 18:30:20 +0000732 "xmlEncodeEntitiesReentrant : char out of range\n");
733 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
734#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000735 snprintf(buf, sizeof(buf), "&#%d;", *cur);
Daniel Veillardcf461992000-03-14 18:30:20 +0000736#else
737 sprintf(buf, "&#%d;", *cur);
738#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000739 buf[sizeof(buf) - 1] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000740 ptr = buf;
741 while (*ptr != 0) *out++ = *ptr++;
742 cur++;
743 continue;
744 }
745 /*
746 * We could do multiple things here. Just save as a char ref
747 */
748#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000749 snprintf(buf, sizeof(buf), "&#x%X;", val);
Daniel Veillardcf461992000-03-14 18:30:20 +0000750#else
751 sprintf(buf, "&#x%X;", val);
752#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000753 buf[sizeof(buf) - 1] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000754 ptr = buf;
755 while (*ptr != 0) *out++ = *ptr++;
756 cur += l;
757 continue;
758 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000759 } else if (IS_CHAR(*cur)) {
760 char buf[10], *ptr;
761
762#ifdef HAVE_SNPRINTF
Daniel Veillard39c7d712000-09-10 16:14:55 +0000763 snprintf(buf, sizeof(buf), "&#%d;", *cur);
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000764#else
765 sprintf(buf, "&#%d;", *cur);
766#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +0000767 buf[sizeof(buf) - 1] = 0;
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000768 ptr = buf;
769 while (*ptr != 0) *out++ = *ptr++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000770 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000771#if 0
772 else {
773 /*
774 * default case, this is not a valid char !
775 * Skip it...
776 */
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000777 xmlGenericError(xmlGenericErrorContext,
778 "xmlEncodeEntities: invalid char %d\n", (int) *cur);
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000779 }
780#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000781 cur++;
782 }
783 *out++ = 0;
784 return(buffer);
785}
786
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000787/**
Daniel Veillardbe803962000-06-28 23:40:59 +0000788 * xmlEncodeSpecialChars:
789 * @doc: the document containing the string
790 * @input: A string to convert to XML.
791 *
792 * Do a global encoding of a string, replacing the predefined entities
793 * this routine is reentrant, and result must be deallocated.
794 *
795 * Returns A newly allocated string with the substitution done.
796 */
797xmlChar *
798xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
799 const xmlChar *cur = input;
800 xmlChar *buffer = NULL;
801 xmlChar *out = NULL;
802 int buffer_size = 0;
803 int html = 0;
804
805 if (input == NULL) return(NULL);
806 if (doc != NULL)
807 html = (doc->type == XML_HTML_DOCUMENT_NODE);
808
809 /*
810 * allocate an translation buffer.
811 */
812 buffer_size = 1000;
813 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
814 if (buffer == NULL) {
815 perror("malloc failed");
816 return(NULL);
817 }
818 out = buffer;
819
820 while (*cur != '\0') {
821 if (out - buffer > buffer_size - 10) {
822 int index = out - buffer;
823
824 growBufferReentrant();
825 out = &buffer[index];
826 }
827
828 /*
829 * By default one have to encode at least '<', '>', '"' and '&' !
830 */
831 if (*cur == '<') {
832 *out++ = '&';
833 *out++ = 'l';
834 *out++ = 't';
835 *out++ = ';';
836 } else if (*cur == '>') {
837 *out++ = '&';
838 *out++ = 'g';
839 *out++ = 't';
840 *out++ = ';';
841 } else if (*cur == '&') {
842 *out++ = '&';
843 *out++ = 'a';
844 *out++ = 'm';
845 *out++ = 'p';
846 *out++ = ';';
847 } else if (*cur == '"') {
848 *out++ = '&';
849 *out++ = 'q';
850 *out++ = 'u';
851 *out++ = 'o';
852 *out++ = 't';
853 *out++ = ';';
854 } else {
855 /*
856 * Works because on UTF-8, all extended sequences cannot
857 * result in bytes in the ASCII range.
858 */
859 *out++ = *cur;
860 }
861 cur++;
862 }
863 *out++ = 0;
864 return(buffer);
865}
866
867/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000868 * xmlCreateEntitiesTable:
869 *
870 * create and initialize an empty entities hash table.
871 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000872 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000873 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000874xmlEntitiesTablePtr
875xmlCreateEntitiesTable(void) {
Daniel Veillard52afe802000-10-22 16:56:02 +0000876 return((xmlEntitiesTablePtr) xmlHashCreate(0));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000877}
878
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000879/**
880 * xmlFreeEntitiesTable:
881 * @table: An entity table
882 *
883 * Deallocate the memory used by an entities hash table.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000884 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000885void
886xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
Daniel Veillard52afe802000-10-22 16:56:02 +0000887 xmlHashFree(table, (xmlHashDeallocator) xmlFreeEntity);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000888}
889
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000890/**
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000891 * xmlCopyEntity:
892 * @ent: An entity
893 *
894 * Build a copy of an entity
895 *
896 * Returns the new xmlEntitiesPtr or NULL in case of error.
897 */
898xmlEntityPtr
899xmlCopyEntity(xmlEntityPtr ent) {
900 xmlEntityPtr cur;
901
902 cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
903 if (cur == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000904 xmlGenericError(xmlGenericErrorContext,
905 "xmlCopyEntity: out of memory !\n");
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000906 return(NULL);
907 }
908 memset(cur, 0, sizeof(xmlEntity));
909 cur->type = XML_ELEMENT_DECL;
910
911 cur->etype = ent->etype;
912 if (ent->name != NULL)
913 cur->name = xmlStrdup(ent->name);
914 if (ent->ExternalID != NULL)
915 cur->ExternalID = xmlStrdup(ent->ExternalID);
916 if (ent->SystemID != NULL)
917 cur->SystemID = xmlStrdup(ent->SystemID);
918 if (ent->content != NULL)
919 cur->content = xmlStrdup(ent->content);
920 if (ent->orig != NULL)
921 cur->orig = xmlStrdup(ent->orig);
922 return(cur);
923}
924
925/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000926 * xmlCopyEntitiesTable:
927 * @table: An entity table
928 *
929 * Build a copy of an entity table.
930 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000931 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000932 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000933xmlEntitiesTablePtr
934xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
Daniel Veillard52afe802000-10-22 16:56:02 +0000935 return(xmlHashCopy(table, (xmlHashCopier) xmlCopyEntity));
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000936}
937
938/**
Daniel Veillardcf461992000-03-14 18:30:20 +0000939 * xmlDumpEntityDecl:
940 * @buf: An XML buffer.
941 * @ent: An entity table
942 *
943 * This will dump the content of the entity table as an XML DTD definition
944 */
945void
946xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
947 switch (ent->etype) {
948 case XML_INTERNAL_GENERAL_ENTITY:
949 xmlBufferWriteChar(buf, "<!ENTITY ");
950 xmlBufferWriteCHAR(buf, ent->name);
951 xmlBufferWriteChar(buf, " ");
952 if (ent->orig != NULL)
953 xmlBufferWriteQuotedString(buf, ent->orig);
954 else
955 xmlBufferWriteQuotedString(buf, ent->content);
956 xmlBufferWriteChar(buf, ">\n");
957 break;
958 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
959 xmlBufferWriteChar(buf, "<!ENTITY ");
960 xmlBufferWriteCHAR(buf, ent->name);
961 if (ent->ExternalID != NULL) {
962 xmlBufferWriteChar(buf, " PUBLIC ");
963 xmlBufferWriteQuotedString(buf, ent->ExternalID);
964 xmlBufferWriteChar(buf, " ");
965 xmlBufferWriteQuotedString(buf, ent->SystemID);
966 } else {
967 xmlBufferWriteChar(buf, " SYSTEM ");
968 xmlBufferWriteQuotedString(buf, ent->SystemID);
969 }
970 xmlBufferWriteChar(buf, ">\n");
971 break;
972 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
973 xmlBufferWriteChar(buf, "<!ENTITY ");
974 xmlBufferWriteCHAR(buf, ent->name);
975 if (ent->ExternalID != NULL) {
976 xmlBufferWriteChar(buf, " PUBLIC ");
977 xmlBufferWriteQuotedString(buf, ent->ExternalID);
978 xmlBufferWriteChar(buf, " ");
979 xmlBufferWriteQuotedString(buf, ent->SystemID);
980 } else {
981 xmlBufferWriteChar(buf, " SYSTEM ");
982 xmlBufferWriteQuotedString(buf, ent->SystemID);
983 }
984 if (ent->content != NULL) { /* Should be true ! */
985 xmlBufferWriteChar(buf, " NDATA ");
986 if (ent->orig != NULL)
987 xmlBufferWriteCHAR(buf, ent->orig);
988 else
989 xmlBufferWriteCHAR(buf, ent->content);
990 }
991 xmlBufferWriteChar(buf, ">\n");
992 break;
993 case XML_INTERNAL_PARAMETER_ENTITY:
994 xmlBufferWriteChar(buf, "<!ENTITY % ");
995 xmlBufferWriteCHAR(buf, ent->name);
996 xmlBufferWriteChar(buf, " ");
997 if (ent->orig == NULL)
998 xmlBufferWriteQuotedString(buf, ent->content);
999 else
1000 xmlBufferWriteQuotedString(buf, ent->orig);
1001 xmlBufferWriteChar(buf, ">\n");
1002 break;
1003 case XML_EXTERNAL_PARAMETER_ENTITY:
1004 xmlBufferWriteChar(buf, "<!ENTITY % ");
1005 xmlBufferWriteCHAR(buf, ent->name);
1006 if (ent->ExternalID != NULL) {
1007 xmlBufferWriteChar(buf, " PUBLIC ");
1008 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1009 xmlBufferWriteChar(buf, " ");
1010 xmlBufferWriteQuotedString(buf, ent->SystemID);
1011 } else {
1012 xmlBufferWriteChar(buf, " SYSTEM ");
1013 xmlBufferWriteQuotedString(buf, ent->SystemID);
1014 }
1015 xmlBufferWriteChar(buf, ">\n");
1016 break;
1017 default:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001018 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardcf461992000-03-14 18:30:20 +00001019 "xmlDumpEntitiesTable: internal: unknown type %d\n",
1020 ent->etype);
1021 }
1022}
1023
1024/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001025 * xmlDumpEntitiesTable:
Daniel Veillard5099ae81999-04-21 20:12:07 +00001026 * @buf: An XML buffer.
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001027 * @table: An entity table
1028 *
1029 * This will dump the content of the entity table as an XML DTD definition
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001030 */
1031void
Daniel Veillard5099ae81999-04-21 20:12:07 +00001032xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
Daniel Veillard52afe802000-10-22 16:56:02 +00001033 xmlHashScan(table, (xmlHashScanner)xmlDumpEntityDecl, buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001034}