Annotation of XML/entities.c, revision 1.30

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.23      daniel      6:  * Daniel.Veillard@w3.org
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.2       httpng     33:  * xmlFreeEntity : clean-up an entity record.
1.1       httpng     34:  */
1.2       httpng     35: void xmlFreeEntity(xmlEntityPtr entity) {
                     36:     if (entity == NULL) return;
                     37: 
1.11      daniel     38:     if (entity->name != NULL)
                     39:        free((char *) entity->name);
1.14      daniel     40:     if (entity->ExternalID != NULL)
                     41:         free((char *) entity->ExternalID);
                     42:     if (entity->SystemID != NULL)
                     43:         free((char *) entity->SystemID);
                     44:     if (entity->content != NULL)
                     45:         free((char *) entity->content);
1.27      daniel     46:     if (entity->orig != NULL)
                     47:         free((char *) entity->orig);
1.14      daniel     48:     memset(entity, -1, sizeof(xmlEntity));
1.2       httpng     49: }
1.1       httpng     50: 
                     51: /*
1.22      daniel     52:  * xmlAddEntity : register a new entity for an entities table.
1.13      daniel     53:  *
                     54:  * TODO !!! We should check here that the combination of type
                     55:  *          ExternalID and SystemID is valid.
1.1       httpng     56:  */
1.22      daniel     57: static void
                     58: xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
1.13      daniel     59:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2       httpng     60:     int i;
                     61:     xmlEntityPtr cur;
1.14      daniel     62:     int len;
1.1       httpng     63: 
1.2       httpng     64:     for (i = 0;i < table->nb_entities;i++) {
                     65:         cur = &table->table[i];
1.11      daniel     66:        if (!xmlStrcmp(cur->name, name)) {
1.13      daniel     67:            /*
                     68:             * The entity is already defined in this Dtd, the spec says to NOT
                     69:             * override it ... Is it worth a Warning ??? !!!
                     70:             */
1.30    ! daniel     71:            if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
        !            72:                 (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
        !            73:                ((cur->type == XML_INTERNAL_PARAMETER_ENTITY) ||
        !            74:                 (cur->type == XML_EXTERNAL_PARAMETER_ENTITY)))
        !            75:                return;
        !            76:            else
        !            77:            if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
        !            78:                 (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
        !            79:                ((cur->type != XML_INTERNAL_PARAMETER_ENTITY) &&
        !            80:                 (cur->type != XML_EXTERNAL_PARAMETER_ENTITY)))
        !            81:                return;
1.7       veillard   82:        }
1.2       httpng     83:     }
                     84:     if (table->nb_entities >= table->max_entities) {
                     85:         /*
                     86:         * need more elements.
                     87:         */
                     88:        table->max_entities *= 2;
                     89:        table->table = (xmlEntityPtr) 
                     90:            realloc(table->table, table->max_entities * sizeof(xmlEntity));
1.29      daniel     91:        if (table->table == NULL) {
1.2       httpng     92:            perror("realloc failed");
1.29      daniel     93:            return;
1.2       httpng     94:        }
                     95:     }
                     96:     cur = &table->table[table->nb_entities];
1.11      daniel     97:     cur->name = xmlStrdup(name);
1.14      daniel     98:     for (len = 0;name[0] != 0;name++)len++;
                     99:     cur->len = len;
1.13      daniel    100:     cur->type = type;
                    101:     if (ExternalID != NULL)
                    102:        cur->ExternalID = xmlStrdup(ExternalID);
1.14      daniel    103:     else
                    104:         cur->ExternalID = NULL;
1.13      daniel    105:     if (SystemID != NULL)
1.14      daniel    106:        cur->SystemID = xmlStrdup(SystemID);
                    107:     else
                    108:         cur->SystemID = NULL;
1.13      daniel    109:     if (content != NULL)
                    110:        cur->content = xmlStrdup(content);
1.14      daniel    111:     else
                    112:         cur->content = NULL;
1.27      daniel    113:     cur->orig = NULL;
1.2       httpng    114:     table->nb_entities++;
                    115: }
