Annotation of XML/entities.c, revision 1.59

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.42      daniel      9: #ifdef WIN32
                     10: #include "win32config.h"
                     11: #else
1.37      daniel     12: #include "config.h"
                     13: #endif
                     14: 
1.1       httpng     15: #include <stdio.h>
1.37      daniel     16: #include <string.h>
                     17: #ifdef HAVE_STDLIB_H
1.17      daniel     18: #include <stdlib.h>
1.37      daniel     19: #endif
1.56      daniel     20: #include <libxml/xmlmemory.h>
                     21: #include <libxml/entities.h>
                     22: #include <libxml/parser.h>
1.1       httpng     23: 
1.54      daniel     24: #define DEBUG_ENT_REF /* debugging of cross entities dependancies */
                     25: 
1.1       httpng     26: /*
1.15      daniel     27:  * The XML predefined entities.
                     28:  */
                     29: 
                     30: struct xmlPredefinedEntityValue {
                     31:     const char *name;
                     32:     const char *value;
                     33: };
                     34: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
                     35:     { "lt", "<" },
                     36:     { "gt", ">" },
                     37:     { "apos", "'" },
                     38:     { "quot", "\"" },
                     39:     { "amp", "&" }
                     40: };
                     41: 
                     42: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
                     43: 
                     44: /*
1.2       httpng     45:  * xmlFreeEntity : clean-up an entity record.
1.1       httpng     46:  */
1.2       httpng     47: void xmlFreeEntity(xmlEntityPtr entity) {
                     48:     if (entity == NULL) return;
                     49: 
1.52      daniel     50:     if (entity->children)
                     51:        xmlFreeNodeList(entity->children);
1.11      daniel     52:     if (entity->name != NULL)
1.36      daniel     53:        xmlFree((char *) entity->name);
1.14      daniel     54:     if (entity->ExternalID != NULL)
1.36      daniel     55:         xmlFree((char *) entity->ExternalID);
1.14      daniel     56:     if (entity->SystemID != NULL)
1.36      daniel     57:         xmlFree((char *) entity->SystemID);
1.14      daniel     58:     if (entity->content != NULL)
1.36      daniel     59:         xmlFree((char *) entity->content);
1.27      daniel     60:     if (entity->orig != NULL)
1.36      daniel     61:         xmlFree((char *) entity->orig);
1.55      daniel     62: #ifdef WITH_EXTRA_ENT_DETECT
1.54      daniel     63:     if (entity->entTab != NULL) {
                     64:        int i;
                     65: 
                     66:        for (i = 0; i < entity->entNr; i++)
                     67:            xmlFree(entity->entTab[i]);
                     68:        xmlFree(entity->entTab);
                     69:     }
1.55      daniel     70: #endif
1.14      daniel     71:     memset(entity, -1, sizeof(xmlEntity));
1.51      daniel     72:     xmlFree(entity);
1.2       httpng     73: }
1.1       httpng     74: 
                     75: /*
1.22      daniel     76:  * xmlAddEntity : register a new entity for an entities table.
1.1       httpng     77:  */
1.51      daniel     78: static xmlEntityPtr
1.38      daniel     79: xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
                     80:          const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
