msxml3: Validate node content in domelem_put_dataType().

This commit is contained in:
Adam Martinson 2010-11-22 20:57:29 -06:00 committed by Alexandre Julliard
parent f090ddfe13
commit 643cbafabc
4 changed files with 182 additions and 73 deletions

View File

@ -38,6 +38,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2
static const xmlChar DT_prefix[] = "dt";
static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
typedef struct _domelem
@ -823,10 +824,94 @@ static HRESULT WINAPI domelem_get_dataType(
static HRESULT WINAPI domelem_put_dataType(
IXMLDOMElement *iface,
BSTR p)
BSTR dtName)
{
domelem *This = impl_from_IXMLDOMElement( iface );
return IXMLDOMNode_put_dataType( IXMLDOMNode_from_impl(&This->node), p );
HRESULT hr = E_FAIL;
xmlChar *str;
XDR_DT dt;
TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
if(dtName == NULL)
return E_INVALIDARG;
dt = bstr_to_dt(dtName, -1);
/* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
This applies to changing types (string->bool) or setting a new one
*/
str = xmlNodeGetContent(get_element(This));
hr = dt_validate(dt, str);
xmlFree(str);
/* Check all supported types. */
if (hr == S_OK)
{
switch (dt)
{
case DT_BIN_BASE64:
case DT_BIN_HEX:
case DT_BOOLEAN:
case DT_CHAR:
case DT_DATE:
case DT_DATE_TZ:
case DT_DATETIME:
case DT_DATETIME_TZ:
case DT_FIXED_14_4:
case DT_FLOAT:
case DT_I1:
case DT_I2:
case DT_I4:
case DT_I8:
case DT_INT:
case DT_NMTOKEN:
case DT_NMTOKENS:
case DT_NUMBER:
case DT_R4:
case DT_R8:
case DT_STRING:
case DT_TIME:
case DT_TIME_TZ:
case DT_UI1:
case DT_UI2:
case DT_UI4:
case DT_UI8:
case DT_URI:
case DT_UUID:
{
xmlAttrPtr attr = xmlHasNsProp(get_element(This), DT_prefix, DT_nsURI);
if (attr)
{
attr = xmlSetNsProp(get_element(This), attr->ns, DT_prefix, dt_to_str(dt));
hr = S_OK;
}
else
{
xmlNsPtr ns = xmlNewNs(get_element(This), DT_nsURI, DT_prefix);
if (ns)
{
attr = xmlNewNsProp(get_element(This), ns, DT_prefix, dt_to_str(dt));
if (attr)
{
xmlAddChild(get_element(This), (xmlNodePtr)attr);
hr = S_OK;
}
else
ERR("Failed to create Attribute\n");
}
else
ERR("Failed to create Namespace\n");
}
}
break;
default:
FIXME("need to handle dt:%s\n", dt_to_str(dt));
break;
}
}
return hr;
}
static HRESULT WINAPI domelem_get_xml(

View File

@ -273,6 +273,7 @@ extern XDR_DT bstr_to_dt(OLECHAR const* bstr, int len /* calculated if -1 */);
extern xmlChar const* dt_to_str(XDR_DT dt);
extern OLECHAR const* dt_to_bstr(XDR_DT dt);
extern XDR_DT element_get_dt(xmlNodePtr node);
extern HRESULT dt_validate(XDR_DT dt, xmlChar const* content);
extern BSTR EnsureCorrectEOL(BSTR);

View File

@ -42,6 +42,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2
/* TODO: get rid of these and use the enum */
static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0};
static const WCHAR szString[] = {'s','t','r','i','n','g',0};
static const WCHAR szNumber[] = {'n','u','m','b','e','r',0};
@ -883,78 +884,18 @@ static HRESULT WINAPI xmlnode_put_nodeTypedValue(
static HRESULT WINAPI xmlnode_put_dataType(
IXMLDOMNode *iface,
BSTR dataTypeName)
BSTR dtName)
{
xmlnode *This = impl_from_IXMLDOMNode( iface );
HRESULT hr = E_FAIL;
TRACE("(%p)->(%s)\n", This, debugstr_w(dataTypeName));
TRACE("(%p)->(%s)\n", This, debugstr_w(dtName));
if(dataTypeName == NULL)
if(!dtName)
return E_INVALIDARG;
/* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type.
This applies to changing types (string->bool) or setting a new one
*/
FIXME("Need to Validate the data before allowing a type to be set.\n");
FIXME("need to handle node type %i\n", This->node->type);
/* Check all supported types. */
if(lstrcmpiW(dataTypeName,szString) == 0 ||
lstrcmpiW(dataTypeName,szNumber) == 0 ||
lstrcmpiW(dataTypeName,szUUID) == 0 ||
lstrcmpiW(dataTypeName,szInt) == 0 ||
lstrcmpiW(dataTypeName,szI4) == 0 ||
lstrcmpiW(dataTypeName,szFixed) == 0 ||
lstrcmpiW(dataTypeName,szBoolean) == 0 ||
lstrcmpiW(dataTypeName,szDateTime) == 0 ||
lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 ||
lstrcmpiW(dataTypeName,szDate) == 0 ||
lstrcmpiW(dataTypeName,szTime) == 0 ||
lstrcmpiW(dataTypeName,szTimeTZ) == 0 ||
lstrcmpiW(dataTypeName,szI1) == 0 ||
lstrcmpiW(dataTypeName,szI2) == 0 ||
lstrcmpiW(dataTypeName,szIU1) == 0 ||
lstrcmpiW(dataTypeName,szIU2) == 0 ||
lstrcmpiW(dataTypeName,szIU4) == 0 ||
lstrcmpiW(dataTypeName,szR4) == 0 ||
lstrcmpiW(dataTypeName,szR8) == 0 ||
lstrcmpiW(dataTypeName,szFloat) == 0 ||
lstrcmpiW(dataTypeName,szBinHex) == 0 ||
lstrcmpiW(dataTypeName,szBinBase64) == 0)
{
xmlChar* str = xmlChar_from_wchar(dataTypeName);
xmlAttrPtr attr;
if (!str) return E_OUTOFMEMORY;
attr = xmlHasNsProp(This->node, (const xmlChar*)"dt",
(const xmlChar*)"urn:schemas-microsoft-com:datatypes");
if (attr)
{
attr = xmlSetNsProp(This->node, attr->ns, (const xmlChar*)"dt", str);
hr = S_OK;
}
else
{
xmlNsPtr ns = xmlNewNs(This->node, (const xmlChar*)"urn:schemas-microsoft-com:datatypes", (const xmlChar*)"dt");
if (ns)
{
attr = xmlNewNsProp(This->node, ns, (const xmlChar*)"dt", str);
if (attr)
{
xmlAddChild(This->node, (xmlNodePtr)attr);
hr = S_OK;
}
else
ERR("Failed to create Attribute\n");
}
else
ERR("Failed to create Namespace\n");
}
heap_free( str );
}
return hr;
return E_FAIL;
}
BSTR EnsureCorrectEOL(BSTR sInput)