1.1       httpng    116: 
1.22      daniel    117: /**
                    118:  * xmlInitializePredefinedEntities:
                    119:  *
                    120:  * Set up the predefined entities.
1.15      daniel    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:  *
1.24      daniel    152:  * Returns NULL if not, othervise the entity
1.17      daniel    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.22      daniel    168: /**
                    169:  * xmlAddDtdEntity:
                    170:  * @doc:  the document
                    171:  * @name:  the entity name
                    172:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    173:  * @ExternalID:  the entity external ID if available
                    174:  * @SystemID:  the entity system ID if available
                    175:  * @content:  the entity content
                    176:  *
                    177:  * Register a new entity for this document DTD.
1.1       httpng    178:  */
1.22      daniel    179: void
                    180: xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
1.13      daniel    181:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2       httpng    182:     xmlEntitiesTablePtr table;
1.1       httpng    183: 
1.22      daniel    184:     if (doc->extSubset == NULL) {
                    185:         fprintf(stderr,
                    186:                "xmlAddDtdEntity: document without external subset !\n");
1.16      daniel    187:        return;
                    188:     }
1.22      daniel    189:     table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.2       httpng    190:     if (table == NULL) {
                    191:         table = xmlCreateEntitiesTable();
1.22      daniel    192:        doc->extSubset->entities = table;
1.1       httpng    193:     }
1.13      daniel    194:     xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1       httpng    195: }
                    196: 
1.22      daniel    197: /**
                    198:  * xmlAddDocEntity:
                    199:  * @doc:  the document
                    200:  * @name:  the entity name
                    201:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    202:  * @ExternalID:  the entity external ID if available
                    203:  * @SystemID:  the entity system ID if available
                    204:  * @content:  the entity content
                    205:  *
                    206:  * Register a new entity for this document.
1.1       httpng    207:  */
1.22      daniel    208: void
                    209: xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
1.13      daniel    210:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.16      daniel    211:     xmlEntitiesTablePtr table;
                    212: 
1.22      daniel    213:     if (doc == NULL) {
                    214:         fprintf(stderr,
                    215:                "xmlAddDocEntity: document is NULL !\n");
                    216:        return;
                    217:     }
                    218:     if (doc->intSubset == NULL) {
                    219:         fprintf(stderr,
                    220:                "xmlAddDtdEntity: document without internal subset !\n");
                    221:        return;
                    222:     }
                    223:     table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    224:     if (table == NULL) {
                    225:         table = xmlCreateEntitiesTable();
1.22      daniel    226:        doc->intSubset->entities = table;
1.2       httpng    227:     }
1.22      daniel    228:     xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1       httpng    229: }
                    230: 
