Annotation of XML/entities.c, revision 1.20
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.20 ! daniel 6: * $Id: entities.c,v 1.19 1998/11/11 20:07:54 daniel 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.20 ! daniel 324: } else if ((*cur >= 1) && (*cur < 0x20) &&
! 325: (*cur != '\n') && (*cur != '\r') && (*cur != '\t')) {
! 326: char buf[10], *ptr;
! 327:
! 328: #ifdef HAVE_SNPRINTF
! 329: snprintf(buf, 9, "&#%d;", *cur);
! 330: #else
! 331: sprintf(buf, "&#%d;", *cur);
! 332: #endif
! 333: ptr = buf;
! 334: while (*ptr != 0) *out++ = *ptr++;
1.6 veillard 335: } else {
336: /*
337: * default case, just copy !
338: */
339: *out++ = *cur;
340: }
341: cur++;
342: }
343: *out++ = 0;
344: return(buffer);
1.2 httpng 345: }
346:
347: /*
348: * xmlCreateEntitiesTable : create and initialize an enmpty hash table
349: */
350: xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
351: xmlEntitiesTablePtr ret;
1.1 httpng 352:
1.2 httpng 353: ret = (xmlEntitiesTablePtr)
354: malloc(sizeof(xmlEntitiesTable));
1.1 httpng 355: if (ret == NULL) {
1.2 httpng 356: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
357: sizeof(xmlEntitiesTable));
358: return(NULL);
359: }
360: ret->max_entities = XML_MIN_ENTITIES_TABLE;
361: ret->nb_entities = 0;
362: ret->table = (xmlEntityPtr )
363: malloc(ret->max_entities * sizeof(xmlEntity));
364: if (ret == NULL) {
365: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
366: ret->max_entities * sizeof(xmlEntity));
367: free(ret);
1.1 httpng 368: return(NULL);
369: }
370: return(ret);
371: }
372:
373: /*
1.2 httpng 374: * xmlFreeEntitiesTable : clean up and free an entities hash table.
1.1 httpng 375: */
1.2 httpng 376: void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 377: int i;
378:
379: if (table == NULL) return;
380:
1.2 httpng 381: for (i = 0;i < table->nb_entities;i++) {
382: xmlFreeEntity(&table->table[i]);
1.1 httpng 383: }
1.2 httpng 384: free(table->table);
1.1 httpng 385: free(table);
386: }
387:
1.13 daniel 388: /*
389: * Dump the content of an entity table to the document output.
390: */
391: void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
1.14 daniel 392: int i;
393: xmlEntityPtr cur;
394:
395: if (table == NULL) return;
396:
397: for (i = 0;i < table->nb_entities;i++) {
398: cur = &table->table[i];
399: switch (cur->type) {
400: case XML_INTERNAL_GENERAL_ENTITY:
401: xmlBufferWriteChar("<!ENTITY ");
402: xmlBufferWriteCHAR(cur->name);
403: xmlBufferWriteChar(" \"");
404: xmlBufferWriteCHAR(cur->content);
405: xmlBufferWriteChar("\">\n");
406: break;
407: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
408: xmlBufferWriteChar("<!ENTITY ");
409: xmlBufferWriteCHAR(cur->name);
410: if (cur->ExternalID != NULL) {
411: xmlBufferWriteChar(" PUBLIC \"");
412: xmlBufferWriteCHAR(cur->ExternalID);
413: xmlBufferWriteChar("\" \"");
414: xmlBufferWriteCHAR(cur->SystemID);
415: xmlBufferWriteChar("\"");
416: } else {
417: xmlBufferWriteChar(" SYSTEM \"");
418: xmlBufferWriteCHAR(cur->SystemID);
419: xmlBufferWriteChar("\"");
420: }
421: xmlBufferWriteChar(">\n");
422: break;
423: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
424: xmlBufferWriteChar("<!ENTITY ");
425: xmlBufferWriteCHAR(cur->name);
426: if (cur->ExternalID != NULL) {
427: xmlBufferWriteChar(" PUBLIC \"");
428: xmlBufferWriteCHAR(cur->ExternalID);
429: xmlBufferWriteChar("\" \"");
430: xmlBufferWriteCHAR(cur->SystemID);
431: xmlBufferWriteChar("\"");
432: } else {
433: xmlBufferWriteChar(" SYSTEM \"");
434: xmlBufferWriteCHAR(cur->SystemID);
435: xmlBufferWriteChar("\"");
436: }
437: if (cur->content != NULL) { /* Should be true ! */
438: xmlBufferWriteChar(" NDATA ");
439: xmlBufferWriteCHAR(cur->content);
440: }
441: xmlBufferWriteChar(">\n");
442: break;
443: case XML_INTERNAL_PARAMETER_ENTITY:
444: xmlBufferWriteChar("<!ENTITY % ");
445: xmlBufferWriteCHAR(cur->name);
446: xmlBufferWriteChar(" \"");
447: xmlBufferWriteCHAR(cur->content);
448: xmlBufferWriteChar("\">\n");
449: break;
450: case XML_EXTERNAL_PARAMETER_ENTITY:
451: xmlBufferWriteChar("<!ENTITY % ");
452: xmlBufferWriteCHAR(cur->name);
453: if (cur->ExternalID != NULL) {
454: xmlBufferWriteChar(" PUBLIC \"");
455: xmlBufferWriteCHAR(cur->ExternalID);
456: xmlBufferWriteChar("\" \"");
457: xmlBufferWriteCHAR(cur->SystemID);
458: xmlBufferWriteChar("\"");
459: } else {
460: xmlBufferWriteChar(" SYSTEM \"");
461: xmlBufferWriteCHAR(cur->SystemID);
462: xmlBufferWriteChar("\"");
463: }
464: xmlBufferWriteChar(">\n");
465: break;
466: default:
467: fprintf(stderr,
468: "xmlDumpEntitiesTable: internal: unknown type %d\n",
469: cur->type);
470: }
471: }
1.13 daniel 472: }
Webmaster