1.2       httpng     81:     int i;
1.51      daniel     82:     xmlEntityPtr ret;
1.1       httpng     83: 
1.2       httpng     84:     for (i = 0;i < table->nb_entities;i++) {
1.51      daniel     85:         ret = table->table[i];
                     86:        if (!xmlStrcmp(ret->name, name)) {
1.13      daniel     87:            /*
                     88:             * The entity is already defined in this Dtd, the spec says to NOT
                     89:             * override it ... Is it worth a Warning ??? !!!
1.33      daniel     90:             * Not having a cprinting context this seems hard ...
1.13      daniel     91:             */
1.30      daniel     92:            if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
                     93:                 (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51      daniel     94:                ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
                     95:                 (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
                     96:                return(NULL);
1.30      daniel     97:            else
                     98:            if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
                     99:                 (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51      daniel    100:                ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
                    101:                 (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
                    102:                return(NULL);
1.7       veillard  103:        }
1.2       httpng    104:     }
                    105:     if (table->nb_entities >= table->max_entities) {
                    106:         /*
                    107:         * need more elements.
                    108:         */
                    109:        table->max_entities *= 2;
1.51      daniel    110:        table->table = (xmlEntityPtr *) 
                    111:            xmlRealloc(table->table,
                    112:                       table->max_entities * sizeof(xmlEntityPtr));
1.29      daniel    113:        if (table->table == NULL) {
1.2       httpng    114:            perror("realloc failed");
1.51      daniel    115:            return(NULL);
1.2       httpng    116:        }
                    117:     }
1.51      daniel    118:     ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
                    119:     if (ret == NULL) {
                    120:        fprintf(stderr, "xmlAddEntity: out of memory\n");
                    121:        return(NULL);
                    122:     }
                    123:     memset(ret, 0, sizeof(xmlEntity));
                    124:     ret->type = XML_ENTITY_DECL;
                    125:     table->table[table->nb_entities] = ret;
                    126: 
                    127:     /*
                    128:      * fill the structure.
                    129:      */
                    130:     ret->name = xmlStrdup(name);
1.58      veillard  131:     ret->etype = (xmlEntityType) type;
1.13      daniel    132:     if (ExternalID != NULL)
1.51      daniel    133:        ret->ExternalID = xmlStrdup(ExternalID);
1.13      daniel    134:     if (SystemID != NULL)
1.51      daniel    135:        ret->SystemID = xmlStrdup(SystemID);
1.43      daniel    136:     if (content != NULL) {
1.51      daniel    137:         ret->length = xmlStrlen(content);
                    138:        ret->content = xmlStrndup(content, ret->length);
1.43      daniel    139:      } else {
1.51      daniel    140:         ret->length = 0;
                    141:         ret->content = NULL;
1.43      daniel    142:     }
1.51      daniel    143:     ret->orig = NULL;
1.2       httpng    144:     table->nb_entities++;
1.51      daniel    145: 
                    146:     return(ret);
1.2       httpng    147: }
1.1       httpng    148: 
1.22      daniel    149: /**
                    150:  * xmlInitializePredefinedEntities:
                    151:  *
                    152:  * Set up the predefined entities.
1.15      daniel    153:  */
                    154: void xmlInitializePredefinedEntities(void) {
                    155:     int i;
1.38      daniel    156:     xmlChar name[50];
                    157:     xmlChar value[50];
1.15      daniel    158:     const char *in;
1.38      daniel    159:     xmlChar *out;
1.15      daniel    160: 
                    161:     if (xmlPredefinedEntities != NULL) return;
                    162: 
                    163:     xmlPredefinedEntities = xmlCreateEntitiesTable();
                    164:     for (i = 0;i < sizeof(xmlPredefinedEntityValues) / 
                    165:                    sizeof(xmlPredefinedEntityValues[0]);i++) {
                    166:         in = xmlPredefinedEntityValues[i].name;
                    167:        out = &name[0];
1.38      daniel    168:        for (;(*out++ = (xmlChar) *in);)in++;
1.15      daniel    169:         in = xmlPredefinedEntityValues[i].value;
                    170:        out = &value[0];
1.38      daniel    171:        for (;(*out++ = (xmlChar) *in);)in++;
                    172:         xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
1.18      daniel    173:                     XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15      daniel    174:                     &value[0]);
                    175:     }
                    176: }
1.17      daniel    177: 
                    178: /**
1.40      daniel    179:  * xmlCleanupPredefinedEntities:
                    180:  *
                    181:  * Cleanup up the predefined entities table.
                    182:  */
                    183: void xmlCleanupPredefinedEntities(void) {
                    184:     if (xmlPredefinedEntities == NULL) return;
                    185: 
                    186:     xmlFreeEntitiesTable(xmlPredefinedEntities);
                    187:     xmlPredefinedEntities = NULL;
                    188: }
                    189: 
                    190: /**
1.17      daniel    191:  * xmlGetPredefinedEntity:
                    192:  * @name:  the entity name
                    193:  *
                    194:  * Check whether this name is an predefined entity.
                    195:  *
1.24      daniel    196:  * Returns NULL if not, othervise the entity
1.17      daniel    197:  */
                    198: xmlEntityPtr
1.38      daniel    199: xmlGetPredefinedEntity(const xmlChar *name) {
1.17      daniel    200:     int i;
                    201:     xmlEntityPtr cur;
                    202: 
                    203:     if (xmlPredefinedEntities == NULL)
                    204:         xmlInitializePredefinedEntities();
                    205:     for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
1.51      daniel    206:        cur = xmlPredefinedEntities->table[i];
1.17      daniel    207:        if (!xmlStrcmp(cur->name, name)) return(cur);
                    208:     }
                    209:     return(NULL);
                    210: }
                    211: 
1.22      daniel    212: /**
                    213:  * xmlAddDtdEntity:
                    214:  * @doc:  the document
                    215:  * @name:  the entity name
                    216:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    217:  * @ExternalID:  the entity external ID if available
                    218:  * @SystemID:  the entity system ID if available
                    219:  * @content:  the entity content
                    220:  *
1.51      daniel    221:  * Register a new entity for this document DTD external subset.
                    222:  *
                    223:  * Returns a pointer to the entity or NULL in case of error
1.1       httpng    224:  */
1.51      daniel    225: xmlEntityPtr
1.38      daniel    226: xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51      daniel    227:                const xmlChar *ExternalID, const xmlChar *SystemID,
                    228:                const xmlChar *content) {
1.2       httpng    229:     xmlEntitiesTablePtr table;
1.51      daniel    230:     xmlEntityPtr ret;
                    231:     xmlDtdPtr dtd;
1.1       httpng    232: 
1.51      daniel    233:     if (doc == NULL) {
                    234:         fprintf(stderr,
                    235:                "xmlAddDtdEntity: doc == NULL !\n");
                    236:        return(NULL);
                    237:     }
1.22      daniel    238:     if (doc->extSubset == NULL) {
                    239:         fprintf(stderr,
                    240:                "xmlAddDtdEntity: document without external subset !\n");
1.51      daniel    241:        return(NULL);
1.16      daniel    242:     }
1.51      daniel    243:     dtd = doc->extSubset;
                    244:     table = (xmlEntitiesTablePtr) dtd->entities;
1.2       httpng    245:     if (table == NULL) {
                    246:         table = xmlCreateEntitiesTable();
1.51      daniel    247:        dtd->entities = table;
1.1       httpng    248:     }
1.51      daniel    249:     ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
                    250:     if (ret == NULL) return(NULL);
                    251: 
                    252:     /*
                    253:      * Link it to the Dtd
                    254:      */
                    255:     ret->parent = dtd;
                    256:     ret->doc = dtd->doc;
                    257:     if (dtd->last == NULL) {
                    258:        dtd->children = dtd->last = (xmlNodePtr) ret;
                    259:     } else {
                    260:         dtd->last->next = (xmlNodePtr) ret;
                    261:        ret->prev = dtd->last;
                    262:        dtd->last = (xmlNodePtr) ret;
                    263:     }
                    264:     return(ret);
1.1       httpng    265: }
                    266: 
