Annotation of XML/entities.c, revision 1.32

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.32    ! daniel     59:          const CHAR *ExternalID, const CHAR *SystemID, const 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.32    ! daniel    181:          const CHAR *ExternalID, const CHAR *SystemID, const 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.32    ! daniel    210:          const CHAR *ExternalID, const CHAR *SystemID, const 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:  *
1.31      daniel    347:  * TODO: remove this, once we are not afraid of breaking binary compatibility
1.28      daniel    348:  */
                    349: static int buffer_size = 0;
                    350: static CHAR *buffer = NULL;
                    351: 
                    352: void growBuffer(void) {
                    353:     buffer_size *= 2;
                    354:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
                    355:     if (buffer == NULL) {
                    356:         perror("realloc failed");
                    357:         exit(1);
                    358:     }
                    359: }
                    360: 
                    361: 
1.22      daniel    362: /**
                    363:  * xmlEncodeEntities:
                    364:  * @doc:  the document containing the string
                    365:  * @input:  A string to convert to XML.
                    366:  *
                    367:  * Do a global encoding of a string, replacing the predefined entities
                    368:  * and non ASCII values with their entities and CharRef counterparts.
                    369:  *
1.31      daniel    370:  * TODO: remove this, once we are not afraid of breaking binary compatibility
1.28      daniel    371:  *
                    372:  * People must migrate their code to xmlEncodeEntitiesReentrant !
1.31      daniel    373:  * This routine will issue a warning when encountered.
1.28      daniel    374:  * 
                    375:  * Returns A newly allocated string with the substitution done.
                    376:  */
                    377: const CHAR *
                    378: xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
                    379:     const CHAR *cur = input;
                    380:     CHAR *out = buffer;
1.31      daniel    381:     static int warning = 1;
                    382: 
                    383:     if (warning) {
                    384:     fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
                    385:     fprintf(stderr, "   change code to use xmlEncodeEntitiesReentrant()\n");
                    386:     warning = 0;
                    387:     }
