Annotation of XML/entities.c, revision 1.19

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

Webmaster