2 * entities.c : implementation for the XML entities handling
4 * See Copyright for the status of this software.
9 /* To avoid EBCDIC trouble when parsing on zOS */
11 #pragma convert("ISO8859-1")
20 #include <libxml/xmlmemory.h>
21 #include <libxml/hash.h>
22 #include <libxml/entities.h>
23 #include <libxml/parser.h>
24 #include <libxml/parserInternals.h>
25 #include <libxml/xmlerror.h>
26 #include <libxml/globals.h>
27 #include <libxml/dict.h>
29 #include "private/entities.h"
30 #include "private/error.h"
33 * The XML predefined entities.
36 static xmlEntity xmlEntityLt
= {
37 NULL
, XML_ENTITY_DECL
, BAD_CAST
"lt",
38 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
39 BAD_CAST
"<", BAD_CAST
"<", 1,
40 XML_INTERNAL_PREDEFINED_ENTITY
,
41 NULL
, NULL
, NULL
, NULL
, 0, 0, 0
43 static xmlEntity xmlEntityGt
= {
44 NULL
, XML_ENTITY_DECL
, BAD_CAST
"gt",
45 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
46 BAD_CAST
">", BAD_CAST
">", 1,
47 XML_INTERNAL_PREDEFINED_ENTITY
,
48 NULL
, NULL
, NULL
, NULL
, 0, 0, 0
50 static xmlEntity xmlEntityAmp
= {
51 NULL
, XML_ENTITY_DECL
, BAD_CAST
"amp",
52 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
53 BAD_CAST
"&", BAD_CAST
"&", 1,
54 XML_INTERNAL_PREDEFINED_ENTITY
,
55 NULL
, NULL
, NULL
, NULL
, 0, 0, 0
57 static xmlEntity xmlEntityQuot
= {
58 NULL
, XML_ENTITY_DECL
, BAD_CAST
"quot",
59 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
60 BAD_CAST
"\"", BAD_CAST
"\"", 1,
61 XML_INTERNAL_PREDEFINED_ENTITY
,
62 NULL
, NULL
, NULL
, NULL
, 0, 0, 0
64 static xmlEntity xmlEntityApos
= {
65 NULL
, XML_ENTITY_DECL
, BAD_CAST
"apos",
66 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
67 BAD_CAST
"'", BAD_CAST
"'", 1,
68 XML_INTERNAL_PREDEFINED_ENTITY
,
69 NULL
, NULL
, NULL
, NULL
, 0, 0, 0
73 * xmlEntitiesErrMemory:
74 * @extra: extra information
76 * Handle an out of memory condition
79 xmlEntitiesErrMemory(const char *extra
)
81 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
86 * @code: the error code
91 static void LIBXML_ATTR_FORMAT(2,0)
92 xmlEntitiesErr(xmlParserErrors code
, const char *msg
)
94 __xmlSimpleError(XML_FROM_TREE
, code
, NULL
, msg
, NULL
);
99 * @code: the error code
104 static void LIBXML_ATTR_FORMAT(2,0)
105 xmlEntitiesWarn(xmlParserErrors code
, const char *msg
, const xmlChar
*str1
)
107 __xmlRaiseError(NULL
, NULL
, NULL
,
108 NULL
, NULL
, XML_FROM_TREE
, code
,
109 XML_ERR_WARNING
, NULL
, 0,
110 (const char *)str1
, NULL
, NULL
, 0, 0,
111 msg
, (const char *)str1
, NULL
);
115 * xmlFreeEntity : clean-up an entity record.
118 xmlFreeEntity(xmlEntityPtr entity
)
120 xmlDictPtr dict
= NULL
;
125 if (entity
->doc
!= NULL
)
126 dict
= entity
->doc
->dict
;
129 if ((entity
->children
) && (entity
->owner
== 1) &&
130 (entity
== (xmlEntityPtr
) entity
->children
->parent
))
131 xmlFreeNodeList(entity
->children
);
132 if ((entity
->name
!= NULL
) &&
133 ((dict
== NULL
) || (!xmlDictOwns(dict
, entity
->name
))))
134 xmlFree((char *) entity
->name
);
135 if (entity
->ExternalID
!= NULL
)
136 xmlFree((char *) entity
->ExternalID
);
137 if (entity
->SystemID
!= NULL
)
138 xmlFree((char *) entity
->SystemID
);
139 if (entity
->URI
!= NULL
)
140 xmlFree((char *) entity
->URI
);
141 if (entity
->content
!= NULL
)
142 xmlFree((char *) entity
->content
);
143 if (entity
->orig
!= NULL
)
144 xmlFree((char *) entity
->orig
);
151 * internal routine doing the entity node structures allocations
154 xmlCreateEntity(xmlDictPtr dict
, const xmlChar
*name
, int type
,
155 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
156 const xmlChar
*content
) {
159 ret
= (xmlEntityPtr
) xmlMalloc(sizeof(xmlEntity
));
161 xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
164 memset(ret
, 0, sizeof(xmlEntity
));
165 ret
->type
= XML_ENTITY_DECL
;
168 * fill the structure.
170 ret
->etype
= (xmlEntityType
) type
;
172 ret
->name
= xmlStrdup(name
);
173 if (ExternalID
!= NULL
)
174 ret
->ExternalID
= xmlStrdup(ExternalID
);
175 if (SystemID
!= NULL
)
176 ret
->SystemID
= xmlStrdup(SystemID
);
178 ret
->name
= xmlDictLookup(dict
, name
, -1);
179 ret
->ExternalID
= xmlStrdup(ExternalID
);
180 ret
->SystemID
= xmlStrdup(SystemID
);
182 if (content
!= NULL
) {
183 ret
->length
= xmlStrlen(content
);
184 ret
->content
= xmlStrndup(content
, ret
->length
);
189 ret
->URI
= NULL
; /* to be computed by the layer knowing
190 the defining entity */
198 * xmlAddEntity : register a new entity for an entities table.
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
, predef
;
212 if (dtd
->doc
!= NULL
)
213 dict
= dtd
->doc
->dict
;
216 case XML_INTERNAL_GENERAL_ENTITY
:
217 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
218 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
219 predef
= xmlGetPredefinedEntity(name
);
220 if (predef
!= NULL
) {
223 /* 4.6 Predefined Entities */
224 if ((type
== XML_INTERNAL_GENERAL_ENTITY
) &&
226 int c
= predef
->content
[0];
228 if (((content
[0] == c
) && (content
[1] == 0)) &&
229 ((c
== '>') || (c
== '\'') || (c
== '"'))) {
231 } else if ((content
[0] == '&') && (content
[1] == '#')) {
232 if (content
[2] == 'x') {
233 xmlChar
*hex
= BAD_CAST
"0123456789ABCDEF";
234 xmlChar ref
[] = "00;";
236 ref
[0] = hex
[c
/ 16 % 16];
237 ref
[1] = hex
[c
% 16];
238 if (xmlStrcasecmp(&content
[3], ref
) == 0)
241 xmlChar ref
[] = "00;";
243 ref
[0] = '0' + c
/ 10 % 10;
244 ref
[1] = '0' + c
% 10;
245 if (xmlStrEqual(&content
[2], ref
))
251 xmlEntitiesWarn(XML_ERR_ENTITY_PROCESSING
,
252 "xmlAddEntity: invalid redeclaration of predefined"
253 " entity '%s'", name
);
257 if (dtd
->entities
== NULL
)
258 dtd
->entities
= xmlHashCreateDict(0, dict
);
259 table
= dtd
->entities
;
261 case XML_INTERNAL_PARAMETER_ENTITY
:
262 case XML_EXTERNAL_PARAMETER_ENTITY
:
263 if (dtd
->pentities
== NULL
)
264 dtd
->pentities
= xmlHashCreateDict(0, dict
);
265 table
= dtd
->pentities
;
267 case XML_INTERNAL_PREDEFINED_ENTITY
:
272 ret
= xmlCreateEntity(dict
, name
, type
, ExternalID
, SystemID
, content
);
277 if (xmlHashAddEntry(table
, name
, ret
)) {
279 * entity was already defined at another level.
288 * xmlGetPredefinedEntity:
289 * @name: the entity name
291 * Check whether this name is an predefined entity.
293 * Returns NULL if not, otherwise the entity
296 xmlGetPredefinedEntity(const xmlChar
*name
) {
297 if (name
== NULL
) return(NULL
);
300 if (xmlStrEqual(name
, BAD_CAST
"lt"))
301 return(&xmlEntityLt
);
304 if (xmlStrEqual(name
, BAD_CAST
"gt"))
305 return(&xmlEntityGt
);
308 if (xmlStrEqual(name
, BAD_CAST
"amp"))
309 return(&xmlEntityAmp
);
310 if (xmlStrEqual(name
, BAD_CAST
"apos"))
311 return(&xmlEntityApos
);
314 if (xmlStrEqual(name
, BAD_CAST
"quot"))
315 return(&xmlEntityQuot
);
326 * @name: the entity name
327 * @type: the entity type XML_xxx_yyy_ENTITY
328 * @ExternalID: the entity external ID if available
329 * @SystemID: the entity system ID if available
330 * @content: the entity content
332 * Register a new entity for this document DTD external subset.
334 * Returns a pointer to the entity or NULL in case of error
337 xmlAddDtdEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
338 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
339 const xmlChar
*content
) {
344 xmlEntitiesErr(XML_DTD_NO_DOC
,
345 "xmlAddDtdEntity: document is NULL");
348 if (doc
->extSubset
== NULL
) {
349 xmlEntitiesErr(XML_DTD_NO_DTD
,
350 "xmlAddDtdEntity: document without external subset");
353 dtd
= doc
->extSubset
;
354 ret
= xmlAddEntity(dtd
, name
, type
, ExternalID
, SystemID
, content
);
355 if (ret
== NULL
) return(NULL
);
362 if (dtd
->last
== NULL
) {
363 dtd
->children
= dtd
->last
= (xmlNodePtr
) ret
;
365 dtd
->last
->next
= (xmlNodePtr
) ret
;
366 ret
->prev
= dtd
->last
;
367 dtd
->last
= (xmlNodePtr
) ret
;
375 * @name: the entity name
376 * @type: the entity type XML_xxx_yyy_ENTITY
377 * @ExternalID: the entity external ID if available
378 * @SystemID: the entity system ID if available
379 * @content: the entity content
381 * Register a new entity for this document.
383 * Returns a pointer to the entity or NULL in case of error
386 xmlAddDocEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
387 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
388 const xmlChar
*content
) {
393 xmlEntitiesErr(XML_DTD_NO_DOC
,
394 "xmlAddDocEntity: document is NULL");
397 if (doc
->intSubset
== NULL
) {
398 xmlEntitiesErr(XML_DTD_NO_DTD
,
399 "xmlAddDocEntity: document without internal subset");
402 dtd
= doc
->intSubset
;
403 ret
= xmlAddEntity(dtd
, name
, type
, ExternalID
, SystemID
, content
);
404 if (ret
== NULL
) return(NULL
);
411 if (dtd
->last
== NULL
) {
412 dtd
->children
= dtd
->last
= (xmlNodePtr
) ret
;
414 dtd
->last
->next
= (xmlNodePtr
) ret
;
415 ret
->prev
= dtd
->last
;
416 dtd
->last
= (xmlNodePtr
) ret
;
424 * @name: the entity name
425 * @type: the entity type XML_xxx_yyy_ENTITY
426 * @ExternalID: the entity external ID if available
427 * @SystemID: the entity system ID if available
428 * @content: the entity content
430 * Create a new entity, this differs from xmlAddDocEntity() that if
431 * the document is NULL or has no internal subset defined, then an
432 * unlinked entity structure will be returned, it is then the responsibility
433 * of the caller to link it to the document later or free it when not needed
436 * Returns a pointer to the entity or NULL in case of error
439 xmlNewEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
440 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
441 const xmlChar
*content
) {
445 if ((doc
!= NULL
) && (doc
->intSubset
!= NULL
)) {
446 return(xmlAddDocEntity(doc
, name
, type
, ExternalID
, SystemID
, content
));
452 ret
= xmlCreateEntity(dict
, name
, type
, ExternalID
, SystemID
, content
);
460 * xmlGetEntityFromTable:
461 * @table: an entity table
462 * @name: the entity name
463 * @parameter: look for parameter entities
465 * Do an entity lookup in the table.
466 * returns the corresponding parameter entity, if found.
468 * Returns A pointer to the entity structure or NULL if not found.
471 xmlGetEntityFromTable(xmlEntitiesTablePtr table
, const xmlChar
*name
) {
472 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
476 * xmlGetParameterEntity:
477 * @doc: the document referencing the entity
478 * @name: the entity name
480 * Do an entity lookup in the internal and external subsets and
481 * returns the corresponding parameter entity, if found.
483 * Returns A pointer to the entity structure or NULL if not found.
486 xmlGetParameterEntity(xmlDocPtr doc
, const xmlChar
*name
) {
487 xmlEntitiesTablePtr table
;
492 if ((doc
->intSubset
!= NULL
) && (doc
->intSubset
->pentities
!= NULL
)) {
493 table
= (xmlEntitiesTablePtr
) doc
->intSubset
->pentities
;
494 ret
= xmlGetEntityFromTable(table
, name
);
498 if ((doc
->extSubset
!= NULL
) && (doc
->extSubset
->pentities
!= NULL
)) {
499 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->pentities
;
500 return(xmlGetEntityFromTable(table
, name
));
507 * @doc: the document referencing the entity
508 * @name: the entity name
510 * Do an entity lookup in the DTD entity hash table and
511 * returns the corresponding entity, if found.
512 * Note: the first argument is the document node, not the DTD node.
514 * Returns A pointer to the entity structure or NULL if not found.
517 xmlGetDtdEntity(xmlDocPtr doc
, const xmlChar
*name
) {
518 xmlEntitiesTablePtr table
;
522 if ((doc
->extSubset
!= NULL
) && (doc
->extSubset
->entities
!= NULL
)) {
523 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->entities
;
524 return(xmlGetEntityFromTable(table
, name
));
531 * @doc: the document referencing the entity
532 * @name: the entity name
534 * Do an entity lookup in the document entity hash table and
535 * returns the corresponding entity, otherwise a lookup is done
536 * in the predefined entities too.
538 * Returns A pointer to the entity structure or NULL if not found.
541 xmlGetDocEntity(const xmlDoc
*doc
, const xmlChar
*name
) {
543 xmlEntitiesTablePtr table
;
546 if ((doc
->intSubset
!= NULL
) && (doc
->intSubset
->entities
!= NULL
)) {
547 table
= (xmlEntitiesTablePtr
) doc
->intSubset
->entities
;
548 cur
= xmlGetEntityFromTable(table
, name
);
552 if (doc
->standalone
!= 1) {
553 if ((doc
->extSubset
!= NULL
) &&
554 (doc
->extSubset
->entities
!= NULL
)) {
555 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->entities
;
556 cur
= xmlGetEntityFromTable(table
, name
);
562 return(xmlGetPredefinedEntity(name
));
566 * Macro used to grow the current buffer.
568 #define growBufferReentrant() { \
570 size_t new_size = buffer_size * 2; \
571 if (new_size < buffer_size) goto mem_error; \
572 tmp = (xmlChar *) xmlRealloc(buffer, new_size); \
573 if (tmp == NULL) goto mem_error; \
575 buffer_size = new_size; \
579 * xmlEncodeEntitiesInternal:
580 * @doc: the document containing the string
581 * @input: A string to convert to XML.
582 * @attr: are we handling an attribute value
584 * Do a global encoding of a string, replacing the predefined entities
585 * and non ASCII values with their entities and CharRef counterparts.
586 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
587 * must be deallocated.
589 * Returns A newly allocated string with the substitution done.
592 xmlEncodeEntitiesInternal(xmlDocPtr doc
, const xmlChar
*input
, int attr
) {
593 const xmlChar
*cur
= input
;
594 xmlChar
*buffer
= NULL
;
596 size_t buffer_size
= 0;
599 if (input
== NULL
) return(NULL
);
601 html
= (doc
->type
== XML_HTML_DOCUMENT_NODE
);
604 * allocate an translation buffer.
607 buffer
= (xmlChar
*) xmlMalloc(buffer_size
);
608 if (buffer
== NULL
) {
609 xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed");
614 while (*cur
!= '\0') {
615 size_t indx
= out
- buffer
;
616 if (indx
+ 100 > buffer_size
) {
618 growBufferReentrant();
623 * By default one have to encode at least '<', '>', '"' and '&' !
629 * Special handling of server side include in HTML attributes
632 (cur
[1] == '!') && (cur
[2] == '-') && (cur
[3] == '-') &&
633 ((end
= xmlStrstr(cur
, BAD_CAST
"-->")) != NULL
)) {
637 if (indx
+ 100 > buffer_size
) {
638 growBufferReentrant();
651 } else if (*cur
== '>') {
656 } else if (*cur
== '&') {
658 * Special handling of &{...} construct from HTML 4, see
659 * http://www.w3.org/TR/html401/appendix/notes.html#h-B.7.1
661 if (html
&& attr
&& (cur
[1] == '{') &&
662 (strchr((const char *) cur
, '}'))) {
663 while (*cur
!= '}') {
666 if (indx
+ 100 > buffer_size
) {
667 growBufferReentrant();
679 } else if (((*cur
>= 0x20) && (*cur
< 0x80)) ||
680 (*cur
== '\n') || (*cur
== '\t') || ((html
) && (*cur
== '\r'))) {
682 * default case, just copy !
685 } else if (*cur
>= 0x80) {
686 if (((doc
!= NULL
) && (doc
->encoding
!= NULL
)) || (html
)) {
688 * Bjørn Reese <br@sseusa.com> provided the patch
690 xc = (*cur & 0x3F) << 6;
692 xc += *(++cur) & 0x3F;
699 * We assume we have UTF-8 input.
700 * It must match either:
702 * 1110xxxx 10xxxxxx 10xxxxxx
703 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
707 * cur[2] is 10xxxxxx if cur[0] is 111xxxxx
708 * cur[3] is 10xxxxxx if cur[0] is 1111xxxx
709 * cur[0] is not 11111xxx
714 if (((cur
[0] & 0xC0) != 0xC0) ||
715 ((cur
[1] & 0xC0) != 0x80) ||
716 (((cur
[0] & 0xE0) == 0xE0) && ((cur
[2] & 0xC0) != 0x80)) ||
717 (((cur
[0] & 0xF0) == 0xF0) && ((cur
[3] & 0xC0) != 0x80)) ||
718 (((cur
[0] & 0xF8) == 0xF8))) {
719 xmlEntitiesErr(XML_CHECK_NOT_UTF8
,
720 "xmlEncodeEntities: input not UTF-8");
722 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
723 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
724 buf
[sizeof(buf
) - 1] = 0;
726 while (*ptr
!= 0) *out
++ = *ptr
++;
729 } else if (*cur
< 0xE0) {
730 val
= (cur
[0]) & 0x1F;
732 val
|= (cur
[1]) & 0x3F;
734 } else if (*cur
< 0xF0) {
735 val
= (cur
[0]) & 0x0F;
737 val
|= (cur
[1]) & 0x3F;
739 val
|= (cur
[2]) & 0x3F;
741 } else if (*cur
< 0xF8) {
742 val
= (cur
[0]) & 0x07;
744 val
|= (cur
[1]) & 0x3F;
746 val
|= (cur
[2]) & 0x3F;
748 val
|= (cur
[3]) & 0x3F;
751 if ((l
== 1) || (!IS_CHAR(val
))) {
752 xmlEntitiesErr(XML_ERR_INVALID_CHAR
,
753 "xmlEncodeEntities: char out of range\n");
755 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
756 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
757 buf
[sizeof(buf
) - 1] = 0;
759 while (*ptr
!= 0) *out
++ = *ptr
++;
764 * We could do multiple things here. Just save as a char ref
766 snprintf(buf
, sizeof(buf
), "&#x%X;", val
);
767 buf
[sizeof(buf
) - 1] = 0;
769 while (*ptr
!= 0) *out
++ = *ptr
++;
773 } else if (IS_BYTE_CHAR(*cur
)) {
776 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
777 buf
[sizeof(buf
) - 1] = 0;
779 while (*ptr
!= 0) *out
++ = *ptr
++;
787 xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed");
793 * xmlEncodeAttributeEntities:
794 * @doc: the document containing the string
795 * @input: A string to convert to XML.
797 * Do a global encoding of a string, replacing the predefined entities
798 * and non ASCII values with their entities and CharRef counterparts for
801 * Returns A newly allocated string with the substitution done.
804 xmlEncodeAttributeEntities(xmlDocPtr doc
, const xmlChar
*input
) {
805 return xmlEncodeEntitiesInternal(doc
, input
, 1);
809 * xmlEncodeEntitiesReentrant:
810 * @doc: the document containing the string
811 * @input: A string to convert to XML.
813 * Do a global encoding of a string, replacing the predefined entities
814 * and non ASCII values with their entities and CharRef counterparts.
815 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
816 * must be deallocated.
818 * Returns A newly allocated string with the substitution done.
821 xmlEncodeEntitiesReentrant(xmlDocPtr doc
, const xmlChar
*input
) {
822 return xmlEncodeEntitiesInternal(doc
, input
, 0);
826 * xmlEncodeSpecialChars:
827 * @doc: the document containing the string
828 * @input: A string to convert to XML.
830 * Do a global encoding of a string, replacing the predefined entities
831 * this routine is reentrant, and result must be deallocated.
833 * Returns A newly allocated string with the substitution done.
836 xmlEncodeSpecialChars(const xmlDoc
*doc ATTRIBUTE_UNUSED
, const xmlChar
*input
) {
837 const xmlChar
*cur
= input
;
838 xmlChar
*buffer
= NULL
;
840 size_t buffer_size
= 0;
841 if (input
== NULL
) return(NULL
);
844 * allocate an translation buffer.
847 buffer
= (xmlChar
*) xmlMalloc(buffer_size
);
848 if (buffer
== NULL
) {
849 xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed");
854 while (*cur
!= '\0') {
855 size_t indx
= out
- buffer
;
856 if (indx
+ 10 > buffer_size
) {
858 growBufferReentrant();
863 * By default one have to encode at least '<', '>', '"' and '&' !
870 } else if (*cur
== '>') {
875 } else if (*cur
== '&') {
881 } else if (*cur
== '"') {
888 } else if (*cur
== '\r') {
896 * Works because on UTF-8, all extended sequences cannot
897 * result in bytes in the ASCII range.
907 xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
913 * xmlCreateEntitiesTable:
915 * create and initialize an empty entities hash table.
916 * This really doesn't make sense and should be deprecated
918 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
921 xmlCreateEntitiesTable(void) {
922 return((xmlEntitiesTablePtr
) xmlHashCreate(0));
926 * xmlFreeEntityWrapper:
930 * Deallocate the memory used by an entities in the hash table.
933 xmlFreeEntityWrapper(void *entity
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
935 xmlFreeEntity((xmlEntityPtr
) entity
);
939 * xmlFreeEntitiesTable:
940 * @table: An entity table
942 * Deallocate the memory used by an entities hash table.
945 xmlFreeEntitiesTable(xmlEntitiesTablePtr table
) {
946 xmlHashFree(table
, xmlFreeEntityWrapper
);
949 #ifdef LIBXML_TREE_ENABLED
954 * Build a copy of an entity
956 * Returns the new xmlEntitiesPtr or NULL in case of error.
959 xmlCopyEntity(void *payload
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
960 xmlEntityPtr ent
= (xmlEntityPtr
) payload
;
963 cur
= (xmlEntityPtr
) xmlMalloc(sizeof(xmlEntity
));
965 xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed");
968 memset(cur
, 0, sizeof(xmlEntity
));
969 cur
->type
= XML_ENTITY_DECL
;
971 cur
->etype
= ent
->etype
;
972 if (ent
->name
!= NULL
)
973 cur
->name
= xmlStrdup(ent
->name
);
974 if (ent
->ExternalID
!= NULL
)
975 cur
->ExternalID
= xmlStrdup(ent
->ExternalID
);
976 if (ent
->SystemID
!= NULL
)
977 cur
->SystemID
= xmlStrdup(ent
->SystemID
);
978 if (ent
->content
!= NULL
)
979 cur
->content
= xmlStrdup(ent
->content
);
980 if (ent
->orig
!= NULL
)
981 cur
->orig
= xmlStrdup(ent
->orig
);
982 if (ent
->URI
!= NULL
)
983 cur
->URI
= xmlStrdup(ent
->URI
);
988 * xmlCopyEntitiesTable:
989 * @table: An entity table
991 * Build a copy of an entity table.
993 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
996 xmlCopyEntitiesTable(xmlEntitiesTablePtr table
) {
997 return(xmlHashCopy(table
, xmlCopyEntity
));
999 #endif /* LIBXML_TREE_ENABLED */
1001 #ifdef LIBXML_OUTPUT_ENABLED
1004 * xmlDumpEntityContent:
1005 * @buf: An XML buffer.
1006 * @content: The entity content.
1008 * This will dump the quoted string value, taking care of the special
1009 * treatment required by %
1012 xmlDumpEntityContent(xmlBufferPtr buf
, const xmlChar
*content
) {
1013 if (xmlStrchr(content
, '%')) {
1014 const xmlChar
* base
, *cur
;
1016 xmlBufferCCat(buf
, "\"");
1017 base
= cur
= content
;
1021 xmlBufferAdd(buf
, base
, cur
- base
);
1022 xmlBufferAdd(buf
, BAD_CAST
""", 6);
1025 } else if (*cur
== '%') {
1027 xmlBufferAdd(buf
, base
, cur
- base
);
1028 xmlBufferAdd(buf
, BAD_CAST
"%", 6);
1036 xmlBufferAdd(buf
, base
, cur
- base
);
1037 xmlBufferCCat(buf
, "\"");
1039 xmlBufferWriteQuotedString(buf
, content
);
1044 * xmlDumpEntityDecl:
1045 * @buf: An XML buffer.
1046 * @ent: An entity table
1048 * This will dump the content of the entity table as an XML DTD definition
1051 xmlDumpEntityDecl(xmlBufferPtr buf
, xmlEntityPtr ent
) {
1052 if ((buf
== NULL
) || (ent
== NULL
)) return;
1053 switch (ent
->etype
) {
1054 case XML_INTERNAL_GENERAL_ENTITY
:
1055 xmlBufferWriteChar(buf
, "<!ENTITY ");
1056 xmlBufferWriteCHAR(buf
, ent
->name
);
1057 xmlBufferWriteChar(buf
, " ");
1058 if (ent
->orig
!= NULL
)
1059 xmlBufferWriteQuotedString(buf
, ent
->orig
);
1061 xmlDumpEntityContent(buf
, ent
->content
);
1062 xmlBufferWriteChar(buf
, ">\n");
1064 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
1065 xmlBufferWriteChar(buf
, "<!ENTITY ");
1066 xmlBufferWriteCHAR(buf
, ent
->name
);
1067 if (ent
->ExternalID
!= NULL
) {
1068 xmlBufferWriteChar(buf
, " PUBLIC ");
1069 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1070 xmlBufferWriteChar(buf
, " ");
1071 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1073 xmlBufferWriteChar(buf
, " SYSTEM ");
1074 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1076 xmlBufferWriteChar(buf
, ">\n");
1078 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
1079 xmlBufferWriteChar(buf
, "<!ENTITY ");
1080 xmlBufferWriteCHAR(buf
, ent
->name
);
1081 if (ent
->ExternalID
!= NULL
) {
1082 xmlBufferWriteChar(buf
, " PUBLIC ");
1083 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1084 xmlBufferWriteChar(buf
, " ");
1085 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1087 xmlBufferWriteChar(buf
, " SYSTEM ");
1088 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1090 if (ent
->content
!= NULL
) { /* Should be true ! */
1091 xmlBufferWriteChar(buf
, " NDATA ");
1092 if (ent
->orig
!= NULL
)
1093 xmlBufferWriteCHAR(buf
, ent
->orig
);
1095 xmlBufferWriteCHAR(buf
, ent
->content
);
1097 xmlBufferWriteChar(buf
, ">\n");
1099 case XML_INTERNAL_PARAMETER_ENTITY
:
1100 xmlBufferWriteChar(buf
, "<!ENTITY % ");
1101 xmlBufferWriteCHAR(buf
, ent
->name
);
1102 xmlBufferWriteChar(buf
, " ");
1103 if (ent
->orig
== NULL
)
1104 xmlDumpEntityContent(buf
, ent
->content
);
1106 xmlBufferWriteQuotedString(buf
, ent
->orig
);
1107 xmlBufferWriteChar(buf
, ">\n");
1109 case XML_EXTERNAL_PARAMETER_ENTITY
:
1110 xmlBufferWriteChar(buf
, "<!ENTITY % ");
1111 xmlBufferWriteCHAR(buf
, ent
->name
);
1112 if (ent
->ExternalID
!= NULL
) {
1113 xmlBufferWriteChar(buf
, " PUBLIC ");
1114 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1115 xmlBufferWriteChar(buf
, " ");
1116 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1118 xmlBufferWriteChar(buf
, " SYSTEM ");
1119 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1121 xmlBufferWriteChar(buf
, ">\n");
1124 xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY
,
1125 "xmlDumpEntitiesDecl: internal: unknown type entity type");
1130 * xmlDumpEntityDeclScan:
1131 * @ent: An entity table
1132 * @buf: An XML buffer.
1134 * When using the hash table scan function, arguments need to be reversed
1137 xmlDumpEntityDeclScan(void *ent
, void *buf
,
1138 const xmlChar
*name ATTRIBUTE_UNUSED
) {
1139 xmlDumpEntityDecl((xmlBufferPtr
) buf
, (xmlEntityPtr
) ent
);
1143 * xmlDumpEntitiesTable:
1144 * @buf: An XML buffer.
1145 * @table: An entity table
1147 * This will dump the content of the entity table as an XML DTD definition
1150 xmlDumpEntitiesTable(xmlBufferPtr buf
, xmlEntitiesTablePtr table
) {
1151 xmlHashScan(table
, xmlDumpEntityDeclScan
, buf
);
1153 #endif /* LIBXML_OUTPUT_ENABLED */