summaryrefslogtreecommitdiff
path: root/sax
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@gmail.com>2020-11-08 13:17:36 +0200
committerJan Holesovsky <kendy@collabora.com>2021-02-09 13:43:36 +0100
commit6b4b1339b4fb9e1436827235526116c1e411fa2f (patch)
treee18bd0f5caca1095914b8724984ce013c8fa08a5 /sax
parent68892230ddcde135e9951047a3621438eb7987d0 (diff)
ofz#26944
this actually a regression from commit 8c5ffecf1dbd3f93128910433da11d5315661680 Author: Noel <noelgrandin@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@collabora.co.uk> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110284 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Jan Holesovsky <kendy@collabora.com>
Diffstat (limited to 'sax')
-rw-r--r--sax/source/fastparser/fastparser.cxx145
1 files changed, 143 insertions, 2 deletions
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: */