[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - sax/source

Noel Grandin (via logerrit) logerrit at kemper.freedesktop.org
Tue Feb 9 12:44:09 UTC 2021


 sax/source/fastparser/fastparser.cxx |  145 ++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 2 deletions(-)

New commits:
commit 6b4b1339b4fb9e1436827235526116c1e411fa2f
Author:     Noel Grandin <noelgrandin at gmail.com>
AuthorDate: Sun Nov 8 13:17:36 2020 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Feb 9 13:43:36 2021 +0100

    ofz#26944
    
    this actually a regression from
    
        commit 8c5ffecf1dbd3f93128910433da11d5315661680
        Author: Noel <noelgrandin at gmail.com>
       Date:   Fri Oct 23 15:12:22 2020 +0200
        make SvXMLImport capable of mixing fast- and slow- contexts adhoc
    
    where I did not get the namespace handling right, but it only
    became obvious with
    
        commit 3940cf7d716f3e469f47d3c831a799e58edf2eb8
        Date:   Mon Nov 2 12:26:26 2020 +0200
        drop the SvXMLExport::EndElement method..
    
    Specifically, we have weird logic to treat some bad namespaces
    as good (who knows why), but that logic only exists for the
    slowparser path.
    With the dropping of EndElement(), we ended up with calls
    to SvXMLImport::startUnknownElement() calling
    SvXMLImportContext::StartElement(), but without
    a corresponding call to SvXMLImportContext::endFastElement.
    
    To make this work right, I copied the namespace aliasing code
    to FastParser.
    
    Change-Id: I00ecbf046feeaac6f2a789f801175dba40836f84
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105441
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110284
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 9b35c1682be5..524b17363fa8 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -62,6 +62,8 @@ using namespace ::com::sun::star::io;
 using namespace com::sun::star;
 using namespace sax_fastparser;
 
+static void NormalizeURI( OUString& rName );
+
 namespace {
 
 struct Event;
@@ -1154,8 +1156,10 @@ void FastSaxParserImpl::callbackStartElement(const xmlChar *localName , const xm
             // namespaces[] is (prefix/URI)
             if( namespaces[ i ] != nullptr )
             {
-                DefineNamespace( OString( XML_CAST( namespaces[ i ] )),
-                    OUString( XML_CAST( namespaces[ i + 1 ] ), strlen( XML_CAST( namespaces[ i + 1 ] )), RTL_TEXTENCODING_UTF8 ));
+                OString aPrefix( XML_CAST( namespaces[ i ] ));
+                OUString namespaceURL( XML_CAST( namespaces[ i + 1 ] ), strlen( XML_CAST( namespaces[ i + 1 ] )), RTL_TEXTENCODING_UTF8 );
+                NormalizeURI( namespaceURL );
+                DefineNamespace(aPrefix, namespaceURL);
                 if( rEntity.mxNamespaceHandler.is() )
                     rEvent.mxDeclAttributes->addUnknown( OString( XML_CAST( namespaces[ i ] ) ), OString( XML_CAST( namespaces[ i + 1 ] ) ) );
             }
@@ -1163,6 +1167,7 @@ void FastSaxParserImpl::callbackStartElement(const xmlChar *localName , const xm
             {
                 // default namespace
                 sNamespace = OUString( XML_CAST( namespaces[ i + 1 ] ), strlen( XML_CAST( namespaces[ i + 1 ] )), RTL_TEXTENCODING_UTF8 );
+                NormalizeURI( sNamespace );
                 nNamespaceToken = GetNamespaceToken( sNamespace );
                 if( rEntity.mxNamespaceHandler.is() )
                     rEvent.mxDeclAttributes->addUnknown( "", OString( XML_CAST( namespaces[ i + 1 ] ) ) );
@@ -1433,4 +1438,140 @@ com_sun_star_comp_extensions_xml_sax_FastParser_get_implementation(
     return cppu::acquire(new FastSaxParser);
 }
 
+// ----------------------------------------------------------
+// copy of the code in xmloff/source/core/namespace.cxx, which adds namespace aliases
+// for various dodgy namespace decls in the wild.
+
+static bool NormalizeW3URI( OUString& rName );
+static bool NormalizeOasisURN( OUString& rName );
+
+static void NormalizeURI( OUString& rName )
+{
+    // try OASIS + W3 URI normalization
+    bool bSuccess = NormalizeOasisURN( rName );
+    if( ! bSuccess )
+        bSuccess = NormalizeW3URI( rName );
+}
+
+const OUStringLiteral XML_URI_W3_PREFIX("http://www.w3.org/");
+const OUStringLiteral XML_URI_XFORMS_SUFFIX("/xforms");
+const OUStringLiteral XML_N_XFORMS_1_0("http://www.w3.org/2002/xforms");
+const OUStringLiteral XML_N_SVG("http://www.w3.org/2000/svg");
+const OUStringLiteral XML_N_SVG_COMPAT("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
+const OUStringLiteral XML_N_FO("http://www.w3.org/1999/XSL/Format");
+const OUStringLiteral XML_N_FO_COMPAT("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
+const OUStringLiteral XML_N_SMIL("http://www.w3.org/2001/SMIL20/");
+const OUStringLiteral XML_N_SMIL_OLD("http://www.w3.org/2001/SMIL20");
+const OUStringLiteral XML_N_SMIL_COMPAT("urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0");
+const OUStringLiteral XML_URN_OASIS_NAMES_TC("urn:oasis:names:tc");
+const OUStringLiteral XML_XMLNS("xmlns");
+const OUStringLiteral XML_OPENDOCUMENT("opendocument");
+const OUStringLiteral XML_1_0("1.0");
+
+static bool NormalizeW3URI( OUString& rName )
+{
+    // check if URI matches:
+    // http://www.w3.org/[0-9]*/[:letter:]*
+    //                   (year)/(WG name)
+    // For the following WG/standards names:
+    // - xforms
+
+    bool bSuccess = false;
+    const OUString& sURIPrefix = XML_URI_W3_PREFIX;
+    if( rName.startsWith( sURIPrefix ) )
+    {
+        const OUString& sURISuffix = XML_URI_XFORMS_SUFFIX ;
+        sal_Int32 nCompareFrom = rName.getLength() - sURISuffix.getLength();
+        if( rName.copy( nCompareFrom ) == sURISuffix )
+        {
+            // found W3 prefix, and xforms suffix
+            rName = XML_N_XFORMS_1_0;
+            bSuccess = true;
+        }
+    }
+    return bSuccess;
+}
+
+static bool NormalizeOasisURN( OUString& rName )
+{
+    // #i38644#
+    // we exported the wrong namespace for smil, so we correct this here on load
+    // for older documents
+    if( rName == XML_N_SVG )
+    {
+        rName = XML_N_SVG_COMPAT;
+        return true;
+    }
+    else if( rName == XML_N_FO )
+    {
+        rName = XML_N_FO_COMPAT;
+        return true;
+    }
+    else if( rName == XML_N_SMIL || rName == XML_N_SMIL_OLD  )
+    {
+        rName = XML_N_SMIL_COMPAT;
+        return true;
+    }
+
+
+    // Check if URN matches
+    // :urn:oasis:names:tc:[^:]*:xmlns:[^:]*:1.[^:]*
+    //                     |---|       |---| |-----|
+    //                     TC-Id      Sub-Id Version
+
+    sal_Int32 nNameLen = rName.getLength();
+    // :urn:oasis:names:tc.*
+    const OUString& rOasisURN = XML_URN_OASIS_NAMES_TC;
+    if( !rName.startsWith( rOasisURN ) )
+        return false;
+
+    // :urn:oasis:names:tc:.*
+    sal_Int32 nPos = rOasisURN.getLength();
+    if( nPos >= nNameLen || rName[nPos] != ':' )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:.*
+    sal_Int32 nTCIdStart = nPos+1;
+    sal_Int32 nTCIdEnd = rName.indexOf( ':', nTCIdStart );
+    if( -1 == nTCIdEnd )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:xmlns.*
+    nPos = nTCIdEnd + 1;
+    OUString sTmp( rName.copy( nPos ) );
+    const OUString& rXMLNS = XML_XMLNS;
+    if( !sTmp.startsWith( rXMLNS ) )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:xmlns:.*
+    nPos += rXMLNS.getLength();
+    if( nPos >= nNameLen || rName[nPos] != ':' )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:xmlns:[^:]*:.*
+    nPos = rName.indexOf( ':', nPos+1 );
+    if( -1 == nPos )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:xmlns:[^:]*:[^:][^:][^:][^:]*
+    sal_Int32 nVersionStart = nPos+1;
+    if( nVersionStart+2 >= nNameLen ||
+        -1 != rName.indexOf( ':', nVersionStart ) )
+        return false;
+
+    // :urn:oasis:names:tc:[^:]:xmlns:[^:]*:1\.[^:][^:]*
+    if( rName[nVersionStart] != '1' || rName[nVersionStart+1] != '.' )
+        return false;
+
+    // replace [tcid] with current TCID and version with current version.
+
+    rName = rName.copy( 0, nTCIdStart ) +
+            XML_OPENDOCUMENT +
+            rName.copy( nTCIdEnd, nVersionStart-nTCIdEnd ) +
+            XML_1_0;
+
+    return true;
+}
+
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list