123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /*
- * documents.c: Implementation of the documents handling
- *
- * See Copyright for the status of this software.
- *
- * daniel@veillard.com
- */
- #define IN_LIBXSLT
- #include "libxslt.h"
- #include <string.h>
- #include <libxml/xmlmemory.h>
- #include <libxml/tree.h>
- #include <libxml/hash.h>
- #include <libxml/parser.h>
- #include <libxml/parserInternals.h>
- #include "xslt.h"
- #include "xsltInternals.h"
- #include "xsltutils.h"
- #include "documents.h"
- #include "transform.h"
- #include "imports.h"
- #include "keys.h"
- #include "security.h"
- #ifdef LIBXML_XINCLUDE_ENABLED
- #include <libxml/xinclude.h>
- #endif
- #define WITH_XSLT_DEBUG_DOCUMENTS
- #ifdef WITH_XSLT_DEBUG
- #define WITH_XSLT_DEBUG_DOCUMENTS
- #endif
- /************************************************************************
- * *
- * Hooks for the document loader *
- * *
- ************************************************************************/
- /**
- * xsltDocDefaultLoaderFunc:
- * @URI: the URI of the document to load
- * @dict: the dictionary to use when parsing that document
- * @options: parsing options, a set of xmlParserOption
- * @ctxt: the context, either a stylesheet or a transformation context
- * @type: the xsltLoadType indicating the kind of loading required
- *
- * Default function to load document not provided by the compilation or
- * transformation API themselve, for example when an xsl:import,
- * xsl:include is found at compilation time or when a document()
- * call is made at runtime.
- *
- * Returns the pointer to the document (which will be modified and
- * freed by the engine later), or NULL in case of error.
- */
- static xmlDocPtr
- xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
- void *ctxt ATTRIBUTE_UNUSED,
- xsltLoadType type ATTRIBUTE_UNUSED)
- {
- xmlParserCtxtPtr pctxt;
- xmlParserInputPtr inputStream;
- xmlDocPtr doc;
- pctxt = xmlNewParserCtxt();
- if (pctxt == NULL)
- return(NULL);
- if ((dict != NULL) && (pctxt->dict != NULL)) {
- xmlDictFree(pctxt->dict);
- pctxt->dict = NULL;
- }
- if (dict != NULL) {
- pctxt->dict = dict;
- xmlDictReference(pctxt->dict);
- #ifdef WITH_XSLT_DEBUG
- xsltGenericDebug(xsltGenericDebugContext,
- "Reusing dictionary for document\n");
- #endif
- }
- xmlCtxtUseOptions(pctxt, options);
- inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
- if (inputStream == NULL) {
- xmlFreeParserCtxt(pctxt);
- return(NULL);
- }
- inputPush(pctxt, inputStream);
- if (pctxt->directory == NULL)
- pctxt->directory = xmlParserGetDirectory((const char *) URI);
- xmlParseDocument(pctxt);
- if (pctxt->wellFormed) {
- doc = pctxt->myDoc;
- }
- else {
- doc = NULL;
- xmlFreeDoc(pctxt->myDoc);
- pctxt->myDoc = NULL;
- }
- xmlFreeParserCtxt(pctxt);
- return(doc);
- }
- xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
- /**
- * xsltSetLoaderFunc:
- * @f: the new function to handle document loading.
- *
- * Set the new function to load document, if NULL it resets it to the
- * default function.
- */
- void
- xsltSetLoaderFunc(xsltDocLoaderFunc f) {
- if (f == NULL)
- xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
- else
- xsltDocDefaultLoader = f;
- }
- /************************************************************************
- * *
- * Module interfaces *
- * *
- ************************************************************************/
- /**
- * xsltNewDocument:
- * @ctxt: an XSLT transformation context (or NULL)
- * @doc: a parsed XML document
- *
- * Register a new document, apply key computations
- *
- * Returns a handler to the document
- */
- xsltDocumentPtr
- xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
- xsltDocumentPtr cur;
- cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
- if (cur == NULL) {
- xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
- "xsltNewDocument : malloc failed\n");
- return(NULL);
- }
- memset(cur, 0, sizeof(xsltDocument));
- cur->doc = doc;
- if (ctxt != NULL) {
- if (! XSLT_IS_RES_TREE_FRAG(doc)) {
- cur->next = ctxt->docList;
- ctxt->docList = cur;
- }
- /*
- * A key with a specific name for a specific document
- * will only be computed if there's a call to the key()
- * function using that specific name for that specific
- * document. I.e. computation of keys will be done in
- * xsltGetKey() (keys.c) on an on-demand basis.
- *
- * xsltInitCtxtKeys(ctxt, cur); not called here anymore
- */
- }
- return(cur);
- }
- /**
- * xsltNewStyleDocument:
- * @style: an XSLT style sheet
- * @doc: a parsed XML document
- *
- * Register a new document, apply key computations
- *
- * Returns a handler to the document
- */
- xsltDocumentPtr
- xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
- xsltDocumentPtr cur;
- cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
- if (cur == NULL) {
- xsltTransformError(NULL, style, (xmlNodePtr) doc,
- "xsltNewStyleDocument : malloc failed\n");
- return(NULL);
- }
- memset(cur, 0, sizeof(xsltDocument));
- cur->doc = doc;
- if (style != NULL) {
- cur->next = style->docList;
- style->docList = cur;
- }
- return(cur);
- }
- /**
- * xsltFreeStyleDocuments:
- * @style: an XSLT stylesheet (representing a stylesheet-level)
- *
- * Frees the node-trees (and xsltDocument structures) of all
- * stylesheet-modules of the stylesheet-level represented by
- * the given @style.
- */
- void
- xsltFreeStyleDocuments(xsltStylesheetPtr style) {
- xsltDocumentPtr doc, cur;
- #ifdef XSLT_REFACTORED_XSLT_NSCOMP
- xsltNsMapPtr nsMap;
- #endif
- if (style == NULL)
- return;
- #ifdef XSLT_REFACTORED_XSLT_NSCOMP
- if (XSLT_HAS_INTERNAL_NSMAP(style))
- nsMap = XSLT_GET_INTERNAL_NSMAP(style);
- else
- nsMap = NULL;
- #endif
- cur = style->docList;
- while (cur != NULL) {
- doc = cur;
- cur = cur->next;
- #ifdef XSLT_REFACTORED_XSLT_NSCOMP
- /*
- * Restore all changed namespace URIs of ns-decls.
- */
- if (nsMap)
- xsltRestoreDocumentNamespaces(nsMap, doc->doc);
- #endif
- xsltFreeDocumentKeys(doc);
- if (!doc->main)
- xmlFreeDoc(doc->doc);
- xmlFree(doc);
- }
- }
- /**
- * xsltFreeDocuments:
- * @ctxt: an XSLT transformation context
- *
- * Free up all the space used by the loaded documents
- */
- void
- xsltFreeDocuments(xsltTransformContextPtr ctxt) {
- xsltDocumentPtr doc, cur;
- cur = ctxt->docList;
- while (cur != NULL) {
- doc = cur;
- cur = cur->next;
- xsltFreeDocumentKeys(doc);
- if (!doc->main)
- xmlFreeDoc(doc->doc);
- xmlFree(doc);
- }
- cur = ctxt->styleList;
- while (cur != NULL) {
- doc = cur;
- cur = cur->next;
- xsltFreeDocumentKeys(doc);
- if (!doc->main)
- xmlFreeDoc(doc->doc);
- xmlFree(doc);
- }
- }
- /**
- * xsltLoadDocument:
- * @ctxt: an XSLT transformation context
- * @URI: the computed URI of the document
- *
- * Try to load a document (not a stylesheet)
- * within the XSLT transformation context
- *
- * Returns the new xsltDocumentPtr or NULL in case of error
- */
- xsltDocumentPtr
- xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
- xsltDocumentPtr ret;
- xmlDocPtr doc;
- if ((ctxt == NULL) || (URI == NULL))
- return(NULL);
- /*
- * Security framework check
- */
- if (ctxt->sec != NULL) {
- int res;
- res = xsltCheckRead(ctxt->sec, ctxt, URI);
- if (res <= 0) {
- if (res == 0)
- xsltTransformError(ctxt, NULL, NULL,
- "xsltLoadDocument: read rights for %s denied\n",
- URI);
- return(NULL);
- }
- }
- /*
- * Walk the context list to find the document if preparsed
- */
- ret = ctxt->docList;
- while (ret != NULL) {
- if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
- (xmlStrEqual(ret->doc->URL, URI)))
- return(ret);
- ret = ret->next;
- }
- doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
- (void *) ctxt, XSLT_LOAD_DOCUMENT);
- if (doc == NULL)
- return(NULL);
- if (ctxt->xinclude != 0) {
- #ifdef LIBXML_XINCLUDE_ENABLED
- #if LIBXML_VERSION >= 20603
- xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
- #else
- xmlXIncludeProcess(doc);
- #endif
- #else
- xsltTransformError(ctxt, NULL, NULL,
- "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
- URI);
- #endif
- }
- /*
- * Apply white-space stripping if asked for
- */
- if (xsltNeedElemSpaceHandling(ctxt))
- xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
- if (ctxt->debugStatus == XSLT_DEBUG_NONE)
- xmlXPathOrderDocElems(doc);
- ret = xsltNewDocument(ctxt, doc);
- return(ret);
- }
- /**
- * xsltLoadStyleDocument:
- * @style: an XSLT style sheet
- * @URI: the computed URI of the document
- *
- * Try to load a stylesheet document within the XSLT transformation context
- *
- * Returns the new xsltDocumentPtr or NULL in case of error
- */
- xsltDocumentPtr
- xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
- xsltDocumentPtr ret;
- xmlDocPtr doc;
- xsltSecurityPrefsPtr sec;
- if ((style == NULL) || (URI == NULL))
- return(NULL);
- /*
- * Security framework check
- */
- sec = xsltGetDefaultSecurityPrefs();
- if (sec != NULL) {
- int res;
- res = xsltCheckRead(sec, NULL, URI);
- if (res <= 0) {
- if (res == 0)
- xsltTransformError(NULL, NULL, NULL,
- "xsltLoadStyleDocument: read rights for %s denied\n",
- URI);
- return(NULL);
- }
- }
- /*
- * Walk the context list to find the document if preparsed
- */
- ret = style->docList;
- while (ret != NULL) {
- if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
- (xmlStrEqual(ret->doc->URL, URI)))
- return(ret);
- ret = ret->next;
- }
- doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
- (void *) style, XSLT_LOAD_STYLESHEET);
- if (doc == NULL)
- return(NULL);
- ret = xsltNewStyleDocument(style, doc);
- return(ret);
- }
- /**
- * xsltFindDocument:
- * @ctxt: an XSLT transformation context
- * @doc: a parsed XML document
- *
- * Try to find a document within the XSLT transformation context.
- * This will not find document infos for temporary
- * Result Tree Fragments.
- *
- * Returns the desired xsltDocumentPtr or NULL in case of error
- */
- xsltDocumentPtr
- xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
- xsltDocumentPtr ret;
- if ((ctxt == NULL) || (doc == NULL))
- return(NULL);
- /*
- * Walk the context list to find the document
- */
- ret = ctxt->docList;
- while (ret != NULL) {
- if (ret->doc == doc)
- return(ret);
- ret = ret->next;
- }
- if (doc == ctxt->style->doc)
- return(ctxt->document);
- return(NULL);
- }
|