blob: 15247a2dcacf21e8058911a05a4d044016ad6254 [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>
21#include <libxml/entities.h>
22#include <libxml/parser.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000023
Daniel Veillardcf461992000-03-14 18:30:20 +000024#define DEBUG_ENT_REF /* debugging of cross entities dependancies */
25
Daniel Veillard260a68f1998-08-13 03:39:55 +000026/*
27 * The XML predefined entities.
28 */
29
30struct xmlPredefinedEntityValue {
31 const char *name;
32 const char *value;
33};
34struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
35 { "lt", "<" },
36 { "gt", ">" },
37 { "apos", "'" },
38 { "quot", "\"" },
39 { "amp", "&" }
40};
41
42xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
43
44/*
Daniel Veillard260a68f1998-08-13 03:39:55 +000045 * xmlFreeEntity : clean-up an entity record.
46 */
Daniel Veillard260a68f1998-08-13 03:39:55 +000047void xmlFreeEntity(xmlEntityPtr entity) {
48 if (entity == NULL) return;
49
Daniel Veillardcf461992000-03-14 18:30:20 +000050 if (entity->children)
51 xmlFreeNodeList(entity->children);
Daniel Veillard260a68f1998-08-13 03:39:55 +000052 if (entity->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000053 xmlFree((char *) entity->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +000054 if (entity->ExternalID != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000055 xmlFree((char *) entity->ExternalID);
Daniel Veillard260a68f1998-08-13 03:39:55 +000056 if (entity->SystemID != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000057 xmlFree((char *) entity->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +000058 if (entity->content != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000059 xmlFree((char *) entity->content);
Daniel Veillard011b63c1999-06-02 17:44:04 +000060 if (entity->orig != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +000061 xmlFree((char *) entity->orig);
Daniel Veillardcf461992000-03-14 18:30:20 +000062#ifdef WITH_EXTRA_ENT_DETECT
63 if (entity->entTab != NULL) {
64 int i;
65
66 for (i = 0; i < entity->entNr; i++)
67 xmlFree(entity->entTab[i]);
68 xmlFree(entity->entTab);
69 }
70#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000071 memset(entity, -1, sizeof(xmlEntity));
Daniel Veillardcf461992000-03-14 18:30:20 +000072 xmlFree(entity);
Daniel Veillard260a68f1998-08-13 03:39:55 +000073}
74
75/*
Daniel Veillardbe36afe1998-11-27 06:39:50 +000076 * xmlAddEntity : register a new entity for an entities table.
Daniel Veillard260a68f1998-08-13 03:39:55 +000077 */
Daniel Veillardcf461992000-03-14 18:30:20 +000078static xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +000079xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
80 const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000081 int i;
Daniel Veillardcf461992000-03-14 18:30:20 +000082 xmlEntityPtr ret;
Daniel Veillard260a68f1998-08-13 03:39:55 +000083
84 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +000085 ret = table->table[i];
86 if (!xmlStrcmp(ret->name, name)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000087 /*
88 * The entity is already defined in this Dtd, the spec says to NOT
89 * override it ... Is it worth a Warning ??? !!!
Daniel Veillardb96e6431999-08-29 21:02:19 +000090 * Not having a cprinting context this seems hard ...
Daniel Veillard260a68f1998-08-13 03:39:55 +000091 */
Daniel Veillardb05deb71999-08-10 19:04:08 +000092 if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
93 (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
Daniel Veillardcf461992000-03-14 18:30:20 +000094 ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
95 (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
96 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +000097 else
98 if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
99 (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000100 ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
101 (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
102 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000103 }
104 }
105 if (table->nb_entities >= table->max_entities) {
106 /*
107 * need more elements.
108 */
109 table->max_entities *= 2;
Daniel Veillardcf461992000-03-14 18:30:20 +0000110 table->table = (xmlEntityPtr *)
111 xmlRealloc(table->table,
112 table->max_entities * sizeof(xmlEntityPtr));
Daniel Veillardb05deb71999-08-10 19:04:08 +0000113 if (table->table == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000114 perror("realloc failed");
Daniel Veillardcf461992000-03-14 18:30:20 +0000115 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000116 }
117 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000118 ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
119 if (ret == NULL) {
120 fprintf(stderr, "xmlAddEntity: out of memory\n");
121 return(NULL);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000122 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000123 memset(ret, 0, sizeof(xmlEntity));
124 ret->type = XML_ENTITY_DECL;
125 table->table[table->nb_entities] = ret;
126
127 /*
128 * fill the structure.
129 */
130 ret->name = xmlStrdup(name);
131 ret->etype = type;
132 if (ExternalID != NULL)
133 ret->ExternalID = xmlStrdup(ExternalID);
134 if (SystemID != NULL)
135 ret->SystemID = xmlStrdup(SystemID);
136 if (content != NULL) {
137 ret->length = xmlStrlen(content);
138 ret->content = xmlStrndup(content, ret->length);
139 } else {
140 ret->length = 0;
141 ret->content = NULL;
142 }
143 ret->orig = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000144 table->nb_entities++;
Daniel Veillardcf461992000-03-14 18:30:20 +0000145
146 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000147}
148
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000149/**
150 * xmlInitializePredefinedEntities:
151 *
152 * Set up the predefined entities.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000153 */
154void xmlInitializePredefinedEntities(void) {
155 int i;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000156 xmlChar name[50];
157 xmlChar value[50];
Daniel Veillard260a68f1998-08-13 03:39:55 +0000158 const char *in;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000159 xmlChar *out;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000160
161 if (xmlPredefinedEntities != NULL) return;
162
163 xmlPredefinedEntities = xmlCreateEntitiesTable();
164 for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
165 sizeof(xmlPredefinedEntityValues[0]);i++) {
166 in = xmlPredefinedEntityValues[i].name;
167 out = &name[0];
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000168 for (;(*out++ = (xmlChar) *in);)in++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000169 in = xmlPredefinedEntityValues[i].value;
170 out = &value[0];
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000171 for (;(*out++ = (xmlChar) *in);)in++;
172 xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
Daniel Veillard25940b71998-10-29 05:51:30 +0000173 XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000174 &value[0]);
175 }
176}
177
Daniel Veillardccb09631998-10-27 06:21:04 +0000178/**
Daniel Veillarda594bf41999-12-01 09:51:45 +0000179 * xmlCleanupPredefinedEntities:
180 *
181 * Cleanup up the predefined entities table.
182 */
183void xmlCleanupPredefinedEntities(void) {
184 if (xmlPredefinedEntities == NULL) return;
185
186 xmlFreeEntitiesTable(xmlPredefinedEntities);
187 xmlPredefinedEntities = NULL;
188}
189
190/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000191 * xmlGetPredefinedEntity:
192 * @name: the entity name
193 *
194 * Check whether this name is an predefined entity.
195 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000196 * Returns NULL if not, othervise the entity
Daniel Veillardccb09631998-10-27 06:21:04 +0000197 */
198xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000199xmlGetPredefinedEntity(const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000200 int i;
201 xmlEntityPtr cur;
202
203 if (xmlPredefinedEntities == NULL)
204 xmlInitializePredefinedEntities();
205 for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000206 cur = xmlPredefinedEntities->table[i];
Daniel Veillardccb09631998-10-27 06:21:04 +0000207 if (!xmlStrcmp(cur->name, name)) return(cur);
208 }
209 return(NULL);
210}
211
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000212/**
213 * xmlAddDtdEntity:
214 * @doc: the document
215 * @name: the entity name
216 * @type: the entity type XML_xxx_yyy_ENTITY
217 * @ExternalID: the entity external ID if available
218 * @SystemID: the entity system ID if available
219 * @content: the entity content
220 *
Daniel Veillardcf461992000-03-14 18:30:20 +0000221 * Register a new entity for this document DTD external subset.
222 *
223 * Returns a pointer to the entity or NULL in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +0000224 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000225xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000226xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
Daniel Veillardcf461992000-03-14 18:30:20 +0000227 const xmlChar *ExternalID, const xmlChar *SystemID,
228 const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 xmlEntitiesTablePtr table;
Daniel Veillardcf461992000-03-14 18:30:20 +0000230 xmlEntityPtr ret;
231 xmlDtdPtr dtd;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000232
Daniel Veillardcf461992000-03-14 18:30:20 +0000233 if (doc == NULL) {
234 fprintf(stderr,
235 "xmlAddDtdEntity: doc == NULL !\n");
236 return(NULL);
237 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000238 if (doc->extSubset == NULL) {
239 fprintf(stderr,
240 "xmlAddDtdEntity: document without external subset !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000241 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000242 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000243 dtd = doc->extSubset;
244 table = (xmlEntitiesTablePtr) dtd->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000245 if (table == NULL) {
246 table = xmlCreateEntitiesTable();
Daniel Veillardcf461992000-03-14 18:30:20 +0000247 dtd->entities = table;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000249 ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
250 if (ret == NULL) return(NULL);
251
252 /*
253 * Link it to the Dtd
254 */
255 ret->parent = dtd;
256 ret->doc = dtd->doc;
257 if (dtd->last == NULL) {
258 dtd->children = dtd->last = (xmlNodePtr) ret;
259 } else {
260 dtd->last->next = (xmlNodePtr) ret;
261 ret->prev = dtd->last;
262 dtd->last = (xmlNodePtr) ret;
263 }
264 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000265}
266
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000267/**
268 * xmlAddDocEntity:
269 * @doc: the document
270 * @name: the entity name
271 * @type: the entity type XML_xxx_yyy_ENTITY
272 * @ExternalID: the entity external ID if available
273 * @SystemID: the entity system ID if available
274 * @content: the entity content
275 *
276 * Register a new entity for this document.
Daniel Veillardcf461992000-03-14 18:30:20 +0000277 *
278 * Returns a pointer to the entity or NULL in case of error
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000280xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000281xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
Daniel Veillardcf461992000-03-14 18:30:20 +0000282 const xmlChar *ExternalID, const xmlChar *SystemID,
283 const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000284 xmlEntitiesTablePtr table;
Daniel Veillardcf461992000-03-14 18:30:20 +0000285 xmlEntityPtr ret;
286 xmlDtdPtr dtd;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000287
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000288 if (doc == NULL) {
289 fprintf(stderr,
290 "xmlAddDocEntity: document is NULL !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000291 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000292 }
293 if (doc->intSubset == NULL) {
294 fprintf(stderr,
295 "xmlAddDtdEntity: document without internal subset !\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000296 return(NULL);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000297 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000298 dtd = doc->intSubset;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000299 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000300 if (table == NULL) {
301 table = xmlCreateEntitiesTable();
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000302 doc->intSubset->entities = table;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000303 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000304 ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
305 if (ret == NULL) return(NULL);
306
307 /*
308 * Link it to the Dtd
309 */
310 ret->parent = dtd;
311 ret->doc = dtd->doc;
312 if (dtd->last == NULL) {
313 dtd->children = dtd->last = (xmlNodePtr) ret;
314 } else {
315 dtd->last->next = (xmlNodePtr) ret;
316 ret->prev = dtd->last;
317 dtd->last = (xmlNodePtr) ret;
318 }
319 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000320}
321
Daniel Veillardcf461992000-03-14 18:30:20 +0000322#ifdef WITH_EXTRA_ENT_DETECT
323/**
324 * xmlEntityCheckReference:
325 * @ent: an existing entity
326 * @to: the entity name it's referencing
327 *
328 * Function to keep track of references and detect cycles (well formedness
329 * errors !).
330 *
331 * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
332 * detection.
333 */
334int
335xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
336 int i;
337 xmlDocPtr doc;
338
339 if (ent == NULL) return(-1);
340 if (to == NULL) return(-1);
341
342 doc = ent->doc;
343 if (doc == NULL) return(-1);
344
345#ifdef DEBUG_ENT_REF
346 printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);
347#endif
348
349
350 /*
351 * Do a recursive checking
352 */
353 for (i = 0;i < ent->entNr;i++) {
354 xmlEntityPtr indir = NULL;
355
356 if (!xmlStrcmp(to, ent->entTab[i]))
357 return(1);
358
359 switch (ent->etype) {
360 case XML_INTERNAL_GENERAL_ENTITY:
361 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
362 indir = xmlGetDocEntity(doc, ent->entTab[i]);
363 break;
364 case XML_INTERNAL_PARAMETER_ENTITY:
365 case XML_EXTERNAL_PARAMETER_ENTITY:
366 indir = xmlGetDtdEntity(doc, ent->entTab[i]);
367 break;
368 case XML_INTERNAL_PREDEFINED_ENTITY:
369 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
370 break;
371 }
372 if (xmlEntityCheckReference(indir, to) == 1)
373 return(1);
374 }
375 return(0);
376}
377
378/**
379 * xmlEntityAddReference:
380 * @ent: an existing entity
381 * @to: the entity name it's referencing
382 *
383 * Function to register reuse of an existing entity from a (new) one
384 * Used to keep track of references and detect cycles (well formedness
385 * errors !).
386 *
387 * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
388 * detection.
389 */
390int
391xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
392 int i;
393 xmlDocPtr doc;
394 xmlEntityPtr indir = NULL;
395
396 if (ent == NULL) return(-1);
397 if (to == NULL) return(-1);
398
399 doc = ent->doc;
400 if (doc == NULL) return(-1);
401
402#ifdef DEBUG_ENT_REF
403 printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);
404#endif
405 if (ent->entTab == NULL) {
406 ent->entNr = 0;
407 ent->entMax = 5;
408 ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
409 if (ent->entTab == NULL) {
410 fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
411 return(-1);
412 }
413 }
414
415 for (i = 0;i < ent->entNr;i++) {
416 if (!xmlStrcmp(to, ent->entTab[i]))
417 return(0);
418 }
419
420 /*
421 * Do a recursive checking
422 */
423
424 switch (ent->etype) {
425 case XML_INTERNAL_GENERAL_ENTITY:
426 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
427 indir = xmlGetDocEntity(doc, to);
428 break;
429 case XML_INTERNAL_PARAMETER_ENTITY:
430 case XML_EXTERNAL_PARAMETER_ENTITY:
431 indir = xmlGetDtdEntity(doc, to);
432 break;
433 case XML_INTERNAL_PREDEFINED_ENTITY:
434 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
435 break;
436 }
437 if ((indir != NULL) &&
438 (xmlEntityCheckReference(indir, ent->name) == 1))
439 return(1);
440
441 /*
442 * Add this to the list
443 */
444 if (ent->entMax <= ent->entNr) {
445 ent->entMax *= 2;
446 ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
447 ent->entMax * sizeof(xmlChar *));
448 if (ent->entTab == NULL) {
449 fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
450 return(-1);
451 }
452 }
453 ent->entTab[ent->entNr++] = xmlStrdup(to);
454 return(0);
455}
456#endif
457
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000458/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000459 * xmlGetParameterEntity:
460 * @doc: the document referencing the entity
461 * @name: the entity name
462 *
463 * Do an entity lookup in the internal and external subsets and
464 * returns the corresponding parameter entity, if found.
465 *
466 * Returns A pointer to the entity structure or NULL if not found.
467 */
468xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000469xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000470 int i;
471 xmlEntityPtr cur;
472 xmlEntitiesTablePtr table;
473
474 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
475 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
476 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000477 cur = table->table[i];
478 if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
479 (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000480 (!xmlStrcmp(cur->name, name))) return(cur);
481 }
482 }
483 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
484 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
485 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000486 cur = table->table[i];
487 if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
488 (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000489 (!xmlStrcmp(cur->name, name))) return(cur);
490 }
491 }
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000492 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
493 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
494 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000495 cur = table->table[i];
496 if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
497 (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000498 (!xmlStrcmp(cur->name, name))) return(cur);
499 }
500 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000501 return(NULL);
502}
503
504/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000505 * xmlGetDtdEntity:
506 * @doc: the document referencing the entity
507 * @name: the entity name
508 *
509 * Do an entity lookup in the Dtd entity hash table and
510 * returns the corresponding entity, if found.
511 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000512 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000513 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000514xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000515xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000516 int i;
517 xmlEntityPtr cur;
518 xmlEntitiesTablePtr table;
519
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000520 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
521 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000522 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000523 cur = table->table[i];
524 if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
525 (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000526 (!xmlStrcmp(cur->name, name))) return(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000527 }
528 }
529 return(NULL);
530}
531
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000532/**
533 * xmlGetDocEntity:
534 * @doc: the document referencing the entity
535 * @name: the entity name
536 *
537 * Do an entity lookup in the document entity hash table and
538 * returns the corrsponding entity, otherwise a lookup is done
539 * in the predefined entities too.
540 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000541 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000542 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000543xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000544xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000545 int i;
546 xmlEntityPtr cur;
547 xmlEntitiesTablePtr table;
548
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000549 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
550 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000551 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000552 cur = table->table[i];
553 if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
554 (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000555 (!xmlStrcmp(cur->name, name))) return(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000556 }
557 }
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000558 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
559 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
560 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000561 cur = table->table[i];
562 if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
563 (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
Daniel Veillard1ff7ae31999-09-01 12:19:13 +0000564 (!xmlStrcmp(cur->name, name))) return(cur);
565 }
566 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000567 if (xmlPredefinedEntities == NULL)
568 xmlInitializePredefinedEntities();
569 table = xmlPredefinedEntities;
570 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000571 cur = table->table[i];
572 if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
573 (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
Daniel Veillardb05deb71999-08-10 19:04:08 +0000574 (!xmlStrcmp(cur->name, name))) return(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000575 }
576
577 return(NULL);
578}
579
580/*
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000581 * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
582 * | [#x10000-#x10FFFF]
583 * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
584 */
585#define IS_CHAR(c) \
586 (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
587 (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
588
Daniel Veillard14fff061999-06-22 21:49:07 +0000589/*
590 * A buffer used for converting entities to their equivalent and back.
Daniel Veillard14fff061999-06-22 21:49:07 +0000591 */
592static int buffer_size = 0;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000593static xmlChar *buffer = NULL;
Daniel Veillard14fff061999-06-22 21:49:07 +0000594
Daniel Veillard0142b842000-01-14 14:45:24 +0000595int growBuffer(void) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000596 buffer_size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000597 buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
Daniel Veillard14fff061999-06-22 21:49:07 +0000598 if (buffer == NULL) {
599 perror("realloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000600 return(-1);
Daniel Veillard14fff061999-06-22 21:49:07 +0000601 }
Daniel Veillard0142b842000-01-14 14:45:24 +0000602 return(0);
Daniel Veillard14fff061999-06-22 21:49:07 +0000603}
604
605
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000606/**
607 * xmlEncodeEntities:
608 * @doc: the document containing the string
609 * @input: A string to convert to XML.
610 *
611 * Do a global encoding of a string, replacing the predefined entities
612 * and non ASCII values with their entities and CharRef counterparts.
613 *
Daniel Veillardb96e6431999-08-29 21:02:19 +0000614 * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
615 * compatibility
Daniel Veillard14fff061999-06-22 21:49:07 +0000616 *
617 * People must migrate their code to xmlEncodeEntitiesReentrant !
Daniel Veillardb05deb71999-08-10 19:04:08 +0000618 * This routine will issue a warning when encountered.
Daniel Veillard14fff061999-06-22 21:49:07 +0000619 *
620 * Returns A newly allocated string with the substitution done.
621 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000622const xmlChar *
623xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
624 const xmlChar *cur = input;
625 xmlChar *out = buffer;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000626 static int warning = 1;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000627 int html = 0;
628
Daniel Veillardb05deb71999-08-10 19:04:08 +0000629
630 if (warning) {
631 fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
632 fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n");
633 warning = 0;
634 }
Daniel Veillard14fff061999-06-22 21:49:07 +0000635
636 if (input == NULL) return(NULL);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000637 if (doc != NULL)
638 html = (doc->type == XML_HTML_DOCUMENT_NODE);
639
Daniel Veillard14fff061999-06-22 21:49:07 +0000640 if (buffer == NULL) {
641 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000642 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard14fff061999-06-22 21:49:07 +0000643 if (buffer == NULL) {
644 perror("malloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000645 return(NULL);
Daniel Veillard14fff061999-06-22 21:49:07 +0000646 }
647 out = buffer;
648 }
649 while (*cur != '\0') {
650 if (out - buffer > buffer_size - 100) {
651 int index = out - buffer;
652
653 growBuffer();
654 out = &buffer[index];
655 }
656
657 /*
658 * By default one have to encode at least '<', '>', '"' and '&' !
659 */
660 if (*cur == '<') {
661 *out++ = '&';
662 *out++ = 'l';
663 *out++ = 't';
664 *out++ = ';';
665 } else if (*cur == '>') {
666 *out++ = '&';
667 *out++ = 'g';
668 *out++ = 't';
669 *out++ = ';';
670 } else if (*cur == '&') {
671 *out++ = '&';
672 *out++ = 'a';
673 *out++ = 'm';
674 *out++ = 'p';
675 *out++ = ';';
676 } else if (*cur == '"') {
677 *out++ = '&';
678 *out++ = 'q';
679 *out++ = 'u';
680 *out++ = 'o';
681 *out++ = 't';
682 *out++ = ';';
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000683 } else if ((*cur == '\'') && (!html)) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000684 *out++ = '&';
685 *out++ = 'a';
686 *out++ = 'p';
687 *out++ = 'o';
688 *out++ = 's';
689 *out++ = ';';
690 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
691 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
692 /*
693 * default case, just copy !
694 */
695 *out++ = *cur;
696#ifndef USE_UTF_8
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000697 } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
Daniel Veillard14fff061999-06-22 21:49:07 +0000698 char buf[10], *ptr;
699#ifdef HAVE_SNPRINTF
700 snprintf(buf, 9, "&#%d;", *cur);
701#else
702 sprintf(buf, "&#%d;", *cur);
703#endif
704 ptr = buf;
705 while (*ptr != 0) *out++ = *ptr++;
706#endif
707 } else if (IS_CHAR(*cur)) {
708 char buf[10], *ptr;
709
710#ifdef HAVE_SNPRINTF
711 snprintf(buf, 9, "&#%d;", *cur);
712#else
713 sprintf(buf, "&#%d;", *cur);
714#endif
715 ptr = buf;
716 while (*ptr != 0) *out++ = *ptr++;
717 }
718#if 0
719 else {
720 /*
721 * default case, this is not a valid char !
722 * Skip it...
723 */
724 fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
725 }
726#endif
727 cur++;
728 }
729 *out++ = 0;
730 return(buffer);
731}
732
733/*
734 * Macro used to grow the current buffer.
735 */
736#define growBufferReentrant() { \
737 buffer_size *= 2; \
Daniel Veillard0142b842000-01-14 14:45:24 +0000738 buffer = (xmlChar *) \
739 xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
Daniel Veillard14fff061999-06-22 21:49:07 +0000740 if (buffer == NULL) { \
741 perror("realloc failed"); \
Daniel Veillard0142b842000-01-14 14:45:24 +0000742 return(NULL); \
Daniel Veillard14fff061999-06-22 21:49:07 +0000743 } \
744}
745
746
747/**
748 * xmlEncodeEntitiesReentrant:
749 * @doc: the document containing the string
750 * @input: A string to convert to XML.
751 *
752 * Do a global encoding of a string, replacing the predefined entities
753 * and non ASCII values with their entities and CharRef counterparts.
754 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
755 * must be deallocated.
756 *
757 * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
758 * get erroneous.
759 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000760 * Returns A newly allocated string with the substitution done.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000761 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000762xmlChar *
763xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
764 const xmlChar *cur = input;
765 xmlChar *buffer = NULL;
766 xmlChar *out = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000767 int buffer_size = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000768 int html = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000769
Daniel Veillard242590e1998-11-13 18:04:35 +0000770 if (input == NULL) return(NULL);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000771 if (doc != NULL)
772 html = (doc->type == XML_HTML_DOCUMENT_NODE);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000773
774 /*
775 * allocate an translation buffer.
776 */
777 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000778 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000779 if (buffer == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000780 perror("malloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000781 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000782 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000783 out = buffer;
784
Daniel Veillard260a68f1998-08-13 03:39:55 +0000785 while (*cur != '\0') {
786 if (out - buffer > buffer_size - 100) {
787 int index = out - buffer;
788
Daniel Veillard14fff061999-06-22 21:49:07 +0000789 growBufferReentrant();
Daniel Veillard260a68f1998-08-13 03:39:55 +0000790 out = &buffer[index];
791 }
792
793 /*
794 * By default one have to encode at least '<', '>', '"' and '&' !
Daniel Veillard260a68f1998-08-13 03:39:55 +0000795 */
796 if (*cur == '<') {
797 *out++ = '&';
798 *out++ = 'l';
799 *out++ = 't';
800 *out++ = ';';
801 } else if (*cur == '>') {
802 *out++ = '&';
803 *out++ = 'g';
804 *out++ = 't';
805 *out++ = ';';
806 } else if (*cur == '&') {
807 *out++ = '&';
808 *out++ = 'a';
809 *out++ = 'm';
810 *out++ = 'p';
811 *out++ = ';';
812 } else if (*cur == '"') {
813 *out++ = '&';
814 *out++ = 'q';
815 *out++ = 'u';
816 *out++ = 'o';
817 *out++ = 't';
818 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000819#if 0
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000820 } else if ((*cur == '\'') && (!html)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000821 *out++ = '&';
822 *out++ = 'a';
823 *out++ = 'p';
824 *out++ = 'o';
825 *out++ = 's';
826 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000827#endif
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000828 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
829 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
830 /*
831 * default case, just copy !
832 */
833 *out++ = *cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000834 } else if (*cur >= 0x80) {
835 if (html) {
836 char buf[15], *ptr;
837
838 /*
839 * TODO: improve by searching in html40EntitiesTable
840 */
Daniel Veillardda4d3c41998-11-04 20:07:05 +0000841#ifdef HAVE_SNPRINTF
Daniel Veillardcf461992000-03-14 18:30:20 +0000842 snprintf(buf, 9, "&#%d;", *cur);
Daniel Veillardda4d3c41998-11-04 20:07:05 +0000843#else
Daniel Veillardcf461992000-03-14 18:30:20 +0000844 sprintf(buf, "&#%d;", *cur);
Daniel Veillardda4d3c41998-11-04 20:07:05 +0000845#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000846 ptr = buf;
847 while (*ptr != 0) *out++ = *ptr++;
848 } else if (doc->encoding != NULL) {
849 /*
850 * TODO !!!
851 */
852 *out++ = *cur;
853 } else {
854 /*
855 * We assume we have UTF-8 input.
856 */
857 char buf[10], *ptr;
858 int val = 0, l = 1;
859
860 if (*cur < 0xC0) {
861 fprintf(stderr,
862 "xmlEncodeEntitiesReentrant : input not UTF-8\n");
863 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
864#ifdef HAVE_SNPRINTF
865 snprintf(buf, 9, "&#%d;", *cur);
866#else
867 sprintf(buf, "&#%d;", *cur);
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000868#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000869 ptr = buf;
870 while (*ptr != 0) *out++ = *ptr++;
871 continue;
872 } else if (*cur < 0xE0) {
873 val = (cur[0]) & 0x1F;
874 val <<= 6;
875 val |= (cur[1]) & 0x3F;
876 l = 2;
877 } else if (*cur < 0xF0) {
878 val = (cur[0]) & 0x0F;
879 val <<= 6;
880 val |= (cur[1]) & 0x3F;
881 val <<= 6;
882 val |= (cur[2]) & 0x3F;
883 l = 3;
884 } else if (*cur < 0xF8) {
885 val = (cur[0]) & 0x07;
886 val <<= 6;
887 val |= (cur[1]) & 0x3F;
888 val <<= 6;
889 val |= (cur[2]) & 0x3F;
890 val <<= 6;
891 val |= (cur[3]) & 0x3F;
892 l = 4;
893 }
894 if ((l == 1) || (!IS_CHAR(val))) {
895 fprintf(stderr,
896 "xmlEncodeEntitiesReentrant : char out of range\n");
897 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
898#ifdef HAVE_SNPRINTF
899 snprintf(buf, 9, "&#%d;", *cur);
900#else
901 sprintf(buf, "&#%d;", *cur);
902#endif
903 ptr = buf;
904 while (*ptr != 0) *out++ = *ptr++;
905 cur++;
906 continue;
907 }
908 /*
909 * We could do multiple things here. Just save as a char ref
910 */
911#ifdef HAVE_SNPRINTF
912 snprintf(buf, 14, "&#x%X;", val);
913#else
914 sprintf(buf, "&#x%X;", val);
915#endif
916 buf[14] = 0;
917 ptr = buf;
918 while (*ptr != 0) *out++ = *ptr++;
919 cur += l;
920 continue;
921 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000922 } else if (IS_CHAR(*cur)) {
923 char buf[10], *ptr;
924
925#ifdef HAVE_SNPRINTF
926 snprintf(buf, 9, "&#%d;", *cur);
927#else
928 sprintf(buf, "&#%d;", *cur);
929#endif
930 ptr = buf;
931 while (*ptr != 0) *out++ = *ptr++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000932 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000933#if 0
934 else {
935 /*
936 * default case, this is not a valid char !
937 * Skip it...
938 */
939 fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
940 }
941#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 cur++;
943 }
944 *out++ = 0;
945 return(buffer);
946}
947
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000948/**
949 * xmlCreateEntitiesTable:
950 *
951 * create and initialize an empty entities hash table.
952 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000953 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000954 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000955xmlEntitiesTablePtr
956xmlCreateEntitiesTable(void) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000957 xmlEntitiesTablePtr ret;
958
959 ret = (xmlEntitiesTablePtr)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000960 xmlMalloc(sizeof(xmlEntitiesTable));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000961 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000962 fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
Daniel Veillardbe70ff71999-07-05 16:50:46 +0000963 (long)sizeof(xmlEntitiesTable));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000964 return(NULL);
965 }
966 ret->max_entities = XML_MIN_ENTITIES_TABLE;
967 ret->nb_entities = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000968 ret->table = (xmlEntityPtr *)
969 xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000970 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000971 fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000972 ret->max_entities * (long)sizeof(xmlEntityPtr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000973 xmlFree(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000974 return(NULL);
975 }
976 return(ret);
977}
978
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000979/**
980 * xmlFreeEntitiesTable:
981 * @table: An entity table
982 *
983 * Deallocate the memory used by an entities hash table.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000984 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000985void
986xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000987 int i;
988
989 if (table == NULL) return;
990
991 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000992 xmlFreeEntity(table->table[i]);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000994 xmlFree(table->table);
995 xmlFree(table);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000996}
997
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000998/**
999 * xmlCopyEntitiesTable:
1000 * @table: An entity table
1001 *
1002 * Build a copy of an entity table.
1003 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001004 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001005 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001006xmlEntitiesTablePtr
1007xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
1008 xmlEntitiesTablePtr ret;
1009 xmlEntityPtr cur, ent;
1010 int i;
1011
Daniel Veillard6454aec1999-09-02 22:04:43 +00001012 ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001013 if (ret == NULL) {
1014 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1015 return(NULL);
1016 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001017 ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
1018 sizeof(xmlEntityPtr));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001019 if (ret->table == NULL) {
1020 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00001021 xmlFree(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001022 return(NULL);
1023 }
1024 ret->max_entities = table->max_entities;
1025 ret->nb_entities = table->nb_entities;
1026 for (i = 0;i < ret->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001027 cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
1028 if (cur == NULL) {
1029 fprintf(stderr, "xmlCopyEntityTable: out of memory !\n");
1030 xmlFree(ret);
1031 xmlFree(ret->table);
1032 return(NULL);
1033 }
1034 memset(cur, 0, sizeof(xmlEntity));
1035 cur->type = XML_ELEMENT_DECL;
1036 ret->table[i] = cur;
1037 ent = table->table[i];
1038
1039 cur->etype = ent->etype;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001040 if (ent->name != NULL)
1041 cur->name = xmlStrdup(ent->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001042 if (ent->ExternalID != NULL)
1043 cur->ExternalID = xmlStrdup(ent->ExternalID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001044 if (ent->SystemID != NULL)
1045 cur->SystemID = xmlStrdup(ent->SystemID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001046 if (ent->content != NULL)
1047 cur->content = xmlStrdup(ent->content);
Daniel Veillard011b63c1999-06-02 17:44:04 +00001048 if (ent->orig != NULL)
1049 cur->orig = xmlStrdup(ent->orig);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001050 }
1051 return(ret);
1052}
1053
1054/**
Daniel Veillardcf461992000-03-14 18:30:20 +00001055 * xmlDumpEntityDecl:
1056 * @buf: An XML buffer.
1057 * @ent: An entity table
1058 *
1059 * This will dump the content of the entity table as an XML DTD definition
1060 */
1061void
1062xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
1063 switch (ent->etype) {
1064 case XML_INTERNAL_GENERAL_ENTITY:
1065 xmlBufferWriteChar(buf, "<!ENTITY ");
1066 xmlBufferWriteCHAR(buf, ent->name);
1067 xmlBufferWriteChar(buf, " ");
1068 if (ent->orig != NULL)
1069 xmlBufferWriteQuotedString(buf, ent->orig);
1070 else
1071 xmlBufferWriteQuotedString(buf, ent->content);
1072 xmlBufferWriteChar(buf, ">\n");
1073 break;
1074 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1075 xmlBufferWriteChar(buf, "<!ENTITY ");
1076 xmlBufferWriteCHAR(buf, ent->name);
1077 if (ent->ExternalID != NULL) {
1078 xmlBufferWriteChar(buf, " PUBLIC ");
1079 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1080 xmlBufferWriteChar(buf, " ");
1081 xmlBufferWriteQuotedString(buf, ent->SystemID);
1082 } else {
1083 xmlBufferWriteChar(buf, " SYSTEM ");
1084 xmlBufferWriteQuotedString(buf, ent->SystemID);
1085 }
1086 xmlBufferWriteChar(buf, ">\n");
1087 break;
1088 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1089 xmlBufferWriteChar(buf, "<!ENTITY ");
1090 xmlBufferWriteCHAR(buf, ent->name);
1091 if (ent->ExternalID != NULL) {
1092 xmlBufferWriteChar(buf, " PUBLIC ");
1093 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1094 xmlBufferWriteChar(buf, " ");
1095 xmlBufferWriteQuotedString(buf, ent->SystemID);
1096 } else {
1097 xmlBufferWriteChar(buf, " SYSTEM ");
1098 xmlBufferWriteQuotedString(buf, ent->SystemID);
1099 }
1100 if (ent->content != NULL) { /* Should be true ! */
1101 xmlBufferWriteChar(buf, " NDATA ");
1102 if (ent->orig != NULL)
1103 xmlBufferWriteCHAR(buf, ent->orig);
1104 else
1105 xmlBufferWriteCHAR(buf, ent->content);
1106 }
1107 xmlBufferWriteChar(buf, ">\n");
1108 break;
1109 case XML_INTERNAL_PARAMETER_ENTITY:
1110 xmlBufferWriteChar(buf, "<!ENTITY % ");
1111 xmlBufferWriteCHAR(buf, ent->name);
1112 xmlBufferWriteChar(buf, " ");
1113 if (ent->orig == NULL)
1114 xmlBufferWriteQuotedString(buf, ent->content);
1115 else
1116 xmlBufferWriteQuotedString(buf, ent->orig);
1117 xmlBufferWriteChar(buf, ">\n");
1118 break;
1119 case XML_EXTERNAL_PARAMETER_ENTITY:
1120 xmlBufferWriteChar(buf, "<!ENTITY % ");
1121 xmlBufferWriteCHAR(buf, ent->name);
1122 if (ent->ExternalID != NULL) {
1123 xmlBufferWriteChar(buf, " PUBLIC ");
1124 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1125 xmlBufferWriteChar(buf, " ");
1126 xmlBufferWriteQuotedString(buf, ent->SystemID);
1127 } else {
1128 xmlBufferWriteChar(buf, " SYSTEM ");
1129 xmlBufferWriteQuotedString(buf, ent->SystemID);
1130 }
1131 xmlBufferWriteChar(buf, ">\n");
1132 break;
1133 default:
1134 fprintf(stderr,
1135 "xmlDumpEntitiesTable: internal: unknown type %d\n",
1136 ent->etype);
1137 }
1138}
1139
1140/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001141 * xmlDumpEntitiesTable:
Daniel Veillard5099ae81999-04-21 20:12:07 +00001142 * @buf: An XML buffer.
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001143 * @table: An entity table
1144 *
1145 * This will dump the content of the entity table as an XML DTD definition
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001146 */
1147void
Daniel Veillard5099ae81999-04-21 20:12:07 +00001148xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149 int i;
1150 xmlEntityPtr cur;
1151
1152 if (table == NULL) return;
1153
1154 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001155 cur = table->table[i];
1156 xmlDumpEntityDecl(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001157 }
1158}