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