1.28      daniel    388: 
                    389:     if (input == NULL) return(NULL);
                    390:     if (buffer == NULL) {
                    391:         buffer_size = 1000;
                    392:         buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
                    393:        if (buffer == NULL) {
                    394:            perror("malloc failed");
                    395:             exit(1);
                    396:        }
                    397:        out = buffer;
                    398:     }
                    399:     while (*cur != '\0') {
                    400:         if (out - buffer > buffer_size - 100) {
                    401:            int index = out - buffer;
                    402: 
                    403:            growBuffer();
                    404:            out = &buffer[index];
                    405:        }
                    406: 
                    407:        /*
                    408:         * By default one have to encode at least '<', '>', '"' and '&' !
                    409:         */
                    410:        if (*cur == '<') {
                    411:            *out++ = '&';
                    412:            *out++ = 'l';
                    413:            *out++ = 't';
                    414:            *out++ = ';';
                    415:        } else if (*cur == '>') {
                    416:            *out++ = '&';
                    417:            *out++ = 'g';
                    418:            *out++ = 't';
                    419:            *out++ = ';';
                    420:        } else if (*cur == '&') {
                    421:            *out++ = '&';
                    422:            *out++ = 'a';
                    423:            *out++ = 'm';
                    424:            *out++ = 'p';
                    425:            *out++ = ';';
                    426:        } else if (*cur == '"') {
                    427:            *out++ = '&';
                    428:            *out++ = 'q';
                    429:            *out++ = 'u';
                    430:            *out++ = 'o';
                    431:            *out++ = 't';
                    432:            *out++ = ';';
                    433:        } else if (*cur == '\'') {
                    434:            *out++ = '&';
                    435:            *out++ = 'a';
                    436:            *out++ = 'p';
                    437:            *out++ = 'o';
                    438:            *out++ = 's';
                    439:            *out++ = ';';
                    440:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    441:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    442:            /*
                    443:             * default case, just copy !
                    444:             */
                    445:            *out++ = *cur;
                    446: #ifndef USE_UTF_8
                    447:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    448:            char buf[10], *ptr;
                    449: #ifdef HAVE_SNPRINTF
                    450:            snprintf(buf, 9, "&#%d;", *cur);
                    451: #else
                    452:            sprintf(buf, "&#%d;", *cur);
                    453: #endif
                    454:             ptr = buf;
                    455:            while (*ptr != 0) *out++ = *ptr++;
                    456: #endif
                    457:        } else if (IS_CHAR(*cur)) {
                    458:            char buf[10], *ptr;
                    459: 
                    460: #ifdef HAVE_SNPRINTF
                    461:            snprintf(buf, 9, "&#%d;", *cur);
                    462: #else
                    463:            sprintf(buf, "&#%d;", *cur);
                    464: #endif
                    465:             ptr = buf;
                    466:            while (*ptr != 0) *out++ = *ptr++;
                    467:        }
                    468: #if 0
                    469:        else {
                    470:            /*
                    471:             * default case, this is not a valid char !
                    472:             * Skip it...
                    473:             */
                    474:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
                    475:        }
                    476: #endif
                    477:        cur++;
                    478:     }
                    479:     *out++ = 0;
                    480:     return(buffer);
                    481: }
                    482: 
                    483: /*
                    484:  * Macro used to grow the current buffer.
                    485:  */
                    486: #define growBufferReentrant() {                                                \
                    487:     buffer_size *= 2;                                                  \
                    488:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));     \
                    489:     if (buffer == NULL) {                                              \
                    490:        perror("realloc failed");                                       \
                    491:        exit(1);                                                        \
                    492:     }                                                                  \
                    493: }
                    494: 
                    495: 
                    496: /**
                    497:  * xmlEncodeEntitiesReentrant:
                    498:  * @doc:  the document containing the string
                    499:  * @input:  A string to convert to XML.
                    500:  *
                    501:  * Do a global encoding of a string, replacing the predefined entities
                    502:  * and non ASCII values with their entities and CharRef counterparts.
                    503:  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
                    504:  * must be deallocated.
                    505:  *
                    506:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    507:  *           get erroneous.
                    508:  *
1.24      daniel    509:  * Returns A newly allocated string with the substitution done.
1.1       httpng    510:  */
1.22      daniel    511: CHAR *
1.28      daniel    512: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const CHAR *input) {
1.7       veillard  513:     const CHAR *cur = input;
1.26      daniel    514:     CHAR *buffer = NULL;
                    515:     CHAR *out = NULL;
                    516:     int buffer_size = 0;
1.3       httpng    517: 
1.19      daniel    518:     if (input == NULL) return(NULL);
1.26      daniel    519: 
                    520:     /*
                    521:      * allocate an translation buffer.
                    522:      */
                    523:     buffer_size = 1000;
                    524:     buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1.3       httpng    525:     if (buffer == NULL) {
1.26      daniel    526:        perror("malloc failed");
                    527:        exit(1);
1.3       httpng    528:     }
1.26      daniel    529:     out = buffer;
                    530: 
1.6       veillard  531:     while (*cur != '\0') {
                    532:         if (out - buffer > buffer_size - 100) {
                    533:            int index = out - buffer;
                    534: 
1.28      daniel    535:            growBufferReentrant();
1.6       veillard  536:            out = &buffer[index];
                    537:        }
                    538: 
                    539:        /*
1.7       veillard  540:         * By default one have to encode at least '<', '>', '"' and '&' !
1.6       veillard  541:         */
                    542:        if (*cur == '<') {
                    543:            *out++ = '&';
                    544:            *out++ = 'l';
                    545:            *out++ = 't';
                    546:            *out++ = ';';
1.7       veillard  547:        } else if (*cur == '>') {
                    548:            *out++ = '&';
                    549:            *out++ = 'g';
                    550:            *out++ = 't';
                    551:            *out++ = ';';
1.6       veillard  552:        } else if (*cur == '&') {
                    553:            *out++ = '&';
                    554:            *out++ = 'a';
                    555:            *out++ = 'm';
                    556:            *out++ = 'p';
1.7       veillard  557:            *out++ = ';';
                    558:        } else if (*cur == '"') {
                    559:            *out++ = '&';
                    560:            *out++ = 'q';
                    561:            *out++ = 'u';
                    562:            *out++ = 'o';
                    563:            *out++ = 't';
                    564:            *out++ = ';';
                    565:        } else if (*cur == '\'') {
                    566:            *out++ = '&';
                    567:            *out++ = 'a';
                    568:            *out++ = 'p';
                    569:            *out++ = 'o';
                    570:            *out++ = 's';
1.6       veillard  571:            *out++ = ';';
1.21      daniel    572:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    573:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    574:            /*
                    575:             * default case, just copy !
                    576:             */
                    577:            *out++ = *cur;
1.19      daniel    578: #ifndef USE_UTF_8
                    579:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    580:            char buf[10], *ptr;
                    581: #ifdef HAVE_SNPRINTF
                    582:            snprintf(buf, 9, "&#%d;", *cur);
                    583: #else
                    584:            sprintf(buf, "&#%d;", *cur);
                    585: #endif
                    586:             ptr = buf;
                    587:            while (*ptr != 0) *out++ = *ptr++;
                    588: #endif
1.21      daniel    589:        } else if (IS_CHAR(*cur)) {
1.20      daniel    590:            char buf[10], *ptr;
                    591: 
                    592: #ifdef HAVE_SNPRINTF
                    593:            snprintf(buf, 9, "&#%d;", *cur);
                    594: #else
                    595:            sprintf(buf, "&#%d;", *cur);
                    596: #endif
                    597:             ptr = buf;
                    598:            while (*ptr != 0) *out++ = *ptr++;
1.21      daniel    599:        }
                    600: #if 0
                    601:        else {
1.6       veillard  602:            /*
1.21      daniel    603:             * default case, this is not a valid char !
                    604:             * Skip it...
1.6       veillard  605:             */
1.21      daniel    606:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6       veillard  607:        }
1.21      daniel    608: #endif
1.6       veillard  609:        cur++;
                    610:     }
                    611:     *out++ = 0;
                    612:     return(buffer);
1.2       httpng    613: }
                    614: 
