/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"

#include "rtl/bootstrap.h"
#include "rtl/bootstrap.hxx"
#include <osl/diagnose.h>
#include <osl/module.h>
#include <osl/process.h>
#include <osl/file.hxx>
#include <osl/mutex.hxx>
#include <osl/profile.hxx>
#include <osl/security.hxx>
#include <rtl/alloc.h>
#include <rtl/string.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <rtl/byteseq.hxx>
#include <rtl/instance.hxx>
#include <rtl/malformeduriexception.hxx>
#include <rtl/uri.hxx>

#include "macro.hxx"

#include <hash_map>
#include <list>

#define MY_STRING_(x) # x
#define MY_STRING(x) MY_STRING_(x)

//----------------------------------------------------------------------------

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);
}

}

//----------------------------------------------------------------------------

struct rtl_bootstrap_NameValue
{
	OUString sName;
	OUString sValue;

    inline rtl_bootstrap_NameValue() SAL_THROW( () )
        {}
    inline rtl_bootstrap_NameValue(
        OUString const & name, OUString const & value ) SAL_THROW( () )
        : sName( name ),
          sValue( value )
        {}
};

typedef std::list<rtl_bootstrap_NameValue> NameValueList;

bool find(
    NameValueList const & list, rtl::OUString const & key,
    rtl::OUString * value)
{
    OSL_ASSERT(value != NULL);
    for (NameValueList::const_iterator i(list.begin()); i != list.end(); ++i) {
        if (i->sName == key) {
            *value = i->sValue;
            return true;
        }
    }
    return false;
}

namespace {
	struct rtl_bootstrap_set_list :
		public rtl::Static< NameValueList, rtl_bootstrap_set_list > {};
}

//----------------------------------------------------------------------------

static sal_Bool getFromCommandLineArgs(
	rtl::OUString const & key, rtl::OUString * value )
{
    OSL_ASSERT(value != NULL);
	static NameValueList *pNameValueList = 0;
	if( ! pNameValueList )
	{
		static NameValueList nameValueList;

		sal_Int32 nArgCount = osl_getCommandArgCount();
		for(sal_Int32 i = 0; i < nArgCount; ++ i)
		{
			rtl_uString *pArg = 0;
			osl_getCommandArg( i, &pArg );
			if( ('-' == pArg->buffer[0] || '/' == pArg->buffer[0] ) &&
				'e' == pArg->buffer[1] &&
				'n' == pArg->buffer[2] &&
				'v' == pArg->buffer[3] &&
				':' == pArg->buffer[4] )
			{
				sal_Int32 nIndex = rtl_ustr_indexOfChar( pArg->buffer, '=' );
				if( nIndex >= 0 )
				{

					rtl_bootstrap_NameValue nameValue;
					nameValue.sName = OUString( &(pArg->buffer[5]), nIndex - 5  );
					nameValue.sValue = OUString( &(pArg->buffer[nIndex+1]) );
					if( i == nArgCount-1 &&
						nameValue.sValue.getLength() &&
						nameValue.sValue[nameValue.sValue.getLength()-1] == 13 )
					{
						// avoid the 13 linefeed for the last argument,
						// when the executable is started from a script,
						// that was edited on windows
						nameValue.sValue = nameValue.sValue.copy(0,nameValue.sValue.getLength()-1);
					}
					nameValueList.push_back( nameValue );
				}
			}
			rtl_uString_release( pArg );
		}
		pNameValueList = &nameValueList;
	}

	sal_Bool found = sal_False;

	for( NameValueList::iterator ii = pNameValueList->begin() ;
		 ii != pNameValueList->end() ;
		 ++ii )
	{
		if( (*ii).sName.equals(key) )
		{
			*value = (*ii).sValue;
			found = sal_True;
			break;
		}
	}

	return found;
}

//----------------------------------------------------------------------------

extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
	rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C();

inline void getExecutableFile_Impl (rtl_uString ** ppFileURL)
{
    osl_bootstrap_getExecutableFile_Impl (ppFileURL);
}

