diff options
Diffstat (limited to 'framework/source/services/urltransformer.cxx')
-rw-r--r-- | framework/source/services/urltransformer.cxx | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/framework/source/services/urltransformer.cxx b/framework/source/services/urltransformer.cxx new file mode 100644 index 000000000..b4fd3de16 --- /dev/null +++ b/framework/source/services/urltransformer.cxx @@ -0,0 +1,310 @@ +/* -*- 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 . + */ + +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +namespace { + +class URLTransformer : public ::cppu::WeakImplHelper< css::util::XURLTransformer, css::lang::XServiceInfo> +{ +public: + URLTransformer() {} + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.framework.URLTransformer"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return {"com.sun.star.util.URLTransformer"}; + } + + virtual sal_Bool SAL_CALL parseStrict( css::util::URL& aURL ) override; + + virtual sal_Bool SAL_CALL parseSmart( css::util::URL& aURL, const OUString& sSmartProtocol ) override; + + virtual sal_Bool SAL_CALL assemble( css::util::URL& aURL ) override; + + virtual OUString SAL_CALL getPresentation( const css::util::URL& aURL, sal_Bool bWithPassword ) override; +}; + +void lcl_ParserHelper(INetURLObject& _rParser, css::util::URL& _rURL,bool _bUseIntern) +{ + // Get all information about this URL. + _rURL.Protocol = INetURLObject::GetScheme( _rParser.GetProtocol() ); + _rURL.User = _rParser.GetUser ( INetURLObject::DecodeMechanism::WithCharset ); + _rURL.Password = _rParser.GetPass ( INetURLObject::DecodeMechanism::WithCharset ); + _rURL.Server = _rParser.GetHost ( INetURLObject::DecodeMechanism::WithCharset ); + _rURL.Port = static_cast<sal_Int16>(_rParser.GetPort()); + + sal_Int32 nCount = _rParser.getSegmentCount( false ); + if ( nCount > 0 ) + { + // Don't add last segment as it is the name! + --nCount; + + OUStringBuffer aPath(128); + for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + aPath.append( '/'); + aPath.append( _rParser.getName( nIndex, false, INetURLObject::DecodeMechanism::NONE )); + } + + if ( nCount > 0 ) + aPath.append( '/' ); // final slash! + + _rURL.Path = aPath.makeStringAndClear(); + _rURL.Name = _rParser.getName( INetURLObject::LAST_SEGMENT, false, INetURLObject::DecodeMechanism::NONE ); + } + else + { + _rURL.Path = _rParser.GetURLPath( INetURLObject::DecodeMechanism::NONE ); + _rURL.Name = _rParser.GetLastName(); + } + + _rURL.Arguments = _rParser.GetParam(); + _rURL.Mark = _rParser.GetMark( INetURLObject::DecodeMechanism::WithCharset ); + + // INetURLObject supports only an intelligent method of parsing URL's. So write + // back Complete to have a valid encoded URL in all cases! + _rURL.Complete = _rParser.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + if ( _bUseIntern ) + _rURL.Complete = _rURL.Complete.intern(); + + _rParser.SetMark( u"" ); + _rParser.SetParam( u"" ); + + _rURL.Main = _rParser.GetMainURL( INetURLObject::DecodeMechanism::NONE ); +} + +// XURLTransformer +sal_Bool SAL_CALL URLTransformer::parseStrict( css::util::URL& aURL ) +{ + // Safe impossible cases. + if ( aURL.Complete.isEmpty() ) + { + return false; + } + // Try to extract the protocol + sal_Int32 nURLIndex = aURL.Complete.indexOf( ':' ); + if ( nURLIndex <= 1 ) + return false; + + std::u16string_view aProtocol = aURL.Complete.subView( 0, nURLIndex+1 ); + + // If INetURLObject knows this protocol let it parse + if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INetProtocol::NotValid ) + { + // Initialize parser with given URL. + INetURLObject aParser( aURL.Complete ); + + // Get all information about this URL. + INetProtocol eINetProt = aParser.GetProtocol(); + if ( eINetProt == INetProtocol::NotValid ) + { + return false; + } + else if ( !aParser.HasError() ) + { + lcl_ParserHelper(aParser,aURL,false); + // Return "URL is parsed". + return true; + } + } + else + { + // Minimal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented + // in framework! + aURL.Protocol = aProtocol; + aURL.Main = aURL.Complete; + aURL.Path = aURL.Complete.copy( nURLIndex+1 ); + + // Return "URL is parsed". + return true; + } + + return false; +} + +// XURLTransformer + +sal_Bool SAL_CALL URLTransformer::parseSmart( css::util::URL& aURL, + const OUString& sSmartProtocol ) +{ + // Safe impossible cases. + if ( aURL.Complete.isEmpty() ) + { + return false; + } + + // Initialize parser with given URL. + INetURLObject aParser; + + aParser.SetSmartProtocol( INetURLObject::CompareProtocolScheme( sSmartProtocol )); + bool bOk = aParser.SetSmartURL( aURL.Complete ); + if ( bOk ) + { + lcl_ParserHelper(aParser,aURL,true); + // Return "URL is parsed". + return true; + } + else + { + // Minimal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented + // in framework! + if ( INetURLObject::CompareProtocolScheme( sSmartProtocol ) == INetProtocol::NotValid ) + { + // Try to extract the protocol + sal_Int32 nIndex = aURL.Complete.indexOf( ':' ); + if ( nIndex > 1 ) + { + OUString aProtocol = aURL.Complete.copy( 0, nIndex+1 ); + + // If INetURLObject knows this protocol something is wrong as detected before => + // give up and return false! + if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INetProtocol::NotValid ) + return false; + else + aURL.Protocol = aProtocol; + } + else + return false; + + aURL.Main = aURL.Complete; + aURL.Path = aURL.Complete.copy( nIndex+1 ); + return true; + } + else + return false; + } +} + +// XURLTransformer +sal_Bool SAL_CALL URLTransformer::assemble( css::util::URL& aURL ) +{ + // Initialize parser. + INetURLObject aParser; + + if ( INetURLObject::CompareProtocolScheme( aURL.Protocol ) != INetProtocol::NotValid ) + { + OUStringBuffer aCompletePath( aURL.Path ); + + // Concat the name if it is provided, just support a final slash + if ( !aURL.Name.isEmpty() ) + { + sal_Int32 nIndex = aURL.Path.lastIndexOf( '/' ); + if ( nIndex == ( aURL.Path.getLength() -1 )) + aCompletePath.append( aURL.Name ); + else + { + aCompletePath.append( '/' ); + aCompletePath.append( aURL.Name ); + } + } + + bool bResult = aParser.ConcatData( + INetURLObject::CompareProtocolScheme( aURL.Protocol ) , + aURL.User , + aURL.Password , + aURL.Server , + aURL.Port , + aCompletePath.makeStringAndClear() ); + + if ( !bResult ) + return false; + + // First parse URL WITHOUT ... + aURL.Main = aParser.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + // ...and then WITH parameter and mark. + aParser.SetParam( aURL.Arguments); + aParser.SetMark ( aURL.Mark, INetURLObject::EncodeMechanism::All ); + aURL.Complete = aParser.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + + // Return "URL is assembled". + return true; + } + else if ( !aURL.Protocol.isEmpty() ) + { + // Minimal support for unknown protocols + aURL.Complete = aURL.Protocol + aURL.Path; + aURL.Main = aURL.Complete; + return true; + } + + return false; +} + +// XURLTransformer + +OUString SAL_CALL URLTransformer::getPresentation( const css::util::URL& aURL, + sal_Bool bWithPassword ) +{ + // Safe impossible cases. + if ( aURL.Complete.isEmpty() ) + { + return OUString(); + } + + // Check given URL + css::util::URL aTestURL = aURL; + bool bParseResult = parseSmart( aTestURL, aTestURL.Protocol ); + if ( bParseResult ) + { + if ( !bWithPassword && !aTestURL.Password.isEmpty() ) + { + // Exchange password text with other placeholder string + aTestURL.Password = "<******>"; + assemble( aTestURL ); + } + + // Convert internal URLs to "praesentation"-URLs! + OUString sPraesentationURL; + INetURLObject::translateToExternal( aTestURL.Complete, sPraesentationURL, INetURLObject::DecodeMechanism::Unambiguous ); + + return sPraesentationURL; + } + else + return OUString(); +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_URLTransformer_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new URLTransformer()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |