[PATCH resend] msxml3: Remove CRs in domtext_put_data and add them in domtext_get_xml.

Alex Henrie alexhenrie24 at gmail.com
Thu Aug 3 10:17:38 CDT 2017


Fixes https://bugs.winehq.org/show_bug.cgi?id=42468

To be clear, I am not trying to fix all whitespace processing issues. I
am only trying to prevent "
" from being erroneously inserted into
the output.

Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
 dlls/msxml3/tests/domdoc.c | 106 +++++++++++++++++++++++++++++++++++++--------
 dlls/msxml3/text.c         |  42 +++++++++++++++---
 2 files changed, 122 insertions(+), 26 deletions(-)

diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index fa10a365f5..00c320c15e 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -12099,34 +12099,101 @@ static void test_put_data(void)
        type++;
     }
 
-    /* \r\n sequence is never escaped */
+    IXMLDOMDocument_Release(doc);
+    free_bstrs();
+}
+
+static void test_newline_normalization(void)
+{
+    const struct msxmlsupported_data_t *table = domdoc_support_data;
+    IXMLDOMDocument *doc;
+    IXMLDOMText *text;
+    IXMLDOMNode *node;
+    VARIANT v;
+    VARIANT_BOOL b;
+    BSTR get_data;
+    HRESULT hr;
+    LONG length;
+
     V_VT(&v) = VT_I2;
     V_I2(&v) = NODE_TEXT;
 
-    hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
-    ok(hr == S_OK, "got 0x%08x\n", hr);
+    while (table->clsid)
+    {
+        if (!is_clsid_supported(table->clsid, &IID_IXMLDOMDocument))
+        {
+            table++;
+            continue;
+        }
 
-    IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
+        hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
-    ok(hr == S_OK, "got 0x%08x\n", hr);
+        hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    hr = IXMLDOMText_get_data(text, &get_data);
-    ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine
-    ok(!lstrcmpW(get_data, _bstr_("\n")), "got %s\n", wine_dbgstr_w(get_data));
-    SysFreeString(get_data);
+        IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
 
-    hr = IXMLDOMText_get_xml(text, &get_data);
-    ok(hr == S_OK, "got 0x%08x\n", hr);
-    ok(!lstrcmpW(get_data, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(get_data));
-    SysFreeString(get_data);
+        /* \r\n is normalized to \n and back to \r\n */
 
-    IXMLDOMText_Release(text);
-    IXMLDOMNode_Release(node);
+        hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
+        ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    IXMLDOMDocument_Release(doc);
-    free_bstrs();
+        hr = IXMLDOMText_get_data(text, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("\n")), "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        hr = IXMLDOMText_get_length(text, &length);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(length == 1, "got %d, expected 1\n", length);
+
+        hr = IXMLDOMText_get_xml(text, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        /* \r\r\n is normalized to \n\n and back to \r\n\r\n */
+
+        hr = IXMLDOMText_put_data(text, _bstr_("\r\r\n"));
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IXMLDOMText_get_data(text, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("\n\n")), "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        hr = IXMLDOMText_get_length(text, &length);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(length == 2, "got %d, expected 2\n", length);
+
+        hr = IXMLDOMText_get_xml(text, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("\r\n\r\n")), "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        /* the same normalizations are applied when loading a document as a whole */
+
+        hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?><root>foo\n\r\n\r\r\nbar</root>"), &b);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IXMLDOMDocument_get_text(doc, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        hr = IXMLDOMDocument_get_xml(doc, &get_data);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(get_data, _bstr_("<?xml version=\"1.0\"?>\r\n<root>foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
+           "got %s\n", wine_dbgstr_w(get_data));
+        SysFreeString(get_data);
+
+        IXMLDOMText_Release(text);
+        IXMLDOMNode_Release(node);
+        IXMLDOMDocument_Release(doc);
+        free_bstrs();
+        table++;
+    }
 }
 
 static void test_putref_schemas(void)
@@ -12635,6 +12702,7 @@ START_TEST(domdoc)
     test_nodeValue();
     test_get_namespaces();
     test_put_data();
+    test_newline_normalization();
     test_putref_schemas();
     test_namedmap_newenum();
     test_xmlns_attribute();
diff --git a/dlls/msxml3/text.c b/dlls/msxml3/text.c
index 3a12d4bf62..6814c1f817 100644
--- a/dlls/msxml3/text.c
+++ b/dlls/msxml3/text.c
@@ -519,10 +519,15 @@ static HRESULT WINAPI domtext_get_xml(
     BSTR* p)
 {
     domtext *This = impl_from_IXMLDOMText( iface );
+    HRESULT hr;
 
     TRACE("(%p)->(%p)\n", This, p);
 
-    return node_get_xml(&This->node, FALSE, p);
+    hr = node_get_xml(&This->node, FALSE, p);
+    if (hr == S_OK)
+        *p = EnsureCorrectEOL(*p);
+
+    return hr;
 }
 
 static HRESULT WINAPI domtext_transformNode(
@@ -616,15 +621,38 @@ static HRESULT WINAPI domtext_put_data(
     BSTR data)
 {
     domtext *This = impl_from_IXMLDOMText( iface );
-    static const WCHAR rnW[] = {'\r','\n',0};
+    BSTR normalized_data = NULL;
+    HRESULT hr;
+    int i, j;
 
     TRACE("(%p)->(%s)\n", This, debugstr_w(data));
 
-    if (data && !strcmpW(rnW, data))
-        This->node.node->name = xmlStringTextNoenc;
-    else
-        domtext_reset_noenc(This);
-    return node_set_content(&This->node, data);
+    if (data)
+    {
+        /* normalize line endings */
+        normalized_data = SysAllocStringLen(NULL, SysStringLen(data));
+        if (!normalized_data) return E_OUTOFMEMORY;
+        for (i = 0, j = 0; data[i]; i++)
+        {
+            if (data[i] == '\r')
+            {
+                if (data[i + 1] == '\n')
+                    continue; /* change \r\n to just \n */
+                else
+                    normalized_data[j] = '\n'; /* change \r by itself to \n */
+            }
+            else
+                normalized_data[j] = data[i];
+            j++;
+        }
+        normalized_data[j] = 0;
+    }
+
+    domtext_reset_noenc(This);
+    hr = node_set_content(&This->node, normalized_data);
+
+    SysFreeString(normalized_data);
+    return hr;
 }
 
 static HRESULT WINAPI domtext_get_length(
-- 
2.13.3




More information about the wine-patches mailing list