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