Line data Source code
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 :
20 : #include <services.h>
21 :
22 : #include <cppuhelper/implbase2.hxx>
23 : #include <cppuhelper/supportsservice.hxx>
24 : #include <tools/urlobj.hxx>
25 : #include <rtl/ref.hxx>
26 : #include <rtl/ustrbuf.hxx>
27 :
28 : #include <com/sun/star/util/XURLTransformer.hpp>
29 : #include <com/sun/star/util/URL.hpp>
30 : #include <com/sun/star/lang/XServiceInfo.hpp>
31 : #include <com/sun/star/uno/XComponentContext.hpp>
32 :
33 : namespace {
34 :
35 : class URLTransformer : public ::cppu::WeakImplHelper2< css::util::XURLTransformer, css::lang::XServiceInfo>
36 : {
37 : public:
38 0 : URLTransformer() {}
39 :
40 0 : virtual ~URLTransformer() {}
41 :
42 0 : virtual OUString SAL_CALL getImplementationName()
43 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
44 : {
45 0 : return OUString("com.sun.star.comp.framework.URLTransformer");
46 : }
47 :
48 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
49 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
50 : {
51 0 : return cppu::supportsService(this, ServiceName);
52 : }
53 :
54 0 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
55 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
56 : {
57 0 : css::uno::Sequence< OUString > aRet(1);
58 0 : aRet[0] = "com.sun.star.util.URLTransformer";
59 0 : return aRet;
60 : }
61 :
62 : virtual sal_Bool SAL_CALL parseStrict( css::util::URL& aURL )
63 : throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
64 :
65 : virtual sal_Bool SAL_CALL parseSmart( css::util::URL& aURL, const OUString& sSmartProtocol )
66 : throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
67 :
68 : virtual sal_Bool SAL_CALL assemble( css::util::URL& aURL )
69 : throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
70 :
71 : virtual OUString SAL_CALL getPresentation( const css::util::URL& aURL, sal_Bool bWithPassword )
72 : throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
73 : };
74 :
75 : namespace
76 : {
77 0 : void lcl_ParserHelper(INetURLObject& _rParser, css::util::URL& _rURL,bool _bUseIntern)
78 : {
79 : // Get all information about this URL.
80 0 : _rURL.Protocol = INetURLObject::GetScheme( _rParser.GetProtocol() );
81 0 : _rURL.User = _rParser.GetUser ( INetURLObject::DECODE_WITH_CHARSET );
82 0 : _rURL.Password = _rParser.GetPass ( INetURLObject::DECODE_WITH_CHARSET );
83 0 : _rURL.Server = _rParser.GetHost ( INetURLObject::DECODE_WITH_CHARSET );
84 0 : _rURL.Port = (sal_Int16)_rParser.GetPort();
85 :
86 0 : sal_Int32 nCount = _rParser.getSegmentCount( false );
87 0 : if ( nCount > 0 )
88 : {
89 : // Don't add last segment as it is the name!
90 0 : --nCount;
91 :
92 0 : OUStringBuffer aPath;
93 0 : for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
94 : {
95 0 : aPath.append( '/');
96 0 : aPath.append( _rParser.getName( nIndex, false, INetURLObject::NO_DECODE ));
97 : }
98 :
99 0 : if ( nCount > 0 )
100 0 : aPath.append( '/' ); // final slash!
101 :
102 0 : _rURL.Path = aPath.makeStringAndClear();
103 0 : _rURL.Name = _rParser.getName( INetURLObject::LAST_SEGMENT, false, INetURLObject::NO_DECODE );
104 : }
105 : else
106 : {
107 0 : _rURL.Path = _rParser.GetURLPath( INetURLObject::NO_DECODE );
108 0 : _rURL.Name = _rParser.GetName ( );
109 : }
110 :
111 0 : _rURL.Arguments = _rParser.GetParam ( INetURLObject::NO_DECODE );
112 0 : _rURL.Mark = _rParser.GetMark ( INetURLObject::DECODE_WITH_CHARSET );
113 :
114 : // INetURLObject supports only an intelligent method of parsing URL's. So write
115 : // back Complete to have a valid encoded URL in all cases!
116 0 : _rURL.Complete = _rParser.GetMainURL( INetURLObject::NO_DECODE );
117 0 : if ( _bUseIntern )
118 0 : _rURL.Complete = _rURL.Complete.intern();
119 :
120 0 : _rParser.SetMark ( OUString() );
121 0 : _rParser.SetParam( OUString() );
122 :
123 0 : _rURL.Main = _rParser.GetMainURL( INetURLObject::NO_DECODE );
124 0 : }
125 : }
126 :
127 : // XURLTransformer
128 0 : sal_Bool SAL_CALL URLTransformer::parseStrict( css::util::URL& aURL ) throw( css::uno::RuntimeException, std::exception )
129 : {
130 : // Safe impossible cases.
131 0 : if (( &aURL == NULL ) ||
132 0 : ( aURL.Complete.isEmpty() ) )
133 : {
134 0 : return sal_False;
135 : }
136 : // Try to extract the protocol
137 0 : sal_Int32 nURLIndex = aURL.Complete.indexOf( ':' );
138 0 : OUString aProtocol;
139 0 : if ( nURLIndex > 1 )
140 : {
141 0 : aProtocol = aURL.Complete.copy( 0, nURLIndex+1 );
142 :
143 : // If INetURLObject knows this protocol let it parse
144 0 : if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
145 : {
146 : // Initialize parser with given URL.
147 0 : INetURLObject aParser( aURL.Complete );
148 :
149 : // Get all information about this URL.
150 0 : INetProtocol eINetProt = aParser.GetProtocol();
151 0 : if ( eINetProt == INET_PROT_NOT_VALID )
152 : {
153 0 : return sal_False;
154 : }
155 0 : else if ( !aParser.HasError() )
156 : {
157 0 : lcl_ParserHelper(aParser,aURL,false);
158 : // Return "URL is parsed".
159 0 : return sal_True;
160 0 : }
161 : }
162 : else
163 : {
164 : // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
165 : // in framework!
166 0 : aURL.Protocol = aProtocol;
167 0 : aURL.Main = aURL.Complete;
168 0 : aURL.Path = aURL.Complete.copy( nURLIndex+1 );;
169 :
170 : // Return "URL is parsed".
171 0 : return sal_True;
172 : }
173 : }
174 :
175 0 : return sal_False;
176 : }
177 :
178 : // XURLTransformer
179 :
180 0 : sal_Bool SAL_CALL URLTransformer::parseSmart( css::util::URL& aURL,
181 : const OUString& sSmartProtocol ) throw( css::uno::RuntimeException, std::exception )
182 : {
183 : // Safe impossible cases.
184 0 : if (( &aURL == NULL ) ||
185 0 : ( aURL.Complete.isEmpty() ) )
186 : {
187 0 : return sal_False;
188 : }
189 :
190 : // Initialize parser with given URL.
191 0 : INetURLObject aParser;
192 :
193 0 : aParser.SetSmartProtocol( INetURLObject::CompareProtocolScheme( sSmartProtocol ));
194 0 : bool bOk = aParser.SetSmartURL( aURL.Complete );
195 0 : if ( bOk )
196 : {
197 0 : lcl_ParserHelper(aParser,aURL,true);
198 : // Return "URL is parsed".
199 0 : return sal_True;
200 : }
201 : else
202 : {
203 : // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
204 : // in framework!
205 0 : if ( INetURLObject::CompareProtocolScheme( sSmartProtocol ) == INET_PROT_NOT_VALID )
206 : {
207 : // Try to extract the protocol
208 0 : sal_Int32 nIndex = aURL.Complete.indexOf( ':' );
209 0 : OUString aProtocol;
210 0 : if ( nIndex > 1 )
211 : {
212 0 : aProtocol = aURL.Complete.copy( 0, nIndex+1 );
213 :
214 : // If INetURLObject knows this protocol something is wrong as detected before =>
215 : // give up and return false!
216 0 : if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
217 0 : return sal_False;
218 : else
219 0 : aURL.Protocol = aProtocol;
220 : }
221 : else
222 0 : return sal_False;
223 :
224 0 : aURL.Main = aURL.Complete;
225 0 : aURL.Path = aURL.Complete.copy( nIndex+1 );
226 0 : return sal_True;
227 : }
228 : else
229 0 : return sal_False;
230 0 : }
231 : }
232 :
233 : // XURLTransformer
234 0 : sal_Bool SAL_CALL URLTransformer::assemble( css::util::URL& aURL ) throw( css::uno::RuntimeException, std::exception )
235 : {
236 : // Safe impossible cases.
237 0 : if ( &aURL == NULL )
238 0 : return sal_False;
239 :
240 : // Initialize parser.
241 0 : INetURLObject aParser;
242 :
243 0 : if ( INetURLObject::CompareProtocolScheme( aURL.Protocol ) != INET_PROT_NOT_VALID )
244 : {
245 0 : OUStringBuffer aCompletePath( aURL.Path );
246 :
247 : // Concat the name if it is provided, just support a final slash
248 0 : if ( !aURL.Name.isEmpty() )
249 : {
250 0 : sal_Int32 nIndex = aURL.Path.lastIndexOf( '/' );
251 0 : if ( nIndex == ( aURL.Path.getLength() -1 ))
252 0 : aCompletePath.append( aURL.Name );
253 : else
254 : {
255 0 : aCompletePath.append( '/' );
256 0 : aCompletePath.append( aURL.Name );
257 : }
258 : }
259 :
260 : bool bResult = aParser.ConcatData(
261 : INetURLObject::CompareProtocolScheme( aURL.Protocol ) ,
262 : aURL.User ,
263 : aURL.Password ,
264 : aURL.Server ,
265 : aURL.Port ,
266 0 : aCompletePath.makeStringAndClear() );
267 :
268 0 : if ( !bResult )
269 0 : return sal_False;
270 :
271 : // First parse URL WITHOUT ...
272 0 : aURL.Main = aParser.GetMainURL( INetURLObject::NO_DECODE );
273 : // ...and then WITH parameter and mark.
274 0 : aParser.SetParam( aURL.Arguments);
275 0 : aParser.SetMark ( aURL.Mark, INetURLObject::ENCODE_ALL );
276 0 : aURL.Complete = aParser.GetMainURL( INetURLObject::NO_DECODE );
277 :
278 : // Return "URL is assembled".
279 0 : return sal_True;
280 : }
281 0 : else if ( !aURL.Protocol.isEmpty() )
282 : {
283 : // Minimal support for unknown protocols
284 0 : OUStringBuffer aBuffer( aURL.Protocol );
285 0 : aBuffer.append( aURL.Path );
286 0 : aURL.Complete = aBuffer.makeStringAndClear();
287 0 : aURL.Main = aURL.Complete;
288 0 : return sal_True;
289 : }
290 :
291 0 : return sal_False;
292 : }
293 :
294 : // XURLTransformer
295 :
296 0 : OUString SAL_CALL URLTransformer::getPresentation( const css::util::URL& aURL,
297 : sal_Bool bWithPassword ) throw( css::uno::RuntimeException, std::exception )
298 : {
299 : // Safe impossible cases.
300 0 : if (( &aURL == NULL ) ||
301 0 : ( aURL.Complete.isEmpty() ) ||
302 0 : (( bWithPassword != sal_True ) &&
303 : ( bWithPassword != sal_False ) ) )
304 : {
305 0 : return OUString();
306 : }
307 :
308 : // Check given URL
309 0 : css::util::URL aTestURL = aURL;
310 0 : bool bParseResult = parseSmart( aTestURL, aTestURL.Protocol );
311 0 : if ( bParseResult )
312 : {
313 0 : if ( !bWithPassword && !aTestURL.Password.isEmpty() )
314 : {
315 : // Exchange password text with other placeholder string
316 0 : aTestURL.Password = "<******>";
317 0 : assemble( aTestURL );
318 : }
319 :
320 : // Convert internal URLs to "praesentation"-URLs!
321 0 : OUString sPraesentationURL;
322 0 : INetURLObject::translateToExternal( aTestURL.Complete, sPraesentationURL, INetURLObject::DECODE_UNAMBIGUOUS );
323 :
324 0 : return sPraesentationURL;
325 : }
326 : else
327 0 : return OUString();
328 : }
329 :
330 : }
331 :
332 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
333 0 : com_sun_star_comp_framework_URLTransformer_get_implementation(
334 : css::uno::XComponentContext *,
335 : css::uno::Sequence<css::uno::Any> const &)
336 : {
337 0 : return cppu::acquire(new URLTransformer());
338 : }
339 :
340 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|