mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-26 00:37:43 +03:00
encoding: Report malloc failures
Introduce new API functions that return a separate error code if a memory allocation fails. - xmlOpenCharEncodingHandler - xmlLookupCharEncodingHandler Fix a few places where malloc failures weren't reported.
This commit is contained in:
643
encoding.c
643
encoding.c
@@ -71,57 +71,6 @@ static int xmlCharEncodingAliasesMax = 0;
|
||||
|
||||
static int xmlLittleEndian = 1;
|
||||
|
||||
#ifdef LIBXML_ICU_ENABLED
|
||||
static uconv_t*
|
||||
openIcuConverter(const char* name, int toUnicode)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
uconv_t *conv = (uconv_t *) xmlMalloc(sizeof(uconv_t));
|
||||
if (conv == NULL)
|
||||
return NULL;
|
||||
|
||||
conv->pivot_source = conv->pivot_buf;
|
||||
conv->pivot_target = conv->pivot_buf;
|
||||
|
||||
conv->uconv = ucnv_open(name, &status);
|
||||
if (U_FAILURE(status))
|
||||
goto error;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
if (toUnicode) {
|
||||
ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP,
|
||||
NULL, NULL, NULL, &status);
|
||||
}
|
||||
else {
|
||||
ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP,
|
||||
NULL, NULL, NULL, &status);
|
||||
}
|
||||
if (U_FAILURE(status))
|
||||
goto error;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
conv->utf8 = ucnv_open("UTF-8", &status);
|
||||
if (U_SUCCESS(status))
|
||||
return conv;
|
||||
|
||||
error:
|
||||
if (conv->uconv)
|
||||
ucnv_close(conv->uconv);
|
||||
xmlFree(conv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
closeIcuConverter(uconv_t *conv)
|
||||
{
|
||||
if (conv != NULL) {
|
||||
ucnv_close(conv->uconv);
|
||||
ucnv_close(conv->utf8);
|
||||
xmlFree(conv);
|
||||
}
|
||||
}
|
||||
#endif /* LIBXML_ICU_ENABLED */
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Conversions To/From UTF8 encoding *
|
||||
@@ -1374,6 +1323,7 @@ static const xmlCharEncodingHandler defaultHandlers[] = {
|
||||
|
||||
static const xmlCharEncodingHandler *xmlUTF16LEHandler = &defaultHandlers[1];
|
||||
static const xmlCharEncodingHandler *xmlUTF16BEHandler = &defaultHandlers[2];
|
||||
static const xmlCharEncodingHandler *xmlLatin1Handler = &defaultHandlers[4];
|
||||
|
||||
/* the size should be growable, but it's not a big deal ... */
|
||||
#define MAX_ENCODING_HANDLERS 50
|
||||
@@ -1535,162 +1485,428 @@ free_handler:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIBXML_ICONV_ENABLED
|
||||
static int
|
||||
xmlCreateIconvHandler(const char *name, xmlCharEncodingHandler **out) {
|
||||
xmlCharEncodingHandlerPtr enc = NULL;
|
||||
iconv_t icv_in = (iconv_t) -1;
|
||||
iconv_t icv_out = (iconv_t) -1;
|
||||
int ret;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
icv_in = iconv_open("UTF-8", name);
|
||||
if (icv_in == (iconv_t) -1) {
|
||||
if (errno == EINVAL)
|
||||
ret = XML_ERR_UNSUPPORTED_ENCODING;
|
||||
else if (errno == ENOMEM)
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
else
|
||||
ret = XML_ERR_SYSTEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
icv_out = iconv_open(name, "UTF-8");
|
||||
if (icv_out == (iconv_t) -1) {
|
||||
if (errno == EINVAL)
|
||||
ret = XML_ERR_UNSUPPORTED_ENCODING;
|
||||
else if (errno == ENOMEM)
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
else
|
||||
ret = XML_ERR_SYSTEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
enc = xmlMalloc(sizeof(*enc));
|
||||
if (enc == NULL) {
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
memset(enc, 0, sizeof(*enc));
|
||||
|
||||
enc->name = xmlMemStrdup(name);
|
||||
if (enc->name == NULL) {
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
enc->iconv_in = icv_in;
|
||||
enc->iconv_out = icv_out;
|
||||
|
||||
*out = enc;
|
||||
return(0);
|
||||
|
||||
error:
|
||||
if (enc != NULL)
|
||||
xmlFree(enc);
|
||||
if (icv_in != (iconv_t) -1)
|
||||
iconv_close(icv_in);
|
||||
if (icv_out != (iconv_t) -1)
|
||||
iconv_close(icv_out);
|
||||
return(ret);
|
||||
}
|
||||
#endif /* LIBXML_ICONV_ENABLED */
|
||||
|
||||
#ifdef LIBXML_ICU_ENABLED
|
||||
static int
|
||||
openIcuConverter(const char* name, int toUnicode, uconv_t **out)
|
||||
{
|
||||
UErrorCode status;
|
||||
uconv_t *conv;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
conv = (uconv_t *) xmlMalloc(sizeof(uconv_t));
|
||||
if (conv == NULL)
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
|
||||
conv->pivot_source = conv->pivot_buf;
|
||||
conv->pivot_target = conv->pivot_buf;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
conv->uconv = ucnv_open(name, &status);
|
||||
if (U_FAILURE(status))
|
||||
goto error;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
if (toUnicode) {
|
||||
ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP,
|
||||
NULL, NULL, NULL, &status);
|
||||
}
|
||||
else {
|
||||
ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP,
|
||||
NULL, NULL, NULL, &status);
|
||||
}
|
||||
if (U_FAILURE(status))
|
||||
goto error;
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
conv->utf8 = ucnv_open("UTF-8", &status);
|
||||
if (U_FAILURE(status))
|
||||
goto error;
|
||||
|
||||
*out = conv;
|
||||
return(0);
|
||||
|
||||
error:
|
||||
if (conv->uconv)
|
||||
ucnv_close(conv->uconv);
|
||||
xmlFree(conv);
|
||||
|
||||
if (status == U_FILE_ACCESS_ERROR)
|
||||
return(XML_ERR_UNSUPPORTED_ENCODING);
|
||||
if (status == U_MEMORY_ALLOCATION_ERROR)
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
return(XML_ERR_SYSTEM);
|
||||
}
|
||||
|
||||
static void
|
||||
closeIcuConverter(uconv_t *conv)
|
||||
{
|
||||
if (conv == NULL)
|
||||
return;
|
||||
ucnv_close(conv->uconv);
|
||||
ucnv_close(conv->utf8);
|
||||
xmlFree(conv);
|
||||
}
|
||||
|
||||
static int
|
||||
xmlCreateUconvHandler(const char *name, xmlCharEncodingHandler **out) {
|
||||
xmlCharEncodingHandlerPtr enc = NULL;
|
||||
uconv_t *ucv_in = NULL;
|
||||
uconv_t *ucv_out = NULL;
|
||||
int ret;
|
||||
|
||||
ret = openIcuConverter(name, 1, &ucv_in);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
ret = openIcuConverter(name, 0, &ucv_out);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
enc = (xmlCharEncodingHandlerPtr)
|
||||
xmlMalloc(sizeof(xmlCharEncodingHandler));
|
||||
if (enc == NULL) {
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
memset(enc, 0, sizeof(xmlCharEncodingHandler));
|
||||
|
||||
enc->name = xmlMemStrdup(name);
|
||||
if (enc->name == NULL) {
|
||||
ret = XML_ERR_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
enc->input = NULL;
|
||||
enc->output = NULL;
|
||||
enc->uconv_in = ucv_in;
|
||||
enc->uconv_out = ucv_out;
|
||||
|
||||
*out = enc;
|
||||
return(0);
|
||||
|
||||
error:
|
||||
if (enc != NULL)
|
||||
xmlFree(enc);
|
||||
if (ucv_in != NULL)
|
||||
closeIcuConverter(ucv_in);
|
||||
if (ucv_out != NULL)
|
||||
closeIcuConverter(ucv_out);
|
||||
return(ret);
|
||||
}
|
||||
#endif /* LIBXML_ICU_ENABLED */
|
||||
|
||||
/**
|
||||
* xmlGetCharEncodingHandler:
|
||||
* @enc: an xmlCharEncoding value.
|
||||
* xmlFindExtraHandler:
|
||||
* @name: a string describing the char encoding.
|
||||
* @out: pointer to resulting handler
|
||||
*
|
||||
* Search in the registered set the handler able to read/write that encoding.
|
||||
* Search the non-default handlers for an exact match.
|
||||
*
|
||||
* Returns the handler or NULL if not found
|
||||
* Returns 0 on success, 1 if no handler was found, -1 if a memory
|
||||
* allocation failed.
|
||||
*/
|
||||
xmlCharEncodingHandlerPtr
|
||||
xmlGetCharEncodingHandler(xmlCharEncoding enc) {
|
||||
xmlCharEncodingHandlerPtr handler;
|
||||
static int
|
||||
xmlFindExtraHandler(const char *name, xmlCharEncodingHandler **out) {
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
(void) ret;
|
||||
|
||||
if (handlers != NULL) {
|
||||
for (i = 0; i < nbCharEncodingHandler; i++) {
|
||||
if (!xmlStrcasecmp((const xmlChar *) name,
|
||||
(const xmlChar *) handlers[i]->name)) {
|
||||
*out = handlers[i];
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIBXML_ICONV_ENABLED
|
||||
ret = xmlCreateIconvHandler(name, out);
|
||||
if (*out != NULL)
|
||||
return(0);
|
||||
if (ret != XML_ERR_UNSUPPORTED_ENCODING)
|
||||
return(ret);
|
||||
#endif /* LIBXML_ICONV_ENABLED */
|
||||
|
||||
#ifdef LIBXML_ICU_ENABLED
|
||||
ret = xmlCreateUconvHandler(name, out);
|
||||
if (*out != NULL)
|
||||
return(0);
|
||||
if (ret != XML_ERR_UNSUPPORTED_ENCODING)
|
||||
return(ret);
|
||||
#endif /* LIBXML_ICU_ENABLED */
|
||||
|
||||
return(XML_ERR_UNSUPPORTED_ENCODING);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFindHandler:
|
||||
* @name: a string describing the char encoding.
|
||||
* @out: pointer to resulting handler
|
||||
*
|
||||
* Search all handlers for an exact match.
|
||||
*
|
||||
* Returns 0 on success, 1 if no handler was found, -1 if a memory
|
||||
* allocation failed.
|
||||
*/
|
||||
static int
|
||||
xmlFindHandler(const char *name, xmlCharEncodingHandler **out) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Check for default handlers
|
||||
*/
|
||||
for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) {
|
||||
if (xmlStrcasecmp((const xmlChar *) name,
|
||||
(const xmlChar *) defaultHandlers[i].name) == 0) {
|
||||
*out = (xmlCharEncodingHandler *) &defaultHandlers[i];
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for other handlers
|
||||
*/
|
||||
return(xmlFindExtraHandler(name, out));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlLookupCharEncodingHandler:
|
||||
* @enc: an xmlCharEncoding value.
|
||||
* @out: pointer to result
|
||||
*
|
||||
* Find or create a handler matching the encoding. If no default or
|
||||
* registered handler could be found, try to create a handler using
|
||||
* iconv or ICU if supported.
|
||||
*
|
||||
* The handler must be closed with xmlCharEncCloseFunc.
|
||||
*
|
||||
* Available since 2.13.0.
|
||||
*
|
||||
* Returns an xmlParserErrors error code.
|
||||
*/
|
||||
int
|
||||
xmlLookupCharEncodingHandler(xmlCharEncoding enc,
|
||||
xmlCharEncodingHandler **out) {
|
||||
const char *name = NULL;
|
||||
static const char *const ebcdicNames[] = {
|
||||
"EBCDIC", "ebcdic", "EBCDIC-US", "IBM-037"
|
||||
};
|
||||
static const char *const ucs4Names[] = {
|
||||
"ISO-10646-UCS-4", "UCS-4", "UCS4"
|
||||
};
|
||||
static const char *const ucs2Names[] = {
|
||||
"ISO-10646-UCS-2", "UCS-2", "UCS2"
|
||||
};
|
||||
static const char *const shiftJisNames[] = {
|
||||
"SHIFT-JIS", "SHIFT_JIS", "Shift_JIS",
|
||||
};
|
||||
const char *const *names = NULL;
|
||||
int numNames = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (out == NULL)
|
||||
return(XML_ERR_ARGUMENT);
|
||||
*out = NULL;
|
||||
|
||||
switch (enc) {
|
||||
case XML_CHAR_ENCODING_ERROR:
|
||||
return(NULL);
|
||||
return(XML_ERR_UNSUPPORTED_ENCODING);
|
||||
case XML_CHAR_ENCODING_NONE:
|
||||
return(NULL);
|
||||
return(0);
|
||||
case XML_CHAR_ENCODING_UTF8:
|
||||
return(NULL);
|
||||
return(0);
|
||||
case XML_CHAR_ENCODING_UTF16LE:
|
||||
return((xmlCharEncodingHandlerPtr) xmlUTF16LEHandler);
|
||||
*out = (xmlCharEncodingHandler *) xmlUTF16LEHandler;
|
||||
return(0);
|
||||
case XML_CHAR_ENCODING_UTF16BE:
|
||||
return((xmlCharEncodingHandlerPtr) xmlUTF16BEHandler);
|
||||
*out = (xmlCharEncodingHandler *) xmlUTF16BEHandler;
|
||||
return(0);
|
||||
case XML_CHAR_ENCODING_EBCDIC:
|
||||
handler = xmlFindCharEncodingHandler("EBCDIC");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("ebcdic");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("EBCDIC-US");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("IBM-037");
|
||||
if (handler != NULL) return(handler);
|
||||
names = ebcdicNames;
|
||||
numNames = sizeof(ebcdicNames) / sizeof(ebcdicNames[0]);
|
||||
break;
|
||||
case XML_CHAR_ENCODING_UCS4BE:
|
||||
handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS-4");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS4");
|
||||
if (handler != NULL) return(handler);
|
||||
break;
|
||||
case XML_CHAR_ENCODING_UCS4LE:
|
||||
handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS-4");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS4");
|
||||
if (handler != NULL) return(handler);
|
||||
names = ucs4Names;
|
||||
numNames = sizeof(ucs4Names) / sizeof(ucs4Names[0]);
|
||||
break;
|
||||
case XML_CHAR_ENCODING_UCS4_2143:
|
||||
break;
|
||||
case XML_CHAR_ENCODING_UCS4_3412:
|
||||
break;
|
||||
case XML_CHAR_ENCODING_UCS2:
|
||||
handler = xmlFindCharEncodingHandler("ISO-10646-UCS-2");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS-2");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("UCS2");
|
||||
if (handler != NULL) return(handler);
|
||||
names = ucs2Names;
|
||||
numNames = sizeof(ucs2Names) / sizeof(ucs2Names[0]);
|
||||
break;
|
||||
|
||||
/*
|
||||
* We used to keep ISO Latin encodings native in the
|
||||
* generated data. This led to so many problems that
|
||||
* this has been removed. One can still change this
|
||||
* back by registering no-ops encoders for those
|
||||
*/
|
||||
case XML_CHAR_ENCODING_8859_1:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-1");
|
||||
if (handler != NULL) return(handler);
|
||||
break;
|
||||
*out = (xmlCharEncodingHandler *) xmlLatin1Handler;
|
||||
return(0);
|
||||
case XML_CHAR_ENCODING_8859_2:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-2");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-2";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_3:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-3");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-3";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_4:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-4");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-4";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_5:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-5");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-5";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_6:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-6");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-6";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_7:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-7");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-7";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_8:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-8");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-8";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_8859_9:
|
||||
handler = xmlFindCharEncodingHandler("ISO-8859-9");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-8859-9";
|
||||
break;
|
||||
|
||||
|
||||
case XML_CHAR_ENCODING_2022_JP:
|
||||
handler = xmlFindCharEncodingHandler("ISO-2022-JP");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "ISO-2022-JP";
|
||||
break;
|
||||
case XML_CHAR_ENCODING_SHIFT_JIS:
|
||||
handler = xmlFindCharEncodingHandler("SHIFT-JIS");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("SHIFT_JIS");
|
||||
if (handler != NULL) return(handler);
|
||||
handler = xmlFindCharEncodingHandler("Shift_JIS");
|
||||
if (handler != NULL) return(handler);
|
||||
names = shiftJisNames;
|
||||
numNames = sizeof(shiftJisNames) / sizeof(shiftJisNames[0]);
|
||||
break;
|
||||
case XML_CHAR_ENCODING_EUC_JP:
|
||||
handler = xmlFindCharEncodingHandler("EUC-JP");
|
||||
if (handler != NULL) return(handler);
|
||||
name = "EUC-JP";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
if (name != NULL)
|
||||
return(xmlFindExtraHandler(name, out));
|
||||
|
||||
if (names != NULL) {
|
||||
for (i = 0; i < numNames; i++) {
|
||||
ret = xmlFindExtraHandler(names[i], out);
|
||||
if (*out != NULL)
|
||||
return(0);
|
||||
if (ret != XML_ERR_UNSUPPORTED_ENCODING)
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
|
||||
return(XML_ERR_UNSUPPORTED_ENCODING);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFindCharEncodingHandler:
|
||||
* @name: a string describing the char encoding.
|
||||
* xmlGetCharEncodingHandler:
|
||||
* @enc: an xmlCharEncoding value.
|
||||
*
|
||||
* Search in the registered set the handler able to read/write that encoding
|
||||
* or create a new one.
|
||||
* DEPRECATED: Use xmlLookupCharEncodingHandler which has better error
|
||||
* reporting.
|
||||
*
|
||||
* Returns the handler or NULL if not found
|
||||
* Returns the handler or NULL if no handler was found or an error
|
||||
* occurred.
|
||||
*/
|
||||
xmlCharEncodingHandlerPtr
|
||||
xmlFindCharEncodingHandler(const char *name) {
|
||||
xmlGetCharEncodingHandler(xmlCharEncoding enc) {
|
||||
xmlCharEncodingHandler *ret;
|
||||
|
||||
xmlLookupCharEncodingHandler(enc, &ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOpenCharEncodingHandler:
|
||||
* @name: a string describing the char encoding.
|
||||
* @out: pointer to result
|
||||
*
|
||||
* Find or create a handler matching the encoding. If no default or
|
||||
* registered handler could be found, try to create a handler using
|
||||
* iconv or ICU if supported.
|
||||
*
|
||||
* The handler must be closed with xmlCharEncCloseFunc.
|
||||
*
|
||||
* Available since 2.13.0.
|
||||
*
|
||||
* Returns an xmlParserErrors error code.
|
||||
*/
|
||||
int
|
||||
xmlOpenCharEncodingHandler(const char *name, xmlCharEncodingHandler **out) {
|
||||
const char *nalias;
|
||||
const char *norig;
|
||||
xmlCharEncoding alias;
|
||||
#ifdef LIBXML_ICONV_ENABLED
|
||||
xmlCharEncodingHandlerPtr enc;
|
||||
iconv_t icv_in, icv_out;
|
||||
#endif /* LIBXML_ICONV_ENABLED */
|
||||
#ifdef LIBXML_ICU_ENABLED
|
||||
xmlCharEncodingHandlerPtr encu;
|
||||
uconv_t *ucv_in, *ucv_out;
|
||||
#endif /* LIBXML_ICU_ENABLED */
|
||||
char upper[100];
|
||||
int i;
|
||||
xmlCharEncoding enc;
|
||||
int ret;
|
||||
|
||||
if (name == NULL) return(NULL);
|
||||
if (name[0] == 0) return(NULL);
|
||||
if (out == NULL)
|
||||
return(XML_ERR_ARGUMENT);
|
||||
*out = NULL;
|
||||
|
||||
if (name == NULL)
|
||||
return(XML_ERR_ARGUMENT);
|
||||
|
||||
/*
|
||||
* Do the alias resolution
|
||||
@@ -1700,111 +1916,35 @@ xmlFindCharEncodingHandler(const char *name) {
|
||||
if (nalias != NULL)
|
||||
name = nalias;
|
||||
|
||||
/*
|
||||
* Check first for directly registered encoding names
|
||||
*/
|
||||
for (i = 0;i < 99;i++) {
|
||||
upper[i] = (char) toupper((unsigned char) name[i]);
|
||||
if (upper[i] == 0) break;
|
||||
}
|
||||
upper[i] = 0;
|
||||
|
||||
for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) {
|
||||
if (strcmp(upper, defaultHandlers[i].name) == 0)
|
||||
return((xmlCharEncodingHandlerPtr) &defaultHandlers[i]);
|
||||
}
|
||||
|
||||
if (handlers != NULL) {
|
||||
for (i = 0;i < nbCharEncodingHandler; i++) {
|
||||
if (!strcmp(upper, handlers[i]->name)) {
|
||||
return(handlers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LIBXML_ICONV_ENABLED
|
||||
/* check whether iconv can handle this */
|
||||
icv_in = iconv_open("UTF-8", name);
|
||||
icv_out = iconv_open(name, "UTF-8");
|
||||
if (icv_in == (iconv_t) -1) {
|
||||
icv_in = iconv_open("UTF-8", upper);
|
||||
}
|
||||
if (icv_out == (iconv_t) -1) {
|
||||
icv_out = iconv_open(upper, "UTF-8");
|
||||
}
|
||||
if ((icv_in != (iconv_t) -1) && (icv_out != (iconv_t) -1)) {
|
||||
enc = (xmlCharEncodingHandlerPtr)
|
||||
xmlMalloc(sizeof(xmlCharEncodingHandler));
|
||||
if (enc == NULL) {
|
||||
iconv_close(icv_in);
|
||||
iconv_close(icv_out);
|
||||
return(NULL);
|
||||
}
|
||||
memset(enc, 0, sizeof(xmlCharEncodingHandler));
|
||||
enc->name = xmlMemStrdup(name);
|
||||
if (enc->name == NULL) {
|
||||
xmlFree(enc);
|
||||
iconv_close(icv_in);
|
||||
iconv_close(icv_out);
|
||||
return(NULL);
|
||||
}
|
||||
enc->input = NULL;
|
||||
enc->output = NULL;
|
||||
enc->iconv_in = icv_in;
|
||||
enc->iconv_out = icv_out;
|
||||
return enc;
|
||||
} else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) {
|
||||
if (icv_in != (iconv_t) -1)
|
||||
iconv_close(icv_in);
|
||||
else
|
||||
iconv_close(icv_out);
|
||||
}
|
||||
#endif /* LIBXML_ICONV_ENABLED */
|
||||
#ifdef LIBXML_ICU_ENABLED
|
||||
/* check whether icu can handle this */
|
||||
ucv_in = openIcuConverter(name, 1);
|
||||
ucv_out = openIcuConverter(name, 0);
|
||||
if (ucv_in != NULL && ucv_out != NULL) {
|
||||
encu = (xmlCharEncodingHandlerPtr)
|
||||
xmlMalloc(sizeof(xmlCharEncodingHandler));
|
||||
if (encu == NULL) {
|
||||
closeIcuConverter(ucv_in);
|
||||
closeIcuConverter(ucv_out);
|
||||
return(NULL);
|
||||
}
|
||||
memset(encu, 0, sizeof(xmlCharEncodingHandler));
|
||||
encu->name = xmlMemStrdup(name);
|
||||
if (encu->name == NULL) {
|
||||
xmlFree(encu);
|
||||
closeIcuConverter(ucv_in);
|
||||
closeIcuConverter(ucv_out);
|
||||
return(NULL);
|
||||
}
|
||||
encu->input = NULL;
|
||||
encu->output = NULL;
|
||||
encu->uconv_in = ucv_in;
|
||||
encu->uconv_out = ucv_out;
|
||||
return encu;
|
||||
} else if (ucv_in != NULL || ucv_out != NULL) {
|
||||
closeIcuConverter(ucv_in);
|
||||
closeIcuConverter(ucv_out);
|
||||
}
|
||||
#endif /* LIBXML_ICU_ENABLED */
|
||||
ret = xmlFindHandler(name, out);
|
||||
if (*out != NULL)
|
||||
return(0);
|
||||
if (ret != XML_ERR_UNSUPPORTED_ENCODING)
|
||||
return(ret);
|
||||
|
||||
/*
|
||||
* Fallback using the canonical names
|
||||
*/
|
||||
alias = xmlParseCharEncoding(norig);
|
||||
if (alias != XML_CHAR_ENCODING_ERROR) {
|
||||
const char* canon;
|
||||
canon = xmlGetCharEncodingName(alias);
|
||||
if ((canon != NULL) && (strcmp(name, canon))) {
|
||||
return(xmlFindCharEncodingHandler(canon));
|
||||
}
|
||||
}
|
||||
enc = xmlParseCharEncoding(norig);
|
||||
return(xmlLookupCharEncodingHandler(enc, out));
|
||||
}
|
||||
|
||||
/* If "none of the above", give up */
|
||||
return(NULL);
|
||||
/**
|
||||
* xmlFindCharEncodingHandler:
|
||||
* @name: a string describing the char encoding.
|
||||
*
|
||||
* DEPRECATED: Use xmlOpenCharEncodingHandler which has better error
|
||||
* reporting.
|
||||
*
|
||||
* Returns the handler or NULL if no handler was found or an error
|
||||
* occurred.
|
||||
*/
|
||||
xmlCharEncodingHandlerPtr
|
||||
xmlFindCharEncodingHandler(const char *name) {
|
||||
xmlCharEncodingHandler *ret;
|
||||
|
||||
xmlOpenCharEncodingHandler(name, &ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -2169,7 +2309,8 @@ xmlCharEncInput(xmlParserInputBufferPtr input)
|
||||
else
|
||||
input->rawconsumed += c_in;
|
||||
|
||||
if ((c_out == 0) && (ret != 0)) {
|
||||
if (((ret != 0) && (c_out == 0)) ||
|
||||
(ret == XML_ENC_ERR_MEMORY)) {
|
||||
if (input->error == 0)
|
||||
input->error = xmlEncConvertError(ret);
|
||||
return(ret);
|
||||
@@ -2277,7 +2418,10 @@ retry:
|
||||
if (toconv > 64 * 1024)
|
||||
toconv = 64 * 1024;
|
||||
if (toconv * 4 >= written) {
|
||||
xmlBufGrow(out, toconv * 4);
|
||||
if (xmlBufGrow(out, toconv * 4) < 0) {
|
||||
ret = XML_ENC_ERR_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
written = xmlBufAvail(out);
|
||||
}
|
||||
if (written > 256 * 1024)
|
||||
@@ -2331,7 +2475,8 @@ retry:
|
||||
}
|
||||
|
||||
error:
|
||||
if ((writtentot <= 0) && (ret != 0)) {
|
||||
if (((writtentot <= 0) && (ret != 0)) ||
|
||||
(ret == XML_ENC_ERR_MEMORY)) {
|
||||
if (output->error == 0)
|
||||
output->error = xmlEncConvertError(ret);
|
||||
return(ret);
|
||||
|
||||
@@ -162,6 +162,12 @@ XMLPUBFUN void
|
||||
xmlCleanupCharEncodingHandlers (void);
|
||||
XMLPUBFUN void
|
||||
xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler);
|
||||
XMLPUBFUN int
|
||||
xmlLookupCharEncodingHandler (xmlCharEncoding enc,
|
||||
xmlCharEncodingHandlerPtr *out);
|
||||
XMLPUBFUN int
|
||||
xmlOpenCharEncodingHandler (const char *name,
|
||||
xmlCharEncodingHandlerPtr *out);
|
||||
XMLPUBFUN xmlCharEncodingHandlerPtr
|
||||
xmlGetCharEncodingHandler (xmlCharEncoding enc);
|
||||
XMLPUBFUN xmlCharEncodingHandlerPtr
|
||||
|
||||
@@ -211,6 +211,10 @@ typedef enum {
|
||||
XML_ERR_USER_STOP, /* 111 */
|
||||
XML_ERR_COMMENT_ABRUPTLY_ENDED, /* 112 */
|
||||
XML_WAR_ENCODING_MISMATCH, /* 113 */
|
||||
XML_ERR_RESOURCE_LIMIT, /* 114 */
|
||||
XML_ERR_ARGUMENT, /* 115 */
|
||||
XML_ERR_SYSTEM, /* 116 */
|
||||
XML_ERR_REDECL_PREDEF_ENTITY, /* 117 */
|
||||
XML_NS_ERR_XML_NAMESPACE = 200,
|
||||
XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */
|
||||
XML_NS_ERR_QNAME, /* 202 */
|
||||
|
||||
@@ -373,6 +373,18 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
|
||||
case XML_IO_UNKNOWN:
|
||||
errmsg = "I/O error";
|
||||
break;
|
||||
case XML_ERR_RESOURCE_LIMIT:
|
||||
errmsg = "Resource limit exceeded";
|
||||
break;
|
||||
case XML_ERR_ARGUMENT:
|
||||
errmsg = "Invalid argument";
|
||||
break;
|
||||
case XML_ERR_SYSTEM:
|
||||
errmsg = "Out of system resources";
|
||||
break;
|
||||
case XML_ERR_REDECL_PREDEF_ENTITY:
|
||||
errmsg = "Invalid redeclaration of predefined entity";
|
||||
break;
|
||||
#if 0
|
||||
case:
|
||||
errmsg = "";
|
||||
|
||||
Reference in New Issue
Block a user