xref: /trunk/main/framework/source/services/urltransformer.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //  my own includes
33 //_________________________________________________________________________________________________________________
34 #include <services/urltransformer.hxx>
35 #include <threadhelp/resetableguard.hxx>
36 #include <macros/debug.hxx>
37 #include <services.h>
38 
39 //_________________________________________________________________________________________________________________
40 //  interface includes
41 //_________________________________________________________________________________________________________________
42 
43 //_________________________________________________________________________________________________________________
44 //  includes of other projects
45 //_________________________________________________________________________________________________________________
46 #include <tools/urlobj.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <vcl/svapp.hxx>
49 
50 //_________________________________________________________________________________________________________________
51 //  namespace
52 //_________________________________________________________________________________________________________________
53 
54 namespace framework{
55 
56 using namespace ::osl                           ;
57 using namespace ::cppu                          ;
58 using namespace ::com::sun::star::uno           ;
59 using namespace ::com::sun::star::lang          ;
60 using namespace ::com::sun::star::util          ;
61 
62 //_________________________________________________________________________________________________________________
63 //  non exported const
64 //_________________________________________________________________________________________________________________
65 
66 //_________________________________________________________________________________________________________________
67 //  non exported definitions
68 //_________________________________________________________________________________________________________________
69 
70 //_________________________________________________________________________________________________________________
71 //  declarations
72 //_________________________________________________________________________________________________________________
73 
74 //*****************************************************************************************************************
75 //  constructor
76 //*****************************************************************************************************************
77 URLTransformer::URLTransformer( const Reference< XMultiServiceFactory >& /*xFactory*/ )
78 {
79     // Safe impossible cases.
80     // Method not defined for all incoming parameter.
81     //LOG_ASSERT( xFactory.is(), "URLTransformer::URLTransformer()\nInvalid parameter detected!\n" )
82 }
83 
84 //*****************************************************************************************************************
85 //  destructor
86 //*****************************************************************************************************************
87 URLTransformer::~URLTransformer()
88 {
89 }
90 
91 //*****************************************************************************************************************
92 //  XInterface, XTypeProvider, XServiceInfo
93 //*****************************************************************************************************************
94 
95 DEFINE_XSERVICEINFO_MULTISERVICE    (   URLTransformer                      ,
96                                         OWeakObject                         ,
97                                         SERVICENAME_URLTRANSFORMER          ,
98                                         IMPLEMENTATIONNAME_URLTRANSFORMER
99                                     )
100 
101 DEFINE_INIT_SERVICE                 (   URLTransformer,
102                                         {
103                                         }
104                                     )
105 
106 namespace
107 {
108     void lcl_ParserHelper(INetURLObject& _rParser,URL& _rURL,bool _bUseIntern)
109     {
110         // Get all information about this URL.
111         _rURL.Protocol  = INetURLObject::GetScheme( _rParser.GetProtocol() );
112         _rURL.User      = _rParser.GetUser  ( INetURLObject::DECODE_WITH_CHARSET );
113         _rURL.Password  = _rParser.GetPass  ( INetURLObject::DECODE_WITH_CHARSET );
114         _rURL.Server        = _rParser.GetHost  ( INetURLObject::DECODE_WITH_CHARSET );
115         _rURL.Port      = (sal_Int16)_rParser.GetPort();
116 
117         sal_Int32 nCount = _rParser.getSegmentCount( false );
118         if ( nCount > 0 )
119         {
120             // Don't add last segment as it is the name!
121             --nCount;
122 
123             rtl::OUStringBuffer aPath;
124             for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
125             {
126                 aPath.append( sal_Unicode( '/' ));
127                 aPath.append( _rParser.getName( nIndex, false, INetURLObject::NO_DECODE ));
128             }
129 
130             if ( nCount > 0 )
131                 aPath.append( sal_Unicode( '/' )); // final slash!
132 
133             _rURL.Path = aPath.makeStringAndClear();
134             _rURL.Name = _rParser.getName( INetURLObject::LAST_SEGMENT, false, INetURLObject::NO_DECODE );
135         }
136         else
137         {
138             _rURL.Path       = _rParser.GetURLPath( INetURLObject::NO_DECODE           );
139             _rURL.Name      = _rParser.GetName  (                                    );
140         }
141 
142         _rURL.Arguments  = _rParser.GetParam  ( INetURLObject::NO_DECODE           );
143         _rURL.Mark      = _rParser.GetMark  ( INetURLObject::DECODE_WITH_CHARSET );
144 
145         // INetURLObject supports only an intelligent method of parsing URL's. So write
146         // back Complete to have a valid encoded URL in all cases!
147         _rURL.Complete  = _rParser.GetMainURL( INetURLObject::NO_DECODE           );
148         if ( _bUseIntern )
149             _rURL.Complete   = _rURL.Complete.intern();
150 
151         _rParser.SetMark    ( ::rtl::OUString() );
152         _rParser.SetParam( ::rtl::OUString() );
153 
154         _rURL.Main       = _rParser.GetMainURL( INetURLObject::NO_DECODE           );
155     }
156 }
157 //*****************************************************************************************************************
158 //  XURLTransformer
159 //*****************************************************************************************************************
160 sal_Bool SAL_CALL URLTransformer::parseStrict( URL& aURL ) throw( RuntimeException )
161 {
162     // Safe impossible cases.
163     if  (( &aURL                        ==  NULL    )   ||
164          ( aURL.Complete.getLength()    <   1       )       )
165     {
166         return sal_False;
167     }
168     // Try to extract the protocol
169     sal_Int32 nURLIndex = aURL.Complete.indexOf( sal_Unicode( ':' ));
170     ::rtl::OUString aProtocol;
171     if ( nURLIndex > 1 )
172     {
173         aProtocol = aURL.Complete.copy( 0, nURLIndex+1 );
174 
175         // If INetURLObject knows this protocol let it parse
176         if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
177         {
178             // Initialize parser with given URL.
179             INetURLObject aParser( aURL.Complete );
180 
181             // Get all information about this URL.
182             INetProtocol eINetProt = aParser.GetProtocol();
183             if ( eINetProt == INET_PROT_NOT_VALID )
184             {
185                 return sal_False;
186             }
187             else if ( !aParser.HasError() )
188             {
189                 lcl_ParserHelper(aParser,aURL,false);
190                 // Return "URL is parsed".
191                 return sal_True;
192             }
193         }
194         else
195         {
196             // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
197             // in framework!
198             aURL.Protocol   = aProtocol;
199             aURL.Main       = aURL.Complete;
200             aURL.Path       = aURL.Complete.copy( nURLIndex+1 );;
201 
202             // Return "URL is parsed".
203             return sal_True;
204         }
205     }
206 
207     return sal_False;
208 }
209 
210 //*****************************************************************************************************************
211 //  XURLTransformer
212 //*****************************************************************************************************************
213 sal_Bool SAL_CALL URLTransformer::parseSmart(           URL&        aURL            ,
214                                                 const   ::rtl::OUString&    sSmartProtocol  ) throw( RuntimeException )
215 {
216     // Safe impossible cases.
217     if  (( &aURL                            ==  NULL    ) ||
218          ( aURL.Complete.getLength()        <   1       )    )
219     {
220         return sal_False;
221     }
222 
223     // Initialize parser with given URL.
224     INetURLObject aParser;
225 
226     aParser.SetSmartProtocol( INetURLObject::CompareProtocolScheme( sSmartProtocol ));
227     bool bOk = aParser.SetSmartURL( aURL.Complete );
228     if ( bOk )
229     {
230         lcl_ParserHelper(aParser,aURL,true);
231         // Return "URL is parsed".
232         return sal_True;
233     }
234     else
235     {
236         // Minmal support for unknown protocols. This is mandatory to support the "Protocol Handlers" implemented
237         // in framework!
238         if ( INetURLObject::CompareProtocolScheme( sSmartProtocol ) == INET_PROT_NOT_VALID )
239         {
240             // Try to extract the protocol
241             sal_Int32 nIndex = aURL.Complete.indexOf( sal_Unicode( ':' ));
242             ::rtl::OUString aProtocol;
243             if ( nIndex > 1 )
244             {
245                 aProtocol = aURL.Complete.copy( 0, nIndex+1 );
246 
247                 // If INetURLObject knows this protocol something is wrong as detected before =>
248                 // give up and return false!
249                 if ( INetURLObject::CompareProtocolScheme( aProtocol ) != INET_PROT_NOT_VALID )
250                     return sal_False;
251                 else
252                     aURL.Protocol = aProtocol;
253             }
254             else
255                 return sal_False;
256 
257             aURL.Main = aURL.Complete;
258             aURL.Path = aURL.Complete.copy( nIndex+1 );
259             return sal_True;
260         }
261         else
262             return sal_False;
263     }
264 }
265 
266 //*****************************************************************************************************************
267 //  XURLTransformer
268 //*****************************************************************************************************************
269 sal_Bool SAL_CALL URLTransformer::assemble( URL& aURL ) throw( RuntimeException )
270 {
271     // Safe impossible cases.
272     if  ( &aURL == NULL )
273         return sal_False ;
274 
275     // Initialize parser.
276     INetURLObject aParser;
277 
278     if ( INetURLObject::CompareProtocolScheme( aURL.Protocol ) != INET_PROT_NOT_VALID )
279     {
280         ::rtl::OUStringBuffer aCompletePath( aURL.Path );
281 
282         // Concat the name if it is provided, just support a final slash
283         if ( aURL.Name.getLength() > 0 )
284         {
285             sal_Int32 nIndex = aURL.Path.lastIndexOf( sal_Unicode('/') );
286             if ( nIndex == ( aURL.Path.getLength() -1 ))
287                 aCompletePath.append( aURL.Name );
288             else
289             {
290                 aCompletePath.append( sal_Unicode( '/' ) );
291                 aCompletePath.append( aURL.Name );
292             }
293         }
294 
295         bool bResult = aParser.ConcatData(
296                             INetURLObject::CompareProtocolScheme( aURL.Protocol )   ,
297                             aURL.User                                               ,
298                             aURL.Password                                           ,
299                             aURL.Server                                             ,
300                             aURL.Port                                               ,
301                             aCompletePath.makeStringAndClear()                          );
302 
303         if ( !bResult )
304             return sal_False;
305 
306         // First parse URL WITHOUT ...
307         aURL.Main = aParser.GetMainURL( INetURLObject::NO_DECODE );
308         // ...and then WITH parameter and mark.
309         aParser.SetParam( aURL.Arguments);
310         aParser.SetMark ( aURL.Mark, INetURLObject::ENCODE_ALL );
311         aURL.Complete = aParser.GetMainURL( INetURLObject::NO_DECODE );
312 
313         // Return "URL is assembled".
314         return sal_True;
315     }
316     else if ( aURL.Protocol.getLength() > 0 )
317     {
318         // Minimal support for unknown protocols
319         ::rtl::OUStringBuffer aBuffer( aURL.Protocol );
320         aBuffer.append( aURL.Path );
321         aURL.Complete   = aBuffer.makeStringAndClear();
322         aURL.Main       = aURL.Complete;
323         return sal_True;
324     }
325 
326     return sal_False;
327 }
328 
329 //*****************************************************************************************************************
330 //  XURLTransformer
331 //*****************************************************************************************************************
332 ::rtl::OUString SAL_CALL URLTransformer::getPresentation(   const   URL&        aURL            ,
333                                                             sal_Bool    bWithPassword   ) throw( RuntimeException )
334 {
335     // Safe impossible cases.
336     if  (( &aURL                        ==  NULL        )   ||
337          ( aURL.Complete.getLength()    <   1           )   ||
338             (( bWithPassword            !=  sal_True    )   &&
339              ( bWithPassword            !=  sal_False   )       ) )
340     {
341         return ::rtl::OUString();
342     }
343 
344     // Check given URL
345     URL aTestURL = aURL;
346     sal_Bool bParseResult = parseSmart( aTestURL, aTestURL.Protocol );
347     if ( bParseResult )
348     {
349         if ( !bWithPassword && aTestURL.Password.getLength() > 0 )
350         {
351             // Exchange password text with other placeholder string
352             aTestURL.Password = ::rtl::OUString::createFromAscii( "<******>" );
353             assemble( aTestURL );
354         }
355 
356         // Convert internal URLs to "praesentation"-URLs!
357         rtl::OUString sPraesentationURL;
358         INetURLObject::translateToExternal( aTestURL.Complete, sPraesentationURL, INetURLObject::DECODE_UNAMBIGUOUS );
359 
360         return sPraesentationURL;
361     }
362     else
363         return ::rtl::OUString();
364 }
365 
366 //_________________________________________________________________________________________________________________
367 //  debug methods
368 //_________________________________________________________________________________________________________________
369 
370 
371 }       //  namespace framework
372 
373