[2/4] msxml3: Respect 'namespaces' feature calling content handler callbacks

Nikolay Sivov nsivov at codeweavers.com
Thu Apr 19 01:58:21 CDT 2012


Respect 'namespaces' feature calling content handler callbacks
-------------- next part --------------
>From 90beaa5bc9651d90b4e821f5fa33bde9e80b4e0f Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Thu, 19 Apr 2012 10:46:03 +0400
Subject: [PATCH 2/4] Respect 'namespaces' feature calling content handler callbacks

---
 dlls/msxml3/saxreader.c       |   97 +++++++++++++++----------
 dlls/msxml3/tests/saxreader.c |  160 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 193 insertions(+), 64 deletions(-)

diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c
index 8205c99..e9ab841 100644
--- a/dlls/msxml3/saxreader.c
+++ b/dlls/msxml3/saxreader.c
@@ -302,6 +302,11 @@ static inline HRESULT get_feature_value(const saxreader *reader, saxreader_featu
     return S_OK;
 }
 
+static BOOL is_namespaces_enabled(const saxreader *reader)
+{
+    return (reader->version < MSXML4) || (reader->features & Namespaces);
+}
+
 static inline BOOL has_content_handler(const saxlocator *locator)
 {
     return  (locator->vbInterface && locator->saxreader->vbcontentHandler) ||
@@ -1286,42 +1291,53 @@ static void libxmlStartElementNS(
     if (has_content_handler(This))
     {
         BSTR uri;
-        int i;
 
-        for (i = 0; i < nb_namespaces; i++)
+        if (is_namespaces_enabled(This->saxreader))
         {
-            if(This->vbInterface)
-                hr = IVBSAXContentHandler_startPrefixMapping(
-                        This->saxreader->vbcontentHandler,
-                        &element->ns[i].prefix,
-                        &element->ns[i].uri);
-            else
-                hr = ISAXContentHandler_startPrefixMapping(
-                        This->saxreader->contentHandler,
-                        element->ns[i].prefix,
-                        SysStringLen(element->ns[i].prefix),
-                        element->ns[i].uri,
-                        SysStringLen(element->ns[i].uri));
+            int i;
 
-            if (sax_callback_failed(This, hr))
+            for (i = 0; i < nb_namespaces; i++)
             {
-                format_error_message_from_id(This, hr);
-                return;
+                if (This->vbInterface)
+                    hr = IVBSAXContentHandler_startPrefixMapping(
+                            This->saxreader->vbcontentHandler,
+                            &element->ns[i].prefix,
+                            &element->ns[i].uri);
+                else
+                    hr = ISAXContentHandler_startPrefixMapping(
+                            This->saxreader->contentHandler,
+                            element->ns[i].prefix,
+                            SysStringLen(element->ns[i].prefix),
+                            element->ns[i].uri,
+                            SysStringLen(element->ns[i].uri));
+
+                if (sax_callback_failed(This, hr))
+                {
+                    format_error_message_from_id(This, hr);
+                    return;
+                }
             }
         }
 
         uri = find_element_uri(This, URI);
 
         hr = SAXAttributes_populate(This, nb_namespaces, namespaces, nb_attributes, attributes);
-        if(hr == S_OK)
+        if (hr == S_OK)
         {
-            if(This->vbInterface)
+            BSTR local;
+
+            if (is_namespaces_enabled(This->saxreader))
+                local = element->local;
+            else
+                uri = local = NULL;
+
+            if (This->vbInterface)
                 hr = IVBSAXContentHandler_startElement(This->saxreader->vbcontentHandler,
-                        &uri, &element->local, &element->qname, &This->IVBSAXAttributes_iface);
+                        &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
             else
                 hr = ISAXContentHandler_startElement(This->saxreader->contentHandler,
                         uri, SysStringLen(uri),
-                        element->local, SysStringLen(element->local),
+                        local, SysStringLen(local),
                         element->qname, SysStringLen(element->qname),
                         &This->ISAXAttributes_iface);
         }
@@ -1340,9 +1356,8 @@ static void libxmlEndElementNS(
     saxlocator *This = ctx;
     element_entry *element;
     const xmlChar *p;
+    BSTR uri, local;
     HRESULT hr;
-    BSTR uri;
-    int i;
 
     update_position(This, FALSE);
     p = This->pParserCtxt->input->cur;
@@ -1382,15 +1397,20 @@ static void libxmlEndElementNS(
         return;
     }
 
-    if(This->vbInterface)
+    if (is_namespaces_enabled(This->saxreader))
+        local = element->local;
+    else
+        uri = local = NULL;
+
+    if (This->vbInterface)
         hr = IVBSAXContentHandler_endElement(
                 This->saxreader->vbcontentHandler,
-                &uri, &element->local, &element->qname);
+                &uri, &local, &element->qname);
     else
         hr = ISAXContentHandler_endElement(
                 This->saxreader->contentHandler,
                 uri, SysStringLen(uri),
-                element->local, SysStringLen(element->local),
+                local, SysStringLen(local),
                 element->qname, SysStringLen(element->qname));
 
     This->nb_attributes = 0;
@@ -1402,18 +1422,21 @@ static void libxmlEndElementNS(
         return;
     }
 
-    i = -1;
-    while (iterate_endprefix_index(This, element, &i))
+    if (is_namespaces_enabled(This->saxreader))
     {
-        if(This->vbInterface)
-            hr = IVBSAXContentHandler_endPrefixMapping(
-                    This->saxreader->vbcontentHandler, &element->ns[i].prefix);
-        else
-            hr = ISAXContentHandler_endPrefixMapping(
-                    This->saxreader->contentHandler,
-                    element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
+        int i = -1;
+        while (iterate_endprefix_index(This, element, &i))
+        {
+            if (This->vbInterface)
+                hr = IVBSAXContentHandler_endPrefixMapping(
+                        This->saxreader->vbcontentHandler, &element->ns[i].prefix);
+            else
+                hr = ISAXContentHandler_endPrefixMapping(
+                        This->saxreader->contentHandler,
+                        element->ns[i].prefix, SysStringLen(element->ns[i].prefix));
 
-        if (sax_callback_failed(This, hr)) break;
+            if (sax_callback_failed(This, hr)) break;
+       }
     }
 
     if (sax_callback_failed(This, hr))
@@ -2820,7 +2843,7 @@ static HRESULT WINAPI saxxmlreader_putFeature(
     /* accepted cases */
     if ((feature == ExternalGeneralEntities   && value == VARIANT_FALSE) ||
         (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
-        (feature == Namespaces                && value == VARIANT_TRUE ))
+         feature == Namespaces)
     {
         return set_feature_value(This, feature, value);
     }
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index aa3b2a5..0c107af 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -554,7 +554,7 @@ static const CHAR testXML[] =
 "   <Name>Captain Ahab</Name>\n"
 "</BankAccount>\n";
 
-static const CHAR szTestAttributes[] =
+static const char test_attributes[] =
 "<?xml version=\"1.0\" ?>\n"
 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
 "<node1 xmlns:p=\"test\" />"
@@ -733,6 +733,28 @@ static struct call_entry content_handler_test_attributes_alternate_4[] = {
     { CH_ENDTEST }
 };
 
+/* 'namespace' feature switched off */
+static struct attribute_entry ch_attributes_alt_no_ns[] = {
+    { "", "", "xmlns:test", "prefix_test" },
+    { "", "", "xmlns", "prefix" },
+    { "", "", "test:arg1", "arg1" },
+    { "", "", "arg2", "arg2" },
+    { "", "", "test:ar3", "arg3" },
+    { NULL }
+};
+
+static struct call_entry content_handler_test_attributes_alt_no_ns[] = {
+    { CH_PUTDOCUMENTLOCATOR, 1, 0, S_OK },
+    { CH_STARTDOCUMENT, 1, 22, S_OK },
+    { CH_STARTELEMENT, 2, 95, S_OK, "", "", "document", ch_attributes_alt_no_ns },
+    { CH_CHARACTERS, 3, 1, S_OK, "\n" },
+    { CH_STARTELEMENT, 3, 24, S_OK, "", "", "node1", ch_attributes2 },
+    { CH_ENDELEMENT, 3, 24, S_OK, "", "", "node1" },
+    { CH_ENDELEMENT, 3, 35, S_OK, "", "", "document" },
+    { CH_ENDDOCUMENT, 4, 0, S_OK },
+    { CH_ENDTEST }
+};
+
 static struct attribute_entry ch_attributes_alt_6[] = {
     { "prefix_test", "arg1", "test:arg1", "arg1" },
     { "", "arg2", "arg2", "arg2" },
@@ -796,6 +818,7 @@ static const char xmlspace_attr[] =
 
 static struct call_entry *expectCall;
 static ISAXLocator *locator;
+static ISAXXMLReader *g_reader;
 int msxml_version;
 
 static void set_expected_seq(struct call_entry *expected)
@@ -968,11 +991,16 @@ static HRESULT WINAPI contentHandler_startElement(
 
     if (len)
     {
+        VARIANT_BOOL v;
         int i;
 
         struct attribute_entry *attr;
         attr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(struct attribute_entry));
 
+        v = VARIANT_TRUE;
+        hr = ISAXXMLReader_getFeature(g_reader, _bstr_("http://xml.org/sax/features/namespaces"), &v);
+        EXPECT_HR(hr, S_OK);
+
         for (i = 0; i < len; i++)
         {
             const WCHAR *value;
@@ -985,8 +1013,18 @@ static HRESULT WINAPI contentHandler_startElement(
             hr = ISAXAttributes_getValue(saxattr, i, &value, &value_len);
             EXPECT_HR(hr, S_OK);
 
-            attr[i].uriW   = SysAllocStringLen(uri, uri_len);
-            attr[i].localW = SysAllocStringLen(localname, local_len);
+            /* if 'namespaces' switched off uri and local name contains garbage */
+            if (v == VARIANT_FALSE && msxml_version > 0)
+            {
+                attr[i].uriW   = SysAllocStringLen(NULL, 0);
+                attr[i].localW = SysAllocStringLen(NULL, 0);
+            }
+            else
+            {
+                attr[i].uriW   = SysAllocStringLen(uri, uri_len);
+                attr[i].localW = SysAllocStringLen(localname, local_len);
+            }
+
             attr[i].qnameW = SysAllocStringLen(qname, qname_len);
             attr[i].valueW = SysAllocStringLen(value, value_len);
         }
@@ -1720,8 +1758,8 @@ static void test_saxreader(void)
     SAFEARRAYBOUND SADim[1];
     char *ptr = NULL;
     IStream *stream;
-    ULARGE_INTEGER liSize;
-    LARGE_INTEGER liPos;
+    ULARGE_INTEGER size;
+    LARGE_INTEGER pos;
     ULONG written;
     HANDLE file;
     static const CHAR testXmlA[] = "test.xml";
@@ -1742,8 +1780,14 @@ static void test_saxreader(void)
 
         hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (void**)&reader);
         EXPECT_HR(hr, S_OK);
+        g_reader = reader;
 
-        msxml_version = IsEqualGUID(table->clsid, &CLSID_SAXXMLReader60) ? 6 : 0;
+        if (IsEqualGUID(table->clsid, &CLSID_SAXXMLReader40))
+            msxml_version = 4;
+        else if (IsEqualGUID(table->clsid, &CLSID_SAXXMLReader60))
+            msxml_version = 6;
+        else
+            msxml_version = 0;
 
         /* crashes on old versions */
         if (!IsEqualGUID(table->clsid, &CLSID_SAXXMLReader40) &&
@@ -1809,11 +1853,11 @@ static void test_saxreader(void)
         SafeArrayDestroy(sa);
 
         CreateStreamOnHGlobal(NULL, TRUE, &stream);
-        liSize.QuadPart = strlen(testXML);
-        IStream_SetSize(stream, liSize);
+        size.QuadPart = strlen(testXML);
+        IStream_SetSize(stream, size);
         IStream_Write(stream, testXML, strlen(testXML), &written);
-        liPos.QuadPart = 0;
-        IStream_Seek(stream, liPos, STREAM_SEEK_SET, NULL);
+        pos.QuadPart = 0;
+        IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
         V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
         V_UNKNOWN(&var) = (IUnknown*)stream;
 
@@ -1825,11 +1869,11 @@ static void test_saxreader(void)
         IStream_Release(stream);
 
         CreateStreamOnHGlobal(NULL, TRUE, &stream);
-        liSize.QuadPart = strlen(szTestAttributes);
-        IStream_SetSize(stream, liSize);
-        IStream_Write(stream, szTestAttributes, strlen(szTestAttributes), &written);
-        liPos.QuadPart = 0;
-        IStream_Seek(stream, liPos, STREAM_SEEK_SET, NULL);
+        size.QuadPart = strlen(test_attributes);
+        IStream_SetSize(stream, size);
+        IStream_Write(stream, test_attributes, strlen(test_attributes), &written);
+        pos.QuadPart = 0;
+        IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
         V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
         V_UNKNOWN(&var) = (IUnknown*)stream;
 
@@ -1962,6 +2006,32 @@ static void test_saxreader(void)
         else
             ok_sequence(sequences, CONTENT_HANDLER_INDEX, test_seq, "xml:space handling", FALSE);
 
+        /* switch off 'namespaces' feature */
+        hr = ISAXXMLReader_putFeature(reader, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE);
+        EXPECT_HR(hr, S_OK);
+
+        CreateStreamOnHGlobal(NULL, TRUE, &stream);
+        size.QuadPart = strlen(test_attributes);
+        IStream_SetSize(stream, size);
+        IStream_Write(stream, test_attributes, strlen(test_attributes), &written);
+        pos.QuadPart = 0;
+        IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+        V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
+        V_UNKNOWN(&var) = (IUnknown*)stream;
+
+        if (IsEqualGUID(table->clsid, &CLSID_SAXXMLReader40) ||
+            IsEqualGUID(table->clsid, &CLSID_SAXXMLReader60))
+        {
+            test_seq = content_handler_test_attributes_alt_no_ns;
+        }
+        else
+            test_seq = content_handler_test_attributes;
+
+        set_expected_seq(test_seq);
+        hr = ISAXXMLReader_parse(reader, var);
+        EXPECT_HR(hr, S_OK);
+        ok_sequence(sequences, CONTENT_HANDLER_INDEX, test_seq, "content test attributes", TRUE);
+
         ISAXXMLReader_Release(reader);
         table++;
     }
@@ -2078,16 +2148,22 @@ struct feature_ns_entry_t {
     const GUID *guid;
     const char *clsid;
     VARIANT_BOOL value;
+    VARIANT_BOOL value2; /* feature value after feature set to 0xc */
 };
 
 static const struct feature_ns_entry_t feature_ns_entry_data[] = {
-    { &CLSID_SAXXMLReader,   "CLSID_SAXXMLReader",   VARIANT_TRUE },
-    { &CLSID_SAXXMLReader30, "CLSID_SAXXMLReader30", VARIANT_TRUE },
-    { &CLSID_SAXXMLReader40, "CLSID_SAXXMLReader40", VARIANT_TRUE },
-    { &CLSID_SAXXMLReader60, "CLSID_SAXXMLReader60", VARIANT_TRUE },
+    { &CLSID_SAXXMLReader,   "CLSID_SAXXMLReader",   VARIANT_TRUE, VARIANT_FALSE },
+    { &CLSID_SAXXMLReader30, "CLSID_SAXXMLReader30", VARIANT_TRUE, VARIANT_FALSE },
+    { &CLSID_SAXXMLReader40, "CLSID_SAXXMLReader40", VARIANT_TRUE, VARIANT_TRUE },
+    { &CLSID_SAXXMLReader60, "CLSID_SAXXMLReader60", VARIANT_TRUE, VARIANT_TRUE },
     { 0 }
 };
 
+static const char *feature_names[] = {
+    "http://xml.org/sax/features/namespaces",
+    0
+};
+
 static void test_saxreader_features(void)
 {
     const struct feature_ns_entry_t *entry = feature_ns_entry_data;
@@ -2096,6 +2172,7 @@ static void test_saxreader_features(void)
     while (entry->guid)
     {
         VARIANT_BOOL value;
+        const char **name;
         HRESULT hr;
 
         hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (void**)&reader);
@@ -2106,15 +2183,44 @@ static void test_saxreader_features(void)
             continue;
         }
 
-        value = 0xc;
-        hr = ISAXXMLReader_getFeature(reader, _bstr_("http://xml.org/sax/features/namespaces"), &value);
-        EXPECT_HR(hr, S_OK);
-        ok(entry->value == value, "%s: got wrong default value %x, expected %x\n", entry->clsid, value, entry->value);
+        name = feature_names;
+        while (*name)
+        {
+            value = 0xc;
+            hr = ISAXXMLReader_getFeature(reader, _bstr_(*name), &value);
+            EXPECT_HR(hr, S_OK);
+            ok(entry->value == value, "%s: got wrong default value %x, expected %x\n", entry->clsid, value, entry->value);
 
-        value = 0xc;
-        hr = ISAXXMLReader_getFeature(reader, _bstr_("http://xml.org/sax/features/namespace-prefixes"), &value);
-        EXPECT_HR(hr, S_OK);
-        ok(entry->value == value, "%s: got wrong default value %x, expected %x\n", entry->clsid, value, entry->value);
+            value = 0xc;
+            hr = ISAXXMLReader_putFeature(reader, _bstr_(*name), value);
+            EXPECT_HR(hr, S_OK);
+
+            value = 0xd;
+            hr = ISAXXMLReader_getFeature(reader, _bstr_(*name), &value);
+            EXPECT_HR(hr, S_OK);
+            if (IsEqualGUID(entry->guid, &CLSID_SAXXMLReader40) ||
+                IsEqualGUID(entry->guid, &CLSID_SAXXMLReader60))
+            todo_wine
+                ok(entry->value2 == value, "%s: got wrong value %x, expected %x\n", entry->clsid, value, entry->value2);
+            else
+                ok(entry->value2 == value, "%s: got wrong value %x, expected %x\n", entry->clsid, value, entry->value2);
+
+            hr = ISAXXMLReader_putFeature(reader, _bstr_(*name), VARIANT_FALSE);
+            EXPECT_HR(hr, S_OK);
+            value = 0xd;
+            hr = ISAXXMLReader_getFeature(reader, _bstr_(*name), &value);
+            EXPECT_HR(hr, S_OK);
+            ok(value == VARIANT_FALSE, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry->clsid, value);
+
+            hr = ISAXXMLReader_putFeature(reader, _bstr_(*name), VARIANT_TRUE);
+            EXPECT_HR(hr, S_OK);
+            value = 0xd;
+            hr = ISAXXMLReader_getFeature(reader, _bstr_(*name), &value);
+            EXPECT_HR(hr, S_OK);
+            ok(value == VARIANT_TRUE, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry->clsid, value);
+
+            name++;
+        }
 
         ISAXXMLReader_Release(reader);
 
-- 
1.5.6.5




More information about the wine-patches mailing list