From c40d3462cb138d5e665063fd7af8914545c5d27a Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Mon, 4 Jun 2018 18:20:10 +0200 Subject: Properly decompose vnd.sun.star.pkg URL When the URL encoded in the vnd.sun.star.pkg URL's authority contains a "@" (e.g., because it is a file URL denoting a pathname containging a "@" in one of the segments), that "@" need not be encoded (cf. the grammar at the top of tools/source/fsys/urlobj.cxx) and INetURLObject::GetHost would only return the part following the "@". When constructing sBaseURI in ODatabaseContext::loadObjectFromURL (dbaccess/source/core/dataaccess/databasecontext.cxx), the path part shall obviously not be decoded (but which the original code erroneously did). However, when obtaining sStreamRelPath in ODBFilter::implImport (dbaccess/source/filter/xml/xmlfilter.cxx), it isn't clear to me whether the path should be decoded, so I left that in (and added a TODO). (Caused `make CppunitTest_sw_uiwriter CPPUNIT_TEST_NAME=SwUiWriterTest::testEmbeddedDataSource` to fail when SRCDIR is such a pathname containing a "@" in one of the segments.) Change-Id: I6ffd842f3f3d37d2682e7cf14399fb3dbfa0a2aa Reviewed-on: https://gerrit.libreoffice.org/55286 Reviewed-by: Stephan Bergmann Tested-by: Stephan Bergmann (cherry picked from commit e310ac4ab942feb014f3bb5bc4519dcf966b47fc) Reviewed-on: https://gerrit.libreoffice.org/55633 Tested-by: Jenkins Reviewed-by: Christian Lohmaier --- .../source/core/dataaccess/databasecontext.cxx | 24 +++++++++++-- dbaccess/source/filter/xml/xmlfilter.cxx | 40 ++++++++++++++++++---- 2 files changed, 56 insertions(+), 8 deletions(-) (limited to 'dbaccess') diff --git a/dbaccess/source/core/dataaccess/databasecontext.cxx b/dbaccess/source/core/dataaccess/databasecontext.cxx index 974d431109d7..3f4a443abaa1 100644 --- a/dbaccess/source/core/dataaccess/databasecontext.cxx +++ b/dbaccess/source/core/dataaccess/databasecontext.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -363,8 +365,26 @@ Reference< XInterface > ODatabaseContext::loadObjectFromURL(const OUString& _rNa if (bEmbeddedDataSource) { // In this case the host contains the real path, and the path is the embedded stream name. - OUString sBaseURI = aURL.GetHost(INetURLObject::DecodeMechanism::WithCharset) + aURL.GetURLPath(INetURLObject::DecodeMechanism::WithCharset); - aArgs.put("BaseURI", sBaseURI); + auto const uri = css::uri::UriReferenceFactory::create(m_aContext)->parse(_sURL); + if (uri.is() && uri->isAbsolute() && uri->isHierarchical() + && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment()) + { + auto const auth = uri->getAuthority(); + auto const decAuth = rtl::Uri::decode( + auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8); + if (auth.isEmpty() == decAuth.isEmpty()) { + // Decoding of auth to UTF-8 succeeded: + OUString sBaseURI = decAuth + uri->getPath(); + aArgs.put("BaseURI", sBaseURI); + } else { + SAL_WARN( + "dbaccess.core", + "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL"); + } + } else { + SAL_WARN( + "dbaccess.core", "<" << _sURL << "> cannot be parse as vnd.sun.star.pkg URL"); + } } Sequence< PropertyValue > aResource( aArgs.getPropertyValues() ); diff --git a/dbaccess/source/filter/xml/xmlfilter.cxx b/dbaccess/source/filter/xml/xmlfilter.cxx index 906a2bd69272..a77db0ecec0f 100644 --- a/dbaccess/source/filter/xml/xmlfilter.cxx +++ b/dbaccess/source/filter/xml/xmlfilter.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include #include #include +#include using namespace ::com::sun::star; @@ -308,12 +310,38 @@ bool ODBFilter::implImport( const Sequence< PropertyValue >& rDescriptor ) OUString sStreamRelPath; if (sFileName.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:")) { - // In this case the host contains the real path, and the path is the embedded stream name. - INetURLObject aURL(sFileName); - sFileName = aURL.GetHost(INetURLObject::DecodeMechanism::WithCharset); - sStreamRelPath = aURL.GetURLPath(INetURLObject::DecodeMechanism::WithCharset); - if (sStreamRelPath.startsWith("/")) - sStreamRelPath = sStreamRelPath.copy(1); + // In this case the authority contains the real path, and the path is the embedded stream name. + auto const uri = css::uri::UriReferenceFactory::create(GetComponentContext()) + ->parse(sFileName); + if (uri.is() && uri->isAbsolute() && uri->isHierarchical() + && uri->hasAuthority() && !uri->hasQuery() && !uri->hasFragment()) + { + auto const auth = uri->getAuthority(); + auto const decAuth = rtl::Uri::decode( + auth, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8); + auto path = uri->getPath(); + if (!path.isEmpty()) { + assert(path[0] == '/'); + path = path.copy(1); + } + auto const decPath = rtl::Uri::decode( + path, rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8); + //TODO: really decode path? + if (auth.isEmpty() == decAuth.isEmpty() && path.isEmpty() == decPath.isEmpty()) + { + // Decoding of auth and path to UTF-8 succeeded: + sFileName = decAuth; + sStreamRelPath = decPath; + } else { + SAL_WARN( + "dbaccess", + "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL"); + } + } else { + SAL_WARN( + "dbaccess", + "<" << sFileName << "> cannot be parse as vnd.sun.star.pkg URL"); + } } pMedium = new SfxMedium(sFileName, (StreamMode::READ | StreamMode::NOCREATE)); -- cgit