1.22      daniel    267: /**
                    268:  * xmlAddDocEntity:
                    269:  * @doc:  the document
                    270:  * @name:  the entity name
                    271:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    272:  * @ExternalID:  the entity external ID if available
                    273:  * @SystemID:  the entity system ID if available
                    274:  * @content:  the entity content
                    275:  *
                    276:  * Register a new entity for this document.
1.51      daniel    277:  *
                    278:  * Returns a pointer to the entity or NULL in case of error
1.1       httpng    279:  */
1.51      daniel    280: xmlEntityPtr
1.38      daniel    281: xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51      daniel    282:                const xmlChar *ExternalID, const xmlChar *SystemID,
                    283:                const xmlChar *content) {
1.16      daniel    284:     xmlEntitiesTablePtr table;
1.51      daniel    285:     xmlEntityPtr ret;
                    286:     xmlDtdPtr dtd;
1.16      daniel    287: 
1.22      daniel    288:     if (doc == NULL) {
                    289:         fprintf(stderr,
                    290:                "xmlAddDocEntity: document is NULL !\n");
1.51      daniel    291:        return(NULL);
1.22      daniel    292:     }
                    293:     if (doc->intSubset == NULL) {
                    294:         fprintf(stderr,
                    295:                "xmlAddDtdEntity: document without internal subset !\n");
1.51      daniel    296:        return(NULL);
1.22      daniel    297:     }
1.51      daniel    298:     dtd = doc->intSubset;
1.22      daniel    299:     table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    300:     if (table == NULL) {
                    301:         table = xmlCreateEntitiesTable();
1.22      daniel    302:        doc->intSubset->entities = table;
1.2       httpng    303:     }
1.51      daniel    304:     ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
                    305:     if (ret == NULL) return(NULL);
                    306: 
                    307:     /*
                    308:      * Link it to the Dtd
                    309:      */
                    310:     ret->parent = dtd;
                    311:     ret->doc = dtd->doc;
                    312:     if (dtd->last == NULL) {
                    313:        dtd->children = dtd->last = (xmlNodePtr) ret;
                    314:     } else {
                    315:        dtd->last->next = (xmlNodePtr) ret;
                    316:        ret->prev = dtd->last;
                    317:        dtd->last = (xmlNodePtr) ret;
                    318:     }
                    319:     return(ret);
1.54      daniel    320: }
                    321: 
1.55      daniel    322: #ifdef WITH_EXTRA_ENT_DETECT
1.54      daniel    323: /**
                    324:  * xmlEntityCheckReference:
                    325:  * @ent:  an existing entity
                    326:  * @to:  the entity name it's referencing
                    327:  *
                    328:  * Function to keep track of references and detect cycles (well formedness 
                    329:  * errors !).
                    330:  *
                    331:  * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop 
                    332:  *      detection.
                    333:  */
                    334: int
                    335: xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
                    336:     int i;
                    337:     xmlDocPtr doc;
                    338: 
                    339:     if (ent == NULL) return(-1);
                    340:     if (to == NULL) return(-1);
                    341: 
                    342:     doc = ent->doc;
                    343:     if (doc == NULL) return(-1);
                    344: 
                    345: #ifdef DEBUG_ENT_REF
                    346:     printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);
                    347: #endif
                    348: 
                    349: 
                    350:     /*
                    351:      * Do a recursive checking
                    352:      */
                    353:     for (i = 0;i < ent->entNr;i++) {
                    354:        xmlEntityPtr indir = NULL;
                    355: 
                    356:        if (!xmlStrcmp(to, ent->entTab[i]))
                    357:            return(1);
                    358: 
                    359:        switch (ent->etype) {
                    360:             case XML_INTERNAL_GENERAL_ENTITY:
                    361:             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    362:                indir = xmlGetDocEntity(doc, ent->entTab[i]);
                    363:                break;
                    364:             case XML_INTERNAL_PARAMETER_ENTITY:
                    365:             case XML_EXTERNAL_PARAMETER_ENTITY:
                    366:                indir = xmlGetDtdEntity(doc, ent->entTab[i]);
                    367:                break;
                    368:             case XML_INTERNAL_PREDEFINED_ENTITY:
                    369:             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    370:                break;
                    371:        }
                    372:        if (xmlEntityCheckReference(indir, to) == 1)
                    373:            return(1);
                    374:     }
                    375:     return(0);
                    376: }
                    377: 
                    378: /**
                    379:  * xmlEntityAddReference:
                    380:  * @ent:  an existing entity
                    381:  * @to:  the entity name it's referencing
                    382:  *
                    383:  * Function to register reuse of an existing entity from a (new) one
                    384:  * Used to keep track of references and detect cycles (well formedness 
                    385:  * errors !).
                    386:  *
                    387:  * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop 
                    388:  *      detection.
                    389:  */
                    390: int
                    391: xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
                    392:     int i;
                    393:     xmlDocPtr doc;
                    394:     xmlEntityPtr indir = NULL;
                    395: 
                    396:     if (ent == NULL) return(-1);
                    397:     if (to == NULL) return(-1);
                    398: 
                    399:     doc = ent->doc;
                    400:     if (doc == NULL) return(-1);
                    401: 
                    402: #ifdef DEBUG_ENT_REF
                    403:     printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);
                    404: #endif
                    405:     if (ent->entTab == NULL) {
                    406:        ent->entNr = 0;
                    407:        ent->entMax = 5;
                    408:        ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
                    409:        if (ent->entTab == NULL) {
                    410:            fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
                    411:            return(-1);
                    412:        }
                    413:     }
                    414: 
                    415:     for (i = 0;i < ent->entNr;i++) {
                    416:        if (!xmlStrcmp(to, ent->entTab[i]))
                    417:            return(0);
                    418:     }
                    419: 
                    420:     /*
                    421:      * Do a recursive checking
                    422:      */
                    423: 
                    424:     switch (ent->etype) {
                    425:        case XML_INTERNAL_GENERAL_ENTITY:
                    426:        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    427:            indir = xmlGetDocEntity(doc, to);
                    428:            break;
                    429:        case XML_INTERNAL_PARAMETER_ENTITY:
                    430:        case XML_EXTERNAL_PARAMETER_ENTITY:
                    431:            indir = xmlGetDtdEntity(doc, to);
                    432:            break;
                    433:        case XML_INTERNAL_PREDEFINED_ENTITY:
                    434:        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    435:            break;
                    436:     }
                    437:     if ((indir != NULL) &&
                    438:        (xmlEntityCheckReference(indir, ent->name) == 1))
                    439:        return(1);
                    440: 
                    441:     /*
                    442:      * Add this to the list
                    443:      */
                    444:     if (ent->entMax <= ent->entNr) {
                    445:        ent->entMax *= 2;
                    446:        ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
                    447:                                              ent->entMax * sizeof(xmlChar *));
                    448:        if (ent->entTab == NULL) {
                    449:            fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
                    450:            return(-1);
                    451:        }
                    452:     }
                    453:     ent->entTab[ent->entNr++] = xmlStrdup(to);
                    454:     return(0);
