2001-02-23 17:55:21 +00:00
/*
2001-12-31 16:16:02 +00:00
* entities . c : implementation for the XML entities handling
2001-02-23 17:55:21 +00:00
*
* See Copyright for the status of this software .
*
2001-06-24 12:13:24 +00:00
* daniel @ veillard . com
2001-02-23 17:55:21 +00:00
*/
2002-03-18 19:37:11 +00:00
# define IN_LIBXML
2001-04-21 16:57:29 +00:00
# include "libxml.h"
2001-02-23 17:55:21 +00:00
# include <string.h>
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
# include <libxml/xmlmemory.h>
# include <libxml/hash.h>
# include <libxml/entities.h>
# include <libxml/parser.h>
2003-10-18 16:20:14 +00:00
# include <libxml/parserInternals.h>
2001-02-23 17:55:21 +00:00
# include <libxml/xmlerror.h>
2001-10-17 15:58:35 +00:00
# include <libxml/globals.h>
2001-02-23 17:55:21 +00:00
/*
* The XML predefined entities .
*/
2003-09-30 13:38:04 +00:00
static xmlEntity xmlEntityLt = {
NULL , XML_ENTITY_DECL , BAD_CAST " lt " ,
NULL , NULL , NULL , NULL , NULL , NULL ,
BAD_CAST " < " , BAD_CAST " < " , 1 ,
XML_INTERNAL_PREDEFINED_ENTITY ,
NULL , NULL , NULL , NULL , 0
2001-02-23 17:55:21 +00:00
} ;
2003-09-30 13:38:04 +00:00
static xmlEntity xmlEntityGt = {
NULL , XML_ENTITY_DECL , BAD_CAST " gt " ,
NULL , NULL , NULL , NULL , NULL , NULL ,
BAD_CAST " > " , BAD_CAST " > " , 1 ,
XML_INTERNAL_PREDEFINED_ENTITY ,
NULL , NULL , NULL , NULL , 0
} ;
static xmlEntity xmlEntityAmp = {
NULL , XML_ENTITY_DECL , BAD_CAST " amp " ,
NULL , NULL , NULL , NULL , NULL , NULL ,
BAD_CAST " & " , BAD_CAST " & " , 1 ,
XML_INTERNAL_PREDEFINED_ENTITY ,
NULL , NULL , NULL , NULL , 0
} ;
static xmlEntity xmlEntityQuot = {
NULL , XML_ENTITY_DECL , BAD_CAST " quot " ,
NULL , NULL , NULL , NULL , NULL , NULL ,
BAD_CAST " \" " , BAD_CAST " \" " , 1 ,
XML_INTERNAL_PREDEFINED_ENTITY ,
NULL , NULL , NULL , NULL , 0
} ;
static xmlEntity xmlEntityApos = {
NULL , XML_ENTITY_DECL , BAD_CAST " apos " ,
NULL , NULL , NULL , NULL , NULL , NULL ,
BAD_CAST " ' " , BAD_CAST " ' " , 1 ,
XML_INTERNAL_PREDEFINED_ENTITY ,
NULL , NULL , NULL , NULL , 0
2001-02-23 17:55:21 +00:00
} ;
/*
* xmlFreeEntity : clean - up an entity record .
*/
2001-03-24 17:00:36 +00:00
static void xmlFreeEntity ( xmlEntityPtr entity ) {
2001-02-23 17:55:21 +00:00
if ( entity = = NULL ) return ;
2002-12-30 00:01:08 +00:00
if ( ( entity - > children ) & & ( entity - > owner = = 1 ) & &
2001-07-16 00:06:07 +00:00
( entity = = ( xmlEntityPtr ) entity - > children - > parent ) )
2001-02-23 17:55:21 +00:00
xmlFreeNodeList ( entity - > children ) ;
if ( entity - > name ! = NULL )
xmlFree ( ( char * ) entity - > name ) ;
if ( entity - > ExternalID ! = NULL )
xmlFree ( ( char * ) entity - > ExternalID ) ;
if ( entity - > SystemID ! = NULL )
xmlFree ( ( char * ) entity - > SystemID ) ;
if ( entity - > URI ! = NULL )
xmlFree ( ( char * ) entity - > URI ) ;
if ( entity - > content ! = NULL )
xmlFree ( ( char * ) entity - > content ) ;
if ( entity - > orig ! = NULL )
xmlFree ( ( char * ) entity - > orig ) ;
xmlFree ( entity ) ;
}
/*
* xmlAddEntity : register a new entity for an entities table .
*/
static xmlEntityPtr
xmlAddEntity ( xmlDtdPtr dtd , const xmlChar * name , int type ,
const xmlChar * ExternalID , const xmlChar * SystemID ,
const xmlChar * content ) {
xmlEntitiesTablePtr table = NULL ;
xmlEntityPtr ret ;
if ( name = = NULL )
return ( NULL ) ;
switch ( type ) {
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
if ( dtd - > entities = = NULL )
dtd - > entities = xmlHashCreate ( 0 ) ;
table = dtd - > entities ;
break ;
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
if ( dtd - > pentities = = NULL )
dtd - > pentities = xmlHashCreate ( 0 ) ;
table = dtd - > pentities ;
break ;
case XML_INTERNAL_PREDEFINED_ENTITY :
2003-09-30 13:38:04 +00:00
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
}
if ( table = = NULL )
return ( NULL ) ;
ret = ( xmlEntityPtr ) xmlMalloc ( sizeof ( xmlEntity ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddEntity: out of memory \n " ) ;
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlEntity ) ) ;
ret - > type = XML_ENTITY_DECL ;
/*
* fill the structure .
*/
ret - > name = xmlStrdup ( name ) ;
ret - > etype = ( xmlEntityType ) type ;
if ( ExternalID ! = NULL )
ret - > ExternalID = xmlStrdup ( ExternalID ) ;
if ( SystemID ! = NULL )
ret - > SystemID = xmlStrdup ( SystemID ) ;
if ( content ! = NULL ) {
ret - > length = xmlStrlen ( content ) ;
ret - > content = xmlStrndup ( content , ret - > length ) ;
} else {
ret - > length = 0 ;
ret - > content = NULL ;
}
ret - > URI = NULL ; /* to be computed by the layer knowing
the defining entity */
ret - > orig = NULL ;
2002-12-30 00:01:08 +00:00
ret - > owner = 0 ;
2001-02-23 17:55:21 +00:00
if ( xmlHashAddEntry ( table , name , ret ) ) {
/*
* entity was already defined at another level .
*/
xmlFreeEntity ( ret ) ;
return ( NULL ) ;
}
return ( ret ) ;
}
/**
* xmlGetPredefinedEntity :
* @ name : the entity name
*
* Check whether this name is an predefined entity .
*
2001-12-31 16:16:02 +00:00
* Returns NULL if not , otherwise the entity
2001-02-23 17:55:21 +00:00
*/
xmlEntityPtr
xmlGetPredefinedEntity ( const xmlChar * name ) {
2003-09-30 13:38:04 +00:00
if ( name = = NULL ) return ( NULL ) ;
switch ( name [ 0 ] ) {
case ' l ' :
if ( xmlStrEqual ( name , BAD_CAST " lt " ) )
return ( & xmlEntityLt ) ;
break ;
case ' g ' :
if ( xmlStrEqual ( name , BAD_CAST " gt " ) )
return ( & xmlEntityGt ) ;
break ;
case ' a ' :
if ( xmlStrEqual ( name , BAD_CAST " amp " ) )
return ( & xmlEntityAmp ) ;
if ( xmlStrEqual ( name , BAD_CAST " apos " ) )
return ( & xmlEntityApos ) ;
break ;
case ' q ' :
if ( xmlStrEqual ( name , BAD_CAST " quot " ) )
return ( & xmlEntityQuot ) ;
break ;
default :
break ;
}
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
}
/**
* xmlAddDtdEntity :
* @ doc : the document
* @ name : the entity name
* @ type : the entity type XML_xxx_yyy_ENTITY
* @ ExternalID : the entity external ID if available
* @ SystemID : the entity system ID if available
* @ content : the entity content
*
* Register a new entity for this document DTD external subset .
*
* Returns a pointer to the entity or NULL in case of error
*/
xmlEntityPtr
xmlAddDtdEntity ( xmlDocPtr doc , const xmlChar * name , int type ,
const xmlChar * ExternalID , const xmlChar * SystemID ,
const xmlChar * content ) {
xmlEntityPtr ret ;
xmlDtdPtr dtd ;
if ( doc = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddDtdEntity: doc == NULL ! \n " ) ;
return ( NULL ) ;
}
if ( doc - > extSubset = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddDtdEntity: document without external subset ! \n " ) ;
return ( NULL ) ;
}
dtd = doc - > extSubset ;
ret = xmlAddEntity ( dtd , name , type , ExternalID , SystemID , content ) ;
if ( ret = = NULL ) return ( NULL ) ;
/*
2001-12-31 16:16:02 +00:00
* Link it to the DTD
2001-02-23 17:55:21 +00:00
*/
ret - > parent = dtd ;
ret - > doc = dtd - > doc ;
if ( dtd - > last = = NULL ) {
dtd - > children = dtd - > last = ( xmlNodePtr ) ret ;
} else {
dtd - > last - > next = ( xmlNodePtr ) ret ;
ret - > prev = dtd - > last ;
dtd - > last = ( xmlNodePtr ) ret ;
}
return ( ret ) ;
}
/**
* xmlAddDocEntity :
* @ doc : the document
* @ name : the entity name
* @ type : the entity type XML_xxx_yyy_ENTITY
* @ ExternalID : the entity external ID if available
* @ SystemID : the entity system ID if available
* @ content : the entity content
*
* Register a new entity for this document .
*
* Returns a pointer to the entity or NULL in case of error
*/
xmlEntityPtr
xmlAddDocEntity ( xmlDocPtr doc , const xmlChar * name , int type ,
const xmlChar * ExternalID , const xmlChar * SystemID ,
const xmlChar * content ) {
xmlEntityPtr ret ;
xmlDtdPtr dtd ;
if ( doc = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddDocEntity: document is NULL ! \n " ) ;
return ( NULL ) ;
}
if ( doc - > intSubset = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
2001-12-31 16:16:02 +00:00
" xmlAddDocEntity: document without internal subset ! \n " ) ;
2001-02-23 17:55:21 +00:00
return ( NULL ) ;
}
dtd = doc - > intSubset ;
ret = xmlAddEntity ( dtd , name , type , ExternalID , SystemID , content ) ;
if ( ret = = NULL ) return ( NULL ) ;
/*
2001-12-31 16:16:02 +00:00
* Link it to the DTD
2001-02-23 17:55:21 +00:00
*/
ret - > parent = dtd ;
ret - > doc = dtd - > doc ;
if ( dtd - > last = = NULL ) {
dtd - > children = dtd - > last = ( xmlNodePtr ) ret ;
} else {
dtd - > last - > next = ( xmlNodePtr ) ret ;
ret - > prev = dtd - > last ;
dtd - > last = ( xmlNodePtr ) ret ;
}
return ( ret ) ;
}
/**
* xmlGetEntityFromTable :
* @ table : an entity table
* @ name : the entity name
* @ parameter : look for parameter entities
*
* Do an entity lookup in the table .
* returns the corresponding parameter entity , if found .
*
* Returns A pointer to the entity structure or NULL if not found .
*/
2001-03-24 17:00:36 +00:00
static xmlEntityPtr
2001-02-23 17:55:21 +00:00
xmlGetEntityFromTable ( xmlEntitiesTablePtr table , const xmlChar * name ) {
return ( ( xmlEntityPtr ) xmlHashLookup ( table , name ) ) ;
}
/**
* xmlGetParameterEntity :
* @ doc : the document referencing the entity
* @ name : the entity name
*
* Do an entity lookup in the internal and external subsets and
* returns the corresponding parameter entity , if found .
*
* Returns A pointer to the entity structure or NULL if not found .
*/
xmlEntityPtr
xmlGetParameterEntity ( xmlDocPtr doc , const xmlChar * name ) {
xmlEntitiesTablePtr table ;
xmlEntityPtr ret ;
2002-01-24 15:02:46 +00:00
if ( doc = = NULL )
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
if ( ( doc - > intSubset ! = NULL ) & & ( doc - > intSubset - > pentities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) doc - > intSubset - > pentities ;
ret = xmlGetEntityFromTable ( table , name ) ;
if ( ret ! = NULL )
return ( ret ) ;
}
if ( ( doc - > extSubset ! = NULL ) & & ( doc - > extSubset - > pentities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) doc - > extSubset - > pentities ;
return ( xmlGetEntityFromTable ( table , name ) ) ;
}
return ( NULL ) ;
}
/**
* xmlGetDtdEntity :
* @ doc : the document referencing the entity
* @ name : the entity name
*
2001-12-31 16:16:02 +00:00
* Do an entity lookup in the DTD entity hash table and
2001-02-23 17:55:21 +00:00
* returns the corresponding entity , if found .
2002-01-24 15:02:46 +00:00
* Note : the first argument is the document node , not the DTD node .
2001-02-23 17:55:21 +00:00
*
* Returns A pointer to the entity structure or NULL if not found .
*/
xmlEntityPtr
xmlGetDtdEntity ( xmlDocPtr doc , const xmlChar * name ) {
xmlEntitiesTablePtr table ;
2002-01-24 15:02:46 +00:00
if ( doc = = NULL )
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
if ( ( doc - > extSubset ! = NULL ) & & ( doc - > extSubset - > entities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) doc - > extSubset - > entities ;
return ( xmlGetEntityFromTable ( table , name ) ) ;
}
return ( NULL ) ;
}
/**
* xmlGetDocEntity :
* @ doc : the document referencing the entity
* @ name : the entity name
*
* Do an entity lookup in the document entity hash table and
2001-12-31 16:16:02 +00:00
* returns the corresponding entity , otherwise a lookup is done
2001-02-23 17:55:21 +00:00
* in the predefined entities too .
*
* Returns A pointer to the entity structure or NULL if not found .
*/
xmlEntityPtr
xmlGetDocEntity ( xmlDocPtr doc , const xmlChar * name ) {
xmlEntityPtr cur ;
xmlEntitiesTablePtr table ;
if ( doc ! = NULL ) {
if ( ( doc - > intSubset ! = NULL ) & & ( doc - > intSubset - > entities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) doc - > intSubset - > entities ;
cur = xmlGetEntityFromTable ( table , name ) ;
if ( cur ! = NULL )
return ( cur ) ;
}
2002-02-18 11:19:30 +00:00
if ( doc - > standalone ! = 1 ) {
if ( ( doc - > extSubset ! = NULL ) & &
( doc - > extSubset - > entities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) doc - > extSubset - > entities ;
cur = xmlGetEntityFromTable ( table , name ) ;
if ( cur ! = NULL )
return ( cur ) ;
}
2001-02-23 17:55:21 +00:00
}
}
2003-09-30 13:38:04 +00:00
return ( xmlGetPredefinedEntity ( name ) ) ;
2001-02-23 17:55:21 +00:00
}
/*
* Macro used to grow the current buffer .
*/
# define growBufferReentrant() { \
buffer_size * = 2 ; \
buffer = ( xmlChar * ) \
xmlRealloc ( buffer , buffer_size * sizeof ( xmlChar ) ) ; \
if ( buffer = = NULL ) { \
2002-09-05 11:33:25 +00:00
xmlGenericError ( xmlGenericErrorContext , " realloc failed \n " ) ; \
2001-02-23 17:55:21 +00:00
return ( NULL ) ; \
} \
}
/**
* xmlEncodeEntitiesReentrant :
* @ doc : the document containing the string
* @ input : A string to convert to XML .
*
* Do a global encoding of a string , replacing the predefined entities
* and non ASCII values with their entities and CharRef counterparts .
* Contrary to xmlEncodeEntities , this routine is reentrant , and result
* must be deallocated .
*
* Returns A newly allocated string with the substitution done .
*/
xmlChar *
xmlEncodeEntitiesReentrant ( xmlDocPtr doc , const xmlChar * input ) {
const xmlChar * cur = input ;
xmlChar * buffer = NULL ;
xmlChar * out = NULL ;
int buffer_size = 0 ;
int html = 0 ;
if ( input = = NULL ) return ( NULL ) ;
if ( doc ! = NULL )
html = ( doc - > type = = XML_HTML_DOCUMENT_NODE ) ;
/*
* allocate an translation buffer .
*/
buffer_size = 1000 ;
buffer = ( xmlChar * ) xmlMalloc ( buffer_size * sizeof ( xmlChar ) ) ;
if ( buffer = = NULL ) {
2002-09-05 11:33:25 +00:00
xmlGenericError ( xmlGenericErrorContext , " malloc failed \n " ) ;
2001-02-23 17:55:21 +00:00
return ( NULL ) ;
}
out = buffer ;
while ( * cur ! = ' \0 ' ) {
if ( out - buffer > buffer_size - 100 ) {
2001-03-24 17:00:36 +00:00
int indx = out - buffer ;
2001-02-23 17:55:21 +00:00
growBufferReentrant ( ) ;
2001-03-24 17:00:36 +00:00
out = & buffer [ indx ] ;
2001-02-23 17:55:21 +00:00
}
/*
* By default one have to encode at least ' < ' , ' > ' , ' " ' and ' & ' !
*/
if ( * cur = = ' < ' ) {
* out + + = ' & ' ;
* out + + = ' l ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * cur = = ' > ' ) {
* out + + = ' & ' ;
* out + + = ' g ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * cur = = ' & ' ) {
* out + + = ' & ' ;
* out + + = ' a ' ;
* out + + = ' m ' ;
* out + + = ' p ' ;
* out + + = ' ; ' ;
} else if ( ( ( * cur > = 0x20 ) & & ( * cur < 0x80 ) ) | |
2003-02-23 13:52:30 +00:00
( * cur = = ' \n ' ) | | ( * cur = = ' \t ' ) | | ( ( html ) & & ( * cur = = ' \r ' ) ) ) {
2001-02-23 17:55:21 +00:00
/*
* default case , just copy !
*/
* out + + = * cur ;
} else if ( * cur > = 0x80 ) {
2001-04-24 12:12:30 +00:00
if ( ( ( doc ! = NULL ) & & ( doc - > encoding ! = NULL ) ) | | ( html ) ) {
2001-02-23 17:55:21 +00:00
/*
* Bj <EFBFBD> rn Reese < br @ sseusa . com > provided the patch
xmlChar xc ;
xc = ( * cur & 0x3F ) < < 6 ;
if ( cur [ 1 ] ! = 0 ) {
xc + = * ( + + cur ) & 0x3F ;
* out + + = xc ;
} else
*/
* out + + = * cur ;
} else {
/*
* We assume we have UTF - 8 input .
*/
2003-10-01 19:13:56 +00:00
char buf [ 11 ] , * ptr ;
2001-02-23 17:55:21 +00:00
int val = 0 , l = 1 ;
if ( * cur < 0xC0 ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlEncodeEntitiesReentrant : input not UTF-8 \n " ) ;
2001-04-24 12:12:30 +00:00
if ( doc ! = NULL )
doc - > encoding = xmlStrdup ( BAD_CAST " ISO-8859-1 " ) ;
2001-02-23 17:55:21 +00:00
snprintf ( buf , sizeof ( buf ) , " &#%d; " , * cur ) ;
buf [ sizeof ( buf ) - 1 ] = 0 ;
ptr = buf ;
while ( * ptr ! = 0 ) * out + + = * ptr + + ;
2001-09-09 08:38:09 +00:00
cur + + ;
2001-02-23 17:55:21 +00:00
continue ;
} else if ( * cur < 0xE0 ) {
val = ( cur [ 0 ] ) & 0x1F ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
l = 2 ;
} else if ( * cur < 0xF0 ) {
val = ( cur [ 0 ] ) & 0x0F ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 2 ] ) & 0x3F ;
l = 3 ;
} else if ( * cur < 0xF8 ) {
val = ( cur [ 0 ] ) & 0x07 ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 2 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 3 ] ) & 0x3F ;
l = 4 ;
}
if ( ( l = = 1 ) | | ( ! IS_CHAR ( val ) ) ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlEncodeEntitiesReentrant : char out of range \n " ) ;
2001-04-24 12:12:30 +00:00
if ( doc ! = NULL )
doc - > encoding = xmlStrdup ( BAD_CAST " ISO-8859-1 " ) ;
2001-02-23 17:55:21 +00:00
snprintf ( buf , sizeof ( buf ) , " &#%d; " , * cur ) ;
buf [ sizeof ( buf ) - 1 ] = 0 ;
ptr = buf ;
while ( * ptr ! = 0 ) * out + + = * ptr + + ;
cur + + ;
continue ;
}
/*
* We could do multiple things here . Just save as a char ref
*/
2001-09-14 10:29:27 +00:00
if ( html )
snprintf ( buf , sizeof ( buf ) , " &#%d; " , val ) ;
else
snprintf ( buf , sizeof ( buf ) , " &#x%X; " , val ) ;
2001-02-23 17:55:21 +00:00
buf [ sizeof ( buf ) - 1 ] = 0 ;
ptr = buf ;
while ( * ptr ! = 0 ) * out + + = * ptr + + ;
cur + = l ;
continue ;
}
2003-10-18 16:20:14 +00:00
} else if ( IS_BYTE_CHAR ( * cur ) ) {
2003-10-01 19:13:56 +00:00
char buf [ 11 ] , * ptr ;
2001-02-23 17:55:21 +00:00
snprintf ( buf , sizeof ( buf ) , " &#%d; " , * cur ) ;
buf [ sizeof ( buf ) - 1 ] = 0 ;
ptr = buf ;
while ( * ptr ! = 0 ) * out + + = * ptr + + ;
}
cur + + ;
}
* out + + = 0 ;
return ( buffer ) ;
}
/**
* xmlEncodeSpecialChars :
* @ doc : the document containing the string
* @ input : A string to convert to XML .
*
* Do a global encoding of a string , replacing the predefined entities
* this routine is reentrant , and result must be deallocated .
*
* Returns A newly allocated string with the substitution done .
*/
xmlChar *
2003-09-28 00:19:54 +00:00
xmlEncodeSpecialChars ( xmlDocPtr doc ATTRIBUTE_UNUSED , const xmlChar * input ) {
2001-02-23 17:55:21 +00:00
const xmlChar * cur = input ;
xmlChar * buffer = NULL ;
xmlChar * out = NULL ;
int buffer_size = 0 ;
2003-09-26 18:03:42 +00:00
if ( input = = NULL ) return ( NULL ) ;
2001-02-23 17:55:21 +00:00
/*
* allocate an translation buffer .
*/
buffer_size = 1000 ;
buffer = ( xmlChar * ) xmlMalloc ( buffer_size * sizeof ( xmlChar ) ) ;
if ( buffer = = NULL ) {
2002-09-05 11:33:25 +00:00
xmlGenericError ( xmlGenericErrorContext , " malloc failed \n " ) ;
2001-02-23 17:55:21 +00:00
return ( NULL ) ;
}
out = buffer ;
while ( * cur ! = ' \0 ' ) {
if ( out - buffer > buffer_size - 10 ) {
2001-03-24 17:00:36 +00:00
int indx = out - buffer ;
2001-02-23 17:55:21 +00:00
growBufferReentrant ( ) ;
2001-03-24 17:00:36 +00:00
out = & buffer [ indx ] ;
2001-02-23 17:55:21 +00:00
}
/*
* By default one have to encode at least ' < ' , ' > ' , ' " ' and ' & ' !
*/
if ( * cur = = ' < ' ) {
* out + + = ' & ' ;
* out + + = ' l ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * cur = = ' > ' ) {
* out + + = ' & ' ;
* out + + = ' g ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
} else if ( * cur = = ' & ' ) {
* out + + = ' & ' ;
* out + + = ' a ' ;
* out + + = ' m ' ;
* out + + = ' p ' ;
* out + + = ' ; ' ;
2003-11-25 18:29:55 +00:00
#if 0
2001-02-23 17:55:21 +00:00
} else if ( * cur = = ' " ' ) {
* out + + = ' & ' ;
* out + + = ' q ' ;
* out + + = ' u ' ;
* out + + = ' o ' ;
* out + + = ' t ' ;
* out + + = ' ; ' ;
2003-11-25 18:29:55 +00:00
# endif
2003-02-26 15:49:03 +00:00
} else if ( * cur = = ' \r ' ) {
* out + + = ' & ' ;
* out + + = ' # ' ;
* out + + = ' 1 ' ;
* out + + = ' 3 ' ;
* out + + = ' ; ' ;
2001-02-23 17:55:21 +00:00
} else {
/*
* Works because on UTF - 8 , all extended sequences cannot
* result in bytes in the ASCII range .
*/
* out + + = * cur ;
}
cur + + ;
}
* out + + = 0 ;
return ( buffer ) ;
}
/**
* xmlCreateEntitiesTable :
*
* create and initialize an empty entities hash table .
*
* Returns the xmlEntitiesTablePtr just created or NULL in case of error .
*/
xmlEntitiesTablePtr
xmlCreateEntitiesTable ( void ) {
return ( ( xmlEntitiesTablePtr ) xmlHashCreate ( 0 ) ) ;
}
2002-12-30 00:01:08 +00:00
/**
* xmlFreeEntityWrapper :
* @ entity : An entity
* @ name : its name
*
* Deallocate the memory used by an entities in the hash table .
*/
static void
xmlFreeEntityWrapper ( xmlEntityPtr entity ,
const xmlChar * name ATTRIBUTE_UNUSED ) {
if ( entity ! = NULL )
xmlFreeEntity ( entity ) ;
}
2001-02-23 17:55:21 +00:00
/**
* xmlFreeEntitiesTable :
* @ table : An entity table
*
* Deallocate the memory used by an entities hash table .
*/
void
xmlFreeEntitiesTable ( xmlEntitiesTablePtr table ) {
2002-12-30 00:01:08 +00:00
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeEntityWrapper ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 18:02:38 +00:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 17:55:21 +00:00
/**
* xmlCopyEntity :
* @ ent : An entity
*
* Build a copy of an entity
*
* Returns the new xmlEntitiesPtr or NULL in case of error .
*/
2001-03-24 17:00:36 +00:00
static xmlEntityPtr
2001-02-23 17:55:21 +00:00
xmlCopyEntity ( xmlEntityPtr ent ) {
xmlEntityPtr cur ;
cur = ( xmlEntityPtr ) xmlMalloc ( sizeof ( xmlEntity ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlCopyEntity: out of memory ! \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlEntity ) ) ;
2002-01-09 11:51:37 +00:00
cur - > type = XML_ENTITY_DECL ;
2001-02-23 17:55:21 +00:00
cur - > etype = ent - > etype ;
if ( ent - > name ! = NULL )
cur - > name = xmlStrdup ( ent - > name ) ;
if ( ent - > ExternalID ! = NULL )
cur - > ExternalID = xmlStrdup ( ent - > ExternalID ) ;
if ( ent - > SystemID ! = NULL )
cur - > SystemID = xmlStrdup ( ent - > SystemID ) ;
if ( ent - > content ! = NULL )
cur - > content = xmlStrdup ( ent - > content ) ;
if ( ent - > orig ! = NULL )
cur - > orig = xmlStrdup ( ent - > orig ) ;
2002-01-26 21:42:58 +00:00
if ( ent - > URI ! = NULL )
cur - > URI = xmlStrdup ( ent - > URI ) ;
2001-02-23 17:55:21 +00:00
return ( cur ) ;
}
/**
* xmlCopyEntitiesTable :
* @ table : An entity table
*
* Build a copy of an entity table .
*
* Returns the new xmlEntitiesTablePtr or NULL in case of error .
*/
xmlEntitiesTablePtr
xmlCopyEntitiesTable ( xmlEntitiesTablePtr table ) {
return ( xmlHashCopy ( table , ( xmlHashCopier ) xmlCopyEntity ) ) ;
}
2003-09-29 18:02:38 +00:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 17:55:21 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2003-12-09 22:51:37 +00:00
/**
* xmlDumpEntityContent :
* @ buf : An XML buffer .
* @ content : The entity content .
*
* This will dump the quoted string value , taking care of the special
* treatment required by %
*/
static void
xmlDumpEntityContent ( xmlBufferPtr buf , const xmlChar * content ) {
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ;
if ( xmlStrchr ( content , ' % ' ) ) {
const xmlChar * base , * cur ;
xmlBufferCCat ( buf , " \" " ) ;
base = cur = content ;
while ( * cur ! = 0 ) {
if ( * cur = = ' " ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " " " , 6 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' % ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " % " , 6 ) ;
cur + + ;
base = cur ;
} else {
cur + + ;
}
}
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferCCat ( buf , " \" " ) ;
} else {
xmlBufferWriteQuotedString ( buf , content ) ;
}
}
2001-02-23 17:55:21 +00:00
/**
* xmlDumpEntityDecl :
* @ buf : An XML buffer .
* @ ent : An entity table
*
* This will dump the content of the entity table as an XML DTD definition
*/
void
xmlDumpEntityDecl ( xmlBufferPtr buf , xmlEntityPtr ent ) {
switch ( ent - > etype ) {
case XML_INTERNAL_GENERAL_ENTITY :
xmlBufferWriteChar ( buf , " <!ENTITY " ) ;
xmlBufferWriteCHAR ( buf , ent - > name ) ;
xmlBufferWriteChar ( buf , " " ) ;
if ( ent - > orig ! = NULL )
xmlBufferWriteQuotedString ( buf , ent - > orig ) ;
else
2003-12-09 22:51:37 +00:00
xmlDumpEntityContent ( buf , ent - > content ) ;
2001-02-23 17:55:21 +00:00
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
xmlBufferWriteChar ( buf , " <!ENTITY " ) ;
xmlBufferWriteCHAR ( buf , ent - > name ) ;
if ( ent - > ExternalID ! = NULL ) {
xmlBufferWriteChar ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf , ent - > ExternalID ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
} else {
xmlBufferWriteChar ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
}
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
xmlBufferWriteChar ( buf , " <!ENTITY " ) ;
xmlBufferWriteCHAR ( buf , ent - > name ) ;
if ( ent - > ExternalID ! = NULL ) {
xmlBufferWriteChar ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf , ent - > ExternalID ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
} else {
xmlBufferWriteChar ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
}
if ( ent - > content ! = NULL ) { /* Should be true ! */
xmlBufferWriteChar ( buf , " NDATA " ) ;
if ( ent - > orig ! = NULL )
xmlBufferWriteCHAR ( buf , ent - > orig ) ;
else
xmlBufferWriteCHAR ( buf , ent - > content ) ;
}
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
case XML_INTERNAL_PARAMETER_ENTITY :
xmlBufferWriteChar ( buf , " <!ENTITY % " ) ;
xmlBufferWriteCHAR ( buf , ent - > name ) ;
xmlBufferWriteChar ( buf , " " ) ;
if ( ent - > orig = = NULL )
2003-12-09 22:51:37 +00:00
xmlDumpEntityContent ( buf , ent - > content ) ;
2001-02-23 17:55:21 +00:00
else
xmlBufferWriteQuotedString ( buf , ent - > orig ) ;
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
case XML_EXTERNAL_PARAMETER_ENTITY :
xmlBufferWriteChar ( buf , " <!ENTITY % " ) ;
xmlBufferWriteCHAR ( buf , ent - > name ) ;
if ( ent - > ExternalID ! = NULL ) {
xmlBufferWriteChar ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf , ent - > ExternalID ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
} else {
xmlBufferWriteChar ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf , ent - > SystemID ) ;
}
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
default :
xmlGenericError ( xmlGenericErrorContext ,
2001-12-31 16:16:02 +00:00
" xmlDumpEntitiesDecl: internal: unknown type %d \n " ,
2001-02-23 17:55:21 +00:00
ent - > etype ) ;
}
}
2003-10-20 14:56:06 +00:00
/**
* xmlDumpEntityDeclScan :
* @ ent : An entity table
* @ buf : An XML buffer .
*
* When using the hash table scan function , arguments need to be reversed
*/
static void
xmlDumpEntityDeclScan ( xmlEntityPtr ent , xmlBufferPtr buf ) {
xmlDumpEntityDecl ( buf , ent ) ;
}
2001-02-23 17:55:21 +00:00
/**
* xmlDumpEntitiesTable :
* @ buf : An XML buffer .
* @ table : An entity table
*
* This will dump the content of the entity table as an XML DTD definition
*/
void
xmlDumpEntitiesTable ( xmlBufferPtr buf , xmlEntitiesTablePtr table ) {
2003-10-20 14:56:06 +00:00
xmlHashScan ( table , ( xmlHashScanner ) xmlDumpEntityDeclScan , buf ) ;
2001-02-23 17:55:21 +00:00
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */