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