mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-23 01:52:48 +03:00
io: Pass error codes from xmlFileOpenReal to xmlNewInputFromFile
This allows to report the reason why opening a file failed to the parser context and improve error messages. Now we can also remove the stat call before opening a file.
This commit is contained in:
@@ -5,13 +5,15 @@
|
|||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
#include <libxml/xmlversion.h>
|
#include <libxml/xmlversion.h>
|
||||||
|
|
||||||
XML_HIDDEN void
|
XML_HIDDEN int
|
||||||
__xmlIOErr(int domain, int code, const char *extra);
|
__xmlIOErr(int domain, int code, const char *extra);
|
||||||
XML_HIDDEN void
|
XML_HIDDEN void
|
||||||
xmlLoaderErr(xmlParserCtxtPtr ctxt, const char *msg,
|
xmlLoaderErr(xmlParserCtxtPtr ctxt, int code, const char *filename);
|
||||||
const char *filename) LIBXML_ATTR_FORMAT(2,0);
|
|
||||||
|
|
||||||
xmlParserInputBufferPtr
|
XML_HIDDEN int
|
||||||
|
xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc,
|
||||||
|
xmlParserInputBufferPtr *out);
|
||||||
|
XML_HIDDEN xmlParserInputBufferPtr
|
||||||
xmlParserInputBufferCreateString(const xmlChar *str);
|
xmlParserInputBufferCreateString(const xmlChar *str);
|
||||||
|
|
||||||
#ifdef LIBXML_OUTPUT_ENABLED
|
#ifdef LIBXML_OUTPUT_ENABLED
|
||||||
|
@@ -1804,17 +1804,15 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
|
|||||||
xmlParserInputPtr inputStream;
|
xmlParserInputPtr inputStream;
|
||||||
char *directory = NULL;
|
char *directory = NULL;
|
||||||
xmlChar *URI = NULL;
|
xmlChar *URI = NULL;
|
||||||
|
int code;
|
||||||
|
|
||||||
if (ctxt == NULL) return(NULL);
|
if ((ctxt == NULL) || (filename == NULL))
|
||||||
buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
|
return(NULL);
|
||||||
|
|
||||||
|
code = xmlParserInputBufferCreateFilenameSafe(filename,
|
||||||
|
XML_CHAR_ENCODING_NONE, &buf);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
if (filename == NULL)
|
xmlLoaderErr(ctxt, code, filename);
|
||||||
xmlLoaderErr(ctxt,
|
|
||||||
"failed to load external entity: NULL filename\n",
|
|
||||||
NULL);
|
|
||||||
else
|
|
||||||
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
|
|
||||||
(const char *) filename);
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ import libxml2
|
|||||||
# Memory debug specific
|
# Memory debug specific
|
||||||
libxml2.debugMemory(1)
|
libxml2.debugMemory(1)
|
||||||
|
|
||||||
expect='--> I/O --> warning : --> failed to load external entity "missing.xml"\n'
|
expect='--> I/O --> warning : --> failed to load "missing.xml": No such file or directory\n'
|
||||||
err=""
|
err=""
|
||||||
def callback(ctx, str):
|
def callback(ctx, str):
|
||||||
global err
|
global err
|
||||||
|
@@ -91,7 +91,7 @@ run_test(desc="Loading entity without custom callback",
|
|||||||
exp_status="not loaded", exp_err=[
|
exp_status="not loaded", exp_err=[
|
||||||
(-1, "I/O "),
|
(-1, "I/O "),
|
||||||
(-1, "warning : "),
|
(-1, "warning : "),
|
||||||
(-1, "failed to load external entity \"py://strings/xml/sample.xml\"\n")
|
(-1, "failed to load \"py://strings/xml/sample.xml\": No such file or directory\n")
|
||||||
])
|
])
|
||||||
|
|
||||||
# Register handler and try to load the same entity
|
# Register handler and try to load the same entity
|
||||||
@@ -99,7 +99,7 @@ libxml2.registerInputCallback(my_input_cb)
|
|||||||
run_test(desc="Loading entity with custom callback",
|
run_test(desc="Loading entity with custom callback",
|
||||||
docpath=startURL, catalog=None,
|
docpath=startURL, catalog=None,
|
||||||
exp_status="loaded", exp_err=[
|
exp_status="loaded", exp_err=[
|
||||||
( 3, "Attempt to load network entity http://example.com/dtds/sample.dtd"),
|
( 3, 'failed to load "http://example.com/dtds/sample.dtd": Attempt to load network entity\n'),
|
||||||
( 4, "Entity 'sample.entity' not defined\n")
|
( 4, "Entity 'sample.entity' not defined\n")
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ run_test(desc="Loading entity and unregistering callback",
|
|||||||
docpath=startURL, catalog=catURL,
|
docpath=startURL, catalog=catURL,
|
||||||
test_callback=lambda: libxml2.popInputCallbacks(),
|
test_callback=lambda: libxml2.popInputCallbacks(),
|
||||||
exp_status="loaded", exp_err=[
|
exp_status="loaded", exp_err=[
|
||||||
( 3, "failed to load external entity \"py://strings/dtds/sample.dtd\"\n"),
|
( 3, "failed to load \"py://strings/dtds/sample.dtd\": No such file or directory\n"),
|
||||||
( 4, "Entity 'sample.entity' not defined\n")
|
( 4, "Entity 'sample.entity' not defined\n")
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ run_test(desc="Retry loading document after unregistering callback",
|
|||||||
exp_status="not loaded", exp_err=[
|
exp_status="not loaded", exp_err=[
|
||||||
(-1, "I/O "),
|
(-1, "I/O "),
|
||||||
(-1, "warning : "),
|
(-1, "warning : "),
|
||||||
(-1, "failed to load external entity \"py://strings/xml/sample.xml\"\n")
|
(-1, "failed to load \"py://strings/xml/sample.xml\": No such file or directory\n")
|
||||||
])
|
])
|
||||||
|
|
||||||
# But should be able to read standard I/O yet...
|
# But should be able to read standard I/O yet...
|
||||||
@@ -142,7 +142,7 @@ run_test(desc="Loading using standard i/o after unregistering all callbacks",
|
|||||||
exp_status="not loaded", exp_err=[
|
exp_status="not loaded", exp_err=[
|
||||||
(-1, "I/O "),
|
(-1, "I/O "),
|
||||||
(-1, "warning : "),
|
(-1, "warning : "),
|
||||||
(-1, "failed to load external entity \"tst.xml\"\n")
|
(-1, "failed to load \"tst.xml\": No such file or directory\n")
|
||||||
])
|
])
|
||||||
|
|
||||||
print("OK")
|
print("OK")
|
||||||
|
@@ -58,8 +58,8 @@ class TestCase(unittest.TestCase):
|
|||||||
("dummy.xml",None,0),
|
("dummy.xml",None,0),
|
||||||
libxml2.treeError,
|
libxml2.treeError,
|
||||||
domain=libxml2.XML_FROM_IO,
|
domain=libxml2.XML_FROM_IO,
|
||||||
code=libxml2.XML_IO_LOAD_ERROR,
|
code=libxml2.XML_IO_ENOENT,
|
||||||
message='failed to load external entity "dummy.xml"\n',
|
message='failed to load "dummy.xml": No such file or directory\n',
|
||||||
level=libxml2.XML_ERR_WARNING,
|
level=libxml2.XML_ERR_WARNING,
|
||||||
file=None,
|
file=None,
|
||||||
line=0)
|
line=0)
|
||||||
|
@@ -1 +1 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/docs/something.xml"
|
I/O warning : failed to load "test/XInclude/docs/something.xml": No such file or directory
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/docs/b.xml"
|
I/O warning : failed to load "test/XInclude/docs/b.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/c.xml"
|
I/O warning : failed to load "test/XInclude/docs/c.xml": No such file or directory
|
||||||
|
@@ -1 +1 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/docs/c.xml"
|
I/O warning : failed to load "test/XInclude/docs/c.xml": No such file or directory
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/docs/a01.xml"
|
I/O warning : failed to load "test/XInclude/docs/a01.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a02.xml"
|
I/O warning : failed to load "test/XInclude/docs/a02.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a03.xml"
|
I/O warning : failed to load "test/XInclude/docs/a03.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a04.xml"
|
I/O warning : failed to load "test/XInclude/docs/a04.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a05.xml"
|
I/O warning : failed to load "test/XInclude/docs/a05.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a06.xml"
|
I/O warning : failed to load "test/XInclude/docs/a06.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a07.xml"
|
I/O warning : failed to load "test/XInclude/docs/a07.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a08.xml"
|
I/O warning : failed to load "test/XInclude/docs/a08.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a09.xml"
|
I/O warning : failed to load "test/XInclude/docs/a09.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a10.xml"
|
I/O warning : failed to load "test/XInclude/docs/a10.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a11.xml"
|
I/O warning : failed to load "test/XInclude/docs/a11.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a12.xml"
|
I/O warning : failed to load "test/XInclude/docs/a12.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a13.xml"
|
I/O warning : failed to load "test/XInclude/docs/a13.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a14.xml"
|
I/O warning : failed to load "test/XInclude/docs/a14.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a15.xml"
|
I/O warning : failed to load "test/XInclude/docs/a15.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/a16.xml"
|
I/O warning : failed to load "test/XInclude/docs/a16.xml": No such file or directory
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/docs/b.xml"
|
I/O warning : failed to load "test/XInclude/docs/b.xml": No such file or directory
|
||||||
I/O warning : failed to load external entity "test/XInclude/docs/c.xml"
|
I/O warning : failed to load "test/XInclude/docs/c.xml": No such file or directory
|
||||||
|
@@ -1 +1 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/without-reader/404.xml"
|
I/O warning : failed to load "test/XInclude/without-reader/404.xml": No such file or directory
|
||||||
|
@@ -1 +1 @@
|
|||||||
I/O warning : failed to load external entity "test/XInclude/without-reader/b.xml"
|
I/O warning : failed to load "test/XInclude/without-reader/b.xml": No such file or directory
|
||||||
|
@@ -1 +1 @@
|
|||||||
I/O warning : failed to load external entity "/etc/doesnotexist"
|
I/O warning : failed to load "/etc/doesnotexist": No such file or directory
|
||||||
|
260
xmlIO.c
260
xmlIO.c
@@ -228,7 +228,7 @@ xmlIOErrMemory(void)
|
|||||||
*
|
*
|
||||||
* Handle an I/O error
|
* Handle an I/O error
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
__xmlIOErr(int domain, int code, const char *extra)
|
__xmlIOErr(int domain, int code, const char *extra)
|
||||||
{
|
{
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
@@ -399,8 +399,12 @@ __xmlIOErr(int domain, int code, const char *extra)
|
|||||||
domain, code, XML_ERR_ERROR, NULL, 0,
|
domain, code, XML_ERR_ERROR, NULL, 0,
|
||||||
extra, NULL, NULL, 0, 0,
|
extra, NULL, NULL, 0, 0,
|
||||||
IOerr[idx], extra);
|
IOerr[idx], extra);
|
||||||
if (res < 0)
|
if (res < 0) {
|
||||||
xmlIOErrMemory();
|
xmlIOErrMemory();
|
||||||
|
return(XML_ERR_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -410,33 +414,40 @@ __xmlIOErr(int domain, int code, const char *extra)
|
|||||||
*
|
*
|
||||||
* Handle an I/O error
|
* Handle an I/O error
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
xmlIOErr(int code, const char *extra)
|
xmlIOErr(int code, const char *extra)
|
||||||
{
|
{
|
||||||
__xmlIOErr(XML_FROM_IO, code, extra);
|
return(__xmlIOErr(XML_FROM_IO, code, extra));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __xmlLoaderErr:
|
* xmlLoaderErr:
|
||||||
* @ctx: the parser context
|
* @ctx: parser context
|
||||||
* @extra: extra information
|
* @code: error code
|
||||||
|
* @filename: file name
|
||||||
*
|
*
|
||||||
* Handle a resource access error
|
* Handle a resource access error
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlLoaderErr(xmlParserCtxtPtr ctxt, const char *msg, const char *filename)
|
xmlLoaderErr(xmlParserCtxtPtr ctxt, int code, const char *filename)
|
||||||
{
|
{
|
||||||
xmlErrorLevel level;
|
xmlErrorLevel level;
|
||||||
|
unsigned idx = 0;
|
||||||
|
|
||||||
if (ctxt->validate)
|
if (ctxt->validate)
|
||||||
level = XML_ERR_ERROR;
|
level = XML_ERR_ERROR;
|
||||||
else
|
else
|
||||||
level = XML_ERR_WARNING;
|
level = XML_ERR_WARNING;
|
||||||
|
|
||||||
xmlErrParser(ctxt, NULL, XML_FROM_IO, XML_IO_LOAD_ERROR, level,
|
if (code >= XML_IO_UNKNOWN) {
|
||||||
(const xmlChar *) filename, NULL, NULL, 0,
|
idx = code - XML_IO_UNKNOWN;
|
||||||
msg, filename);
|
if (idx >= (sizeof(IOerr) / sizeof(IOerr[0])))
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlErrParser(ctxt, NULL, XML_FROM_IO, code, level,
|
||||||
|
(const xmlChar *) filename, NULL, NULL, 0,
|
||||||
|
"failed to load \"%s\": %s\n", filename, IOerr[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -736,25 +747,28 @@ xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlFileOpen_real:
|
* xmlFileOpenReal:
|
||||||
* @filename: the URI for matching
|
* @filename: the URI for matching
|
||||||
|
* @out: pointer to resulting context
|
||||||
*
|
*
|
||||||
* input from FILE *, supports compressed input
|
* input from FILE *, supports compressed input
|
||||||
* if @filename is " " then the standard input is used
|
* if @filename is "-" then the standard input is used
|
||||||
*
|
*
|
||||||
* Returns an I/O context or NULL in case of error
|
* Returns an I/O context or NULL in case of error
|
||||||
*/
|
*/
|
||||||
static void *
|
static int
|
||||||
xmlFileOpen_real (const char *filename) {
|
xmlFileOpenReal(const char *filename, void **out) {
|
||||||
const char *path = filename;
|
const char *path = filename;
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
|
int ret = XML_ERR_OK;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
if (filename == NULL)
|
if (filename == NULL)
|
||||||
return(NULL);
|
return(XML_ERR_ARGUMENT);
|
||||||
|
|
||||||
if (!strcmp(filename, "-")) {
|
if (!strcmp(filename, "-")) {
|
||||||
fd = stdin;
|
*out = stdin;
|
||||||
return((void *) fd);
|
return(XML_ERR_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
|
if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) {
|
||||||
@@ -778,45 +792,76 @@ xmlFileOpen_real (const char *filename) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not check DDNAME on zOS ! */
|
|
||||||
#if !defined(__MVS__)
|
|
||||||
if (!xmlCheckFilename(path))
|
|
||||||
return(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
fd = xmlWrapOpenUtf8(path, 0);
|
fd = xmlWrapOpenUtf8(path, 0);
|
||||||
#else
|
#else
|
||||||
fd = fopen(path, "rb");
|
fd = fopen(path, "rb");
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
if (fd == NULL) xmlIOErr(0, path);
|
|
||||||
return((void *) fd);
|
if (fd == NULL) {
|
||||||
|
/*
|
||||||
|
* Windows and possibly other platforms return EINVAL
|
||||||
|
* for invalid filenames.
|
||||||
|
*/
|
||||||
|
if ((errno == ENOENT) || (errno == EINVAL)) {
|
||||||
|
ret = XML_IO_ENOENT;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This error won't be forwarded to the parser context
|
||||||
|
* which will report it a second time.
|
||||||
|
*/
|
||||||
|
ret = xmlIOErr(0, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = fd;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlFileOpenSafe:
|
||||||
|
* @filename: the URI for matching
|
||||||
|
* @out: pointer to resulting context
|
||||||
|
*
|
||||||
|
* Wrapper around xmlFileOpen_real that try it with an unescaped
|
||||||
|
* version of @filename, if this fails fallback to @filename
|
||||||
|
*
|
||||||
|
* Returns an xmlParserErrors code.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xmlFileOpenSafe(const char *filename, void **out) {
|
||||||
|
char *unescaped;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = xmlFileOpenReal(filename, out);
|
||||||
|
if (retval == XML_ERR_OK)
|
||||||
|
return(retval);
|
||||||
|
|
||||||
|
if (retval == XML_IO_ENOENT) {
|
||||||
|
unescaped = xmlURIUnescapeString(filename, 0, NULL);
|
||||||
|
if (unescaped == NULL)
|
||||||
|
return(XML_ERR_NO_MEMORY);
|
||||||
|
retval = xmlFileOpenReal(unescaped, out);
|
||||||
|
xmlFree(unescaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlFileOpen:
|
* xmlFileOpen:
|
||||||
* @filename: the URI for matching
|
* @filename: the URI for matching
|
||||||
*
|
*
|
||||||
* Wrapper around xmlFileOpen_real that try it with an unescaped
|
* Open a file.
|
||||||
* version of @filename, if this fails fallback to @filename
|
|
||||||
*
|
*
|
||||||
* Returns a handler or NULL in case or failure
|
* Returns an IO context or NULL in case or failure
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
xmlFileOpen (const char *filename) {
|
xmlFileOpen(const char *filename) {
|
||||||
char *unescaped;
|
void *context;
|
||||||
void *retval;
|
|
||||||
|
|
||||||
retval = xmlFileOpen_real(filename);
|
xmlFileOpenSafe(filename, &context);
|
||||||
if (retval == NULL) {
|
return(context);
|
||||||
unescaped = xmlURIUnescapeString(filename, 0, NULL);
|
|
||||||
if (unescaped != NULL) {
|
|
||||||
retval = xmlFileOpen_real(unescaped);
|
|
||||||
xmlFree(unescaped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBXML_OUTPUT_ENABLED
|
#ifdef LIBXML_OUTPUT_ENABLED
|
||||||
@@ -2066,8 +2111,17 @@ xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) {
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlInputDefaultOpen:
|
||||||
|
* @buf: input buffer to be filled
|
||||||
|
* @filename: filename or URI
|
||||||
|
*
|
||||||
|
* Returns an xmlParserErrors code.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename) {
|
xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
#ifdef LIBXML_FTP_ENABLED
|
#ifdef LIBXML_FTP_ENABLED
|
||||||
if (xmlIOFTPMatch(filename)) {
|
if (xmlIOFTPMatch(filename)) {
|
||||||
buf->context = xmlIOFTPOpen(filename);
|
buf->context = xmlIOFTPOpen(filename);
|
||||||
@@ -2140,13 +2194,15 @@ xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename) {
|
|||||||
#endif /* LIBXML_ZLIB_ENABLED */
|
#endif /* LIBXML_ZLIB_ENABLED */
|
||||||
|
|
||||||
if (xmlFileMatch(filename)) {
|
if (xmlFileMatch(filename)) {
|
||||||
buf->context = xmlFileOpen(filename);
|
ret = xmlFileOpenSafe(filename, &buf->context);
|
||||||
|
|
||||||
if (buf->context != NULL) {
|
if (buf->context != NULL) {
|
||||||
buf->readcallback = xmlFileRead;
|
buf->readcallback = xmlFileRead;
|
||||||
buf->closecallback = xmlFileClose;
|
buf->closecallback = xmlFileClose;
|
||||||
return(XML_ERR_OK);
|
return(XML_ERR_OK);
|
||||||
}
|
}
|
||||||
|
if (ret != XML_IO_ENOENT)
|
||||||
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(XML_IO_ENOENT);
|
return(XML_IO_ENOENT);
|
||||||
@@ -2163,6 +2219,15 @@ xmlRegisterDefaultInputCallbacks(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBXML_OUTPUT_ENABLED
|
#ifdef LIBXML_OUTPUT_ENABLED
|
||||||
|
/**
|
||||||
|
* xmlOutputDefaultOpen:
|
||||||
|
* @buf: input buffer to be filled
|
||||||
|
* @filename: filename or URI
|
||||||
|
* @compression: compression level or 0
|
||||||
|
* @is_file_uri: whether filename is a file URI
|
||||||
|
*
|
||||||
|
* Returns an xmlParserErrors code.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
|
xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
|
||||||
int compression, int is_file_uri) {
|
int compression, int is_file_uri) {
|
||||||
@@ -2448,49 +2513,71 @@ xmlOutputBufferClose(xmlOutputBufferPtr out)
|
|||||||
}
|
}
|
||||||
#endif /* LIBXML_OUTPUT_ENABLED */
|
#endif /* LIBXML_OUTPUT_ENABLED */
|
||||||
|
|
||||||
xmlParserInputBufferPtr
|
/**
|
||||||
__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
* xmlParserInputBufferCreateFilenameInt:
|
||||||
xmlParserInputBufferPtr ret;
|
* @URI: the filename or URI
|
||||||
int i = 0;
|
* @enc: encoding enum (deprecated)
|
||||||
|
* @out: pointer to resulting input buffer
|
||||||
|
*
|
||||||
|
* Returns an xmlParserErrors code.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xmlParserInputBufferCreateFilenameInt(const char *URI, xmlCharEncoding enc,
|
||||||
|
xmlParserInputBufferPtr *out) {
|
||||||
|
xmlParserInputBufferPtr buf;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (URI == NULL) return(NULL);
|
*out = NULL;
|
||||||
|
if (URI == NULL)
|
||||||
|
return(XML_ERR_ARGUMENT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate the Input buffer front-end.
|
* Allocate the Input buffer front-end.
|
||||||
*/
|
*/
|
||||||
ret = xmlAllocParserInputBuffer(enc);
|
buf = xmlAllocParserInputBuffer(enc);
|
||||||
if (ret == NULL)
|
if (buf == NULL)
|
||||||
return(NULL);
|
return(XML_ERR_NO_MEMORY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find one of the input accept method accepting that scheme
|
* Try to find one of the input accept method accepting that scheme
|
||||||
* Go in reverse to give precedence to user defined handlers.
|
* Go in reverse to give precedence to user defined handlers.
|
||||||
*/
|
*/
|
||||||
|
ret = XML_IO_ENOENT;
|
||||||
for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
|
for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
|
||||||
xmlInputCallback *cb = &xmlInputCallbackTable[i];
|
xmlInputCallback *cb = &xmlInputCallbackTable[i];
|
||||||
|
|
||||||
if (cb->matchcallback == xmlIODefaultMatch) {
|
if (cb->matchcallback == xmlIODefaultMatch) {
|
||||||
int code = xmlInputDefaultOpen(ret, URI);
|
ret = xmlInputDefaultOpen(buf, URI);
|
||||||
|
|
||||||
if (code == XML_ERR_OK)
|
if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT))
|
||||||
break;
|
break;
|
||||||
/* TODO: Handle other errors */
|
|
||||||
} else if ((cb->matchcallback != NULL) &&
|
} else if ((cb->matchcallback != NULL) &&
|
||||||
(cb->matchcallback(URI) != 0)) {
|
(cb->matchcallback(URI) != 0)) {
|
||||||
ret->context = cb->opencallback(URI);
|
buf->context = cb->opencallback(URI);
|
||||||
if (ret->context != NULL) {
|
if (buf->context != NULL) {
|
||||||
ret->readcallback = cb->readcallback;
|
buf->readcallback = cb->readcallback;
|
||||||
ret->closecallback = cb->closecallback;
|
buf->closecallback = cb->closecallback;
|
||||||
|
ret = XML_ERR_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret->context == NULL) {
|
if (ret != XML_ERR_OK) {
|
||||||
xmlFreeParserInputBuffer(ret);
|
xmlFreeParserInputBuffer(buf);
|
||||||
/* TODO: Return not found error */
|
*out = NULL;
|
||||||
return(NULL);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out = buf;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlParserInputBufferPtr
|
||||||
|
__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
||||||
|
xmlParserInputBufferPtr ret;
|
||||||
|
|
||||||
|
xmlParserInputBufferCreateFilenameInt(URI, enc, &ret);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2500,7 +2587,7 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
|||||||
* @enc: the charset encoding if known
|
* @enc: the charset encoding if known
|
||||||
*
|
*
|
||||||
* Create a buffered parser input for the progressive parsing of a file
|
* Create a buffered parser input for the progressive parsing of a file
|
||||||
* If filename is "-' then we use stdin as the input.
|
* If filename is "-" then we use stdin as the input.
|
||||||
* Automatic support for ZLIB/Compress compressed document is provided
|
* Automatic support for ZLIB/Compress compressed document is provided
|
||||||
* by default if found at compile-time.
|
* by default if found at compile-time.
|
||||||
* Do an encoding check if enc == XML_CHAR_ENCODING_NONE
|
* Do an encoding check if enc == XML_CHAR_ENCODING_NONE
|
||||||
@@ -2509,10 +2596,32 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
|||||||
*/
|
*/
|
||||||
xmlParserInputBufferPtr
|
xmlParserInputBufferPtr
|
||||||
xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
||||||
if ((xmlParserInputBufferCreateFilenameValue)) {
|
if (xmlParserInputBufferCreateFilenameValue != NULL)
|
||||||
return xmlParserInputBufferCreateFilenameValue(URI, enc);
|
return(xmlParserInputBufferCreateFilenameValue(URI, enc));
|
||||||
}
|
|
||||||
return __xmlParserInputBufferCreateFilename(URI, enc);
|
return(__xmlParserInputBufferCreateFilename(URI, enc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlParserInputBufferCreateFilenameSafe:
|
||||||
|
* @URI: the filename or URI
|
||||||
|
* @enc: encoding enum (deprecated)
|
||||||
|
* @out: pointer to resulting input buffer
|
||||||
|
*
|
||||||
|
* Returns an xmlParserErrors code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc,
|
||||||
|
xmlParserInputBufferPtr *out) {
|
||||||
|
if (xmlParserInputBufferCreateFilenameValue != NULL) {
|
||||||
|
*out = xmlParserInputBufferCreateFilenameValue(URI, enc);
|
||||||
|
|
||||||
|
if (*out == NULL)
|
||||||
|
return(XML_IO_ENOENT);
|
||||||
|
return(XML_ERR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(xmlParserInputBufferCreateFilenameInt(URI, enc, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBXML_OUTPUT_ENABLED
|
#ifdef LIBXML_OUTPUT_ENABLED
|
||||||
@@ -3723,10 +3832,9 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) {
|
|||||||
if (code >= 400) {
|
if (code >= 400) {
|
||||||
/* fatal error */
|
/* fatal error */
|
||||||
if (ret->filename != NULL)
|
if (ret->filename != NULL)
|
||||||
xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n",
|
xmlLoaderErr(ctxt, XML_IO_LOAD_ERROR, ret->filename);
|
||||||
(const char *) ret->filename);
|
|
||||||
else
|
else
|
||||||
xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL);
|
xmlLoaderErr(ctxt, XML_IO_LOAD_ERROR, "<null>");
|
||||||
xmlFreeInputStream(ret);
|
xmlFreeInputStream(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
} else {
|
} else {
|
||||||
@@ -3877,6 +3985,9 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
|
|||||||
xmlParserInputPtr ret = NULL;
|
xmlParserInputPtr ret = NULL;
|
||||||
xmlChar *resource = NULL;
|
xmlChar *resource = NULL;
|
||||||
|
|
||||||
|
if (URL == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
|
if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
|
||||||
int options = ctxt->options;
|
int options = ctxt->options;
|
||||||
|
|
||||||
@@ -3892,13 +4003,6 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
|
|||||||
if (resource == NULL)
|
if (resource == NULL)
|
||||||
resource = (xmlChar *) URL;
|
resource = (xmlChar *) URL;
|
||||||
|
|
||||||
if (resource == NULL) {
|
|
||||||
if (ID == NULL)
|
|
||||||
ID = "NULL";
|
|
||||||
if (ctxt != NULL)
|
|
||||||
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
ret = xmlNewInputFromFile(ctxt, (const char *) resource);
|
ret = xmlNewInputFromFile(ctxt, (const char *) resource);
|
||||||
if ((resource != NULL) && (resource != (xmlChar *) URL))
|
if ((resource != NULL) && (resource != (xmlChar *) URL))
|
||||||
xmlFree(resource);
|
xmlFree(resource);
|
||||||
@@ -3995,7 +4099,7 @@ xmlNoNetExternalEntityLoader(const char *URL, const char *ID,
|
|||||||
if (resource != NULL) {
|
if (resource != NULL) {
|
||||||
if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
|
if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) ||
|
||||||
(!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
|
(!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) {
|
||||||
xmlLoaderErr(ctxt, "Attempt to load network entity %s",
|
xmlLoaderErr(ctxt, XML_IO_NETWORK_ATTEMPT,
|
||||||
(const char *) resource);
|
(const char *) resource);
|
||||||
if (resource != (xmlChar *) URL)
|
if (resource != (xmlChar *) URL)
|
||||||
xmlFree(resource);
|
xmlFree(resource);
|
||||||
|
Reference in New Issue
Block a user