Annotation of embedaddon/libxml2/entities.c, revision 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>