Annotation of XML/entities.c, revision 1.46
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;
! 652: int val, l = 1;
! 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: * if it fits on one byte
! 705: */
! 706: if (val <= 0xFF) {
! 707: #ifdef HAVE_SNPRINTF
! 708: snprintf(buf, 9, "&#%d;", val);
! 709: #else
! 710: sprintf(buf, "&#%d;", val);
! 711: #endif
! 712: ptr = buf;
! 713: while (*ptr != 0) *out++ = *ptr++;
! 714: cur += l;
! 715: continue;
! 716: } else {
! 717: int i;
! 718: while (l-- > 0)
! 719: *out++ = *cur++;
! 720: continue;
! 721: }
1.45 daniel 722: }
1.21 daniel 723: } else if (IS_CHAR(*cur)) {
1.20 daniel 724: char buf[10], *ptr;
725:
726: #ifdef HAVE_SNPRINTF
727: snprintf(buf, 9, "&#%d;", *cur);
728: #else
729: sprintf(buf, "&#%d;", *cur);
730: #endif
731: ptr = buf;
732: while (*ptr != 0) *out++ = *ptr++;
1.21 daniel 733: }
734: #if 0
735: else {
1.6 veillard 736: /*
1.21 daniel 737: * default case, this is not a valid char !
738: * Skip it...
1.6 veillard 739: */
1.21 daniel 740: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6 veillard 741: }
1.21 daniel 742: #endif
1.6 veillard 743: cur++;
744: }
745: *out++ = 0;
746: return(buffer);
1.2 httpng 747: }
748:
1.22 daniel 749: /**
750: * xmlCreateEntitiesTable:
751: *
752: * create and initialize an empty entities hash table.
753: *
1.24 daniel 754: * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2 httpng 755: */
1.22 daniel 756: xmlEntitiesTablePtr
757: xmlCreateEntitiesTable(void) {
1.2 httpng 758: xmlEntitiesTablePtr ret;
1.1 httpng 759:
1.2 httpng 760: ret = (xmlEntitiesTablePtr)
1.36 daniel 761: xmlMalloc(sizeof(xmlEntitiesTable));
1.1 httpng 762: if (ret == NULL) {
1.36 daniel 763: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 764: (long)sizeof(xmlEntitiesTable));
1.2 httpng 765: return(NULL);
766: }
767: ret->max_entities = XML_MIN_ENTITIES_TABLE;
768: ret->nb_entities = 0;
769: ret->table = (xmlEntityPtr )
1.36 daniel 770: xmlMalloc(ret->max_entities * sizeof(xmlEntity));
1.2 httpng 771: if (ret == NULL) {
1.36 daniel 772: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 773: ret->max_entities * (long)sizeof(xmlEntity));
1.36 daniel 774: xmlFree(ret);
1.1 httpng 775: return(NULL);
776: }
777: return(ret);
778: }
779:
1.22 daniel 780: /**
781: * xmlFreeEntitiesTable:
782: * @table: An entity table
783: *
784: * Deallocate the memory used by an entities hash table.
1.1 httpng 785: */
1.22 daniel 786: void
787: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 788: int i;
789:
790: if (table == NULL) return;
791:
1.2 httpng 792: for (i = 0;i < table->nb_entities;i++) {
793: xmlFreeEntity(&table->table[i]);
1.1 httpng 794: }
1.36 daniel 795: xmlFree(table->table);
796: xmlFree(table);
1.1 httpng 797: }
798:
1.22 daniel 799: /**
800: * xmlCopyEntitiesTable:
801: * @table: An entity table
802: *
803: * Build a copy of an entity table.
804: *
1.24 daniel 805: * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22 daniel 806: */
807: xmlEntitiesTablePtr
808: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
809: xmlEntitiesTablePtr ret;
810: xmlEntityPtr cur, ent;
811: int i;
812:
1.36 daniel 813: ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
1.22 daniel 814: if (ret == NULL) {
815: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
816: return(NULL);
817: }
1.36 daniel 818: ret->table = (xmlEntityPtr) xmlMalloc(table->max_entities *
1.22 daniel 819: sizeof(xmlEntity));
820: if (ret->table == NULL) {
821: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1.36 daniel 822: xmlFree(ret);
1.22 daniel 823: return(NULL);
824: }
825: ret->max_entities = table->max_entities;
826: ret->nb_entities = table->nb_entities;
827: for (i = 0;i < ret->nb_entities;i++) {
828: cur = &ret->table[i];
829: ent = &table->table[i];
830: cur->len = ent->len;
831: cur->type = ent->type;
832: if (ent->name != NULL)
833: cur->name = xmlStrdup(ent->name);
834: else
835: cur->name = NULL;
836: if (ent->ExternalID != NULL)
837: cur->ExternalID = xmlStrdup(ent->ExternalID);
838: else
839: cur->ExternalID = NULL;
840: if (ent->SystemID != NULL)
841: cur->SystemID = xmlStrdup(ent->SystemID);
842: else
843: cur->SystemID = NULL;
844: if (ent->content != NULL)
845: cur->content = xmlStrdup(ent->content);
846: else
847: cur->content = NULL;
1.27 daniel 848: if (ent->orig != NULL)
849: cur->orig = xmlStrdup(ent->orig);
850: else
851: cur->orig = NULL;
1.22 daniel 852: }
853: return(ret);
854: }
855:
856: /**
857: * xmlDumpEntitiesTable:
1.25 daniel 858: * @buf: An XML buffer.
1.22 daniel 859: * @table: An entity table
860: *
861: * This will dump the content of the entity table as an XML DTD definition
1.13 daniel 862: */
1.22 daniel 863: void
1.25 daniel 864: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14 daniel 865: int i;
866: xmlEntityPtr cur;
867:
868: if (table == NULL) return;
869:
870: for (i = 0;i < table->nb_entities;i++) {
871: cur = &table->table[i];
872: switch (cur->type) {
873: case XML_INTERNAL_GENERAL_ENTITY:
1.25 daniel 874: xmlBufferWriteChar(buf, "<!ENTITY ");
875: xmlBufferWriteCHAR(buf, cur->name);
1.27 daniel 876: xmlBufferWriteChar(buf, " ");
877: if (cur->orig != NULL)
878: xmlBufferWriteQuotedString(buf, cur->orig);
879: else
880: xmlBufferWriteQuotedString(buf, cur->content);
881: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 882: break;
883: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.25 daniel 884: xmlBufferWriteChar(buf, "<!ENTITY ");
885: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 886: if (cur->ExternalID != NULL) {
1.27 daniel 887: xmlBufferWriteChar(buf, " PUBLIC ");
888: xmlBufferWriteQuotedString(buf, cur->ExternalID);
889: xmlBufferWriteChar(buf, " ");
890: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 891: } else {
1.27 daniel 892: xmlBufferWriteChar(buf, " SYSTEM ");
893: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 894: }
1.25 daniel 895: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 896: break;
897: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.25 daniel 898: xmlBufferWriteChar(buf, "<!ENTITY ");
899: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 900: if (cur->ExternalID != NULL) {
1.27 daniel 901: xmlBufferWriteChar(buf, " PUBLIC ");
902: xmlBufferWriteQuotedString(buf, cur->ExternalID);
903: xmlBufferWriteChar(buf, " ");
904: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 905: } else {
1.27 daniel 906: xmlBufferWriteChar(buf, " SYSTEM ");
907: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 908: }
909: if (cur->content != NULL) { /* Should be true ! */
1.25 daniel 910: xmlBufferWriteChar(buf, " NDATA ");
1.27 daniel 911: if (cur->orig != NULL)
912: xmlBufferWriteCHAR(buf, cur->orig);
913: else
914: xmlBufferWriteCHAR(buf, cur->content);
1.14 daniel 915: }
1.25 daniel 916: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 917: break;
918: case XML_INTERNAL_PARAMETER_ENTITY:
1.25 daniel 919: xmlBufferWriteChar(buf, "<!ENTITY % ");
920: xmlBufferWriteCHAR(buf, cur->name);
1.27 daniel 921: xmlBufferWriteChar(buf, " ");
922: if (cur->orig == NULL)
923: xmlBufferWriteQuotedString(buf, cur->content);
924: else
925: xmlBufferWriteQuotedString(buf, cur->orig);
926: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 927: break;
928: case XML_EXTERNAL_PARAMETER_ENTITY:
1.25 daniel 929: xmlBufferWriteChar(buf, "<!ENTITY % ");
930: xmlBufferWriteCHAR(buf, cur->name);
1.14 daniel 931: if (cur->ExternalID != NULL) {
1.27 daniel 932: xmlBufferWriteChar(buf, " PUBLIC ");
933: xmlBufferWriteQuotedString(buf, cur->ExternalID);
934: xmlBufferWriteChar(buf, " ");
935: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 936: } else {
1.27 daniel 937: xmlBufferWriteChar(buf, " SYSTEM ");
938: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14 daniel 939: }
1.25 daniel 940: xmlBufferWriteChar(buf, ">\n");
1.14 daniel 941: break;
942: default:
943: fprintf(stderr,
944: "xmlDumpEntitiesTable: internal: unknown type %d\n",
945: cur->type);
946: }
947: }
1.13 daniel 948: }
Webmaster