1.22      daniel    615: /**
                    616:  * xmlCreateEntitiesTable:
                    617:  *
                    618:  * create and initialize an empty entities hash table.
                    619:  *
1.24      daniel    620:  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2       httpng    621:  */
1.22      daniel    622: xmlEntitiesTablePtr
                    623: xmlCreateEntitiesTable(void) {
1.2       httpng    624:     xmlEntitiesTablePtr ret;
1.1       httpng    625: 
1.2       httpng    626:     ret = (xmlEntitiesTablePtr) 
                    627:          malloc(sizeof(xmlEntitiesTable));
1.1       httpng    628:     if (ret == NULL) {
1.28      daniel    629:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    630:                (long)sizeof(xmlEntitiesTable));
1.2       httpng    631:         return(NULL);
                    632:     }
                    633:     ret->max_entities = XML_MIN_ENTITIES_TABLE;
                    634:     ret->nb_entities = 0;
                    635:     ret->table = (xmlEntityPtr ) 
                    636:          malloc(ret->max_entities * sizeof(xmlEntity));
                    637:     if (ret == NULL) {
1.28      daniel    638:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    639:                ret->max_entities * (long)sizeof(xmlEntity));
1.2       httpng    640:        free(ret);
1.1       httpng    641:         return(NULL);
                    642:     }
                    643:     return(ret);
                    644: }
                    645: 
1.22      daniel    646: /**
                    647:  * xmlFreeEntitiesTable:
                    648:  * @table:  An entity table
                    649:  *
                    650:  * Deallocate the memory used by an entities hash table.
1.1       httpng    651:  */
1.22      daniel    652: void
                    653: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1       httpng    654:     int i;
                    655: 
                    656:     if (table == NULL) return;
                    657: 
1.2       httpng    658:     for (i = 0;i < table->nb_entities;i++) {
                    659:         xmlFreeEntity(&table->table[i]);
1.1       httpng    660:     }
1.2       httpng    661:     free(table->table);
1.1       httpng    662:     free(table);
                    663: }
                    664: 