1.1       httpng    455: }
1.55      daniel    456: #endif
1.1       httpng    457: 
1.22      daniel    458: /**
1.30      daniel    459:  * xmlGetParameterEntity:
                    460:  * @doc:  the document referencing the entity
                    461:  * @name:  the entity name
                    462:  *
                    463:  * Do an entity lookup in the internal and external subsets and
                    464:  * returns the corresponding parameter entity, if found.
                    465:  * 
                    466:  * Returns A pointer to the entity structure or NULL if not found.
                    467:  */
                    468: xmlEntityPtr
1.38      daniel    469: xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
1.30      daniel    470:     int i;
                    471:     xmlEntityPtr cur;
                    472:     xmlEntitiesTablePtr table;
                    473: 
                    474:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    475:        table = (xmlEntitiesTablePtr) doc->intSubset->entities;
                    476:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    477:            cur = table->table[i];
1.49      daniel    478:            if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
                    479:                 (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.30      daniel    480:                (!xmlStrcmp(cur->name, name))) return(cur);
                    481:        }
                    482:     }
                    483:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    484:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
                    485:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    486:            cur = table->table[i];
1.49      daniel    487:            if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
                    488:                 (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.30      daniel    489:                (!xmlStrcmp(cur->name, name))) return(cur);
                    490:        }
                    491:     }
1.35      daniel    492:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    493:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
                    494:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    495:            cur = table->table[i];
1.49      daniel    496:            if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
                    497:                 (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.35      daniel    498:                (!xmlStrcmp(cur->name, name))) return(cur);
                    499:        }
                    500:     }
1.30      daniel    501:     return(NULL);
                    502: }
                    503: 
                    504: /**
1.22      daniel    505:  * xmlGetDtdEntity:
                    506:  * @doc:  the document referencing the entity
                    507:  * @name:  the entity name
                    508:  *
                    509:  * Do an entity lookup in the Dtd entity hash table and
                    510:  * returns the corresponding entity, if found.
                    511:  * 
1.24      daniel    512:  * Returns A pointer to the entity structure or NULL if not found.
1.1       httpng    513:  */
1.22      daniel    514: xmlEntityPtr
1.38      daniel    515: xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
1.2       httpng    516:     int i;
                    517:     xmlEntityPtr cur;
                    518:     xmlEntitiesTablePtr table;
                    519: 
1.22      daniel    520:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    521:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.15      daniel    522:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    523:            cur = table->table[i];
1.49      daniel    524:            if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
                    525:                (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30      daniel    526:                (!xmlStrcmp(cur->name, name))) return(cur);
1.15      daniel    527:        }
                    528:     }
1.7       veillard  529:     return(NULL);
1.3       httpng    530: }
                    531: 
1.22      daniel    532: /**
                    533:  * xmlGetDocEntity:
                    534:  * @doc:  the document referencing the entity
                    535:  * @name:  the entity name
                    536:  *
                    537:  * Do an entity lookup in the document entity hash table and
                    538:  * returns the corrsponding entity, otherwise a lookup is done
                    539:  * in the predefined entities too.
                    540:  * 
1.24      daniel    541:  * Returns A pointer to the entity structure or NULL if not found.
1.14      daniel    542:  */
1.22      daniel    543: xmlEntityPtr
1.38      daniel    544: xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
1.14      daniel    545:     int i;
1.16      daniel    546:     xmlEntityPtr cur;
1.14      daniel    547:     xmlEntitiesTablePtr table;
                    548: 
1.22      daniel    549:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    550:        table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    551:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    552:            cur = table->table[i];
1.49      daniel    553:            if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
                    554:                (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30      daniel    555:                (!xmlStrcmp(cur->name, name))) return(cur);
1.16      daniel    556:        }
                    557:     }
1.34      daniel    558:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    559:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
                    560:        for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    561:            cur = table->table[i];
1.49      daniel    562:            if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
                    563:                (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
1.34      daniel    564:                (!xmlStrcmp(cur->name, name))) return(cur);
                    565:        }
                    566:     }
1.15      daniel    567:     if (xmlPredefinedEntities == NULL)
                    568:         xmlInitializePredefinedEntities();
1.16      daniel    569:     table = xmlPredefinedEntities;
                    570:     for (i = 0;i < table->nb_entities;i++) {
1.51      daniel    571:        cur = table->table[i];
1.49      daniel    572:        if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
                    573:            (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30      daniel    574:            (!xmlStrcmp(cur->name, name))) return(cur);
1.14      daniel    575:     }
                    576: 
                    577:     return(NULL);
