Annotation of embedaddon/libxml2/entities.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * entities.c : implementation for the XML entities handling
                      3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
                      6:  * daniel@veillard.com
                      7:  */
                      8: 
                      9: #define IN_LIBXML
                     10: #include "libxml.h"
                     11: 
                     12: #include <string.h>
                     13: #ifdef HAVE_STDLIB_H
                     14: #include <stdlib.h>
                     15: #endif
                     16: #include <libxml/xmlmemory.h>
                     17: #include <libxml/hash.h>
                     18: #include <libxml/entities.h>
                     19: #include <libxml/parser.h>
                     20: #include <libxml/parserInternals.h>
                     21: #include <libxml/xmlerror.h>
                     22: #include <libxml/globals.h>
                     23: #include <libxml/dict.h>
                     24: 
                     25: /*
                     26:  * The XML predefined entities.
                     27:  */
                     28: 
                     29: static xmlEntity xmlEntityLt = {
                     30:     NULL, XML_ENTITY_DECL, BAD_CAST "lt",
                     31:     NULL, NULL, NULL, NULL, NULL, NULL, 
                     32:     BAD_CAST "<", BAD_CAST "<", 1,
                     33:     XML_INTERNAL_PREDEFINED_ENTITY,
                     34:     NULL, NULL, NULL, NULL, 0, 1
                     35: };
                     36: static xmlEntity xmlEntityGt = {
                     37:     NULL, XML_ENTITY_DECL, BAD_CAST "gt",
                     38:     NULL, NULL, NULL, NULL, NULL, NULL, 
                     39:     BAD_CAST ">", BAD_CAST ">", 1,
                     40:     XML_INTERNAL_PREDEFINED_ENTITY,
                     41:     NULL, NULL, NULL, NULL, 0, 1
                     42: };
                     43: static xmlEntity xmlEntityAmp = {
                     44:     NULL, XML_ENTITY_DECL, BAD_CAST "amp",
                     45:     NULL, NULL, NULL, NULL, NULL, NULL, 
                     46:     BAD_CAST "&", BAD_CAST "&", 1,
                     47:     XML_INTERNAL_PREDEFINED_ENTITY,
                     48:     NULL, NULL, NULL, NULL, 0, 1
                     49: };
                     50: static xmlEntity xmlEntityQuot = {
                     51:     NULL, XML_ENTITY_DECL, BAD_CAST "quot",
                     52:     NULL, NULL, NULL, NULL, NULL, NULL, 
                     53:     BAD_CAST "\"", BAD_CAST "\"", 1,
                     54:     XML_INTERNAL_PREDEFINED_ENTITY,
                     55:     NULL, NULL, NULL, NULL, 0, 1
                     56: };
                     57: static xmlEntity xmlEntityApos = {
                     58:     NULL, XML_ENTITY_DECL, BAD_CAST "apos",
                     59:     NULL, NULL, NULL, NULL, NULL, NULL, 
                     60:     BAD_CAST "'", BAD_CAST "'", 1,
                     61:     XML_INTERNAL_PREDEFINED_ENTITY,
                     62:     NULL, NULL, NULL, NULL, 0, 1
                     63: };
                     64: 
                     65: /**
                     66:  * xmlEntitiesErrMemory:
                     67:  * @extra:  extra informations
                     68:  *
                     69:  * Handle an out of memory condition
                     70:  */
                     71: static void
                     72: xmlEntitiesErrMemory(const char *extra)
                     73: {
                     74:     __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
                     75: }
                     76: 
                     77: /**
                     78:  * xmlEntitiesErr:
                     79:  * @code:  the error code
                     80:  * @msg:  the message
                     81:  *
                     82:  * Handle an out of memory condition
                     83:  */
                     84: static void
                     85: xmlEntitiesErr(xmlParserErrors code, const char *msg)
                     86: {
                     87:     __xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL);
                     88: }
                     89: 
                     90: /*
                     91:  * xmlFreeEntity : clean-up an entity record.
                     92:  */
                     93: static void
                     94: xmlFreeEntity(xmlEntityPtr entity)
                     95: {
                     96:     xmlDictPtr dict = NULL;
                     97: 
                     98:     if (entity == NULL)
                     99:         return;
                    100: 
                    101:     if (entity->doc != NULL)
                    102:         dict = entity->doc->dict;
                    103: 
                    104: 
                    105:     if ((entity->children) && (entity->owner == 1) &&
                    106:         (entity == (xmlEntityPtr) entity->children->parent))
                    107:         xmlFreeNodeList(entity->children);
                    108:     if (dict != NULL) {
                    109:         if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name)))
                    110:             xmlFree((char *) entity->name);
                    111:         if ((entity->ExternalID != NULL) &&
                    112:            (!xmlDictOwns(dict, entity->ExternalID)))
                    113:             xmlFree((char *) entity->ExternalID);
                    114:         if ((entity->SystemID != NULL) &&
                    115:            (!xmlDictOwns(dict, entity->SystemID)))
                    116:             xmlFree((char *) entity->SystemID);
                    117:         if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI)))
                    118:             xmlFree((char *) entity->URI);
                    119:         if ((entity->content != NULL)
                    120:             && (!xmlDictOwns(dict, entity->content)))
                    121:             xmlFree((char *) entity->content);
                    122:         if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig)))
                    123:             xmlFree((char *) entity->orig);
                    124:     } else {
                    125:         if (entity->name != NULL)
                    126:             xmlFree((char *) entity->name);
                    127:         if (entity->ExternalID != NULL)
                    128:             xmlFree((char *) entity->ExternalID);
                    129:         if (entity->SystemID != NULL)
                    130:             xmlFree((char *) entity->SystemID);
                    131:         if (entity->URI != NULL)
                    132:             xmlFree((char *) entity->URI);
                    133:         if (entity->content != NULL)
                    134:             xmlFree((char *) entity->content);
                    135:         if (entity->orig != NULL)
                    136:             xmlFree((char *) entity->orig);
                    137:     }
                    138:     xmlFree(entity);
                    139: }
                    140: 
                    141: /*
                    142:  * xmlCreateEntity:
                    143:  *
                    144:  * internal routine doing the entity node strutures allocations
                    145:  */
                    146: static xmlEntityPtr
                    147: xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
                    148:                const xmlChar *ExternalID, const xmlChar *SystemID,
                    149:                const xmlChar *content) {
                    150:     xmlEntityPtr ret;
                    151: 
                    152:     ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
                    153:     if (ret == NULL) {
                    154:         xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
                    155:        return(NULL);
                    156:     }
                    157:     memset(ret, 0, sizeof(xmlEntity));
                    158:     ret->type = XML_ENTITY_DECL;
                    159:     ret->checked = 0;
                    160: 
                    161:     /*
                    162:      * fill the structure.
                    163:      */
                    164:     ret->etype = (xmlEntityType) type;
                    165:     if (dict == NULL) {
                    166:        ret->name = xmlStrdup(name);
                    167:        if (ExternalID != NULL)
                    168:            ret->ExternalID = xmlStrdup(ExternalID);
                    169:        if (SystemID != NULL)
                    170:            ret->SystemID = xmlStrdup(SystemID);
                    171:     } else {
                    172:         ret->name = xmlDictLookup(dict, name, -1);
                    173:        if (ExternalID != NULL)
                    174:            ret->ExternalID = xmlDictLookup(dict, ExternalID, -1);
                    175:        if (SystemID != NULL)
                    176:            ret->SystemID = xmlDictLookup(dict, SystemID, -1);
                    177:     }
                    178:     if (content != NULL) {
                    179:         ret->length = xmlStrlen(content);
                    180:        if ((dict != NULL) && (ret->length < 5))
                    181:            ret->content = (xmlChar *)
                    182:                           xmlDictLookup(dict, content, ret->length);
                    183:        else
                    184:            ret->content = xmlStrndup(content, ret->length);
                    185:      } else {
                    186:         ret->length = 0;
                    187:         ret->content = NULL;
                    188:     }
                    189:     ret->URI = NULL; /* to be computed by the layer knowing
                    190:                        the defining entity */
                    191:     ret->orig = NULL;
                    192:     ret->owner = 0;
                    193: 
                    194:     return(ret);
                    195: }
                    196: 
                    197: /*
                    198:  * xmlAddEntity : register a new entity for an entities table.
                    199:  */
                    200: static xmlEntityPtr
                    201: xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
                    202:          const xmlChar *ExternalID, const xmlChar *SystemID,
                    203:          const xmlChar *content) {
                    204:     xmlDictPtr dict = NULL;
                    205:     xmlEntitiesTablePtr table = NULL;
                    206:     xmlEntityPtr ret;
                    207: 
                    208:     if (name == NULL)
                    209:        return(NULL);
                    210:     if (dtd == NULL)
                    211:        return(NULL);
                    212:     if (dtd->doc != NULL)
                    213:         dict = dtd->doc->dict;
                    214: 
                    215:     switch (type) {
                    216:         case XML_INTERNAL_GENERAL_ENTITY:
                    217:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    218:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    219:            if (dtd->entities == NULL)
                    220:                dtd->entities = xmlHashCreateDict(0, dict);
                    221:            table = dtd->entities;
                    222:            break;
                    223:         case XML_INTERNAL_PARAMETER_ENTITY:
                    224:         case XML_EXTERNAL_PARAMETER_ENTITY:
                    225:            if (dtd->pentities == NULL)
                    226:                dtd->pentities = xmlHashCreateDict(0, dict);
                    227:            table = dtd->pentities;
                    228:            break;
                    229:         case XML_INTERNAL_PREDEFINED_ENTITY:
                    230:            return(NULL);
                    231:     }
                    232:     if (table == NULL)
                    233:        return(NULL);
                    234:     ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
                    235:     if (ret == NULL)
                    236:         return(NULL);
                    237:     ret->doc = dtd->doc;
                    238: 
                    239:     if (xmlHashAddEntry(table, name, ret)) {
                    240:        /*
                    241:         * entity was already defined at another level.
                    242:         */
                    243:         xmlFreeEntity(ret);
                    244:        return(NULL);
                    245:     }
                    246:     return(ret);
                    247: }
                    248: 
                    249: /**
                    250:  * xmlGetPredefinedEntity:
                    251:  * @name:  the entity name
                    252:  *
                    253:  * Check whether this name is an predefined entity.
                    254:  *
                    255:  * Returns NULL if not, otherwise the entity
                    256:  */
                    257: xmlEntityPtr
                    258: xmlGetPredefinedEntity(const xmlChar *name) {
                    259:     if (name == NULL) return(NULL);
                    260:     switch (name[0]) {
                    261:         case 'l':
                    262:            if (xmlStrEqual(name, BAD_CAST "lt"))
                    263:                return(&xmlEntityLt);
                    264:            break;
                    265:         case 'g':
                    266:            if (xmlStrEqual(name, BAD_CAST "gt"))
                    267:                return(&xmlEntityGt);
                    268:            break;
                    269:         case 'a':
                    270:            if (xmlStrEqual(name, BAD_CAST "amp"))
                    271:                return(&xmlEntityAmp);
                    272:            if (xmlStrEqual(name, BAD_CAST "apos"))
                    273:                return(&xmlEntityApos);
                    274:            break;
                    275:         case 'q':
                    276:            if (xmlStrEqual(name, BAD_CAST "quot"))
                    277:                return(&xmlEntityQuot);
                    278:            break;
                    279:        default:
                    280:            break;
                    281:     }
                    282:     return(NULL);
                    283: }
                    284: 
                    285: /**
                    286:  * xmlAddDtdEntity:
                    287:  * @doc:  the document
                    288:  * @name:  the entity name
                    289:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    290:  * @ExternalID:  the entity external ID if available
                    291:  * @SystemID:  the entity system ID if available
                    292:  * @content:  the entity content
                    293:  *
                    294:  * Register a new entity for this document DTD external subset.
                    295:  *
                    296:  * Returns a pointer to the entity or NULL in case of error
                    297:  */
                    298: xmlEntityPtr
                    299: xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
                    300:                const xmlChar *ExternalID, const xmlChar *SystemID,
                    301:                const xmlChar *content) {
                    302:     xmlEntityPtr ret;
                    303:     xmlDtdPtr dtd;
                    304: 
                    305:     if (doc == NULL) {
                    306:        xmlEntitiesErr(XML_DTD_NO_DOC,
                    307:                "xmlAddDtdEntity: document is NULL");
                    308:        return(NULL);
                    309:     }
                    310:     if (doc->extSubset == NULL) {
                    311:        xmlEntitiesErr(XML_DTD_NO_DTD,
                    312:                "xmlAddDtdEntity: document without external subset");
                    313:        return(NULL);
                    314:     }
                    315:     dtd = doc->extSubset;
                    316:     ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
                    317:     if (ret == NULL) return(NULL);
                    318: 
                    319:     /*
                    320:      * Link it to the DTD
                    321:      */
                    322:     ret->parent = dtd;
                    323:     ret->doc = dtd->doc;
                    324:     if (dtd->last == NULL) {
                    325:        dtd->children = dtd->last = (xmlNodePtr) ret;
                    326:     } else {
                    327:         dtd->last->next = (xmlNodePtr) ret;
                    328:        ret->prev = dtd->last;
                    329:        dtd->last = (xmlNodePtr) ret;
                    330:     }
                    331:     return(ret);
                    332: }
                    333: 
                    334: /**
                    335:  * xmlAddDocEntity:
                    336:  * @doc:  the document
                    337:  * @name:  the entity name
                    338:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    339:  * @ExternalID:  the entity external ID if available
                    340:  * @SystemID:  the entity system ID if available
                    341:  * @content:  the entity content
                    342:  *
                    343:  * Register a new entity for this document.
                    344:  *
                    345:  * Returns a pointer to the entity or NULL in case of error
                    346:  */
                    347: xmlEntityPtr
                    348: xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
                    349:                const xmlChar *ExternalID, const xmlChar *SystemID,
                    350:                const xmlChar *content) {
                    351:     xmlEntityPtr ret;
                    352:     xmlDtdPtr dtd;
                    353: 
                    354:     if (doc == NULL) {
                    355:        xmlEntitiesErr(XML_DTD_NO_DOC,
                    356:                "xmlAddDocEntity: document is NULL");
                    357:        return(NULL);
                    358:     }
                    359:     if (doc->intSubset == NULL) {
                    360:        xmlEntitiesErr(XML_DTD_NO_DTD,
                    361:                "xmlAddDocEntity: document without internal subset");
                    362:        return(NULL);
                    363:     }
                    364:     dtd = doc->intSubset;
                    365:     ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
                    366:     if (ret == NULL) return(NULL);
                    367: 
                    368:     /*
                    369:      * Link it to the DTD
                    370:      */
                    371:     ret->parent = dtd;
                    372:     ret->doc = dtd->doc;
                    373:     if (dtd->last == NULL) {
                    374:        dtd->children = dtd->last = (xmlNodePtr) ret;
                    375:     } else {
                    376:        dtd->last->next = (xmlNodePtr) ret;
                    377:        ret->prev = dtd->last;
                    378:        dtd->last = (xmlNodePtr) ret;
                    379:     }
                    380:     return(ret);
                    381: }
                    382: 
                    383: /**
                    384:  * xmlNewEntity:
                    385:  * @doc:  the document
                    386:  * @name:  the entity name
                    387:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    388:  * @ExternalID:  the entity external ID if available
                    389:  * @SystemID:  the entity system ID if available
                    390:  * @content:  the entity content
                    391:  *
                    392:  * Create a new entity, this differs from xmlAddDocEntity() that if
                    393:  * the document is NULL or has no internal subset defined, then an
                    394:  * unlinked entity structure will be returned, it is then the responsability
                    395:  * of the caller to link it to the document later or free it when not needed
                    396:  * anymore.
                    397:  *
                    398:  * Returns a pointer to the entity or NULL in case of error
                    399:  */
                    400: xmlEntityPtr
                    401: xmlNewEntity(xmlDocPtr doc, const xmlChar *name, int type,
                    402:             const xmlChar *ExternalID, const xmlChar *SystemID,
                    403:             const xmlChar *content) {
                    404:     xmlEntityPtr ret;
                    405:     xmlDictPtr dict;
                    406: 
                    407:     if ((doc != NULL) && (doc->intSubset != NULL)) {
                    408:        return(xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content));
                    409:     }
                    410:     if (doc != NULL)
                    411:         dict = doc->dict;
                    412:     else
                    413:         dict = NULL;
                    414:     ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content);
                    415:     if (ret == NULL)
                    416:         return(NULL);
                    417:     ret->doc = doc;
                    418:     return(ret);
                    419: }
                    420: 
                    421: /**
                    422:  * xmlGetEntityFromTable:
                    423:  * @table:  an entity table
                    424:  * @name:  the entity name
                    425:  * @parameter:  look for parameter entities
                    426:  *
                    427:  * Do an entity lookup in the table.
                    428:  * returns the corresponding parameter entity, if found.
                    429:  * 
                    430:  * Returns A pointer to the entity structure or NULL if not found.
                    431:  */
                    432: static xmlEntityPtr
                    433: xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) {
                    434:     return((xmlEntityPtr) xmlHashLookup(table, name));
                    435: }
                    436: 
                    437: /**
                    438:  * xmlGetParameterEntity:
                    439:  * @doc:  the document referencing the entity
                    440:  * @name:  the entity name
                    441:  *
                    442:  * Do an entity lookup in the internal and external subsets and
                    443:  * returns the corresponding parameter entity, if found.
                    444:  * 
                    445:  * Returns A pointer to the entity structure or NULL if not found.
                    446:  */
                    447: xmlEntityPtr
                    448: xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
                    449:     xmlEntitiesTablePtr table;
                    450:     xmlEntityPtr ret;
                    451: 
                    452:     if (doc == NULL)
                    453:        return(NULL);
                    454:     if ((doc->intSubset != NULL) && (doc->intSubset->pentities != NULL)) {
                    455:        table = (xmlEntitiesTablePtr) doc->intSubset->pentities;
                    456:        ret = xmlGetEntityFromTable(table, name);
                    457:        if (ret != NULL)
                    458:            return(ret);
                    459:     }
                    460:     if ((doc->extSubset != NULL) && (doc->extSubset->pentities != NULL)) {
                    461:        table = (xmlEntitiesTablePtr) doc->extSubset->pentities;
                    462:        return(xmlGetEntityFromTable(table, name));
                    463:     }
                    464:     return(NULL);
                    465: }
                    466: 
                    467: /**
                    468:  * xmlGetDtdEntity:
                    469:  * @doc:  the document referencing the entity
                    470:  * @name:  the entity name
                    471:  *
                    472:  * Do an entity lookup in the DTD entity hash table and
                    473:  * returns the corresponding entity, if found.
                    474:  * Note: the first argument is the document node, not the DTD node.
                    475:  * 
                    476:  * Returns A pointer to the entity structure or NULL if not found.
                    477:  */
                    478: xmlEntityPtr
                    479: xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
                    480:     xmlEntitiesTablePtr table;
                    481: 
                    482:     if (doc == NULL)
                    483:        return(NULL);
                    484:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    485:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
                    486:        return(xmlGetEntityFromTable(table, name));
                    487:     }
                    488:     return(NULL);
                    489: }
                    490: 
                    491: /**
                    492:  * xmlGetDocEntity:
                    493:  * @doc:  the document referencing the entity
                    494:  * @name:  the entity name
                    495:  *
                    496:  * Do an entity lookup in the document entity hash table and
                    497:  * returns the corresponding entity, otherwise a lookup is done
                    498:  * in the predefined entities too.
                    499:  * 
                    500:  * Returns A pointer to the entity structure or NULL if not found.
                    501:  */
                    502: xmlEntityPtr
                    503: xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
                    504:     xmlEntityPtr cur;
                    505:     xmlEntitiesTablePtr table;
                    506: 
                    507:     if (doc != NULL) {
                    508:        if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    509:            table = (xmlEntitiesTablePtr) doc->intSubset->entities;
                    510:            cur = xmlGetEntityFromTable(table, name);
                    511:            if (cur != NULL)
                    512:                return(cur);
                    513:        }
                    514:        if (doc->standalone != 1) {
                    515:            if ((doc->extSubset != NULL) &&
                    516:                (doc->extSubset->entities != NULL)) {
                    517:                table = (xmlEntitiesTablePtr) doc->extSubset->entities;
                    518:                cur = xmlGetEntityFromTable(table, name);
                    519:                if (cur != NULL)
                    520:                    return(cur);
                    521:            }
                    522:        }
                    523:     }
                    524:     return(xmlGetPredefinedEntity(name));
                    525: }
                    526: 
                    527: /*
                    528:  * Macro used to grow the current buffer.
                    529:  */
                    530: #define growBufferReentrant() {                                                \
                    531:     buffer_size *= 2;                                                  \
                    532:     buffer = (xmlChar *)                                               \
                    533:                xmlRealloc(buffer, buffer_size * sizeof(xmlChar));      \
                    534:     if (buffer == NULL) {                                              \
                    535:         xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\
                    536:        return(NULL);                                                   \
                    537:     }                                                                  \
                    538: }
                    539: 
                    540: 
                    541: /**
                    542:  * xmlEncodeEntitiesReentrant:
                    543:  * @doc:  the document containing the string
                    544:  * @input:  A string to convert to XML.
                    545:  *
                    546:  * Do a global encoding of a string, replacing the predefined entities
                    547:  * and non ASCII values with their entities and CharRef counterparts.
                    548:  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
                    549:  * must be deallocated.
                    550:  *
                    551:  * Returns A newly allocated string with the substitution done.
                    552:  */
                    553: xmlChar *
                    554: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
                    555:     const xmlChar *cur = input;
                    556:     xmlChar *buffer = NULL;
                    557:     xmlChar *out = NULL;
                    558:     int buffer_size = 0;
                    559:     int html = 0;
                    560: 
                    561:     if (input == NULL) return(NULL);
                    562:     if (doc != NULL)
                    563:         html = (doc->type == XML_HTML_DOCUMENT_NODE);
                    564: 
                    565:     /*
                    566:      * allocate an translation buffer.
                    567:      */
                    568:     buffer_size = 1000;
                    569:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
                    570:     if (buffer == NULL) {
                    571:         xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: malloc failed");
                    572:        return(NULL);
                    573:     }
                    574:     out = buffer;
                    575: 
                    576:     while (*cur != '\0') {
                    577:         if (out - buffer > buffer_size - 100) {
                    578:            int indx = out - buffer;
                    579: 
                    580:            growBufferReentrant();
                    581:            out = &buffer[indx];
                    582:        }
                    583: 
                    584:        /*
                    585:         * By default one have to encode at least '<', '>', '"' and '&' !
                    586:         */
                    587:        if (*cur == '<') {
                    588:            *out++ = '&';
                    589:            *out++ = 'l';
                    590:            *out++ = 't';
                    591:            *out++ = ';';
                    592:        } else if (*cur == '>') {
                    593:            *out++ = '&';
                    594:            *out++ = 'g';
                    595:            *out++ = 't';
                    596:            *out++ = ';';
                    597:        } else if (*cur == '&') {
                    598:            *out++ = '&';
                    599:            *out++ = 'a';
                    600:            *out++ = 'm';
                    601:            *out++ = 'p';
                    602:            *out++ = ';';
                    603:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    604:            (*cur == '\n') || (*cur == '\t') || ((html) && (*cur == '\r'))) {
                    605:            /*
                    606:             * default case, just copy !
                    607:             */
                    608:            *out++ = *cur;
                    609:        } else if (*cur >= 0x80) {
                    610:            if (((doc != NULL) && (doc->encoding != NULL)) || (html)) {
                    611:                /*
                    612:                 * Bjørn Reese <br@sseusa.com> provided the patch
                    613:                xmlChar xc;
                    614:                xc = (*cur & 0x3F) << 6;
                    615:                if (cur[1] != 0) {
                    616:                    xc += *(++cur) & 0x3F;
                    617:                    *out++ = xc;
                    618:                } else
                    619:                 */
                    620:                *out++ = *cur;
                    621:            } else {
                    622:                /*
                    623:                 * We assume we have UTF-8 input.
                    624:                 */
                    625:                char buf[11], *ptr;
                    626:                int val = 0, l = 1;
                    627: 
                    628:                if (*cur < 0xC0) {
                    629:                    xmlEntitiesErr(XML_CHECK_NOT_UTF8,
                    630:                            "xmlEncodeEntitiesReentrant : input not UTF-8");
                    631:                    if (doc != NULL)
                    632:                        doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    633:                    snprintf(buf, sizeof(buf), "&#%d;", *cur);
                    634:                    buf[sizeof(buf) - 1] = 0;
                    635:                    ptr = buf;
                    636:                    while (*ptr != 0) *out++ = *ptr++;
                    637:                    cur++;
                    638:                    continue;
                    639:                } else if (*cur < 0xE0) {
                    640:                     val = (cur[0]) & 0x1F;
                    641:                    val <<= 6;
                    642:                    val |= (cur[1]) & 0x3F;
                    643:                    l = 2;
                    644:                } else if (*cur < 0xF0) {
                    645:                     val = (cur[0]) & 0x0F;
                    646:                    val <<= 6;
                    647:                    val |= (cur[1]) & 0x3F;
                    648:                    val <<= 6;
                    649:                    val |= (cur[2]) & 0x3F;
                    650:                    l = 3;
                    651:                } else if (*cur < 0xF8) {
                    652:                     val = (cur[0]) & 0x07;
                    653:                    val <<= 6;
                    654:                    val |= (cur[1]) & 0x3F;
                    655:                    val <<= 6;
                    656:                    val |= (cur[2]) & 0x3F;
                    657:                    val <<= 6;
                    658:                    val |= (cur[3]) & 0x3F;
                    659:                    l = 4;
                    660:                }
                    661:                if ((l == 1) || (!IS_CHAR(val))) {
                    662:                    xmlEntitiesErr(XML_ERR_INVALID_CHAR,
                    663:                        "xmlEncodeEntitiesReentrant : char out of range\n");
                    664:                    if (doc != NULL)
                    665:                        doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                    666:                    snprintf(buf, sizeof(buf), "&#%d;", *cur);
                    667:                    buf[sizeof(buf) - 1] = 0;
                    668:                    ptr = buf;
                    669:                    while (*ptr != 0) *out++ = *ptr++;
                    670:                    cur++;
                    671:                    continue;
                    672:                }
                    673:                /*
                    674:                 * We could do multiple things here. Just save as a char ref
                    675:                 */
                    676:                snprintf(buf, sizeof(buf), "&#x%X;", val);
                    677:                buf[sizeof(buf) - 1] = 0;
                    678:                ptr = buf;
                    679:                while (*ptr != 0) *out++ = *ptr++;
                    680:                cur += l;
                    681:                continue;
                    682:            }
                    683:        } else if (IS_BYTE_CHAR(*cur)) {
                    684:            char buf[11], *ptr;
                    685: 
                    686:            snprintf(buf, sizeof(buf), "&#%d;", *cur);
                    687:            buf[sizeof(buf) - 1] = 0;
                    688:             ptr = buf;
                    689:            while (*ptr != 0) *out++ = *ptr++;
                    690:        }
                    691:        cur++;
                    692:     }
                    693:     *out = 0;
                    694:     return(buffer);
                    695: }
                    696: 
                    697: /**
                    698:  * xmlEncodeSpecialChars:
                    699:  * @doc:  the document containing the string
                    700:  * @input:  A string to convert to XML.
                    701:  *
                    702:  * Do a global encoding of a string, replacing the predefined entities
                    703:  * this routine is reentrant, and result must be deallocated.
                    704:  *
                    705:  * Returns A newly allocated string with the substitution done.
                    706:  */
                    707: xmlChar *
                    708: xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
                    709:     const xmlChar *cur = input;
                    710:     xmlChar *buffer = NULL;
                    711:     xmlChar *out = NULL;
                    712:     int buffer_size = 0;
                    713:     if (input == NULL) return(NULL);
                    714: 
                    715:     /*
                    716:      * allocate an translation buffer.
                    717:      */
                    718:     buffer_size = 1000;
                    719:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
                    720:     if (buffer == NULL) {
                    721:         xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed");
                    722:        return(NULL);
                    723:     }
                    724:     out = buffer;
                    725: 
                    726:     while (*cur != '\0') {
                    727:         if (out - buffer > buffer_size - 10) {
                    728:            int indx = out - buffer;
                    729: 
                    730:            growBufferReentrant();
                    731:            out = &buffer[indx];
                    732:        }
                    733: 
                    734:        /*
                    735:         * By default one have to encode at least '<', '>', '"' and '&' !
                    736:         */
                    737:        if (*cur == '<') {
                    738:            *out++ = '&';
                    739:            *out++ = 'l';
                    740:            *out++ = 't';
                    741:            *out++ = ';';
                    742:        } else if (*cur == '>') {
                    743:            *out++ = '&';
                    744:            *out++ = 'g';
                    745:            *out++ = 't';
                    746:            *out++ = ';';
                    747:        } else if (*cur == '&') {
                    748:            *out++ = '&';
                    749:            *out++ = 'a';
                    750:            *out++ = 'm';
                    751:            *out++ = 'p';
                    752:            *out++ = ';';
                    753:        } else if (*cur == '"') {
                    754:            *out++ = '&';
                    755:            *out++ = 'q';
                    756:            *out++ = 'u';
                    757:            *out++ = 'o';
                    758:            *out++ = 't';
                    759:            *out++ = ';';
                    760:        } else if (*cur == '\r') {
                    761:            *out++ = '&';
                    762:            *out++ = '#';
                    763:            *out++ = '1';
                    764:            *out++ = '3';
                    765:            *out++ = ';';
                    766:        } else {
                    767:            /*
                    768:             * Works because on UTF-8, all extended sequences cannot
                    769:             * result in bytes in the ASCII range.
                    770:             */
                    771:            *out++ = *cur;
                    772:        }
                    773:        cur++;
                    774:     }
                    775:     *out = 0;
                    776:     return(buffer);
                    777: }
                    778: 
                    779: /**
                    780:  * xmlCreateEntitiesTable:
                    781:  *
                    782:  * create and initialize an empty entities hash table.
                    783:  * This really doesn't make sense and should be deprecated
                    784:  *
                    785:  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
                    786:  */
                    787: xmlEntitiesTablePtr
                    788: xmlCreateEntitiesTable(void) {
                    789:     return((xmlEntitiesTablePtr) xmlHashCreate(0));
                    790: }
                    791: 
                    792: /**
                    793:  * xmlFreeEntityWrapper:
                    794:  * @entity:  An entity
                    795:  * @name:  its name
                    796:  *
                    797:  * Deallocate the memory used by an entities in the hash table.
                    798:  */
                    799: static void
                    800: xmlFreeEntityWrapper(xmlEntityPtr entity,
                    801:                       const xmlChar *name ATTRIBUTE_UNUSED) {
                    802:     if (entity != NULL)
                    803:        xmlFreeEntity(entity);
                    804: }
                    805: 
                    806: /**
                    807:  * xmlFreeEntitiesTable:
                    808:  * @table:  An entity table
                    809:  *
                    810:  * Deallocate the memory used by an entities hash table.
                    811:  */
                    812: void
                    813: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
                    814:     xmlHashFree(table, (xmlHashDeallocator) xmlFreeEntityWrapper);
                    815: }
                    816: 
                    817: #ifdef LIBXML_TREE_ENABLED
                    818: /**
                    819:  * xmlCopyEntity:
                    820:  * @ent:  An entity
                    821:  *
                    822:  * Build a copy of an entity
                    823:  * 
                    824:  * Returns the new xmlEntitiesPtr or NULL in case of error.
                    825:  */
                    826: static xmlEntityPtr
                    827: xmlCopyEntity(xmlEntityPtr ent) {
                    828:     xmlEntityPtr cur;
                    829: 
                    830:     cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
                    831:     if (cur == NULL) {
                    832:         xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed");
                    833:        return(NULL);
                    834:     }
                    835:     memset(cur, 0, sizeof(xmlEntity));
                    836:     cur->type = XML_ENTITY_DECL;
                    837: 
                    838:     cur->etype = ent->etype;
                    839:     if (ent->name != NULL)
                    840:        cur->name = xmlStrdup(ent->name);
                    841:     if (ent->ExternalID != NULL)
                    842:        cur->ExternalID = xmlStrdup(ent->ExternalID);
                    843:     if (ent->SystemID != NULL)
                    844:        cur->SystemID = xmlStrdup(ent->SystemID);
                    845:     if (ent->content != NULL)
                    846:        cur->content = xmlStrdup(ent->content);
                    847:     if (ent->orig != NULL)
                    848:        cur->orig = xmlStrdup(ent->orig);
                    849:     if (ent->URI != NULL)
                    850:        cur->URI = xmlStrdup(ent->URI);
                    851:     return(cur);
                    852: }
                    853: 
                    854: /**
                    855:  * xmlCopyEntitiesTable:
                    856:  * @table:  An entity table
                    857:  *
                    858:  * Build a copy of an entity table.
                    859:  * 
                    860:  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
                    861:  */
                    862: xmlEntitiesTablePtr
                    863: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
                    864:     return(xmlHashCopy(table, (xmlHashCopier) xmlCopyEntity));
                    865: }
                    866: #endif /* LIBXML_TREE_ENABLED */
                    867: 
                    868: #ifdef LIBXML_OUTPUT_ENABLED
                    869: 
                    870: /**
                    871:  * xmlDumpEntityContent:
                    872:  * @buf:  An XML buffer.
                    873:  * @content:  The entity content.
                    874:  *
                    875:  * This will dump the quoted string value, taking care of the special
                    876:  * treatment required by %
                    877:  */
                    878: static void
                    879: xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) {
                    880:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
                    881:     if (xmlStrchr(content, '%')) {
                    882:         const xmlChar * base, *cur;
                    883: 
                    884:        xmlBufferCCat(buf, "\"");
                    885:        base = cur = content;
                    886:        while (*cur != 0) {
                    887:            if (*cur == '"') {
                    888:                if (base != cur)
                    889:                    xmlBufferAdd(buf, base, cur - base);
                    890:                xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
                    891:                cur++;
                    892:                base = cur;
                    893:            } else if (*cur == '%') {
                    894:                if (base != cur)
                    895:                    xmlBufferAdd(buf, base, cur - base);
                    896:                xmlBufferAdd(buf, BAD_CAST "&#x25;", 6);
                    897:                cur++;
                    898:                base = cur;
                    899:            } else {
                    900:                cur++;
                    901:            }
                    902:        }
                    903:        if (base != cur)
                    904:            xmlBufferAdd(buf, base, cur - base);
                    905:        xmlBufferCCat(buf, "\"");
                    906:     } else {
                    907:         xmlBufferWriteQuotedString(buf, content);
                    908:     }
                    909: }
                    910: 
                    911: /**
                    912:  * xmlDumpEntityDecl:
                    913:  * @buf:  An XML buffer.
                    914:  * @ent:  An entity table
                    915:  *
                    916:  * This will dump the content of the entity table as an XML DTD definition
                    917:  */
                    918: void
                    919: xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
                    920:     if ((buf == NULL) || (ent == NULL)) return;
                    921:     switch (ent->etype) {
                    922:        case XML_INTERNAL_GENERAL_ENTITY:
                    923:            xmlBufferWriteChar(buf, "<!ENTITY ");
                    924:            xmlBufferWriteCHAR(buf, ent->name);
                    925:            xmlBufferWriteChar(buf, " ");
                    926:            if (ent->orig != NULL)
                    927:                xmlBufferWriteQuotedString(buf, ent->orig);
                    928:            else
                    929:                xmlDumpEntityContent(buf, ent->content);
                    930:            xmlBufferWriteChar(buf, ">\n");
                    931:            break;
                    932:        case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    933:            xmlBufferWriteChar(buf, "<!ENTITY ");
                    934:            xmlBufferWriteCHAR(buf, ent->name);
                    935:            if (ent->ExternalID != NULL) {
                    936:                 xmlBufferWriteChar(buf, " PUBLIC ");
                    937:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                    938:                 xmlBufferWriteChar(buf, " ");
                    939:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    940:            } else {
                    941:                 xmlBufferWriteChar(buf, " SYSTEM ");
                    942:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    943:            }
                    944:            xmlBufferWriteChar(buf, ">\n");
                    945:            break;
                    946:        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    947:            xmlBufferWriteChar(buf, "<!ENTITY ");
                    948:            xmlBufferWriteCHAR(buf, ent->name);
                    949:            if (ent->ExternalID != NULL) {
                    950:                 xmlBufferWriteChar(buf, " PUBLIC ");
                    951:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                    952:                 xmlBufferWriteChar(buf, " ");
                    953:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    954:            } else {
                    955:                 xmlBufferWriteChar(buf, " SYSTEM ");
                    956:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    957:            }
                    958:            if (ent->content != NULL) { /* Should be true ! */
                    959:                xmlBufferWriteChar(buf, " NDATA ");
                    960:                if (ent->orig != NULL)
                    961:                    xmlBufferWriteCHAR(buf, ent->orig);
                    962:                else
                    963:                    xmlBufferWriteCHAR(buf, ent->content);
                    964:            }
                    965:            xmlBufferWriteChar(buf, ">\n");
                    966:            break;
                    967:        case XML_INTERNAL_PARAMETER_ENTITY:
                    968:            xmlBufferWriteChar(buf, "<!ENTITY % ");
                    969:            xmlBufferWriteCHAR(buf, ent->name);
                    970:            xmlBufferWriteChar(buf, " ");
                    971:            if (ent->orig == NULL)
                    972:                xmlDumpEntityContent(buf, ent->content);
                    973:            else
                    974:                xmlBufferWriteQuotedString(buf, ent->orig);
                    975:            xmlBufferWriteChar(buf, ">\n");
                    976:            break;
                    977:        case XML_EXTERNAL_PARAMETER_ENTITY:
                    978:            xmlBufferWriteChar(buf, "<!ENTITY % ");
                    979:            xmlBufferWriteCHAR(buf, ent->name);
                    980:            if (ent->ExternalID != NULL) {
                    981:                 xmlBufferWriteChar(buf, " PUBLIC ");
                    982:                 xmlBufferWriteQuotedString(buf, ent->ExternalID);
                    983:                 xmlBufferWriteChar(buf, " ");
                    984:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    985:            } else {
                    986:                 xmlBufferWriteChar(buf, " SYSTEM ");
                    987:                 xmlBufferWriteQuotedString(buf, ent->SystemID);
                    988:            }
                    989:            xmlBufferWriteChar(buf, ">\n");
                    990:            break;
                    991:        default:
                    992:            xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY,
                    993:                "xmlDumpEntitiesDecl: internal: unknown type entity type");
                    994:     }
                    995: }
                    996: 
                    997: /**
                    998:  * xmlDumpEntityDeclScan:
                    999:  * @ent:  An entity table
                   1000:  * @buf:  An XML buffer.
                   1001:  *
                   1002:  * When using the hash table scan function, arguments need to be reversed
                   1003:  */
                   1004: static void
                   1005: xmlDumpEntityDeclScan(xmlEntityPtr ent, xmlBufferPtr buf) {
                   1006:     xmlDumpEntityDecl(buf, ent);
                   1007: }
                   1008:       
                   1009: /**
                   1010:  * xmlDumpEntitiesTable:
                   1011:  * @buf:  An XML buffer.
                   1012:  * @table:  An entity table
                   1013:  *
                   1014:  * This will dump the content of the entity table as an XML DTD definition
                   1015:  */
                   1016: void
                   1017: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
                   1018:     xmlHashScan(table, (xmlHashScanner)xmlDumpEntityDeclScan, buf);
                   1019: }
                   1020: #endif /* LIBXML_OUTPUT_ENABLED */
                   1021: #define bottom_entities
                   1022: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>