LibreOffice Module framework (master) 1
urltransformer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
22#include <tools/urlobj.hxx>
23#include <rtl/ustrbuf.hxx>
24
25#include <com/sun/star/util/XURLTransformer.hpp>
26#include <com/sun/star/util/URL.hpp>
27#include <com/sun/star/lang/XServiceInfo.hpp>
28#include <com/sun/star/uno/XComponentContext.hpp>
29
30namespace {
31
32class URLTransformer : public ::cppu::WeakImplHelper< css::util::XURLTransformer, css::lang::XServiceInfo>
33{
34public:
35 URLTransformer() {}
36
37 virtual OUString SAL_CALL getImplementationName() override
38 {
39 return "com.sun.star.comp.framework.URLTransformer";
40 }
41
42 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
43 {
44 return cppu::supportsService(this, ServiceName);
45 }
46
47 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
48 {
49 return {"com.sun.star.util.URLTransformer"};
50 }
51
52 virtual sal_Bool SAL_CALL parseStrict( css::util::URL& aURL ) override;
53
54 virtual sal_Bool SAL_CALL parseSmart( css::util::URL& aURL, const OUString& sSmartProtocol ) override;
55
56 virtual sal_Bool SAL_CALL assemble( css::util::URL& aURL ) override;
57
58 virtual OUString SAL_CALL getPresentation( const css::util::URL& aURL, sal_Bool bWithPassword ) override;
59};
60
61void lcl_ParserHelper(INetURLObject& _rParser, css::util::URL& _rURL)
62{
63 // Get all information about this URL.
64 _rURL.Protocol = INetURLObject::GetScheme( _rParser.GetProtocol() );
66 _rURL.Password = _rParser.GetPass ( INetURLObject::DecodeMechanism::WithCharset );
67 _rURL.Server = _rParser.GetHost ( INetURLObject::DecodeMechanism::WithCharset );
68 _rURL.Port = static_cast<sal_Int16>(_rParser.GetPort());
69
70 sal_Int32 nCount = _rParser.getSegmentCount( false );
71 if ( nCount > 0 )
72 {
73 // Don't add last segment as it is the name!
74 --nCount;
75
76 OUStringBuffer aPath(128);
77 for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
78 {
79 aPath.append( "/"
80 + _rParser.getName( nIndex, false, INetURLObject::DecodeMechanism::NONE ));
81 }
82
83 if ( nCount > 0 )
84 aPath.append( '/' ); // final slash!
85
86 _rURL.Path = aPath.makeStringAndClear();
88 }
89 else
90 {
91 _rURL.Path = _rParser.GetURLPath( INetURLObject::DecodeMechanism::NONE );
92 _rURL.Name = _rParser.GetLastName();
93 }
94
95 _rURL.Arguments = _rParser.GetParam();
97
98 // INetURLObject supports only an intelligent method of parsing URL's. So write
99 // back Complete to have a valid encoded URL in all cases!
100 _rURL.Complete = _rParser.GetMainURL( INetURLObject::DecodeMechanism::NONE );
101
102 _rParser.SetMark( u"" );
103 _rParser.SetParam( u"" );
104
105 _rURL.Main = _rParser.GetMainURL( INetURLObject::DecodeMechanism::NONE );
106}
107
108// XURLTransformer
109sal_Bool SAL_CALL URLTransformer::parseStrict( css::util::URL& aURL )
110{
111 // Safe impossible cases.
112 if ( aURL.Complete.isEmpty() )
113 {
114 return false;
115 }
116 // Try to extract the protocol
117 sal_Int32 nURLIndex = aURL.Complete.indexOf( ':' );
118 if ( nURLIndex <= 1 )
119 return false;
120
121 std::u16string_view aProtocol = aURL.Complete.subView( 0, nURLIndex+1 );
122
123 // If INetURLObject knows this protocol let it parse
124 if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INetProtocol::NotValid )
125 {
126 // Initialize parser with given URL.
127 INetURLObject aParser( aURL.Complete );
128
129 // Get all information about this URL.
130 INetProtocol eINetProt = aParser.GetProtocol();
131 if ( eINetProt == INetProtocol::NotValid )
132 {
133 return false;
134 }
135 else if ( !aParser.HasError() )
136 {
137 lcl_ParserHelper(aParser,aURL);
138 // Return "URL is parsed".
139 return true;
140 }
141 }
142 else
143 {
144 // Minimal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
145 // in framework!
146 aURL.Protocol = aProtocol;
147 aURL.Main = aURL.Complete;
148 aURL.Path = aURL.Complete.copy( nURLIndex+1 );
149
150 // Return "URL is parsed".
151 return true;
152 }
153
154 return false;
155}
156
157// XURLTransformer
158
159sal_Bool SAL_CALL URLTransformer::parseSmart( css::util::URL& aURL,
160 const OUString& sSmartProtocol )
161{
162 // Safe impossible cases.
163 if ( aURL.Complete.isEmpty() )
164 {
165 return false;
166 }
167
168 // Initialize parser with given URL.
169 INetURLObject aParser;
170
171 aParser.SetSmartProtocol( INetURLObject::CompareProtocolScheme( sSmartProtocol ));
172 bool bOk = aParser.SetSmartURL( aURL.Complete );
173 if ( bOk )
174 {
175 lcl_ParserHelper(aParser,aURL);
176 // Return "URL is parsed".
177 return true;
178 }
179 else
180 {
181 // Minimal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
182 // in framework!
183 if ( INetURLObject::CompareProtocolScheme( sSmartProtocol ) == INetProtocol::NotValid )
184 {
185 // Try to extract the protocol
186 sal_Int32 nIndex = aURL.Complete.indexOf( ':' );
187 if ( nIndex > 1 )
188 {
189 OUString aProtocol = aURL.Complete.copy( 0, nIndex+1 );
190
191 // If INetURLObject knows this protocol something is wrong as detected before =>
192 // give up and return false!
193 if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INetProtocol::NotValid )
194 return false;
195 else
196 aURL.Protocol = aProtocol;
197 }
198 else
199 return false;
200
201 aURL.Main = aURL.Complete;
202 aURL.Path = aURL.Complete.copy( nIndex+1 );
203 return true;
204 }
205 else
206 return false;
207 }
208}
209
210// XURLTransformer
211sal_Bool SAL_CALL URLTransformer::assemble( css::util::URL& aURL )
212{
213 // Initialize parser.
214 INetURLObject aParser;
215
216 if ( INetURLObject::CompareProtocolScheme( aURL.Protocol ) != INetProtocol::NotValid )
217 {
218 OUStringBuffer aCompletePath( aURL.Path );
219
220 // Concat the name if it is provided, just support a final slash
221 if ( !aURL.Name.isEmpty() )
222 {
223 sal_Int32 nIndex = aURL.Path.lastIndexOf( '/' );
224 if ( nIndex == ( aURL.Path.getLength() -1 ))
225 aCompletePath.append( aURL.Name );
226 else
227 {
228 aCompletePath.append( "/" + aURL.Name );
229 }
230 }
231
232 bool bResult = aParser.ConcatData(
234 aURL.User ,
235 aURL.Password ,
236 aURL.Server ,
237 aURL.Port ,
238 aCompletePath);
239
240 if ( !bResult )
241 return false;
242
243 // First parse URL WITHOUT ...
245 // ...and then WITH parameter and mark.
246 aParser.SetParam( aURL.Arguments);
249
250 // Return "URL is assembled".
251 return true;
252 }
253 else if ( !aURL.Protocol.isEmpty() )
254 {
255 // Minimal support for unknown protocols
256 aURL.Complete = aURL.Protocol + aURL.Path;
257 aURL.Main = aURL.Complete;
258 return true;
259 }
260
261 return false;
262}
263
264// XURLTransformer
265
266OUString SAL_CALL URLTransformer::getPresentation( const css::util::URL& aURL,
267 sal_Bool bWithPassword )
268{
269 // Safe impossible cases.
270 if ( aURL.Complete.isEmpty() )
271 {
272 return OUString();
273 }
274
275 // Check given URL
276 css::util::URL aTestURL = aURL;
277 bool bParseResult = parseSmart( aTestURL, aTestURL.Protocol );
278 if ( bParseResult )
279 {
280 if ( !bWithPassword && !aTestURL.Password.isEmpty() )
281 {
282 // Exchange password text with other placeholder string
283 aTestURL.Password = "<******>";
284 assemble( aTestURL );
285 }
286
287 // Convert internal URLs to "praesentation"-URLs!
288 OUString sPraesentationURL;
290
291 return sPraesentationURL;
292 }
293 else
294 return OUString();
295}
296
297}
298
299extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
301 css::uno::XComponentContext *,
302 css::uno::Sequence<css::uno::Any> const &)
303{
304 return cppu::acquire(new URLTransformer());
305}
306
307/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString getName(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
void SetSmartProtocol(INetProtocol eTheSmartScheme)
sal_uInt32 GetPort() const
static OUString GetScheme(INetProtocol eTheScheme)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static bool translateToExternal(std::u16string_view rTheIntURIRef, OUString &rTheExtURIRef, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString GetMark(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetPass(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool SetSmartURL(std::u16string_view rTheAbsURIRef, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
OUString GetLastName(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool ConcatData(INetProtocol eTheScheme, std::u16string_view rTheUser, std::u16string_view rThePassword, std::u16string_view rTheHost, sal_uInt32 nThePort, std::u16string_view rThePath)
static INetProtocol CompareProtocolScheme(std::u16string_view aTheAbsURIRef)
OUString GetUser(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
sal_Int32 getSegmentCount(bool bIgnoreFinalSlash=true) const
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetParam(rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetHost(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
INetProtocol GetProtocol() const
bool SetMark(std::u16string_view rTheFragment, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
bool SetParam(std::u16string_view rTheQuery, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
int nCount
URL aURL
sal_Int32 nIndex
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
unsigned char sal_Bool
INetProtocol
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_framework_URLTransformer_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)