Annotation of XML/entities.c, revision 1.62

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

Webmaster