1.1       httpng    578: }
                    579: 
                    580: /*
1.21      daniel    581:  * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
                    582:  *                  | [#x10000-#x10FFFF]
                    583:  * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
                    584:  */
                    585: #define IS_CHAR(c)                                                     \
                    586:     (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) ||                        \
                    587:      (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
                    588: 
1.28      daniel    589: /*
                    590:  * A buffer used for converting entities to their equivalent and back.
                    591:  */
                    592: static int buffer_size = 0;
1.38      daniel    593: static xmlChar *buffer = NULL;
1.28      daniel    594: 
1.44      daniel    595: int growBuffer(void) {
1.28      daniel    596:     buffer_size *= 2;
1.38      daniel    597:     buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
1.28      daniel    598:     if (buffer == NULL) {
                    599:         perror("realloc failed");
1.44      daniel    600:        return(-1);
1.28      daniel    601:     }
1.44      daniel    602:     return(0);
1.28      daniel    603: }
                    604: 
                    605: 
1.22      daniel    606: /**
                    607:  * xmlEncodeEntities:
                    608:  * @doc:  the document containing the string
                    609:  * @input:  A string to convert to XML.
                    610:  *
                    611:  * Do a global encoding of a string, replacing the predefined entities
                    612:  * and non ASCII values with their entities and CharRef counterparts.
                    613:  *
1.33      daniel    614:  * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
                    615:  *       compatibility
1.28      daniel    616:  *
                    617:  * People must migrate their code to xmlEncodeEntitiesReentrant !
1.31      daniel    618:  * This routine will issue a warning when encountered.
1.28      daniel    619:  * 
                    620:  * Returns A newly allocated string with the substitution done.
                    621:  */
1.38      daniel    622: const xmlChar *
                    623: xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
                    624:     const xmlChar *cur = input;
                    625:     xmlChar *out = buffer;
1.31      daniel    626:     static int warning = 1;
1.39      daniel    627:     int html = 0;
                    628: 
1.31      daniel    629: 
                    630:     if (warning) {
                    631:     fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
                    632:     fprintf(stderr, "   change code to use xmlEncodeEntitiesReentrant()\n");
                    633:     warning = 0;
                    634:     }
1.28      daniel    635: 
                    636:     if (input == NULL) return(NULL);
1.39      daniel    637:     if (doc != NULL)
                    638:         html = (doc->type == XML_HTML_DOCUMENT_NODE);
                    639: 
1.28      daniel    640:     if (buffer == NULL) {
                    641:         buffer_size = 1000;
1.38      daniel    642:         buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.28      daniel    643:        if (buffer == NULL) {
                    644:            perror("malloc failed");
1.44      daniel    645:             return(NULL);
1.28      daniel    646:        }
                    647:        out = buffer;
                    648:     }
                    649:     while (*cur != '\0') {
                    650:         if (out - buffer > buffer_size - 100) {
                    651:            int index = out - buffer;
                    652: 
                    653:            growBuffer();
                    654:            out = &buffer[index];
                    655:        }
                    656: 
                    657:        /*
                    658:         * By default one have to encode at least '<', '>', '"' and '&' !
                    659:         */
                    660:        if (*cur == '<') {
                    661:            *out++ = '&';
                    662:            *out++ = 'l';
                    663:            *out++ = 't';
                    664:            *out++ = ';';
                    665:        } else if (*cur == '>') {
                    666:            *out++ = '&';
                    667:            *out++ = 'g';
                    668:            *out++ = 't';
                    669:            *out++ = ';';
                    670:        } else if (*cur == '&') {
                    671:            *out++ = '&';
                    672:            *out++ = 'a';
                    673:            *out++ = 'm';
                    674:            *out++ = 'p';
                    675:            *out++ = ';';
                    676:        } else if (*cur == '"') {
                    677:            *out++ = '&';
                    678:            *out++ = 'q';
                    679:            *out++ = 'u';
                    680:            *out++ = 'o';
                    681:            *out++ = 't';
                    682:            *out++ = ';';
1.39      daniel    683:        } else if ((*cur == '\'') && (!html)) {
1.28      daniel    684:            *out++ = '&';
                    685:            *out++ = 'a';
                    686:            *out++ = 'p';
                    687:            *out++ = 'o';
                    688:            *out++ = 's';
                    689:            *out++ = ';';
                    690:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    691:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    692:            /*
                    693:             * default case, just copy !
                    694:             */
                    695:            *out++ = *cur;
                    696: #ifndef USE_UTF_8
1.38      daniel    697:        } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
1.28      daniel    698:            char buf[10], *ptr;
                    699: #ifdef HAVE_SNPRINTF
                    700:            snprintf(buf, 9, "&#%d;", *cur);
                    701: #else
                    702:            sprintf(buf, "&#%d;", *cur);
                    703: #endif
                    704:             ptr = buf;
                    705:            while (*ptr != 0) *out++ = *ptr++;
                    706: #endif
                    707:        } else if (IS_CHAR(*cur)) {
                    708:            char buf[10], *ptr;
                    709: 
                    710: #ifdef HAVE_SNPRINTF
                    711:            snprintf(buf, 9, "&#%d;", *cur);
                    712: #else
                    713:            sprintf(buf, "&#%d;", *cur);
                    714: #endif
                    715:             ptr = buf;
                    716:            while (*ptr != 0) *out++ = *ptr++;
                    717:        }
                    718: #if 0
                    719:        else {
                    720:            /*
                    721:             * default case, this is not a valid char !
                    722:             * Skip it...
                    723:             */
                    724:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
                    725:        }
                    726: #endif
                    727:        cur++;
                    728:     }
                    729:     *out++ = 0;
                    730:     return(buffer);
                    731: }
                    732: 
                    733: /*
                    734:  * Macro used to grow the current buffer.
                    735:  */
                    736: #define growBufferReentrant() {                                                \
                    737:     buffer_size *= 2;                                                  \
1.44      daniel    738:     buffer = (xmlChar *)                                               \
                    739:                xmlRealloc(buffer, buffer_size * sizeof(xmlChar));      \
1.28      daniel    740:     if (buffer == NULL) {                                              \
                    741:        perror("realloc failed");                                       \
1.44      daniel    742:        return(NULL);                                                   \
1.28      daniel    743:     }                                                                  \
                    744: }
                    745: 
                    746: 
                    747: /**
                    748:  * xmlEncodeEntitiesReentrant:
                    749:  * @doc:  the document containing the string
                    750:  * @input:  A string to convert to XML.
                    751:  *
                    752:  * Do a global encoding of a string, replacing the predefined entities
                    753:  * and non ASCII values with their entities and CharRef counterparts.
                    754:  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
                    755:  * must be deallocated.
                    756:  *
                    757:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    758:  *           get erroneous.
                    759:  *
1.24      daniel    760:  * Returns A newly allocated string with the substitution done.
1.1       httpng    761:  */
1.38      daniel    762: xmlChar *
                    763: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
                    764:     const xmlChar *cur = input;
                    765:     xmlChar *buffer = NULL;
                    766:     xmlChar *out = NULL;
1.26      daniel    767:     int buffer_size = 0;
1.39      daniel    768:     int html = 0;
1.3       httpng    769: 
1.19      daniel    770:     if (input == NULL) return(NULL);
1.39      daniel    771:     if (doc != NULL)
                    772:         html = (doc->type == XML_HTML_DOCUMENT_NODE);
1.26      daniel    773: 
                    774:     /*
                    775:      * allocate an translation buffer.
                    776:      */
                    777:     buffer_size = 1000;
1.38      daniel    778:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.3       httpng    779:     if (buffer == NULL) {
1.26      daniel    780:        perror("malloc failed");
1.44      daniel    781:        return(NULL);
1.3       httpng    782:     }
1.26      daniel    783:     out = buffer;
                    784: 