View File

@ -64,9 +64,11 @@ static const xmlChar XDR_schema[] = "Schema";
static const xmlChar XDR_nsURI[] = "urn:schemas-microsoft-com:xml-data";
static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
static xmlChar const* datatypes_schema = NULL;
static HGLOBAL datatypes_handle = NULL;
static HRSRC datatypes_rsrc = NULL;
static xmlChar const* datatypes_src = NULL;
static int datatypes_len = 0;
static HGLOBAL datatypes_handle = NULL;
static HRSRC datatypes_rsrc = NULL;
static xmlSchemaPtr datatypes_schema = NULL;
/* Supported Types:
* msxml3 - XDR only
@ -484,6 +486,83 @@ OLECHAR const* dt_to_bstr(XDR_DT dt)
return DT_wstring_table[dt];
}
HRESULT dt_validate(XDR_DT dt, xmlChar const* content)
{
xmlDocPtr tmp_doc;
xmlNodePtr node;
xmlNsPtr ns;
xmlSchemaValidCtxtPtr svctx;
BOOL valid;
if (!datatypes_schema)
{
xmlSchemaParserCtxtPtr spctx;
assert(datatypes_src != NULL);
spctx = xmlSchemaNewMemParserCtxt((char const*)datatypes_src, datatypes_len);
datatypes_schema = xmlSchemaParse(spctx);
xmlSchemaFreeParserCtxt(spctx);
}
switch (dt)
{
case DT_INVALID:
return E_FAIL;
break;
case DT_BIN_BASE64:
case DT_BIN_HEX:
case DT_BOOLEAN:
case DT_CHAR:
case DT_DATE:
case DT_DATE_TZ:
case DT_DATETIME:
case DT_DATETIME_TZ:
case DT_FIXED_14_4:
case DT_FLOAT:
case DT_I1:
case DT_I2:
case DT_I4:
case DT_I8:
case DT_INT:
case DT_NMTOKEN:
case DT_NMTOKENS:
case DT_NUMBER:
case DT_R4:
case DT_R8:
case DT_STRING:
case DT_TIME:
case DT_TIME_TZ:
case DT_UI1:
case DT_UI2:
case DT_UI4:
case DT_UI8:
case DT_URI:
case DT_UUID:
assert(datatypes_schema != NULL);
if (content && xmlStrlen(content))
{
svctx = xmlSchemaNewValidCtxt(datatypes_schema);
tmp_doc = xmlNewDoc(NULL);
node = xmlNewChild((xmlNodePtr)tmp_doc, NULL, dt_to_str(dt), content);
ns = xmlNewNs(node, DT_nsURI, BAD_CAST "dt");
xmlSetNs(node, ns);
xmlDocSetRootElement(tmp_doc, node);
valid = !xmlSchemaValidateDoc(svctx, tmp_doc);
xmlSchemaFreeValidCtxt(svctx);
xmlFreeDoc(tmp_doc);
}
else
{ /* probably the node is being created manually and has no content yet */
valid = TRUE;
}
return valid? S_OK : S_FALSE;
break;
default:
FIXME("need to handle dt:%s\n", dt_to_str(dt));
return S_OK;
break;
}
}
static inline xmlChar const* get_node_nsURI(xmlNodePtr node)
{
return (node->ns != NULL)? node->ns->href : NULL;
@ -513,13 +592,13 @@ static xmlParserInputPtr external_entity_loader(const char *URL, const char *ID,
assert(MSXML_hInstance != NULL);
assert(datatypes_rsrc != NULL);
assert(datatypes_handle != NULL);
assert(datatypes_schema != NULL);
assert(datatypes_src != NULL);
/* TODO: if the desired schema is in the cache, load it from there */
if (lstrcmpA(URL, "urn:schemas-microsoft-com:datatypes") == 0)
{
TRACE("loading built-in schema for %s\n", URL);
input = xmlNewStringInputStream(ctxt, datatypes_schema);
input = xmlNewStringInputStream(ctxt, datatypes_src);
}
else
{
@ -551,7 +630,8 @@ void schemasInit(void)
* need a null-terminated string */
while (buf[len] != '>')
buf[len--] = 0;
datatypes_schema = BAD_CAST buf;
datatypes_src = BAD_CAST buf;
datatypes_len = len + 1;
if ((void*)xmlGetExternalEntityLoader() != (void*)external_entity_loader)
{
@ -564,6 +644,8 @@ void schemasCleanup(void)
{
if (datatypes_handle)
FreeResource(datatypes_handle);
if (datatypes_schema)
xmlSchemaFree(datatypes_schema);
xmlSetExternalEntityLoader(_external_entity_loader);
}