/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "boost/noncopyable.hpp" #include "rtl/bootstrap.h" #include "rtl/bootstrap.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rtl/allocator.hxx" #include "macro.hxx" #include #include #include #include #define MY_STRING_(x) # x #define MY_STRING(x) MY_STRING_(x) extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl( rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C(); using osl::DirectoryItem; using osl::FileStatus; using rtl::OString; using rtl::OUString; using rtl::OUStringToOString; struct Bootstrap_Impl; namespace { static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:"; bool isPathnameUrl(rtl::OUString const & url) { return url.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME)); } bool resolvePathnameUrl(rtl::OUString * url) { OSL_ASSERT(url != NULL); if (!isPathnameUrl(*url) || (osl::FileBase::getFileURLFromSystemPath( url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)), *url) == osl::FileBase::E_None)) { return true; } else { *url = rtl::OUString(); return false; } } enum LookupMode { LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP, LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION }; struct ExpandRequestLink { ExpandRequestLink const * next; Bootstrap_Impl const * file; rtl::OUString key; }; rtl::OUString expandMacros( Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode, ExpandRequestLink const * requestStack); rtl::OUString recursivelyExpandMacros( Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode, Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey, ExpandRequestLink const * requestStack) { for (; requestStack != NULL; requestStack = requestStack->next) { if (requestStack->file == requestFile && requestStack->key == requestKey) { return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***")); } } ExpandRequestLink link = { requestStack, requestFile, requestKey }; return expandMacros(file, text, mode, &link); } class ParameterMap: private boost::noncopyable { public: bool get(rtl::OUString const & key, rtl::OUString * value) const; protected: ParameterMap() {} ~ParameterMap() {} typedef std::map< rtl::OUString, rtl::OUString > Map; Map map_; }; bool ParameterMap::get(rtl::OUString const & key, rtl::OUString * value) const { OSL_ASSERT(value != 0); Map::const_iterator i(map_.find(key)); if (i == map_.end()) { return false; } else { *value = i->second; return true; } } class ExplicitParameterMap: public ParameterMap { public: bool get(rtl::OUString const & key, rtl::OUString * value) const; void set(rtl::OUString const & key, rtl::OUString const & value); private: mutable osl::Mutex mutex_; }; bool ExplicitParameterMap::get(rtl::OUString const & key, rtl::OUString * value) const { osl::MutexGuard g(mutex_); return ParameterMap::get(key, value); } void ExplicitParameterMap::set( rtl::OUString const & key, rtl::OUString const & value) { osl::MutexGuard g(mutex_); map_[key] = value; } struct ExplicitParameters: public rtl::Static< ExplicitParameterMap, ExplicitParameters > {}; class CommandLineParameterMap: public ParameterMap { public: CommandLineParameterMap(); }; CommandLineParameterMap::CommandLineParameterMap() { sal_uInt32 n = osl_getCommandArgCount(); for (sal_uInt32 i = 0; i != n; ++i) { rtl::OUString s; osl_getCommandArg(i, &s.pData); static char const PREFIX[] = "-env:"; if (s.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))) { sal_Int32 j = s.indexOf('=', RTL_CONSTASCII_LENGTH(PREFIX)); rtl::OUString k( s.copy( RTL_CONSTASCII_LENGTH(PREFIX), ((j < 0 ? s.getLength() : j) - RTL_CONSTASCII_LENGTH(PREFIX)))); if (j < 0) { map_.erase(s.copy(RTL_CONSTASCII_LENGTH(PREFIX))); } else { map_[ s.copy( RTL_CONSTASCII_LENGTH(PREFIX), j - RTL_CONSTASCII_LENGTH(PREFIX))] = s.copy(j + 1); } } } } struct CommandLineParameters: public rtl::Static< CommandLineParameterMap, CommandLineParameters > {}; } static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL) { OUString fileName; osl_bootstrap_getExecutableFile_Impl (&(fileName.pData)); sal_Int32 nDirEnd = fileName.lastIndexOf('/'); OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory"); rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd); } static inline bool path_exists( OUString const & path ) { DirectoryItem dirItem; return (DirectoryItem::E_None == DirectoryItem::get( path, dirItem )); } //---------------------------------------------------------------------------- // #111772# // ensure the given file url has no final slash inline void EnsureNoFinalSlash (rtl::OUString & url) { sal_Int32 i = url.getLength(); if (i > 0 && url[i - 1] == '/') { url = url.copy(0, i - 1); } } struct Bootstrap_Impl: private ParameterMap { OUString _iniName; explicit Bootstrap_Impl (OUString const & rIniName); bool getValue( rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue, LookupMode mode, bool override, ExpandRequestLink const * requestStack) const; bool getDirectValue( rtl::OUString const & key, rtl_uString ** value, LookupMode mode, ExpandRequestLink const * requestStack) const; bool getAmbienceValue( rtl::OUString const & key, rtl_uString ** value, LookupMode mode, ExpandRequestLink const * requestStack) const; void expandValue( rtl_uString ** value, rtl::OUString const & text, LookupMode mode, Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey, ExpandRequestLink const * requestStack) const; }; //---------------------------------------------------------------------------- Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName ) : _iniName (rIniName) { #if OSL_DEBUG_LEVEL > 1 OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US); OSL_TRACE(__FILE__" -- Bootstrap_Impl() - %s\n", sFile.getStr()); #endif /* OSL_DEBUG_LEVEL > 1 */ oslFileHandle handle; if (_iniName.getLength() && osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read)) { rtl::ByteSequence seq; while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq)) { OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() ); sal_Int32 nIndex = line.indexOf('='); if (nIndex >= 1) { rtl::OUString sName = OStringToOUString( line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US ); rtl::OUString sValue = OStringToOUString( line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 ); #if OSL_DEBUG_LEVEL > 1 OString name_tmp = OUStringToOString(sName, RTL_TEXTENCODING_ASCII_US); OString value_tmp = OUStringToOString(sValue, RTL_TEXTENCODING_UTF8); OSL_TRACE( __FILE__" -- pushing: name=%s value=%s\n", name_tmp.getStr(), value_tmp.getStr() ); #endif /* OSL_DEBUG_LEVEL > 1 */ map_[sName] = sValue; } } osl_closeFile(handle); } #if OSL_DEBUG_LEVEL > 1 else { OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US); OSL_TRACE( __FILE__" -- couldn't open file: %s", file_tmp.getStr() ); } #endif /* OSL_DEBUG_LEVEL > 1 */ } namespace { class BootstrapMap: private boost::noncopyable { public: BootstrapMap(); ~BootstrapMap(); Bootstrap_Impl * getIni(rtl::OUString const & uri, bool alwaysCreate); void setBaseIniUri(rtl::OUString const & uri); Bootstrap_Impl * getBaseIni(); Bootstrap_Impl * getFundamentalIni(); private: typedef std::map< rtl::OUString, Bootstrap_Impl * > Map; osl::Mutex mutex_; Map map_; rtl::OUString baseIniUri_; Bootstrap_Impl * baseIni_; bool hasFundamentalIni_; Bootstrap_Impl * fundamentalIni_; }; BootstrapMap::BootstrapMap(): baseIni_(0), hasFundamentalIni_(false), fundamentalIni_(0) {} BootstrapMap::~BootstrapMap() { for (Map::iterator i(map_.begin()); i != map_.end(); ++i) { delete i->second; } } Bootstrap_Impl * BootstrapMap::getIni( rtl::OUString const & uri, bool alwaysCreate) { rtl::OUString normUri; // normalize URI if possible DirectoryItem dirItem; FileStatus status(osl_FileStatus_Mask_FileURL); if (DirectoryItem::get(uri, dirItem) == DirectoryItem::E_None && dirItem.getFileStatus(status) == DirectoryItem::E_None) { normUri = status.getFileURL(); } else if (alwaysCreate) { normUri = uri; } else { return 0; } osl::MutexGuard g(mutex_); Map::iterator i(map_.find(normUri)); if (i == map_.end()) { std::auto_ptr< Bootstrap_Impl > b(new Bootstrap_Impl(normUri)); std::pair< Map::iterator, bool > ins( map_.insert(Map::value_type(normUri, b.get()))); b.release(); OSL_ASSERT(ins.second); i = ins.first; } return i->second; } void BootstrapMap::setBaseIniUri(rtl::OUString const & uri) { OSL_ASSERT(uri.getLength() != 0); osl::MutexGuard g(mutex_); OSL_ASSERT(baseIniUri_.getLength() == 0 && baseIni_ == 0); baseIniUri_ = uri; } Bootstrap_Impl * BootstrapMap::getBaseIni() { osl::MutexGuard g(mutex_); if (baseIni_ == 0) { rtl::OUString uri; if (baseIniUri_.getLength() == 0) { if (CommandLineParameters::get().get( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")), &uri)) { resolvePathnameUrl(&uri); } else { osl_bootstrap_getExecutableFile_Impl(&uri.pData); // Strip potentially two such extensions, to allow for // renaming of soffice.bin to soffice.bin.exe so that // Visual Studio agrees to start it, if you want to // debug it from the start. static char const BIN_EXT[] = ".bin"; static char const EXE_EXT[] = ".exe"; for (int i = 0; i < 2; i++) { if (uri.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(BIN_EXT))) { uri = uri.copy( 0, uri.getLength() - RTL_CONSTASCII_LENGTH(BIN_EXT)); } else if (uri.endsWithAsciiL( RTL_CONSTASCII_STRINGPARAM(EXE_EXT))) { uri = uri.copy( 0, uri.getLength() - RTL_CONSTASCII_LENGTH(EXE_EXT)); } } uri += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE(""))); } } else { uri = baseIniUri_; } baseIni_ = getIni(uri, true); } return baseIni_; } Bootstrap_Impl * BootstrapMap::getFundamentalIni() { osl::MutexGuard g(mutex_); if (!hasFundamentalIni_) { rtl::OUString uri; fundamentalIni_ = (getBaseIni()->getValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")), &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0) && resolvePathnameUrl(&uri)) ? getIni(uri, false) : 0; hasFundamentalIni_ = true; } return fundamentalIni_; } struct BootstrapMapSingleton: public rtl::Static< BootstrapMap, BootstrapMapSingleton > {}; } bool Bootstrap_Impl::getValue( rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue, LookupMode mode, bool override, ExpandRequestLink const * requestStack) const { if (mode == LOOKUP_MODE_NORMAL && key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP"))) { mode = LOOKUP_MODE_URE_BOOTSTRAP; } if (override && getDirectValue(key, value, mode, requestStack)) { return true; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_OS"))) { rtl_uString_assign( value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_OS)).pData); return true; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_ARCH"))) { rtl_uString_assign( value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_ARCH)).pData); return true; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_CPPU_ENV"))) { rtl_uString_assign( value, (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))). pData)); return true; } if (key.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ORIGIN"))) { rtl_uString_assign( value, _iniName.copy( 0, std::max(0, _iniName.lastIndexOf('/'))).pData); return true; } if (getAmbienceValue(key, value, mode, requestStack)) { return true; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERCONFIG"))) { rtl::OUString v; bool b = osl::Security().getConfigDir(v); EnsureNoFinalSlash(v); rtl_uString_assign(value, v.pData); return b; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERHOME"))) { rtl::OUString v; bool b = osl::Security().getHomeDir(v); EnsureNoFinalSlash(v); rtl_uString_assign(value, v.pData); return b; } if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSBINDIR"))) { getExecutableDirectory_Impl(value); return true; } Bootstrap_Impl * b = BootstrapMapSingleton::get().getBaseIni(); if (b != this && b->getDirectValue(key, value, mode, requestStack)) { return true; } if (!override && getDirectValue(key, value, mode, requestStack)) { return true; } if (mode == LOOKUP_MODE_NORMAL) { b = BootstrapMapSingleton::get().getFundamentalIni(); if (b != 0 && b != this && b->getDirectValue(key, value, mode, requestStack)) { return true; } } if (defaultValue != NULL) { rtl_uString_assign(value, defaultValue); return true; } rtl_uString_new(value); return false; } bool Bootstrap_Impl::getDirectValue( rtl::OUString const & key, rtl_uString ** value, LookupMode mode, ExpandRequestLink const * requestStack) const { rtl::OUString v; if (get(key, &v)) { expandValue(value, v, mode, this, key, requestStack); return true; } else { return false; } } bool Bootstrap_Impl::getAmbienceValue( rtl::OUString const & key, rtl_uString ** value, LookupMode mode, ExpandRequestLink const * requestStack) const { rtl::OUString v; if (ExplicitParameters::get().get(key, &v) || CommandLineParameters::get().get(key, &v) || osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None) { expandValue(value, v, mode, NULL, key, requestStack); return true; } else { return false; } } void Bootstrap_Impl::expandValue( rtl_uString ** value, rtl::OUString const & text, LookupMode mode, Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey, ExpandRequestLink const * requestStack) const { rtl_uString_assign( value, (mode == LOOKUP_MODE_URE_BOOTSTRAP && isPathnameUrl(text) ? text : recursivelyExpandMacros( this, text, (mode == LOOKUP_MODE_URE_BOOTSTRAP ? LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION : mode), requestFile, requestKey, requestStack)).pData); } rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open ( rtl_uString * pIniName ) SAL_THROW_EXTERN_C() { return BootstrapMapSingleton::get().getIni(rtl::OUString(pIniName), false); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_args_close ( rtlBootstrapHandle ) SAL_THROW_EXTERN_C() { // do nothing; the BootstrapMap::map_ just keeps growing for now } //---------------------------------------------------------------------------- sal_Bool SAL_CALL rtl_bootstrap_get_from_handle( rtlBootstrapHandle handle, rtl_uString * pName, rtl_uString ** ppValue, rtl_uString * pDefault ) SAL_THROW_EXTERN_C() { return (handle == 0 ? BootstrapMapSingleton::get().getBaseIni() : static_cast< Bootstrap_Impl * >(handle))-> getValue(pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, 0); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_get_iniName_from_handle ( rtlBootstrapHandle handle, rtl_uString ** ppIniName ) SAL_THROW_EXTERN_C() { rtl_uString_assign( ppIniName, ((handle == 0 ? BootstrapMapSingleton::get().getBaseIni() : static_cast(handle))-> _iniName.pData)); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_setIniFileName ( rtl_uString * pName ) SAL_THROW_EXTERN_C() { BootstrapMapSingleton::get().setBaseIniUri(rtl::OUString(pName)); } //---------------------------------------------------------------------------- sal_Bool SAL_CALL rtl_bootstrap_get ( rtl_uString * pName, rtl_uString ** ppValue, rtl_uString * pDefault ) SAL_THROW_EXTERN_C() { return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_set ( rtl_uString * pName, rtl_uString * pValue ) SAL_THROW_EXTERN_C() { ExplicitParameters::get().set(rtl::OUString(pName), rtl::OUString(pValue)); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_expandMacros_from_handle ( rtlBootstrapHandle handle, rtl_uString ** macro ) SAL_THROW_EXTERN_C() { rtl::OUString expanded( expandMacros( (handle == 0 ? BootstrapMapSingleton::get().getBaseIni() : static_cast< Bootstrap_Impl * >(handle)), *reinterpret_cast< OUString const * >(macro), LOOKUP_MODE_NORMAL, 0)); rtl_uString_assign(macro, expanded.pData); } //---------------------------------------------------------------------------- void SAL_CALL rtl_bootstrap_expandMacros( rtl_uString ** macro ) SAL_THROW_EXTERN_C() { rtl_bootstrap_expandMacros_from_handle(NULL, macro); } void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded ) SAL_THROW_EXTERN_C() { OSL_ASSERT(value != NULL); rtl::OUStringBuffer b; for (sal_Int32 i = 0; i < value->length; ++i) { sal_Unicode c = value->buffer[i]; if (c == '$' || c == '\\') { b.append(sal_Unicode('\\')); } b.append(c); } rtl_uString_assign(encoded, b.makeStringAndClear().pData); } namespace { int hex(sal_Unicode c) { return c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F' ? c - 'A' + 10 : c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1; } sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) { OSL_ASSERT( pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL); sal_Unicode c = text[(*pos)++]; if (c == '\\') { int n1, n2, n3, n4; if (*pos < text.getLength() - 4 && text[*pos] == 'u' && ((n1 = hex(text[*pos + 1])) >= 0) && ((n2 = hex(text[*pos + 2])) >= 0) && ((n3 = hex(text[*pos + 3])) >= 0) && ((n4 = hex(text[*pos + 4])) >= 0)) { *pos += 5; *escaped = true; return static_cast< sal_Unicode >( (n1 << 12) | (n2 << 8) | (n3 << 4) | n4); } else if (*pos < text.getLength()) { *escaped = true; return text[(*pos)++]; } } *escaped = false; return c; } rtl::OUString lookup( Bootstrap_Impl const * file, LookupMode mode, bool override, rtl::OUString const & key, ExpandRequestLink const * requestStack) { rtl::OUString v; (file == 0 ? BootstrapMapSingleton::get().getBaseIni() : file)->getValue( key, &v.pData, NULL, mode, override, requestStack); return v; } rtl::OUString expandMacros( Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode, ExpandRequestLink const * requestStack) { rtl::OUStringBuffer buf; for (sal_Int32 i = 0; i < text.getLength();) { bool escaped; sal_Unicode c = read(text, &i, &escaped); if (escaped || c != '$') { buf.append(c); } else { if (i < text.getLength() && text[i] == '{') { ++i; sal_Int32 p = i; sal_Int32 nesting = 0; rtl::OUString seg[3]; int n = 0; while (i < text.getLength()) { sal_Int32 j = i; c = read(text, &i, &escaped); if (!escaped) { switch (c) { case '{': ++nesting; break; case '}': if (nesting == 0) { seg[n++] = text.copy(p, j - p); goto done; } else { --nesting; } break; case ':': if (nesting == 0 && n < 2) { seg[n++] = text.copy(p, j - p); p = i; } break; } } } done: for (int j = 0; j < n; ++j) { seg[j] = expandMacros(file, seg[j], mode, requestStack); } if (n == 3 && seg[1].getLength() == 0) { // For backward compatibility, treat ${file::key} the same // as just ${file:key}: seg[1] = seg[2]; n = 2; } if (n == 1) { buf.append(lookup(file, mode, false, seg[0], requestStack)); } else if (n == 2) { if (seg[0].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".link"))) { osl::File f(seg[1]); rtl::ByteSequence seq; rtl::OUString line; rtl::OUString url; // Silently ignore any errors (is that good?): if (f.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None && f.readLine(seq) == osl::FileBase::E_None && rtl_convertStringToUString( &line.pData, reinterpret_cast< char const * >( seq.getConstArray()), seq.getLength(), RTL_TEXTENCODING_UTF8, (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) && (osl::File::getFileURLFromSystemPath(line, url) == osl::FileBase::E_None)) { try { buf.append( rtl::Uri::convertRelToAbs(seg[1], url)); } catch (const rtl::MalformedUriException &) {} } } else { buf.append( lookup( static_cast< Bootstrap_Impl * >( rtl::Bootstrap(seg[0]).getHandle()), mode, false, seg[1], requestStack)); } } else if (seg[0].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".override"))) { rtl::Bootstrap b(seg[1]); Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >( b.getHandle()); buf.append( lookup(f, mode, f != NULL, seg[2], requestStack)); } else { // Going through osl::Profile, this code erroneously does // not recursively expand macros in the resulting // replacement text (and if it did, it would fail to detect // cycles that pass through here): buf.append( rtl::OStringToOUString( osl::Profile(seg[0]).readString( rtl::OUStringToOString( seg[1], RTL_TEXTENCODING_UTF8), rtl::OUStringToOString( seg[2], RTL_TEXTENCODING_UTF8), rtl::OString()), RTL_TEXTENCODING_UTF8)); } } else { rtl::OUStringBuffer kbuf; for (; i < text.getLength();) { sal_Int32 j = i; c = read(text, &j, &escaped); if (!escaped && (c == ' ' || c == '$' || c == '-' || c == '/' || c == ';' || c == '\\')) { break; } kbuf.append(c); i = j; } buf.append( lookup( file, mode, false, kbuf.makeStringAndClear(), requestStack)); } } } return buf.makeStringAndClear(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */