From 0f658d9dc8232e7a5e7beb545eea875cb8f859f3 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 12 Jan 2012 23:31:22 +0300 Subject: [PATCH] msxml3: Leading space chars are allowed in SelectionNamespaces value string. --- dlls/msxml3/domdoc.c | 45 +++++++++++++--------- dlls/msxml3/tests/domdoc.c | 79 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 4bb4fa4ff0d..47ce60d4a55 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -2767,14 +2767,11 @@ static HRESULT WINAPI domdoc_setProperty( } else if (lstrcmpiW(p, PropertySelectionNamespacesW) == 0) { + xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr; + struct list *pNsList; VARIANT varStr; HRESULT hr; BSTR bstr; - xmlChar *pTokBegin, *pTokEnd, *pTokInner; - xmlChar *nsStr = (xmlChar*)This->properties->selectNsStr; - xmlXPathContextPtr ctx; - struct list *pNsList; - select_ns_entry* pNsEntry = NULL; V_VT(&varStr) = VT_EMPTY; if (V_VT(&var) != VT_BSTR) @@ -2793,20 +2790,30 @@ static HRESULT WINAPI domdoc_setProperty( heap_free(nsStr); nsStr = xmlchar_from_wchar(bstr); - TRACE("Setting SelectionNamespaces property to: %s\n", nsStr); + TRACE("property value: \"%s\"\n", debugstr_w(bstr)); This->properties->selectNsStr = nsStr; This->properties->selectNsStr_len = xmlStrlen(nsStr); if (bstr && *bstr) { + xmlChar *pTokBegin, *pTokEnd, *pTokInner; + select_ns_entry* ns_entry = NULL; + xmlXPathContextPtr ctx; + ctx = xmlXPathNewContext(This->node.node->doc); pTokBegin = nsStr; + + /* skip leading spaces */ + while (*pTokBegin == ' ' || *pTokBegin == '\n' || + *pTokBegin == '\t' || *pTokBegin == '\r') + ++pTokBegin; + for (; *pTokBegin; pTokBegin = pTokEnd) { - if (pNsEntry != NULL) - memset(pNsEntry, 0, sizeof(select_ns_entry)); + if (ns_entry) + memset(ns_entry, 0, sizeof(select_ns_entry)); else - pNsEntry = heap_alloc_zero(sizeof(select_ns_entry)); + ns_entry = heap_alloc_zero(sizeof(select_ns_entry)); while (*pTokBegin == ' ') ++pTokBegin; @@ -2831,7 +2838,7 @@ static HRESULT WINAPI domdoc_setProperty( } else if (*pTokBegin == ':') { - pNsEntry->prefix = ++pTokBegin; + ns_entry->prefix = ++pTokBegin; for (pTokInner = pTokBegin; pTokInner != pTokEnd && *pTokInner != '='; ++pTokInner) ; @@ -2843,7 +2850,7 @@ static HRESULT WINAPI domdoc_setProperty( continue; } - pNsEntry->prefix_end = *pTokInner; + ns_entry->prefix_end = *pTokInner; *pTokInner = 0; ++pTokInner; @@ -2851,25 +2858,25 @@ static HRESULT WINAPI domdoc_setProperty( ((*pTokInner == '\'' && *(pTokEnd-1) == '\'') || (*pTokInner == '"' && *(pTokEnd-1) == '"'))) { - pNsEntry->href = ++pTokInner; - pNsEntry->href_end = *(pTokEnd-1); + ns_entry->href = ++pTokInner; + ns_entry->href_end = *(pTokEnd-1); *(pTokEnd-1) = 0; - list_add_tail(pNsList, &pNsEntry->entry); + list_add_tail(pNsList, &ns_entry->entry); /*let libxml figure out if they're valid from here ;)*/ - if (xmlXPathRegisterNs(ctx, pNsEntry->prefix, pNsEntry->href) != 0) + if (xmlXPathRegisterNs(ctx, ns_entry->prefix, ns_entry->href) != 0) { hr = E_FAIL; } - pNsEntry = NULL; + ns_entry = NULL; continue; } else { WARN("Syntax error in xmlns string: %s\n\tat token: %s\n", wine_dbgstr_w(bstr), wine_dbgstr_an((const char*)pTokInner, pTokEnd-pTokInner)); - list_add_tail(pNsList, &pNsEntry->entry); + list_add_tail(pNsList, &ns_entry->entry); - pNsEntry = NULL; + ns_entry = NULL; hr = E_FAIL; continue; } @@ -2880,7 +2887,7 @@ static HRESULT WINAPI domdoc_setProperty( continue; } } - heap_free(pNsEntry); + heap_free(ns_entry); xmlXPathFreeContext(ctx); } diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index a4e5ab165be..0041763dbf6 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -5480,8 +5480,41 @@ static void test_whitespace(void) free_bstrs(); } -static void test_XPath(void) +typedef struct { + const GUID *clsid; + const char *name; + const char *ns; + HRESULT hr; +} selection_ns_t; + +/* supposed to be tested with szExampleXML */ +static const selection_ns_t selection_ns_data[] = { + { &CLSID_DOMDocument, "CLSID_DOMDocument", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument, "CLSID_DOMDocument", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument, "CLSID_DOMDocument", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + + { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument2, "CLSID_DOMDocument2", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + + { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument30, "CLSID_DOMDocument30", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + + { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument40, "CLSID_DOMDocument40", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + + { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + { &CLSID_DOMDocument60, "CLSID_DOMDocument60", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK }, + + { NULL } +}; + +void test_XPath(void) { + const selection_ns_t *ptr = selection_ns_data; VARIANT var; VARIANT_BOOL b; IXMLDOMDocument2 *doc; @@ -5498,7 +5531,8 @@ static void test_XPath(void) doc = create_document(&IID_IXMLDOMDocument2); if (!doc) return; - ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b)); + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b); + EXPECT_HR(hr, S_OK); ok(b == VARIANT_TRUE, "failed to load XML string\n"); /* switch to XPath */ @@ -5711,8 +5745,47 @@ static void test_XPath(void) IXMLDOMNode_Release(rootNode); IXMLDOMNodeList_Release(list); IXMLDOMDocument_Release(doc2); - IXMLDOMDocument2_Release(doc); + + while (ptr->clsid) + { + hr = CoCreateInstance(ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc); + if (hr != S_OK) + { + win_skip("can't create instance of %s\n", ptr->name); + ptr++; + continue; + } + + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b); + EXPECT_HR(hr, S_OK); + ok(b == VARIANT_TRUE, "failed to load, %s\n", ptr->name); + + hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")); + EXPECT_HR(hr, S_OK); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = _bstr_(ptr->ns); + + hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var); + ok(hr == ptr->hr, "got 0x%08x, for %s, %s\n", hr, ptr->name, ptr->ns); + + V_VT(&var) = VT_EMPTY; + hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var); + EXPECT_HR(hr, S_OK); + ok(V_VT(&var) == VT_BSTR, "got wrong property type %d\n", V_VT(&var)); + ok(!lstrcmpW(V_BSTR(&var), _bstr_(ptr->ns)), "got wrong value %s\n", wine_dbgstr_w(V_BSTR(&var))); + VariantClear(&var); + + hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list); + EXPECT_HR(hr, S_OK); + if (hr == S_OK) + expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1"); + + IXMLDOMDocument2_Release(doc); + ptr++; + } + free_bstrs(); }