xref: /aoo41x/main/sal/rtl/source/bootstrap.cxx (revision 79e556ee)
187d2adbcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
387d2adbcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
487d2adbcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
587d2adbcSAndrew Rist  * distributed with this work for additional information
687d2adbcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
787d2adbcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
887d2adbcSAndrew Rist  * "License"); you may not use this file except in compliance
987d2adbcSAndrew Rist  * with the License.  You may obtain a copy of the License at
1087d2adbcSAndrew Rist  *
1187d2adbcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1287d2adbcSAndrew Rist  *
1387d2adbcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1487d2adbcSAndrew Rist  * software distributed under the License is distributed on an
1587d2adbcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1687d2adbcSAndrew Rist  * KIND, either express or implied.  See the License for the
1787d2adbcSAndrew Rist  * specific language governing permissions and limitations
1887d2adbcSAndrew Rist  * under the License.
1987d2adbcSAndrew Rist  *
2087d2adbcSAndrew Rist  *************************************************************/
2187d2adbcSAndrew Rist 
2287d2adbcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sal.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "rtl/bootstrap.h"
28cdf0e10cSrcweir #include "rtl/bootstrap.hxx"
29cdf0e10cSrcweir #include <osl/diagnose.h>
30cdf0e10cSrcweir #include <osl/module.h>
31cdf0e10cSrcweir #include <osl/process.h>
32cdf0e10cSrcweir #include <osl/file.hxx>
33cdf0e10cSrcweir #include <osl/mutex.hxx>
34cdf0e10cSrcweir #include <osl/profile.hxx>
35cdf0e10cSrcweir #include <osl/security.hxx>
36cdf0e10cSrcweir #include <rtl/alloc.h>
37cdf0e10cSrcweir #include <rtl/string.hxx>
38cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
39cdf0e10cSrcweir #include <rtl/ustring.hxx>
40cdf0e10cSrcweir #include <rtl/byteseq.hxx>
41cdf0e10cSrcweir #include <rtl/instance.hxx>
42cdf0e10cSrcweir #include <rtl/malformeduriexception.hxx>
43cdf0e10cSrcweir #include <rtl/uri.hxx>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include "macro.hxx"
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <hash_map>
48cdf0e10cSrcweir #include <list>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #define MY_STRING_(x) # x
51cdf0e10cSrcweir #define MY_STRING(x) MY_STRING_(x)
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //----------------------------------------------------------------------------
54cdf0e10cSrcweir 
55cdf0e10cSrcweir using osl::DirectoryItem;
56cdf0e10cSrcweir using osl::FileStatus;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir using rtl::OString;
59cdf0e10cSrcweir using rtl::OUString;
60cdf0e10cSrcweir using rtl::OUStringToOString;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir struct Bootstrap_Impl;
63cdf0e10cSrcweir 
64cdf0e10cSrcweir namespace {
65cdf0e10cSrcweir 
66cdf0e10cSrcweir static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:";
67cdf0e10cSrcweir 
isPathnameUrl(rtl::OUString const & url)68cdf0e10cSrcweir bool isPathnameUrl(rtl::OUString const & url) {
69cdf0e10cSrcweir     return url.matchIgnoreAsciiCaseAsciiL(
70cdf0e10cSrcweir         RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME));
71cdf0e10cSrcweir }
72cdf0e10cSrcweir 
resolvePathnameUrl(rtl::OUString * url)73cdf0e10cSrcweir bool resolvePathnameUrl(rtl::OUString * url) {
74cdf0e10cSrcweir     OSL_ASSERT(url !=  NULL);
75cdf0e10cSrcweir     if (!isPathnameUrl(*url) ||
76cdf0e10cSrcweir         (osl::FileBase::getFileURLFromSystemPath(
77cdf0e10cSrcweir             url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)), *url) ==
78cdf0e10cSrcweir          osl::FileBase::E_None))
79cdf0e10cSrcweir     {
80cdf0e10cSrcweir         return true;
81cdf0e10cSrcweir     } else {
82cdf0e10cSrcweir         *url = rtl::OUString();
83cdf0e10cSrcweir         return false;
84cdf0e10cSrcweir     }
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir enum LookupMode {
88cdf0e10cSrcweir     LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP,
89cdf0e10cSrcweir     LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION };
90cdf0e10cSrcweir 
91cdf0e10cSrcweir struct ExpandRequestLink {
92cdf0e10cSrcweir     ExpandRequestLink const * next;
93cdf0e10cSrcweir     Bootstrap_Impl const * file;
94cdf0e10cSrcweir     rtl::OUString key;
95cdf0e10cSrcweir };
96cdf0e10cSrcweir 
97cdf0e10cSrcweir rtl::OUString expandMacros(
98cdf0e10cSrcweir     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
99cdf0e10cSrcweir     ExpandRequestLink const * requestStack);
100cdf0e10cSrcweir 
recursivelyExpandMacros(Bootstrap_Impl const * file,rtl::OUString const & text,LookupMode mode,Bootstrap_Impl const * requestFile,rtl::OUString const & requestKey,ExpandRequestLink const * requestStack)101cdf0e10cSrcweir rtl::OUString recursivelyExpandMacros(
102cdf0e10cSrcweir     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
103cdf0e10cSrcweir     Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
104cdf0e10cSrcweir     ExpandRequestLink const * requestStack)
105cdf0e10cSrcweir {
106cdf0e10cSrcweir     for (; requestStack != NULL; requestStack = requestStack->next) {
107cdf0e10cSrcweir         if (requestStack->file == requestFile &&
108cdf0e10cSrcweir             requestStack->key == requestKey)
109cdf0e10cSrcweir         {
110cdf0e10cSrcweir             return rtl::OUString(
111cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***"));
112cdf0e10cSrcweir         }
113cdf0e10cSrcweir     }
114cdf0e10cSrcweir     ExpandRequestLink link = { requestStack, requestFile, requestKey };
115cdf0e10cSrcweir     return expandMacros(file, text, mode, &link);
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir }
119cdf0e10cSrcweir 
120cdf0e10cSrcweir //----------------------------------------------------------------------------
121cdf0e10cSrcweir 
122cdf0e10cSrcweir struct rtl_bootstrap_NameValue
123cdf0e10cSrcweir {
124cdf0e10cSrcweir 	OUString sName;
125cdf0e10cSrcweir 	OUString sValue;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir     inline rtl_bootstrap_NameValue() SAL_THROW( () )
128cdf0e10cSrcweir         {}
rtl_bootstrap_NameValuertl_bootstrap_NameValue129cdf0e10cSrcweir     inline rtl_bootstrap_NameValue(
130cdf0e10cSrcweir         OUString const & name, OUString const & value ) SAL_THROW( () )
131cdf0e10cSrcweir         : sName( name ),
132cdf0e10cSrcweir           sValue( value )
133cdf0e10cSrcweir         {}
134cdf0e10cSrcweir };
135cdf0e10cSrcweir 
136*79e556eeSJuergen Schmidt typedef std::list<rtl_bootstrap_NameValue> NameValueList;
137cdf0e10cSrcweir 
find(NameValueList const & list,rtl::OUString const & key,rtl::OUString * value)138cdf0e10cSrcweir bool find(
139cdf0e10cSrcweir     NameValueList const & list, rtl::OUString const & key,
140cdf0e10cSrcweir     rtl::OUString * value)
141cdf0e10cSrcweir {
142cdf0e10cSrcweir     OSL_ASSERT(value != NULL);
143cdf0e10cSrcweir     for (NameValueList::const_iterator i(list.begin()); i != list.end(); ++i) {
144cdf0e10cSrcweir         if (i->sName == key) {
145cdf0e10cSrcweir             *value = i->sValue;
146cdf0e10cSrcweir             return true;
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir     return false;
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir namespace {
153cdf0e10cSrcweir 	struct rtl_bootstrap_set_list :
154cdf0e10cSrcweir 		public rtl::Static< NameValueList, rtl_bootstrap_set_list > {};
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir //----------------------------------------------------------------------------
158cdf0e10cSrcweir 
getFromCommandLineArgs(rtl::OUString const & key,rtl::OUString * value)159cdf0e10cSrcweir static sal_Bool getFromCommandLineArgs(
160cdf0e10cSrcweir 	rtl::OUString const & key, rtl::OUString * value )
161cdf0e10cSrcweir {
162cdf0e10cSrcweir     OSL_ASSERT(value != NULL);
163cdf0e10cSrcweir 	static NameValueList *pNameValueList = 0;
164cdf0e10cSrcweir 	if( ! pNameValueList )
165cdf0e10cSrcweir 	{
166cdf0e10cSrcweir 		static NameValueList nameValueList;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 		sal_Int32 nArgCount = osl_getCommandArgCount();
169cdf0e10cSrcweir 		for(sal_Int32 i = 0; i < nArgCount; ++ i)
170cdf0e10cSrcweir 		{
171cdf0e10cSrcweir 			rtl_uString *pArg = 0;
172cdf0e10cSrcweir 			osl_getCommandArg( i, &pArg );
173cdf0e10cSrcweir 			if( ('-' == pArg->buffer[0] || '/' == pArg->buffer[0] ) &&
174cdf0e10cSrcweir 				'e' == pArg->buffer[1] &&
175cdf0e10cSrcweir 				'n' == pArg->buffer[2] &&
176cdf0e10cSrcweir 				'v' == pArg->buffer[3] &&
177cdf0e10cSrcweir 				':' == pArg->buffer[4] )
178cdf0e10cSrcweir 			{
179cdf0e10cSrcweir 				sal_Int32 nIndex = rtl_ustr_indexOfChar( pArg->buffer, '=' );
180cdf0e10cSrcweir 				if( nIndex >= 0 )
181cdf0e10cSrcweir 				{
182cdf0e10cSrcweir 
183cdf0e10cSrcweir 					rtl_bootstrap_NameValue nameValue;
184cdf0e10cSrcweir 					nameValue.sName = OUString( &(pArg->buffer[5]), nIndex - 5  );
185cdf0e10cSrcweir 					nameValue.sValue = OUString( &(pArg->buffer[nIndex+1]) );
186cdf0e10cSrcweir 					if( i == nArgCount-1 &&
187cdf0e10cSrcweir 						nameValue.sValue.getLength() &&
188cdf0e10cSrcweir 						nameValue.sValue[nameValue.sValue.getLength()-1] == 13 )
189cdf0e10cSrcweir 					{
190cdf0e10cSrcweir 						// avoid the 13 linefeed for the last argument,
191cdf0e10cSrcweir 						// when the executable is started from a script,
192cdf0e10cSrcweir 						// that was edited on windows
193cdf0e10cSrcweir 						nameValue.sValue = nameValue.sValue.copy(0,nameValue.sValue.getLength()-1);
194cdf0e10cSrcweir 					}
195cdf0e10cSrcweir 					nameValueList.push_back( nameValue );
196cdf0e10cSrcweir 				}
197cdf0e10cSrcweir 			}
198cdf0e10cSrcweir 			rtl_uString_release( pArg );
199cdf0e10cSrcweir 		}
200cdf0e10cSrcweir 		pNameValueList = &nameValueList;
201cdf0e10cSrcweir 	}
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 	sal_Bool found = sal_False;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	for( NameValueList::iterator ii = pNameValueList->begin() ;
206cdf0e10cSrcweir 		 ii != pNameValueList->end() ;
207cdf0e10cSrcweir 		 ++ii )
208cdf0e10cSrcweir 	{
209cdf0e10cSrcweir 		if( (*ii).sName.equals(key) )
210cdf0e10cSrcweir 		{
211cdf0e10cSrcweir 			*value = (*ii).sValue;
212cdf0e10cSrcweir 			found = sal_True;
213cdf0e10cSrcweir 			break;
214cdf0e10cSrcweir 		}
215cdf0e10cSrcweir 	}
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 	return found;
218cdf0e10cSrcweir }
219cdf0e10cSrcweir 
220cdf0e10cSrcweir //----------------------------------------------------------------------------
221cdf0e10cSrcweir 
222cdf0e10cSrcweir extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
223cdf0e10cSrcweir 	rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C();
224cdf0e10cSrcweir 
getExecutableFile_Impl(rtl_uString ** ppFileURL)225cdf0e10cSrcweir inline void getExecutableFile_Impl (rtl_uString ** ppFileURL)
226cdf0e10cSrcweir {
227cdf0e10cSrcweir     osl_bootstrap_getExecutableFile_Impl (ppFileURL);
228cdf0e10cSrcweir }
229cdf0e10cSrcweir 
230cdf0e10cSrcweir //----------------------------------------------------------------------------
231cdf0e10cSrcweir 
getExecutableDirectory_Impl(rtl_uString ** ppDirURL)232cdf0e10cSrcweir static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
233cdf0e10cSrcweir {
234cdf0e10cSrcweir     OUString fileName;
235cdf0e10cSrcweir     getExecutableFile_Impl (&(fileName.pData));
236cdf0e10cSrcweir 
237cdf0e10cSrcweir     sal_Int32 nDirEnd = fileName.lastIndexOf('/');
238cdf0e10cSrcweir     OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
239cdf0e10cSrcweir 
240cdf0e10cSrcweir     rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd);
241cdf0e10cSrcweir }
242cdf0e10cSrcweir 
243cdf0e10cSrcweir //----------------------------------------------------------------------------
244cdf0e10cSrcweir 
getIniFileName_Impl()245cdf0e10cSrcweir static OUString & getIniFileName_Impl()
246cdf0e10cSrcweir {
247cdf0e10cSrcweir 	static OUString *pStaticName = 0;
248cdf0e10cSrcweir 	if( ! pStaticName )
249cdf0e10cSrcweir 	{
250cdf0e10cSrcweir 		OUString fileName;
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 		if(getFromCommandLineArgs(
253cdf0e10cSrcweir                OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")), &fileName))
254cdf0e10cSrcweir         {
255cdf0e10cSrcweir             resolvePathnameUrl(&fileName);
256cdf0e10cSrcweir         }
257cdf0e10cSrcweir         else
258cdf0e10cSrcweir 		{
259cdf0e10cSrcweir 			getExecutableFile_Impl (&(fileName.pData));
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 			// get rid of a potential executable extension
262cdf0e10cSrcweir 			OUString progExt (RTL_CONSTASCII_USTRINGPARAM(".bin"));
263cdf0e10cSrcweir 			if(fileName.getLength() > progExt.getLength()
264cdf0e10cSrcweir 		    && fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
265cdf0e10cSrcweir 				fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());
266cdf0e10cSrcweir 
267cdf0e10cSrcweir 			progExt = OUString::createFromAscii(".exe");
268cdf0e10cSrcweir 			if(fileName.getLength() > progExt.getLength()
269cdf0e10cSrcweir 			&& fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
270cdf0e10cSrcweir 				fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 			// append config file suffix
273cdf0e10cSrcweir 			fileName += OUString(RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE("")));
274cdf0e10cSrcweir 		}
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 		static OUString theFileName;
277cdf0e10cSrcweir 		if(fileName.getLength())
278cdf0e10cSrcweir 			theFileName = fileName;
279cdf0e10cSrcweir 
280cdf0e10cSrcweir 		pStaticName = &theFileName;
281cdf0e10cSrcweir 	}
282cdf0e10cSrcweir 
283cdf0e10cSrcweir 	return *pStaticName;
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir //----------------------------------------------------------------------------
287cdf0e10cSrcweir 
path_exists(OUString const & path)288cdf0e10cSrcweir static inline bool path_exists( OUString const & path )
289cdf0e10cSrcweir {
290cdf0e10cSrcweir     DirectoryItem dirItem;
291cdf0e10cSrcweir     return (DirectoryItem::E_None == DirectoryItem::get( path, dirItem ));
292cdf0e10cSrcweir }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir //----------------------------------------------------------------------------
295cdf0e10cSrcweir // #111772#
296cdf0e10cSrcweir // ensure the given file url has no final slash
297cdf0e10cSrcweir 
EnsureNoFinalSlash(rtl::OUString & url)298cdf0e10cSrcweir inline void EnsureNoFinalSlash (rtl::OUString & url)
299cdf0e10cSrcweir {
300cdf0e10cSrcweir     sal_Int32 i = url.getLength();
301cdf0e10cSrcweir     if (i > 0 && url[i - 1] == '/') {
302cdf0e10cSrcweir         url = url.copy(0, i - 1);
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir //----------------------------------------------------------------------------
307cdf0e10cSrcweir //----------------------------------------------------------------------------
308cdf0e10cSrcweir 
309cdf0e10cSrcweir struct Bootstrap_Impl
310cdf0e10cSrcweir {
311cdf0e10cSrcweir     sal_Int32 _nRefCount;
312cdf0e10cSrcweir     Bootstrap_Impl * _base_ini;
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 	NameValueList _nameValueList;
315cdf0e10cSrcweir 	OUString      _iniName;
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 	explicit Bootstrap_Impl (OUString const & rIniName);
318cdf0e10cSrcweir 	~Bootstrap_Impl();
319cdf0e10cSrcweir 
operator newBootstrap_Impl320cdf0e10cSrcweir 	static void * operator new (std::size_t n) SAL_THROW(())
321cdf0e10cSrcweir         { return rtl_allocateMemory (sal_uInt32(n)); }
operator deleteBootstrap_Impl322cdf0e10cSrcweir 	static void operator delete (void * p , std::size_t) SAL_THROW(())
323cdf0e10cSrcweir         { rtl_freeMemory (p); }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir     bool getValue(
326cdf0e10cSrcweir         rtl::OUString const & key, rtl_uString ** value,
327cdf0e10cSrcweir         rtl_uString * defaultValue, LookupMode mode, bool override,
328cdf0e10cSrcweir         ExpandRequestLink const * requestStack) const;
329cdf0e10cSrcweir     bool getDirectValue(
330cdf0e10cSrcweir         rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
331cdf0e10cSrcweir         ExpandRequestLink const * requestStack) const;
332cdf0e10cSrcweir     bool getAmbienceValue(
333cdf0e10cSrcweir         rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
334cdf0e10cSrcweir         ExpandRequestLink const * requestStack) const;
335cdf0e10cSrcweir     void expandValue(
336cdf0e10cSrcweir         rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
337cdf0e10cSrcweir         Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
338cdf0e10cSrcweir         ExpandRequestLink const * requestStack) const;
339cdf0e10cSrcweir };
340cdf0e10cSrcweir 
341cdf0e10cSrcweir //----------------------------------------------------------------------------
342cdf0e10cSrcweir 
Bootstrap_Impl(OUString const & rIniName)343cdf0e10cSrcweir Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName )
344cdf0e10cSrcweir 	: _nRefCount( 0 ),
345cdf0e10cSrcweir       _base_ini( 0 ),
346cdf0e10cSrcweir       _iniName (rIniName)
347cdf0e10cSrcweir {
348cdf0e10cSrcweir     OUString base_ini( getIniFileName_Impl() );
349cdf0e10cSrcweir     // normalize path
350cdf0e10cSrcweir     FileStatus status( FileStatusMask_FileURL );
351cdf0e10cSrcweir     DirectoryItem dirItem;
352cdf0e10cSrcweir     if (DirectoryItem::E_None == DirectoryItem::get( base_ini, dirItem ) &&
353cdf0e10cSrcweir         DirectoryItem::E_None == dirItem.getFileStatus( status ))
354cdf0e10cSrcweir     {
355cdf0e10cSrcweir         base_ini = status.getFileURL();
356cdf0e10cSrcweir         if (! rIniName.equals( base_ini ))
357cdf0e10cSrcweir         {
358cdf0e10cSrcweir             _base_ini = static_cast< Bootstrap_Impl * >(
359cdf0e10cSrcweir                 rtl_bootstrap_args_open( base_ini.pData ) );
360cdf0e10cSrcweir         }
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
364cdf0e10cSrcweir 	OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
365cdf0e10cSrcweir 	OSL_TRACE(__FILE__" -- Bootstrap_Impl() - %s\n", sFile.getStr());
366cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL > 1 */
367cdf0e10cSrcweir 
368cdf0e10cSrcweir 	oslFileHandle handle;
369cdf0e10cSrcweir 	if (_iniName.getLength() &&
370cdf0e10cSrcweir         osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read))
371cdf0e10cSrcweir 	{
372cdf0e10cSrcweir 		rtl::ByteSequence seq;
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 		while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq))
375cdf0e10cSrcweir 		{
376cdf0e10cSrcweir 			OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
377cdf0e10cSrcweir 			sal_Int32 nIndex = line.indexOf('=');
378cdf0e10cSrcweir 			if (nIndex >= 1)
379cdf0e10cSrcweir 			{
380cdf0e10cSrcweir 				struct rtl_bootstrap_NameValue nameValue;
381cdf0e10cSrcweir 				nameValue.sName = OStringToOUString(
382cdf0e10cSrcweir                     line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US );
383cdf0e10cSrcweir 				nameValue.sValue = OStringToOUString(
384cdf0e10cSrcweir                     line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 );
385cdf0e10cSrcweir 
386cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
387cdf0e10cSrcweir 				OString name_tmp = OUStringToOString(nameValue.sName, RTL_TEXTENCODING_ASCII_US);
388cdf0e10cSrcweir 				OString value_tmp = OUStringToOString(nameValue.sValue, RTL_TEXTENCODING_UTF8);
389cdf0e10cSrcweir 				OSL_TRACE(
390cdf0e10cSrcweir                     __FILE__" -- pushing: name=%s value=%s\n",
391cdf0e10cSrcweir                     name_tmp.getStr(), value_tmp.getStr() );
392cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL > 1 */
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 				_nameValueList.push_back(nameValue);
395cdf0e10cSrcweir 			}
396cdf0e10cSrcweir 		}
397cdf0e10cSrcweir 		osl_closeFile(handle);
398cdf0e10cSrcweir 	}
399cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
400cdf0e10cSrcweir 	else
401cdf0e10cSrcweir 	{
402cdf0e10cSrcweir 		OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
403cdf0e10cSrcweir 		OSL_TRACE( __FILE__" -- couldn't open file: %s", file_tmp.getStr() );
404cdf0e10cSrcweir 	}
405cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL > 1 */
406cdf0e10cSrcweir }
407cdf0e10cSrcweir 
408cdf0e10cSrcweir //----------------------------------------------------------------------------
409cdf0e10cSrcweir 
~Bootstrap_Impl()410cdf0e10cSrcweir Bootstrap_Impl::~Bootstrap_Impl()
411cdf0e10cSrcweir {
412cdf0e10cSrcweir     if (_base_ini != 0)
413cdf0e10cSrcweir         rtl_bootstrap_args_close( _base_ini );
414cdf0e10cSrcweir }
415cdf0e10cSrcweir 
416cdf0e10cSrcweir //----------------------------------------------------------------------------
417cdf0e10cSrcweir 
418cdf0e10cSrcweir namespace {
419cdf0e10cSrcweir 
get_static_bootstrap_handle()420cdf0e10cSrcweir Bootstrap_Impl * get_static_bootstrap_handle() SAL_THROW(())
421cdf0e10cSrcweir {
422cdf0e10cSrcweir 	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
423cdf0e10cSrcweir     static Bootstrap_Impl * s_handle = 0;
424cdf0e10cSrcweir     if (s_handle == 0)
425cdf0e10cSrcweir     {
426cdf0e10cSrcweir 		OUString iniName (getIniFileName_Impl());
427cdf0e10cSrcweir         s_handle = static_cast< Bootstrap_Impl * >(
428cdf0e10cSrcweir             rtl_bootstrap_args_open( iniName.pData ) );
429cdf0e10cSrcweir         if (s_handle == 0)
430cdf0e10cSrcweir         {
431cdf0e10cSrcweir             Bootstrap_Impl * that = new Bootstrap_Impl( iniName );
432cdf0e10cSrcweir             ++that->_nRefCount;
433cdf0e10cSrcweir             s_handle = that;
434cdf0e10cSrcweir         }
435cdf0e10cSrcweir     }
436cdf0e10cSrcweir     return s_handle;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir struct FundamentalIniData {
440cdf0e10cSrcweir     rtlBootstrapHandle ini;
441cdf0e10cSrcweir 
FundamentalIniData__anonab9480a50311::FundamentalIniData442cdf0e10cSrcweir     FundamentalIniData() {
443cdf0e10cSrcweir         OUString uri;
444cdf0e10cSrcweir         ini =
445cdf0e10cSrcweir             ((static_cast< Bootstrap_Impl * >(get_static_bootstrap_handle())->
446cdf0e10cSrcweir               getValue(
447cdf0e10cSrcweir                   rtl::OUString(
448cdf0e10cSrcweir                       RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")),
449cdf0e10cSrcweir                   &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0)) &&
450cdf0e10cSrcweir              resolvePathnameUrl(&uri))
451cdf0e10cSrcweir             ? rtl_bootstrap_args_open(uri.pData) : NULL;
452cdf0e10cSrcweir     }
453cdf0e10cSrcweir 
~FundamentalIniData__anonab9480a50311::FundamentalIniData454cdf0e10cSrcweir     ~FundamentalIniData() { rtl_bootstrap_args_close(ini); }
455cdf0e10cSrcweir 
456cdf0e10cSrcweir private:
457cdf0e10cSrcweir     FundamentalIniData(FundamentalIniData &); // not defined
458cdf0e10cSrcweir     void operator =(FundamentalIniData &); // not defined
459cdf0e10cSrcweir };
460cdf0e10cSrcweir 
461cdf0e10cSrcweir struct FundamentalIni: public rtl::Static< FundamentalIniData, FundamentalIni >
462cdf0e10cSrcweir {};
463cdf0e10cSrcweir 
464cdf0e10cSrcweir }
465cdf0e10cSrcweir 
getValue(rtl::OUString const & key,rtl_uString ** value,rtl_uString * defaultValue,LookupMode mode,bool override,ExpandRequestLink const * requestStack) const466cdf0e10cSrcweir bool Bootstrap_Impl::getValue(
467cdf0e10cSrcweir     rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue,
468cdf0e10cSrcweir     LookupMode mode, bool override, ExpandRequestLink const * requestStack)
469cdf0e10cSrcweir     const
470cdf0e10cSrcweir {
471cdf0e10cSrcweir     if (mode == LOOKUP_MODE_NORMAL &&
472cdf0e10cSrcweir         key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP")))
473cdf0e10cSrcweir     {
474cdf0e10cSrcweir         mode = LOOKUP_MODE_URE_BOOTSTRAP;
475cdf0e10cSrcweir     }
476cdf0e10cSrcweir     if (override && getDirectValue(key, value, mode, requestStack)) {
477cdf0e10cSrcweir         return true;
478cdf0e10cSrcweir     }
479cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_OS"))) {
480cdf0e10cSrcweir         rtl_uString_assign(
481cdf0e10cSrcweir             value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_OS)).pData);
482cdf0e10cSrcweir         return true;
483cdf0e10cSrcweir     }
484cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_ARCH"))) {
485cdf0e10cSrcweir         rtl_uString_assign(
486cdf0e10cSrcweir             value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_ARCH)).pData);
487cdf0e10cSrcweir         return true;
488cdf0e10cSrcweir     }
489cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_CPPU_ENV"))) {
490cdf0e10cSrcweir         rtl_uString_assign(
491cdf0e10cSrcweir             value,
492cdf0e10cSrcweir             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))).
493cdf0e10cSrcweir              pData));
494cdf0e10cSrcweir         return true;
495cdf0e10cSrcweir     }
496cdf0e10cSrcweir     if (key.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ORIGIN"))) {
497cdf0e10cSrcweir         rtl_uString_assign(
498cdf0e10cSrcweir             value,
499cdf0e10cSrcweir             _iniName.copy(
500cdf0e10cSrcweir                 0, std::max<sal_Int32>(0, _iniName.lastIndexOf('/'))).pData);
501cdf0e10cSrcweir         return true;
502cdf0e10cSrcweir     }
503cdf0e10cSrcweir     if (getAmbienceValue(key, value, mode, requestStack)) {
504cdf0e10cSrcweir         return true;
505cdf0e10cSrcweir     }
506cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERCONFIG"))) {
507cdf0e10cSrcweir         rtl::OUString v;
508cdf0e10cSrcweir         bool b = osl::Security().getConfigDir(v);
509cdf0e10cSrcweir         EnsureNoFinalSlash(v);
510cdf0e10cSrcweir         rtl_uString_assign(value, v.pData);
511cdf0e10cSrcweir         return b;
512cdf0e10cSrcweir     }
513cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERHOME"))) {
514cdf0e10cSrcweir         rtl::OUString v;
515cdf0e10cSrcweir         bool b = osl::Security().getHomeDir(v);
516cdf0e10cSrcweir         EnsureNoFinalSlash(v);
517cdf0e10cSrcweir         rtl_uString_assign(value, v.pData);
518cdf0e10cSrcweir         return b;
519cdf0e10cSrcweir     }
520cdf0e10cSrcweir     if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSBINDIR"))) {
521cdf0e10cSrcweir         getExecutableDirectory_Impl(value);
522cdf0e10cSrcweir         return true;
523cdf0e10cSrcweir     }
524cdf0e10cSrcweir     if (_base_ini != NULL &&
525cdf0e10cSrcweir         _base_ini->getDirectValue(key, value, mode, requestStack))
526cdf0e10cSrcweir     {
527cdf0e10cSrcweir         return true;
528cdf0e10cSrcweir     }
529cdf0e10cSrcweir     if (!override && getDirectValue(key, value, mode, requestStack)) {
530cdf0e10cSrcweir         return true;
531cdf0e10cSrcweir     }
532cdf0e10cSrcweir     if (mode == LOOKUP_MODE_NORMAL) {
533cdf0e10cSrcweir         FundamentalIniData const & d = FundamentalIni::get();
534cdf0e10cSrcweir         Bootstrap_Impl const * b = static_cast<Bootstrap_Impl const *>(d.ini);
535cdf0e10cSrcweir         if (b != NULL && b != this &&
536cdf0e10cSrcweir             b->getDirectValue(key, value, mode, requestStack))
537cdf0e10cSrcweir         {
538cdf0e10cSrcweir             return true;
539cdf0e10cSrcweir         }
540cdf0e10cSrcweir     }
541cdf0e10cSrcweir     if (defaultValue != NULL) {
542cdf0e10cSrcweir         rtl_uString_assign(value, defaultValue);
543cdf0e10cSrcweir         return true;
544cdf0e10cSrcweir     }
545cdf0e10cSrcweir     rtl_uString_new(value);
546cdf0e10cSrcweir     return false;
547cdf0e10cSrcweir }
548cdf0e10cSrcweir 
getDirectValue(rtl::OUString const & key,rtl_uString ** value,LookupMode mode,ExpandRequestLink const * requestStack) const549cdf0e10cSrcweir bool Bootstrap_Impl::getDirectValue(
550cdf0e10cSrcweir     rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
551cdf0e10cSrcweir     ExpandRequestLink const * requestStack) const
552cdf0e10cSrcweir {
553cdf0e10cSrcweir     rtl::OUString v;
554cdf0e10cSrcweir     if (find(_nameValueList, key, &v)) {
555cdf0e10cSrcweir         expandValue(value, v, mode, this, key, requestStack);
556cdf0e10cSrcweir         return true;
557cdf0e10cSrcweir     } else {
558cdf0e10cSrcweir         return false;
559cdf0e10cSrcweir     }
560cdf0e10cSrcweir }
561cdf0e10cSrcweir 
getAmbienceValue(rtl::OUString const & key,rtl_uString ** value,LookupMode mode,ExpandRequestLink const * requestStack) const562cdf0e10cSrcweir bool Bootstrap_Impl::getAmbienceValue(
563cdf0e10cSrcweir     rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
564cdf0e10cSrcweir     ExpandRequestLink const * requestStack) const
565cdf0e10cSrcweir {
566cdf0e10cSrcweir     rtl::OUString v;
567cdf0e10cSrcweir     bool f;
568cdf0e10cSrcweir     {
569cdf0e10cSrcweir         osl::MutexGuard g(osl::Mutex::getGlobalMutex());
570cdf0e10cSrcweir         f = find(rtl_bootstrap_set_list::get(), key, &v);
571cdf0e10cSrcweir     }
572cdf0e10cSrcweir     if (f || getFromCommandLineArgs(key, &v) ||
573cdf0e10cSrcweir         osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None)
574cdf0e10cSrcweir     {
575cdf0e10cSrcweir         expandValue(value, v, mode, NULL, key, requestStack);
576cdf0e10cSrcweir         return true;
577cdf0e10cSrcweir     } else {
578cdf0e10cSrcweir         return false;
579cdf0e10cSrcweir     }
580cdf0e10cSrcweir }
581cdf0e10cSrcweir 
expandValue(rtl_uString ** value,rtl::OUString const & text,LookupMode mode,Bootstrap_Impl const * requestFile,rtl::OUString const & requestKey,ExpandRequestLink const * requestStack) const582cdf0e10cSrcweir void Bootstrap_Impl::expandValue(
583cdf0e10cSrcweir     rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
584cdf0e10cSrcweir     Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
585cdf0e10cSrcweir     ExpandRequestLink const * requestStack) const
586cdf0e10cSrcweir {
587cdf0e10cSrcweir     rtl_uString_assign(
588cdf0e10cSrcweir         value,
589cdf0e10cSrcweir         (mode == LOOKUP_MODE_URE_BOOTSTRAP && isPathnameUrl(text) ?
590cdf0e10cSrcweir          text :
591cdf0e10cSrcweir          recursivelyExpandMacros(
592cdf0e10cSrcweir              this, text,
593cdf0e10cSrcweir              (mode == LOOKUP_MODE_URE_BOOTSTRAP ?
594cdf0e10cSrcweir               LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION : mode),
595cdf0e10cSrcweir              requestFile, requestKey, requestStack)).pData);
596cdf0e10cSrcweir }
597cdf0e10cSrcweir 
598cdf0e10cSrcweir //----------------------------------------------------------------------------
599cdf0e10cSrcweir //----------------------------------------------------------------------------
600cdf0e10cSrcweir 
601cdf0e10cSrcweir namespace {
602cdf0e10cSrcweir 
603cdf0e10cSrcweir struct bootstrap_map {
604*79e556eeSJuergen Schmidt     typedef std::hash_map< const rtl::OUString, Bootstrap_Impl*, rtl::OUStringHash > t;
605cdf0e10cSrcweir 
606cdf0e10cSrcweir     // get and release must only be called properly synchronized via some mutex
607cdf0e10cSrcweir     // (e.g., osl::Mutex::getGlobalMutex()):
608cdf0e10cSrcweir 
get__anonab9480a50411::bootstrap_map609cdf0e10cSrcweir     static t * get() {
610cdf0e10cSrcweir         if (m_map == NULL) {
611cdf0e10cSrcweir             m_map = new t;
612cdf0e10cSrcweir         }
613cdf0e10cSrcweir         return m_map;
614cdf0e10cSrcweir     }
615cdf0e10cSrcweir 
release__anonab9480a50411::bootstrap_map616cdf0e10cSrcweir     static void release() {
617cdf0e10cSrcweir         if (m_map != NULL && m_map->empty()) {
618cdf0e10cSrcweir             delete m_map;
619cdf0e10cSrcweir             m_map = NULL;
620cdf0e10cSrcweir         }
621cdf0e10cSrcweir     }
622cdf0e10cSrcweir 
623cdf0e10cSrcweir private:
624cdf0e10cSrcweir     bootstrap_map(); // not defined
625cdf0e10cSrcweir 
626cdf0e10cSrcweir     static t * m_map;
627cdf0e10cSrcweir };
628cdf0e10cSrcweir 
629cdf0e10cSrcweir bootstrap_map::t * bootstrap_map::m_map = NULL;
630cdf0e10cSrcweir 
631cdf0e10cSrcweir }
632cdf0e10cSrcweir 
633cdf0e10cSrcweir //----------------------------------------------------------------------------
634cdf0e10cSrcweir 
rtl_bootstrap_args_open(rtl_uString * pIniName)635cdf0e10cSrcweir rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
636cdf0e10cSrcweir 	rtl_uString * pIniName
637cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
638cdf0e10cSrcweir {
639cdf0e10cSrcweir 	OUString iniName( pIniName );
640cdf0e10cSrcweir 
641cdf0e10cSrcweir     // normalize path
642cdf0e10cSrcweir     FileStatus status( FileStatusMask_FileURL );
643cdf0e10cSrcweir     DirectoryItem dirItem;
644cdf0e10cSrcweir     if (DirectoryItem::E_None != DirectoryItem::get( iniName, dirItem ) ||
645cdf0e10cSrcweir         DirectoryItem::E_None != dirItem.getFileStatus( status ))
646cdf0e10cSrcweir     {
647cdf0e10cSrcweir         return 0;
648cdf0e10cSrcweir     }
649cdf0e10cSrcweir     iniName = status.getFileURL();
650cdf0e10cSrcweir 
651cdf0e10cSrcweir     Bootstrap_Impl * that;
652cdf0e10cSrcweir     osl::ResettableMutexGuard guard( osl::Mutex::getGlobalMutex() );
653cdf0e10cSrcweir     bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
654cdf0e10cSrcweir     bootstrap_map::t::const_iterator iFind( p_bootstrap_map->find( iniName ) );
655cdf0e10cSrcweir     if (iFind == p_bootstrap_map->end())
656cdf0e10cSrcweir     {
657cdf0e10cSrcweir         bootstrap_map::release();
658cdf0e10cSrcweir         guard.clear();
659cdf0e10cSrcweir         that = new Bootstrap_Impl( iniName );
660cdf0e10cSrcweir         guard.reset();
661cdf0e10cSrcweir         p_bootstrap_map = bootstrap_map::get();
662cdf0e10cSrcweir         iFind = p_bootstrap_map->find( iniName );
663cdf0e10cSrcweir         if (iFind == p_bootstrap_map->end())
664cdf0e10cSrcweir         {
665cdf0e10cSrcweir             ++that->_nRefCount;
666cdf0e10cSrcweir             ::std::pair< bootstrap_map::t::iterator, bool > insertion(
667cdf0e10cSrcweir                 p_bootstrap_map->insert(
668cdf0e10cSrcweir                     bootstrap_map::t::value_type( iniName, that ) ) );
669cdf0e10cSrcweir             OSL_ASSERT( insertion.second );
670cdf0e10cSrcweir         }
671cdf0e10cSrcweir         else
672cdf0e10cSrcweir         {
673cdf0e10cSrcweir             Bootstrap_Impl * obsolete = that;
674cdf0e10cSrcweir             that = iFind->second;
675cdf0e10cSrcweir             ++that->_nRefCount;
676cdf0e10cSrcweir             guard.clear();
677cdf0e10cSrcweir             delete obsolete;
678cdf0e10cSrcweir         }
679cdf0e10cSrcweir     }
680cdf0e10cSrcweir     else
681cdf0e10cSrcweir     {
682cdf0e10cSrcweir         that = iFind->second;
683cdf0e10cSrcweir         ++that->_nRefCount;
684cdf0e10cSrcweir     }
685cdf0e10cSrcweir 	return static_cast< rtlBootstrapHandle >( that );
686cdf0e10cSrcweir }
687cdf0e10cSrcweir 
688cdf0e10cSrcweir //----------------------------------------------------------------------------
689cdf0e10cSrcweir 
rtl_bootstrap_args_close(rtlBootstrapHandle handle)690cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_args_close (
691cdf0e10cSrcweir 	rtlBootstrapHandle handle
692cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
693cdf0e10cSrcweir {
694cdf0e10cSrcweir     if (handle == 0)
695cdf0e10cSrcweir         return;
696cdf0e10cSrcweir     Bootstrap_Impl * that = static_cast< Bootstrap_Impl * >( handle );
697cdf0e10cSrcweir 
698cdf0e10cSrcweir     osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
699cdf0e10cSrcweir     bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
700cdf0e10cSrcweir     OSL_ASSERT(
701cdf0e10cSrcweir         p_bootstrap_map->find( that->_iniName )->second == that );
702cdf0e10cSrcweir     --that->_nRefCount;
703cdf0e10cSrcweir     if (that->_nRefCount == 0)
704cdf0e10cSrcweir     {
705cdf0e10cSrcweir         ::std::size_t nLeaking = 8; // only hold up to 8 files statically
706cdf0e10cSrcweir 
707cdf0e10cSrcweir #if OSL_DEBUG_LEVEL == 1 // nonpro
708cdf0e10cSrcweir         nLeaking = 0;
709cdf0e10cSrcweir #elif OSL_DEBUG_LEVEL > 1 // debug
710cdf0e10cSrcweir         nLeaking = 1;
711cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */
712cdf0e10cSrcweir 
713cdf0e10cSrcweir         if (p_bootstrap_map->size() > nLeaking)
714cdf0e10cSrcweir         {
715cdf0e10cSrcweir             ::std::size_t erased = p_bootstrap_map->erase( that->_iniName );
716cdf0e10cSrcweir             if (erased != 1) {
717cdf0e10cSrcweir                 OSL_ASSERT( false );
718cdf0e10cSrcweir             }
719cdf0e10cSrcweir             delete that;
720cdf0e10cSrcweir         }
721cdf0e10cSrcweir         bootstrap_map::release();
722cdf0e10cSrcweir     }
723cdf0e10cSrcweir }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir //----------------------------------------------------------------------------
726cdf0e10cSrcweir 
rtl_bootstrap_get_from_handle(rtlBootstrapHandle handle,rtl_uString * pName,rtl_uString ** ppValue,rtl_uString * pDefault)727cdf0e10cSrcweir sal_Bool SAL_CALL rtl_bootstrap_get_from_handle(
728cdf0e10cSrcweir     rtlBootstrapHandle handle,
729cdf0e10cSrcweir 	rtl_uString      * pName,
730cdf0e10cSrcweir 	rtl_uString     ** ppValue,
731cdf0e10cSrcweir     rtl_uString      * pDefault
732cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
733cdf0e10cSrcweir {
734cdf0e10cSrcweir 	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
735cdf0e10cSrcweir 
736cdf0e10cSrcweir 	sal_Bool found = sal_False;
737cdf0e10cSrcweir 	if(ppValue && pName)
738cdf0e10cSrcweir 	{
739cdf0e10cSrcweir 		if (handle == 0)
740cdf0e10cSrcweir             handle = get_static_bootstrap_handle();
741cdf0e10cSrcweir         found = static_cast< Bootstrap_Impl * >( handle )->getValue(
742cdf0e10cSrcweir             pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, NULL );
743cdf0e10cSrcweir 	}
744cdf0e10cSrcweir 
745cdf0e10cSrcweir 	return found;
746cdf0e10cSrcweir }
747cdf0e10cSrcweir 
748cdf0e10cSrcweir //----------------------------------------------------------------------------
749cdf0e10cSrcweir 
rtl_bootstrap_get_iniName_from_handle(rtlBootstrapHandle handle,rtl_uString ** ppIniName)750cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
751cdf0e10cSrcweir     rtlBootstrapHandle handle,
752cdf0e10cSrcweir 	rtl_uString     ** ppIniName
753cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
754cdf0e10cSrcweir {
755cdf0e10cSrcweir 	if(ppIniName)
756cdf0e10cSrcweir     {
757cdf0e10cSrcweir 		if(handle)
758cdf0e10cSrcweir         {
759cdf0e10cSrcweir 			Bootstrap_Impl * pImpl = static_cast<Bootstrap_Impl*>(handle);
760cdf0e10cSrcweir 			rtl_uString_assign(ppIniName, pImpl->_iniName.pData);
761cdf0e10cSrcweir         }
762cdf0e10cSrcweir 		else
763cdf0e10cSrcweir         {
764cdf0e10cSrcweir 			const OUString & iniName = getIniFileName_Impl();
765cdf0e10cSrcweir 			rtl_uString_assign(ppIniName, iniName.pData);
766cdf0e10cSrcweir 		}
767cdf0e10cSrcweir     }
768cdf0e10cSrcweir }
769cdf0e10cSrcweir 
770cdf0e10cSrcweir //----------------------------------------------------------------------------
771cdf0e10cSrcweir 
rtl_bootstrap_setIniFileName(rtl_uString * pName)772cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_setIniFileName (
773cdf0e10cSrcweir 	rtl_uString * pName
774cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
775cdf0e10cSrcweir {
776cdf0e10cSrcweir 	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
777cdf0e10cSrcweir 	OUString & file = getIniFileName_Impl();
778cdf0e10cSrcweir 	file = pName;
779cdf0e10cSrcweir }
780cdf0e10cSrcweir 
781cdf0e10cSrcweir //----------------------------------------------------------------------------
782cdf0e10cSrcweir 
rtl_bootstrap_get(rtl_uString * pName,rtl_uString ** ppValue,rtl_uString * pDefault)783cdf0e10cSrcweir sal_Bool SAL_CALL rtl_bootstrap_get (
784cdf0e10cSrcweir     rtl_uString  * pName,
785cdf0e10cSrcweir 	rtl_uString ** ppValue,
786cdf0e10cSrcweir 	rtl_uString  * pDefault
787cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
788cdf0e10cSrcweir {
789cdf0e10cSrcweir 	return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault);
790cdf0e10cSrcweir }
791cdf0e10cSrcweir 
792cdf0e10cSrcweir //----------------------------------------------------------------------------
793cdf0e10cSrcweir 
rtl_bootstrap_set(rtl_uString * pName,rtl_uString * pValue)794cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_set (
795cdf0e10cSrcweir 	rtl_uString * pName,
796cdf0e10cSrcweir 	rtl_uString * pValue
797cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
798cdf0e10cSrcweir {
799cdf0e10cSrcweir     const OUString name( pName );
800cdf0e10cSrcweir     const OUString value( pValue );
801cdf0e10cSrcweir 
802cdf0e10cSrcweir     osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
803cdf0e10cSrcweir 
804cdf0e10cSrcweir     NameValueList& r_rtl_bootstrap_set_list = rtl_bootstrap_set_list::get();
805cdf0e10cSrcweir     NameValueList::iterator iPos( r_rtl_bootstrap_set_list.begin() );
806cdf0e10cSrcweir     NameValueList::iterator iEnd( r_rtl_bootstrap_set_list.end() );
807cdf0e10cSrcweir     for ( ; iPos != iEnd; ++iPos )
808cdf0e10cSrcweir     {
809cdf0e10cSrcweir         if (iPos->sName.equals( name ))
810cdf0e10cSrcweir         {
811cdf0e10cSrcweir             iPos->sValue = value;
812cdf0e10cSrcweir             return;
813cdf0e10cSrcweir         }
814cdf0e10cSrcweir     }
815cdf0e10cSrcweir 
816cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
817cdf0e10cSrcweir     OString cstr_name( OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ) );
818cdf0e10cSrcweir     OString cstr_value( OUStringToOString( value, RTL_TEXTENCODING_ASCII_US ) );
819cdf0e10cSrcweir     OSL_TRACE(
820cdf0e10cSrcweir         "bootstrap.cxx: explicitly setting: name=%s value=%s\n",
821cdf0e10cSrcweir         cstr_name.getStr(), cstr_value.getStr() );
822cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL > 1 */
823cdf0e10cSrcweir 
824cdf0e10cSrcweir     r_rtl_bootstrap_set_list.push_back( rtl_bootstrap_NameValue( name, value ) );
825cdf0e10cSrcweir }
826cdf0e10cSrcweir 
827cdf0e10cSrcweir //----------------------------------------------------------------------------
828cdf0e10cSrcweir 
rtl_bootstrap_expandMacros_from_handle(rtlBootstrapHandle handle,rtl_uString ** macro)829cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
830cdf0e10cSrcweir     rtlBootstrapHandle handle,
831cdf0e10cSrcweir 	rtl_uString     ** macro
832cdf0e10cSrcweir ) SAL_THROW_EXTERN_C()
833cdf0e10cSrcweir {
834cdf0e10cSrcweir     if (handle == NULL) {
835cdf0e10cSrcweir         handle = get_static_bootstrap_handle();
836cdf0e10cSrcweir     }
837cdf0e10cSrcweir     OUString expanded( expandMacros( static_cast< Bootstrap_Impl * >( handle ),
838cdf0e10cSrcweir 									 * reinterpret_cast< OUString const * >( macro ),
839cdf0e10cSrcweir                                      LOOKUP_MODE_NORMAL, NULL ) );
840cdf0e10cSrcweir     rtl_uString_assign( macro, expanded.pData );
841cdf0e10cSrcweir }
842cdf0e10cSrcweir 
843cdf0e10cSrcweir //----------------------------------------------------------------------------
844cdf0e10cSrcweir 
rtl_bootstrap_expandMacros(rtl_uString ** macro)845cdf0e10cSrcweir void SAL_CALL rtl_bootstrap_expandMacros(
846cdf0e10cSrcweir     rtl_uString ** macro )
847cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
848cdf0e10cSrcweir {
849cdf0e10cSrcweir     rtl_bootstrap_expandMacros_from_handle(NULL, macro);
850cdf0e10cSrcweir }
851cdf0e10cSrcweir 
rtl_bootstrap_encode(rtl_uString const * value,rtl_uString ** encoded)852cdf0e10cSrcweir void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded )
853cdf0e10cSrcweir     SAL_THROW_EXTERN_C()
854cdf0e10cSrcweir {
855cdf0e10cSrcweir     OSL_ASSERT(value != NULL);
856cdf0e10cSrcweir     rtl::OUStringBuffer b;
857cdf0e10cSrcweir     for (sal_Int32 i = 0; i < value->length; ++i) {
858cdf0e10cSrcweir         sal_Unicode c = value->buffer[i];
859cdf0e10cSrcweir         if (c == '$' || c == '\\') {
860cdf0e10cSrcweir             b.append(sal_Unicode('\\'));
861cdf0e10cSrcweir         }
862cdf0e10cSrcweir         b.append(c);
863cdf0e10cSrcweir     }
864cdf0e10cSrcweir     rtl_uString_assign(encoded, b.makeStringAndClear().pData);
865cdf0e10cSrcweir }
866cdf0e10cSrcweir 
867cdf0e10cSrcweir namespace {
868cdf0e10cSrcweir 
hex(sal_Unicode c)869cdf0e10cSrcweir int hex(sal_Unicode c) {
870cdf0e10cSrcweir     return
871cdf0e10cSrcweir         c >= '0' && c <= '9' ? c - '0' :
872cdf0e10cSrcweir         c >= 'A' && c <= 'F' ? c - 'A' + 10 :
873cdf0e10cSrcweir         c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
874cdf0e10cSrcweir }
875cdf0e10cSrcweir 
read(rtl::OUString const & text,sal_Int32 * pos,bool * escaped)876cdf0e10cSrcweir sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
877cdf0e10cSrcweir     OSL_ASSERT(
878cdf0e10cSrcweir         pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL);
879cdf0e10cSrcweir     sal_Unicode c = text[(*pos)++];
880cdf0e10cSrcweir     if (c == '\\') {
881cdf0e10cSrcweir         int n1, n2, n3, n4;
882cdf0e10cSrcweir         if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
883cdf0e10cSrcweir             ((n1 = hex(text[*pos + 1])) >= 0) &&
884cdf0e10cSrcweir             ((n2 = hex(text[*pos + 2])) >= 0) &&
885cdf0e10cSrcweir             ((n3 = hex(text[*pos + 3])) >= 0) &&
886cdf0e10cSrcweir             ((n4 = hex(text[*pos + 4])) >= 0))
887cdf0e10cSrcweir         {
888cdf0e10cSrcweir             *pos += 5;
889cdf0e10cSrcweir             *escaped = true;
890cdf0e10cSrcweir             return static_cast< sal_Unicode >(
891cdf0e10cSrcweir                 (n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
892cdf0e10cSrcweir         } else if (*pos < text.getLength()) {
893cdf0e10cSrcweir             *escaped = true;
894cdf0e10cSrcweir             return text[(*pos)++];
895cdf0e10cSrcweir         }
896cdf0e10cSrcweir     }
897cdf0e10cSrcweir     *escaped = false;
898cdf0e10cSrcweir     return c;
899cdf0e10cSrcweir }
900cdf0e10cSrcweir 
lookup(Bootstrap_Impl const * file,LookupMode mode,bool override,rtl::OUString const & key,ExpandRequestLink const * requestStack)901cdf0e10cSrcweir rtl::OUString lookup(
902cdf0e10cSrcweir     Bootstrap_Impl const * file, LookupMode mode, bool override,
903cdf0e10cSrcweir     rtl::OUString const & key, ExpandRequestLink const * requestStack)
904cdf0e10cSrcweir {
905cdf0e10cSrcweir     rtl::OUString v;
906cdf0e10cSrcweir     (file == NULL ? get_static_bootstrap_handle() : file)->getValue(
907cdf0e10cSrcweir         key, &v.pData, NULL, mode, override, requestStack);
908cdf0e10cSrcweir     return v;
909cdf0e10cSrcweir }
910cdf0e10cSrcweir 
expandMacros(Bootstrap_Impl const * file,rtl::OUString const & text,LookupMode mode,ExpandRequestLink const * requestStack)911cdf0e10cSrcweir rtl::OUString expandMacros(
912cdf0e10cSrcweir     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
913cdf0e10cSrcweir     ExpandRequestLink const * requestStack)
914cdf0e10cSrcweir {
915cdf0e10cSrcweir     rtl::OUStringBuffer buf;
916cdf0e10cSrcweir     for (sal_Int32 i = 0; i < text.getLength();) {
917cdf0e10cSrcweir         bool escaped;
918cdf0e10cSrcweir         sal_Unicode c = read(text, &i, &escaped);
919cdf0e10cSrcweir         if (escaped || c != '$') {
920cdf0e10cSrcweir             buf.append(c);
921cdf0e10cSrcweir         } else {
922cdf0e10cSrcweir             if (i < text.getLength() && text[i] == '{') {
923cdf0e10cSrcweir                 ++i;
924cdf0e10cSrcweir                 sal_Int32 p = i;
925cdf0e10cSrcweir                 sal_Int32 nesting = 0;
926cdf0e10cSrcweir                 rtl::OUString seg[3];
927cdf0e10cSrcweir                 int n = 0;
928cdf0e10cSrcweir                 while (i < text.getLength()) {
929cdf0e10cSrcweir                     sal_Int32 j = i;
930cdf0e10cSrcweir                     c = read(text, &i, &escaped);
931cdf0e10cSrcweir                     if (!escaped) {
932cdf0e10cSrcweir                         switch (c) {
933cdf0e10cSrcweir                         case '{':
934cdf0e10cSrcweir                             ++nesting;
935cdf0e10cSrcweir                             break;
936cdf0e10cSrcweir                         case '}':
937cdf0e10cSrcweir                             if (nesting == 0) {
938cdf0e10cSrcweir                                 seg[n++] = text.copy(p, j - p);
939cdf0e10cSrcweir                                 goto done;
940cdf0e10cSrcweir                             } else {
941cdf0e10cSrcweir                                 --nesting;
942cdf0e10cSrcweir                             }
943cdf0e10cSrcweir                             break;
944cdf0e10cSrcweir                         case ':':
945cdf0e10cSrcweir                             if (nesting == 0 && n < 2) {
946cdf0e10cSrcweir                                 seg[n++] = text.copy(p, j - p);
947cdf0e10cSrcweir                                 p = i;
948cdf0e10cSrcweir                             }
949cdf0e10cSrcweir                             break;
950cdf0e10cSrcweir                         }
951cdf0e10cSrcweir                     }
952cdf0e10cSrcweir                 }
953cdf0e10cSrcweir             done:
954cdf0e10cSrcweir                 for (int j = 0; j < n; ++j) {
955cdf0e10cSrcweir                     seg[j] = expandMacros(file, seg[j], mode, requestStack);
956cdf0e10cSrcweir                 }
957cdf0e10cSrcweir                 if (n == 3 && seg[1].getLength() == 0) {
958cdf0e10cSrcweir                     // For backward compatibility, treat ${file::key} the same
959cdf0e10cSrcweir                     // as just ${file:key}:
960cdf0e10cSrcweir                     seg[1] = seg[2];
961cdf0e10cSrcweir                     n = 2;
962cdf0e10cSrcweir                 }
963cdf0e10cSrcweir                 if (n == 1) {
964cdf0e10cSrcweir                     buf.append(lookup(file, mode, false, seg[0], requestStack));
965cdf0e10cSrcweir                 } else if (n == 2) {
966cdf0e10cSrcweir                     if (seg[0].equalsAsciiL(
967cdf0e10cSrcweir                             RTL_CONSTASCII_STRINGPARAM(".link")))
968cdf0e10cSrcweir                     {
969cdf0e10cSrcweir                         osl::File f(seg[1]);
970cdf0e10cSrcweir                         rtl::ByteSequence seq;
971cdf0e10cSrcweir                         rtl::OUString line;
972cdf0e10cSrcweir                         rtl::OUString url;
973cdf0e10cSrcweir                         // Silently ignore any errors (is that good?):
974cdf0e10cSrcweir                         if (f.open(OpenFlag_Read) == osl::FileBase::E_None &&
975cdf0e10cSrcweir                             f.readLine(seq) == osl::FileBase::E_None &&
976cdf0e10cSrcweir                             rtl_convertStringToUString(
977cdf0e10cSrcweir                                 &line.pData,
978cdf0e10cSrcweir                                 reinterpret_cast< char const * >(
979cdf0e10cSrcweir                                     seq.getConstArray()),
980cdf0e10cSrcweir                                 seq.getLength(), RTL_TEXTENCODING_UTF8,
981cdf0e10cSrcweir                                 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
982cdf0e10cSrcweir                                  RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
983cdf0e10cSrcweir                                  RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) &&
984cdf0e10cSrcweir                             (osl::File::getFileURLFromSystemPath(line, url) ==
985cdf0e10cSrcweir                              osl::FileBase::E_None))
986cdf0e10cSrcweir                         {
987cdf0e10cSrcweir                             try {
988cdf0e10cSrcweir                                 buf.append(
989cdf0e10cSrcweir                                     rtl::Uri::convertRelToAbs(seg[1], url));
990cdf0e10cSrcweir                             } catch (rtl::MalformedUriException &) {}
991cdf0e10cSrcweir                         }
992cdf0e10cSrcweir                     } else {
993cdf0e10cSrcweir                         buf.append(
994cdf0e10cSrcweir                             lookup(
995cdf0e10cSrcweir                                 static_cast< Bootstrap_Impl * >(
996cdf0e10cSrcweir                                     rtl::Bootstrap(seg[0]).getHandle()),
997cdf0e10cSrcweir                                 mode, false, seg[1], requestStack));
998cdf0e10cSrcweir                     }
999cdf0e10cSrcweir                 } else if (seg[0].equalsAsciiL(
1000cdf0e10cSrcweir                                RTL_CONSTASCII_STRINGPARAM(".override")))
1001cdf0e10cSrcweir                 {
1002cdf0e10cSrcweir                     rtl::Bootstrap b(seg[1]);
1003cdf0e10cSrcweir                     Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
1004cdf0e10cSrcweir                         b.getHandle());
1005cdf0e10cSrcweir                     buf.append(
1006cdf0e10cSrcweir                         lookup(f, mode, f != NULL, seg[2], requestStack));
1007cdf0e10cSrcweir                 } else {
1008cdf0e10cSrcweir                     // Going through osl::Profile, this code erroneously does
1009cdf0e10cSrcweir                     // not recursively expand macros in the resulting
1010cdf0e10cSrcweir                     // replacement text (and if it did, it would fail to detect
1011cdf0e10cSrcweir                     // cycles that pass through here):
1012cdf0e10cSrcweir                     buf.append(
1013cdf0e10cSrcweir                         rtl::OStringToOUString(
1014cdf0e10cSrcweir                             osl::Profile(seg[0]).readString(
1015cdf0e10cSrcweir                                 rtl::OUStringToOString(
1016cdf0e10cSrcweir                                     seg[1], RTL_TEXTENCODING_UTF8),
1017cdf0e10cSrcweir                                 rtl::OUStringToOString(
1018cdf0e10cSrcweir                                     seg[2], RTL_TEXTENCODING_UTF8),
1019cdf0e10cSrcweir                                 rtl::OString()),
1020cdf0e10cSrcweir                             RTL_TEXTENCODING_UTF8));
1021cdf0e10cSrcweir                 }
1022cdf0e10cSrcweir             } else {
1023cdf0e10cSrcweir                 rtl::OUStringBuffer kbuf;
1024cdf0e10cSrcweir                 for (; i < text.getLength();) {
1025cdf0e10cSrcweir                     sal_Int32 j = i;
1026cdf0e10cSrcweir                     c = read(text, &j, &escaped);
1027cdf0e10cSrcweir                     if (!escaped &&
1028cdf0e10cSrcweir                         (c == ' ' || c == '$' || c == '-' || c == '/' ||
1029cdf0e10cSrcweir                          c == ';' || c == '\\'))
1030cdf0e10cSrcweir                     {
1031cdf0e10cSrcweir                         break;
1032cdf0e10cSrcweir                     }
1033cdf0e10cSrcweir                     kbuf.append(c);
1034cdf0e10cSrcweir                     i = j;
1035cdf0e10cSrcweir                 }
1036cdf0e10cSrcweir                 buf.append(
1037cdf0e10cSrcweir                     lookup(
1038cdf0e10cSrcweir                         file, mode, false, kbuf.makeStringAndClear(),
1039cdf0e10cSrcweir                         requestStack));
1040cdf0e10cSrcweir             }
1041cdf0e10cSrcweir         }
1042cdf0e10cSrcweir     }
1043cdf0e10cSrcweir     return buf.makeStringAndClear();
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir }
1047