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_unotools.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	includes
33 //_________________________________________________________________________________________________________________
34 
35 #include <unotools/extendedsecurityoptions.hxx>
36 #include <unotools/configmgr.hxx>
37 #include <unotools/configitem.hxx>
38 #include <tools/debug.hxx>
39 #include <com/sun/star/uno/Any.hxx>
40 #include <com/sun/star/uno/Sequence.hxx>
41 #include <tools/urlobj.hxx>
42 #include <tools/wldcrd.hxx>
43 #include <rtl/ustrbuf.hxx>
44 
45 #include <unotools/pathoptions.hxx>
46 
47 #include <hash_map>
48 
49 #include <rtl/logfile.hxx>
50 #include "itemholder1.hxx"
51 
52 //_________________________________________________________________________________________________________________
53 //	namespaces
54 //_________________________________________________________________________________________________________________
55 
56 using namespace ::utl					;
57 using namespace ::rtl					;
58 using namespace ::osl					;
59 using namespace ::com::sun::star::uno	;
60 
61 //_________________________________________________________________________________________________________________
62 //	const
63 //_________________________________________________________________________________________________________________
64 
65 #define	ROOTNODE_SECURITY				OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Security"))
66 
67 #define SECURE_EXTENSIONS_SET			OUString(RTL_CONSTASCII_USTRINGPARAM("SecureExtensions"))
68 #define EXTENSION_PROPNAME				OUString(RTL_CONSTASCII_USTRINGPARAM("/Extension"))
69 
70 #define PROPERTYNAME_HYPERLINKS_OPEN	OUString(RTL_CONSTASCII_USTRINGPARAM("Hyperlinks/Open"))
71 
72 #define PROPERTYHANDLE_HYPERLINKS_OPEN	0
73 
74 #define PROPERTYCOUNT                   1
75 
76 //_________________________________________________________________________________________________________________
77 //	private declarations!
78 //_________________________________________________________________________________________________________________
79 
80 struct OUStringHashCode
81 {
82     size_t operator()( const ::rtl::OUString& sString ) const
83 	{
84 		return sString.hashCode();
85 	}
86 };
87 
88 class ExtensionHashMap : public ::std::hash_map< ::rtl::OUString,
89 												 sal_Int32,
90 												 OUStringHashCode,
91 												 ::std::equal_to< ::rtl::OUString > >
92 {
93 	public:
94 		inline void free()
95 		{
96 			ExtensionHashMap().swap( *this );
97 		}
98 };
99 
100 class SvtExtendedSecurityOptions_Impl : public ConfigItem
101 {
102 	//-------------------------------------------------------------------------------------------------------------
103 	//	public methods
104 	//-------------------------------------------------------------------------------------------------------------
105 
106 	public:
107 
108 		//---------------------------------------------------------------------------------------------------------
109 		//	constructor / destructor
110 		//---------------------------------------------------------------------------------------------------------
111 
112 		 SvtExtendedSecurityOptions_Impl();
113 		~SvtExtendedSecurityOptions_Impl();
114 
115 		//---------------------------------------------------------------------------------------------------------
116 		//	overloaded methods of baseclass
117 		//---------------------------------------------------------------------------------------------------------
118 
119 		/*-****************************************************************************************************//**
120 			@short		called for notify of configmanager
121 			@descr		These method is called from the ConfigManager before application ends or from the
122 			 			PropertyChangeListener if the sub tree broadcasts changes. You must update your
123 						internal values.
124 
125 			@seealso	baseclass ConfigItem
126 
127 			@param		"seqPropertyNames" is the list of properties which should be updated.
128 			@return		-
129 
130 			@onerror	-
131 		*//*-*****************************************************************************************************/
132 
133     	virtual void Notify( const Sequence< OUString >& seqPropertyNames );
134 
135 		/*-****************************************************************************************************//**
136 			@short		write changes to configuration
137 			@descr		These method writes the changed values into the sub tree
138 						and should always called in our destructor to guarantee consistency of config data.
139 
140 			@seealso	baseclass ConfigItem
141 
142 			@param		-
143 			@return		-
144 
145 			@onerror	-
146 		*//*-*****************************************************************************************************/
147 
148     	virtual void Commit();
149 
150 		//---------------------------------------------------------------------------------------------------------
151 		//	public interface
152 		//---------------------------------------------------------------------------------------------------------
153 
154 		/*-****************************************************************************************************//**
155 			@short		Access method to check for security problems
156 			@descr		Different methods to check for security related problems.
157 
158 			@seealso	-
159 
160 			@param		-
161 			@return		-
162 
163 			@onerror	-
164 		*//*-*****************************************************************************************************/
165 
166 		sal_Bool										IsSecureHyperlink( const rtl::OUString& aURL ) const;
167 		Sequence< rtl::OUString >						GetSecureExtensionList() const;
168 
169 		SvtExtendedSecurityOptions::OpenHyperlinkMode	GetOpenHyperlinkMode();
170 		void											SetOpenHyperlinkMode( SvtExtendedSecurityOptions::OpenHyperlinkMode aMode );
171         sal_Bool                                        IsOpenHyperlinkModeReadOnly() const;
172 
173 	//-------------------------------------------------------------------------------------------------------------
174 	//	private methods
175 	//-------------------------------------------------------------------------------------------------------------
176 
177 	private:
178 
179 		/*-****************************************************************************************************//**
180 			@short		return list of key names of ouer configuration management which represent oue module tree
181 			@descr		These methods return a static const list of key names. We need it to get needed values from our
182 						configuration management.
183 
184 			@seealso	-
185 
186 			@param		-
187 			@return		A list of needed configuration keys is returned.
188 
189 			@onerror	-
190 		*//*-*****************************************************************************************************/
191 
192 		static Sequence< OUString > GetPropertyNames();
193 
194 		/*-****************************************************************************************************//**
195 			@short		Fills the hash map with all extensions known to be secure
196 			@descr		These methods fills the given hash map object with all extensions known to be secure.
197 
198 			@seealso	-
199 
200 			@param		aHashMap
201 						A hash map to be filled with secure extension strings.
202 			@return		-
203 
204 			@onerror	-
205 		*//*-*****************************************************************************************************/
206 		void FillExtensionHashMap( ExtensionHashMap& aHashMap );
207 
208 	//-------------------------------------------------------------------------------------------------------------
209 	//	private member
210 	//-------------------------------------------------------------------------------------------------------------
211 
212 	private:
213 		OUString										m_aSecureExtensionsSetName;
214 		OUString										m_aExtensionPropName;
215 
216 		SvtExtendedSecurityOptions::OpenHyperlinkMode	m_eOpenHyperlinkMode;
217         sal_Bool                                        m_bROOpenHyperlinkMode;
218 		ExtensionHashMap								m_aExtensionHashMap;
219 };
220 
221 //_________________________________________________________________________________________________________________
222 //	definitions
223 //_________________________________________________________________________________________________________________
224 
225 //*****************************************************************************************************************
226 //	constructor
227 //*****************************************************************************************************************
228 SvtExtendedSecurityOptions_Impl::SvtExtendedSecurityOptions_Impl()
229 	// Init baseclasses first
230     :	ConfigItem			( ROOTNODE_SECURITY			),
231 	m_aSecureExtensionsSetName( SECURE_EXTENSIONS_SET ),
232     m_aExtensionPropName( EXTENSION_PROPNAME ),
233     m_bROOpenHyperlinkMode(sal_False)
234 	// Init member then.
235 {
236 	// Fill the extension hash map with all secure extension strings
237 	FillExtensionHashMap( m_aExtensionHashMap );
238 
239 	Sequence< OUString >	seqNames	= GetPropertyNames();
240 	Sequence< Any >			seqValues	= GetProperties( seqNames );
241     Sequence< sal_Bool >    seqRO       = GetReadOnlyStates ( seqNames  );
242 
243 	sal_Int32 nPropertyCount = seqValues.getLength();
244 	for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
245 	{
246 		// Safe impossible cases.
247 		// Check any for valid value.
248 		DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtExtendedSecurityOptions_Impl::SvtExtendedSecurityOptions_Impl()\nInvalid property value detected!\n" );
249         switch( nProperty )
250 		{
251 			case PROPERTYHANDLE_HYPERLINKS_OPEN:
252 			{
253 				DBG_ASSERT( ( seqValues[nProperty].getValueTypeClass() == TypeClass_LONG ), "SvtExtendedSecurityOptions_Impl::SvtExtendedSecurityOptions_Impl()\nWho has changed the value type of 'Hyperlink/Open'?" );
254 
255 				sal_Int32 nMode = SvtExtendedSecurityOptions::OPEN_WITHSECURITYCHECK;
256 				if ( seqValues[nProperty] >>= nMode )
257 					m_eOpenHyperlinkMode = (SvtExtendedSecurityOptions::OpenHyperlinkMode)nMode;
258 				else {
259 					DBG_ERROR("Wrong type for Open mode!");
260                 }
261                 m_bROOpenHyperlinkMode = seqRO[nProperty];
262 			}
263 			break;
264 		}
265 	}
266 
267 	// Enable notification mechanism of our baseclass.
268 	// We need it to get information about changes outside these class on ouer used configuration keys!
269 	Sequence< OUString > seqNotifyNames( 1 );
270 	seqNotifyNames[0] = m_aSecureExtensionsSetName;
271 	EnableNotification( seqNotifyNames );
272 }
273 
274 //*****************************************************************************************************************
275 //	destructor
276 //*****************************************************************************************************************
277 SvtExtendedSecurityOptions_Impl::~SvtExtendedSecurityOptions_Impl()
278 {
279 	// We must save our current values .. if user forget it!
280 	if( IsModified() == sal_True )
281 	{
282 		Commit();
283 	}
284 }
285 
286 //*****************************************************************************************************************
287 //	public method
288 //*****************************************************************************************************************
289 void SvtExtendedSecurityOptions_Impl::Notify( const Sequence< OUString >& )
290 {
291 	// Not implemented
292 }
293 
294 //*****************************************************************************************************************
295 //	public method
296 //*****************************************************************************************************************
297 void SvtExtendedSecurityOptions_Impl::Commit()
298 {
299 	// Get names of supported properties, create a list for values and copy current values to it.
300 	Sequence< OUString >	seqNames	= GetPropertyNames	();
301 	sal_Int32				nCount		= seqNames.getLength();
302 	Sequence< Any >			seqValues	( nCount );
303 	for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
304 	{
305         switch( nProperty )
306         {
307             case PROPERTYHANDLE_HYPERLINKS_OPEN:	{
308 														seqValues[nProperty] <<= (sal_Int32)m_eOpenHyperlinkMode;
309 													}
310                 									break;
311         }
312 	}
313 
314 	// Set properties in configuration.
315 	PutProperties( seqNames, seqValues );
316 }
317 
318 //*****************************************************************************************************************
319 //	public method
320 //*****************************************************************************************************************
321 sal_Bool SvtExtendedSecurityOptions_Impl::IsSecureHyperlink( const OUString& aURL ) const
322 {
323 	INetURLObject aURLObject( aURL );
324 
325 	String aExtension = aURLObject.getExtension();
326 	aExtension.ToLowerAscii();
327 
328 	ExtensionHashMap::const_iterator pIter = m_aExtensionHashMap.find( aExtension );
329 	if ( pIter != m_aExtensionHashMap.end() )
330 		return sal_True;
331 	else
332 		return sal_False;
333 }
334 
335 //*****************************************************************************************************************
336 //	public method
337 //*****************************************************************************************************************
338 Sequence< OUString > SvtExtendedSecurityOptions_Impl::GetSecureExtensionList() const
339 {
340 	Sequence< OUString > aResult( m_aExtensionHashMap.size() );
341 
342 	sal_Int32 nIndex = 0;
343 	for ( ExtensionHashMap::const_iterator pIter = m_aExtensionHashMap.begin();
344 			pIter != m_aExtensionHashMap.end(); pIter++ )
345 	{
346 		aResult[nIndex++] = pIter->first;
347 	}
348 
349 	return aResult;
350 }
351 
352 //*****************************************************************************************************************
353 //	public method
354 //*****************************************************************************************************************
355 SvtExtendedSecurityOptions::OpenHyperlinkMode SvtExtendedSecurityOptions_Impl::GetOpenHyperlinkMode()
356 {
357 	return m_eOpenHyperlinkMode;
358 }
359 /* -----------------09.07.2003 11:26-----------------
360 
361  --------------------------------------------------*/
362 sal_Bool SvtExtendedSecurityOptions_Impl::IsOpenHyperlinkModeReadOnly() const
363 {
364     return m_bROOpenHyperlinkMode;
365 }
366 
367 //*****************************************************************************************************************
368 //	public method
369 //*****************************************************************************************************************
370 void SvtExtendedSecurityOptions_Impl::SetOpenHyperlinkMode( SvtExtendedSecurityOptions::OpenHyperlinkMode eNewMode )
371 {
372 	m_eOpenHyperlinkMode = eNewMode;
373 	SetModified();
374 }
375 
376 //*****************************************************************************************************************
377 //	private method
378 //*****************************************************************************************************************
379 void SvtExtendedSecurityOptions_Impl::FillExtensionHashMap( ExtensionHashMap& aHashMap )
380 {
381 	// Get sequence with secure extensions from configuration
382 	Sequence< OUString >	seqNodes = GetNodeNames( m_aSecureExtensionsSetName );
383 
384 	OUString				aValue;
385 	Sequence< Any >			aValues;
386 	Sequence< OUString >	aPropSeq( 1 );
387 	for ( int i = 0; i < seqNodes.getLength(); i++ )
388 	{
389 		// Create access name for property
390 		OUStringBuffer aExtEntryProp( m_aSecureExtensionsSetName );
391 		aExtEntryProp.appendAscii( "/" );
392 		aExtEntryProp.append( seqNodes[i] );
393 		aExtEntryProp.append( m_aExtensionPropName );
394 
395 		aPropSeq[0] = aExtEntryProp.makeStringAndClear();
396 		aValues = GetProperties( aPropSeq );
397 		if ( aValues.getLength() == 1 )
398 		{
399 			// Don't use value if sequence has not the correct length
400 			if ( aValues[0] >>= aValue )
401 				// Add extension into secure extensions hash map
402 				aHashMap.insert( ExtensionHashMap::value_type( aValue.toAsciiLowerCase(), 1 ) );
403 			else
404 			{
405 				DBG_ERRORFILE( "SvtExtendedSecurityOptions_Impl::FillExtensionHashMap(): not string value?" );
406 			}
407 		}
408 	}
409 }
410 
411 //*****************************************************************************************************************
412 //	private method (currently not used)
413 //*****************************************************************************************************************
414 Sequence< OUString > SvtExtendedSecurityOptions_Impl::GetPropertyNames()
415 {
416 	// Build static list of configuration key names.
417 	static const OUString pProperties[] =
418 	{
419 		PROPERTYNAME_HYPERLINKS_OPEN
420 	};
421 	// Initialize return sequence with these list ...
422 	static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
423 	// ... and return it.
424 	return seqPropertyNames;
425 }
426 
427 //*****************************************************************************************************************
428 //	initialize static member
429 //	DON'T DO IT IN YOUR HEADER!
430 //	see definition for further informations
431 //*****************************************************************************************************************
432 SvtExtendedSecurityOptions_Impl*	SvtExtendedSecurityOptions::m_pDataContainer	= NULL	;
433 sal_Int32							SvtExtendedSecurityOptions::m_nRefCount			= 0		;
434 
435 //*****************************************************************************************************************
436 //	constructor
437 //*****************************************************************************************************************
438 SvtExtendedSecurityOptions::SvtExtendedSecurityOptions()
439 {
440     // Global access, must be guarded (multithreading!).
441     MutexGuard aGuard( GetInitMutex() );
442 	// Increase ouer refcount ...
443 	++m_nRefCount;
444 	// ... and initialize ouer data container only if it not already exist!
445     if( m_pDataContainer == NULL )
446 	{
447        RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtExtendedSecurityOptions_Impl::ctor()");
448        m_pDataContainer = new SvtExtendedSecurityOptions_Impl;
449 
450         ItemHolder1::holdConfigItem(E_EXTENDEDSECURITYOPTIONS);
451 	}
452 }
453 
454 //*****************************************************************************************************************
455 //	destructor
456 //*****************************************************************************************************************
457 SvtExtendedSecurityOptions::~SvtExtendedSecurityOptions()
458 {
459     // Global access, must be guarded (multithreading!)
460     MutexGuard aGuard( GetInitMutex() );
461 	// Decrease ouer refcount.
462 	--m_nRefCount;
463 	// If last instance was deleted ...
464 	// we must destroy ouer static data container!
465     if( m_nRefCount <= 0 )
466 	{
467 		delete m_pDataContainer;
468 		m_pDataContainer = NULL;
469 	}
470 }
471 
472 //*****************************************************************************************************************
473 //	public method
474 //*****************************************************************************************************************
475 sal_Bool SvtExtendedSecurityOptions::IsSecureHyperlink( const rtl::OUString& aURL ) const
476 {
477     MutexGuard aGuard( GetInitMutex() );
478 	return m_pDataContainer->IsSecureHyperlink( aURL );
479 }
480 
481 //*****************************************************************************************************************
482 //	public method
483 //*****************************************************************************************************************
484 Sequence< rtl::OUString > SvtExtendedSecurityOptions::GetSecureExtensionList() const
485 {
486     MutexGuard aGuard( GetInitMutex() );
487 	return m_pDataContainer->GetSecureExtensionList();
488 }
489 
490 //*****************************************************************************************************************
491 //	public method
492 //*****************************************************************************************************************
493 SvtExtendedSecurityOptions::OpenHyperlinkMode SvtExtendedSecurityOptions::GetOpenHyperlinkMode()
494 {
495     MutexGuard aGuard( GetInitMutex() );
496 	return m_pDataContainer->GetOpenHyperlinkMode();
497 }
498 /* -----------------09.07.2003 11:26-----------------
499 
500  --------------------------------------------------*/
501 sal_Bool SvtExtendedSecurityOptions::IsOpenHyperlinkModeReadOnly() const
502 {
503     return m_pDataContainer->IsOpenHyperlinkModeReadOnly();
504 }
505 
506 //*****************************************************************************************************************
507 //	public method
508 //*****************************************************************************************************************
509 void SvtExtendedSecurityOptions::SetOpenHyperlinkMode( SvtExtendedSecurityOptions::OpenHyperlinkMode eMode )
510 {
511     MutexGuard aGuard( GetInitMutex() );
512 	m_pDataContainer->SetOpenHyperlinkMode( eMode );
513 }
514 
515 //*****************************************************************************************************************
516 //	private method
517 //*****************************************************************************************************************
518 Mutex& SvtExtendedSecurityOptions::GetInitMutex()
519 {
520 	// Initialize static mutex only for one time!
521     static Mutex* pMutex = NULL;
522 	// If these method first called (Mutex not already exist!) ...
523     if( pMutex == NULL )
524     {
525 		// ... we must create a new one. Protect follow code with the global mutex -
526 		// It must be - we create a static variable!
527         MutexGuard aGuard( Mutex::getGlobalMutex() );
528 		// We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
529         if( pMutex == NULL )
530         {
531 			// Create the new mutex and set it for return on static variable.
532             static Mutex aMutex;
533             pMutex = &aMutex;
534         }
535     }
536 	// Return new created or already existing mutex object.
537     return *pMutex;
538 }
539