office-gobmx/ucb/source/ucp/package/pkguri.cxx
Noel Grandin b24a4d255d use more string_view
found by tweaking the loplugin:stringview and making it whitelist
getLength

Change-Id: Ic15d3703d1fb07658e99e1db1c89e2fa5bc70c19
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132771
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-04-10 20:15:16 +02:00

234 lines
7.2 KiB
C++

/* -*- 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: */