blob: 75059433478ed09e45a04726e21261f89f7b3293 [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);
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000131 ret->etype = (xmlEntityType) type;
Daniel Veillardcf461992000-03-14 18:30:20 +0000132 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 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000757 * Returns A newly allocated string with the substitution done.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000758 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000759xmlChar *
760xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
761 const xmlChar *cur = input;
762 xmlChar *buffer = NULL;
763 xmlChar *out = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000764 int buffer_size = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000765 int html = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000766
Daniel Veillard242590e1998-11-13 18:04:35 +0000767 if (input == NULL) return(NULL);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000768 if (doc != NULL)
769 html = (doc->type == XML_HTML_DOCUMENT_NODE);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000770
771 /*
772 * allocate an translation buffer.
773 */
774 buffer_size = 1000;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000775 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000776 if (buffer == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000777 perror("malloc failed");
Daniel Veillard0142b842000-01-14 14:45:24 +0000778 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000779 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000780 out = buffer;
781
Daniel Veillard260a68f1998-08-13 03:39:55 +0000782 while (*cur != '\0') {
783 if (out - buffer > buffer_size - 100) {
784 int index = out - buffer;
785
Daniel Veillard14fff061999-06-22 21:49:07 +0000786 growBufferReentrant();
Daniel Veillard260a68f1998-08-13 03:39:55 +0000787 out = &buffer[index];
788 }
789
790 /*
791 * By default one have to encode at least '<', '>', '"' and '&' !
Daniel Veillard260a68f1998-08-13 03:39:55 +0000792 */
793 if (*cur == '<') {
794 *out++ = '&';
795 *out++ = 'l';
796 *out++ = 't';
797 *out++ = ';';
798 } else if (*cur == '>') {
799 *out++ = '&';
800 *out++ = 'g';
801 *out++ = 't';
802 *out++ = ';';
803 } else if (*cur == '&') {
804 *out++ = '&';
805 *out++ = 'a';
806 *out++ = 'm';
807 *out++ = 'p';
808 *out++ = ';';
809 } else if (*cur == '"') {
810 *out++ = '&';
811 *out++ = 'q';
812 *out++ = 'u';
813 *out++ = 'o';
814 *out++ = 't';
815 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000816#if 0
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000817 } else if ((*cur == '\'') && (!html)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818 *out++ = '&';
819 *out++ = 'a';
820 *out++ = 'p';
821 *out++ = 'o';
822 *out++ = 's';
823 *out++ = ';';
Daniel Veillardcf461992000-03-14 18:30:20 +0000824#endif
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000825 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
826 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
827 /*
828 * default case, just copy !
829 */
830 *out++ = *cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000831 } else if (*cur >= 0x80) {
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000832 if ((doc->encoding != NULL) || (html)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000833 /*
834 * TODO !!!
835 */
836 *out++ = *cur;
837 } else {
838 /*
839 * We assume we have UTF-8 input.
840 */
841 char buf[10], *ptr;
842 int val = 0, l = 1;
843
844 if (*cur < 0xC0) {
845 fprintf(stderr,
846 "xmlEncodeEntitiesReentrant : input not UTF-8\n");
847 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
848#ifdef HAVE_SNPRINTF
849 snprintf(buf, 9, "&#%d;", *cur);
850#else
851 sprintf(buf, "&#%d;", *cur);
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000852#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000853 ptr = buf;
854 while (*ptr != 0) *out++ = *ptr++;
855 continue;
856 } else if (*cur < 0xE0) {
857 val = (cur[0]) & 0x1F;
858 val <<= 6;
859 val |= (cur[1]) & 0x3F;
860 l = 2;
861 } else if (*cur < 0xF0) {
862 val = (cur[0]) & 0x0F;
863 val <<= 6;
864 val |= (cur[1]) & 0x3F;
865 val <<= 6;
866 val |= (cur[2]) & 0x3F;
867 l = 3;
868 } else if (*cur < 0xF8) {
869 val = (cur[0]) & 0x07;
870 val <<= 6;
871 val |= (cur[1]) & 0x3F;
872 val <<= 6;
873 val |= (cur[2]) & 0x3F;
874 val <<= 6;
875 val |= (cur[3]) & 0x3F;
876 l = 4;
877 }
878 if ((l == 1) || (!IS_CHAR(val))) {
879 fprintf(stderr,
880 "xmlEncodeEntitiesReentrant : char out of range\n");
881 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
882#ifdef HAVE_SNPRINTF
883 snprintf(buf, 9, "&#%d;", *cur);
884#else
885 sprintf(buf, "&#%d;", *cur);
886#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000887 buf[9] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000888 ptr = buf;
889 while (*ptr != 0) *out++ = *ptr++;
890 cur++;
891 continue;
892 }
893 /*
894 * We could do multiple things here. Just save as a char ref
895 */
896#ifdef HAVE_SNPRINTF
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000897 snprintf(buf, 9, "&#x%X;", val);
Daniel Veillardcf461992000-03-14 18:30:20 +0000898#else
899 sprintf(buf, "&#x%X;", val);
900#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000901 buf[9] = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +0000902 ptr = buf;
903 while (*ptr != 0) *out++ = *ptr++;
904 cur += l;
905 continue;
906 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000907 } else if (IS_CHAR(*cur)) {
908 char buf[10], *ptr;
909
910#ifdef HAVE_SNPRINTF
911 snprintf(buf, 9, "&#%d;", *cur);
912#else
913 sprintf(buf, "&#%d;", *cur);
914#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000915 buf[9] = 0;
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000916 ptr = buf;
917 while (*ptr != 0) *out++ = *ptr++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000918 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000919#if 0
920 else {
921 /*
922 * default case, this is not a valid char !
923 * Skip it...
924 */
925 fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
926 }
927#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000928 cur++;
929 }
930 *out++ = 0;
931 return(buffer);
932}
933
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000934/**
Daniel Veillardbe803962000-06-28 23:40:59 +0000935 * xmlEncodeSpecialChars:
936 * @doc: the document containing the string
937 * @input: A string to convert to XML.
938 *
939 * Do a global encoding of a string, replacing the predefined entities
940 * this routine is reentrant, and result must be deallocated.
941 *
942 * Returns A newly allocated string with the substitution done.
943 */
944xmlChar *
945xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
946 const xmlChar *cur = input;
947 xmlChar *buffer = NULL;
948 xmlChar *out = NULL;
949 int buffer_size = 0;
950 int html = 0;
951
952 if (input == NULL) return(NULL);
953 if (doc != NULL)
954 html = (doc->type == XML_HTML_DOCUMENT_NODE);
955
956 /*
957 * allocate an translation buffer.
958 */
959 buffer_size = 1000;
960 buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
961 if (buffer == NULL) {
962 perror("malloc failed");
963 return(NULL);
964 }
965 out = buffer;
966
967 while (*cur != '\0') {
968 if (out - buffer > buffer_size - 10) {
969 int index = out - buffer;
970
971 growBufferReentrant();
972 out = &buffer[index];
973 }
974
975 /*
976 * By default one have to encode at least '<', '>', '"' and '&' !
977 */
978 if (*cur == '<') {
979 *out++ = '&';
980 *out++ = 'l';
981 *out++ = 't';
982 *out++ = ';';
983 } else if (*cur == '>') {
984 *out++ = '&';
985 *out++ = 'g';
986 *out++ = 't';
987 *out++ = ';';
988 } else if (*cur == '&') {
989 *out++ = '&';
990 *out++ = 'a';
991 *out++ = 'm';
992 *out++ = 'p';
993 *out++ = ';';
994 } else if (*cur == '"') {
995 *out++ = '&';
996 *out++ = 'q';
997 *out++ = 'u';
998 *out++ = 'o';
999 *out++ = 't';
1000 *out++ = ';';
1001 } else {
1002 /*
1003 * Works because on UTF-8, all extended sequences cannot
1004 * result in bytes in the ASCII range.
1005 */
1006 *out++ = *cur;
1007 }
1008 cur++;
1009 }
1010 *out++ = 0;
1011 return(buffer);
1012}
1013
1014/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001015 * xmlCreateEntitiesTable:
1016 *
1017 * create and initialize an empty entities hash table.
1018 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001019 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001020 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001021xmlEntitiesTablePtr
1022xmlCreateEntitiesTable(void) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001023 xmlEntitiesTablePtr ret;
1024
1025 ret = (xmlEntitiesTablePtr)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001026 xmlMalloc(sizeof(xmlEntitiesTable));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001027 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00001028 fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001029 (long)sizeof(xmlEntitiesTable));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001030 return(NULL);
1031 }
1032 ret->max_entities = XML_MIN_ENTITIES_TABLE;
1033 ret->nb_entities = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +00001034 ret->table = (xmlEntityPtr *)
1035 xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001036 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00001037 fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
Daniel Veillardcf461992000-03-14 18:30:20 +00001038 ret->max_entities * (long)sizeof(xmlEntityPtr));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001039 xmlFree(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001040 return(NULL);
1041 }
1042 return(ret);
1043}
1044
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001045/**
1046 * xmlFreeEntitiesTable:
1047 * @table: An entity table
1048 *
1049 * Deallocate the memory used by an entities hash table.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001050 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001051void
1052xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001053 int i;
1054
1055 if (table == NULL) return;
1056
1057 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001058 xmlFreeEntity(table->table[i]);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001059 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00001060 xmlFree(table->table);
1061 xmlFree(table);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001062}
1063
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001064/**
1065 * xmlCopyEntitiesTable:
1066 * @table: An entity table
1067 *
1068 * Build a copy of an entity table.
1069 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001070 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001071 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001072xmlEntitiesTablePtr
1073xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
1074 xmlEntitiesTablePtr ret;
1075 xmlEntityPtr cur, ent;
1076 int i;
1077
Daniel Veillard6454aec1999-09-02 22:04:43 +00001078 ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001079 if (ret == NULL) {
1080 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1081 return(NULL);
1082 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001083 ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
1084 sizeof(xmlEntityPtr));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001085 if (ret->table == NULL) {
1086 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00001087 xmlFree(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001088 return(NULL);
1089 }
1090 ret->max_entities = table->max_entities;
1091 ret->nb_entities = table->nb_entities;
1092 for (i = 0;i < ret->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001093 cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
1094 if (cur == NULL) {
1095 fprintf(stderr, "xmlCopyEntityTable: out of memory !\n");
1096 xmlFree(ret);
1097 xmlFree(ret->table);
1098 return(NULL);
1099 }
1100 memset(cur, 0, sizeof(xmlEntity));
1101 cur->type = XML_ELEMENT_DECL;
1102 ret->table[i] = cur;
1103 ent = table->table[i];
1104
1105 cur->etype = ent->etype;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001106 if (ent->name != NULL)
1107 cur->name = xmlStrdup(ent->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001108 if (ent->ExternalID != NULL)
1109 cur->ExternalID = xmlStrdup(ent->ExternalID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001110 if (ent->SystemID != NULL)
1111 cur->SystemID = xmlStrdup(ent->SystemID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001112 if (ent->content != NULL)
1113 cur->content = xmlStrdup(ent->content);
Daniel Veillard011b63c1999-06-02 17:44:04 +00001114 if (ent->orig != NULL)
1115 cur->orig = xmlStrdup(ent->orig);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001116 }
1117 return(ret);
1118}
1119
1120/**
Daniel Veillardcf461992000-03-14 18:30:20 +00001121 * xmlDumpEntityDecl:
1122 * @buf: An XML buffer.
1123 * @ent: An entity table
1124 *
1125 * This will dump the content of the entity table as an XML DTD definition
1126 */
1127void
1128xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
1129 switch (ent->etype) {
1130 case XML_INTERNAL_GENERAL_ENTITY:
1131 xmlBufferWriteChar(buf, "<!ENTITY ");
1132 xmlBufferWriteCHAR(buf, ent->name);
1133 xmlBufferWriteChar(buf, " ");
1134 if (ent->orig != NULL)
1135 xmlBufferWriteQuotedString(buf, ent->orig);
1136 else
1137 xmlBufferWriteQuotedString(buf, ent->content);
1138 xmlBufferWriteChar(buf, ">\n");
1139 break;
1140 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1141 xmlBufferWriteChar(buf, "<!ENTITY ");
1142 xmlBufferWriteCHAR(buf, ent->name);
1143 if (ent->ExternalID != NULL) {
1144 xmlBufferWriteChar(buf, " PUBLIC ");
1145 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1146 xmlBufferWriteChar(buf, " ");
1147 xmlBufferWriteQuotedString(buf, ent->SystemID);
1148 } else {
1149 xmlBufferWriteChar(buf, " SYSTEM ");
1150 xmlBufferWriteQuotedString(buf, ent->SystemID);
1151 }
1152 xmlBufferWriteChar(buf, ">\n");
1153 break;
1154 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1155 xmlBufferWriteChar(buf, "<!ENTITY ");
1156 xmlBufferWriteCHAR(buf, ent->name);
1157 if (ent->ExternalID != NULL) {
1158 xmlBufferWriteChar(buf, " PUBLIC ");
1159 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1160 xmlBufferWriteChar(buf, " ");
1161 xmlBufferWriteQuotedString(buf, ent->SystemID);
1162 } else {
1163 xmlBufferWriteChar(buf, " SYSTEM ");
1164 xmlBufferWriteQuotedString(buf, ent->SystemID);
1165 }
1166 if (ent->content != NULL) { /* Should be true ! */
1167 xmlBufferWriteChar(buf, " NDATA ");
1168 if (ent->orig != NULL)
1169 xmlBufferWriteCHAR(buf, ent->orig);
1170 else
1171 xmlBufferWriteCHAR(buf, ent->content);
1172 }
1173 xmlBufferWriteChar(buf, ">\n");
1174 break;
1175 case XML_INTERNAL_PARAMETER_ENTITY:
1176 xmlBufferWriteChar(buf, "<!ENTITY % ");
1177 xmlBufferWriteCHAR(buf, ent->name);
1178 xmlBufferWriteChar(buf, " ");
1179 if (ent->orig == NULL)
1180 xmlBufferWriteQuotedString(buf, ent->content);
1181 else
1182 xmlBufferWriteQuotedString(buf, ent->orig);
1183 xmlBufferWriteChar(buf, ">\n");
1184 break;
1185 case XML_EXTERNAL_PARAMETER_ENTITY:
1186 xmlBufferWriteChar(buf, "<!ENTITY % ");
1187 xmlBufferWriteCHAR(buf, ent->name);
1188 if (ent->ExternalID != NULL) {
1189 xmlBufferWriteChar(buf, " PUBLIC ");
1190 xmlBufferWriteQuotedString(buf, ent->ExternalID);
1191 xmlBufferWriteChar(buf, " ");
1192 xmlBufferWriteQuotedString(buf, ent->SystemID);
1193 } else {
1194 xmlBufferWriteChar(buf, " SYSTEM ");
1195 xmlBufferWriteQuotedString(buf, ent->SystemID);
1196 }
1197 xmlBufferWriteChar(buf, ">\n");
1198 break;
1199 default:
1200 fprintf(stderr,
1201 "xmlDumpEntitiesTable: internal: unknown type %d\n",
1202 ent->etype);
1203 }
1204}
1205
1206/**
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001207 * xmlDumpEntitiesTable:
Daniel Veillard5099ae81999-04-21 20:12:07 +00001208 * @buf: An XML buffer.
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001209 * @table: An entity table
1210 *
1211 * This will dump the content of the entity table as an XML DTD definition
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001212 */
1213void
Daniel Veillard5099ae81999-04-21 20:12:07 +00001214xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001215 int i;
1216 xmlEntityPtr cur;
1217
1218 if (table == NULL) return;
1219
1220 for (i = 0;i < table->nb_entities;i++) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001221 cur = table->table[i];
1222 xmlDumpEntityDecl(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001223 }
1224}