summaryrefslogtreecommitdiffstats
path: root/ucb/source/ucp/package/pkguri.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ucb/source/ucp/package/pkguri.cxx234
1 files changed, 234 insertions, 0 deletions
diff --git a/ucb/source/ucp/package/pkguri.cxx b/ucb/source/ucp/package/pkguri.cxx
new file mode 100644
index 000000000..b1de54aa4
--- /dev/null
+++ b/ucb/source/ucp/package/pkguri.cxx
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <comphelper/storagehelper.hxx>
+
+#include "../inc/urihelper.hxx"
+
+#include "pkguri.hxx"
+
+using namespace package_ucp;
+
+
+// PackageUri Implementation.
+
+
+static void normalize( OUString& rURL )
+{
+ sal_Int32 nPos = 0;
+ do
+ {
+ nPos = rURL.indexOf( '%', nPos );
+ if ( nPos != -1 )
+ {
+ if ( nPos < ( rURL.getLength() - 2 ) )
+ {
+ OUString aTmp = rURL.copy( nPos + 1, 2 );
+ rURL = rURL.replaceAt( nPos + 1, 2, aTmp.toAsciiUpperCase() );
+ nPos++;
+ }
+ }
+ }
+ while ( nPos != -1 );
+}
+
+
+void PackageUri::init() const
+{
+ // Already inited?
+ if ( m_aUri.isEmpty() || !m_aPath.isEmpty() )
+ return;
+
+ // Note: Maybe it's a re-init, setUri only resets m_aPath!
+ m_aPackage.clear();
+ m_aParentUri.clear();
+ m_aName.clear();
+ m_aParam.clear();
+ m_aScheme.clear();
+
+ // URI must match at least: <scheme>://<non_empty_url_to_file>
+ if ( m_aUri.getLength() < PACKAGE_URL_SCHEME_LENGTH + 4 )
+ {
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ return;
+ }
+
+ // Scheme must be followed by '://'
+ if ( ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH ] != ':' )
+ ||
+ ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH + 1 ] != '/' )
+ ||
+ ( m_aUri[ PACKAGE_URL_SCHEME_LENGTH + 2 ] != '/' ) )
+ {
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ return;
+ }
+
+ OUString aPureUri;
+ sal_Int32 nParam = m_aUri.indexOf( '?' );
+ if( nParam >= 0 )
+ {
+ m_aParam = m_aUri.copy( nParam );
+ aPureUri = m_aUri.copy( 0, nParam );
+ }
+ else
+ aPureUri = m_aUri;
+
+ // Scheme is case insensitive.
+ m_aScheme = aPureUri.copy(
+ 0, PACKAGE_URL_SCHEME_LENGTH ).toAsciiLowerCase();
+
+ if ( m_aScheme == PACKAGE_URL_SCHEME || m_aScheme == PACKAGE_ZIP_URL_SCHEME )
+ {
+ if ( m_aScheme == PACKAGE_ZIP_URL_SCHEME )
+ {
+ m_aParam +=
+ ( !m_aParam.isEmpty()
+ ? std::u16string_view( u"&purezip" )
+ : std::u16string_view( u"?purezip" ) );
+ }
+
+ aPureUri = aPureUri.replaceAt( 0,
+ m_aScheme.getLength(),
+ m_aScheme );
+
+ sal_Int32 nStart = PACKAGE_URL_SCHEME_LENGTH + 3;
+ sal_Int32 nEnd = aPureUri.lastIndexOf( '/' );
+ if ( nEnd == PACKAGE_URL_SCHEME_LENGTH + 3 )
+ {
+ // Only <scheme>:/// - Empty authority
+
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ return;
+ }
+ else if ( nEnd == ( aPureUri.getLength() - 1 ) )
+ {
+ if ( aPureUri[ aPureUri.getLength() - 2 ] == '/' )
+ {
+ // Only <scheme>://// or <scheme>://<something>
+
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ return;
+ }
+
+ // Remove trailing slash.
+ aPureUri = aPureUri.copy( 0, nEnd );
+ }
+
+
+ nEnd = aPureUri.indexOf( '/', nStart );
+ if ( nEnd == -1 )
+ {
+ // root folder.
+
+ OUString aNormPackage = aPureUri.copy( nStart );
+ normalize( aNormPackage );
+
+ aPureUri = aPureUri.replaceAt(
+ nStart, aPureUri.getLength() - nStart, aNormPackage );
+ m_aPackage
+ = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
+ m_aPath = "/";
+ m_aUri = m_aUri.replaceAt( 0,
+ ( nParam >= 0 )
+ ? nParam
+ : m_aUri.getLength(), aPureUri );
+
+ sal_Int32 nLastSlash = m_aPackage.lastIndexOf( '/' );
+ if ( nLastSlash != -1 )
+ m_aName = ::ucb_impl::urihelper::decodeSegment(
+ m_aPackage.copy( nLastSlash + 1 ) );
+ else
+ m_aName
+ = ::ucb_impl::urihelper::decodeSegment( m_aPackage );
+ }
+ else
+ {
+ m_aPath = aPureUri.copy( nEnd + 1 );
+
+ // Unexpected sequences of characters:
+ // - empty path segments
+ // - encoded slashes
+ // - parent folder segments ".."
+ // - current folder segments "."
+ if ( m_aPath.indexOf( "//" ) != -1
+ || m_aPath.indexOf( "%2F" ) != -1
+ || m_aPath.indexOf( "%2f" ) != -1
+ || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, u".." )
+ || ::comphelper::OStorageHelper::PathHasSegment( m_aPath, u"." ) )
+ {
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ return;
+ }
+
+ OUString aNormPackage = aPureUri.copy( nStart, nEnd - nStart );
+ normalize( aNormPackage );
+
+ aPureUri = aPureUri.replaceAt(
+ nStart, nEnd - nStart, aNormPackage );
+ aPureUri = aPureUri.replaceAt(
+ nEnd + 1,
+ aPureUri.getLength() - nEnd - 1,
+ ::ucb_impl::urihelper::encodeURI( m_aPath ) );
+
+ m_aPackage
+ = ::ucb_impl::urihelper::decodeSegment( aNormPackage );
+ m_aPath = ::ucb_impl::urihelper::decodeSegment( m_aPath );
+ m_aUri = m_aUri.replaceAt( 0,
+ ( nParam >= 0 )
+ ? nParam
+ : m_aUri.getLength(), aPureUri );
+
+ sal_Int32 nLastSlash = aPureUri.lastIndexOf( '/' );
+ if ( nLastSlash != -1 )
+ {
+ m_aParentUri = aPureUri.copy( 0, nLastSlash );
+ m_aName = ::ucb_impl::urihelper::decodeSegment(
+ aPureUri.copy( nLastSlash + 1 ) );
+ }
+ }
+
+ // success
+ m_bValid = true;
+ }
+ else
+ {
+ // error, but remember that we did an init().
+ m_aPath = "/";
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */