msxml3: Implement domdoc schema validation.
This commit is contained in:
parent
9408b4973d
commit
c367215bbc
|
@ -116,7 +116,7 @@ struct domdoc
|
||||||
VARIANT_BOOL resolving;
|
VARIANT_BOOL resolving;
|
||||||
VARIANT_BOOL preserving;
|
VARIANT_BOOL preserving;
|
||||||
domdoc_properties* properties;
|
domdoc_properties* properties;
|
||||||
IXMLDOMSchemaCollection *schema;
|
IXMLDOMSchemaCollection2* schema;
|
||||||
bsc_t *bsc;
|
bsc_t *bsc;
|
||||||
HRESULT error;
|
HRESULT error;
|
||||||
|
|
||||||
|
@ -875,7 +875,7 @@ static ULONG WINAPI domdoc_Release(
|
||||||
if (This->site)
|
if (This->site)
|
||||||
IUnknown_Release( This->site );
|
IUnknown_Release( This->site );
|
||||||
destroy_xmlnode(&This->node);
|
destroy_xmlnode(&This->node);
|
||||||
if(This->schema) IXMLDOMSchemaCollection_Release( This->schema );
|
if(This->schema) IXMLDOMSchemaCollection2_Release(This->schema);
|
||||||
if (This->stream) IStream_Release(This->stream);
|
if (This->stream) IStream_Release(This->stream);
|
||||||
HeapFree( GetProcessHeap(), 0, This );
|
HeapFree( GetProcessHeap(), 0, This );
|
||||||
}
|
}
|
||||||
|
@ -2391,7 +2391,7 @@ static HRESULT WINAPI domdoc_get_schemas(
|
||||||
{
|
{
|
||||||
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
||||||
HRESULT hr = S_FALSE;
|
HRESULT hr = S_FALSE;
|
||||||
IXMLDOMSchemaCollection *cur_schema = This->schema;
|
IXMLDOMSchemaCollection2* cur_schema = This->schema;
|
||||||
|
|
||||||
TRACE("(%p)->(%p)\n", This, var1);
|
TRACE("(%p)->(%p)\n", This, var1);
|
||||||
|
|
||||||
|
@ -2400,7 +2400,7 @@ static HRESULT WINAPI domdoc_get_schemas(
|
||||||
|
|
||||||
if(cur_schema)
|
if(cur_schema)
|
||||||
{
|
{
|
||||||
hr = IXMLDOMSchemaCollection_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
|
hr = IXMLDOMSchemaCollection2_QueryInterface(cur_schema, &IID_IDispatch, (void**)&V_DISPATCH(var1));
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
V_VT(var1) = VT_DISPATCH;
|
V_VT(var1) = VT_DISPATCH;
|
||||||
}
|
}
|
||||||
|
@ -2413,7 +2413,7 @@ static HRESULT WINAPI domdoc_putref_schemas(
|
||||||
{
|
{
|
||||||
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
||||||
HRESULT hr = E_FAIL;
|
HRESULT hr = E_FAIL;
|
||||||
IXMLDOMSchemaCollection *new_schema = NULL;
|
IXMLDOMSchemaCollection2* new_schema = NULL;
|
||||||
|
|
||||||
FIXME("(%p): semi-stub\n", This);
|
FIXME("(%p): semi-stub\n", This);
|
||||||
switch(V_VT(&var1))
|
switch(V_VT(&var1))
|
||||||
|
@ -2437,18 +2437,48 @@ static HRESULT WINAPI domdoc_putref_schemas(
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
if(SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
|
IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
|
||||||
if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
|
if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOL is_wellformed(xmlDocPtr doc)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_XMLDOC_PROPERTIES
|
||||||
|
return doc->properties & XML_DOC_WELLFORMED;
|
||||||
|
#else
|
||||||
|
/* Not a full check, but catches the worst violations */
|
||||||
|
xmlNodePtr child;
|
||||||
|
int root = 0;
|
||||||
|
|
||||||
|
for (child = doc->children; child != NULL; child = child->next)
|
||||||
|
{
|
||||||
|
switch (child->type)
|
||||||
|
{
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
if (++root > 1)
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
case XML_TEXT_NODE:
|
||||||
|
case XML_CDATA_SECTION_NODE:
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return root == 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
|
static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
LIBXML2_CALLBACK_ERR(domdoc_validate, msg, ap);
|
LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2456,44 +2486,111 @@ static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ..
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
LIBXML2_CALLBACK_WARN(domdoc_validate, msg, ap);
|
LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI domdoc_validateNode(
|
||||||
|
IXMLDOMDocument3* iface,
|
||||||
|
IXMLDOMNode* node,
|
||||||
|
IXMLDOMParseError** err)
|
||||||
|
{
|
||||||
|
domdoc* This = impl_from_IXMLDOMDocument3(iface);
|
||||||
|
LONG state, err_code = 0;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
int validated = 0;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%p, %p)\n", This, node, err);
|
||||||
|
domdoc_get_readyState(iface, &state);
|
||||||
|
if (state != READYSTATE_COMPLETE)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
*err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
|
||||||
|
return E_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
*err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
*err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_wellformed(get_doc(This)))
|
||||||
|
{
|
||||||
|
ERR("doc not well-formed");
|
||||||
|
if (err)
|
||||||
|
*err = create_parseError(E_XML_NOTWF, NULL, NULL, NULL, 0, 0, 0);
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DTD validation */
|
||||||
|
if (get_doc(This)->intSubset || get_doc(This)->extSubset)
|
||||||
|
{
|
||||||
|
xmlValidCtxtPtr vctx = xmlNewValidCtxt();
|
||||||
|
vctx->error = validate_error;
|
||||||
|
vctx->warning = validate_warning;
|
||||||
|
++validated;
|
||||||
|
|
||||||
|
if (!((node == (IXMLDOMNode*)iface)?
|
||||||
|
xmlValidateDocument(vctx, get_doc(This)) :
|
||||||
|
xmlValidateElement(vctx, get_doc(This), get_node_obj(node)->node)))
|
||||||
|
{
|
||||||
|
/* TODO: get a real error code here */
|
||||||
|
TRACE("DTD validation failed\n");
|
||||||
|
err_code = E_XML_INVALID;
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
xmlFreeValidCtxt(vctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schema validation */
|
||||||
|
if (hr == S_OK && This->schema != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
hr = SchemaCache_validate_tree(This->schema, get_node_obj(node)->node);
|
||||||
|
if (!FAILED(hr))
|
||||||
|
{
|
||||||
|
++validated;
|
||||||
|
/* TODO: get a real error code here */
|
||||||
|
TRACE("schema validation failed\n");
|
||||||
|
if (hr != S_OK)
|
||||||
|
err_code = E_XML_INVALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* not really OK, just didn't find a schema for the ns */
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validated)
|
||||||
|
{
|
||||||
|
TRACE("no DTD or schema found\n");
|
||||||
|
err_code = E_XML_NODTD;
|
||||||
|
hr = S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
*err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI domdoc_validate(
|
static HRESULT WINAPI domdoc_validate(
|
||||||
IXMLDOMDocument3* iface,
|
IXMLDOMDocument3* iface,
|
||||||
IXMLDOMParseError** err)
|
IXMLDOMParseError** err)
|
||||||
{
|
{
|
||||||
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
||||||
LONG state;
|
|
||||||
xmlValidCtxtPtr vctx;
|
|
||||||
|
|
||||||
TRACE("(%p)->(%p)\n", This, err);
|
TRACE("(%p)->(%p)\n", This, err);
|
||||||
domdoc_get_readyState(iface, &state);
|
return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
|
||||||
if (state != READYSTATE_COMPLETE)
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
*err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
|
|
||||||
return E_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
vctx = xmlNewValidCtxt();
|
|
||||||
vctx->error = validate_error;
|
|
||||||
vctx->warning = validate_warning;
|
|
||||||
|
|
||||||
if (xmlValidateDocument(vctx, get_doc(This)))
|
|
||||||
{
|
|
||||||
if (err)
|
|
||||||
*err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
|
|
||||||
xmlFreeValidCtxt(vctx);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
FIXME("partial stub!\n");
|
|
||||||
if (err)
|
|
||||||
*err = create_parseError(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
|
|
||||||
xmlFreeValidCtxt(vctx);
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI domdoc_setProperty(
|
static HRESULT WINAPI domdoc_setProperty(
|
||||||
|
@ -2729,16 +2826,6 @@ static HRESULT WINAPI domdoc_getProperty(
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI domdoc_validateNode(
|
|
||||||
IXMLDOMDocument3* iface,
|
|
||||||
IXMLDOMNode* node,
|
|
||||||
IXMLDOMParseError** error)
|
|
||||||
{
|
|
||||||
domdoc *This = impl_from_IXMLDOMDocument3( iface );
|
|
||||||
FIXME("(%p)->(%p %p): stub\n", This, node, error);
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI domdoc_importNode(
|
static HRESULT WINAPI domdoc_importNode(
|
||||||
IXMLDOMDocument3* iface,
|
IXMLDOMDocument3* iface,
|
||||||
IXMLDOMNode* node,
|
IXMLDOMNode* node,
|
||||||
|
|
|
@ -3507,7 +3507,7 @@ static void test_IXMLDOMDocument2(void)
|
||||||
res = 0;
|
res = 0;
|
||||||
ole_check(IXMLDOMParseError_get_errorCode(err, &res));
|
ole_check(IXMLDOMParseError_get_errorCode(err, &res));
|
||||||
/* XML_E_NODTD */
|
/* XML_E_NODTD */
|
||||||
todo_wine ok(res == E_XML_NODTD, "got %08x\n", res);
|
ok(res == E_XML_NODTD, "got %08x\n", res);
|
||||||
IXMLDOMParseError_Release(err);
|
IXMLDOMParseError_Release(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue