Annotation of XML/entities.c, revision 1.13
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.13 ! daniel 6: * $Id: entities.c,v 1.12 1998/08/06 02:23:28 daniel Exp $
1.1 httpng 7: */
8:
9: #include <stdio.h>
10: #include <malloc.h>
1.10 daniel 11: #include <string.h>
1.1 httpng 12: #include "entities.h"
13:
14: /*
1.3 httpng 15: * A buffer used for converting entities to their equivalent and back.
16: */
1.6 veillard 17: static CHAR *buffer = NULL;
1.3 httpng 18: static int buffer_size = 0;
19:
20: void growBuffer(void) {
21: buffer_size *= 2;
22: buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
23: if (buffer == NULL) {
24: perror("realloc failed");
25: exit(1);
26: }
27: }
28:
29: /*
1.2 httpng 30: * xmlFreeEntity : clean-up an entity record.
1.1 httpng 31: */
32:
1.2 httpng 33: void xmlFreeEntity(xmlEntityPtr entity) {
34: if (entity == NULL) return;
35:
1.11 daniel 36: if (entity->content != NULL) free(entity->content);
37: entity->content = NULL;
38: if (entity->name != NULL)
39: free((char *) entity->name);
1.2 httpng 40: }
1.1 httpng 41:
42: /*
1.2 httpng 43: * xmlAddDocEntity : register a new entity for an entities table.
1.13 ! daniel 44: *
! 45: * TODO !!! We should check here that the combination of type
! 46: * ExternalID and SystemID is valid.
1.1 httpng 47: */
1.13 ! daniel 48: static void xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
! 49: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2 httpng 50: int i;
51: xmlEntityPtr cur;
1.1 httpng 52:
1.2 httpng 53: for (i = 0;i < table->nb_entities;i++) {
54: cur = &table->table[i];
1.11 daniel 55: if (!xmlStrcmp(cur->name, name)) {
1.13 ! daniel 56: /*
! 57: * The entity is already defined in this Dtd, the spec says to NOT
! 58: * override it ... Is it worth a Warning ??? !!!
! 59: */
! 60: return;
1.7 veillard 61: }
1.2 httpng 62: }
63: if (table->nb_entities >= table->max_entities) {
64: /*
65: * need more elements.
66: */
67: table->max_entities *= 2;
68: table->table = (xmlEntityPtr)
69: realloc(table->table, table->max_entities * sizeof(xmlEntity));
70: if (table->table) {
71: perror("realloc failed");
72: exit(1);
73: }
74: }
75: cur = &table->table[table->nb_entities];
1.11 daniel 76: cur->name = xmlStrdup(name);
1.13 ! daniel 77: cur->type = type;
! 78: if (ExternalID != NULL)
! 79: cur->ExternalID = xmlStrdup(ExternalID);
! 80: if (SystemID != NULL)
! 81: cur->ExternalID = xmlStrdup(SystemID);
! 82: if (content != NULL)
! 83: cur->content = xmlStrdup(content);
1.2 httpng 84: table->nb_entities++;
85: }
1.1 httpng 86:
87:
88: /*
1.12 daniel 89: * xmlAddDtdEntity : register a new entity for this DTD.
1.1 httpng 90: */
1.13 ! daniel 91: void xmlAddDtdEntity(xmlDtdPtr dtd, const CHAR *name, int type,
! 92: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2 httpng 93: xmlEntitiesTablePtr table;
1.1 httpng 94:
1.2 httpng 95: table = (xmlEntitiesTablePtr) dtd->entities;
96: if (table == NULL) {
97: table = xmlCreateEntitiesTable();
98: dtd->entities = table;
1.1 httpng 99: }
1.13 ! daniel 100: xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1 httpng 101: }
102:
103: /*
1.2 httpng 104: * xmlAddDocEntity : register a new entity for this document.
1.1 httpng 105: */
1.13 ! daniel 106: void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
! 107: const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.12 daniel 108: if (doc->dtd == NULL) {
109: fprintf(stderr, "xmlAddDocEntity: document without DTD\n");
110: return;
1.2 httpng 111: }
1.13 ! daniel 112: xmlAddDtdEntity(doc->dtd, name, type, ExternalID, SystemID, content);
1.1 httpng 113: }
114:
115: /*
116: * xmlGetEntity : do an entity lookup in the hash table and
1.7 veillard 117: * returns the corrsponding CHAR *, if found, zero otherwise.
1.1 httpng 118: */
1.11 daniel 119: CHAR *xmlGetEntity(xmlDocPtr doc, const CHAR *name) {
1.2 httpng 120: int i;
121: xmlEntityPtr cur;
122: xmlEntitiesTablePtr table;
123:
1.12 daniel 124: if (doc->dtd == NULL) return(NULL);
125: if (doc->dtd->entities == NULL) return(NULL);
126: table = (xmlEntitiesTablePtr) doc->dtd->entities;
1.2 httpng 127: for (i = 0;i < table->nb_entities;i++) {
128: cur = &table->table[i];
1.11 daniel 129: if (!xmlStrcmp(cur->name, name)) return(cur->content);
1.2 httpng 130: }
1.12 daniel 131: /* TODO !!! recurse for embedded DTD if available */
1.7 veillard 132: return(NULL);
1.1 httpng 133: }
134:
135: /*
1.6 veillard 136: * xmlReadEntities : read an entity.
1.12 daniel 137: * TODO !!!! Complete nonsense, rewite !!!
1.1 httpng 138: */
1.7 veillard 139: const CHAR *xmlReadEntity(xmlDocPtr doc, const CHAR **input) {
140: static CHAR *entity = NULL;
141: static int entity_size = 100;
142: const CHAR *cur = *input;
143:
144: if (entity == NULL) {
145: entity = (CHAR *) malloc(entity_size * sizeof(CHAR));
146: if (entity == NULL) {
147: fprintf(stderr, "xmlReadEntity : cannot allocate %d bytes\n",
148: entity_size * sizeof(CHAR));
149: return(NULL);
150: }
151: }
152: if (*cur == '&') {
153: cur++;
154: if (*cur == '#') {
155: /* TODO !!!!
156: fprintf(stderr, "Character reference not yet implemented\n"); */
1.3 httpng 157: } else {
1.7 veillard 158: /* TODO !!!!
159: fprintf(stderr, "Entity search not yet implemented\n"); */
1.3 httpng 160: }
161: }
1.7 veillard 162:
163: /*
164: * The few predefined entities.
165: */
166: if ((cur[0] == 'a') && (cur[1] == 'm') && (cur[2] == 'p') &&
167: (cur[3] == ';')) {
1.13 ! daniel 168: entity[0] = '&';
1.7 veillard 169: entity[1] = 0;
1.8 veillard 170: cur += 3;
1.7 veillard 171: *input = cur;
172: return(entity);
173: } else if ((cur[0] == 'q') && (cur[1] == 'u') && (cur[2] == 'o') &&
174: (cur[3] == 't') && (cur[4] == ';')) {
175: entity[0] = '"';
176: entity[1] = 0;
177: cur += 4;
178: *input = cur;
179: return(entity);
180: } else if ((cur[0] == 'a') && (cur[1] == 'p') && (cur[2] == 'o') &&
181: (cur[3] == 's') && (cur[4] == ';')) {
182: entity[0] = '\'';
183: entity[1] = 0;
184: cur += 4;
185: *input = cur;
186: return(entity);
187: } else if ((cur[0] == 'l') && (cur[1] == 't') && (cur[2] == ';')) {
188: entity[0] = '<';
189: entity[1] = 0;
1.8 veillard 190: cur += 2;
1.7 veillard 191: *input = cur;
192: return(entity);
193: } else if ((cur[0] == 'g') && (cur[1] == 't') && (cur[2] == ';')) {
194: entity[0] = '>';
195: entity[1] = 0;
1.8 veillard 196: cur += 2;
1.7 veillard 197: *input = cur;
198: return(entity);
1.13 ! daniel 199: } else {
! 200: entity[0] = '&';
! 201: entity[1] = 0;
! 202: return(entity);
1.7 veillard 203: }
1.13 ! daniel 204:
1.7 veillard 205:
206: return(NULL);
1.3 httpng 207: }
208:
209: /*
1.7 veillard 210: * xmlDecodeEntities : do a global entities lookup on a input string
1.3 httpng 211: * and returns a duplicate after the entities substitution.
1.12 daniel 212: * TODO !!!! rewite !!!
1.3 httpng 213: */
1.7 veillard 214: CHAR *xmlDecodeEntities(xmlDocPtr doc, const CHAR *input, int len) {
215: const CHAR *cur = input;
1.3 httpng 216: CHAR *out = buffer;
217: int i;
218:
219: if (buffer == NULL) {
220: buffer_size = 1000;
221: buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
222: if (buffer == NULL) {
223: perror("malloc failed");
224: exit(1);
225: }
226: out = buffer;
227: }
1.7 veillard 228: for (i = 0;(*cur != 0) && (cur - input < len);cur++) {
1.3 httpng 229: if (*cur == '&') {
1.7 veillard 230: const CHAR *entity = xmlReadEntity(doc, &cur);
1.3 httpng 231: if (entity != NULL)
232: while (*entity != 0) {
233: *out++ = *entity++;
234: i++;
1.6 veillard 235: if (i + 10 > buffer_size) {
236: int index = out - buffer;
237:
238: growBuffer();
239: out = &buffer[index];
240: }
1.3 httpng 241: }
242: } else if (*cur == '%') {
1.7 veillard 243: /* TODO !!!!!
244: fprintf(stderr, " \n"); */
1.3 httpng 245: } else {
1.7 veillard 246: *out++ = *cur;
1.3 httpng 247: i++;
248: }
249:
1.6 veillard 250: if (i + 10 > buffer_size) {
251: int index = out - buffer;
252:
253: growBuffer();
254: out = &buffer[index];
255: }
1.3 httpng 256: }
1.7 veillard 257: *out++ = 0;
1.3 httpng 258: return(buffer);
1.1 httpng 259: }
260:
261: /*
1.2 httpng 262: * xmlEncodeEntities : do a global encoding of a string, replacing the
1.11 daniel 263: * basic content with their entities form.
1.12 daniel 264: * TODO !!!! rewite !!!
1.1 httpng 265: */
1.2 httpng 266: CHAR *xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
1.7 veillard 267: const CHAR *cur = input;
1.3 httpng 268: CHAR *out = buffer;
269:
270: if (buffer == NULL) {
271: buffer_size = 1000;
272: buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
273: if (buffer == NULL) {
274: perror("malloc failed");
275: exit(1);
276: }
277: out = buffer;
278: }
1.6 veillard 279: while (*cur != '\0') {
280: if (out - buffer > buffer_size - 100) {
281: int index = out - buffer;
282:
283: growBuffer();
284: out = &buffer[index];
285: }
286:
287: /*
1.7 veillard 288: * By default one have to encode at least '<', '>', '"' and '&' !
289: * One could try a better encoding using the entities defined and
290: * used as a compression code !!!.
1.6 veillard 291: */
292: if (*cur == '<') {
293: *out++ = '&';
294: *out++ = 'l';
295: *out++ = 't';
296: *out++ = ';';
1.7 veillard 297: } else if (*cur == '>') {
298: *out++ = '&';
299: *out++ = 'g';
300: *out++ = 't';
301: *out++ = ';';
1.6 veillard 302: } else if (*cur == '&') {
303: *out++ = '&';
304: *out++ = 'a';
305: *out++ = 'm';
306: *out++ = 'p';
1.7 veillard 307: *out++ = ';';
308: } else if (*cur == '"') {
309: *out++ = '&';
310: *out++ = 'q';
311: *out++ = 'u';
312: *out++ = 'o';
313: *out++ = 't';
314: *out++ = ';';
315: } else if (*cur == '\'') {
316: *out++ = '&';
317: *out++ = 'a';
318: *out++ = 'p';
319: *out++ = 'o';
320: *out++ = 's';
1.6 veillard 321: *out++ = ';';
322: } else {
323: /*
324: * default case, just copy !
325: */
326: *out++ = *cur;
327: }
328: cur++;
329: }
330: *out++ = 0;
331: return(buffer);
1.2 httpng 332: }
333:
334: /*
335: * xmlCreateEntitiesTable : create and initialize an enmpty hash table
336: */
337: xmlEntitiesTablePtr xmlCreateEntitiesTable(void) {
338: xmlEntitiesTablePtr ret;
1.1 httpng 339:
1.2 httpng 340: ret = (xmlEntitiesTablePtr)
341: malloc(sizeof(xmlEntitiesTable));
1.1 httpng 342: if (ret == NULL) {
1.2 httpng 343: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
344: sizeof(xmlEntitiesTable));
345: return(NULL);
346: }
347: ret->max_entities = XML_MIN_ENTITIES_TABLE;
348: ret->nb_entities = 0;
349: ret->table = (xmlEntityPtr )
350: malloc(ret->max_entities * sizeof(xmlEntity));
351: if (ret == NULL) {
352: fprintf(stderr, "xmlCreateEntitiesTable : malloc(%d) failed\n",
353: ret->max_entities * sizeof(xmlEntity));
354: free(ret);
1.1 httpng 355: return(NULL);
356: }
357: return(ret);
358: }
359:
360: /*
1.2 httpng 361: * xmlFreeEntitiesTable : clean up and free an entities hash table.
1.1 httpng 362: */
1.2 httpng 363: void xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 364: int i;
365:
366: if (table == NULL) return;
367:
1.2 httpng 368: for (i = 0;i < table->nb_entities;i++) {
369: xmlFreeEntity(&table->table[i]);
1.1 httpng 370: }
1.2 httpng 371: free(table->table);
1.1 httpng 372: free(table);
373: }
374:
1.13 ! daniel 375: /*
! 376: * Dump the content of an entity table to the document output.
! 377: */
! 378: void xmlDumpEntitiesTable(xmlEntitiesTablePtr table) {
! 379: }
Webmaster