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