1.6       veillard  785:     while (*cur != '\0') {
                    786:         if (out - buffer > buffer_size - 100) {
                    787:            int index = out - buffer;
                    788: 
1.28      daniel    789:            growBufferReentrant();
1.6       veillard  790:            out = &buffer[index];
                    791:        }
                    792: 
                    793:        /*
1.7       veillard  794:         * By default one have to encode at least '<', '>', '"' and '&' !
1.6       veillard  795:         */
                    796:        if (*cur == '<') {
                    797:            *out++ = '&';
                    798:            *out++ = 'l';
                    799:            *out++ = 't';
                    800:            *out++ = ';';
1.7       veillard  801:        } else if (*cur == '>') {
                    802:            *out++ = '&';
                    803:            *out++ = 'g';
                    804:            *out++ = 't';
                    805:            *out++ = ';';
1.6       veillard  806:        } else if (*cur == '&') {
                    807:            *out++ = '&';
                    808:            *out++ = 'a';
                    809:            *out++ = 'm';
                    810:            *out++ = 'p';
1.7       veillard  811:            *out++ = ';';
                    812:        } else if (*cur == '"') {
                    813:            *out++ = '&';
                    814:            *out++ = 'q';
                    815:            *out++ = 'u';
                    816:            *out++ = 'o';
                    817:            *out++ = 't';
                    818:            *out++ = ';';
1.53      daniel    819: #if 0
1.39      daniel    820:        } else if ((*cur == '\'') && (!html)) {
1.7       veillard  821:            *out++ = '&';
                    822:            *out++ = 'a';
                    823:            *out++ = 'p';
                    824:            *out++ = 'o';
                    825:            *out++ = 's';
1.6       veillard  826:            *out++ = ';';
1.53      daniel    827: #endif
1.21      daniel    828:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    829:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    830:            /*
                    831:             * default case, just copy !
                    832:             */
                    833:            *out++ = *cur;
1.46      daniel    834:        } else if (*cur >= 0x80) {
1.59    ! veillard  835:            if ((doc->encoding != NULL) || (html)) {
1.46      daniel    836:                /*
                    837:                 * TODO !!!
                    838:                 */
                    839:                *out++ = *cur;
                    840:            } else {
                    841:                /*
                    842:                 * We assume we have UTF-8 input.
                    843:                 */
                    844:                char buf[10], *ptr;
1.48      daniel    845:                int val = 0, l = 1;
1.46      daniel    846: 
                    847:                if (*cur < 0xC0) {
                    848:                    fprintf(stderr,
                    849:                            "xmlEncodeEntitiesReentrant : input not UTF-8\n");
                    850:                    doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    851: #ifdef HAVE_SNPRINTF
                    852:                    snprintf(buf, 9, "&#%d;", *cur);
                    853: #else
                    854:                    sprintf(buf, "&#%d;", *cur);
                    855: #endif
                    856:                    ptr = buf;
                    857:                    while (*ptr != 0) *out++ = *ptr++;
                    858:                    continue;
                    859:                } else if (*cur < 0xE0) {
                    860:                     val = (cur[0]) & 0x1F;
                    861:                    val <<= 6;
                    862:                    val |= (cur[1]) & 0x3F;
                    863:                    l = 2;
                    864:                } else if (*cur < 0xF0) {
                    865:                     val = (cur[0]) & 0x0F;
                    866:                    val <<= 6;
                    867:                    val |= (cur[1]) & 0x3F;
                    868:                    val <<= 6;
                    869:                    val |= (cur[2]) & 0x3F;
                    870:                    l = 3;
                    871:                } else if (*cur < 0xF8) {
                    872:                     val = (cur[0]) & 0x07;
                    873:                    val <<= 6;
                    874:                    val |= (cur[1]) & 0x3F;
                    875:                    val <<= 6;
                    876:                    val |= (cur[2]) & 0x3F;
                    877:                    val <<= 6;
                    878:                    val |= (cur[3]) & 0x3F;
                    879:                    l = 4;
                    880:                }
                    881:                if ((l == 1) || (!IS_CHAR(val))) {
                    882:                    fprintf(stderr,
                    883:                        "xmlEncodeEntitiesReentrant : char out of range\n");
                    884:                    doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    885: #ifdef HAVE_SNPRINTF
                    886:                    snprintf(buf, 9, "&#%d;", *cur);
                    887: #else
                    888:                    sprintf(buf, "&#%d;", *cur);
                    889: #endif
                    890:                    ptr = buf;
                    891:                    while (*ptr != 0) *out++ = *ptr++;
                    892:                    cur++;
                    893:                    continue;
                    894:                }
                    895:                /*
                    896:                 * We could do multiple things here. Just save as a char ref
                    897:                 */
                    898: #ifdef HAVE_SNPRINTF
1.50      daniel    899:                snprintf(buf, 14, "&#x%X;", val);
1.46      daniel    900: #else
1.50      daniel    901:                sprintf(buf, "&#x%X;", val);
1.46      daniel    902: #endif
1.50      daniel    903:                buf[14] = 0;
1.47      daniel    904:                ptr = buf;
                    905:                while (*ptr != 0) *out++ = *ptr++;
                    906:                cur += l;
                    907:                continue;
1.45      daniel    908:            }
1.21      daniel    909:        } else if (IS_CHAR(*cur)) {
1.20      daniel    910:            char buf[10], *ptr;
                    911: 
                    912: #ifdef HAVE_SNPRINTF
                    913:            snprintf(buf, 9, "&#%d;", *cur);
                    914: #else
                    915:            sprintf(buf, "&#%d;", *cur);
                    916: #endif
                    917:             ptr = buf;
                    918:            while (*ptr != 0) *out++ = *ptr++;
1.21      daniel    919:        }
                    920: #if 0
                    921:        else {
1.6       veillard  922:            /*
1.21      daniel    923:             * default case, this is not a valid char !
                    924:             * Skip it...
1.6       veillard  925:             */
1.21      daniel    926:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6       veillard  927:        }
1.21      daniel    928: #endif
1.6       veillard  929:        cur++;
                    930:     }
                    931:     *out++ = 0;
                    932:     return(buffer);
1.2       httpng    933: }
                    934: 
