Module: wine Branch: master Commit: 5016f7ba4a36265bd1bff3e5abe81213ed5c6ec0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5016f7ba4a36265bd1bff3e5ab...
Author: Nikolay Sivov nsivov@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);