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