mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 10:41:12 +00:00
msxml3: Properly escape character data in text nodes.
This commit is contained in:
parent
cdac8cb176
commit
5016f7ba4a
2 changed files with 103 additions and 8 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue