Annotation of XML/entities.c, revision 1.48
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.36 daniel 20: #include "xmlmemory.h"
1.1 httpng 21: #include "entities.h"
1.41 daniel 22: #include "parser.h"
1.1 httpng 23:
24: /*
1.15 daniel 25: * The XML predefined entities.
26: */
27:
28: struct xmlPredefinedEntityValue {
29: const char *name;
30: const char *value;
31: };
32: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
33: { "lt", "<" },
34: { "gt", ">" },
35: { "apos", "'" },
36: { "quot", "\"" },
37: { "amp", "&" }
38: };
39:
40: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
41:
42: /*
1.2 httpng 43: * xmlFreeEntity : clean-up an entity record.
1.1 httpng 44: */
1.2 httpng 45: void xmlFreeEntity(xmlEntityPtr entity) {
46: if (entity == NULL) return;
47:
1.11 daniel 48: if (entity->name != NULL)
1.36 daniel 49: xmlFree((char *) entity->name);
1.14 daniel 50: if (entity->ExternalID != NULL)
1.36 daniel 51: xmlFree((char *) entity->ExternalID);
1.14 daniel 52: if (entity->SystemID != NULL)
1.36 daniel 53: xmlFree((char *) entity->SystemID);
1.14 daniel 54: if (entity->content != NULL)
1.36 daniel 55: xmlFree((char *) entity->content);
1.27 daniel 56: if (entity->orig != NULL)
1.36 daniel 57: xmlFree((char *) entity->orig);
1.14 daniel 58: memset(entity, -1, sizeof(xmlEntity));
1.2 httpng 59: }
1.1 httpng 60:
61: /*
1.22 daniel 62: * xmlAddEntity : register a new entity for an entities table.
1.1 httpng 63: */
1.22 daniel 64: static void
1.38 daniel 65: xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
66: const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
1.2 httpng 67: int i;
68: xmlEntityPtr cur;
1.14 daniel 69: int len;
1.1 httpng 70:
1.2 httpng 71: for (i = 0;i < table->nb_entities;i++) {
72: cur = &table->table[i];
1.11 daniel 73: if (!xmlStrcmp(cur->name, name)) {
1.13 daniel 74: /*
75: * The entity is already defined in this Dtd, the spec says to NOT
76: * override it ... Is it worth a Warning ??? !!!
1.33 daniel 77: * Not having a cprinting context this seems hard ...
1.13 daniel 78: */
1.30 daniel 79: if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
80: (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
81: ((cur->type == XML_INTERNAL_PARAMETER_ENTITY) ||
82: (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)))
83: return;
84: else
85: if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
86: (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
87: ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
88: (cur->type != XML_EXTERNAL_PARAMETER_ENTITY)))
89: return;
1.7 veillard 90: }
1.2 httpng 91: }
92: if (table->nb_entities >= table->max_entities) {
93: /*
94: * need more elements.
95: */
96: table->max_entities *= 2;
97: table->table = (xmlEntityPtr)
1.36 daniel 98: xmlRealloc(table->table, table->max_entities * sizeof(xmlEntity));
1.29 daniel 99: if (table->table == NULL) {
1.2 httpng 100: perror("realloc failed");
1.29 daniel 101: return;
1.2 httpng 102: }
103: }
104: cur = &table->table[table->nb_entities];
1.11 daniel 105: cur->name = xmlStrdup(name);
1.14 daniel 106: for (len = 0;name[0] != 0;name++)len++;
107: cur->len = len;
1.13 daniel 108: cur->type = type;
109: if (ExternalID != NULL)
110: cur->ExternalID = xmlStrdup(ExternalID);
1.14 daniel 111: else
112: cur->ExternalID = NULL;
1.13 daniel 113: if (SystemID != NULL)
1.14 daniel 114: cur->SystemID = xmlStrdup(SystemID);
115: else
116: cur->SystemID = NULL;
1.43 daniel 117: if (content != NULL) {
118: cur->length = xmlStrlen(content);
119: cur->content = xmlStrndup(content, cur->length);
120: } else {
121: cur->length = 0;
1.14 daniel 122: cur->content = NULL;
1.43 daniel 123: }
1.27 daniel 124: cur->orig = NULL;
1.2 httpng 125: table->nb_entities++;
126: }
1.1 httpng 127:
1.22 daniel 128: /**
129: * xmlInitializePredefinedEntities:
130: *
131: * Set up the predefined entities.
1.15 daniel 132: */
133: void xmlInitializePredefinedEntities(void) {
134: int i;
1.38 daniel 135: xmlChar name[50];
136: xmlChar value[50];
1.15 daniel 137: const char *in;
1.38 daniel 138: xmlChar *out;
1.15 daniel 139:
140: if (xmlPredefinedEntities != NULL) return;
141:
142: xmlPredefinedEntities = xmlCreateEntitiesTable();
143: for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
144: sizeof(xmlPredefinedEntityValues[0]);i++) {
145: in = xmlPredefinedEntityValues[i].name;
146: out = &name[0];
1.38 daniel 147: for (;(*out++ = (xmlChar) *in);)in++;
1.15 daniel 148: in = xmlPredefinedEntityValues[i].value;
149: out = &value[0];
1.38 daniel 150: for (;(*out++ = (xmlChar) *in);)in++;
151: xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
1.18 daniel 152: XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15 daniel 153: &value[0]);
154: }
155: }
1.17 daniel 156:
157: /**
1.40 daniel 158: * xmlCleanupPredefinedEntities:
159: *
160: * Cleanup up the predefined entities table.
161: */
162: void xmlCleanupPredefinedEntities(void) {
163: if (xmlPredefinedEntities == NULL) return;
164:
165: xmlFreeEntitiesTable(xmlPredefinedEntities);
166: xmlPredefinedEntities = NULL;
167: }
168:
169: /**
1.17 daniel 170: * xmlGetPredefinedEntity:
171: * @name: the entity name
172: *
173: * Check whether this name is an predefined entity.
174: *
1.24 daniel 175: * Returns NULL if not, othervise the entity
1.17 daniel 176: */
177: xmlEntityPtr
1.38 daniel 178: xmlGetPredefinedEntity(const xmlChar *name) {
1.17 daniel 179: int i;
180: xmlEntityPtr cur;
181:
182: if (xmlPredefinedEntities == NULL)
183: xmlInitializePredefinedEntities();
184: for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
185: cur = &xmlPredefinedEntities->table[i];
186: if (!xmlStrcmp(cur->name, name)) return(cur);
187: }
188: return(NULL);
189: }
190:
1.22 daniel 191: /**
192: * xmlAddDtdEntity:
193: * @doc: the document
194: * @name: the entity name
195: * @type: the entity type XML_xxx_yyy_ENTITY
196: * @ExternalID: the entity external ID if available
197: * @SystemID: the entity system ID if available
198: * @content: the entity content
199: *
200: * Register a new entity for this document DTD.
1.1 httpng 201: */
1.22 daniel 202: void
1.38 daniel 203: xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
204: const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
1.2 httpng 205: xmlEntitiesTablePtr table;
1.1 httpng 206:
1.22 daniel 207: if (doc->extSubset == NULL) {
208: fprintf(stderr,
209: "xmlAddDtdEntity: document without external subset !\n");
1.16 daniel 210: return;
211: }
1.22 daniel 212: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.2 httpng 213: if (table == NULL) {
214: table = xmlCreateEntitiesTable();
1.22 daniel 215: doc->extSubset->entities = table;
1.1 httpng 216: }
1.13 daniel 217: xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1 httpng 218: }
219:
1.22 daniel 220: /**
221: * xmlAddDocEntity:
222: * @doc: the document
223: * @name: the entity name
224: * @type: the entity type XML_xxx_yyy_ENTITY
225: * @ExternalID: the entity external ID if available
226: * @SystemID: the entity system ID if available
227: * @content: the entity content
228: *
229: * Register a new entity for this document.
1.1 httpng 230: */
1.22 daniel 231: void
1.38 daniel 232: xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
233: const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
1.16 daniel 234: xmlEntitiesTablePtr table;
235:
1.22 daniel 236: if (doc == NULL) {
237: fprintf(stderr,
238: "xmlAddDocEntity: document is NULL !\n");
239: return;
240: }
241: if (doc->intSubset == NULL) {
242: fprintf(stderr,
243: "xmlAddDtdEntity: document without internal subset !\n");
244: return;
245: }
246: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16 daniel 247: if (table == NULL) {
248: table = xmlCreateEntitiesTable();
1.22 daniel 249: doc->intSubset->entities = table;
1.2 httpng 250: }
1.22 daniel 251: xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1 httpng 252: }
253:
1.22 daniel 254: /**
1.30 daniel 255: * xmlGetParameterEntity:
256: * @doc: the document referencing the entity
257: * @name: the entity name
258: *
259: * Do an entity lookup in the internal and external subsets and
260: * returns the corresponding parameter entity, if found.
261: *
262: * Returns A pointer to the entity structure or NULL if not found.
263: */
264: xmlEntityPtr
1.38 daniel 265: xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
1.30 daniel 266: int i;
267: xmlEntityPtr cur;
268: xmlEntitiesTablePtr table;
269:
270: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
271: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
272: for (i = 0;i < table->nb_entities;i++) {
273: cur = &table->table[i];
274: if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) ||
275: (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
276: (!xmlStrcmp(cur->name, name))) return(cur);
277: }
278: }
279: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
280: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
281: for (i = 0;i < table->nb_entities;i++) {
282: cur = &table->table[i];
283: if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) ||
284: (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
285: (!xmlStrcmp(cur->name, name))) return(cur);
286: }
287: }
1.35 daniel 288: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
289: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
290: for (i = 0;i < table->nb_entities;i++) {
291: cur = &table->table[i];
292: if (((cur->type == XML_INTERNAL_PARAMETER_ENTITY) ||
293: (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
294: (!xmlStrcmp(cur->name, name))) return(cur);
295: }
296: }
1.30 daniel 297: return(NULL);
298: }
299:
300: /**
1.22 daniel 301: * xmlGetDtdEntity:
302: * @doc: the document referencing the entity
303: * @name: the entity name
304: *
305: * Do an entity lookup in the Dtd entity hash table and
306: * returns the corresponding entity, if found.
307: *
1.24 daniel 308: * Returns A pointer to the entity structure or NULL if not found.
1.1 httpng 309: */
1.22 daniel 310: xmlEntityPtr
1.38 daniel 311: xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
1.2 httpng 312: int i;
313: xmlEntityPtr cur;
314: xmlEntitiesTablePtr table;
315:
1.22 daniel 316: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
317: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.15 daniel 318: for (i = 0;i < table->nb_entities;i++) {
319: cur = &table->table[i];
1.30 daniel 320: if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
321: (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) &&
322: (!xmlStrcmp(cur->name, name))) return(cur);
1.15 daniel 323: }
324: }
1.7 veillard 325: return(NULL);
1.3 httpng 326: }
327:
1.22 daniel 328: /**
329: * xmlGetDocEntity:
330: * @doc: the document referencing the entity
331: * @name: the entity name
332: *
333: * Do an entity lookup in the document entity hash table and
334: * returns the corrsponding entity, otherwise a lookup is done
335: * in the predefined entities too.
336: *
1.24 daniel 337: * Returns A pointer to the entity structure or NULL if not found.
1.14 daniel 338: */
1.22 daniel 339: xmlEntityPtr
1.38 daniel 340: xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
1.14 daniel 341: int i;
1.16 daniel 342: xmlEntityPtr cur;
1.14 daniel 343: xmlEntitiesTablePtr table;
344:
1.22 daniel 345: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
346: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16 daniel 347: for (i = 0;i < table->nb_entities;i++) {
348: cur = &table->table[i];
1.30 daniel 349: if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
350: (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) &&
351: (!xmlStrcmp(cur->name, name))) return(cur);
1.16 daniel 352: }
353: }
1.34 daniel 354: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
355: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
356: for (i = 0;i < table->nb_entities;i++) {
357: cur = &table->table[i];
358: if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
359: (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) &&
360: (!xmlStrcmp(cur->name, name))) return(cur);
361: }
362: }
1.15 daniel 363: if (xmlPredefinedEntities == NULL)
364: xmlInitializePredefinedEntities();
1.16 daniel 365: table = xmlPredefinedEntities;
366: for (i = 0;i < table->nb_entities;i++) {
367: cur = &table->table[i];
1.30 daniel 368: if ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
369: (cur->type != XML_EXTERNAL_PARAMETER_ENTITY) &&
370: (!xmlStrcmp(cur->name, name))) return(cur);
1.14 daniel 371: }
372:
373: return(NULL);
1.1 httpng 374: }
375:
376: /*
1.21 daniel 377: * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
378: * | [#x10000-#x10FFFF]
379: * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
380: */
381: #define IS_CHAR(c) \
382: (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
383: (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
384:
1.28 daniel 385: /*
386: * A buffer used for converting entities to their equivalent and back.
387: */
388: static int buffer_size = 0;
1.38 daniel 389: static xmlChar *buffer = NULL;
1.28 daniel 390:
1.44 daniel 391: int growBuffer(void) {
1.28 daniel 392: buffer_size *= 2;
1.38 daniel 393: buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
1.28 daniel 394: if (buffer == NULL) {
395: perror("realloc failed");
1.44 daniel 396: return(-1);
1.28 daniel 397: }
1.44 daniel 398: return(0);
1.28 daniel 399: }
400:
401:
1.22 daniel 402: /**
403: * xmlEncodeEntities:
404: * @doc: the document containing the string
405: * @input: A string to convert to XML.
406: *
407: * Do a global encoding of a string, replacing the predefined entities
408: * and non ASCII values with their entities and CharRef counterparts.
409: *
1.33 daniel 410: * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
411: * compatibility
1.28 daniel 412: *
413: * People must migrate their code to xmlEncodeEntitiesReentrant !
1.31 daniel 414: * This routine will issue a warning when encountered.
1.28 daniel 415: *
416: * Returns A newly allocated string with the substitution done.
417: */
1.38 daniel 418: const xmlChar *
419: xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
420: const xmlChar *cur = input;
421: xmlChar *out = buffer;
1.31 daniel 422: static int warning = 1;
1.39 daniel 423: int html = 0;
424:
1.31 daniel 425:
426: if (warning) {
427: fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
428: fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n");
429: warning = 0;
430: }
1.28 daniel 431:
432: if (input == NULL) return(NULL);
1.39 daniel 433: if (doc != NULL)
434: html = (doc->type == XML_HTML_DOCUMENT_NODE);
435:
1.28 daniel 436: if (buffer == NULL) {
437: buffer_size = 1000;
1.38 daniel 438: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.28 daniel 439: if (buffer == NULL) {
440: perror("malloc failed");
1.44 daniel 441: return(NULL);
1.28 daniel 442: }
443: out = buffer;
444: }
445: while (*cur != '\0') {
446: if (out - buffer > buffer_size - 100) {
447: int index = out - buffer;
448:
449: growBuffer();
450: out = &buffer[index];
451: }
452:
453: /*
454: * By default one have to encode at least '<', '>', '"' and '&' !
455: */
456: if (*cur == '<') {
457: *out++ = '&';
458: *out++ = 'l';
459: *out++ = 't';
460: *out++ = ';';
461: } else if (*cur == '>') {
462: *out++ = '&';
463: *out++ = 'g';
464: *out++ = 't';
465: *out++ = ';';
466: } else if (*cur == '&') {
467: *out++ = '&';
468: *out++ = 'a';
469: *out++ = 'm';
470: *out++ = 'p';
471: *out++ = ';';
472: } else if (*cur == '"') {
473: *out++ = '&';
474: *out++ = 'q';
475: *out++ = 'u';
476: *out++ = 'o';
477: *out++ = 't';
478: *out++ = ';';
1.39 daniel 479: } else if ((*cur == '\'') && (!html)) {
1.28 daniel 480: *out++ = '&';
481: *out++ = 'a';
482: *out++ = 'p';
483: *out++ = 'o';
484: *out++ = 's';
485: *out++ = ';';
486: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
487: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
488: /*
489: * default case, just copy !
490: */
491: *out++ = *cur;
492: #ifndef USE_UTF_8
1.38 daniel 493: } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
1.28 daniel 494: char buf[10], *ptr;
495: #ifdef HAVE_SNPRINTF
496: snprintf(buf, 9, "&#%d;", *cur);
497: #else
498: sprintf(buf, "&#%d;", *cur);
499: #endif
500: ptr = buf;
501: while (*ptr != 0) *out++ = *ptr++;
502: #endif
503: } else if (IS_CHAR(*cur)) {
504: char buf[10], *ptr;
505:
506: #ifdef HAVE_SNPRINTF
507: snprintf(buf, 9, "&#%d;", *cur);
508: #else
509: sprintf(buf, "&#%d;", *cur);
510: #endif
511: ptr = buf;
512: while (*ptr != 0) *out++ = *ptr++;
513: }
514: #if 0
515: else {
516: /*
517: * default case, this is not a valid char !
518: * Skip it...
519: */
520: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
521: }
522: #endif
523: cur++;
524: }
525: *out++ = 0;
526: return(buffer);
527: }
528:
529: /*
530: * Macro used to grow the current buffer.
531: */
532: #define growBufferReentrant() { \
533: buffer_size *= 2; \
1.44 daniel 534: buffer = (xmlChar *) \
535: xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
1.28 daniel 536: if (buffer == NULL) { \
537: perror("realloc failed"); \
1.44 daniel 538: return(NULL); \
1.28 daniel 539: } \
540: }
541:
542:
543: /**
544: * xmlEncodeEntitiesReentrant:
545: * @doc: the document containing the string
546: * @input: A string to convert to XML.
547: *
548: * Do a global encoding of a string, replacing the predefined entities
549: * and non ASCII values with their entities and CharRef counterparts.
550: * Contrary to xmlEncodeEntities, this routine is reentrant, and result
551: * must be deallocated.
552: *
553: * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
554: * get erroneous.
555: *
1.24 daniel 556: * Returns A newly allocated string with the substitution done.
1.1 httpng 557: */
1.38 daniel 558: xmlChar *
559: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
560: const xmlChar *cur = input;
561: xmlChar *buffer = NULL;
562: xmlChar *out = NULL;
1.26 daniel 563: int buffer_size = 0;
1.39 daniel 564: int html = 0;
1.3 httpng 565:
1.19 daniel 566: if (input == NULL) return(NULL);
1.39 daniel 567: if (doc != NULL)
568: html = (doc->type == XML_HTML_DOCUMENT_NODE);
1.26 daniel 569:
570: /*
571: * allocate an translation buffer.
572: */
573: buffer_size = 1000;
1.38 daniel 574: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.3 httpng 575: if (buffer == NULL) {
1.26 daniel 576: perror("malloc failed");
1.44 daniel 577: return(NULL);
1.3 httpng 578: }
1.26 daniel 579: out = buffer;
580:
1.6 veillard 581: while (*cur != '\0') {
582: if (out - buffer > buffer_size - 100) {
583: int index = out - buffer;
584:
1.28 daniel 585: growBufferReentrant();
1.6 veillard 586: out = &buffer[index];
587: }
588:
589: /*
1.7 veillard 590: * By default one have to encode at least '<', '>', '"' and '&' !
1.6 veillard 591: */
592: if (*cur == '<') {
593: *out++ = '&';
594: *out++ = 'l';
595: *out++ = 't';
596: *out++ = ';';
1.7 veillard 597: } else if (*cur == '>') {
598: *out++ = '&';
599: *out++ = 'g';
600: *out++ = 't';
601: *out++ = ';';
1.6 veillard 602: } else if (*cur == '&') {
603: *out++ = '&';
604: *out++ = 'a';
605: *out++ = 'm';
606: *out++ = 'p';
1.7 veillard 607: *out++ = ';';
608: } else if (*cur == '"') {
609: *out++ = '&';
610: *out++ = 'q';
611: *out++ = 'u';
612: *out++ = 'o';
613: *out++ = 't';
614: *out++ = ';';
1.39 daniel 615: } else if ((*cur == '\'') && (!html)) {
1.7 veillard 616: *out++ = '&';
617: *out++ = 'a';
618: *out++ = 'p';
619: *out++ = 'o';
620: *out++ = 's';
1.6 veillard 621: *out++ = ';';
1.21 daniel 622: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
623: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
624: /*
625: * default case, just copy !
626: */
627: *out++ = *cur;
1.46 daniel 628: } else if (*cur >= 0x80) {
629: if (html) {
1.45 daniel 630: char buf[10], *ptr;
1.46 daniel 631:
632: /*
633: * TODO: improve by searching in html40EntitiesTable
634: */
1.19 daniel 635: #ifdef HAVE_SNPRINTF
1.45 daniel 636: snprintf(buf, 9, "&#%d;", *cur);
1.19 daniel 637: #else
1.45 daniel 638: sprintf(buf, "&#%d;", *cur);
1.19 daniel 639: #endif
1.45 daniel 640: ptr = buf;
641: while (*ptr != 0) *out++ = *ptr++;
1.46 daniel 642: } else if (doc->encoding != NULL) {
643: /*
644: * TODO !!!
645: */
646: *out++ = *cur;
647: } else {
648: /*
649: * We assume we have UTF-8 input.
650: */
651: char buf[10], *ptr;
1.48 ! daniel 652: int val = 0, l = 1;
1.46 daniel 653:
654: if (*cur < 0xC0) {
655: fprintf(stderr,
656: "xmlEncodeEntitiesReentrant : input not UTF-8\n");
657: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
658: #ifdef HAVE_SNPRINTF
659: snprintf(buf, 9, "&#%d;", *cur);
660: #else
661: sprintf(buf, "&#%d;", *cur);
662: #endif
663: ptr = buf;
664: while (*ptr != 0) *out++ = *ptr++;
665: continue;
666: } else if (*cur < 0xE0) {
667: val = (cur[0]) & 0x1F;
668: val <<= 6;
669: val |= (cur[1]) & 0x3F;
670: l = 2;
671: } else if (*cur < 0xF0) {
672: val = (cur[0]) & 0x0F;
673: val <<= 6;
674: val |= (cur[1]) & 0x3F;
675: val <<= 6;
676: val |= (cur[2]) & 0x3F;
677: l = 3;
678: } else if (*cur < 0xF8) {
679: val = (cur[0]) & 0x07;
680: val <<= 6;
681: val |= (cur[1]) & 0x3F;
682: val <<= 6;
683: val |= (cur[2]) & 0x3F;
684: val <<= 6;
685: val |= (cur[3]) & 0x3F;
686: l = 4;
687: }
688: if ((l == 1) || (!IS_CHAR(val))) {
689: fprintf(stderr,
690: "xmlEncodeEntitiesReentrant : char out of range\n");
691: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
692: #ifdef HAVE_SNPRINTF
693: snprintf(buf, 9, "&#%d;", *cur);
694: #else
695: sprintf(buf, "&#%d;", *cur);
696: #endif
697: ptr = buf;
698: while (*ptr != 0) *out++ = *ptr++;
699: cur++;
700: continue;
701: }
702: /*
703: * We could do multiple things here. Just save as a char ref
704: */
705: #ifdef HAVE_SNPRINTF
1.47 daniel 706: snprintf(buf, 9, "&#%d;", val);
1.46 daniel 707: #else
1.47 daniel 708: sprintf(buf, "&#%d;", val);
1.46 daniel 709: #endif
1.47 daniel 710: ptr = buf;
711: while (*ptr != 0) *out++ = *ptr++;
712: cur += l;
713: continue;
1.45 daniel 714: }
1.21 daniel 715: } else if (IS_CHAR(*cur)) {
1.20 daniel 716: char buf[10], *ptr;
717:
718: #ifdef HAVE_SNPRINTF
719: snprintf(buf, 9, "&#%d;", *cur);
720: #else
721: sprintf(buf, "&#%d;", *cur);
722: #endif
723: ptr = buf;
724: while (*ptr != 0) *out++ = *ptr++;
1.21 daniel 725: }
726: #if 0
727: else {
1.6 veillard 728: /*
1.21 daniel 729: * default case, this is not a valid char !
730: * Skip it...
1.6 veillard 731: */
1.21 daniel 732: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6 veillard 733: }
1.21 daniel 734: #endif
1.6 veillard 735: cur++;
736: }
737: *out++ = 0;
738: return(buffer);
1.2 httpng 739: }
740:
1.22 daniel 741: /**
742: * xmlCreateEntitiesTable:
743: *
744: * create and initialize an empty entities hash table.
745: *
1.24 daniel 746: * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2 httpng 747: */
1.22 daniel 748: xmlEntitiesTablePtr
749: xmlCreateEntitiesTable(void) {
1.2 httpng 750: xmlEntitiesTablePtr ret;
1.1 httpng 751:
1.2 httpng 752: ret = (xmlEntitiesTablePtr)
1.36 daniel 753: xmlMalloc(sizeof(xmlEntitiesTable));
1.1 httpng 754: if (ret == NULL) {
1.36 daniel 755: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 756: (long)sizeof(xmlEntitiesTable));
1.2 httpng 757: return(NULL);
758: }
759: ret->max_entities = XML_MIN_ENTITIES_TABLE;
760: ret->nb_entities = 0;
761: ret->table = (xmlEntityPtr )
1.36 daniel 762: xmlMalloc(ret->max_entities * sizeof(xmlEntity));
1.2 httpng 763: if (ret == NULL) {
1.36 daniel 764: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 765: ret->max_entities * (long)sizeof(xmlEntity));
1.36 daniel 766: xmlFree(ret);
1.1 httpng 767: return(NULL);
768: }
769: return(ret);
770: }
771:
1.22 daniel 772: /**
773: * xmlFreeEntitiesTable:
774: * @table: An entity table
775: *
776: * Deallocate the memory used by an entities hash table.
1.1 httpng 777: */
1.22 daniel 778: void
779: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 780: int i;
781:
782: if (table == NULL) return;
783:
1.2 httpng 784: for (i = 0;i < table->nb_entities;i++) {
785: xmlFreeEntity(&table->table[i]);
1.1 httpng 786: }
1.36 daniel 787: xmlFree(table->table);
788: xmlFree(table);
1.1 httpng 789: }
790:
1.22 daniel 791: /**
792: * xmlCopyEntitiesTable:
793: * @table: An entity table
794: *
795: * Build a copy of an entity table.
796: *
1.24 daniel 797: * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22 daniel 798: */
799: xmlEntitiesTablePtr
800: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
801: xmlEntitiesTablePtr ret;
802: xmlEntityPtr cur, ent;
803: int i;
804:
1.36 daniel 805: ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
1.22 daniel 806: if (ret == NULL) {
807: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
808: return(NULL);
809: }
1.36 daniel 810: ret->table = (xmlEntityPtr) xmlMalloc(table->max_entities *
1.22 daniel 811: sizeof(xmlEntity));
812: if (ret->table == NULL) {
813: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1.36 daniel 814: xmlFree(ret);
1.22 daniel 815: return(NULL);
816: }
817: ret->max_entities = table->max_entities;
818: ret->nb_entities = table->nb_entities;
819: for (i = 0;i < ret->nb_entities;i++) {
820: cur = &ret->table[i];
821: ent = &table->table[i];
822: cur->len = ent->len;
823: cur->type = ent->type;
824: if (ent->name != NULL)
825: cur->name = xmlStrdup(ent->name);
826: else
827: cur->name = NULL;
828: if (ent->ExternalID != NULL)
829: cur->ExternalID = xmlStrdup(ent->ExternalID);
830: else
831: cur->ExternalID = NULL;
832: if (ent->SystemID != NULL)
833: cur->SystemID = xmlStrdup(ent->SystemID);
834: else
835: cur->SystemID = NULL;
836: if (ent->content != NULL)
837: cur->content = xmlStrdup(ent->content);
838: else
839: cur->content = NULL;
1.27 daniel 840: if (ent->orig != NULL)
841: cur->orig = xmlStrdup(ent->orig);
842: else
843: cur->orig = NULL;
1.22 daniel 844: }
845: return(ret);
846: }
847:
848: /**
849: * xmlDumpEntitiesTable:
1.25 daniel 850: * @buf: An XML buffer.
1.22 daniel 851: * @table: An entity table
852: *
853: * This will dump the content of the entity table as an XML DTD definition
1.13 daniel 854: */
1.22 daniel 855: void
1.25 daniel 856: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14 daniel 857: int i;
858: xmlEntityPtr cur;
859:
860: if (table == NULL) return;
861:
862: for (i = 0;i < table->nb_entities;i++) {
863: cur = &table->table[i];
864: switch (cur->type) {
865: case XML_INTERNAL_GENERAL_ENTITY:
1.25 daniel 866: xmlBufferWriteChar(buf, "<!ENTITY ");
867: xmlBufferWriteCHAR(buf, cur->name);
1.27 daniel 868: xmlBufferWriteChar(buf, " ");
869: if (cur->orig != NULL)
870: xmlBufferWriteQuotedString(buf, cur->orig);
871: else
872: xmlBufferWriteQuotedString(buf, cur->content);
873: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 874: break;
875: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.25 daniel 876: xmlBufferWriteChar(buf, "<!ENTITY ");
877: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 878: if (cur->ExternalID != NULL) {
1.27 daniel 879: xmlBufferWriteChar(buf, " PUBLIC ");
880: xmlBufferWriteQuotedString(buf, cur->ExternalID);
881: xmlBufferWriteChar(buf, " ");
882: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 883: } else {
1.27 daniel 884: xmlBufferWriteChar(buf, " SYSTEM ");
885: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 886: }
1.25 daniel 887: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 888: break;
889: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.25 daniel 890: xmlBufferWriteChar(buf, "<!ENTITY ");
891: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 892: if (cur->ExternalID != NULL) {
1.27 daniel 893: xmlBufferWriteChar(buf, " PUBLIC ");
894: xmlBufferWriteQuotedString(buf, cur->ExternalID);
895: xmlBufferWriteChar(buf, " ");
896: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 897: } else {
1.27 daniel 898: xmlBufferWriteChar(buf, " SYSTEM ");
899: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 900: }
901: if (cur->content != NULL) { /* Should be true ! */
1.25 daniel 902: xmlBufferWriteChar(buf, " NDATA ");
1.27 daniel 903: if (cur->orig != NULL)
904: xmlBufferWriteCHAR(buf, cur->orig);
905: else
906: xmlBufferWriteCHAR(buf, cur->content);
1.14 daniel 907: }
1.25 daniel 908: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 909: break;
910: case XML_INTERNAL_PARAMETER_ENTITY:
1.25 daniel 911: xmlBufferWriteChar(buf, "<!ENTITY % ");
912: xmlBufferWriteCHAR(buf, cur->name);
1.27 daniel 913: xmlBufferWriteChar(buf, " ");
914: if (cur->orig == NULL)
915: xmlBufferWriteQuotedString(buf, cur->content);
916: else
917: xmlBufferWriteQuotedString(buf, cur->orig);
918: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 919: break;
920: case XML_EXTERNAL_PARAMETER_ENTITY:
1.25 daniel 921: xmlBufferWriteChar(buf, "<!ENTITY % ");
922: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 923: if (cur->ExternalID != NULL) {
1.27 daniel 924: xmlBufferWriteChar(buf, " PUBLIC ");
925: xmlBufferWriteQuotedString(buf, cur->ExternalID);
926: xmlBufferWriteChar(buf, " ");
927: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 928: } else {
1.27 daniel 929: xmlBufferWriteChar(buf, " SYSTEM ");
930: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 931: }
1.25 daniel 932: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 933: break;
934: default:
935: fprintf(stderr,
936: "xmlDumpEntitiesTable: internal: unknown type %d\n",
937: cur->type);
938: }
939: }
1.13 daniel 940: }
Webmaster