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