Adam Martinson : msxml3: Implement domdoc schema validation.

Alexandre Julliard julliard at winehq.org
Wed Nov 3 11:37:06 CDT 2010


Module: wine
Branch: master
Commit: c367215bbca3b51779f29819c73b24bd20975aab
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c367215bbca3b51779f29819c73b24bd20975aab

Author: Adam Martinson <amartinson at codeweavers.com>
Date:   Tue Nov  2 17:20:31 2010 -0500

msxml3: Implement domdoc schema validation.

---

 dlls/msxml3/domdoc.c       |  157 ++++++++++++++++++++++++++++++++++----------
 dlls/msxml3/tests/domdoc.c |    2 +-
 2 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 500bde8..a5100f0 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -116,7 +116,7 @@ struct domdoc
     VARIANT_BOOL resolving;
     VARIANT_BOOL preserving;
     domdoc_properties* properties;
-    IXMLDOMSchemaCollection *schema;
+    IXMLDOMSchemaCollection2* schema;
     bsc_t *bsc;
     HRESULT error;
 
@@ -875,7 +875,7 @@ static ULONG WINAPI domdoc_Release(
         if (This->site)
             IUnknown_Release( This->site );
         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);
         HeapFree( GetProcessHeap(), 0, This );
     }
@@ -2391,7 +2391,7 @@ static HRESULT WINAPI domdoc_get_schemas(
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
     HRESULT hr = S_FALSE;
-    IXMLDOMSchemaCollection *cur_schema = This->schema;
+    IXMLDOMSchemaCollection2* cur_schema = This->schema;
 
     TRACE("(%p)->(%p)\n", This, var1);
 
@@ -2400,7 +2400,7 @@ static HRESULT WINAPI domdoc_get_schemas(
 
     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))
             V_VT(var1) = VT_DISPATCH;
     }
@@ -2413,7 +2413,7 @@ static HRESULT WINAPI domdoc_putref_schemas(
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
     HRESULT hr = E_FAIL;
-    IXMLDOMSchemaCollection *new_schema = NULL;
+    IXMLDOMSchemaCollection2* new_schema = NULL;
 
     FIXME("(%p): semi-stub\n", This);
     switch(V_VT(&var1))
@@ -2437,18 +2437,48 @@ static HRESULT WINAPI domdoc_putref_schemas(
 
     if(SUCCEEDED(hr))
     {
-        IXMLDOMSchemaCollection *old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
-        if(old_schema) IXMLDOMSchemaCollection_Release(old_schema);
+        IXMLDOMSchemaCollection2* old_schema = InterlockedExchangePointer((void**)&This->schema, new_schema);
+        if(old_schema) IXMLDOMSchemaCollection2_Release(old_schema);
     }
 
     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, ...)
 {
     va_list ap;
     va_start(ap, msg);
-    LIBXML2_CALLBACK_ERR(domdoc_validate, msg, ap);
+    LIBXML2_CALLBACK_ERR(domdoc_validateNode, msg, ap);
     va_end(ap);
 }
 
@@ -2456,44 +2486,111 @@ static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ..
 {
     va_list ap;
     va_start(ap, msg);
-    LIBXML2_CALLBACK_WARN(domdoc_validate, msg, ap);
+    LIBXML2_CALLBACK_WARN(domdoc_validateNode, msg, ap);
     va_end(ap);
 }
 
-static HRESULT WINAPI domdoc_validate(
+static HRESULT WINAPI domdoc_validateNode(
     IXMLDOMDocument3* iface,
+    IXMLDOMNode* node,
     IXMLDOMParseError** err)
 {
-    domdoc *This = impl_from_IXMLDOMDocument3( iface );
-    LONG state;
-    xmlValidCtxtPtr vctx;
+    domdoc* This = impl_from_IXMLDOMDocument3(iface);
+    LONG state, err_code = 0;
+    HRESULT hr = S_OK;
+    int validated = 0;
 
-    TRACE("(%p)->(%p)\n", This, err);
+    TRACE("(%p)->(%p, %p)\n", This, node, err);
     domdoc_get_readyState(iface, &state);
     if (state != READYSTATE_COMPLETE)
     {
         if (err)
-            *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
+           *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
         return E_PENDING;
     }
 
-    vctx = xmlNewValidCtxt();
-    vctx->error = validate_error;
-    vctx->warning = validate_warning;
+    if (!node)
+    {
+        if (err)
+            *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
+        return E_POINTER;
+    }
 
-    if (xmlValidateDocument(vctx, get_doc(This)))
+    if (!get_node_obj(node)->node || get_node_obj(node)->node->doc != get_doc(This))
     {
         if (err)
-            *err = create_parseError(0, NULL, NULL, NULL, 0, 0, 0);
+            *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);
-        return S_OK;
     }
 
-    FIXME("partial stub!\n");
+    /* 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(0xC00CE223, NULL, NULL, NULL, 0, 0, 0);
-    xmlFreeValidCtxt(vctx);
-    return S_FALSE;
+        *err = create_parseError(err_code, NULL, NULL, NULL, 0, 0, 0);
+
+    return hr;
+}
+
+static HRESULT WINAPI domdoc_validate(
+    IXMLDOMDocument3* iface,
+    IXMLDOMParseError** err)
+{
+    domdoc *This = impl_from_IXMLDOMDocument3( iface );
+    TRACE("(%p)->(%p)\n", This, err);
+    return domdoc_validateNode(iface, (IXMLDOMNode*)iface, err);
 }
 
 static HRESULT WINAPI domdoc_setProperty(
@@ -2729,16 +2826,6 @@ static HRESULT WINAPI domdoc_getProperty(
     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(
     IXMLDOMDocument3* iface,
     IXMLDOMNode* node,
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index e009829..3ab6be3 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -3507,7 +3507,7 @@ static void test_IXMLDOMDocument2(void)
         res = 0;
         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
         /* 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);
     }
 




More information about the wine-cvs mailing list