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