1.22      daniel    935: /**
1.57      daniel    936:  * xmlEncodeSpecialChars:
                    937:  * @doc:  the document containing the string
                    938:  * @input:  A string to convert to XML.
                    939:  *
                    940:  * Do a global encoding of a string, replacing the predefined entities
                    941:  * this routine is reentrant, and result must be deallocated.
                    942:  *
                    943:  * Returns A newly allocated string with the substitution done.
                    944:  */
                    945: xmlChar *
                    946: xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
                    947:     const xmlChar *cur = input;
                    948:     xmlChar *buffer = NULL;
                    949:     xmlChar *out = NULL;
                    950:     int buffer_size = 0;
                    951:     int html = 0;
                    952: 
                    953:     if (input == NULL) return(NULL);
                    954:     if (doc != NULL)
                    955:         html = (doc->type == XML_HTML_DOCUMENT_NODE);
                    956: 
                    957:     /*
                    958:      * allocate an translation buffer.
                    959:      */
                    960:     buffer_size = 1000;
                    961:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
                    962:     if (buffer == NULL) {
                    963:        perror("malloc failed");
                    964:        return(NULL);
                    965:     }
                    966:     out = buffer;
                    967: 
                    968:     while (*cur != '\0') {
                    969:         if (out - buffer > buffer_size - 10) {
                    970:            int index = out - buffer;
                    971: 
                    972:            growBufferReentrant();
                    973:            out = &buffer[index];
                    974:        }
                    975: 
                    976:        /*
                    977:         * By default one have to encode at least '<', '>', '"' and '&' !
                    978:         */
                    979:        if (*cur == '<') {
                    980:            *out++ = '&';
                    981:            *out++ = 'l';
                    982:            *out++ = 't';
                    983:            *out++ = ';';
                    984:        } else if (*cur == '>') {
                    985:            *out++ = '&';
                    986:            *out++ = 'g';
                    987:            *out++ = 't';
                    988:            *out++ = ';';
                    989:        } else if (*cur == '&') {
                    990:            *out++ = '&';
                    991:            *out++ = 'a';
                    992:            *out++ = 'm';
                    993:            *out++ = 'p';
                    994:            *out++ = ';';
                    995:        } else if (*cur == '"') {
                    996:            *out++ = '&';
                    997:            *out++ = 'q';
                    998:            *out++ = 'u';
                    999:            *out++ = 'o';
                   1000:            *out++ = 't';
                   1001:            *out++ = ';';
                   1002:        } else {
                   1003:            /*
                   1004:             * Works because on UTF-8, all extended sequences cannot
                   1005:             * result in bytes in the ASCII range.
                   1006:             */
                   1007:            *out++ = *cur;
                   1008:        }
                   1009:        cur++;
                   1010:     }
                   1011:     *out++ = 0;
                   1012:     return(buffer);
                   1013: }
                   1014: 
                   1015: /**
1.22      daniel   1016:  * xmlCreateEntitiesTable:
                   1017:  *
                   1018:  * create and initialize an empty entities hash table.
                   1019:  *
1.24      daniel   1020:  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2       httpng   1021:  */
1.22      daniel   1022: xmlEntitiesTablePtr
                   1023: xmlCreateEntitiesTable(void) {
1.2       httpng   1024:     xmlEntitiesTablePtr ret;
1.1       httpng   1025: 
1.2       httpng   1026:     ret = (xmlEntitiesTablePtr) 
1.36      daniel   1027:          xmlMalloc(sizeof(xmlEntitiesTable));
1.1       httpng   1028:     if (ret == NULL) {
1.36      daniel   1029:         fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28      daniel   1030:                (long)sizeof(xmlEntitiesTable));
1.2       httpng   1031:         return(NULL);
                   1032:     }
                   1033:     ret->max_entities = XML_MIN_ENTITIES_TABLE;
                   1034:     ret->nb_entities = 0;
1.51      daniel   1035:     ret->table = (xmlEntityPtr *) 
                   1036:          xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
1.2       httpng   1037:     if (ret == NULL) {
1.36      daniel   1038:         fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.51      daniel   1039:                ret->max_entities * (long)sizeof(xmlEntityPtr));
1.36      daniel   1040:        xmlFree(ret);
1.1       httpng   1041:         return(NULL);
                   1042:     }
                   1043:     return(ret);
                   1044: }
                   1045: 
1.22      daniel   1046: /**
                   1047:  * xmlFreeEntitiesTable:
                   1048:  * @table:  An entity table
                   1049:  *
                   1050:  * Deallocate the memory used by an entities hash table.
1.1       httpng   1051:  */
1.22      daniel   1052: void
                   1053: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1       httpng   1054:     int i;
                   1055: 
                   1056:     if (table == NULL) return;
                   1057: 
1.2       httpng   1058:     for (i = 0;i < table->nb_entities;i++) {
1.51      daniel   1059:         xmlFreeEntity(table->table[i]);
1.1       httpng   1060:     }
1.36      daniel   1061:     xmlFree(table->table);
                   1062:     xmlFree(table);
1.1       httpng   1063: }
                   1064: 
1.22      daniel   1065: /**
                   1066:  * xmlCopyEntitiesTable:
                   1067:  * @table:  An entity table
                   1068:  *
                   1069:  * Build a copy of an entity table.
                   1070:  * 
1.24      daniel   1071:  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22      daniel   1072:  */
                   1073: xmlEntitiesTablePtr
                   1074: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
                   1075:     xmlEntitiesTablePtr ret;
                   1076:     xmlEntityPtr cur, ent;
                   1077:     int i;
                   1078: 
1.36      daniel   1079:     ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
1.22      daniel   1080:     if (ret == NULL) {
                   1081:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                   1082:        return(NULL);
                   1083:     }
1.51      daniel   1084:     ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
                   1085:                                             sizeof(xmlEntityPtr));
