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