entities.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:30k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * entities.c : implementation for the XML entities handking
  3.  *
  4.  * See Copyright for the status of this software.
  5.  *
  6.  * Daniel.Veillard@w3.org
  7.  */
  8. #ifdef WIN32
  9. #include "win32config.h"
  10. #else
  11. #include "config.h"
  12. #endif
  13. #include <stdio.h>
  14. #include <string.h>
  15. #ifdef HAVE_STDLIB_H
  16. #include <stdlib.h>
  17. #endif
  18. #include <libxml/xmlmemory.h>
  19. #include <libxml/entities.h>
  20. #include <libxml/parser.h>
  21. #define DEBUG_ENT_REF /* debugging of cross entities dependancies */
  22. /*
  23.  * The XML predefined entities.
  24.  */
  25. struct xmlPredefinedEntityValue {
  26.     const char *name;
  27.     const char *value;
  28. };
  29. struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
  30.     { "lt", "<" },
  31.     { "gt", ">" },
  32.     { "apos", "'" },
  33.     { "quot", """ },
  34.     { "amp", "&" }
  35. };
  36. xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
  37. /*
  38.  * xmlFreeEntity : clean-up an entity record.
  39.  */
  40. void xmlFreeEntity(xmlEntityPtr entity) {
  41.     if (entity == NULL) return;
  42.     if (entity->children)
  43. xmlFreeNodeList(entity->children);
  44.     if (entity->name != NULL)
  45. xmlFree((char *) entity->name);
  46.     if (entity->ExternalID != NULL)
  47.         xmlFree((char *) entity->ExternalID);
  48.     if (entity->SystemID != NULL)
  49.         xmlFree((char *) entity->SystemID);
  50.     if (entity->content != NULL)
  51.         xmlFree((char *) entity->content);
  52.     if (entity->orig != NULL)
  53.         xmlFree((char *) entity->orig);
  54. #ifdef WITH_EXTRA_ENT_DETECT
  55.     if (entity->entTab != NULL) {
  56. int i;
  57. for (i = 0; i < entity->entNr; i++)
  58.     xmlFree(entity->entTab[i]);
  59. xmlFree(entity->entTab);
  60.     }
  61. #endif
  62.     memset(entity, -1, sizeof(xmlEntity));
  63.     xmlFree(entity);
  64. }
  65. /*
  66.  * xmlAddEntity : register a new entity for an entities table.
  67.  */
  68. static xmlEntityPtr
  69. xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
  70.   const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
  71.     int i;
  72.     xmlEntityPtr ret;
  73.     for (i = 0;i < table->nb_entities;i++) {
  74.         ret = table->table[i];
  75. if (!xmlStrcmp(ret->name, name)) {
  76.     /*
  77.      * The entity is already defined in this Dtd, the spec says to NOT
  78.      * override it ... Is it worth a Warning ??? !!!
  79.      * Not having a cprinting context this seems hard ...
  80.      */
  81.     if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
  82.          (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
  83.         ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
  84.          (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
  85. return(NULL);
  86.     else
  87.     if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
  88.          (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
  89.         ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
  90.          (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
  91. return(NULL);
  92. }
  93.     }
  94.     if (table->nb_entities >= table->max_entities) {
  95.         /*
  96.  * need more elements.
  97.  */
  98. table->max_entities *= 2;
  99. table->table = (xmlEntityPtr *) 
  100.     xmlRealloc(table->table,
  101.        table->max_entities * sizeof(xmlEntityPtr));
  102. if (table->table == NULL) {
  103.     perror("realloc failed");
  104.     return(NULL);
  105. }
  106.     }
  107.     ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
  108.     if (ret == NULL) {
  109. fprintf(stderr, "xmlAddEntity: out of memoryn");
  110. return(NULL);
  111.     }
  112.     memset(ret, 0, sizeof(xmlEntity));
  113.     ret->type = XML_ENTITY_DECL;
  114.     table->table[table->nb_entities] = ret;
  115.     /*
  116.      * fill the structure.
  117.      */
  118.     ret->name = xmlStrdup(name);
  119.     ret->etype = type;
  120.     if (ExternalID != NULL)
  121. ret->ExternalID = xmlStrdup(ExternalID);
  122.     if (SystemID != NULL)
  123. ret->SystemID = xmlStrdup(SystemID);
  124.     if (content != NULL) {
  125.         ret->length = xmlStrlen(content);
  126. ret->content = xmlStrndup(content, ret->length);
  127.      } else {
  128.         ret->length = 0;
  129.         ret->content = NULL;
  130.     }
  131.     ret->orig = NULL;
  132.     table->nb_entities++;
  133.     return(ret);
  134. }
  135. /**
  136.  * xmlInitializePredefinedEntities:
  137.  *
  138.  * Set up the predefined entities.
  139.  */
  140. void xmlInitializePredefinedEntities(void) {
  141.     int i;
  142.     xmlChar name[50];
  143.     xmlChar value[50];
  144.     const char *in;
  145.     xmlChar *out;
  146.     if (xmlPredefinedEntities != NULL) return;
  147.     xmlPredefinedEntities = xmlCreateEntitiesTable();
  148.     for (i = 0;i < sizeof(xmlPredefinedEntityValues) / 
  149.                    sizeof(xmlPredefinedEntityValues[0]);i++) {
  150.         in = xmlPredefinedEntityValues[i].name;
  151. out = &name[0];
  152. for (;(*out++ = (xmlChar) *in);)in++;
  153.         in = xmlPredefinedEntityValues[i].value;
  154. out = &value[0];
  155. for (;(*out++ = (xmlChar) *in);)in++;
  156.         xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
  157.              XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
  158.      &value[0]);
  159.     }
  160. }
  161. /**
  162.  * xmlCleanupPredefinedEntities:
  163.  *
  164.  * Cleanup up the predefined entities table.
  165.  */
  166. void xmlCleanupPredefinedEntities(void) {
  167.     if (xmlPredefinedEntities == NULL) return;
  168.     xmlFreeEntitiesTable(xmlPredefinedEntities);
  169.     xmlPredefinedEntities = NULL;
  170. }
  171. /**
  172.  * xmlGetPredefinedEntity:
  173.  * @name:  the entity name
  174.  *
  175.  * Check whether this name is an predefined entity.
  176.  *
  177.  * Returns NULL if not, othervise the entity
  178.  */
  179. xmlEntityPtr
  180. xmlGetPredefinedEntity(const xmlChar *name) {
  181.     int i;
  182.     xmlEntityPtr cur;
  183.     if (xmlPredefinedEntities == NULL)
  184.         xmlInitializePredefinedEntities();
  185.     for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
  186. cur = xmlPredefinedEntities->table[i];
  187. if (!xmlStrcmp(cur->name, name)) return(cur);
  188.     }
  189.     return(NULL);
  190. }
  191. /**
  192.  * xmlAddDtdEntity:
  193.  * @doc:  the document
  194.  * @name:  the entity name
  195.  * @type:  the entity type XML_xxx_yyy_ENTITY
  196.  * @ExternalID:  the entity external ID if available
  197.  * @SystemID:  the entity system ID if available
  198.  * @content:  the entity content
  199.  *
  200.  * Register a new entity for this document DTD external subset.
  201.  *
  202.  * Returns a pointer to the entity or NULL in case of error
  203.  */
  204. xmlEntityPtr
  205. xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
  206.         const xmlChar *ExternalID, const xmlChar *SystemID,
  207. const xmlChar *content) {
  208.     xmlEntitiesTablePtr table;
  209.     xmlEntityPtr ret;
  210.     xmlDtdPtr dtd;
  211.     if (doc == NULL) {
  212.         fprintf(stderr,
  213.         "xmlAddDtdEntity: doc == NULL !n");
  214. return(NULL);
  215.     }
  216.     if (doc->extSubset == NULL) {
  217.         fprintf(stderr,
  218.         "xmlAddDtdEntity: document without external subset !n");
  219. return(NULL);
  220.     }
  221.     dtd = doc->extSubset;
  222.     table = (xmlEntitiesTablePtr) dtd->entities;
  223.     if (table == NULL) {
  224.         table = xmlCreateEntitiesTable();
  225. dtd->entities = table;
  226.     }
  227.     ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
  228.     if (ret == NULL) return(NULL);
  229.     /*
  230.      * Link it to the Dtd
  231.      */
  232.     ret->parent = dtd;
  233.     ret->doc = dtd->doc;
  234.     if (dtd->last == NULL) {
  235. dtd->children = dtd->last = (xmlNodePtr) ret;
  236.     } else {
  237.         dtd->last->next = (xmlNodePtr) ret;
  238. ret->prev = dtd->last;
  239. dtd->last = (xmlNodePtr) ret;
  240.     }
  241.     return(ret);
  242. }
  243. /**
  244.  * xmlAddDocEntity:
  245.  * @doc:  the document
  246.  * @name:  the entity name
  247.  * @type:  the entity type XML_xxx_yyy_ENTITY
  248.  * @ExternalID:  the entity external ID if available
  249.  * @SystemID:  the entity system ID if available
  250.  * @content:  the entity content
  251.  *
  252.  * Register a new entity for this document.
  253.  *
  254.  * Returns a pointer to the entity or NULL in case of error
  255.  */
  256. xmlEntityPtr
  257. xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
  258.         const xmlChar *ExternalID, const xmlChar *SystemID,
  259.         const xmlChar *content) {
  260.     xmlEntitiesTablePtr table;
  261.     xmlEntityPtr ret;
  262.     xmlDtdPtr dtd;
  263.     if (doc == NULL) {
  264.         fprintf(stderr,
  265.         "xmlAddDocEntity: document is NULL !n");
  266. return(NULL);
  267.     }
  268.     if (doc->intSubset == NULL) {
  269.         fprintf(stderr,
  270.         "xmlAddDtdEntity: document without internal subset !n");
  271. return(NULL);
  272.     }
  273.     dtd = doc->intSubset;
  274.     table = (xmlEntitiesTablePtr) doc->intSubset->entities;
  275.     if (table == NULL) {
  276.         table = xmlCreateEntitiesTable();
  277. doc->intSubset->entities = table;
  278.     }
  279.     ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
  280.     if (ret == NULL) return(NULL);
  281.     /*
  282.      * Link it to the Dtd
  283.      */
  284.     ret->parent = dtd;
  285.     ret->doc = dtd->doc;
  286.     if (dtd->last == NULL) {
  287. dtd->children = dtd->last = (xmlNodePtr) ret;
  288.     } else {
  289. dtd->last->next = (xmlNodePtr) ret;
  290. ret->prev = dtd->last;
  291. dtd->last = (xmlNodePtr) ret;
  292.     }
  293.     return(ret);
  294. }
  295. #ifdef WITH_EXTRA_ENT_DETECT
  296. /**
  297.  * xmlEntityCheckReference:
  298.  * @ent:  an existing entity
  299.  * @to:  the entity name it's referencing
  300.  *
  301.  * Function to keep track of references and detect cycles (well formedness 
  302.  * errors !).
  303.  *
  304.  * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop 
  305.  *      detection.
  306.  */
  307. int
  308. xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
  309.     int i;
  310.     xmlDocPtr doc;
  311.     if (ent == NULL) return(-1);
  312.     if (to == NULL) return(-1);
  313.     doc = ent->doc;
  314.     if (doc == NULL) return(-1);
  315. #ifdef DEBUG_ENT_REF
  316.     printf("xmlEntityCheckReference(%s to %s)n", ent->name, to);
  317. #endif
  318.     /*
  319.      * Do a recursive checking
  320.      */
  321.     for (i = 0;i < ent->entNr;i++) {
  322. xmlEntityPtr indir = NULL;
  323. if (!xmlStrcmp(to, ent->entTab[i]))
  324.     return(1);
  325. switch (ent->etype) {
  326.             case XML_INTERNAL_GENERAL_ENTITY:
  327.             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  328. indir = xmlGetDocEntity(doc, ent->entTab[i]);
  329. break;
  330.             case XML_INTERNAL_PARAMETER_ENTITY:
  331.             case XML_EXTERNAL_PARAMETER_ENTITY:
  332. indir = xmlGetDtdEntity(doc, ent->entTab[i]);
  333. break;
  334.             case XML_INTERNAL_PREDEFINED_ENTITY:
  335.             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  336. break;
  337. }
  338. if (xmlEntityCheckReference(indir, to) == 1)
  339.     return(1);
  340.     }
  341.     return(0);
  342. }
  343. /**
  344.  * xmlEntityAddReference:
  345.  * @ent:  an existing entity
  346.  * @to:  the entity name it's referencing
  347.  *
  348.  * Function to register reuse of an existing entity from a (new) one
  349.  * Used to keep track of references and detect cycles (well formedness 
  350.  * errors !).
  351.  *
  352.  * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop 
  353.  *      detection.
  354.  */
  355. int
  356. xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
  357.     int i;
  358.     xmlDocPtr doc;
  359.     xmlEntityPtr indir = NULL;
  360.     if (ent == NULL) return(-1);
  361.     if (to == NULL) return(-1);
  362.     doc = ent->doc;
  363.     if (doc == NULL) return(-1);
  364. #ifdef DEBUG_ENT_REF
  365.     printf("xmlEntityAddReference(%s to %s)n", ent->name, to);
  366. #endif
  367.     if (ent->entTab == NULL) {
  368. ent->entNr = 0;
  369. ent->entMax = 5;
  370. ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
  371. if (ent->entTab == NULL) {
  372.     fprintf(stderr, "xmlEntityAddReference: out of memory !n");
  373.     return(-1);
  374. }
  375.     }
  376.     for (i = 0;i < ent->entNr;i++) {
  377. if (!xmlStrcmp(to, ent->entTab[i]))
  378.     return(0);
  379.     }
  380.     /*
  381.      * Do a recursive checking
  382.      */
  383.     switch (ent->etype) {
  384. case XML_INTERNAL_GENERAL_ENTITY:
  385. case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  386.     indir = xmlGetDocEntity(doc, to);
  387.     break;
  388. case XML_INTERNAL_PARAMETER_ENTITY:
  389. case XML_EXTERNAL_PARAMETER_ENTITY:
  390.     indir = xmlGetDtdEntity(doc, to);
  391.     break;
  392. case XML_INTERNAL_PREDEFINED_ENTITY:
  393. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  394.     break;
  395.     }
  396.     if ((indir != NULL) &&
  397. (xmlEntityCheckReference(indir, ent->name) == 1))
  398. return(1);
  399.     /*
  400.      * Add this to the list
  401.      */
  402.     if (ent->entMax <= ent->entNr) {
  403. ent->entMax *= 2;
  404. ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
  405.                               ent->entMax * sizeof(xmlChar *));
  406. if (ent->entTab == NULL) {
  407.     fprintf(stderr, "xmlEntityAddReference: out of memory !n");
  408.     return(-1);
  409. }
  410.     }
  411.     ent->entTab[ent->entNr++] = xmlStrdup(to);
  412.     return(0);
  413. }
  414. #endif
  415. /**
  416.  * xmlGetParameterEntity:
  417.  * @doc:  the document referencing the entity
  418.  * @name:  the entity name
  419.  *
  420.  * Do an entity lookup in the internal and external subsets and
  421.  * returns the corresponding parameter entity, if found.
  422.  * 
  423.  * Returns A pointer to the entity structure or NULL if not found.
  424.  */
  425. xmlEntityPtr
  426. xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
  427.     int i;
  428.     xmlEntityPtr cur;
  429.     xmlEntitiesTablePtr table;
  430.     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
  431. table = (xmlEntitiesTablePtr) doc->intSubset->entities;
  432. for (i = 0;i < table->nb_entities;i++) {
  433.     cur = table->table[i];
  434.     if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
  435.          (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
  436. (!xmlStrcmp(cur->name, name))) return(cur);
  437. }
  438.     }
  439.     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
  440. table = (xmlEntitiesTablePtr) doc->extSubset->entities;
  441. for (i = 0;i < table->nb_entities;i++) {
  442.     cur = table->table[i];
  443.     if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
  444.          (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
  445. (!xmlStrcmp(cur->name, name))) return(cur);
  446. }
  447.     }
  448.     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
  449. table = (xmlEntitiesTablePtr) doc->extSubset->entities;
  450. for (i = 0;i < table->nb_entities;i++) {
  451.     cur = table->table[i];
  452.     if (((cur->etype ==  XML_INTERNAL_PARAMETER_ENTITY) ||
  453.          (cur->etype ==  XML_EXTERNAL_PARAMETER_ENTITY)) &&
  454. (!xmlStrcmp(cur->name, name))) return(cur);
  455. }
  456.     }
  457.     return(NULL);
  458. }
  459. /**
  460.  * xmlGetDtdEntity:
  461.  * @doc:  the document referencing the entity
  462.  * @name:  the entity name
  463.  *
  464.  * Do an entity lookup in the Dtd entity hash table and
  465.  * returns the corresponding entity, if found.
  466.  * 
  467.  * Returns A pointer to the entity structure or NULL if not found.
  468.  */
  469. xmlEntityPtr
  470. xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
  471.     int i;
  472.     xmlEntityPtr cur;
  473.     xmlEntitiesTablePtr table;
  474.     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
  475. table = (xmlEntitiesTablePtr) doc->extSubset->entities;
  476. for (i = 0;i < table->nb_entities;i++) {
  477.     cur = table->table[i];
  478.     if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
  479.         (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
  480.         (!xmlStrcmp(cur->name, name))) return(cur);
  481. }
  482.     }
  483.     return(NULL);
  484. }
  485. /**
  486.  * xmlGetDocEntity:
  487.  * @doc:  the document referencing the entity
  488.  * @name:  the entity name
  489.  *
  490.  * Do an entity lookup in the document entity hash table and
  491.  * returns the corrsponding entity, otherwise a lookup is done
  492.  * in the predefined entities too.
  493.  * 
  494.  * Returns A pointer to the entity structure or NULL if not found.
  495.  */
  496. xmlEntityPtr
  497. xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
  498.     int i;
  499.     xmlEntityPtr cur;
  500.     xmlEntitiesTablePtr table;
  501.     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
  502. table = (xmlEntitiesTablePtr) doc->intSubset->entities;
  503. for (i = 0;i < table->nb_entities;i++) {
  504.     cur = table->table[i];
  505.     if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
  506.         (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
  507.         (!xmlStrcmp(cur->name, name))) return(cur);
  508. }
  509.     }
  510.     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
  511. table = (xmlEntitiesTablePtr) doc->extSubset->entities;
  512. for (i = 0;i < table->nb_entities;i++) {
  513.     cur = table->table[i];
  514.     if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
  515.         (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
  516.         (!xmlStrcmp(cur->name, name))) return(cur);
  517. }
  518.     }
  519.     if (xmlPredefinedEntities == NULL)
  520.         xmlInitializePredefinedEntities();
  521.     table = xmlPredefinedEntities;
  522.     for (i = 0;i < table->nb_entities;i++) {
  523. cur = table->table[i];
  524. if ((cur->etype !=  XML_INTERNAL_PARAMETER_ENTITY) &&
  525.     (cur->etype !=  XML_EXTERNAL_PARAMETER_ENTITY) &&
  526.     (!xmlStrcmp(cur->name, name))) return(cur);
  527.     }
  528.     return(NULL);
  529. }
  530. /*
  531.  * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
  532.  *                  | [#x10000-#x10FFFF]
  533.  * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
  534.  */
  535. #define IS_CHAR(c)
  536.     (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) ||
  537.      (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
  538. /*
  539.  * A buffer used for converting entities to their equivalent and back.
  540.  */
  541. static int buffer_size = 0;
  542. static xmlChar *buffer = NULL;
  543. int growBuffer(void) {
  544.     buffer_size *= 2;
  545.     buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
  546.     if (buffer == NULL) {
  547.         perror("realloc failed");
  548. return(-1);
  549.     }
  550.     return(0);
  551. }
  552. /**
  553.  * xmlEncodeEntities:
  554.  * @doc:  the document containing the string
  555.  * @input:  A string to convert to XML.
  556.  *
  557.  * Do a global encoding of a string, replacing the predefined entities
  558.  * and non ASCII values with their entities and CharRef counterparts.
  559.  *
  560.  * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
  561.  *       compatibility
  562.  *
  563.  * People must migrate their code to xmlEncodeEntitiesReentrant !
  564.  * This routine will issue a warning when encountered.
  565.  * 
  566.  * Returns A newly allocated string with the substitution done.
  567.  */
  568. const xmlChar *
  569. xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
  570.     const xmlChar *cur = input;
  571.     xmlChar *out = buffer;
  572.     static int warning = 1;
  573.     int html = 0;
  574.     if (warning) {
  575.     fprintf(stderr, "Deprecated API xmlEncodeEntities() usedn");
  576.     fprintf(stderr, "   change code to use xmlEncodeEntitiesReentrant()n");
  577.     warning = 0;
  578.     }
  579.     if (input == NULL) return(NULL);
  580.     if (doc != NULL)
  581.         html = (doc->type == XML_HTML_DOCUMENT_NODE);
  582.     if (buffer == NULL) {
  583.         buffer_size = 1000;
  584.         buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
  585. if (buffer == NULL) {
  586.     perror("malloc failed");
  587.             return(NULL);
  588. }
  589. out = buffer;
  590.     }
  591.     while (*cur != '') {
  592.         if (out - buffer > buffer_size - 100) {
  593.     int index = out - buffer;
  594.     growBuffer();
  595.     out = &buffer[index];
  596. }
  597. /*
  598.  * By default one have to encode at least '<', '>', '"' and '&' !
  599.  */
  600. if (*cur == '<') {
  601.     *out++ = '&';
  602.     *out++ = 'l';
  603.     *out++ = 't';
  604.     *out++ = ';';
  605. } else if (*cur == '>') {
  606.     *out++ = '&';
  607.     *out++ = 'g';
  608.     *out++ = 't';
  609.     *out++ = ';';
  610. } else if (*cur == '&') {
  611.     *out++ = '&';
  612.     *out++ = 'a';
  613.     *out++ = 'm';
  614.     *out++ = 'p';
  615.     *out++ = ';';
  616. } else if (*cur == '"') {
  617.     *out++ = '&';
  618.     *out++ = 'q';
  619.     *out++ = 'u';
  620.     *out++ = 'o';
  621.     *out++ = 't';
  622.     *out++ = ';';
  623. } else if ((*cur == ''') && (!html)) {
  624.     *out++ = '&';
  625.     *out++ = 'a';
  626.     *out++ = 'p';
  627.     *out++ = 'o';
  628.     *out++ = 's';
  629.     *out++ = ';';
  630. } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
  631.     (*cur == 'n') || (*cur == 'r') || (*cur == 't')) {
  632.     /*
  633.      * default case, just copy !
  634.      */
  635.     *out++ = *cur;
  636. #ifndef USE_UTF_8
  637. } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
  638.     char buf[10], *ptr;
  639. #ifdef HAVE_SNPRINTF
  640.     snprintf(buf, 9, "&#%d;", *cur);
  641. #else
  642.     sprintf(buf, "&#%d;", *cur);
  643. #endif
  644.             ptr = buf;
  645.     while (*ptr != 0) *out++ = *ptr++;
  646. #endif
  647. } else if (IS_CHAR(*cur)) {
  648.     char buf[10], *ptr;
  649. #ifdef HAVE_SNPRINTF
  650.     snprintf(buf, 9, "&#%d;", *cur);
  651. #else
  652.     sprintf(buf, "&#%d;", *cur);
  653. #endif
  654.             ptr = buf;
  655.     while (*ptr != 0) *out++ = *ptr++;
  656. }
  657. #if 0
  658. else {
  659.     /*
  660.      * default case, this is not a valid char !
  661.      * Skip it...
  662.      */
  663.     fprintf(stderr, "xmlEncodeEntities: invalid char %dn", (int) *cur);
  664. }
  665. #endif
  666. cur++;
  667.     }
  668.     *out++ = 0;
  669.     return(buffer);
  670. }
  671. /*
  672.  * Macro used to grow the current buffer.
  673.  */
  674. #define growBufferReentrant() {
  675.     buffer_size *= 2;
  676.     buffer = (xmlChar *)
  677.      xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
  678.     if (buffer == NULL) {
  679. perror("realloc failed");
  680. return(NULL);
  681.     }
  682. }
  683. /**
  684.  * xmlEncodeEntitiesReentrant:
  685.  * @doc:  the document containing the string
  686.  * @input:  A string to convert to XML.
  687.  *
  688.  * Do a global encoding of a string, replacing the predefined entities
  689.  * and non ASCII values with their entities and CharRef counterparts.
  690.  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
  691.  * must be deallocated.
  692.  *
  693.  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
  694.  *           get erroneous.
  695.  *
  696.  * Returns A newly allocated string with the substitution done.
  697.  */
  698. xmlChar *
  699. xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
  700.     const xmlChar *cur = input;
  701.     xmlChar *buffer = NULL;
  702.     xmlChar *out = NULL;
  703.     int buffer_size = 0;
  704.     int html = 0;
  705.     if (input == NULL) return(NULL);
  706.     if (doc != NULL)
  707.         html = (doc->type == XML_HTML_DOCUMENT_NODE);
  708.     /*
  709.      * allocate an translation buffer.
  710.      */
  711.     buffer_size = 1000;
  712.     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
  713.     if (buffer == NULL) {
  714. perror("malloc failed");
  715. return(NULL);
  716.     }
  717.     out = buffer;
  718.     while (*cur != '') {
  719.         if (out - buffer > buffer_size - 100) {
  720.     int index = out - buffer;
  721.     growBufferReentrant();
  722.     out = &buffer[index];
  723. }
  724. /*
  725.  * By default one have to encode at least '<', '>', '"' and '&' !
  726.  */
  727. if (*cur == '<') {
  728.     *out++ = '&';
  729.     *out++ = 'l';
  730.     *out++ = 't';
  731.     *out++ = ';';
  732. } else if (*cur == '>') {
  733.     *out++ = '&';
  734.     *out++ = 'g';
  735.     *out++ = 't';
  736.     *out++ = ';';
  737. } else if (*cur == '&') {
  738.     *out++ = '&';
  739.     *out++ = 'a';
  740.     *out++ = 'm';
  741.     *out++ = 'p';
  742.     *out++ = ';';
  743. } else if (*cur == '"') {
  744.     *out++ = '&';
  745.     *out++ = 'q';
  746.     *out++ = 'u';
  747.     *out++ = 'o';
  748.     *out++ = 't';
  749.     *out++ = ';';
  750. #if 0
  751. } else if ((*cur == ''') && (!html)) {
  752.     *out++ = '&';
  753.     *out++ = 'a';
  754.     *out++ = 'p';
  755.     *out++ = 'o';
  756.     *out++ = 's';
  757.     *out++ = ';';
  758. #endif
  759. } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
  760.     (*cur == 'n') || (*cur == 'r') || (*cur == 't')) {
  761.     /*
  762.      * default case, just copy !
  763.      */
  764.     *out++ = *cur;
  765. } else if (*cur >= 0x80) {
  766.     if (html) {
  767. char buf[15], *ptr;
  768. /*
  769.  * TODO: improve by searching in html40EntitiesTable
  770.  */
  771. #ifdef HAVE_SNPRINTF
  772. snprintf(buf, 9, "&#%d;", *cur);
  773. #else
  774. sprintf(buf, "&#%d;", *cur);
  775. #endif
  776. ptr = buf;
  777. while (*ptr != 0) *out++ = *ptr++;
  778.     } else if (doc->encoding != NULL) {
  779. /*
  780.  * TODO !!!
  781.  */
  782. *out++ = *cur;
  783.     } else {
  784. /*
  785.  * We assume we have UTF-8 input.
  786.  */
  787. char buf[10], *ptr;
  788. int val = 0, l = 1;
  789. if (*cur < 0xC0) {
  790.     fprintf(stderr,
  791.     "xmlEncodeEntitiesReentrant : input not UTF-8n");
  792.     doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
  793. #ifdef HAVE_SNPRINTF
  794.     snprintf(buf, 9, "&#%d;", *cur);
  795. #else
  796.     sprintf(buf, "&#%d;", *cur);
  797. #endif
  798.     ptr = buf;
  799.     while (*ptr != 0) *out++ = *ptr++;
  800.     continue;
  801. } else if (*cur < 0xE0) {
  802.                     val = (cur[0]) & 0x1F;
  803.     val <<= 6;
  804.     val |= (cur[1]) & 0x3F;
  805.     l = 2;
  806. } else if (*cur < 0xF0) {
  807.                     val = (cur[0]) & 0x0F;
  808.     val <<= 6;
  809.     val |= (cur[1]) & 0x3F;
  810.     val <<= 6;
  811.     val |= (cur[2]) & 0x3F;
  812.     l = 3;
  813. } else if (*cur < 0xF8) {
  814.                     val = (cur[0]) & 0x07;
  815.     val <<= 6;
  816.     val |= (cur[1]) & 0x3F;
  817.     val <<= 6;
  818.     val |= (cur[2]) & 0x3F;
  819.     val <<= 6;
  820.     val |= (cur[3]) & 0x3F;
  821.     l = 4;
  822. }
  823. if ((l == 1) || (!IS_CHAR(val))) {
  824.     fprintf(stderr,
  825. "xmlEncodeEntitiesReentrant : char out of rangen");
  826.     doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
  827. #ifdef HAVE_SNPRINTF
  828.     snprintf(buf, 9, "&#%d;", *cur);
  829. #else
  830.     sprintf(buf, "&#%d;", *cur);
  831. #endif
  832.     ptr = buf;
  833.     while (*ptr != 0) *out++ = *ptr++;
  834.     cur++;
  835.     continue;
  836. }
  837. /*
  838.  * We could do multiple things here. Just save as a char ref
  839.  */
  840. #ifdef HAVE_SNPRINTF
  841. snprintf(buf, 14, "&#x%X;", val);
  842. #else
  843. sprintf(buf, "&#x%X;", val);
  844. #endif
  845. buf[14] = 0;
  846. ptr = buf;
  847. while (*ptr != 0) *out++ = *ptr++;
  848. cur += l;
  849. continue;
  850.     }
  851. } else if (IS_CHAR(*cur)) {
  852.     char buf[10], *ptr;
  853. #ifdef HAVE_SNPRINTF
  854.     snprintf(buf, 9, "&#%d;", *cur);
  855. #else
  856.     sprintf(buf, "&#%d;", *cur);
  857. #endif
  858.             ptr = buf;
  859.     while (*ptr != 0) *out++ = *ptr++;
  860. }
  861. #if 0
  862. else {
  863.     /*
  864.      * default case, this is not a valid char !
  865.      * Skip it...
  866.      */
  867.     fprintf(stderr, "xmlEncodeEntities: invalid char %dn", (int) *cur);
  868. }
  869. #endif
  870. cur++;
  871.     }
  872.     *out++ = 0;
  873.     return(buffer);
  874. }
  875. /**
  876.  * xmlCreateEntitiesTable:
  877.  *
  878.  * create and initialize an empty entities hash table.
  879.  *
  880.  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
  881.  */
  882. xmlEntitiesTablePtr
  883. xmlCreateEntitiesTable(void) {
  884.     xmlEntitiesTablePtr ret;
  885.     ret = (xmlEntitiesTablePtr) 
  886.          xmlMalloc(sizeof(xmlEntitiesTable));
  887.     if (ret == NULL) {
  888.         fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failedn",
  889.         (long)sizeof(xmlEntitiesTable));
  890.         return(NULL);
  891.     }
  892.     ret->max_entities = XML_MIN_ENTITIES_TABLE;
  893.     ret->nb_entities = 0;
  894.     ret->table = (xmlEntityPtr *) 
  895.          xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
  896.     if (ret == NULL) {
  897.         fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failedn",
  898.         ret->max_entities * (long)sizeof(xmlEntityPtr));
  899. xmlFree(ret);
  900.         return(NULL);
  901.     }
  902.     return(ret);
  903. }
  904. /**
  905.  * xmlFreeEntitiesTable:
  906.  * @table:  An entity table
  907.  *
  908.  * Deallocate the memory used by an entities hash table.
  909.  */
  910. void
  911. xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
  912.     int i;
  913.     if (table == NULL) return;
  914.     for (i = 0;i < table->nb_entities;i++) {
  915.         xmlFreeEntity(table->table[i]);
  916.     }
  917.     xmlFree(table->table);
  918.     xmlFree(table);
  919. }
  920. /**
  921.  * xmlCopyEntitiesTable:
  922.  * @table:  An entity table
  923.  *
  924.  * Build a copy of an entity table.
  925.  * 
  926.  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
  927.  */
  928. xmlEntitiesTablePtr
  929. xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
  930.     xmlEntitiesTablePtr ret;
  931.     xmlEntityPtr cur, ent;
  932.     int i;
  933.     ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
  934.     if (ret == NULL) {
  935.         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !n");
  936. return(NULL);
  937.     }
  938.     ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
  939.                                             sizeof(xmlEntityPtr));
  940.     if (ret->table == NULL) {
  941.         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !n");
  942. xmlFree(ret);
  943. return(NULL);
  944.     }
  945.     ret->max_entities = table->max_entities;
  946.     ret->nb_entities = table->nb_entities;
  947.     for (i = 0;i < ret->nb_entities;i++) {
  948. cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
  949. if (cur == NULL) {
  950.     fprintf(stderr, "xmlCopyEntityTable: out of memory !n");
  951.     xmlFree(ret);
  952.     xmlFree(ret->table);
  953.     return(NULL);
  954. }
  955. memset(cur, 0, sizeof(xmlEntity));
  956. cur->type = XML_ELEMENT_DECL;
  957. ret->table[i] = cur;
  958. ent = table->table[i];
  959. cur->etype = ent->etype;
  960. if (ent->name != NULL)
  961.     cur->name = xmlStrdup(ent->name);
  962. if (ent->ExternalID != NULL)
  963.     cur->ExternalID = xmlStrdup(ent->ExternalID);
  964. if (ent->SystemID != NULL)
  965.     cur->SystemID = xmlStrdup(ent->SystemID);
  966. if (ent->content != NULL)
  967.     cur->content = xmlStrdup(ent->content);
  968. if (ent->orig != NULL)
  969.     cur->orig = xmlStrdup(ent->orig);
  970.     }
  971.     return(ret);
  972. }
  973. /**
  974.  * xmlDumpEntityDecl:
  975.  * @buf:  An XML buffer.
  976.  * @ent:  An entity table
  977.  *
  978.  * This will dump the content of the entity table as an XML DTD definition
  979.  */
  980. void
  981. xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
  982.     switch (ent->etype) {
  983. case XML_INTERNAL_GENERAL_ENTITY:
  984.     xmlBufferWriteChar(buf, "<!ENTITY ");
  985.     xmlBufferWriteCHAR(buf, ent->name);
  986.     xmlBufferWriteChar(buf, " ");
  987.     if (ent->orig != NULL)
  988. xmlBufferWriteQuotedString(buf, ent->orig);
  989.     else
  990. xmlBufferWriteQuotedString(buf, ent->content);
  991.     xmlBufferWriteChar(buf, ">n");
  992.     break;
  993. case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
  994.     xmlBufferWriteChar(buf, "<!ENTITY ");
  995.     xmlBufferWriteCHAR(buf, ent->name);
  996.     if (ent->ExternalID != NULL) {
  997.  xmlBufferWriteChar(buf, " PUBLIC ");
  998.  xmlBufferWriteQuotedString(buf, ent->ExternalID);
  999.  xmlBufferWriteChar(buf, " ");
  1000.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1001.     } else {
  1002.  xmlBufferWriteChar(buf, " SYSTEM ");
  1003.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1004.     }
  1005.     xmlBufferWriteChar(buf, ">n");
  1006.     break;
  1007. case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
  1008.     xmlBufferWriteChar(buf, "<!ENTITY ");
  1009.     xmlBufferWriteCHAR(buf, ent->name);
  1010.     if (ent->ExternalID != NULL) {
  1011.  xmlBufferWriteChar(buf, " PUBLIC ");
  1012.  xmlBufferWriteQuotedString(buf, ent->ExternalID);
  1013.  xmlBufferWriteChar(buf, " ");
  1014.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1015.     } else {
  1016.  xmlBufferWriteChar(buf, " SYSTEM ");
  1017.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1018.     }
  1019.     if (ent->content != NULL) { /* Should be true ! */
  1020. xmlBufferWriteChar(buf, " NDATA ");
  1021. if (ent->orig != NULL)
  1022.     xmlBufferWriteCHAR(buf, ent->orig);
  1023. else
  1024.     xmlBufferWriteCHAR(buf, ent->content);
  1025.     }
  1026.     xmlBufferWriteChar(buf, ">n");
  1027.     break;
  1028. case XML_INTERNAL_PARAMETER_ENTITY:
  1029.     xmlBufferWriteChar(buf, "<!ENTITY % ");
  1030.     xmlBufferWriteCHAR(buf, ent->name);
  1031.     xmlBufferWriteChar(buf, " ");
  1032.     if (ent->orig == NULL)
  1033. xmlBufferWriteQuotedString(buf, ent->content);
  1034.     else
  1035. xmlBufferWriteQuotedString(buf, ent->orig);
  1036.     xmlBufferWriteChar(buf, ">n");
  1037.     break;
  1038. case XML_EXTERNAL_PARAMETER_ENTITY:
  1039.     xmlBufferWriteChar(buf, "<!ENTITY % ");
  1040.     xmlBufferWriteCHAR(buf, ent->name);
  1041.     if (ent->ExternalID != NULL) {
  1042.  xmlBufferWriteChar(buf, " PUBLIC ");
  1043.  xmlBufferWriteQuotedString(buf, ent->ExternalID);
  1044.  xmlBufferWriteChar(buf, " ");
  1045.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1046.     } else {
  1047.  xmlBufferWriteChar(buf, " SYSTEM ");
  1048.  xmlBufferWriteQuotedString(buf, ent->SystemID);
  1049.     }
  1050.     xmlBufferWriteChar(buf, ">n");
  1051.     break;
  1052. default:
  1053.     fprintf(stderr,
  1054. "xmlDumpEntitiesTable: internal: unknown type %dn",
  1055.     ent->etype);
  1056.     }
  1057. }
  1058. /**
  1059.  * xmlDumpEntitiesTable:
  1060.  * @buf:  An XML buffer.
  1061.  * @table:  An entity table
  1062.  *
  1063.  * This will dump the content of the entity table as an XML DTD definition
  1064.  */
  1065. void
  1066. xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
  1067.     int i;
  1068.     xmlEntityPtr cur;
  1069.     if (table == NULL) return;
  1070.     for (i = 0;i < table->nb_entities;i++) {
  1071.         cur = table->table[i];
  1072. xmlDumpEntityDecl(buf, cur);
  1073.     }
  1074. }