msxml3: Implement custom document importing callback.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Nikolay Sivov 2018-01-23 11:27:55 +03:00 committed by Alexandre Julliard
parent cdaf5625d1
commit 92513a9edd
4 changed files with 204 additions and 4 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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)

View File

@ -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)