1.22      daniel    231: /**
1.30    ! daniel    232:  * xmlGetParameterEntity:
        !           233:  * @doc:  the document referencing the entity
        !           234:  * @name:  the entity name
        !           235:  *
        !           236:  * Do an entity lookup in the internal and external subsets and
        !           237:  * returns the corresponding parameter entity, if found.
        !           238:  * 
        !           239:  * Returns A pointer to the entity structure or NULL if not found.
        !           240:  */
        !           241: xmlEntityPtr
        !           242: xmlGetParameterEntity(xmlDocPtr doc, const CHAR *name) {
        !           243:     int i;
        !           244:     xmlEntityPtr cur;
        !           245:     xmlEntitiesTablePtr table;
        !           246: 
        !           247:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
        !           248:        table = (xmlEntitiesTablePtr) doc->intSubset->entities;
        !           249:        for (i = 0;i < table->nb_entities;i++) {
        !           250:            cur = &table->table[i];
        !           251:            if (((cur->type ==  XML_INTERNAL_PARAMETER_ENTITY) ||
        !           252:                 (cur->type ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
        !           253:                (!xmlStrcmp(cur->name, name))) return(cur);
        !           254:        }
        !           255:     }
        !           256:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
        !           257:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
        !           258:        for (i = 0;i < table->nb_entities;i++) {
        !           259:            cur = &table->table[i];
        !           260:            if (((cur->type ==  XML_INTERNAL_PARAMETER_ENTITY) ||
        !           261:                 (cur->type ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
        !           262:                (!xmlStrcmp(cur->name, name))) return(cur);
        !           263:        }
        !           264:     }
        !           265:     return(NULL);
        !           266: }
        !           267: 
        !           268: /**
1.22      daniel    269:  * xmlGetDtdEntity:
                    270:  * @doc:  the document referencing the entity
                    271:  * @name:  the entity name
                    272:  *
                    273:  * Do an entity lookup in the Dtd entity hash table and
                    274:  * returns the corresponding entity, if found.
                    275:  * 
1.24      daniel    276:  * Returns A pointer to the entity structure or NULL if not found.
1.1       httpng    277:  */
1.22      daniel    278: xmlEntityPtr
                    279: xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
1.2       httpng    280:     int i;
                    281:     xmlEntityPtr cur;
                    282:     xmlEntitiesTablePtr table;
                    283: 
1.22      daniel    284:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    285:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.15      daniel    286:        for (i = 0;i < table->nb_entities;i++) {
                    287:            cur = &table->table[i];
1.30    ! daniel    288:            if ((cur->type !=  XML_INTERNAL_PARAMETER_ENTITY) &&
        !           289:                (cur->type !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
        !           290:                (!xmlStrcmp(cur->name, name))) return(cur);
1.15      daniel    291:        }
                    292:     }
1.7       veillard  293:     return(NULL);
1.3       httpng    294: }
                    295: 
1.22      daniel    296: /**
                    297:  * xmlGetDocEntity:
                    298:  * @doc:  the document referencing the entity
                    299:  * @name:  the entity name
                    300:  *
                    301:  * Do an entity lookup in the document entity hash table and
                    302:  * returns the corrsponding entity, otherwise a lookup is done
                    303:  * in the predefined entities too.
                    304:  * 
1.24      daniel    305:  * Returns A pointer to the entity structure or NULL if not found.
1.14      daniel    306:  */
1.22      daniel    307: xmlEntityPtr
                    308: xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
1.14      daniel    309:     int i;
1.16      daniel    310:     xmlEntityPtr cur;
1.14      daniel    311:     xmlEntitiesTablePtr table;
                    312: 
1.22      daniel    313:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    314:        table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    315:        for (i = 0;i < table->nb_entities;i++) {
                    316:            cur = &table->table[i];
1.30    ! daniel    317:            if ((cur->type !=  XML_INTERNAL_PARAMETER_ENTITY) &&
        !           318:                (cur->type !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
        !           319:                (!xmlStrcmp(cur->name, name))) return(cur);
1.16      daniel    320:        }
                    321:     }
1.15      daniel    322:     if (xmlPredefinedEntities == NULL)
                    323:         xmlInitializePredefinedEntities();
1.16      daniel    324:     table = xmlPredefinedEntities;
                    325:     for (i = 0;i < table->nb_entities;i++) {
                    326:        cur = &table->table[i];
1.30    ! daniel    327:        if ((cur->type !=  XML_INTERNAL_PARAMETER_ENTITY) &&
        !           328:            (cur->type !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
        !           329:            (!xmlStrcmp(cur->name, name))) return(cur);
1.14      daniel    330:     }
                    331: 
                    332:     return(NULL);
1.1       httpng    333: }
                    334: 
                    335: /*
1.21      daniel    336:  * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
                    337:  *                  | [#x10000-#x10FFFF]
                    338:  * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
                    339:  */
                    340: #define IS_CHAR(c)                                                     \
                    341:     (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) ||                        \
                    342:      (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
                    343: 
1.28      daniel    344: /*
                    345:  * A buffer used for converting entities to their equivalent and back.
                    346:  *
                    347:  * TODO: remove this, this helps performances but forbid reentrancy in a 
                    348:  *       stupid way.
                    349:  */
                    350: static int buffer_size = 0;
                    351: static CHAR *buffer = NULL;
                    352: 
                    353: void growBuffer(void) {
                    354:     buffer_size *= 2;
                    355:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
                    356:     if (buffer == NULL) {
                    357:         perror("realloc failed");
                    358:         exit(1);
                    359:     }
                    360: }
                    361: 
                    362: 
1.22      daniel    363: /**
                    364:  * xmlEncodeEntities:
                    365:  * @doc:  the document containing the string
                    366:  * @input:  A string to convert to XML.
                    367:  *
                    368:  * Do a global encoding of a string, replacing the predefined entities
                    369:  * and non ASCII values with their entities and CharRef counterparts.
                    370:  *
1.19      daniel    371:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    372:  *           get erroneous.
1.22      daniel    373:  *
1.28      daniel    374:  * TODO This routine is not reentrant, the interface
                    375:  *      should not be modified though.
                    376:  *
                    377:  * People must migrate their code to xmlEncodeEntitiesReentrant !
                    378:  * 
                    379:  * Returns A newly allocated string with the substitution done.
                    380:  */
                    381: const CHAR *
                    382: xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
                    383:     const CHAR *cur = input;
                    384:     CHAR *out = buffer;
                    385: 
                    386:     if (input == NULL) return(NULL);
                    387:     if (buffer == NULL) {
                    388:         buffer_size = 1000;
                    389:         buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
                    390:        if (buffer == NULL) {
                    391:            perror("malloc failed");
                    392:             exit(1);
                    393:        }
                    394:        out = buffer;
                    395:     }
                    396:     while (*cur != '\0') {
                    397:         if (out - buffer > buffer_size - 100) {
                    398:            int index = out - buffer;
                    399: 
                    400:            growBuffer();
                    401:            out = &buffer[index];
                    402:        }
                    403: 
                    404:        /*
                    405:         * By default one have to encode at least '<', '>', '"' and '&' !
                    406:         */
                    407:        if (*cur == '<') {
                    408:            *out++ = '&';
                    409:            *out++ = 'l';
                    410:            *out++ = 't';
                    411:            *out++ = ';';
                    412:        } else if (*cur == '>') {
                    413:            *out++ = '&';
                    414:            *out++ = 'g';
                    415:            *out++ = 't';
                    416:            *out++ = ';';
                    417:        } else if (*cur == '&') {
                    418:            *out++ = '&';
                    419:            *out++ = 'a';
                    420:            *out++ = 'm';
                    421:            *out++ = 'p';
                    422:            *out++ = ';';
                    423:        } else if (*cur == '"') {
                    424:            *out++ = '&';
                    425:            *out++ = 'q';
                    426:            *out++ = 'u';
                    427:            *out++ = 'o';
                    428:            *out++ = 't';
                    429:            *out++ = ';';
                    430:        } else if (*cur == '\'') {
                    431:            *out++ = '&';
                    432:            *out++ = 'a';
                    433:            *out++ = 'p';
                    434:            *out++ = 'o';
                    435:            *out++ = 's';
                    436:            *out++ = ';';
                    437:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    438:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    439:            /*
                    440:             * default case, just copy !
                    441:             */
                    442:            *out++ = *cur;
                    443: #ifndef USE_UTF_8
                    444:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    445:            char buf[10], *ptr;
                    446: #ifdef HAVE_SNPRINTF
                    447:            snprintf(buf, 9, "&#%d;", *cur);
                    448: #else
                    449:            sprintf(buf, "&#%d;", *cur);
                    450: #endif
                    451:             ptr = buf;
                    452:            while (*ptr != 0) *out++ = *ptr++;
                    453: #endif
                    454:        } else if (IS_CHAR(*cur)) {
                    455:            char buf[10], *ptr;
                    456: 
                    457: #ifdef HAVE_SNPRINTF
                    458:            snprintf(buf, 9, "&#%d;", *cur);
                    459: #else
                    460:            sprintf(buf, "&#%d;", *cur);
                    461: #endif
                    462:             ptr = buf;
                    463:            while (*ptr != 0) *out++ = *ptr++;
                    464:        }
                    465: #if 0
                    466:        else {
                    467:            /*
                    468:             * default case, this is not a valid char !
                    469:             * Skip it...
                    470:             */
                    471:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
                    472:        }
                    473: #endif
                    474:        cur++;
                    475:     }
                    476:     *out++ = 0;
                    477:     return(buffer);
                    478: }
                    479: 
                    480: /*
                    481:  * Macro used to grow the current buffer.
                    482:  */
                    483: #define growBufferReentrant() {                                                \
                    484:     buffer_size *= 2;                                                  \
                    485:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));     \
                    486:     if (buffer == NULL) {                                              \
                    487:        perror("realloc failed");                                       \
                    488:        exit(1);                                                        \
                    489:     }                                                                  \
                    490: }
                    491: 
                    492: 
                    493: /**
                    494:  * xmlEncodeEntitiesReentrant:
                    495:  * @doc:  the document containing the string
                    496:  * @input:  A string to convert to XML.
                    497:  *
                    498:  * Do a global encoding of a string, replacing the predefined entities
                    499:  * and non ASCII values with their entities and CharRef counterparts.
                    500:  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
                    501:  * must be deallocated.
                    502:  *
                    503:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    504:  *           get erroneous.
                    505:  *
1.24      daniel    506:  * Returns A newly allocated string with the substitution done.
1.1       httpng    507:  */
1.22      daniel    508: CHAR *
1.28      daniel    509: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const CHAR *input) {
1.7       veillard  510:     const CHAR *cur = input;
1.26      daniel    511:     CHAR *buffer = NULL;
                    512:     CHAR *out = NULL;
                    513:     int buffer_size = 0;
1.3       httpng    514: 
1.19      daniel    515:     if (input == NULL) return(NULL);
1.26      daniel    516: 
                    517:     /*
                    518:      * allocate an translation buffer.
                    519:      */
                    520:     buffer_size = 1000;
                    521:     buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1.3       httpng    522:     if (buffer == NULL) {
1.26      daniel    523:        perror("malloc failed");
                    524:        exit(1);
1.3       httpng    525:     }
1.26      daniel    526:     out = buffer;
                    527: 
1.6       veillard  528:     while (*cur != '\0') {
                    529:         if (out - buffer > buffer_size - 100) {
                    530:            int index = out - buffer;
                    531: 
1.28      daniel    532:            growBufferReentrant();
1.6       veillard  533:            out = &buffer[index];
                    534:        }
                    535: 
                    536:        /*
1.7       veillard  537:         * By default one have to encode at least '<', '>', '"' and '&' !
1.6       veillard  538:         */
                    539:        if (*cur == '<') {
                    540:            *out++ = '&';
                    541:            *out++ = 'l';
                    542:            *out++ = 't';
                    543:            *out++ = ';';
1.7       veillard  544:        } else if (*cur == '>') {
                    545:            *out++ = '&';
                    546:            *out++ = 'g';
                    547:            *out++ = 't';
                    548:            *out++ = ';';
1.6       veillard  549:        } else if (*cur == '&') {
                    550:            *out++ = '&';
                    551:            *out++ = 'a';
                    552:            *out++ = 'm';
                    553:            *out++ = 'p';
1.7       veillard  554:            *out++ = ';';
                    555:        } else if (*cur == '"') {
                    556:            *out++ = '&';
                    557:            *out++ = 'q';
                    558:            *out++ = 'u';
                    559:            *out++ = 'o';
                    560:            *out++ = 't';
                    561:            *out++ = ';';
                    562:        } else if (*cur == '\'') {
                    563:            *out++ = '&';
                    564:            *out++ = 'a';
                    565:            *out++ = 'p';
                    566:            *out++ = 'o';
                    567:            *out++ = 's';
1.6       veillard  568:            *out++ = ';';
1.21      daniel    569:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    570:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    571:            /*
                    572:             * default case, just copy !
                    573:             */
                    574:            *out++ = *cur;
1.19      daniel    575: #ifndef USE_UTF_8
                    576:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    577:            char buf[10], *ptr;
                    578: #ifdef HAVE_SNPRINTF
                    579:            snprintf(buf, 9, "&#%d;", *cur);
                    580: #else
                    581:            sprintf(buf, "&#%d;", *cur);
                    582: #endif
                    583:             ptr = buf;
                    584:            while (*ptr != 0) *out++ = *ptr++;
                    585: #endif
1.21      daniel    586:        } else if (IS_CHAR(*cur)) {
1.20      daniel    587:            char buf[10], *ptr;
                    588: 
                    589: #ifdef HAVE_SNPRINTF
                    590:            snprintf(buf, 9, "&#%d;", *cur);
                    591: #else
                    592:            sprintf(buf, "&#%d;", *cur);
                    593: #endif
                    594:             ptr = buf;
                    595:            while (*ptr != 0) *out++ = *ptr++;
1.21      daniel    596:        }
                    597: #if 0
                    598:        else {
1.6       veillard  599:            /*
1.21      daniel    600:             * default case, this is not a valid char !
                    601:             * Skip it...
1.6       veillard  602:             */
1.21      daniel    603:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6       veillard  604:        }
1.21      daniel    605: #endif
1.6       veillard  606:        cur++;
                    607:     }
                    608:     *out++ = 0;
                    609:     return(buffer);
1.2       httpng    610: }
                    611: 
