Annotation of XML/entities.c, revision 1.40

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

Webmaster