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 #ifndef GCC
31 #endif
32 
33 #include <unotools/pathoptions.hxx>
34 #include <unotools/configitem.hxx>
35 #include <unotools/configmgr.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/resmgr.hxx>
38 #include <tools/urlobj.hxx>
39 #include <com/sun/star/uno/Any.hxx>
40 #include <com/sun/star/uno/Sequence.hxx>
41 #include <osl/mutex.hxx>
42 #include <osl/file.hxx>
43 #include <unotools/localfilehelper.hxx>
44 #include <unotools/bootstrap.hxx>
45 
46 #include <unotools/ucbhelper.hxx>
47 #include <vos/process.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <comphelper/componentcontext.hxx>
50 #include <com/sun/star/beans/XFastPropertySet.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/beans/PropertyAttribute.hpp>
53 #include <com/sun/star/beans/XPropertySetInfo.hpp>
54 #include <com/sun/star/util/XStringSubstitution.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/util/XMacroExpander.hpp>
57 #include <rtl/instance.hxx>
58 
59 #include <itemholder1.hxx>
60 
61 #include <vector>
62 #include <hash_map>
63 
64 using namespace osl;
65 using namespace utl;
66 using namespace rtl;
67 using namespace com::sun::star::uno;
68 using namespace com::sun::star::beans;
69 using namespace com::sun::star::util;
70 using namespace com::sun::star::lang;
71 
72 // define ----------------------------------------------------------------
73 
74 #define SEARCHPATH_DELIMITER			';'
75 
76 #define ASCII_STR(s)					OUString( RTL_CONSTASCII_USTRINGPARAM(s) )
77 
78 #define	SIGN_STARTVARIABLE				ASCII_STR("$(")
79 #define	SIGN_ENDVARIABLE				ASCII_STR(")")
80 
81 // Supported variables by the old SvtPathOptions implementation
82 #define	SUBSTITUTE_INST					"$(inst)"
83 #define	SUBSTITUTE_PROG					"$(prog)"
84 #define	SUBSTITUTE_USER					"$(user)"
85 #define SUBSTITUTE_INSTPATH             "$(instpath)"
86 #define SUBSTITUTE_PROGPATH             "$(progpath)"
87 #define SUBSTITUTE_USERPATH             "$(userpath)"
88 #define	SUBSTITUTE_INSTURL				"$(insturl)"
89 #define	SUBSTITUTE_PROGURL				"$(progurl)"
90 #define	SUBSTITUTE_USERURL				"$(userurl)"
91 #define	SUBSTITUTE_PATH					"$(path)"
92 //#define	SUBSTITUTE_LANG					"$(lang)"
93 #define	SUBSTITUTE_LANGID				"$(langid)"
94 #define	SUBSTITUTE_VLANG				"$(vlang)"
95 #define	SUBSTITUTE_WORKDIRURL			"$(workdirurl)"
96 
97 #define STRPOS_NOTFOUND					-1
98 
99 struct OUStringHashCode
100 {
101     size_t operator()( const ::rtl::OUString& sString ) const
102 	{
103 		return sString.hashCode();
104 	}
105 };
106 
107 enum VarNameProperty
108 {
109 	VAR_NEEDS_SYSTEM_PATH,
110 	VAR_NEEDS_FILEURL
111 };
112 
113 class NameToHandleMap : public ::std::hash_map<	::rtl::OUString, sal_Int32, OUStringHashCode, ::std::equal_to< ::rtl::OUString > >
114 {
115 	public:
116 		inline void free() { NameToHandleMap().swap( *this ); }
117 };
118 
119 class EnumToHandleMap : public ::std::hash_map< sal_Int32, sal_Int32, std::hash< sal_Int32 >, std::equal_to< sal_Int32 > >
120 {
121 	public:
122 		inline void free() { EnumToHandleMap().swap( *this ); }
123 };
124 
125 class VarNameToEnumMap : public ::std::hash_map< OUString, VarNameProperty, OUStringHashCode, ::std::equal_to< OUString > >
126 {
127 	public:
128 		inline void free() { VarNameToEnumMap().swap( *this ); }
129 };
130 
131 
132 // class SvtPathOptions_Impl ---------------------------------------------
133 class SvtPathOptions_Impl
134 {
135 	private:
136 		// Local variables to return const references
137 		std::vector< String >				m_aPathArray;
138 		Reference< XFastPropertySet >		m_xPathSettings;
139 		Reference< XStringSubstitution >	m_xSubstVariables;
140         Reference< XMacroExpander >         m_xMacroExpander;
141         mutable EnumToHandleMap             m_aMapEnumToPropHandle;
142 		VarNameToEnumMap					m_aMapVarNamesToEnum;
143 
144 	    ::com::sun::star::lang::Locale 						m_aLocale;
145 		String								m_aEmptyString;
146         mutable ::osl::Mutex                m_aMutex;
147 
148 	public:
149 						SvtPathOptions_Impl();
150 
151 		// get the pathes, not const because of using a mutex
152         const String&   GetPath( SvtPathOptions::Pathes );
153         const String&   GetAddinPath() { return GetPath( SvtPathOptions::PATH_ADDIN ); }
154 		const String&	GetAutoCorrectPath() { return GetPath( SvtPathOptions::PATH_AUTOCORRECT ); }
155 		const String&	GetAutoTextPath() { return GetPath( SvtPathOptions::PATH_AUTOTEXT ); }
156 		const String&	GetBackupPath() { return GetPath( SvtPathOptions::PATH_BACKUP ); }
157 		const String&	GetBasicPath() { return GetPath( SvtPathOptions::PATH_BASIC ); }
158 		const String&	GetBitmapPath() { return GetPath( SvtPathOptions::PATH_BITMAP ); }
159 		const String&	GetConfigPath() { return GetPath( SvtPathOptions::PATH_CONFIG ); }
160 		const String&	GetDictionaryPath() { return GetPath( SvtPathOptions::PATH_DICTIONARY ); }
161 		const String&	GetFavoritesPath() { return GetPath( SvtPathOptions::PATH_FAVORITES ); }
162 		const String&	GetFilterPath() { return GetPath( SvtPathOptions::PATH_FILTER ); }
163 		const String&	GetGalleryPath() { return GetPath( SvtPathOptions::PATH_GALLERY ); }
164 		const String&	GetGraphicPath() { return GetPath( SvtPathOptions::PATH_GRAPHIC ); }
165 		const String&	GetHelpPath() { return GetPath( SvtPathOptions::PATH_HELP ); }
166 		const String&	GetLinguisticPath() { return GetPath( SvtPathOptions::PATH_LINGUISTIC ); }
167 		const String&	GetModulePath() { return GetPath( SvtPathOptions::PATH_MODULE ); }
168 		const String&	GetPalettePath() { return GetPath( SvtPathOptions::PATH_PALETTE ); }
169 		const String&	GetPluginPath() { return GetPath( SvtPathOptions::PATH_PLUGIN ); }
170 		const String&	GetStoragePath() { return GetPath( SvtPathOptions::PATH_STORAGE ); }
171 		const String&	GetTempPath() { return GetPath( SvtPathOptions::PATH_TEMP ); }
172 		const String&	GetTemplatePath() { return GetPath( SvtPathOptions::PATH_TEMPLATE ); }
173 		const String&	GetUserConfigPath() { return GetPath( SvtPathOptions::PATH_USERCONFIG ); }
174 		const String&	GetWorkPath() { return GetPath( SvtPathOptions::PATH_WORK ); }
175 	    const String&   GetUIConfigPath() { return GetPath( SvtPathOptions::PATH_UICONFIG ); }
176         const String&   GetFingerprintPath() { return GetPath( SvtPathOptions::PATH_FINGERPRINT ); }
177 
178 		// set the pathes
179         void            SetPath( SvtPathOptions::Pathes, const String& rNewPath );
180         void            SetAddinPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_ADDIN, rPath ); }
181 		void			SetAutoCorrectPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_AUTOCORRECT, rPath ); }
182 		void			SetAutoTextPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_AUTOTEXT, rPath ); }
183 		void			SetBackupPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_BACKUP, rPath ); }
184 		void			SetBasicPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_BASIC, rPath ); }
185 		void			SetBitmapPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_BITMAP, rPath ); }
186 		void			SetConfigPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_CONFIG, rPath ); }
187 		void			SetDictionaryPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_DICTIONARY, rPath ); }
188 		void			SetFavoritesPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_FAVORITES, rPath ); }
189 		void			SetFilterPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_FILTER, rPath ); }
190 		void			SetGalleryPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_GALLERY, rPath ); }
191 		void			SetGraphicPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_GRAPHIC, rPath ); }
192 		void			SetHelpPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_HELP, rPath ); }
193 		void			SetLinguisticPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_LINGUISTIC, rPath ); }
194 		void			SetModulePath( const String& rPath ) { SetPath( SvtPathOptions::PATH_MODULE, rPath ); }
195 		void			SetPalettePath( const String& rPath ) { SetPath( SvtPathOptions::PATH_PALETTE, rPath ); }
196 		void			SetPluginPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_PLUGIN, rPath ); }
197 		void			SetStoragePath( const String& rPath ) { SetPath( SvtPathOptions::PATH_STORAGE, rPath ); }
198 		void			SetTempPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_TEMP, rPath ); }
199 		void			SetTemplatePath( const String& rPath ) { SetPath( SvtPathOptions::PATH_TEMPLATE, rPath ); }
200 		void			SetUserConfigPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_USERCONFIG, rPath ); }
201 		void			SetWorkPath( const String& rPath ) { SetPath( SvtPathOptions::PATH_WORK, rPath ); }
202 
203 		rtl::OUString	SubstVar( const rtl::OUString& rVar ) const;
204 		rtl::OUString	ExpandMacros( const rtl::OUString& rPath ) const;
205 		rtl::OUString	UsePathVariables( const rtl::OUString& rPath ) const;
206 
207 		::com::sun::star::lang::Locale	GetLocale() const { return m_aLocale; }
208 
209         sal_Bool            IsPathReadonly(SvtPathOptions::Pathes ePath)const;
210 };
211 
212 // global ----------------------------------------------------------------
213 
214 static SvtPathOptions_Impl* pOptions = NULL;
215 static sal_Int32 nRefCount = 0;
216 
217 // functions -------------------------------------------------------------
218 struct PropertyStruct
219 {
220 	const char*				pPropName;	// The ascii name of the Office path
221 	SvtPathOptions::Pathes	ePath;		// The enum value used by SvtPathOptions
222 };
223 
224 struct VarNameAttribute
225 {
226 	const char*				pVarName;		// The name of the path variable
227 	VarNameProperty			eVarProperty;	// Which return value is needed by this path variable
228 };
229 
230 static PropertyStruct aPropNames[] =
231 {
232 	{ "Addin",			SvtPathOptions::PATH_ADDIN			},
233 	{ "AutoCorrect",	SvtPathOptions::PATH_AUTOCORRECT	},
234 	{ "AutoText",		SvtPathOptions::PATH_AUTOTEXT		},
235 	{ "Backup",			SvtPathOptions::PATH_BACKUP			},
236 	{ "Basic",			SvtPathOptions::PATH_BASIC			},
237 	{ "Bitmap",			SvtPathOptions::PATH_BITMAP			},
238 	{ "Config",			SvtPathOptions::PATH_CONFIG			},
239 	{ "Dictionary",		SvtPathOptions::PATH_DICTIONARY		},
240 	{ "Favorite",		SvtPathOptions::PATH_FAVORITES		},
241 	{ "Filter",			SvtPathOptions::PATH_FILTER			},
242 	{ "Gallery",		SvtPathOptions::PATH_GALLERY		},
243 	{ "Graphic",		SvtPathOptions::PATH_GRAPHIC		},
244 	{ "Help",			SvtPathOptions::PATH_HELP			},
245 	{ "Linguistic",		SvtPathOptions::PATH_LINGUISTIC		},
246 	{ "Module",			SvtPathOptions::PATH_MODULE			},
247 	{ "Palette",		SvtPathOptions::PATH_PALETTE		},
248 	{ "Plugin",			SvtPathOptions::PATH_PLUGIN			},
249 	{ "Storage",		SvtPathOptions::PATH_STORAGE		},
250 	{ "Temp",			SvtPathOptions::PATH_TEMP			},
251 	{ "Template",		SvtPathOptions::PATH_TEMPLATE		},
252 	{ "UserConfig",		SvtPathOptions::PATH_USERCONFIG		},
253     { "Work",           SvtPathOptions::PATH_WORK			},
254     { "UIConfig",       SvtPathOptions::PATH_UICONFIG		},
255     { "Fingerprint",    SvtPathOptions::PATH_FINGERPRINT	}
256 };
257 
258 static VarNameAttribute aVarNameAttribute[] =
259 {
260 	{ SUBSTITUTE_INSTPATH,	VAR_NEEDS_SYSTEM_PATH },	// $(instpath)
261 	{ SUBSTITUTE_PROGPATH,	VAR_NEEDS_SYSTEM_PATH },	// $(progpath)
262 	{ SUBSTITUTE_USERPATH,	VAR_NEEDS_SYSTEM_PATH },	// $(userpath)
263 	{ SUBSTITUTE_PATH,		VAR_NEEDS_SYSTEM_PATH },	// $(path)
264 };
265 
266 #if 0
267 // currently unused
268 static Sequence< OUString > GetPathPropertyNames()
269 {
270 	const int nCount = sizeof( aPropNames ) / sizeof( PropertyStruct );
271 	Sequence< OUString > aNames( nCount );
272 	OUString* pNames = aNames.getArray();
273 	for ( int i = 0; i < nCount; i++ )
274 		pNames[i] = OUString::createFromAscii( aPropNames[i].pPropName );
275 
276 	return aNames;
277 }
278 #endif
279 
280 // class SvtPathOptions_Impl ---------------------------------------------
281 
282 const String& SvtPathOptions_Impl::GetPath( SvtPathOptions::Pathes ePath )
283 {
284 	::osl::MutexGuard aGuard( m_aMutex );
285 
286 	if ( ePath >= SvtPathOptions::PATH_COUNT )
287         return m_aEmptyString;
288 
289     OUString 	aPathValue;
290 	String		aResult;
291 	sal_Int32	nHandle = m_aMapEnumToPropHandle[ (sal_Int32)ePath ];
292 
293 	// Substitution is done by the service itself using the substition service
294 	Any 		a = m_xPathSettings->getFastPropertyValue( nHandle );
295 	a >>= aPathValue;
296 	if( ePath == SvtPathOptions::PATH_ADDIN     ||
297         ePath == SvtPathOptions::PATH_FILTER    ||
298         ePath == SvtPathOptions::PATH_HELP      ||
299         ePath == SvtPathOptions::PATH_MODULE    ||
300         ePath == SvtPathOptions::PATH_PLUGIN    ||
301         ePath == SvtPathOptions::PATH_STORAGE
302       )
303 	{
304         // These office paths have to be converted to system pathes
305         utl::LocalFileHelper::ConvertURLToPhysicalName( aPathValue, aResult );
306         aPathValue = aResult;
307 	}
308 
309 	m_aPathArray[ ePath ] = aPathValue;
310     return m_aPathArray[ ePath ];
311 }
312 // -----------------------------------------------------------------------
313 sal_Bool SvtPathOptions_Impl::IsPathReadonly(SvtPathOptions::Pathes ePath)const
314 {
315     ::osl::MutexGuard aGuard( m_aMutex );
316     sal_Bool bReadonly = sal_False;
317     if ( ePath < SvtPathOptions::PATH_COUNT )
318     {
319         Reference<XPropertySet> xPrSet(m_xPathSettings, UNO_QUERY);
320         if(xPrSet.is())
321         {
322             Reference<XPropertySetInfo> xInfo = xPrSet->getPropertySetInfo();
323 			const char* pA = aPropNames[ePath].pPropName;
324 			::rtl::OUString sU = OUString::createFromAscii(pA);
325             Property aProperty = xInfo->getPropertyByName(sU);
326             bReadonly = 0 != (aProperty.Attributes & PropertyAttribute::READONLY);
327         }
328     }
329     return bReadonly;
330 }
331 // -----------------------------------------------------------------------
332 
333 void SvtPathOptions_Impl::SetPath( SvtPathOptions::Pathes ePath, const String& rNewPath )
334 {
335 	::osl::MutexGuard aGuard( m_aMutex );
336 
337 	if ( ePath < SvtPathOptions::PATH_COUNT )
338 	{
339 		String 		aResult;
340 		OUString	aNewValue;
341 		Any			a;
342 
343 		switch ( ePath )
344 		{
345 			case SvtPathOptions::PATH_ADDIN:
346 			case SvtPathOptions::PATH_FILTER:
347 			case SvtPathOptions::PATH_HELP:
348 			case SvtPathOptions::PATH_MODULE:
349 			case SvtPathOptions::PATH_PLUGIN:
350 			case SvtPathOptions::PATH_STORAGE:
351 			{
352 				// These office paths have to be convert back to UCB-URL's
353 				utl::LocalFileHelper::ConvertPhysicalNameToURL( rNewPath, aResult );
354 				aNewValue = aResult;
355 			}
356 			break;
357 
358 			default:
359 				aNewValue = rNewPath;
360 		}
361 
362 		// Resubstitution is done by the service itself using the substition service
363 		a <<= aNewValue;
364 		try
365 		{
366 			m_xPathSettings->setFastPropertyValue( m_aMapEnumToPropHandle[ (sal_Int32)ePath], a );
367 		}
368 		catch (const Exception&)
369 		{
370 		}
371 	}
372 }
373 
374 //-------------------------------------------------------------------------
375 
376 OUString SvtPathOptions_Impl::ExpandMacros( const rtl::OUString& rPath ) const
377 {
378     ::rtl::OUString sExpanded( rPath );
379 
380     const INetURLObject aParser( rPath );
381     if ( aParser.GetProtocol() == INET_PROT_VND_SUN_STAR_EXPAND )
382         sExpanded = m_xMacroExpander->expandMacros( aParser.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ) );
383 
384     return sExpanded;
385 }
386 
387 //-------------------------------------------------------------------------
388 
389 OUString SvtPathOptions_Impl::UsePathVariables( const OUString& rPath ) const
390 {
391 	return m_xSubstVariables->reSubstituteVariables( rPath );
392 }
393 
394 // -----------------------------------------------------------------------
395 
396 OUString SvtPathOptions_Impl::SubstVar( const OUString& rVar ) const
397 {
398 	// Don't work at parameter-string directly. Copy it.
399 	OUString aWorkText = rVar;
400 
401 	// Convert the returned path to system path!
402 	sal_Bool bConvertLocal = sal_False;
403 
404 	// Search for first occure of "$(...".
405 	sal_Int32 nPosition	= aWorkText.indexOf( SIGN_STARTVARIABLE );	// = first position of "$(" in string
406 	sal_Int32 nLength	= 0;										// = count of letters from "$(" to ")" in string
407 
408 	// Have we found any variable like "$(...)"?
409 	if ( nPosition != STRPOS_NOTFOUND )
410 	{
411 		// Yes; Get length of found variable.
412 		// If no ")" was found - nLength is set to 0 by default! see before.
413 		sal_Int32 nEndPosition = aWorkText.indexOf( SIGN_ENDVARIABLE, nPosition );
414 		if ( nEndPosition != STRPOS_NOTFOUND )
415 			nLength = nEndPosition - nPosition + 1;
416 	}
417 
418 	// Is there another path variable?
419 	while ( ( nPosition != STRPOS_NOTFOUND ) && ( nLength > 0 ) )
420 	{
421 		// YES; Get the next variable for replace.
422 		OUString aReplacement;
423 		OUString aSubString = aWorkText.copy( nPosition, nLength );
424         aSubString = aSubString.toAsciiLowerCase();
425 
426 		// Look for special variable that needs a system path.
427 		VarNameToEnumMap::const_iterator pIter = m_aMapVarNamesToEnum.find( aSubString );
428 		if ( pIter != m_aMapVarNamesToEnum.end() )
429 			bConvertLocal = sal_True;
430 
431 		nPosition += nLength;
432 
433 		// We must control index in string before call something at OUString!
434 		// The OUString-implementation don't do it for us :-( but the result is not defined otherwise.
435 		if ( nPosition + 1 > aWorkText.getLength() )
436 		{
437 			// Position is out of range. Break loop!
438 			nPosition = STRPOS_NOTFOUND;
439 			nLength = 0;
440 		}
441 		else
442 		{
443 			// Else; Position is valid. Search for next variable.
444 			nPosition = aWorkText.indexOf( SIGN_STARTVARIABLE, nPosition );
445 			// Have we found any variable like "$(...)"?
446 			if ( nPosition != STRPOS_NOTFOUND )
447 			{
448 				// Yes; Get length of found variable. If no ")" was found - nLength must set to 0!
449 				nLength	= 0;
450 				sal_Int32 nEndPosition = aWorkText.indexOf( SIGN_ENDVARIABLE, nPosition );
451 				if ( nEndPosition != STRPOS_NOTFOUND )
452 					nLength = nEndPosition - nPosition + 1;
453 			}
454 		}
455 	}
456 
457 	aWorkText = m_xSubstVariables->substituteVariables( rVar, sal_False );
458 
459 	if ( bConvertLocal )
460 	{
461 		// Convert the URL to a system path for special path variables
462         String aReturn;
463 		utl::LocalFileHelper::ConvertURLToPhysicalName( aWorkText, aReturn );
464 		return aReturn;
465 	}
466 
467     return aWorkText;
468 }
469 
470 // -----------------------------------------------------------------------
471 
472 SvtPathOptions_Impl::SvtPathOptions_Impl() :
473 	m_aPathArray( (sal_Int32)SvtPathOptions::PATH_COUNT )
474 {
475 	Reference< XMultiServiceFactory > xSMgr = comphelper::getProcessServiceFactory();
476 
477 	// Create necessary services
478 	m_xPathSettings = Reference< XFastPropertySet >( xSMgr->createInstance(
479 													::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
480 														"com.sun.star.util.PathSettings" ))),
481 												UNO_QUERY );
482     if ( !m_xPathSettings.is() )
483 	{
484         // #112719#: check for existance
485 		DBG_ERROR( "SvtPathOptions_Impl::SvtPathOptions_Impl(): #112719# happened again!" );
486         throw RuntimeException(
487             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Service com.sun.star.util.PathSettings cannot be created" )),
488             Reference< XInterface >() );
489 	}
490 
491     ::comphelper::ComponentContext aContext( xSMgr );
492     m_xSubstVariables.set( aContext.createComponent( "com.sun.star.util.PathSubstitution" ), UNO_QUERY_THROW );
493     m_xMacroExpander.set( aContext.getSingleton( "com.sun.star.util.theMacroExpander" ), UNO_QUERY_THROW );
494 
495     // Create temporary hash map to have a mapping between property names and property handles
496 	Reference< XPropertySet > xPropertySet = Reference< XPropertySet >( m_xPathSettings, UNO_QUERY );
497 	Reference< XPropertySetInfo > xPropSetInfo = xPropertySet->getPropertySetInfo();
498 	Sequence< Property > aPathPropSeq = xPropSetInfo->getProperties();
499 
500 	NameToHandleMap aTempHashMap;
501 	for ( sal_Int32 n = 0; n < aPathPropSeq.getLength(); n++ )
502 	{
503 		const com::sun::star::beans::Property& aProperty = aPathPropSeq[n];
504 		aTempHashMap.insert( NameToHandleMap::value_type( aProperty.Name, aProperty.Handle ));
505 	}
506 
507 	// Create mapping between internal enum (SvtPathOptions::Pathes) and property handle
508 	sal_Int32 nCount = sizeof( aPropNames ) / sizeof( PropertyStruct );
509 	sal_Int32 i;
510 	for ( i = 0; i < nCount; i++ )
511 	{
512 		NameToHandleMap::const_iterator pIter =
513 			aTempHashMap.find( rtl::OUString::createFromAscii( aPropNames[i].pPropName ));
514 
515 		if ( pIter != aTempHashMap.end() )
516 		{
517 			sal_Int32 nHandle	= pIter->second;
518 			sal_Int32 nEnum		= aPropNames[i].ePath;
519 			m_aMapEnumToPropHandle.insert( EnumToHandleMap::value_type( nEnum, nHandle ));
520 		}
521 	}
522 
523 	// Create hash map for path variables that need a system path as a return value!
524 	nCount = sizeof( aVarNameAttribute ) / sizeof( VarNameAttribute );
525 	for ( i = 0; i < nCount; i++ )
526 	{
527 		m_aMapVarNamesToEnum.insert( VarNameToEnumMap::value_type(
528 				OUString::createFromAscii( aVarNameAttribute[i].pVarName ),
529 				aVarNameAttribute[i].eVarProperty ));
530 	}
531 
532 	// Set language type!
533 	Any aLocale = ConfigManager::GetConfigManager()->GetDirectConfigProperty( ConfigManager::LOCALE );
534 	OUString aLocaleStr;
535 	if ( aLocale >>= aLocaleStr )
536     {
537         sal_Int32 nIndex = 0;
538         m_aLocale.Language = aLocaleStr.getToken(0, '-', nIndex );
539         m_aLocale.Country = aLocaleStr.getToken(0, '-', nIndex );
540         m_aLocale.Variant = aLocaleStr.getToken(0, '-', nIndex );
541     }
542 	else
543 	{
544 		DBG_ERRORFILE( "wrong any type" );
545         m_aLocale.Language = OStringToOUString(OString("en"), RTL_TEXTENCODING_UTF8);
546         m_aLocale.Country =  OStringToOUString(OString("US"), RTL_TEXTENCODING_UTF8);
547         m_aLocale.Variant =  OStringToOUString(OString(""), RTL_TEXTENCODING_UTF8);
548 	}
549 }
550 
551 // -----------------------------------------------------------------------
552 
553 // class SvtPathOptions --------------------------------------------------
554 
555 namespace { struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; }
556 
557 SvtPathOptions::SvtPathOptions()
558 {
559     // Global access, must be guarded (multithreading)
560     ::osl::MutexGuard aGuard( lclMutex::get() );
561     if ( !pOptions )
562 	{
563         pOptions = new SvtPathOptions_Impl;
564         ItemHolder1::holdConfigItem(E_PATHOPTIONS);
565 	}
566     ++nRefCount;
567     pImp = pOptions;
568 }
569 
570 // -----------------------------------------------------------------------
571 
572 SvtPathOptions::~SvtPathOptions()
573 {
574     // Global access, must be guarded (multithreading)
575     ::osl::MutexGuard aGuard( lclMutex::get() );
576     if ( !--nRefCount )
577 	{
578         DELETEZ( pOptions );
579 	}
580 }
581 
582 // -----------------------------------------------------------------------
583 
584 const String& SvtPathOptions::GetAddinPath() const
585 {
586 	return pImp->GetAddinPath();
587 }
588 
589 // -----------------------------------------------------------------------
590 
591 const String& SvtPathOptions::GetAutoCorrectPath() const
592 {
593 	return pImp->GetAutoCorrectPath();
594 }
595 
596 // -----------------------------------------------------------------------
597 
598 const String& SvtPathOptions::GetAutoTextPath() const
599 {
600 	return pImp->GetAutoTextPath();
601 }
602 
603 // -----------------------------------------------------------------------
604 
605 const String& SvtPathOptions::GetBackupPath() const
606 {
607 	return pImp->GetBackupPath();
608 }
609 
610 // -----------------------------------------------------------------------
611 
612 const String& SvtPathOptions::GetBasicPath() const
613 {
614 	return pImp->GetBasicPath();
615 }
616 
617 // -----------------------------------------------------------------------
618 
619 const String& SvtPathOptions::GetBitmapPath() const
620 {
621 	return pImp->GetBitmapPath();
622 }
623 
624 // -----------------------------------------------------------------------
625 
626 const String& SvtPathOptions::GetConfigPath() const
627 {
628 	return pImp->GetConfigPath();
629 }
630 
631 // -----------------------------------------------------------------------
632 
633 const String& SvtPathOptions::GetDictionaryPath() const
634 {
635 	return pImp->GetDictionaryPath();
636 }
637 
638 // -----------------------------------------------------------------------
639 
640 const String& SvtPathOptions::GetFavoritesPath() const
641 {
642 	return pImp->GetFavoritesPath();
643 }
644 
645 // -----------------------------------------------------------------------
646 
647 const String& SvtPathOptions::GetFilterPath() const
648 {
649 	return pImp->GetFilterPath();
650 }
651 
652 // -----------------------------------------------------------------------
653 
654 const String& SvtPathOptions::GetGalleryPath() const
655 {
656 	return pImp->GetGalleryPath();
657 }
658 
659 // -----------------------------------------------------------------------
660 
661 const String& SvtPathOptions::GetGraphicPath() const
662 {
663 	return pImp->GetGraphicPath();
664 }
665 
666 // -----------------------------------------------------------------------
667 
668 const String& SvtPathOptions::GetHelpPath() const
669 {
670 	return pImp->GetHelpPath();
671 }
672 
673 // -----------------------------------------------------------------------
674 
675 const String& SvtPathOptions::GetLinguisticPath() const
676 {
677 	return pImp->GetLinguisticPath();
678 }
679 
680 // -----------------------------------------------------------------------
681 
682 const String& SvtPathOptions::GetFingerprintPath() const
683 {
684     return pImp->GetFingerprintPath();
685 }
686 
687 // -----------------------------------------------------------------------
688 
689 const String& SvtPathOptions::GetModulePath() const
690 {
691 	return pImp->GetModulePath();
692 }
693 
694 // -----------------------------------------------------------------------
695 
696 const String& SvtPathOptions::GetPalettePath() const
697 {
698 	return pImp->GetPalettePath();
699 }
700 
701 // -----------------------------------------------------------------------
702 
703 const String& SvtPathOptions::GetPluginPath() const
704 {
705 	return pImp->GetPluginPath();
706 }
707 
708 // -----------------------------------------------------------------------
709 
710 const String& SvtPathOptions::GetStoragePath() const
711 {
712 	return pImp->GetStoragePath();
713 }
714 
715 // -----------------------------------------------------------------------
716 
717 const String& SvtPathOptions::GetTempPath() const
718 {
719 	return pImp->GetTempPath();
720 }
721 
722 // -----------------------------------------------------------------------
723 
724 const String& SvtPathOptions::GetTemplatePath() const
725 {
726 	return pImp->GetTemplatePath();
727 }
728 
729 // -----------------------------------------------------------------------
730 
731 const String& SvtPathOptions::GetUserConfigPath() const
732 {
733 	return pImp->GetUserConfigPath();
734 }
735 
736 const String& SvtPathOptions::GetUIConfigPath() const
737 {
738     return pImp->GetUIConfigPath();
739 }
740 
741 // -----------------------------------------------------------------------
742 
743 const String& SvtPathOptions::GetWorkPath() const
744 {
745 	return pImp->GetWorkPath();
746 }
747 
748 // -----------------------------------------------------------------------
749 
750 void SvtPathOptions::SetAddinPath( const String& rPath )
751 {
752 	pImp->SetAddinPath( rPath );
753 }
754 
755 // -----------------------------------------------------------------------
756 
757 void SvtPathOptions::SetAutoCorrectPath( const String& rPath )
758 {
759 	pImp->SetAutoCorrectPath( rPath );
760 }
761 
762 // -----------------------------------------------------------------------
763 
764 void SvtPathOptions::SetAutoTextPath( const String& rPath )
765 {
766 	pImp->SetAutoTextPath( rPath );
767 }
768 
769 // -----------------------------------------------------------------------
770 
771 void SvtPathOptions::SetBackupPath( const String& rPath )
772 {
773 	pImp->SetBackupPath( rPath );
774 }
775 
776 // -----------------------------------------------------------------------
777 
778 void SvtPathOptions::SetBasicPath( const String& rPath )
779 {
780 	pImp->SetBasicPath( rPath );
781 }
782 
783 // -----------------------------------------------------------------------
784 
785 void SvtPathOptions::SetBitmapPath( const String& rPath )
786 {
787 	pImp->SetBitmapPath( rPath );
788 }
789 
790 // -----------------------------------------------------------------------
791 
792 void SvtPathOptions::SetConfigPath( const String& rPath )
793 {
794 	pImp->SetConfigPath( rPath );
795 }
796 
797 // -----------------------------------------------------------------------
798 
799 void SvtPathOptions::SetDictionaryPath( const String& rPath )
800 {
801 	pImp->SetDictionaryPath( rPath );
802 }
803 
804 // -----------------------------------------------------------------------
805 
806 void SvtPathOptions::SetFavoritesPath( const String& rPath )
807 {
808 	pImp->SetFavoritesPath( rPath );
809 }
810 
811 // -----------------------------------------------------------------------
812 
813 void SvtPathOptions::SetFilterPath( const String& rPath )
814 {
815 	pImp->SetFilterPath( rPath );
816 }
817 
818 // -----------------------------------------------------------------------
819 
820 void SvtPathOptions::SetGalleryPath( const String& rPath )
821 {
822 	pImp->SetGalleryPath( rPath );
823 }
824 
825 // -----------------------------------------------------------------------
826 
827 void SvtPathOptions::SetGraphicPath( const String& rPath )
828 {
829 	pImp->SetGraphicPath( rPath );
830 }
831 
832 // -----------------------------------------------------------------------
833 
834 void SvtPathOptions::SetHelpPath( const String& rPath )
835 {
836 	pImp->SetHelpPath( rPath );
837 }
838 
839 // -----------------------------------------------------------------------
840 
841 void SvtPathOptions::SetLinguisticPath( const String& rPath )
842 {
843 	pImp->SetLinguisticPath( rPath );
844 }
845 
846 // -----------------------------------------------------------------------
847 
848 void SvtPathOptions::SetModulePath( const String& rPath )
849 {
850 	pImp->SetModulePath( rPath );
851 }
852 
853 // -----------------------------------------------------------------------
854 
855 void SvtPathOptions::SetPalettePath( const String& rPath )
856 {
857 	pImp->SetPalettePath( rPath );
858 }
859 
860 // -----------------------------------------------------------------------
861 
862 void SvtPathOptions::SetPluginPath( const String& rPath )
863 {
864 	pImp->SetPluginPath( rPath );
865 }
866 
867 // -----------------------------------------------------------------------
868 
869 void SvtPathOptions::SetStoragePath( const String& rPath )
870 {
871 	pImp->SetStoragePath( rPath );
872 }
873 
874 // -----------------------------------------------------------------------
875 
876 void SvtPathOptions::SetTempPath( const String& rPath )
877 {
878 	pImp->SetTempPath( rPath );
879 }
880 
881 // -----------------------------------------------------------------------
882 
883 void SvtPathOptions::SetTemplatePath( const String& rPath )
884 {
885 	pImp->SetTemplatePath( rPath );
886 }
887 
888 // -----------------------------------------------------------------------
889 
890 void SvtPathOptions::SetUserConfigPath( const String& rPath )
891 {
892 	pImp->SetUserConfigPath( rPath );
893 }
894 
895 // -----------------------------------------------------------------------
896 
897 void SvtPathOptions::SetWorkPath( const String& rPath )
898 {
899 	pImp->SetWorkPath( rPath );
900 }
901 
902 // -----------------------------------------------------------------------
903 
904 String SvtPathOptions::SubstituteVariable( const String& rVar ) const
905 {
906     String aRet = pImp->SubstVar( rVar );
907 	return aRet;
908 }
909 
910 // -----------------------------------------------------------------------
911 
912 String SvtPathOptions::ExpandMacros( const String& rPath ) const
913 {
914     return pImp->ExpandMacros( rPath );
915 }
916 
917 // -----------------------------------------------------------------------
918 
919 String SvtPathOptions::UseVariable( const String& rPath ) const
920 {
921     String aRet = pImp->UsePathVariables( rPath );
922 	return aRet;
923 }
924 
925 // -----------------------------------------------------------------------
926 
927 sal_Bool SvtPathOptions::SearchFile( String& rIniFile, Pathes ePath )
928 {
929 	// check parameter: empty inifile name?
930 	if ( !rIniFile.Len() )
931 	{
932 		DBG_ERRORFILE( "SvtPathOptions::SearchFile(): invalid parameter" );
933 		return sal_False;
934 	}
935 
936     String aIniFile = pImp->SubstVar( rIniFile );
937 	sal_Bool bRet = sal_False;
938 
939 	switch ( ePath )
940 	{
941 		case PATH_USERCONFIG:
942 		{
943             // path is a URL
944 			bRet = sal_True;
945             INetURLObject aObj( GetUserConfigPath() );
946 			xub_StrLen i, nCount = aIniFile.GetTokenCount( '/' );
947 			for ( i = 0; i < nCount; ++i )
948 				aObj.insertName( aIniFile.GetToken( i, '/' ) );
949 
950             if ( !::utl::UCBContentHelper::Exists( aObj.GetMainURL( INetURLObject::NO_DECODE ) ) )
951 			{
952                 aObj.SetSmartURL( GetConfigPath() );
953 				aObj.insertName( aIniFile );
954                 bRet = ::utl::UCBContentHelper::Exists( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
955 			}
956 
957 			if ( bRet )
958 				rIniFile = aObj.GetMainURL( INetURLObject::NO_DECODE );
959 
960 			break;
961 		}
962 
963 		default:
964 		{
965 			String aPath;
966 			switch ( ePath )
967 			{
968 				case PATH_ADDIN:		aPath = GetAddinPath();			break;
969 				case PATH_AUTOCORRECT:	aPath = GetAutoCorrectPath();	break;
970 				case PATH_AUTOTEXT:		aPath = GetAutoTextPath();		break;
971 				case PATH_BACKUP:		aPath = GetBackupPath();		break;
972 				case PATH_BASIC:		aPath = GetBasicPath();			break;
973 				case PATH_BITMAP:		aPath = GetBitmapPath();		break;
974 				case PATH_CONFIG:		aPath = GetConfigPath();		break;
975 				case PATH_DICTIONARY:	aPath = GetDictionaryPath();	break;
976 				case PATH_FAVORITES:	aPath = GetFavoritesPath();		break;
977 				case PATH_FILTER:		aPath = GetFilterPath();		break;
978 				case PATH_GALLERY:		aPath = GetGalleryPath();		break;
979 				case PATH_GRAPHIC:		aPath = GetGraphicPath();		break;
980 				case PATH_HELP:			aPath = GetHelpPath();			break;
981 				case PATH_LINGUISTIC:	aPath = GetLinguisticPath();	break;
982 				case PATH_MODULE:		aPath = GetModulePath();		break;
983 				case PATH_PALETTE:		aPath = GetPalettePath();		break;
984 				case PATH_PLUGIN:		aPath = GetPluginPath();		break;
985 				case PATH_STORAGE:		aPath = GetStoragePath();		break;
986 				case PATH_TEMP:			aPath = GetTempPath();			break;
987 				case PATH_TEMPLATE:		aPath = GetTemplatePath();      break;
988 				case PATH_WORK:			aPath = GetWorkPath();			break;
989                 case PATH_UICONFIG:     aPath = GetUIConfigPath();      break;
990                 case PATH_FINGERPRINT:  aPath = GetFingerprintPath();   break;
991 				case PATH_USERCONFIG:/*-Wall???*/			break;
992                 case PATH_COUNT: /*-Wall???*/ break;
993 			}
994 
995 			sal_uInt16 j, nIdx = 0, nTokenCount = aPath.GetTokenCount( SEARCHPATH_DELIMITER );
996 			for ( j = 0; j < nTokenCount; ++j )
997 			{
998                 sal_Bool bIsURL = sal_True;
999 				String aPathToken = aPath.GetToken( 0, SEARCHPATH_DELIMITER, nIdx );
1000 				INetURLObject aObj( aPathToken );
1001 				if ( aObj.HasError() )
1002 				{
1003                     bIsURL = sal_False;
1004 					String aURL;
1005 					if ( LocalFileHelper::ConvertPhysicalNameToURL( aPathToken, aURL ) )
1006 						aObj.SetURL( aURL );
1007 				}
1008                 if ( aObj.GetProtocol() == INET_PROT_VND_SUN_STAR_EXPAND )
1009                 {
1010                     ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
1011                     Reference< XMacroExpander > xMacroExpander( aContext.getSingleton( "com.sun.star.util.theMacroExpander" ), UNO_QUERY );
1012                     OSL_ENSURE( xMacroExpander.is(), "SvtPathOptions::SearchFile: unable to access the MacroExpander singleton!" );
1013                     if ( xMacroExpander.is() )
1014                     {
1015                         const ::rtl::OUString sExpandedPath = xMacroExpander->expandMacros( aObj.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ) );
1016                         aObj.SetURL( sExpandedPath );
1017                     }
1018                 }
1019 
1020 				xub_StrLen i, nCount = aIniFile.GetTokenCount( '/' );
1021 				for ( i = 0; i < nCount; ++i )
1022 					aObj.insertName( aIniFile.GetToken( i, '/' ) );
1023                 bRet = ::utl::UCBContentHelper::Exists( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
1024 
1025 				if ( bRet )
1026 				{
1027                     if ( !bIsURL )
1028                         ::utl::LocalFileHelper::ConvertURLToPhysicalName(
1029 											aObj.GetMainURL( INetURLObject::NO_DECODE ), rIniFile );
1030 					else
1031 						rIniFile = aObj.GetMainURL( INetURLObject::NO_DECODE );
1032 					break;
1033 				}
1034 			}
1035 		}
1036 	}
1037 
1038 	return bRet;
1039 }
1040 
1041 // -----------------------------------------------------------------------
1042 
1043 ::com::sun::star::lang::Locale SvtPathOptions::GetLocale() const
1044 {
1045 	return pImp->GetLocale();
1046 }
1047 // -----------------------------------------------------------------------
1048 sal_Bool SvtPathOptions::IsPathReadonly(Pathes ePath)const
1049 {
1050     return pImp->IsPathReadonly(ePath);
1051 }
1052 // -----------------------------------------------------------------------
1053 const String& SvtPathOptions::GetPath(Pathes ePath)const
1054 {
1055     return pImp->GetPath(ePath);
1056 }
1057 // -----------------------------------------------------------------------
1058 void SvtPathOptions::SetPath( SvtPathOptions::Pathes ePath, const String& rNewPath )
1059 {
1060     pImp->SetPath(ePath, rNewPath);
1061 }
1062 
1063 // class PathService -----------------------------------------------------
1064 #include <com/sun/star/frame/XConfigManager.hpp>
1065 #include <com/sun/star/lang/XServiceInfo.hpp>
1066 #include <cppuhelper/implbase2.hxx>
1067 
1068 class PathService : public ::cppu::WeakImplHelper2< ::com::sun::star::frame::XConfigManager, ::com::sun::star::lang::XServiceInfo >
1069 {
1070     virtual ::rtl::OUString	SAL_CALL	getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
1071     virtual sal_Bool SAL_CALL			supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException);
1072     virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
1073 										getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);
1074     virtual ::rtl::OUString SAL_CALL	substituteVariables( const ::rtl::OUString& sText ) throw(::com::sun::star::uno::RuntimeException);
1075     virtual void SAL_CALL				addPropertyChangeListener( const ::rtl::OUString& sKeyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::uno::RuntimeException);
1076     virtual void SAL_CALL				removePropertyChangeListener( const ::rtl::OUString& sKeyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::uno::RuntimeException);
1077     virtual void SAL_CALL				flush(  ) throw(::com::sun::star::uno::RuntimeException);
1078 };
1079 
1080 // class PathService -----------------------------------------------------
1081 
1082 void SAL_CALL PathService::addPropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) throw(::com::sun::star::uno::RuntimeException) {}
1083 void SAL_CALL PathService::removePropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) throw(::com::sun::star::uno::RuntimeException) {}
1084 void SAL_CALL PathService::flush(  ) throw(::com::sun::star::uno::RuntimeException) {}
1085 
1086 ::rtl::OUString SAL_CALL PathService::substituteVariables( const ::rtl::OUString& sText ) throw(::com::sun::star::uno::RuntimeException)
1087 {
1088     return SvtPathOptions().SubstituteVariable( sText );
1089 }
1090 
1091 ::rtl::OUString SAL_CALL PathService::getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException)
1092 {
1093     return OUString::createFromAscii("com.sun.star.comp.unotools.PathService");
1094 }
1095 
1096 sal_Bool SAL_CALL PathService::supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException)
1097 {
1098     if ( ServiceName.compareToAscii("com.sun.star.config.SpecialConfigManager") == COMPARE_EQUAL )
1099         return sal_True;
1100     else
1101         return sal_False;
1102 }
1103 
1104 ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL PathService::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)
1105 {
1106     Sequence< OUString > aRet(1);
1107     *aRet.getArray() = OUString::createFromAscii("com.sun.star.config.SpecialConfigManager");
1108     return aRet;
1109 }
1110