1.22      daniel    612: /**
                    613:  * xmlCreateEntitiesTable:
                    614:  *
                    615:  * create and initialize an empty entities hash table.
                    616:  *
1.24      daniel    617:  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2       httpng    618:  */
1.22      daniel    619: xmlEntitiesTablePtr
                    620: xmlCreateEntitiesTable(void) {
1.2       httpng    621:     xmlEntitiesTablePtr ret;
1.1       httpng    622: 
1.2       httpng    623:     ret = (xmlEntitiesTablePtr) 
                    624:          malloc(sizeof(xmlEntitiesTable));
1.1       httpng    625:     if (ret == NULL) {
1.28      daniel    626:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    627:                (long)sizeof(xmlEntitiesTable));
1.2       httpng    628:         return(NULL);
                    629:     }
                    630:     ret->max_entities = XML_MIN_ENTITIES_TABLE;
                    631:     ret->nb_entities = 0;
                    632:     ret->table = (xmlEntityPtr ) 
                    633:          malloc(ret->max_entities * sizeof(xmlEntity));
                    634:     if (ret == NULL) {
1.28      daniel    635:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    636:                ret->max_entities * (long)sizeof(xmlEntity));
1.2       httpng    637:        free(ret);
1.1       httpng    638:         return(NULL);
                    639:     }
                    640:     return(ret);
                    641: }
                    642: 
