File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / entities.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:37:57 2012 UTC (12 years, 4 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_8_0p0, v2_8_0, v2_7_8, HEAD
libxml2

    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>