Annotation of XML/entities.c, revision 1.62
1.1 httpng 1: /*
2: * entities.c : implementation for the XML entities handking
1.9 veillard 3: *
4: * See Copyright for the status of this software.
5: *
1.23 daniel 6: * Daniel.Veillard@w3.org
1.1 httpng 7: */
8:
1.42 daniel 9: #ifdef WIN32
10: #include "win32config.h"
11: #else
1.37 daniel 12: #include "config.h"
13: #endif
14:
1.1 httpng 15: #include <stdio.h>
1.37 daniel 16: #include <string.h>
17: #ifdef HAVE_STDLIB_H
1.17 daniel 18: #include <stdlib.h>
1.37 daniel 19: #endif
1.56 daniel 20: #include <libxml/xmlmemory.h>
21: #include <libxml/entities.h>
22: #include <libxml/parser.h>
1.1 httpng 23:
1.54 daniel 24: #define DEBUG_ENT_REF /* debugging of cross entities dependancies */
1.61 veillard 25: #define ENTITY_HASH_SIZE 256 /* modify xmlEntityComputeHash accordingly */
26:
27: /*
28: * xmlEntityComputeHash:
29: *
30: * Computes the hash value for this given entity
31: */
32: int
33: xmlEntityComputeHash(const xmlChar *name) {
34: register const unsigned char *cur = (const unsigned char *) name;
35: register unsigned char val = 0;
36:
37: if (name == NULL)
38: return(val);
39: while (*cur) val += *cur++;
40: return(val);
41: }
1.54 daniel 42:
1.1 httpng 43: /*
1.15 daniel 44: * The XML predefined entities.
45: */
46:
47: struct xmlPredefinedEntityValue {
48: const char *name;
49: const char *value;
50: };
51: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
52: { "lt", "<" },
53: { "gt", ">" },
54: { "apos", "'" },
55: { "quot", "\"" },
56: { "amp", "&" }
57: };
58:
1.61 veillard 59: /*
60: * TODO: !!!!!!! This is GROSS, allocation of a 256 entry hash for
61: * a fixed number of 4 elements !
62: */
1.15 daniel 63: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
64:
65: /*
1.2 httpng 66: * xmlFreeEntity : clean-up an entity record.
1.1 httpng 67: */
1.2 httpng 68: void xmlFreeEntity(xmlEntityPtr entity) {
69: if (entity == NULL) return;
70:
1.52 daniel 71: if (entity->children)
72: xmlFreeNodeList(entity->children);
1.11 daniel 73: if (entity->name != NULL)
1.36 daniel 74: xmlFree((char *) entity->name);
1.14 daniel 75: if (entity->ExternalID != NULL)
1.36 daniel 76: xmlFree((char *) entity->ExternalID);
1.14 daniel 77: if (entity->SystemID != NULL)
1.36 daniel 78: xmlFree((char *) entity->SystemID);
1.14 daniel 79: if (entity->content != NULL)
1.36 daniel 80: xmlFree((char *) entity->content);
1.27 daniel 81: if (entity->orig != NULL)
1.36 daniel 82: xmlFree((char *) entity->orig);
1.55 daniel 83: #ifdef WITH_EXTRA_ENT_DETECT
1.54 daniel 84: if (entity->entTab != NULL) {
85: int i;
86:
87: for (i = 0; i < entity->entNr; i++)
88: xmlFree(entity->entTab[i]);
89: xmlFree(entity->entTab);
90: }
1.55 daniel 91: #endif
1.14 daniel 92: memset(entity, -1, sizeof(xmlEntity));
1.51 daniel 93: xmlFree(entity);
1.2 httpng 94: }
1.1 httpng 95:
96: /*
1.22 daniel 97: * xmlAddEntity : register a new entity for an entities table.
1.1 httpng 98: */
1.51 daniel 99: static xmlEntityPtr
1.38 daniel 100: xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
1.61 veillard 101: const xmlChar *ExternalID, const xmlChar *SystemID,
102: const xmlChar *content) {
103: #ifndef ENTITY_HASH_SIZE
1.2 httpng 104: int i;
1.61 veillard 105: #endif
106: int hash;
1.51 daniel 107: xmlEntityPtr ret;
1.1 httpng 108:
1.61 veillard 109: if (name == NULL)
110: return(NULL);
111: #ifdef ENTITY_HASH_SIZE
112: hash = xmlEntityComputeHash(name);
113: ret = table->table[hash];
114: while (ret != NULL) {
115: if (!xmlStrcmp(ret->name, name)) {
116: /*
117: * The entity is already defined in this Dtd, the spec says to NOT
118: * override it ... Is it worth a Warning ??? !!!
119: * Not having a cprinting context this seems hard ...
120: */
121: if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
122: (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
123: ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
124: (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
125: return(NULL);
126: else
127: if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
128: (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
129: ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
130: (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
131: return(NULL);
132: }
133: ret = ret->nexte;
134: }
135: #else
1.2 httpng 136: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 137: ret = table->table[i];
138: if (!xmlStrcmp(ret->name, name)) {
1.13 daniel 139: /*
140: * The entity is already defined in this Dtd, the spec says to NOT
141: * override it ... Is it worth a Warning ??? !!!
1.33 daniel 142: * Not having a cprinting context this seems hard ...
1.13 daniel 143: */
1.30 daniel 144: if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
145: (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51 daniel 146: ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
147: (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
148: return(NULL);
1.30 daniel 149: else
150: if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
151: (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51 daniel 152: ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
153: (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
154: return(NULL);
1.7 veillard 155: }
1.2 httpng 156: }
157: if (table->nb_entities >= table->max_entities) {
158: /*
159: * need more elements.
160: */
161: table->max_entities *= 2;
1.51 daniel 162: table->table = (xmlEntityPtr *)
163: xmlRealloc(table->table,
164: table->max_entities * sizeof(xmlEntityPtr));
1.29 daniel 165: if (table->table == NULL) {
1.2 httpng 166: perror("realloc failed");
1.51 daniel 167: return(NULL);
1.2 httpng 168: }
169: }
1.61 veillard 170: #endif
1.51 daniel 171: ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
172: if (ret == NULL) {
173: fprintf(stderr, "xmlAddEntity: out of memory\n");
174: return(NULL);
175: }
176: memset(ret, 0, sizeof(xmlEntity));
177: ret->type = XML_ENTITY_DECL;
1.61 veillard 178: #ifdef ENTITY_HASH_SIZE
179: ret->nexte = table->table[hash];
180: table->table[hash] = ret;
181: #else
1.51 daniel 182: table->table[table->nb_entities] = ret;
1.61 veillard 183: #endif
1.51 daniel 184:
185: /*
186: * fill the structure.
187: */
188: ret->name = xmlStrdup(name);
1.58 veillard 189: ret->etype = (xmlEntityType) type;
1.13 daniel 190: if (ExternalID != NULL)
1.51 daniel 191: ret->ExternalID = xmlStrdup(ExternalID);
1.13 daniel 192: if (SystemID != NULL)
1.51 daniel 193: ret->SystemID = xmlStrdup(SystemID);
1.43 daniel 194: if (content != NULL) {
1.51 daniel 195: ret->length = xmlStrlen(content);
196: ret->content = xmlStrndup(content, ret->length);
1.43 daniel 197: } else {
1.51 daniel 198: ret->length = 0;
199: ret->content = NULL;
1.43 daniel 200: }
1.62 ! veillard 201: ret->URI = NULL; /* to be computed by the layer knowing
! 202: the defining entity */
1.51 daniel 203: ret->orig = NULL;
1.2 httpng 204: table->nb_entities++;
1.51 daniel 205:
206: return(ret);
1.2 httpng 207: }
1.1 httpng 208:
1.22 daniel 209: /**
210: * xmlInitializePredefinedEntities:
211: *
212: * Set up the predefined entities.
1.15 daniel 213: */
214: void xmlInitializePredefinedEntities(void) {
215: int i;
1.38 daniel 216: xmlChar name[50];
217: xmlChar value[50];
1.15 daniel 218: const char *in;
1.38 daniel 219: xmlChar *out;
1.15 daniel 220:
221: if (xmlPredefinedEntities != NULL) return;
222:
223: xmlPredefinedEntities = xmlCreateEntitiesTable();
224: for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
225: sizeof(xmlPredefinedEntityValues[0]);i++) {
226: in = xmlPredefinedEntityValues[i].name;
227: out = &name[0];
1.38 daniel 228: for (;(*out++ = (xmlChar) *in);)in++;
1.15 daniel 229: in = xmlPredefinedEntityValues[i].value;
230: out = &value[0];
1.38 daniel 231: for (;(*out++ = (xmlChar) *in);)in++;
232: xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
1.18 daniel 233: XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15 daniel 234: &value[0]);
235: }
236: }
1.17 daniel 237:
238: /**
1.40 daniel 239: * xmlCleanupPredefinedEntities:
240: *
241: * Cleanup up the predefined entities table.
242: */
243: void xmlCleanupPredefinedEntities(void) {
244: if (xmlPredefinedEntities == NULL) return;
245:
246: xmlFreeEntitiesTable(xmlPredefinedEntities);
247: xmlPredefinedEntities = NULL;
248: }
249:
250: /**
1.17 daniel 251: * xmlGetPredefinedEntity:
252: * @name: the entity name
253: *
254: * Check whether this name is an predefined entity.
255: *
1.24 daniel 256: * Returns NULL if not, othervise the entity
1.17 daniel 257: */
258: xmlEntityPtr
1.38 daniel 259: xmlGetPredefinedEntity(const xmlChar *name) {
1.17 daniel 260: int i;
261: xmlEntityPtr cur;
262:
263: if (xmlPredefinedEntities == NULL)
264: xmlInitializePredefinedEntities();
1.61 veillard 265: #ifdef ENTITY_HASH_SIZE
266: i = xmlEntityComputeHash(name);
267: cur = xmlPredefinedEntities->table[i];
268: while (cur != NULL) {
269: if (!xmlStrcmp(cur->name, name))
270: return(cur);
271: cur = cur->nexte;
272: }
273: #else
1.17 daniel 274: for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
1.51 daniel 275: cur = xmlPredefinedEntities->table[i];
1.17 daniel 276: if (!xmlStrcmp(cur->name, name)) return(cur);
277: }
1.61 veillard 278: #endif
1.17 daniel 279: return(NULL);
280: }
281:
1.22 daniel 282: /**
283: * xmlAddDtdEntity:
284: * @doc: the document
285: * @name: the entity name
286: * @type: the entity type XML_xxx_yyy_ENTITY
287: * @ExternalID: the entity external ID if available
288: * @SystemID: the entity system ID if available
289: * @content: the entity content
290: *
1.51 daniel 291: * Register a new entity for this document DTD external subset.
292: *
293: * Returns a pointer to the entity or NULL in case of error
1.1 httpng 294: */
1.51 daniel 295: xmlEntityPtr
1.38 daniel 296: xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51 daniel 297: const xmlChar *ExternalID, const xmlChar *SystemID,
298: const xmlChar *content) {
1.2 httpng 299: xmlEntitiesTablePtr table;
1.51 daniel 300: xmlEntityPtr ret;
301: xmlDtdPtr dtd;
1.1 httpng 302:
1.51 daniel 303: if (doc == NULL) {
304: fprintf(stderr,
305: "xmlAddDtdEntity: doc == NULL !\n");
306: return(NULL);
307: }
1.22 daniel 308: if (doc->extSubset == NULL) {
309: fprintf(stderr,
310: "xmlAddDtdEntity: document without external subset !\n");
1.51 daniel 311: return(NULL);
1.16 daniel 312: }
1.51 daniel 313: dtd = doc->extSubset;
314: table = (xmlEntitiesTablePtr) dtd->entities;
1.2 httpng 315: if (table == NULL) {
316: table = xmlCreateEntitiesTable();
1.51 daniel 317: dtd->entities = table;
1.1 httpng 318: }
1.51 daniel 319: ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
320: if (ret == NULL) return(NULL);
321:
322: /*
323: * Link it to the Dtd
324: */
325: ret->parent = dtd;
326: ret->doc = dtd->doc;
327: if (dtd->last == NULL) {
328: dtd->children = dtd->last = (xmlNodePtr) ret;
329: } else {
330: dtd->last->next = (xmlNodePtr) ret;
331: ret->prev = dtd->last;
332: dtd->last = (xmlNodePtr) ret;
333: }
334: return(ret);
1.1 httpng 335: }
336:
1.22 daniel 337: /**
338: * xmlAddDocEntity:
339: * @doc: the document
340: * @name: the entity name
341: * @type: the entity type XML_xxx_yyy_ENTITY
342: * @ExternalID: the entity external ID if available
343: * @SystemID: the entity system ID if available
344: * @content: the entity content
345: *
346: * Register a new entity for this document.
1.51 daniel 347: *
348: * Returns a pointer to the entity or NULL in case of error
1.1 httpng 349: */
1.51 daniel 350: xmlEntityPtr
1.38 daniel 351: xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51 daniel 352: const xmlChar *ExternalID, const xmlChar *SystemID,
353: const xmlChar *content) {
1.16 daniel 354: xmlEntitiesTablePtr table;
1.51 daniel 355: xmlEntityPtr ret;
356: xmlDtdPtr dtd;
1.16 daniel 357:
1.22 daniel 358: if (doc == NULL) {
359: fprintf(stderr,
360: "xmlAddDocEntity: document is NULL !\n");
1.51 daniel 361: return(NULL);
1.22 daniel 362: }
363: if (doc->intSubset == NULL) {
364: fprintf(stderr,
365: "xmlAddDtdEntity: document without internal subset !\n");
1.51 daniel 366: return(NULL);
1.22 daniel 367: }
1.51 daniel 368: dtd = doc->intSubset;
1.22 daniel 369: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16 daniel 370: if (table == NULL) {
371: table = xmlCreateEntitiesTable();
1.22 daniel 372: doc->intSubset->entities = table;
1.2 httpng 373: }
1.51 daniel 374: ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
375: if (ret == NULL) return(NULL);
376:
377: /*
378: * Link it to the Dtd
379: */
380: ret->parent = dtd;
381: ret->doc = dtd->doc;
382: if (dtd->last == NULL) {
383: dtd->children = dtd->last = (xmlNodePtr) ret;
384: } else {
385: dtd->last->next = (xmlNodePtr) ret;
386: ret->prev = dtd->last;
387: dtd->last = (xmlNodePtr) ret;
388: }
389: return(ret);
1.54 daniel 390: }
391:
1.55 daniel 392: #ifdef WITH_EXTRA_ENT_DETECT
1.54 daniel 393: /**
394: * xmlEntityCheckReference:
395: * @ent: an existing entity
396: * @to: the entity name it's referencing
397: *
398: * Function to keep track of references and detect cycles (well formedness
399: * errors !).
400: *
401: * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
402: * detection.
403: */
404: int
405: xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
406: int i;
407: xmlDocPtr doc;
408:
409: if (ent == NULL) return(-1);
410: if (to == NULL) return(-1);
411:
412: doc = ent->doc;
413: if (doc == NULL) return(-1);
414:
415: #ifdef DEBUG_ENT_REF
416: printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);
417: #endif
418:
419:
420: /*
421: * Do a recursive checking
422: */
423: for (i = 0;i < ent->entNr;i++) {
424: xmlEntityPtr indir = NULL;
425:
426: if (!xmlStrcmp(to, ent->entTab[i]))
427: return(1);
428:
429: switch (ent->etype) {
430: case XML_INTERNAL_GENERAL_ENTITY:
431: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
432: indir = xmlGetDocEntity(doc, ent->entTab[i]);
433: break;
434: case XML_INTERNAL_PARAMETER_ENTITY:
435: case XML_EXTERNAL_PARAMETER_ENTITY:
436: indir = xmlGetDtdEntity(doc, ent->entTab[i]);
437: break;
438: case XML_INTERNAL_PREDEFINED_ENTITY:
439: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
440: break;
441: }
442: if (xmlEntityCheckReference(indir, to) == 1)
443: return(1);
444: }
445: return(0);
446: }
447:
448: /**
449: * xmlEntityAddReference:
450: * @ent: an existing entity
451: * @to: the entity name it's referencing
452: *
453: * Function to register reuse of an existing entity from a (new) one
454: * Used to keep track of references and detect cycles (well formedness
455: * errors !).
456: *
457: * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
458: * detection.
459: */
460: int
461: xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
462: int i;
463: xmlDocPtr doc;
464: xmlEntityPtr indir = NULL;
465:
466: if (ent == NULL) return(-1);
467: if (to == NULL) return(-1);
468:
469: doc = ent->doc;
470: if (doc == NULL) return(-1);
471:
472: #ifdef DEBUG_ENT_REF
473: printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);
474: #endif
475: if (ent->entTab == NULL) {
476: ent->entNr = 0;
477: ent->entMax = 5;
478: ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
479: if (ent->entTab == NULL) {
480: fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
481: return(-1);
482: }
483: }
484:
485: for (i = 0;i < ent->entNr;i++) {
486: if (!xmlStrcmp(to, ent->entTab[i]))
487: return(0);
488: }
489:
490: /*
491: * Do a recursive checking
492: */
493:
494: switch (ent->etype) {
495: case XML_INTERNAL_GENERAL_ENTITY:
496: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
497: indir = xmlGetDocEntity(doc, to);
498: break;
499: case XML_INTERNAL_PARAMETER_ENTITY:
500: case XML_EXTERNAL_PARAMETER_ENTITY:
501: indir = xmlGetDtdEntity(doc, to);
502: break;
503: case XML_INTERNAL_PREDEFINED_ENTITY:
504: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
505: break;
506: }
507: if ((indir != NULL) &&
508: (xmlEntityCheckReference(indir, ent->name) == 1))
509: return(1);
510:
511: /*
512: * Add this to the list
513: */
514: if (ent->entMax <= ent->entNr) {
515: ent->entMax *= 2;
516: ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
517: ent->entMax * sizeof(xmlChar *));
518: if (ent->entTab == NULL) {
519: fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
520: return(-1);
521: }
522: }
523: ent->entTab[ent->entNr++] = xmlStrdup(to);
524: return(0);
1.1 httpng 525: }
1.55 daniel 526: #endif
1.1 httpng 527:
1.61 veillard 528:
529: /**
530: * xmlGetEntityFromTable:
531: * @table: an entity table
532: * @name: the entity name
533: * @parameter: look for parameter entities
534: *
535: * Do an entity lookup in the table.
536: * returns the corresponding parameter entity, if found.
537: *
538: * Returns A pointer to the entity structure or NULL if not found.
539: */
540: xmlEntityPtr
541: xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name,
542: int parameter) {
543: xmlEntityPtr cur;
544: #ifdef ENTITY_HASH_SIZE
545: int hash;
546:
547: hash = xmlEntityComputeHash(name);
548: cur = table->table[hash];
549: while (cur != NULL) {
550: switch (cur->etype) {
551: case XML_INTERNAL_PARAMETER_ENTITY:
552: case XML_EXTERNAL_PARAMETER_ENTITY:
553: if ((parameter) && (!xmlStrcmp(cur->name, name)))
554: return(cur);
555: default:
556: if ((!parameter) && (!xmlStrcmp(cur->name, name)))
557: return(cur);
558: }
559: cur = cur->nexte;
560: }
561: #else
562: int i;
563:
564: for (i = 0;i < table->nb_entities;i++) {
565: cur = table->table[i];
566: switch (cur->etype) {
567: case XML_INTERNAL_PARAMETER_ENTITY:
568: case XML_EXTERNAL_PARAMETER_ENTITY:
569: if ((parameter) && (!xmlStrcmp(cur->name, name)))
570: return(cur);
571: default:
572: if ((!parameter) && (!xmlStrcmp(cur->name, name)))
573: return(cur);
574: }
575: }
576: #endif
577: return(NULL);
578: }
579:
1.22 daniel 580: /**
1.30 daniel 581: * xmlGetParameterEntity:
582: * @doc: the document referencing the entity
583: * @name: the entity name
584: *
585: * Do an entity lookup in the internal and external subsets and
586: * returns the corresponding parameter entity, if found.
587: *
588: * Returns A pointer to the entity structure or NULL if not found.
589: */
590: xmlEntityPtr
1.38 daniel 591: xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
1.30 daniel 592: xmlEntitiesTablePtr table;
1.61 veillard 593: xmlEntityPtr ret;
1.30 daniel 594:
595: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
596: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.61 veillard 597: ret = xmlGetEntityFromTable(table, name, 1);
598: if (ret != NULL)
599: return(ret);
1.30 daniel 600: }
1.35 daniel 601: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
602: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.61 veillard 603: return(xmlGetEntityFromTable(table, name, 1));
1.35 daniel 604: }
1.30 daniel 605: return(NULL);
606: }
607:
608: /**
1.22 daniel 609: * xmlGetDtdEntity:
610: * @doc: the document referencing the entity
611: * @name: the entity name
612: *
613: * Do an entity lookup in the Dtd entity hash table and
614: * returns the corresponding entity, if found.
615: *
1.24 daniel 616: * Returns A pointer to the entity structure or NULL if not found.
1.1 httpng 617: */
1.22 daniel 618: xmlEntityPtr
1.38 daniel 619: xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
1.2 httpng 620: xmlEntitiesTablePtr table;
621:
1.22 daniel 622: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
623: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.61 veillard 624: return(xmlGetEntityFromTable(table, name, 0));
1.15 daniel 625: }
1.7 veillard 626: return(NULL);
1.3 httpng 627: }
628:
1.22 daniel 629: /**
630: * xmlGetDocEntity:
631: * @doc: the document referencing the entity
632: * @name: the entity name
633: *
634: * Do an entity lookup in the document entity hash table and
635: * returns the corrsponding entity, otherwise a lookup is done
636: * in the predefined entities too.
637: *
1.24 daniel 638: * Returns A pointer to the entity structure or NULL if not found.
1.14 daniel 639: */
1.22 daniel 640: xmlEntityPtr
1.38 daniel 641: xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
1.16 daniel 642: xmlEntityPtr cur;
1.14 daniel 643: xmlEntitiesTablePtr table;
644:
1.22 daniel 645: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
646: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.61 veillard 647: cur = xmlGetEntityFromTable(table, name, 0);
648: if (cur != NULL)
649: return(cur);
1.16 daniel 650: }
1.34 daniel 651: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
652: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.61 veillard 653: cur = xmlGetEntityFromTable(table, name, 0);
654: if (cur != NULL)
655: return(cur);
1.34 daniel 656: }
1.15 daniel 657: if (xmlPredefinedEntities == NULL)
658: xmlInitializePredefinedEntities();
1.16 daniel 659: table = xmlPredefinedEntities;
1.61 veillard 660: return(xmlGetEntityFromTable(table, name, 0));
1.1 httpng 661: }
662:
663: /*
1.21 daniel 664: * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
665: * | [#x10000-#x10FFFF]
666: * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
667: */
668: #define IS_CHAR(c) \
669: (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
670: (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
671:
1.28 daniel 672: /*
673: * A buffer used for converting entities to their equivalent and back.
674: */
675: static int buffer_size = 0;
1.38 daniel 676: static xmlChar *buffer = NULL;
1.28 daniel 677:
1.44 daniel 678: int growBuffer(void) {
1.28 daniel 679: buffer_size *= 2;
1.38 daniel 680: buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
1.28 daniel 681: if (buffer == NULL) {
682: perror("realloc failed");
1.44 daniel 683: return(-1);
1.28 daniel 684: }
1.44 daniel 685: return(0);
1.28 daniel 686: }
687:
688:
1.22 daniel 689: /**
690: * xmlEncodeEntities:
691: * @doc: the document containing the string
692: * @input: A string to convert to XML.
693: *
694: * Do a global encoding of a string, replacing the predefined entities
695: * and non ASCII values with their entities and CharRef counterparts.
696: *
1.33 daniel 697: * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
698: * compatibility
1.28 daniel 699: *
700: * People must migrate their code to xmlEncodeEntitiesReentrant !
1.31 daniel 701: * This routine will issue a warning when encountered.
1.28 daniel 702: *
703: * Returns A newly allocated string with the substitution done.
704: */
1.38 daniel 705: const xmlChar *
706: xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
707: const xmlChar *cur = input;
708: xmlChar *out = buffer;
1.31 daniel 709: static int warning = 1;
1.39 daniel 710: int html = 0;
711:
1.31 daniel 712:
713: if (warning) {
714: fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
715: fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n");
716: warning = 0;
717: }
1.28 daniel 718:
719: if (input == NULL) return(NULL);
1.39 daniel 720: if (doc != NULL)
721: html = (doc->type == XML_HTML_DOCUMENT_NODE);
722:
1.28 daniel 723: if (buffer == NULL) {
724: buffer_size = 1000;
1.38 daniel 725: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.28 daniel 726: if (buffer == NULL) {
727: perror("malloc failed");
1.44 daniel 728: return(NULL);
1.28 daniel 729: }
730: out = buffer;
731: }
732: while (*cur != '\0') {
733: if (out - buffer > buffer_size - 100) {
734: int index = out - buffer;
735:
736: growBuffer();
737: out = &buffer[index];
738: }
739:
740: /*
741: * By default one have to encode at least '<', '>', '"' and '&' !
742: */
743: if (*cur == '<') {
744: *out++ = '&';
745: *out++ = 'l';
746: *out++ = 't';
747: *out++ = ';';
748: } else if (*cur == '>') {
749: *out++ = '&';
750: *out++ = 'g';
751: *out++ = 't';
752: *out++ = ';';
753: } else if (*cur == '&') {
754: *out++ = '&';
755: *out++ = 'a';
756: *out++ = 'm';
757: *out++ = 'p';
758: *out++ = ';';
759: } else if (*cur == '"') {
760: *out++ = '&';
761: *out++ = 'q';
762: *out++ = 'u';
763: *out++ = 'o';
764: *out++ = 't';
765: *out++ = ';';
1.39 daniel 766: } else if ((*cur == '\'') && (!html)) {
1.28 daniel 767: *out++ = '&';
768: *out++ = 'a';
769: *out++ = 'p';
770: *out++ = 'o';
771: *out++ = 's';
772: *out++ = ';';
773: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
774: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
775: /*
776: * default case, just copy !
777: */
778: *out++ = *cur;
779: #ifndef USE_UTF_8
1.38 daniel 780: } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
1.28 daniel 781: char buf[10], *ptr;
782: #ifdef HAVE_SNPRINTF
783: snprintf(buf, 9, "&#%d;", *cur);
784: #else
785: sprintf(buf, "&#%d;", *cur);
786: #endif
787: ptr = buf;
788: while (*ptr != 0) *out++ = *ptr++;
789: #endif
790: } else if (IS_CHAR(*cur)) {
791: char buf[10], *ptr;
792:
793: #ifdef HAVE_SNPRINTF
794: snprintf(buf, 9, "&#%d;", *cur);
795: #else
796: sprintf(buf, "&#%d;", *cur);
797: #endif
798: ptr = buf;
799: while (*ptr != 0) *out++ = *ptr++;
800: }
801: #if 0
802: else {
803: /*
804: * default case, this is not a valid char !
805: * Skip it...
806: */
807: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
808: }
809: #endif
810: cur++;
811: }
812: *out++ = 0;
813: return(buffer);
814: }
815:
816: /*
817: * Macro used to grow the current buffer.
818: */
819: #define growBufferReentrant() { \
820: buffer_size *= 2; \
1.44 daniel 821: buffer = (xmlChar *) \
822: xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
1.28 daniel 823: if (buffer == NULL) { \
824: perror("realloc failed"); \
1.44 daniel 825: return(NULL); \
1.28 daniel 826: } \
827: }
828:
829:
830: /**
831: * xmlEncodeEntitiesReentrant:
832: * @doc: the document containing the string
833: * @input: A string to convert to XML.
834: *
835: * Do a global encoding of a string, replacing the predefined entities
836: * and non ASCII values with their entities and CharRef counterparts.
837: * Contrary to xmlEncodeEntities, this routine is reentrant, and result
838: * must be deallocated.
839: *
1.24 daniel 840: * Returns A newly allocated string with the substitution done.
1.1 httpng 841: */
1.38 daniel 842: xmlChar *
843: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
844: const xmlChar *cur = input;
845: xmlChar *buffer = NULL;
846: xmlChar *out = NULL;
1.26 daniel 847: int buffer_size = 0;
1.39 daniel 848: int html = 0;
1.3 httpng 849:
1.19 daniel 850: if (input == NULL) return(NULL);
1.39 daniel 851: if (doc != NULL)
852: html = (doc->type == XML_HTML_DOCUMENT_NODE);
1.26 daniel 853:
854: /*
855: * allocate an translation buffer.
856: */
857: buffer_size = 1000;
1.38 daniel 858: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.3 httpng 859: if (buffer == NULL) {
1.26 daniel 860: perror("malloc failed");
1.44 daniel 861: return(NULL);
1.3 httpng 862: }
1.26 daniel 863: out = buffer;
864:
1.6 veillard 865: while (*cur != '\0') {
866: if (out - buffer > buffer_size - 100) {
867: int index = out - buffer;
868:
1.28 daniel 869: growBufferReentrant();
1.6 veillard 870: out = &buffer[index];
871: }
872:
873: /*
1.7 veillard 874: * By default one have to encode at least '<', '>', '"' and '&' !
1.6 veillard 875: */
876: if (*cur == '<') {
877: *out++ = '&';
878: *out++ = 'l';
879: *out++ = 't';
880: *out++ = ';';
1.7 veillard 881: } else if (*cur == '>') {
882: *out++ = '&';
883: *out++ = 'g';
884: *out++ = 't';
885: *out++ = ';';
1.6 veillard 886: } else if (*cur == '&') {
887: *out++ = '&';
888: *out++ = 'a';
889: *out++ = 'm';
890: *out++ = 'p';
1.7 veillard 891: *out++ = ';';
892: } else if (*cur == '"') {
893: *out++ = '&';
894: *out++ = 'q';
895: *out++ = 'u';
896: *out++ = 'o';
897: *out++ = 't';
898: *out++ = ';';
1.53 daniel 899: #if 0
1.39 daniel 900: } else if ((*cur == '\'') && (!html)) {
1.7 veillard 901: *out++ = '&';
902: *out++ = 'a';
903: *out++ = 'p';
904: *out++ = 'o';
905: *out++ = 's';
1.6 veillard 906: *out++ = ';';
1.53 daniel 907: #endif
1.21 daniel 908: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
909: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
910: /*
911: * default case, just copy !
912: */
913: *out++ = *cur;
1.46 daniel 914: } else if (*cur >= 0x80) {
1.59 veillard 915: if ((doc->encoding != NULL) || (html)) {
1.46 daniel 916: /*
917: * TODO !!!
918: */
919: *out++ = *cur;
920: } else {
921: /*
922: * We assume we have UTF-8 input.
923: */
924: char buf[10], *ptr;
1.48 daniel 925: int val = 0, l = 1;
1.46 daniel 926:
927: if (*cur < 0xC0) {
928: fprintf(stderr,
929: "xmlEncodeEntitiesReentrant : input not UTF-8\n");
930: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
931: #ifdef HAVE_SNPRINTF
932: snprintf(buf, 9, "&#%d;", *cur);
933: #else
934: sprintf(buf, "&#%d;", *cur);
935: #endif
936: ptr = buf;
937: while (*ptr != 0) *out++ = *ptr++;
938: continue;
939: } else if (*cur < 0xE0) {
940: val = (cur[0]) & 0x1F;
941: val <<= 6;
942: val |= (cur[1]) & 0x3F;
943: l = 2;
944: } else if (*cur < 0xF0) {
945: val = (cur[0]) & 0x0F;
946: val <<= 6;
947: val |= (cur[1]) & 0x3F;
948: val <<= 6;
949: val |= (cur[2]) & 0x3F;
950: l = 3;
951: } else if (*cur < 0xF8) {
952: val = (cur[0]) & 0x07;
953: val <<= 6;
954: val |= (cur[1]) & 0x3F;
955: val <<= 6;
956: val |= (cur[2]) & 0x3F;
957: val <<= 6;
958: val |= (cur[3]) & 0x3F;
959: l = 4;
960: }
961: if ((l == 1) || (!IS_CHAR(val))) {
962: fprintf(stderr,
963: "xmlEncodeEntitiesReentrant : char out of range\n");
964: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
965: #ifdef HAVE_SNPRINTF
966: snprintf(buf, 9, "&#%d;", *cur);
967: #else
968: sprintf(buf, "&#%d;", *cur);
969: #endif
1.60 veillard 970: buf[9] = 0;
1.46 daniel 971: ptr = buf;
972: while (*ptr != 0) *out++ = *ptr++;
973: cur++;
974: continue;
975: }
976: /*
977: * We could do multiple things here. Just save as a char ref
978: */
979: #ifdef HAVE_SNPRINTF
1.60 veillard 980: snprintf(buf, 9, "&#x%X;", val);
1.46 daniel 981: #else
1.50 daniel 982: sprintf(buf, "&#x%X;", val);
1.46 daniel 983: #endif
1.60 veillard 984: buf[9] = 0;
1.47 daniel 985: ptr = buf;
986: while (*ptr != 0) *out++ = *ptr++;
987: cur += l;
988: continue;
1.45 daniel 989: }
1.21 daniel 990: } else if (IS_CHAR(*cur)) {
1.20 daniel 991: char buf[10], *ptr;
992:
993: #ifdef HAVE_SNPRINTF
994: snprintf(buf, 9, "&#%d;", *cur);
995: #else
996: sprintf(buf, "&#%d;", *cur);
997: #endif
1.60 veillard 998: buf[9] = 0;
1.20 daniel 999: ptr = buf;
1000: while (*ptr != 0) *out++ = *ptr++;
1.21 daniel 1001: }
1002: #if 0
1003: else {
1.6 veillard 1004: /*
1.21 daniel 1005: * default case, this is not a valid char !
1006: * Skip it...
1.6 veillard 1007: */
1.21 daniel 1008: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6 veillard 1009: }
1.21 daniel 1010: #endif
1.6 veillard 1011: cur++;
1012: }
1013: *out++ = 0;
1014: return(buffer);
1.2 httpng 1015: }
1016:
1.22 daniel 1017: /**
1.57 daniel 1018: * xmlEncodeSpecialChars:
1019: * @doc: the document containing the string
1020: * @input: A string to convert to XML.
1021: *
1022: * Do a global encoding of a string, replacing the predefined entities
1023: * this routine is reentrant, and result must be deallocated.
1024: *
1025: * Returns A newly allocated string with the substitution done.
1026: */
1027: xmlChar *
1028: xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
1029: const xmlChar *cur = input;
1030: xmlChar *buffer = NULL;
1031: xmlChar *out = NULL;
1032: int buffer_size = 0;
1033: int html = 0;
1034:
1035: if (input == NULL) return(NULL);
1036: if (doc != NULL)
1037: html = (doc->type == XML_HTML_DOCUMENT_NODE);
1038:
1039: /*
1040: * allocate an translation buffer.
1041: */
1042: buffer_size = 1000;
1043: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1044: if (buffer == NULL) {
1045: perror("malloc failed");
1046: return(NULL);
1047: }
1048: out = buffer;
1049:
1050: while (*cur != '\0') {
1051: if (out - buffer > buffer_size - 10) {
1052: int index = out - buffer;
1053:
1054: growBufferReentrant();
1055: out = &buffer[index];
1056: }
1057:
1058: /*
1059: * By default one have to encode at least '<', '>', '"' and '&' !
1060: */
1061: if (*cur == '<') {
1062: *out++ = '&';
1063: *out++ = 'l';
1064: *out++ = 't';
1065: *out++ = ';';
1066: } else if (*cur == '>') {
1067: *out++ = '&';
1068: *out++ = 'g';
1069: *out++ = 't';
1070: *out++ = ';';
1071: } else if (*cur == '&') {
1072: *out++ = '&';
1073: *out++ = 'a';
1074: *out++ = 'm';
1075: *out++ = 'p';
1076: *out++ = ';';
1077: } else if (*cur == '"') {
1078: *out++ = '&';
1079: *out++ = 'q';
1080: *out++ = 'u';
1081: *out++ = 'o';
1082: *out++ = 't';
1083: *out++ = ';';
1084: } else {
1085: /*
1086: * Works because on UTF-8, all extended sequences cannot
1087: * result in bytes in the ASCII range.
1088: */
1089: *out++ = *cur;
1090: }
1091: cur++;
1092: }
1093: *out++ = 0;
1094: return(buffer);
1095: }
1096:
1097: /**
1.22 daniel 1098: * xmlCreateEntitiesTable:
1099: *
1100: * create and initialize an empty entities hash table.
1101: *
1.24 daniel 1102: * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2 httpng 1103: */
1.22 daniel 1104: xmlEntitiesTablePtr
1105: xmlCreateEntitiesTable(void) {
1.2 httpng 1106: xmlEntitiesTablePtr ret;
1.1 httpng 1107:
1.2 httpng 1108: ret = (xmlEntitiesTablePtr)
1.36 daniel 1109: xmlMalloc(sizeof(xmlEntitiesTable));
1.1 httpng 1110: if (ret == NULL) {
1.36 daniel 1111: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 1112: (long)sizeof(xmlEntitiesTable));
1.2 httpng 1113: return(NULL);
1114: }
1.61 veillard 1115: ret->nb_entities = 0;
1116: #ifdef ENTITY_HASH_SIZE
1117: ret->max_entities = ENTITY_HASH_SIZE;
1118: ret->table = (xmlEntityPtr *)
1119: xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
1120: if (ret == NULL) {
1121: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1122: ret->max_entities * (long)sizeof(xmlEntityPtr));
1123: xmlFree(ret);
1124: return(NULL);
1125: }
1126: memset(ret->table, 0, ret->max_entities * sizeof(xmlEntityPtr));
1127: #else
1.2 httpng 1128: ret->max_entities = XML_MIN_ENTITIES_TABLE;
1.51 daniel 1129: ret->table = (xmlEntityPtr *)
1130: xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
1.2 httpng 1131: if (ret == NULL) {
1.36 daniel 1132: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.51 daniel 1133: ret->max_entities * (long)sizeof(xmlEntityPtr));
1.36 daniel 1134: xmlFree(ret);
1.1 httpng 1135: return(NULL);
1136: }
1.61 veillard 1137: #endif
1.1 httpng 1138: return(ret);
1139: }
1140:
1.22 daniel 1141: /**
1142: * xmlFreeEntitiesTable:
1143: * @table: An entity table
1144: *
1145: * Deallocate the memory used by an entities hash table.
1.1 httpng 1146: */
1.22 daniel 1147: void
1148: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 1149: int i;
1.61 veillard 1150: #ifdef ENTITY_HASH_SIZE
1151: xmlEntityPtr cur, next;
1152: #endif
1.1 httpng 1153:
1154: if (table == NULL) return;
1155:
1.61 veillard 1156: #ifdef ENTITY_HASH_SIZE
1157: for (i = 0;i < ENTITY_HASH_SIZE;i++) {
1158: cur = table->table[i];
1159: while (cur != NULL) {
1160: next = cur->nexte;
1161: xmlFreeEntity(cur);
1162: cur = next;
1163: }
1164: }
1165: #else
1.2 httpng 1166: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 1167: xmlFreeEntity(table->table[i]);
1.1 httpng 1168: }
1.61 veillard 1169: #endif
1.36 daniel 1170: xmlFree(table->table);
1171: xmlFree(table);
1.1 httpng 1172: }
1173:
1.22 daniel 1174: /**
1.61 veillard 1175: * xmlCopyEntity:
1176: * @ent: An entity
1177: *
1178: * Build a copy of an entity
1179: *
1180: * Returns the new xmlEntitiesPtr or NULL in case of error.
1181: */
1182: xmlEntityPtr
1183: xmlCopyEntity(xmlEntityPtr ent) {
1184: xmlEntityPtr cur;
1185:
1186: cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
1187: if (cur == NULL) {
1188: fprintf(stderr, "xmlCopyEntity: out of memory !\n");
1189: return(NULL);
1190: }
1191: memset(cur, 0, sizeof(xmlEntity));
1192: cur->type = XML_ELEMENT_DECL;
1193:
1194: cur->etype = ent->etype;
1195: if (ent->name != NULL)
1196: cur->name = xmlStrdup(ent->name);
1197: if (ent->ExternalID != NULL)
1198: cur->ExternalID = xmlStrdup(ent->ExternalID);
1199: if (ent->SystemID != NULL)
1200: cur->SystemID = xmlStrdup(ent->SystemID);
1201: if (ent->content != NULL)
1202: cur->content = xmlStrdup(ent->content);
1203: if (ent->orig != NULL)
1204: cur->orig = xmlStrdup(ent->orig);
1205: return(cur);
1206: }
1207:
1208: /**
1.22 daniel 1209: * xmlCopyEntitiesTable:
1210: * @table: An entity table
1211: *
1212: * Build a copy of an entity table.
1213: *
1.24 daniel 1214: * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22 daniel 1215: */
1216: xmlEntitiesTablePtr
1217: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
1218: xmlEntitiesTablePtr ret;
1219: xmlEntityPtr cur, ent;
1220: int i;
1221:
1.36 daniel 1222: ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
1.22 daniel 1223: if (ret == NULL) {
1224: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1225: return(NULL);
1226: }
1.61 veillard 1227: #ifdef ENTITY_HASH_SIZE
1228: ret->table = (xmlEntityPtr *) xmlMalloc(ENTITY_HASH_SIZE *
1229: sizeof(xmlEntityPtr));
1230: if (ret->table == NULL) {
1231: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1232: xmlFree(ret);
1233: return(NULL);
1234: }
1235: #else
1.51 daniel 1236: ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
1237: sizeof(xmlEntityPtr));
1.22 daniel 1238: if (ret->table == NULL) {
1239: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1.36 daniel 1240: xmlFree(ret);
1.22 daniel 1241: return(NULL);
1242: }
1.61 veillard 1243: #endif
1.22 daniel 1244: ret->max_entities = table->max_entities;
1245: ret->nb_entities = table->nb_entities;
1246: for (i = 0;i < ret->nb_entities;i++) {
1.61 veillard 1247: ent = table->table[i];
1248: if (ent == NULL)
1249: cur = NULL;
1250: else
1251: cur = xmlCopyEntity(ent);
1252: ret->table[i] = cur;
1253: #ifdef ENTITY_HASH_SIZE
1254: ent = ent->nexte;
1255: while ((ent != NULL) && (cur != NULL)) {
1256: cur->nexte = xmlCopyEntity(ent);
1257: cur = cur->nexte;
1.51 daniel 1258: }
1.61 veillard 1259: #endif
1.22 daniel 1260: }
1261: return(ret);
1262: }
1263:
1264: /**
1.53 daniel 1265: * xmlDumpEntityDecl:
1266: * @buf: An XML buffer.
1267: * @ent: An entity table
1268: *
1269: * This will dump the content of the entity table as an XML DTD definition
1270: */
1271: void
1272: xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
1273: switch (ent->etype) {
1274: case XML_INTERNAL_GENERAL_ENTITY:
1275: xmlBufferWriteChar(buf, "<!ENTITY ");
1276: xmlBufferWriteCHAR(buf, ent->name);
1277: xmlBufferWriteChar(buf, " ");
1278: if (ent->orig != NULL)
1279: xmlBufferWriteQuotedString(buf, ent->orig);
1280: else
1281: xmlBufferWriteQuotedString(buf, ent->content);
1282: xmlBufferWriteChar(buf, ">\n");
1283: break;
1284: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1285: xmlBufferWriteChar(buf, "<!ENTITY ");
1286: xmlBufferWriteCHAR(buf, ent->name);
1287: if (ent->ExternalID != NULL) {
1288: xmlBufferWriteChar(buf, " PUBLIC ");
1289: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1290: xmlBufferWriteChar(buf, " ");
1291: xmlBufferWriteQuotedString(buf, ent->SystemID);
1292: } else {
1293: xmlBufferWriteChar(buf, " SYSTEM ");
1294: xmlBufferWriteQuotedString(buf, ent->SystemID);
1295: }
1296: xmlBufferWriteChar(buf, ">\n");
1297: break;
1298: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1299: xmlBufferWriteChar(buf, "<!ENTITY ");
1300: xmlBufferWriteCHAR(buf, ent->name);
1301: if (ent->ExternalID != NULL) {
1302: xmlBufferWriteChar(buf, " PUBLIC ");
1303: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1304: xmlBufferWriteChar(buf, " ");
1305: xmlBufferWriteQuotedString(buf, ent->SystemID);
1306: } else {
1307: xmlBufferWriteChar(buf, " SYSTEM ");
1308: xmlBufferWriteQuotedString(buf, ent->SystemID);
1309: }
1310: if (ent->content != NULL) { /* Should be true ! */
1311: xmlBufferWriteChar(buf, " NDATA ");
1312: if (ent->orig != NULL)
1313: xmlBufferWriteCHAR(buf, ent->orig);
1314: else
1315: xmlBufferWriteCHAR(buf, ent->content);
1316: }
1317: xmlBufferWriteChar(buf, ">\n");
1318: break;
1319: case XML_INTERNAL_PARAMETER_ENTITY:
1320: xmlBufferWriteChar(buf, "<!ENTITY % ");
1321: xmlBufferWriteCHAR(buf, ent->name);
1322: xmlBufferWriteChar(buf, " ");
1323: if (ent->orig == NULL)
1324: xmlBufferWriteQuotedString(buf, ent->content);
1325: else
1326: xmlBufferWriteQuotedString(buf, ent->orig);
1327: xmlBufferWriteChar(buf, ">\n");
1328: break;
1329: case XML_EXTERNAL_PARAMETER_ENTITY:
1330: xmlBufferWriteChar(buf, "<!ENTITY % ");
1331: xmlBufferWriteCHAR(buf, ent->name);
1332: if (ent->ExternalID != NULL) {
1333: xmlBufferWriteChar(buf, " PUBLIC ");
1334: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1335: xmlBufferWriteChar(buf, " ");
1336: xmlBufferWriteQuotedString(buf, ent->SystemID);
1337: } else {
1338: xmlBufferWriteChar(buf, " SYSTEM ");
1339: xmlBufferWriteQuotedString(buf, ent->SystemID);
1340: }
1341: xmlBufferWriteChar(buf, ">\n");
1342: break;
1343: default:
1344: fprintf(stderr,
1345: "xmlDumpEntitiesTable: internal: unknown type %d\n",
1346: ent->etype);
1347: }
1348: }
1349:
1350: /**
1.22 daniel 1351: * xmlDumpEntitiesTable:
1.25 daniel 1352: * @buf: An XML buffer.
1.22 daniel 1353: * @table: An entity table
1354: *
1355: * This will dump the content of the entity table as an XML DTD definition
1.13 daniel 1356: */
1.22 daniel 1357: void
1.25 daniel 1358: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14 daniel 1359: int i;
1360: xmlEntityPtr cur;
1361:
1362: if (table == NULL) return;
1363:
1.61 veillard 1364: #ifdef ENTITY_HASH_SIZE
1365: for (i = 0;i < ENTITY_HASH_SIZE;i++) {
1366: cur = table->table[i];
1367: while (cur != NULL) {
1368: xmlDumpEntityDecl(buf, cur);
1369: cur = cur->nexte;
1370: }
1371: }
1372: #else
1.14 daniel 1373: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 1374: cur = table->table[i];
1.53 daniel 1375: xmlDumpEntityDecl(buf, cur);
1.14 daniel 1376: }
1.61 veillard 1377: #endif
1.13 daniel 1378: }
Webmaster