From 64ad2725250f35e997c6a8df4e7d626bf7f29253 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 11 Jun 2024 03:51:43 +0200 Subject: [PATCH] parser: Introduce per-context resource loader --- SAX2.c | 12 +++++------ include/libxml/parser.h | 11 ++++++++++ parserInternals.c | 48 ++++++++++++++++++++++++++++++++++++++++- xmlIO.c | 4 ++++ 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/SAX2.c b/SAX2.c index 267a5fb3..103cfaff 100644 --- a/SAX2.c +++ b/SAX2.c @@ -391,16 +391,14 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, * @publicId: The public ID of the entity * @systemId: The system ID of the entity * - * The entity loader, to control the loading of external entities, - * the application can either: - * - override this xmlSAX2ResolveEntity() callback in the SAX block - * - or better use the xmlSetExternalEntityLoader() function to - * set up it's own entity resolution routine + * This is only used to load DTDs. The preferred way to install + * custom resolvers is xmlCtxtSetResourceLoader. * - * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. + * Returns a parser input. */ xmlParserInputPtr -xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId) +xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, + const xmlChar *systemId) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlParserInputPtr ret = NULL; diff --git a/include/libxml/parser.h b/include/libxml/parser.h index bad81cfb..c88e3f2e 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -159,6 +159,10 @@ typedef struct _xmlStartTag xmlStartTag; typedef struct _xmlParserNsData xmlParserNsData; typedef struct _xmlAttrHashBucket xmlAttrHashBucket; +typedef int +(*xmlResourceLoader)(void *ctxt, const char *url, const char *publicId, + int type, int flags, xmlParserInputPtr *out); + /** * xmlParserCtxt: * @@ -312,6 +316,9 @@ struct _xmlParserCtxt { xmlStructuredErrorFunc errorHandler; void *errorCtxt; + + xmlResourceLoader resourceLoader; + void *resourceCtxt; }; /** @@ -1197,6 +1204,10 @@ XMLPUBFUN void xmlSetExternalEntityLoader(xmlExternalEntityLoader f); XMLPUBFUN xmlExternalEntityLoader xmlGetExternalEntityLoader(void); +XMLPUBFUN void + xmlCtxtSetResourceLoader(xmlParserCtxtPtr ctxt, + xmlResourceLoader loader, + void *vctxt); XMLPUBFUN xmlParserInputPtr xmlLoadExternalEntity (const char *URL, const char *ID, diff --git a/parserInternals.c b/parserInternals.c index af411f21..29573c69 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -2306,6 +2306,8 @@ xmlDefaultExternalEntityLoader(const char *url, const char *ID, * @ID: the System ID for the entity to load * @ctxt: the context in which the entity is called or NULL * + * DEPRECATED: Use XML_PARSE_NONET. + * * A specific entity loader disabling network accesses, though still * allowing local catalog accesses for resolution. * @@ -2340,7 +2342,11 @@ xmlCurrentExternalEntityLoader = xmlDefaultExternalEntityLoader; * xmlSetExternalEntityLoader: * @f: the new entity resolver function * - * Changes the defaultexternal entity resolver function for the application + * DEPRECATED: This is a global setting and not thread-safe. Use + * xmlCtxtSetResourceLoader or similar functions. + * + * Changes the default external entity resolver function for the + * application. */ void xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { @@ -2350,6 +2356,8 @@ xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { /** * xmlGetExternalEntityLoader: * + * DEPRECATED: See xmlSetExternalEntityLoader. + * * Get the default external entity resolver function for the application * * Returns the xmlExternalEntityLoader function pointer @@ -2359,6 +2367,27 @@ xmlGetExternalEntityLoader(void) { return(xmlCurrentExternalEntityLoader); } +/** + * xmlCtxtSetResourceLoader: + * @ctxt: parser context + * @loader: callback + * @vctxt: user data + * + * Installs a custom callback to load documents, DTDs or external + * entities. + * + * Available since 2.14.0. + */ +void +xmlCtxtSetResourceLoader(xmlParserCtxtPtr ctxt, xmlResourceLoader loader, + void *vctxt) { + if (ctxt == NULL) + return; + + ctxt->resourceLoader = loader; + ctxt->resourceCtxt = vctxt; +} + /** * xmlLoadExternalEntity: * @URL: the URL for the entity to load @@ -2375,6 +2404,7 @@ xmlGetExternalEntityLoader(void) { * The following resource loaders will be called if they were * registered (in order of precedence): * + * - the resource loader set with xmlCtxtSetResourceLoader * - the global external entity loader set with * xmlSetExternalEntityLoader * - the per-thread xmlParserInputBufferCreateFilenameFunc set with @@ -2397,6 +2427,22 @@ xmlLoadExternalEntity(const char *URL, const char *ID, if (URL == NULL) return(NULL); + if ((ctxt != NULL) && (ctxt->resourceLoader != NULL)) { + int flags = 0; + int code; + + if ((ctxt->options & XML_PARSE_NO_UNZIP) == 0) + flags |= XML_INPUT_UNZIP; + + code = ctxt->resourceLoader(ctxt->resourceCtxt, URL, ID, flags, + 0, &ret); + if (code != XML_ERR_OK) { + xmlCtxtErrIO(ctxt, code, URL); + return(NULL); + } + return(ret); + } + canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); if (canonicFilename == NULL) { xmlCtxtErrMemory(ctxt); diff --git a/xmlIO.c b/xmlIO.c index 236038c4..956baded 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -2129,6 +2129,8 @@ xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite, * xmlParserInputBufferCreateFilenameDefault: * @func: function pointer to the new ParserInputBufferCreateFilenameFunc * + * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions. + * * Registers a callback for URI input file handling * * Returns the old value of the registration function @@ -2888,6 +2890,8 @@ xmlInitIOCallbacks(void) * @readFunc: the xmlInputReadCallback * @closeFunc: the xmlInputCloseCallback * + * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions. + * * Register a new set of I/O callback for handling parser input. * * Returns the registered handler number or -1 in case of error