1.22      daniel    665: /**
                    666:  * xmlCopyEntitiesTable:
                    667:  * @table:  An entity table
                    668:  *
                    669:  * Build a copy of an entity table.
                    670:  * 
1.24      daniel    671:  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22      daniel    672:  */
                    673: xmlEntitiesTablePtr
                    674: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
                    675:     xmlEntitiesTablePtr ret;
                    676:     xmlEntityPtr cur, ent;
                    677:     int i;
                    678: 
                    679:     ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
                    680:     if (ret == NULL) {
                    681:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    682:        return(NULL);
                    683:     }
                    684:     ret->table = (xmlEntityPtr) malloc(table->max_entities *
                    685:                                          sizeof(xmlEntity));
                    686:     if (ret->table == NULL) {
                    687:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    688:        free(ret);
                    689:        return(NULL);
                    690:     }
                    691:     ret->max_entities = table->max_entities;
                    692:     ret->nb_entities = table->nb_entities;
                    693:     for (i = 0;i < ret->nb_entities;i++) {
                    694:        cur = &ret->table[i];
                    695:        ent = &table->table[i];
                    696:        cur->len = ent->len;
                    697:        cur->type = ent->type;
                    698:        if (ent->name != NULL)
                    699:            cur->name = xmlStrdup(ent->name);
                    700:        else
                    701:            cur->name = NULL;
                    702:        if (ent->ExternalID != NULL)
                    703:            cur->ExternalID = xmlStrdup(ent->ExternalID);
                    704:        else
                    705:            cur->ExternalID = NULL;
                    706:        if (ent->SystemID != NULL)
                    707:            cur->SystemID = xmlStrdup(ent->SystemID);
                    708:        else
                    709:            cur->SystemID = NULL;
                    710:        if (ent->content != NULL)
                    711:            cur->content = xmlStrdup(ent->content);
                    712:        else
                    713:            cur->content = NULL;
1.27      daniel    714:        if (ent->orig != NULL)
                    715:            cur->orig = xmlStrdup(ent->orig);
                    716:        else
                    717:            cur->orig = NULL;
1.22      daniel    718:     }
                    719:     return(ret);
                    720: }
                    721: 
                    722: /**
                    723:  * xmlDumpEntitiesTable:
1.25      daniel    724:  * @buf:  An XML buffer.
1.22      daniel    725:  * @table:  An entity table
                    726:  *
                    727:  * This will dump the content of the entity table as an XML DTD definition
1.13      daniel    728:  */
1.22      daniel    729: void
1.25      daniel    730: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14      daniel    731:     int i;
                    732:     xmlEntityPtr cur;
                    733: 
                    734:     if (table == NULL) return;
                    735: 
                    736:     for (i = 0;i < table->nb_entities;i++) {
                    737:         cur = &table->table[i];
                    738:         switch (cur->type) {
                    739:            case XML_INTERNAL_GENERAL_ENTITY:
1.25      daniel    740:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    741:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    742:                xmlBufferWriteChar(buf, " ");
                    743:                if (cur->orig != NULL)
                    744:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    745:                else
                    746:                    xmlBufferWriteQuotedString(buf, cur->content);
                    747:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    748:                break;
                    749:            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.25      daniel    750:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    751:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    752:                if (cur->ExternalID != NULL) {
1.27      daniel    753:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    754:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    755:                     xmlBufferWriteChar(buf, " ");
                    756:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    757:                } else {
1.27      daniel    758:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    759:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    760:                }
1.25      daniel    761:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    762:                break;
                    763:            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.25      daniel    764:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    765:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    766:                if (cur->ExternalID != NULL) {
1.27      daniel    767:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    768:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    769:                     xmlBufferWriteChar(buf, " ");
                    770:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    771:                } else {
1.27      daniel    772:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    773:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    774:                }
                    775:                if (cur->content != NULL) { /* Should be true ! */
1.25      daniel    776:                    xmlBufferWriteChar(buf, " NDATA ");
1.27      daniel    777:                    if (cur->orig != NULL)
                    778:                        xmlBufferWriteCHAR(buf, cur->orig);
                    779:                    else
                    780:                        xmlBufferWriteCHAR(buf, cur->content);
1.14      daniel    781:                }
1.25      daniel    782:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    783:                break;
                    784:            case XML_INTERNAL_PARAMETER_ENTITY:
1.25      daniel    785:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    786:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    787:                xmlBufferWriteChar(buf, " ");
                    788:                if (cur->orig == NULL)
                    789:                    xmlBufferWriteQuotedString(buf, cur->content);
                    790:                else
                    791:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    792:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    793:                break;
                    794:            case XML_EXTERNAL_PARAMETER_ENTITY:
1.25      daniel    795:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    796:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    797:                if (cur->ExternalID != NULL) {
1.27      daniel    798:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    799:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    800:                     xmlBufferWriteChar(buf, " ");
                    801:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    802:                } else {
1.27      daniel    803:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    804:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    805:                }
1.25      daniel    806:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    807:                break;
                    808:            default:
                    809:                fprintf(stderr,
                    810:                    "xmlDumpEntitiesTable: internal: unknown type %d\n",
                    811:                        cur->type);
                    812:        }
                    813:     }
1.13      daniel    814: }

Webmaster