Annotation of XML/entities.c, revision 1.19
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.19 ! daniel 6: * $Id: entities.c,v 1.7 1998/11/04 20:07:03 veillard Exp $
1.1 httpng 7: */
8:
9: #include <stdio.h>
1.17 daniel 10: #include <stdlib.h>
1.10 daniel 11: #include <string.h>
1.1 httpng 12: #include "entities.h"
13:
14: /*
1.15 daniel 15: * The XML predefined entities.
16: */
17:
18: struct xmlPredefinedEntityValue {
19: const char *name;
20: const char *value;
21: };
22: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
23: { "lt", "<" },
24: { "gt", ">" },
25: { "apos", "'" },
26: { "quot", "\"" },
27: { "amp", "&" }
28: };
29:
30: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
31:
32: /*
1.3 httpng 33: * A buffer used for converting entities to their equivalent and back.
34: */
1.14 daniel 35: static int buffer_size = 0;
1.6 veillard 36: static CHAR *buffer = NULL;
1.3 httpng 37:
38: void growBuffer(void) {
39: buffer_size *= 2;
40: buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
41: if (buffer == NULL) {
42: perror("realloc failed");
43: exit(1);
44: }
45: }
46:
47: /*
1.2 httpng 48: * xmlFreeEntity : clean-up an entity record.
1.1 httpng 49: */
50:
1.2 httpng 51: void xmlFreeEntity(xmlEntityPtr entity) {
52: if (entity == NULL) return;
53:
1.11 daniel 54: if (entity->name != NULL)
55: free((char *) entity->name);
1.14 daniel 56: if (entity->ExternalID != NULL)
57: free((char *) entity->ExternalID);
58: if (entity->SystemID != NULL)
59: free((char *) entity->SystemID);
60: if (entity->content != NULL)
61: free((char *) entity->content);
62: memset(entity, -1, sizeof(xmlEntity));
1.2 httpng 63: }
1.1 httpng 64:
65: /*
1.2 httpng 66: * xmlAddDocEntity : register a new entity for an entities table.
1.13 daniel 67: *
68: * TODO !!! We should check here that the combination of type
69: * ExternalID and SystemID is valid.
1.1 httpng 70: */
1.13 daniel 71: static void xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
72: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2 httpng 73: int i;
74: xmlEntityPtr cur;
1.14 daniel 75: int len;
1.1 httpng 76:
1.2 httpng 77: for (i = 0;i < table->nb_entities;i++) {
78: cur = &table->table[i];
1.11 daniel 79: if (!xmlStrcmp(cur->name, name)) {
1.13 daniel 80: /*
81: * The entity is already defined in this Dtd, the spec says to NOT
82: * override it ... Is it worth a Warning ??? !!!
83: */
84: return;
1.7 veillard 85: }
1.2 httpng 86: }
87: if (table->nb_entities >= table->max_entities) {
88: /*
89: * need more elements.
90: */
91: table->max_entities *= 2;
92: table->table = (xmlEntityPtr)
93: realloc(table->table, table->max_entities * sizeof(xmlEntity));
94: if (table->table) {
95: perror("realloc failed");
96: exit(1);
97: }
98: }
99: cur = &table->table[table->nb_entities];
1.11 daniel 100: cur->name = xmlStrdup(name);
1.14 daniel 101: for (len = 0;name[0] != 0;name++)len++;
102: cur->len = len;
1.13 daniel 103: cur->type = type;
104: if (ExternalID != NULL)
105: cur->ExternalID = xmlStrdup(ExternalID);
1.14 daniel 106: else
107: cur->ExternalID = NULL;
1.13 daniel 108: if (SystemID != NULL)
1.14 daniel 109: cur->SystemID = xmlStrdup(SystemID);
110: else
111: cur->SystemID = NULL;
1.13 daniel 112: if (content != NULL)
113: cur->content = xmlStrdup(content);
1.14 daniel 114: else
115: cur->content = NULL;
1.2 httpng 116: table->nb_entities++;
117: }
1.1 httpng 118:
1.15 daniel 119: /*
120: * Set up xmlPredefinedEntities from xmlPredefinedEntityValues.
121: */
122: void xmlInitializePredefinedEntities(void) {
123: int i;
124: CHAR name[50];
125: CHAR value[50];
126: const char *in;
127: CHAR *out;
128:
129: if (xmlPredefinedEntities != NULL) return;
130:
131: xmlPredefinedEntities = xmlCreateEntitiesTable();
132: for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
133: sizeof(xmlPredefinedEntityValues[0]);i++) {
134: in = xmlPredefinedEntityValues[i].name;
135: out = &name[0];
136: for (;(*out++ = (CHAR) *in);)in++;
137: in = xmlPredefinedEntityValues[i].value;
138: out = &value[0];
139: for (;(*out++ = (CHAR) *in);)in++;
140: xmlAddEntity(xmlPredefinedEntities, (const CHAR *) &name[0],
1.18 daniel 141: XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15 daniel 142: &value[0]);
143: }
144: }
1.17 daniel 145:
146: /**
147: * xmlGetPredefinedEntity:
148: * @name: the entity name
149: *
150: * Check whether this name is an predefined entity.
151: *
152: * return values: NULL if not, othervise the entity
153: */
154: xmlEntityPtr
155: xmlGetPredefinedEntity(const CHAR *name) {
156: int i;
157: xmlEntityPtr cur;
158:
159: if (xmlPredefinedEntities == NULL)
160: xmlInitializePredefinedEntities();
161: for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
162: cur = &xmlPredefinedEntities->table[i];
163: if (!xmlStrcmp(cur->name, name)) return(cur);
164: }
165: return(NULL);
166: }
167:
1.15 daniel 168:
1.1 httpng 169:
170: /*
1.12 daniel 171: * xmlAddDtdEntity : register a new entity for this DTD.
1.1 httpng 172: */
1.16 daniel 173: void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
1.13 daniel 174: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2 httpng 175: xmlEntitiesTablePtr table;
1.1 httpng 176:
1.16 daniel 177: if (doc->dtd == NULL) {
178: fprintf(stderr, "xmlAddDtdEntity: document without Dtd !\n");
179: return;
180: }
181: table = (xmlEntitiesTablePtr) doc->dtd->entities;
1.2 httpng 182: if (table == NULL) {
183: table = xmlCreateEntitiesTable();
1.16 daniel 184: doc->dtd->entities = table;
1.1 httpng 185: }
1.13 daniel 186: xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1 httpng 187: }
188:
189: /*
1.2 httpng 190: * xmlAddDocEntity : register a new entity for this document.
1.1 httpng 191: */
1.13 daniel 192: void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
193: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.16 daniel 194: xmlEntitiesTablePtr table;
195:
196: table = (xmlEntitiesTablePtr) doc->entities;
197: if (table == NULL) {
198: table = xmlCreateEntitiesTable();
199: doc->entities = table;
1.2 httpng 200: }
1.16 daniel 201: xmlAddEntity(doc->entities, name, type, ExternalID, SystemID, content);
1.1 httpng 202: }
203:
204: /*
1.16 daniel 205: * xmlGetDtdEntity : do an entity lookup in the Dtd entity hash table and
1.15 daniel 206: * returns the corrsponding entity, if found, NULL otherwise.
1.1 httpng 207: */
1.16 daniel 208: xmlEntityPtr xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
1.2 httpng 209: int i;
210: xmlEntityPtr cur;
211: xmlEntitiesTablePtr table;
212:
1.15 daniel 213: if ((doc->dtd != NULL) && (doc->dtd->entities != NULL)) {
214: table = (xmlEntitiesTablePtr) doc->dtd->entities;
215: for (i = 0;i < table->nb_entities;i++) {
216: cur = &table->table[i];
217: if (!xmlStrcmp(cur->name, name)) return(cur);
218: }
219: }
1.7 veillard 220: return(NULL);
1.3 httpng 221: }
222:
223: /*
1.16 daniel 224: * xmlGetDocEntity : do an entity lookup in the document entity hash table and
225: * returns the corrsponding entity, otherwise a lookup is done
226: * in the predefined entities too.
1.14 daniel 227: */
1.16 daniel 228: xmlEntityPtr xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
1.14 daniel 229: int i;
1.16 daniel 230: xmlEntityPtr cur;
1.14 daniel 231: xmlEntitiesTablePtr table;
232:
1.16 daniel 233: if (doc->entities != NULL) {
234: table = (xmlEntitiesTablePtr) doc->entities;
235: for (i = 0;i < table->nb_entities;i++) {
236: cur = &table->table[i];
237: if (!xmlStrcmp(cur->name, name)) return(cur);
238: }
239: }
1.15 daniel 240: if (xmlPredefinedEntities == NULL)
241: xmlInitializePredefinedEntities();
1.16 daniel 242: table = xmlPredefinedEntities;
243: for (i = 0;i < table->nb_entities;i++) {
244: cur = &table->table[i];
245: if (!xmlStrcmp(cur->name, name)) return(cur);
1.14 daniel 246: }
247:
248: return(NULL);
1.1 httpng 249: }
250:
251: /*
1.2 httpng 252: * xmlEncodeEntities : do a global encoding of a string, replacing the
1.19 ! daniel 253: * predefined entities and non ASCII values with their
! 254: * entities and CharRef counterparts.
! 255: * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
! 256: * get erroneous.
1.1 httpng 257: */
1.2 httpng 258: CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
1.7 veillard 259: const CHAR *cur = input;
1.3 httpng 260: CHAR *out = buffer;
261:
1.19 ! daniel 262: if (input == NULL) return(NULL);
1.3 httpng 263: if (buffer == NULL) {
264: buffer_size = 1000;
265: buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
266: if (buffer == NULL) {
267: perror("malloc failed");
268: exit(1);
269: }
270: out = buffer;
271: }
1.6 veillard 272: while (*cur != '\0') {
273: if (out - buffer > buffer_size - 100) {
274: int index = out - buffer;
275:
276: growBuffer();
277: out = &buffer[index];
278: }
279:
280: /*
1.7 veillard 281: * By default one have to encode at least '<', '>', '"' and '&' !
1.6 veillard 282: */
283: if (*cur == '<') {
284: *out++ = '&';
285: *out++ = 'l';
286: *out++ = 't';
287: *out++ = ';';
1.7 veillard 288: } else if (*cur == '>') {
289: *out++ = '&';
290: *out++ = 'g';
291: *out++ = 't';
292: *out++ = ';';
1.6 veillard 293: } else if (*cur == '&') {
294: *out++ = '&';
295: *out++ = 'a';
296: *out++ = 'm';
297: *out++ = 'p';
1.7 veillard 298: *out++ = ';';
299: } else if (*cur == '"') {
300: *out++ = '&';
301: *out++ = 'q';
302: *out++ = 'u';
303: *out++ = 'o';
304: *out++ = 't';
305: *out++ = ';';
306: } else if (*cur == '\'') {
307: *out++ = '&';
308: *out++ = 'a';
309: *out++ = 'p';
310: *out++ = 'o';
311: *out++ = 's';
1.6 veillard 312: *out++ = ';';
1.19 ! daniel 313: #ifndef USE_UTF_8
! 314: } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
! 315: char buf[10], *ptr;
! 316: #ifdef HAVE_SNPRINTF
! 317: snprintf(buf, 9, "&#%d;", *cur);
! 318: #else
! 319: sprintf(buf, "&#%d;", *cur);
! 320: #endif
! 321: ptr = buf;
! 322: while (*ptr != 0) *out++ = *ptr++;
! 323: #endif
1.6 veillard 324: } else {
325: /*
326: * default case, just copy !
327: */
328: *out++ = *cur;
329: }
330: cur++;
331: }
332: *out++ = 0;
333: return(buffer);
1.2 httpng 334: }
335:
336: /*
337: * xmlCreateEntitiesTable : create and initialize an enmpty hash table
338: */
339: xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
340: xmlEntitiesTablePtr ret;
1.1 httpng 341:
1.2 httpng 342: ret = (xmlEntitiesTablePtr)
343: malloc(sizeof(xmlEntitiesTable));
1.1 httpng 344: if (ret == NULL) {
1.2 httpng 345: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
346: sizeof(xmlEntitiesTable));
347: return(NULL);
348: }
349: ret->max_entities = XML_MIN_ENTITIES_TABLE;
350: ret->nb_entities = 0;
351: ret->table = (xmlEntityPtr )
352: malloc(ret->max_entities * sizeof(xmlEntity));
353: if (ret == NULL) {
354: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
355: ret->max_entities * sizeof(xmlEntity));
356: free(ret);
1.1 httpng 357: return(NULL);
358: }
359: return(ret);
360: }
361:
362: /*
1.2 httpng 363: * xmlFreeEntitiesTable : clean up and free an entities hash table.
1.1 httpng 364: */
1.2 httpng 365: void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 366: int i;
367:
368: if (table == NULL) return;
369:
1.2 httpng 370: for (i = 0;i < table->nb_entities;i++) {
371: xmlFreeEntity(&table->table[i]);
1.1 httpng 372: }
1.2 httpng 373: free(table->table);
1.1 httpng 374: free(table);
375: }
376:
1.13 daniel 377: /*
378: * Dump the content of an entity table to the document output.
379: */
380: void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
1.14 daniel 381: int i;
382: xmlEntityPtr cur;
383:
384: if (table == NULL) return;
385:
386: for (i = 0;i < table->nb_entities;i++) {
387: cur = &table->table[i];
388: switch (cur->type) {
389: case XML_INTERNAL_GENERAL_ENTITY:
390: xmlBufferWriteChar("<!ENTITY ");
391: xmlBufferWriteCHAR(cur->name);
392: xmlBufferWriteChar(" \"");
393: xmlBufferWriteCHAR(cur->content);
394: xmlBufferWriteChar("\">\n");
395: break;
396: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
397: xmlBufferWriteChar("<!ENTITY ");
398: xmlBufferWriteCHAR(cur->name);
399: if (cur->ExternalID != NULL) {
400: xmlBufferWriteChar(" PUBLIC \"");
401: xmlBufferWriteCHAR(cur->ExternalID);
402: xmlBufferWriteChar("\" \"");
403: xmlBufferWriteCHAR(cur->SystemID);
404: xmlBufferWriteChar("\"");
405: } else {
406: xmlBufferWriteChar(" SYSTEM \"");
407: xmlBufferWriteCHAR(cur->SystemID);
408: xmlBufferWriteChar("\"");
409: }
410: xmlBufferWriteChar(">\n");
411: break;
412: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
413: xmlBufferWriteChar("<!ENTITY ");
414: xmlBufferWriteCHAR(cur->name);
415: if (cur->ExternalID != NULL) {
416: xmlBufferWriteChar(" PUBLIC \"");
417: xmlBufferWriteCHAR(cur->ExternalID);
418: xmlBufferWriteChar("\" \"");
419: xmlBufferWriteCHAR(cur->SystemID);
420: xmlBufferWriteChar("\"");
421: } else {
422: xmlBufferWriteChar(" SYSTEM \"");
423: xmlBufferWriteCHAR(cur->SystemID);
424: xmlBufferWriteChar("\"");
425: }
426: if (cur->content != NULL) { /* Should be true ! */
427: xmlBufferWriteChar(" NDATA ");
428: xmlBufferWriteCHAR(cur->content);
429: }
430: xmlBufferWriteChar(">\n");
431: break;
432: case XML_INTERNAL_PARAMETER_ENTITY:
433: xmlBufferWriteChar("<!ENTITY % ");
434: xmlBufferWriteCHAR(cur->name);
435: xmlBufferWriteChar(" \"");
436: xmlBufferWriteCHAR(cur->content);
437: xmlBufferWriteChar("\">\n");
438: break;
439: case XML_EXTERNAL_PARAMETER_ENTITY:
440: xmlBufferWriteChar("<!ENTITY % ");
441: xmlBufferWriteCHAR(cur->name);
442: if (cur->ExternalID != NULL) {
443: xmlBufferWriteChar(" PUBLIC \"");
444: xmlBufferWriteCHAR(cur->ExternalID);
445: xmlBufferWriteChar("\" \"");
446: xmlBufferWriteCHAR(cur->SystemID);
447: xmlBufferWriteChar("\"");
448: } else {
449: xmlBufferWriteChar(" SYSTEM \"");
450: xmlBufferWriteCHAR(cur->SystemID);
451: xmlBufferWriteChar("\"");
452: }
453: xmlBufferWriteChar(">\n");
454: break;
455: default:
456: fprintf(stderr,
457: "xmlDumpEntitiesTable: internal: unknown type %d\n",
458: cur->type);
459: }
460: }
1.13 daniel 461: }
Webmaster