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 """, 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 "%", 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>