msxml3: Implement custom document importing callback.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cdaf5625d1
commit
92513a9edd
|
@ -2308,6 +2308,7 @@ static HRESULT WINAPI domdoc_load(
|
|||
This->error = E_FAIL;
|
||||
else
|
||||
{
|
||||
get_doc(This)->name = (char *)xmlchar_from_wcharn(filename, -1, TRUE);
|
||||
This->properties->uri = uri;
|
||||
hr = This->error = S_OK;
|
||||
*isSuccessful = VARIANT_TRUE;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
# include <libxslt/xsltutils.h>
|
||||
# include <libxslt/variables.h>
|
||||
# include <libxslt/xsltInternals.h>
|
||||
# include <libxslt/documents.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -176,6 +177,7 @@ DECL_FUNCPTR(xsltNextImport);
|
|||
DECL_FUNCPTR(xsltParseStylesheetDoc);
|
||||
DECL_FUNCPTR(xsltQuoteUserParams);
|
||||
DECL_FUNCPTR(xsltSaveResultTo);
|
||||
DECL_FUNCPTR(xsltSetLoaderFunc);
|
||||
# undef DECL_FUNCPTR
|
||||
#endif
|
||||
|
||||
|
@ -202,10 +204,14 @@ static void init_libxslt(void)
|
|||
LOAD_FUNCPTR(xsltParseStylesheetDoc, 1);
|
||||
LOAD_FUNCPTR(xsltQuoteUserParams, 1);
|
||||
LOAD_FUNCPTR(xsltSaveResultTo, 1);
|
||||
LOAD_FUNCPTR(xsltSetLoaderFunc, 1);
|
||||
#undef LOAD_FUNCPTR
|
||||
|
||||
if (pxsltInit)
|
||||
pxsltInit();
|
||||
|
||||
pxsltSetLoaderFunc(xslt_doc_default_loader);
|
||||
|
||||
return;
|
||||
|
||||
sym_not_found:
|
||||
|
|
|
@ -379,6 +379,12 @@ extern BSTR EnsureCorrectEOL(BSTR) DECLSPEC_HIDDEN;
|
|||
|
||||
extern xmlChar* tagName_to_XPath(const BSTR tagName) DECLSPEC_HIDDEN;
|
||||
|
||||
#ifdef SONAME_LIBXSLT
|
||||
# include <libxslt/documents.h>
|
||||
extern xmlDocPtr xslt_doc_default_loader(const xmlChar *uri, xmlDictPtr dict, int options,
|
||||
void *_ctxt, xsltLoadType type) DECLSPEC_HIDDEN;
|
||||
#endif /* SONAME_LIBXSLT */
|
||||
|
||||
static inline BSTR bstr_from_xmlChar(const xmlChar *str)
|
||||
{
|
||||
BSTR ret = NULL;
|
||||
|
@ -395,12 +401,12 @@ static inline BSTR bstr_from_xmlChar(const xmlChar *str)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline xmlChar *xmlchar_from_wcharn(const WCHAR *str, int nchars)
|
||||
static inline xmlChar *xmlchar_from_wcharn(const WCHAR *str, int nchars, BOOL use_xml_alloc)
|
||||
{
|
||||
xmlChar *xmlstr;
|
||||
DWORD len = WideCharToMultiByte( CP_UTF8, 0, str, nchars, NULL, 0, NULL, NULL );
|
||||
|
||||
xmlstr = heap_alloc( len+1 );
|
||||
xmlstr = use_xml_alloc ? xmlMalloc( len + 1 ) : heap_alloc( len + 1 );
|
||||
if ( xmlstr )
|
||||
{
|
||||
WideCharToMultiByte( CP_UTF8, 0, str, nchars, (LPSTR) xmlstr, len+1, NULL, NULL );
|
||||
|
@ -411,7 +417,7 @@ static inline xmlChar *xmlchar_from_wcharn(const WCHAR *str, int nchars)
|
|||
|
||||
static inline xmlChar *xmlchar_from_wchar( const WCHAR *str )
|
||||
{
|
||||
return xmlchar_from_wcharn(str, -1);
|
||||
return xmlchar_from_wcharn(str, -1, FALSE);
|
||||
}
|
||||
|
||||
static inline xmlChar *heap_strdupxmlChar(const xmlChar *str)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#ifdef HAVE_LIBXML2
|
||||
# include <libxml/parser.h>
|
||||
# include <libxml/parserInternals.h>
|
||||
# include <libxml/xmlerror.h>
|
||||
# include <libxml/HTMLtree.h>
|
||||
# ifdef SONAME_LIBXSLT
|
||||
|
@ -39,6 +40,7 @@
|
|||
# include <libxslt/variables.h>
|
||||
# include <libxslt/xsltutils.h>
|
||||
# include <libxslt/xsltInternals.h>
|
||||
# include <libxslt/documents.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -1313,7 +1315,192 @@ static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr
|
|||
return hr;
|
||||
}
|
||||
|
||||
#endif
|
||||
struct import_buffer
|
||||
{
|
||||
char *data;
|
||||
int cur;
|
||||
int len;
|
||||
};
|
||||
|
||||
static int XMLCALL import_loader_io_read(void *context, char *out, int len)
|
||||
{
|
||||
struct import_buffer *buffer = (struct import_buffer *)context;
|
||||
|
||||
TRACE("%p, %p, %d\n", context, out, len);
|
||||
|
||||
if (buffer->cur == buffer->len)
|
||||
return 0;
|
||||
|
||||
len = min(len, buffer->len - buffer->cur);
|
||||
memcpy(out, &buffer->data[buffer->cur], len);
|
||||
buffer->cur += len;
|
||||
|
||||
TRACE("read %d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int XMLCALL import_loader_io_close(void * context)
|
||||
{
|
||||
struct import_buffer *buffer = (struct import_buffer *)context;
|
||||
|
||||
TRACE("%p\n", context);
|
||||
|
||||
heap_free(buffer->data);
|
||||
heap_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HRESULT import_loader_onDataAvailable(void *ctxt, char *ptr, DWORD len)
|
||||
{
|
||||
xmlParserInputPtr *input = (xmlParserInputPtr *)ctxt;
|
||||
xmlParserInputBufferPtr inputbuffer;
|
||||
struct import_buffer *buffer;
|
||||
|
||||
buffer = heap_alloc(sizeof(*buffer));
|
||||
|
||||
buffer->data = heap_alloc(len);
|
||||
memcpy(buffer->data, ptr, len);
|
||||
buffer->cur = 0;
|
||||
buffer->len = len;
|
||||
|
||||
inputbuffer = xmlParserInputBufferCreateIO(import_loader_io_read, import_loader_io_close, buffer,
|
||||
XML_CHAR_ENCODING_NONE);
|
||||
*input = xmlNewIOInputStream(ctxt, inputbuffer, XML_CHAR_ENCODING_NONE);
|
||||
if (!*input)
|
||||
xmlFreeParserInputBuffer(inputbuffer);
|
||||
|
||||
return *input ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT xslt_doc_get_uri(const xmlChar *uri, void *_ctxt, xsltLoadType type, IUri **doc_uri)
|
||||
{
|
||||
xsltStylesheetPtr style = (xsltStylesheetPtr)_ctxt;
|
||||
IUri *href_uri;
|
||||
HRESULT hr;
|
||||
BSTR uriW;
|
||||
|
||||
*doc_uri = NULL;
|
||||
|
||||
uriW = bstr_from_xmlChar(uri);
|
||||
hr = CreateUri(uriW, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &href_uri);
|
||||
SysFreeString(uriW);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("Failed to create href uri, %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (type == XSLT_LOAD_STYLESHEET && style->doc && style->doc->name)
|
||||
{
|
||||
IUri *base_uri;
|
||||
BSTR baseuriW;
|
||||
|
||||
baseuriW = bstr_from_xmlChar((xmlChar *)style->doc->name);
|
||||
hr = CreateUri(baseuriW, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &base_uri);
|
||||
SysFreeString(baseuriW);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("Failed to create base uri, %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = CoInternetCombineIUri(base_uri, href_uri, 0, doc_uri, 0);
|
||||
IUri_Release(base_uri);
|
||||
if (FAILED(hr))
|
||||
WARN("Failed to combine uris, %#x.\n", hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
*doc_uri = href_uri;
|
||||
IUri_AddRef(*doc_uri);
|
||||
}
|
||||
|
||||
IUri_Release(href_uri);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
xmlDocPtr xslt_doc_default_loader(const xmlChar *uri, xmlDictPtr dict, int options,
|
||||
void *_ctxt, xsltLoadType type)
|
||||
{
|
||||
IUri *import_uri = NULL;
|
||||
xmlParserInputPtr input;
|
||||
xmlParserCtxtPtr pctxt;
|
||||
xmlDocPtr doc = NULL;
|
||||
IMoniker *moniker;
|
||||
HRESULT hr;
|
||||
bsc_t *bsc;
|
||||
BSTR uriW;
|
||||
|
||||
TRACE("%s, %p, %#x, %p, %d\n", debugstr_a((const char *)uri), dict, options, _ctxt, type);
|
||||
|
||||
pctxt = xmlNewParserCtxt();
|
||||
if (!pctxt)
|
||||
return NULL;
|
||||
|
||||
if (dict && pctxt->dict)
|
||||
{
|
||||
xmlDictFree(pctxt->dict);
|
||||
pctxt->dict = NULL;
|
||||
}
|
||||
|
||||
if (dict)
|
||||
{
|
||||
pctxt->dict = dict;
|
||||
xmlDictReference(pctxt->dict);
|
||||
}
|
||||
|
||||
xmlCtxtUseOptions(pctxt, options);
|
||||
|
||||
hr = xslt_doc_get_uri(uri, _ctxt, type, &import_uri);
|
||||
if (FAILED(hr))
|
||||
goto failed;
|
||||
|
||||
hr = CreateURLMonikerEx2(NULL, import_uri, &moniker, 0);
|
||||
if (FAILED(hr))
|
||||
goto failed;
|
||||
|
||||
hr = bind_url(moniker, import_loader_onDataAvailable, &input, &bsc);
|
||||
IMoniker_Release(moniker);
|
||||
if (FAILED(hr))
|
||||
goto failed;
|
||||
|
||||
if (FAILED(detach_bsc(bsc)))
|
||||
goto failed;
|
||||
|
||||
if (!input)
|
||||
goto failed;
|
||||
|
||||
inputPush(pctxt, input);
|
||||
xmlParseDocument(pctxt);
|
||||
|
||||
if (pctxt->wellFormed)
|
||||
{
|
||||
doc = pctxt->myDoc;
|
||||
/* Set imported uri, to give nested imports a chance. */
|
||||
if (IUri_GetPropertyBSTR(import_uri, Uri_PROPERTY_ABSOLUTE_URI, &uriW, 0) == S_OK)
|
||||
{
|
||||
doc->name = (char *)xmlchar_from_wcharn(uriW, SysStringLen(uriW), TRUE);
|
||||
SysFreeString(uriW);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = NULL;
|
||||
xmlFreeDoc(pctxt->myDoc);
|
||||
pctxt->myDoc = NULL;
|
||||
}
|
||||
|
||||
failed:
|
||||
xmlFreeParserCtxt(pctxt);
|
||||
if (import_uri)
|
||||
IUri_Release(import_uri);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
#endif /* SONAME_LIBXSLT */
|
||||
|
||||
HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
|
||||
ISequentialStream *stream, const struct xslprocessor_params *params)
|
||||
|
|
Loading…
Reference in New Issue