1.22      daniel   1086:     if (ret->table == NULL) {
                   1087:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1.36      daniel   1088:        xmlFree(ret);
1.22      daniel   1089:        return(NULL);
                   1090:     }
                   1091:     ret->max_entities = table->max_entities;
                   1092:     ret->nb_entities = table->nb_entities;
                   1093:     for (i = 0;i < ret->nb_entities;i++) {
1.51      daniel   1094:        cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
                   1095:        if (cur == NULL) {
                   1096:            fprintf(stderr, "xmlCopyEntityTable: out of memory !\n");
                   1097:            xmlFree(ret);
                   1098:            xmlFree(ret->table);
                   1099:            return(NULL);
                   1100:        }
                   1101:        memset(cur, 0, sizeof(xmlEntity));
                   1102:        cur->type = XML_ELEMENT_DECL;
                   1103:        ret->table[i] = cur;
                   1104:        ent = table->table[i];
                   1105: 
1.49      daniel   1106:        cur->etype = ent->etype;
1.22      daniel   1107:        if (ent->name != NULL)
                   1108:            cur->name = xmlStrdup(ent->name);
                   1109:        if (ent->ExternalID != NULL)
                   1110:            cur->ExternalID = xmlStrdup(ent->ExternalID);
                   1111:        if (ent->SystemID != NULL)
                   1112:            cur->SystemID = xmlStrdup(ent->SystemID);
                   1113:        if (ent->content != NULL)
                   1114:            cur->content = xmlStrdup(ent->content);
1.27      daniel   1115:        if (ent->orig != NULL)
                   1116:            cur->orig = xmlStrdup(ent->orig);
1.22      daniel   1117:     }
                   1118:     return(ret);
                   1119: }
                   1120: 
                   1121: /**
1.53      daniel   1122:  * xmlDumpEntityDecl:
                   1123:  * @buf:  An XML buffer.
                   1124:  * @ent:  An entity table
                   1125:  *
                   1126:  * This will dump the content of the entity table as an XML DTD definition
                   1127:  */
                   1128: void
                   1129: xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
                   1130:     switch (ent->etype) {
                   1131:        case XML_INTERNAL_GENERAL_ENTITY:
                   1132:            xmlBufferWriteChar(buf, "<!ENTITY ");
                   1133:            xmlBufferWriteCHAR(buf, ent->name);
                   1134:            xmlBufferWriteChar(buf, " ");
                   1135:            if (ent->orig != NULL)
                   1136:                xmlBufferWriteQuotedString(buf, ent->orig);
                   1137:            else
                   1138:                xmlBufferWriteQuotedString(buf, ent->content);
                   1139:            xmlBufferWriteChar(buf, ">\n");
                   1140:            break;
                   1141:        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                   1142:            xmlBufferWriteChar(buf, "<!ENTITY ");
                   1143:            xmlBufferWriteCHAR(buf, ent->name);
                   1144:            if (ent->ExternalID != NULL) {
                   1145:                 xmlBufferWriteChar(buf, " PUBLIC ");
                   1146:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                   1147:                 xmlBufferWriteChar(buf, " ");
                   1148:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1149:            } else {
                   1150:                 xmlBufferWriteChar(buf, " SYSTEM ");
                   1151:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1152:            }
                   1153:            xmlBufferWriteChar(buf, ">\n");
                   1154:            break;
                   1155:        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   1156:            xmlBufferWriteChar(buf, "<!ENTITY ");
                   1157:            xmlBufferWriteCHAR(buf, ent->name);
                   1158:            if (ent->ExternalID != NULL) {
                   1159:                 xmlBufferWriteChar(buf, " PUBLIC ");
                   1160:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                   1161:                 xmlBufferWriteChar(buf, " ");
                   1162:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1163:            } else {
                   1164:                 xmlBufferWriteChar(buf, " SYSTEM ");
                   1165:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1166:            }
                   1167:            if (ent->content != NULL) { /* Should be true ! */
                   1168:                xmlBufferWriteChar(buf, " NDATA ");
                   1169:                if (ent->orig != NULL)
                   1170:                    xmlBufferWriteCHAR(buf, ent->orig);
                   1171:                else
                   1172:                    xmlBufferWriteCHAR(buf, ent->content);
                   1173:            }
                   1174:            xmlBufferWriteChar(buf, ">\n");
                   1175:            break;
                   1176:        case XML_INTERNAL_PARAMETER_ENTITY:
                   1177:            xmlBufferWriteChar(buf, "<!ENTITY % ");
                   1178:            xmlBufferWriteCHAR(buf, ent->name);
                   1179:            xmlBufferWriteChar(buf, " ");
                   1180:            if (ent->orig == NULL)
                   1181:                xmlBufferWriteQuotedString(buf, ent->content);
                   1182:            else
                   1183:                xmlBufferWriteQuotedString(buf, ent->orig);
                   1184:            xmlBufferWriteChar(buf, ">\n");
                   1185:            break;
                   1186:        case XML_EXTERNAL_PARAMETER_ENTITY:
                   1187:            xmlBufferWriteChar(buf, "<!ENTITY % ");
                   1188:            xmlBufferWriteCHAR(buf, ent->name);
                   1189:            if (ent->ExternalID != NULL) {
                   1190:                 xmlBufferWriteChar(buf, " PUBLIC ");
                   1191:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                   1192:                 xmlBufferWriteChar(buf, " ");
                   1193:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1194:            } else {
                   1195:                 xmlBufferWriteChar(buf, " SYSTEM ");
                   1196:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                   1197:            }
                   1198:            xmlBufferWriteChar(buf, ">\n");
                   1199:            break;
                   1200:        default:
                   1201:            fprintf(stderr,
                   1202:                "xmlDumpEntitiesTable: internal: unknown type %d\n",
                   1203:                    ent->etype);
                   1204:     }
                   1205: }
                   1206: 
                   1207: /**
1.22      daniel   1208:  * xmlDumpEntitiesTable:
1.25      daniel   1209:  * @buf:  An XML buffer.
1.22      daniel   1210:  * @table:  An entity table
                   1211:  *
                   1212:  * This will dump the content of the entity table as an XML DTD definition
1.13      daniel   1213:  */
1.22      daniel   1214: void
1.25      daniel   1215: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14      daniel   1216:     int i;
                   1217:     xmlEntityPtr cur;
                   1218: 
                   1219:     if (table == NULL) return;
                   1220: 
                   1221:     for (i = 0;i < table->nb_entities;i++) {
1.51      daniel   1222:         cur = table->table[i];
1.53      daniel   1223:        xmlDumpEntityDecl(buf, cur);
1.14      daniel   1224:     }
1.13      daniel   1225: }

Webmaster