>From f1f5acafdb53b0ea9d40b15d90c118cf025231c5 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Thu, 12 Jan 2012 23:31:22 +0300
Subject: [PATCH 1/1] 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 4bb4fa4..47ce60d 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 a4e5ab1..0041763 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();
 }
 
-- 
1.5.6.5