1.22      daniel    643: /**
                    644:  * xmlFreeEntitiesTable:
                    645:  * @table:  An entity table
                    646:  *
                    647:  * Deallocate the memory used by an entities hash table.
1.1       httpng    648:  */
1.22      daniel    649: void
                    650: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1       httpng    651:     int i;
                    652: 
                    653:     if (table == NULL) return;
                    654: 
1.2       httpng    655:     for (i = 0;i < table->nb_entities;i++) {
                    656:         xmlFreeEntity(&table->table[i]);
1.1       httpng    657:     }
1.2       httpng    658:     free(table->table);
1.1       httpng    659:     free(table);
                    660: }
                    661: 
1.22      daniel    662: /**
                    663:  * xmlCopyEntitiesTable:
                    664:  * @table:  An entity table
                    665:  *
                    666:  * Build a copy of an entity table.
                    667:  * 
1.24      daniel    668:  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22      daniel    669:  */
                    670: xmlEntitiesTablePtr
                    671: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
                    672:     xmlEntitiesTablePtr ret;
                    673:     xmlEntityPtr cur, ent;
                    674:     int i;
                    675: 
                    676:     ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
                    677:     if (ret == NULL) {
                    678:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    679:        return(NULL);
                    680:     }
                    681:     ret->table = (xmlEntityPtr) malloc(table->max_entities *
                    682:                                          sizeof(xmlEntity));
                    683:     if (ret->table == NULL) {
                    684:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    685:        free(ret);
                    686:        return(NULL);
                    687:     }
                    688:     ret->max_entities = table->max_entities;
                    689:     ret->nb_entities = table->nb_entities;
                    690:     for (i = 0;i < ret->nb_entities;i++) {
                    691:        cur = &ret->table[i];
                    692:        ent = &table->table[i];
                    693:        cur->len = ent->len;
                    694:        cur->type = ent->type;
                    695:        if (ent->name != NULL)
                    696:            cur->name = xmlStrdup(ent->name);
                    697:        else
                    698:            cur->name = NULL;
                    699:        if (ent->ExternalID != NULL)
                    700:            cur->ExternalID = xmlStrdup(ent->ExternalID);
                    701:        else
                    702:            cur->ExternalID = NULL;
                    703:        if (ent->SystemID != NULL)
                    704:            cur->SystemID = xmlStrdup(ent->SystemID);
                    705:        else
                    706:            cur->SystemID = NULL;
                    707:        if (ent->content != NULL)
                    708:            cur->content = xmlStrdup(ent->content);
                    709:        else
                    710:            cur->content = NULL;
1.27      daniel    711:        if (ent->orig != NULL)
                    712:            cur->orig = xmlStrdup(ent->orig);
                    713:        else
                    714:            cur->orig = NULL;
1.22      daniel    715:     }
                    716:     return(ret);
                    717: }
                    718: 
                    719: /**
                    720:  * xmlDumpEntitiesTable:
1.25      daniel    721:  * @buf:  An XML buffer.
1.22      daniel    722:  * @table:  An entity table
                    723:  *
                    724:  * This will dump the content of the entity table as an XML DTD definition
1.13      daniel    725:  */
1.22      daniel    726: void
1.25      daniel    727: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14      daniel    728:     int i;
                    729:     xmlEntityPtr cur;
                    730: 
                    731:     if (table == NULL) return;
                    732: 
                    733:     for (i = 0;i < table->nb_entities;i++) {
                    734:         cur = &table->table[i];
                    735:         switch (cur->type) {
                    736:            case XML_INTERNAL_GENERAL_ENTITY:
1.25      daniel    737:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    738:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    739:                xmlBufferWriteChar(buf, " ");
                    740:                if (cur->orig != NULL)
                    741:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    742:                else
                    743:                    xmlBufferWriteQuotedString(buf, cur->content);
                    744:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    745:                break;
                    746:            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.25      daniel    747:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    748:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    749:                if (cur->ExternalID != NULL) {
1.27      daniel    750:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    751:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    752:                     xmlBufferWriteChar(buf, " ");
                    753:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    754:                } else {
1.27      daniel    755:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    756:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    757:                }
1.25      daniel    758:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    759:                break;
                    760:            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.25      daniel    761:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    762:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    763:                if (cur->ExternalID != NULL) {
1.27      daniel    764:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    765:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    766:                     xmlBufferWriteChar(buf, " ");
                    767:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    768:                } else {
1.27      daniel    769:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    770:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    771:                }
                    772:                if (cur->content != NULL) { /* Should be true ! */
1.25      daniel    773:                    xmlBufferWriteChar(buf, " NDATA ");
1.27      daniel    774:                    if (cur->orig != NULL)
                    775:                        xmlBufferWriteCHAR(buf, cur->orig);
                    776:                    else
                    777:                        xmlBufferWriteCHAR(buf, cur->content);
1.14      daniel    778:                }
1.25      daniel    779:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    780:                break;
                    781:            case XML_INTERNAL_PARAMETER_ENTITY:
1.25      daniel    782:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    783:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    784:                xmlBufferWriteChar(buf, " ");
                    785:                if (cur->orig == NULL)
                    786:                    xmlBufferWriteQuotedString(buf, cur->content);
                    787:                else
                    788:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    789:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    790:                break;
                    791:            case XML_EXTERNAL_PARAMETER_ENTITY:
1.25      daniel    792:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    793:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    794:                if (cur->ExternalID != NULL) {
1.27      daniel    795:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    796:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    797:                     xmlBufferWriteChar(buf, " ");
                    798:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    799:                } else {
1.27      daniel    800:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    801:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    802:                }
1.25      daniel    803:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    804:                break;
                    805:            default:
                    806:                fprintf(stderr,
                    807:                    "xmlDumpEntitiesTable: internal: unknown type %d\n",
                    808:                        cur->type);
                    809:        }
                    810:     }
1.13      daniel    811: }

Webmaster