msxml3: Remove CRs in domtext_put_data and add them in domtext_get_xml. Accepted

Revisions: 

Revision 1

user image Alex Henrie Author
08 Sep. 17

Nikolay and I would like this patch to be included in Wine Staging for additional testing, see https://www.winehq.org/pipermail/wine-devel/2017-September/118879.html

Single files Merged diff Tar archive
You have unsaved changes. Press CTRL + ENTER in a text field to submit your comments.

0001-msxml3-Remove-CRs-in-domtext_put_data-and-add-them-i.patch

From b3e2abf31dfa2bba15d0d71edc77683ff6e7eb7b Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Fri, 25 Aug 2017 09:05:27 -0600
Subject: [PATCH] msxml3: Remove CRs in domtext_put_data and add them in
domtext_get_xml.
Fixes https://bugs.winehq.org/show_bug.cgi?id=42468
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
---
dlls/msxml3/tests/domdoc.c | 153 +++++++++++++++++++++++++++++++++++++++------
dlls/msxml3/text.c | 37 ++++++++---
2 files changed, 164 insertions(+), 26 deletions(-)
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index fa10a365f5..28e8ac02a1 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -12099,34 +12099,148 @@ 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 s;
+ 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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("\n")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ 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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ /* \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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("\n\n")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ 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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("\r\n\r\n")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ /* 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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ hr = IXMLDOMDocument_get_xml(doc, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _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(s));
+ SysFreeString(s);
+
+ /* even if xml:space="preserve" */
+
+ hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?>"
+ "<root xml:space=\"preserve\">foo\n\r\n\r\r\nbar</root>"), &b);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IXMLDOMDocument_get_text(doc, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ hr = IXMLDOMDocument_get_xml(doc, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n"
+ "<root xml:space=\"preserve\">foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
+ "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ /* or preserveWhiteSpace is set */
+
+ hr = IXMLDOMDocument_put_preserveWhiteSpace(doc, VARIANT_TRUE);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ 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, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
+ SysFreeString(s);
+
+ hr = IXMLDOMDocument_get_xml(doc, &s);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ if (IsEqualGUID(table->clsid, &CLSID_DOMDocument60))
+ {
+ /* DOMDocument60 does the newline normalization but does not insert line breaks around the root node */
+todo_wine
+ ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?><root>foo\r\n\r\n\r\n\r\nbar</root>")),
+ "got %s\n", wine_dbgstr_w(s));
+ }
+ else
+ {
+ ok(!lstrcmpW(s, _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(s));
+ }
+ SysFreeString(s);
+
+ IXMLDOMText_Release(text);
+ IXMLDOMNode_Release(node);
+ IXMLDOMDocument_Release(doc);
+ free_bstrs();
+ table++;
+ }
}
static void test_putref_schemas(void)
@@ -12635,6 +12749,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..0666204694 100644
--- a/dlls/msxml3/text.c
+++ b/dlls/msxml3/text.c
@@ -522,7 +522,7 @@ static HRESULT WINAPI domtext_get_xml(
TRACE("(%p)->(%p)\n", This, p);
- return node_get_xml(&This->node, FALSE, p);
+ return node_get_xml(&This->node, TRUE, p);
}
static HRESULT WINAPI domtext_transformNode(
@@ -616,15 +616,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.14.1