Nikolay Sivov : msxml3: Properly escape character data in text nodes.
Alexandre Julliard
julliard at winehq.org
Mon Feb 27 11:27:02 CST 2012
Module: wine
Branch: master
Commit: 5016f7ba4a36265bd1bff3e5abe81213ed5c6ec0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5016f7ba4a36265bd1bff3e5abe81213ed5c6ec0
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Feb 24 23:20:48 2012 +0300
msxml3: Properly escape character data in text nodes.
---
dlls/msxml3/mxwriter.c | 41 ++++++++++++++++++++----
dlls/msxml3/tests/saxreader.c | 70 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 103 insertions(+), 8 deletions(-)
diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c
index cb1a67f..72db31d 100644
--- a/dlls/msxml3/mxwriter.c
+++ b/dlls/msxml3/mxwriter.c
@@ -68,6 +68,12 @@ typedef enum
MXWriter_LastProp
} mxwriter_prop;
+typedef enum
+{
+ EscapeValue,
+ EscapeText
+} escape_mode;
+
typedef struct
{
char *data;
@@ -94,6 +100,7 @@ typedef struct
VARIANT_BOOL props[MXWriter_LastProp];
BOOL prop_changed;
+ BOOL cdata;
BSTR version;
@@ -275,7 +282,7 @@ static void close_output_buffer(mxwriter *This)
'"' -> """
'>' -> ">"
*/
-static WCHAR *get_escaped_string(const WCHAR *str, int *len)
+static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
{
static const WCHAR ltW[] = {'&','l','t',';'};
static const WCHAR ampW[] = {'&','a','m','p',';'};
@@ -311,14 +318,18 @@ static WCHAR *get_escaped_string(const WCHAR *str, int *len)
memcpy(ptr, ampW, sizeof(ampW));
ptr += sizeof(ampW)/sizeof(WCHAR);
break;
- case '"':
- memcpy(ptr, equotW, sizeof(equotW));
- ptr += sizeof(equotW)/sizeof(WCHAR);
- break;
case '>':
memcpy(ptr, gtW, sizeof(gtW));
ptr += sizeof(gtW)/sizeof(WCHAR);
break;
+ case '"':
+ if (mode == EscapeValue)
+ {
+ memcpy(ptr, equotW, sizeof(equotW));
+ ptr += sizeof(equotW)/sizeof(WCHAR);
+ break;
+ }
+ /* fallthrough for text mode */
default:
*ptr++ = *str;
break;
@@ -429,6 +440,7 @@ static inline HRESULT flush_output_buffer(mxwriter *This)
{
close_element_starttag(This);
set_element_name(This, NULL, 0);
+ This->cdata = FALSE;
return write_data_to_stream(This);
}
@@ -978,7 +990,7 @@ static HRESULT WINAPI SAXContentHandler_startElement(
hr = ISAXAttributes_getValue(attr, i, &str, &len);
if (FAILED(hr)) return hr;
- escaped = get_escaped_string(str, &len);
+ escaped = get_escaped_string(str, EscapeValue, &len);
write_output_buffer_quoted(This->buffer, escaped, len);
heap_free(escaped);
}
@@ -1040,7 +1052,19 @@ static HRESULT WINAPI SAXContentHandler_characters(
set_element_name(This, NULL, 0);
if (nchars)
- write_output_buffer(This->buffer, chars, nchars);
+ {
+ if (This->cdata)
+ write_output_buffer(This->buffer, chars, nchars);
+ else
+ {
+ int len = nchars;
+ WCHAR *escaped;
+
+ escaped = get_escaped_string(chars, EscapeText, &len);
+ write_output_buffer(This->buffer, escaped, len);
+ heap_free(escaped);
+ }
+ }
return S_OK;
}
@@ -1203,6 +1227,7 @@ static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
TRACE("(%p)\n", This);
write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
+ This->cdata = TRUE;
return S_OK;
}
@@ -1215,6 +1240,7 @@ static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
TRACE("(%p)\n", This);
write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
+ This->cdata = FALSE;
return S_OK;
}
@@ -1296,6 +1322,7 @@ HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
This->xml_enc = XmlEncoding_UTF16;
This->element = NULL;
+ This->cdata = FALSE;
This->dest = NULL;
This->dest_written = 0;
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index cfead73..74afc67 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -2439,13 +2439,29 @@ static void test_mxwriter_startendelement(void)
free_bstrs();
}
+struct writer_characters_t {
+ const GUID *clsid;
+ const char *data;
+ const char *output;
+};
+
+static const struct writer_characters_t writer_characters[] = {
+ { &CLSID_MXXMLWriter, "< > & \"", "< > & \"" },
+ { &CLSID_MXXMLWriter30, "< > & \"", "< > & \"" },
+ { &CLSID_MXXMLWriter40, "< > & \"", "< > & \"" },
+ { &CLSID_MXXMLWriter60, "< > & \"", "< > & \"" },
+ { NULL }
+};
+
static void test_mxwriter_characters(void)
{
static const WCHAR chardataW[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
+ const struct writer_characters_t *table = writer_characters;
ISAXContentHandler *content;
IMXWriter *writer;
VARIANT dest;
HRESULT hr;
+ int i = 0;
hr = CoCreateInstance(&CLSID_MXXMLWriter, NULL, CLSCTX_INPROC_SERVER,
&IID_IMXWriter, (void**)&writer);
@@ -2515,6 +2531,54 @@ static void test_mxwriter_characters(void)
ISAXContentHandler_Release(content);
IMXWriter_Release(writer);
+ /* batch tests */
+ while (table->clsid)
+ {
+ ISAXContentHandler *content;
+ IMXWriter *writer;
+ HRESULT hr;
+
+ if (!is_clsid_supported(table->clsid, mxwriter_support_data))
+ {
+ table++;
+ i++;
+ continue;
+ }
+
+ hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMXWriter, (void**)&writer);
+ EXPECT_HR(hr, S_OK);
+
+ hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content);
+ EXPECT_HR(hr, S_OK);
+
+ hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE);
+ EXPECT_HR(hr, S_OK);
+
+ hr = ISAXContentHandler_startDocument(content);
+ EXPECT_HR(hr, S_OK);
+
+ hr = ISAXContentHandler_characters(content, _bstr_(table->data), strlen(table->data));
+ EXPECT_HR(hr, S_OK);
+
+ /* test output */
+ if (hr == S_OK)
+ {
+ VARIANT dest;
+
+ V_VT(&dest) = VT_EMPTY;
+ hr = IMXWriter_get_output(writer, &dest);
+ EXPECT_HR(hr, S_OK);
+ ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
+ ok(!lstrcmpW(_bstr_(table->output), V_BSTR(&dest)),
+ "test %d: got wrong content %s, expected %s\n", i, wine_dbgstr_w(V_BSTR(&dest)), table->output);
+ VariantClear(&dest);
+ }
+
+ table++;
+ i++;
+ }
+
free_bstrs();
}
@@ -2975,6 +3039,10 @@ static void test_mxwriter_cdata(void)
hr = ISAXLexicalHandler_startCDATA(lexical);
EXPECT_HR(hr, S_OK);
+ /* all these are escaped for text nodes */
+ hr = ISAXContentHandler_characters(content, _bstr_("< > & \""), 7);
+ EXPECT_HR(hr, S_OK);
+
hr = ISAXLexicalHandler_endCDATA(lexical);
EXPECT_HR(hr, S_OK);
@@ -2982,7 +3050,7 @@ static void test_mxwriter_cdata(void)
hr = IMXWriter_get_output(writer, &dest);
EXPECT_HR(hr, S_OK);
ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
- ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[]]>"), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
+ ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
VariantClear(&dest);
ISAXContentHandler_Release(content);
More information about the wine-cvs
mailing list