Annotation of XML/entities.c, revision 1.66

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

Webmaster