//----------------------------------------------------------------------------

static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
{
    OUString fileName;
    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 OUString & getIniFileName_Impl()
{
	static OUString *pStaticName = 0;
	if( ! pStaticName )
	{
		OUString fileName;

		if(getFromCommandLineArgs(
               OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")), &fileName))
        {
            resolvePathnameUrl(&fileName);
        }
        else
		{
			getExecutableFile_Impl (&(fileName.pData));

			// get rid of a potential executable extension
			OUString progExt (RTL_CONSTASCII_USTRINGPARAM(".bin"));
			if(fileName.getLength() > progExt.getLength()
		    && fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
				fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());

			progExt = OUString::createFromAscii(".exe");
			if(fileName.getLength() > progExt.getLength()
			&& fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
				fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());

			// append config file suffix
			fileName += OUString(RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE("")));
		}

		static OUString theFileName;
		if(fileName.getLength())
			theFileName = fileName;

		pStaticName = &theFileName;
	}

	return *pStaticName;
}

//----------------------------------------------------------------------------

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
{
    sal_Int32 _nRefCount;
    Bootstrap_Impl * _base_ini;

	NameValueList _nameValueList;
	OUString      _iniName;

	explicit Bootstrap_Impl (OUString const & rIniName);
	~Bootstrap_Impl();

	static void * operator new (std::size_t n) SAL_THROW(())
        { return rtl_allocateMemory (sal_uInt32(n)); }
	static void operator delete (void * p , std::size_t) SAL_THROW(())
        { rtl_freeMemory (p); }

    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 )
	: _nRefCount( 0 ),
      _base_ini( 0 ),
      _iniName (rIniName)
{
    OUString base_ini( getIniFileName_Impl() );
    // normalize path
    FileStatus status( FileStatusMask_FileURL );
    DirectoryItem dirItem;
    if (DirectoryItem::E_None == DirectoryItem::get( base_ini, dirItem ) &&
        DirectoryItem::E_None == dirItem.getFileStatus( status ))
    {
        base_ini = status.getFileURL();
        if (! rIniName.equals( base_ini ))
        {
            _base_ini = static_cast< Bootstrap_Impl * >(
                rtl_bootstrap_args_open( base_ini.pData ) );
        }
    }

#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)
			{
				struct rtl_bootstrap_NameValue nameValue;
				nameValue.sName = OStringToOUString(
                    line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US );
				nameValue.sValue = OStringToOUString(
                    line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 );

#if OSL_DEBUG_LEVEL > 1
				OString name_tmp = OUStringToOString(nameValue.sName, RTL_TEXTENCODING_ASCII_US);
				OString value_tmp = OUStringToOString(nameValue.sValue, RTL_TEXTENCODING_UTF8);
				OSL_TRACE(
                    __FILE__" -- pushing: name=%s value=%s\n",
                    name_tmp.getStr(), value_tmp.getStr() );
#endif /* OSL_DEBUG_LEVEL > 1 */

				_nameValueList.push_back(nameValue);
			}
		}
		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 */
}

//----------------------------------------------------------------------------

Bootstrap_Impl::~Bootstrap_Impl()
{
    if (_base_ini != 0)
        rtl_bootstrap_args_close( _base_ini );
}

//----------------------------------------------------------------------------

namespace {

Bootstrap_Impl * get_static_bootstrap_handle() SAL_THROW(())
{
	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
    static Bootstrap_Impl * s_handle = 0;
    if (s_handle == 0)
    {
		OUString iniName (getIniFileName_Impl());
        s_handle = static_cast< Bootstrap_Impl * >(
            rtl_bootstrap_args_open( iniName.pData ) );
        if (s_handle == 0)
        {
            Bootstrap_Impl * that = new Bootstrap_Impl( iniName );
            ++that->_nRefCount;
            s_handle = that;
        }
    }
    return s_handle;
}

struct FundamentalIniData {
    rtlBootstrapHandle ini;

    FundamentalIniData() {
        OUString uri;
        ini =
            ((static_cast< Bootstrap_Impl * >(get_static_bootstrap_handle())->
              getValue(
                  rtl::OUString(
                      RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")),
                  &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0)) &&
             resolvePathnameUrl(&uri))
            ? rtl_bootstrap_args_open(uri.pData) : NULL;
    }

    ~FundamentalIniData() { rtl_bootstrap_args_close(ini); }

private:
    FundamentalIniData(FundamentalIniData &); // not defined
    void operator =(FundamentalIniData &); // not defined
};

struct FundamentalIni: public rtl::Static< FundamentalIniData, FundamentalIni >
{};

}

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<sal_Int32>(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;
    }
    if (_base_ini != NULL &&
        _base_ini->getDirectValue(key, value, mode, requestStack))
    {
        return true;
    }
    if (!override && getDirectValue(key, value, mode, requestStack)) {
        return true;
    }
    if (mode == LOOKUP_MODE_NORMAL) {
        FundamentalIniData const & d = FundamentalIni::get();
        Bootstrap_Impl const * b = static_cast<Bootstrap_Impl const *>(d.ini);
        if (b != NULL && 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 (find(_nameValueList, 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;
    bool f;
    {
        osl::MutexGuard g(osl::Mutex::getGlobalMutex());
        f = find(rtl_bootstrap_set_list::get(), key, &v);
    }
    if (f || getFromCommandLineArgs(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);
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

namespace {

struct bootstrap_map {
    typedef std::hash_map< const rtl::OUString, Bootstrap_Impl*, rtl::OUStringHash > t;

    // get and release must only be called properly synchronized via some mutex
    // (e.g., osl::Mutex::getGlobalMutex()):

    static t * get() {
        if (m_map == NULL) {
            m_map = new t;
        }
        return m_map;
    }

    static void release() {
        if (m_map != NULL && m_map->empty()) {
            delete m_map;
            m_map = NULL;
        }
    }

private:
    bootstrap_map(); // not defined

    static t * m_map;
};

bootstrap_map::t * bootstrap_map::m_map = NULL;

}

//----------------------------------------------------------------------------

rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
	rtl_uString * pIniName
) SAL_THROW_EXTERN_C()
{
	OUString iniName( pIniName );

    // normalize path
    FileStatus status( FileStatusMask_FileURL );
    DirectoryItem dirItem;
    if (DirectoryItem::E_None != DirectoryItem::get( iniName, dirItem ) ||
        DirectoryItem::E_None != dirItem.getFileStatus( status ))
    {
        return 0;
    }
    iniName = status.getFileURL();

    Bootstrap_Impl * that;
    osl::ResettableMutexGuard guard( osl::Mutex::getGlobalMutex() );
    bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
    bootstrap_map::t::const_iterator iFind( p_bootstrap_map->find( iniName ) );
    if (iFind == p_bootstrap_map->end())
    {
        bootstrap_map::release();
        guard.clear();
        that = new Bootstrap_Impl( iniName );
        guard.reset();
        p_bootstrap_map = bootstrap_map::get();
        iFind = p_bootstrap_map->find( iniName );
        if (iFind == p_bootstrap_map->end())
        {
            ++that->_nRefCount;
            ::std::pair< bootstrap_map::t::iterator, bool > insertion(
                p_bootstrap_map->insert(
                    bootstrap_map::t::value_type( iniName, that ) ) );
            OSL_ASSERT( insertion.second );
        }
        else
        {
            Bootstrap_Impl * obsolete = that;
            that = iFind->second;
            ++that->_nRefCount;
            guard.clear();
            delete obsolete;
        }
    }
    else
    {
        that = iFind->second;
        ++that->_nRefCount;
    }
	return static_cast< rtlBootstrapHandle >( that );
}

//----------------------------------------------------------------------------

void SAL_CALL rtl_bootstrap_args_close (
	rtlBootstrapHandle handle
) SAL_THROW_EXTERN_C()
{
    if (handle == 0)
        return;
    Bootstrap_Impl * that = static_cast< Bootstrap_Impl * >( handle );

    osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
    bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
    OSL_ASSERT(
        p_bootstrap_map->find( that->_iniName )->second == that );
    --that->_nRefCount;
    if (that->_nRefCount == 0)
    {
        ::std::size_t nLeaking = 8; // only hold up to 8 files statically

#if OSL_DEBUG_LEVEL == 1 // nonpro
        nLeaking = 0;
#elif OSL_DEBUG_LEVEL > 1 // debug
        nLeaking = 1;
#endif /* OSL_DEBUG_LEVEL */

        if (p_bootstrap_map->size() > nLeaking)
        {
            ::std::size_t erased = p_bootstrap_map->erase( that->_iniName );
            if (erased != 1) {
                OSL_ASSERT( false );
            }
            delete that;
        }
        bootstrap_map::release();
    }
}

//----------------------------------------------------------------------------

sal_Bool SAL_CALL rtl_bootstrap_get_from_handle(
    rtlBootstrapHandle handle,
	rtl_uString      * pName,
	rtl_uString     ** ppValue,
    rtl_uString      * pDefault
) SAL_THROW_EXTERN_C()
{
	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );

	sal_Bool found = sal_False;
	if(ppValue && pName)
	{
		if (handle == 0)
            handle = get_static_bootstrap_handle();
        found = static_cast< Bootstrap_Impl * >( handle )->getValue(
            pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, NULL );
	}

	return found;
}

//----------------------------------------------------------------------------

void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
    rtlBootstrapHandle handle,
	rtl_uString     ** ppIniName
) SAL_THROW_EXTERN_C()
{
	if(ppIniName)
    {
		if(handle)
        {
			Bootstrap_Impl * pImpl = static_cast<Bootstrap_Impl*>(handle);
			rtl_uString_assign(ppIniName, pImpl->_iniName.pData);
        }
		else
        {
			const OUString & iniName = getIniFileName_Impl();
			rtl_uString_assign(ppIniName, iniName.pData);
		}
    }
}

//----------------------------------------------------------------------------

void SAL_CALL rtl_bootstrap_setIniFileName (
	rtl_uString * pName
) SAL_THROW_EXTERN_C()
{
	osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
	OUString & file = getIniFileName_Impl();
	file = 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()
{
    const OUString name( pName );
    const OUString value( pValue );

    osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );

    NameValueList& r_rtl_bootstrap_set_list = rtl_bootstrap_set_list::get();
    NameValueList::iterator iPos( r_rtl_bootstrap_set_list.begin() );
    NameValueList::iterator iEnd( r_rtl_bootstrap_set_list.end() );
    for ( ; iPos != iEnd; ++iPos )
    {
        if (iPos->sName.equals( name ))
        {
            iPos->sValue = value;
            return;
        }
    }

#if OSL_DEBUG_LEVEL > 1
    OString cstr_name( OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ) );
    OString cstr_value( OUStringToOString( value, RTL_TEXTENCODING_ASCII_US ) );
    OSL_TRACE(
        "bootstrap.cxx: explicitly setting: name=%s value=%s\n",
        cstr_name.getStr(), cstr_value.getStr() );
#endif /* OSL_DEBUG_LEVEL > 1 */

    r_rtl_bootstrap_set_list.push_back( rtl_bootstrap_NameValue( name, value ) );
}

//----------------------------------------------------------------------------

void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
    rtlBootstrapHandle handle,
	rtl_uString     ** macro
) SAL_THROW_EXTERN_C()
{
    if (handle == NULL) {
        handle = get_static_bootstrap_handle();
    }
    OUString expanded( expandMacros( static_cast< Bootstrap_Impl * >( handle ),
									 * reinterpret_cast< OUString const * >( macro ),
                                     LOOKUP_MODE_NORMAL, NULL ) );
    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 == NULL ? get_static_bootstrap_handle() : 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(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 (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();
}

}
