msxml3: Escape '<','&','"' and '>' in attribute value.

This commit is contained in:
Nikolay Sivov 2011-12-11 02:32:51 +03:00 committed by Alexandre Julliard
parent b83d322dba
commit d80ee5b3ae
2 changed files with 101 additions and 29 deletions

View File

@ -57,7 +57,7 @@ typedef enum
MXWriter_LastProp
} MXWRITER_PROPS;
typedef struct _mxwriter
typedef struct
{
DispatchEx dispex;
IMXWriter IMXWriter_iface;
@ -106,6 +106,71 @@ static HRESULT bstr_from_xmlCharEncoding(xmlCharEncoding enc, BSTR *encoding)
return *encoding ? S_OK : E_OUTOFMEMORY;
}
/* escapes special characters like:
'<' -> "&lt;"
'&' -> "&amp;"
'"' -> "&quot;"
'>' -> "&gt;"
*/
static WCHAR *get_escaped_string(const WCHAR *str, int *len)
{
static const WCHAR ltW[] = {'&','l','t',';'};
static const WCHAR ampW[] = {'&','a','m','p',';'};
static const WCHAR quotW[] = {'&','q','u','o','t',';'};
static const WCHAR gtW[] = {'&','g','t',';'};
const int default_alloc = 100;
const int grow_thresh = 10;
int p = *len, conv_len;
WCHAR *ptr, *ret;
/* default buffer size to something if length is unknown */
conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
while (*str && p)
{
if (ptr - ret > conv_len - grow_thresh)
{
int written = ptr - ret;
conv_len *= 2;
ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
ptr += written;
}
switch (*str)
{
case '<':
memcpy(ptr, ltW, sizeof(ltW));
ptr += sizeof(ltW)/sizeof(WCHAR);
break;
case '&':
memcpy(ptr, ampW, sizeof(ampW));
ptr += sizeof(ampW)/sizeof(WCHAR);
break;
case '"':
memcpy(ptr, quotW, sizeof(quotW));
ptr += sizeof(quotW)/sizeof(WCHAR);
break;
case '>':
memcpy(ptr, gtW, sizeof(gtW));
ptr += sizeof(gtW)/sizeof(WCHAR);
break;
default:
*ptr++ = *str;
break;
}
str++;
if (*len != -1) p--;
}
if (*len != -1) *len = ptr-ret;
*++ptr = 0;
return ret;
}
/* creates UTF-8 encoded prolog string with specified or store encoding value */
static int write_prolog_buffer(const mxwriter *This, xmlCharEncoding enc, xmlOutputBufferPtr buffer)
{
@ -824,6 +889,7 @@ static HRESULT WINAPI mxwriter_saxcontent_startElement(
for (i = 0; i < length; i++)
{
const WCHAR *str;
WCHAR *escaped;
INT len = 0;
hr = ISAXAttributes_getQName(attr, i, &str, &len);
@ -842,8 +908,10 @@ static HRESULT WINAPI mxwriter_saxcontent_startElement(
hr = ISAXAttributes_getValue(attr, i, &str, &len);
if (FAILED(hr)) return hr;
s = xmlchar_from_wcharn(str, len);
escaped = get_escaped_string(str, &len);
s = xmlchar_from_wcharn(escaped, len);
write_output_buffer_str(This, (char*)s);
heap_free(escaped);
heap_free(s);
write_output_buffer(This, "\"", 1);

View File

@ -737,7 +737,7 @@ static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface)
static HRESULT WINAPI isaxattributes_getLength(ISAXAttributes* iface, int *length)
{
*length = 2;
*length = 3;
return S_OK;
}
@ -763,17 +763,19 @@ static HRESULT WINAPI isaxattributes_getLocalName(
static HRESULT WINAPI isaxattributes_getQName(
ISAXAttributes* iface,
int nIndex,
const WCHAR **pQName,
int *pQNameLength)
int index,
const WCHAR **QName,
int *QNameLength)
{
static const WCHAR attr1W[] = {'a',':','a','t','t','r','1','j','u','n','k',0};
static const WCHAR attr2W[] = {'a','t','t','r','2','j','u','n','k',0};
static const WCHAR attrqnamesW[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
{'a','t','t','r','2','j','u','n','k',0},
{'a','t','t','r','3',0}};
static const int attrqnamelen[] = {7, 5, 5};
ok(nIndex == 0 || nIndex == 1, "invalid index received %d\n", nIndex);
ok(index >= 0 && index <= 2, "invalid index received %d\n", index);
*pQName = (nIndex == 0) ? attr1W : attr2W;
*pQNameLength = (nIndex == 0) ? 7 : 5;
*QName = attrqnamesW[index];
*QNameLength = attrqnamelen[index];
return S_OK;
}
@ -848,19 +850,18 @@ static HRESULT WINAPI isaxattributes_getTypeFromQName(
return E_NOTIMPL;
}
static HRESULT WINAPI isaxattributes_getValue(
ISAXAttributes* iface,
int nIndex,
const WCHAR ** pValue,
int * nValue)
static HRESULT WINAPI isaxattributes_getValue(ISAXAttributes* iface, int index,
const WCHAR **value, int *nValue)
{
static const WCHAR attrval1W[] = {'a','1','j','u','n','k',0};
static const WCHAR attrval2W[] = {'a','2','j','u','n','k',0};
static const WCHAR attrvaluesW[][10] = {{'a','1','j','u','n','k',0},
{'a','2','j','u','n','k',0},
{'<','&','"','>',0}};
static const int attrvalueslen[] = {2, 2, 4};
ok(nIndex == 0 || nIndex == 1, "invalid index received %d\n", nIndex);
ok(index >= 0 && index <= 2, "invalid index received %d\n", index);
*pValue = (nIndex == 0) ? attrval1W : attrval2W;
*nValue = 2;
*value = attrvaluesW[index];
*nValue = attrvalueslen[index];
return S_OK;
}
@ -2039,6 +2040,9 @@ struct writer_startendelement_t {
ISAXAttributes *attr;
};
static const char startelement_xml[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"&lt;&amp;&quot;&gt;\">";
static const char startendelement_xml[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"&lt;&amp;&quot;&gt;\"/>";
static const struct writer_startendelement_t writer_startendelement[] = {
/* 0 */
{ &CLSID_MXXMLWriter, StartElement, NULL, NULL, NULL, NULL, E_INVALIDARG },
@ -2120,17 +2124,17 @@ static const struct writer_startendelement_t writer_startendelement[] = {
{ &CLSID_MXXMLWriter60, EndElement, "uri", "local", "uri:local2", "</uri:local2>", S_OK },
/* with attributes */
{ &CLSID_MXXMLWriter, StartElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter, StartElement, "uri", "local", "uri:local", startelement_xml, S_OK, &saxattributes },
/* 65 */
{ &CLSID_MXXMLWriter30, StartElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter40, StartElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter60, StartElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter30, StartElement, "uri", "local", "uri:local", startelement_xml, S_OK, &saxattributes },
{ &CLSID_MXXMLWriter40, StartElement, "uri", "local", "uri:local", startelement_xml, S_OK, &saxattributes },
{ &CLSID_MXXMLWriter60, StartElement, "uri", "local", "uri:local", startelement_xml, S_OK, &saxattributes },
/* empty elements */
{ &CLSID_MXXMLWriter, StartEndElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter30, StartEndElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter, StartEndElement, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes },
{ &CLSID_MXXMLWriter30, StartEndElement, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes },
/* 70 */
{ &CLSID_MXXMLWriter40, StartEndElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter60, StartEndElement, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK, &saxattributes },
{ &CLSID_MXXMLWriter40, StartEndElement, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes },
{ &CLSID_MXXMLWriter60, StartEndElement, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes },
{ &CLSID_MXXMLWriter, StartEndElement, "", "", "", "</>", S_OK },
{ &CLSID_MXXMLWriter30, StartEndElement, "", "", "", "</>", S_OK },
{ &CLSID_MXXMLWriter40, StartEndElement, "", "", "", "</>", S_OK },