Annotation of XML/entities.c, revision 1.17
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.17 ! daniel 6: * $Id: entities.c,v 1.2 1998/10/01 20:51:12 alves 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],
141: XML_INTERNAL_GENERAL_ENTITY, NULL, NULL,
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.11 daniel 253: * basic content with their entities form.
1.12 daniel 254: * TODO !!!! rewite !!!
1.1 httpng 255: */
1.2 httpng 256: CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
1.7 veillard 257: const CHAR *cur = input;
1.3 httpng 258: CHAR *out = buffer;
259:
260: if (buffer == NULL) {
261: buffer_size = 1000;
262: buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
263: if (buffer == NULL) {
264: perror("malloc failed");
265: exit(1);
266: }
267: out = buffer;
268: }
1.6 veillard 269: while (*cur != '\0') {
270: if (out - buffer > buffer_size - 100) {
271: int index = out - buffer;
272:
273: growBuffer();
274: out = &buffer[index];
275: }
276:
277: /*
1.7 veillard 278: * By default one have to encode at least '<', '>', '"' and '&' !
279: * One could try a better encoding using the entities defined and
280: * used as a compression code !!!.
1.6 veillard 281: */
282: if (*cur == '<') {
283: *out++ = '&';
284: *out++ = 'l';
285: *out++ = 't';
286: *out++ = ';';
1.7 veillard 287: } else if (*cur == '>') {
288: *out++ = '&';
289: *out++ = 'g';
290: *out++ = 't';
291: *out++ = ';';
1.6 veillard 292: } else if (*cur == '&') {
293: *out++ = '&';
294: *out++ = 'a';
295: *out++ = 'm';
296: *out++ = 'p';
1.7 veillard 297: *out++ = ';';
298: } else if (*cur == '"') {
299: *out++ = '&';
300: *out++ = 'q';
301: *out++ = 'u';
302: *out++ = 'o';
303: *out++ = 't';
304: *out++ = ';';
305: } else if (*cur == '\'') {
306: *out++ = '&';
307: *out++ = 'a';
308: *out++ = 'p';
309: *out++ = 'o';
310: *out++ = 's';
1.6 veillard 311: *out++ = ';';
312: } else {
313: /*
314: * default case, just copy !
315: */
316: *out++ = *cur;
317: }
318: cur++;
319: }
320: *out++ = 0;
321: return(buffer);
1.2 httpng 322: }
323:
324: /*
325: * xmlCreateEntitiesTable : create and initialize an enmpty hash table
326: */
327: xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
328: xmlEntitiesTablePtr ret;
1.1 httpng 329:
1.2 httpng 330: ret = (xmlEntitiesTablePtr)
331: malloc(sizeof(xmlEntitiesTable));
1.1 httpng 332: if (ret == NULL) {
1.2 httpng 333: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
334: sizeof(xmlEntitiesTable));
335: return(NULL);
336: }
337: ret->max_entities = XML_MIN_ENTITIES_TABLE;
338: ret->nb_entities = 0;
339: ret->table = (xmlEntityPtr )
340: malloc(ret->max_entities * sizeof(xmlEntity));
341: if (ret == NULL) {
342: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
343: ret->max_entities * sizeof(xmlEntity));
344: free(ret);
1.1 httpng 345: return(NULL);
346: }
347: return(ret);
348: }
349:
350: /*
1.2 httpng 351: * xmlFreeEntitiesTable : clean up and free an entities hash table.
1.1 httpng 352: */
1.2 httpng 353: void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 354: int i;
355:
356: if (table == NULL) return;
357:
1.2 httpng 358: for (i = 0;i < table->nb_entities;i++) {
359: xmlFreeEntity(&table->table[i]);
1.1 httpng 360: }
1.2 httpng 361: free(table->table);
1.1 httpng 362: free(table);
363: }
364:
1.13 daniel 365: /*
366: * Dump the content of an entity table to the document output.
367: */
368: void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
1.14 daniel 369: int i;
370: xmlEntityPtr cur;
371:
372: if (table == NULL) return;
373:
374: for (i = 0;i < table->nb_entities;i++) {
375: cur = &table->table[i];
376: switch (cur->type) {
377: case XML_INTERNAL_GENERAL_ENTITY:
378: xmlBufferWriteChar("<!ENTITY ");
379: xmlBufferWriteCHAR(cur->name);
380: xmlBufferWriteChar(" \"");
381: xmlBufferWriteCHAR(cur->content);
382: xmlBufferWriteChar("\">\n");
383: break;
384: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
385: xmlBufferWriteChar("<!ENTITY ");
386: xmlBufferWriteCHAR(cur->name);
387: if (cur->ExternalID != NULL) {
388: xmlBufferWriteChar(" PUBLIC \"");
389: xmlBufferWriteCHAR(cur->ExternalID);
390: xmlBufferWriteChar("\" \"");
391: xmlBufferWriteCHAR(cur->SystemID);
392: xmlBufferWriteChar("\"");
393: } else {
394: xmlBufferWriteChar(" SYSTEM \"");
395: xmlBufferWriteCHAR(cur->SystemID);
396: xmlBufferWriteChar("\"");
397: }
398: xmlBufferWriteChar(">\n");
399: break;
400: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
401: xmlBufferWriteChar("<!ENTITY ");
402: xmlBufferWriteCHAR(cur->name);
403: if (cur->ExternalID != NULL) {
404: xmlBufferWriteChar(" PUBLIC \"");
405: xmlBufferWriteCHAR(cur->ExternalID);
406: xmlBufferWriteChar("\" \"");
407: xmlBufferWriteCHAR(cur->SystemID);
408: xmlBufferWriteChar("\"");
409: } else {
410: xmlBufferWriteChar(" SYSTEM \"");
411: xmlBufferWriteCHAR(cur->SystemID);
412: xmlBufferWriteChar("\"");
413: }
414: if (cur->content != NULL) { /* Should be true ! */
415: xmlBufferWriteChar(" NDATA ");
416: xmlBufferWriteCHAR(cur->content);
417: }
418: xmlBufferWriteChar(">\n");
419: break;
420: case XML_INTERNAL_PARAMETER_ENTITY:
421: xmlBufferWriteChar("<!ENTITY % ");
422: xmlBufferWriteCHAR(cur->name);
423: xmlBufferWriteChar(" \"");
424: xmlBufferWriteCHAR(cur->content);
425: xmlBufferWriteChar("\">\n");
426: break;
427: case XML_EXTERNAL_PARAMETER_ENTITY:
428: xmlBufferWriteChar("<!ENTITY % ");
429: xmlBufferWriteCHAR(cur->name);
430: if (cur->ExternalID != NULL) {
431: xmlBufferWriteChar(" PUBLIC \"");
432: xmlBufferWriteCHAR(cur->ExternalID);
433: xmlBufferWriteChar("\" \"");
434: xmlBufferWriteCHAR(cur->SystemID);
435: xmlBufferWriteChar("\"");
436: } else {
437: xmlBufferWriteChar(" SYSTEM \"");
438: xmlBufferWriteCHAR(cur->SystemID);
439: xmlBufferWriteChar("\"");
440: }
441: xmlBufferWriteChar(">\n");
442: break;
443: default:
444: fprintf(stderr,
445: "xmlDumpEntitiesTable: internal: unknown type %d\n",
446: cur->type);
447: }
448: }
1.13 daniel 449: }
Webmaster