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