office-gobmx/framework/source/services/substitutepathvars.cxx
Caolán McNamara aed4e00c4f UserInstallation may change in kit-mode
So the setting fetched at ctor time for UserInstallation (and
BRAND_BASE_DIR) may no longer be true, so expanding variables based
on those earlier seen values results in unwanted paths.

add XInitialization to SubstitutePathVariables (like done for
PathSettings) to allow reiniting these explicitly once.

Change-Id: Ia930ea71cb09adc91d6d47ee047c44b24222e8a2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175961
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 410f6b50eb44276b1d2095c844244ef4d0ddefaa)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177109
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
2024-11-24 15:14:48 +01:00

716 lines
26 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <config_folders.h>
#include <comphelper/lok.hxx>
#include <comphelper/compbase.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <osl/file.hxx>
#include <osl/security.hxx>
#include <osl/thread.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <tools/urlobj.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/bootstrap.hxx>
#include <officecfg/Office/Paths.hxx>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/util/XStringSubstitution.hpp>
#include <unordered_map>
using namespace com::sun::star::uno;
using namespace com::sun::star::container;
namespace {
enum PreDefVariable
{
PREDEFVAR_INST,
PREDEFVAR_PROG,
PREDEFVAR_USER,
PREDEFVAR_WORK,
PREDEFVAR_HOME,
PREDEFVAR_TEMP,
PREDEFVAR_PATH,
PREDEFVAR_USERNAME,
PREDEFVAR_LANGID,
PREDEFVAR_VLANG,
PREDEFVAR_INSTPATH,
PREDEFVAR_PROGPATH,
PREDEFVAR_USERPATH,
PREDEFVAR_INSTURL,
PREDEFVAR_PROGURL,
PREDEFVAR_USERURL,
PREDEFVAR_WORKDIRURL,
// New variable of hierarchy service (#i32656#)
PREDEFVAR_BASEINSTURL,
PREDEFVAR_USERDATAURL,
PREDEFVAR_BRANDBASEURL,
PREDEFVAR_COUNT
};
struct FixedVariable
{
OUString pVarName;
bool bAbsPath;
};
// Table with all fixed/predefined variables supported.
constexpr FixedVariable aFixedVarTable[PREDEFVAR_COUNT] =
{
{ u"$(inst)"_ustr, true }, // PREDEFVAR_INST
{ u"$(prog)"_ustr, true }, // PREDEFVAR_PROG
{ u"$(user)"_ustr, true }, // PREDEFVAR_USER
{ u"$(work)"_ustr, true }, // PREDEFVAR_WORK, special variable
// (transient)
{ u"$(home)"_ustr, true }, // PREDEFVAR_HOME
{ u"$(temp)"_ustr, true }, // PREDEFVAR_TEMP
{ u"$(path)"_ustr, true }, // PREDEFVAR_PATH
{ u"$(username)"_ustr, false }, // PREDEFVAR_USERNAME
{ u"$(langid)"_ustr, false }, // PREDEFVAR_LANGID
{ u"$(vlang)"_ustr, false }, // PREDEFVAR_VLANG
{ u"$(instpath)"_ustr, true }, // PREDEFVAR_INSTPATH
{ u"$(progpath)"_ustr, true }, // PREDEFVAR_PROGPATH
{ u"$(userpath)"_ustr, true }, // PREDEFVAR_USERPATH
{ u"$(insturl)"_ustr, true }, // PREDEFVAR_INSTURL
{ u"$(progurl)"_ustr, true }, // PREDEFVAR_PROGURL
{ u"$(userurl)"_ustr, true }, // PREDEFVAR_USERURL
{ u"$(workdirurl)"_ustr, true }, // PREDEFVAR_WORKDIRURL, special variable
// (transient) and don't use for
// resubstitution
{ u"$(baseinsturl)"_ustr, true }, // PREDEFVAR_BASEINSTURL
{ u"$(userdataurl)"_ustr, true }, // PREDEFVAR_USERDATAURL
{ u"$(brandbaseurl)"_ustr, true } // PREDEFVAR_BRANDBASEURL
};
struct PredefinedPathVariables
{
// Predefined variables supported by substitute variables
LanguageType m_eLanguageType; // Language type of Office
OUString m_FixedVar[ PREDEFVAR_COUNT ]; // Variable value access by PreDefVariable
OUString m_FixedVarNames[ PREDEFVAR_COUNT ]; // Variable name access by PreDefVariable
};
struct ReSubstFixedVarOrder
{
sal_Int32 nVarValueLength;
PreDefVariable eVariable;
bool operator< ( const ReSubstFixedVarOrder& aFixedVarOrder ) const
{
// Reverse operator< to have high to low ordering
return ( nVarValueLength > aFixedVarOrder.nVarValueLength );
}
};
typedef comphelper::WeakComponentImplHelper<
css::util::XStringSubstitution,
css::lang::XServiceInfo,
css::lang::XInitialization > SubstitutePathVariables_BASE;
class SubstitutePathVariables : public SubstitutePathVariables_BASE
{
public:
explicit SubstitutePathVariables();
virtual OUString SAL_CALL getImplementationName() override
{
return u"com.sun.star.comp.framework.PathSubstitution"_ustr;
}
virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
{
return cppu::supportsService(this, ServiceName);
}
virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
{
return {u"com.sun.star.util.PathSubstitution"_ustr};
}
// XStringSubstitution
virtual OUString SAL_CALL substituteVariables( const OUString& aText, sal_Bool bSubstRequired ) override;
virtual OUString SAL_CALL reSubstituteVariables( const OUString& aText ) override;
virtual OUString SAL_CALL getSubstituteVariableValue( const OUString& variable ) override;
// XInitialization
virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& /*rArguments*/) override;
private:
void impl_initialize();
void SetPredefinedPathVariables();
// Special case (transient) values can change during runtime!
// Don't store them in the pre defined struct
static OUString GetWorkPath();
static OUString GetWorkVariableValue();
static OUString GetPathVariableValue();
static OUString GetHomeVariableValue();
// XStringSubstitution implementation methods
/// @throws css::container::NoSuchElementException
/// @throws css::uno::RuntimeException
OUString impl_substituteVariable( const OUString& aText, bool bSustRequired );
/// @throws css::uno::RuntimeException
OUString impl_reSubstituteVariables( const OUString& aText );
/// @throws css::container::NoSuchElementException
/// @throws css::uno::RuntimeException
OUString const & impl_getSubstituteVariableValue( const OUString& variable );
private:
typedef std::unordered_map<OUString, PreDefVariable>
VarNameToIndexMap;
VarNameToIndexMap m_aPreDefVarMap; // Mapping from pre-def variable names to enum for array access
PredefinedPathVariables m_aPreDefVars; // All predefined variables
std::vector<ReSubstFixedVarOrder> m_aReSubstFixedVarOrder; // To speed up resubstitution fixed variables (order for lookup)
};
SubstitutePathVariables::SubstitutePathVariables()
{
impl_initialize();
}
void SubstitutePathVariables::impl_initialize()
{
SetPredefinedPathVariables();
// Init the predefined/fixed variable to index hash map
for ( int i = 0; i < PREDEFVAR_COUNT; i++ )
{
// Store variable name into struct of predefined/fixed variables
m_aPreDefVars.m_FixedVarNames[i] = aFixedVarTable[i].pVarName;
// Create hash map entry
m_aPreDefVarMap.emplace( m_aPreDefVars.m_FixedVarNames[i], PreDefVariable(i) );
}
// Sort predefined/fixed variable to path length
for ( int i = 0; i < PREDEFVAR_COUNT; i++ )
{
if (( i != PREDEFVAR_WORKDIRURL ) && ( i != PREDEFVAR_PATH ))
{
// Special path variables, don't include into automatic resubstitution search!
// $(workdirurl) is not allowed to resubstitute! This variable is the value of path settings entry
// and it could be possible that it will be resubstituted by itself!!
// Example: WORK_PATH=c:\test, $(workdirurl)=WORK_PATH => WORK_PATH=$(workdirurl) and this cannot be substituted!
ReSubstFixedVarOrder aFixedVar;
aFixedVar.eVariable = PreDefVariable(i);
aFixedVar.nVarValueLength = m_aPreDefVars.m_FixedVar[static_cast<sal_Int32>(aFixedVar.eVariable)].getLength();
m_aReSubstFixedVarOrder.push_back( aFixedVar );
}
}
sort(m_aReSubstFixedVarOrder.begin(),m_aReSubstFixedVarOrder.end());
}
void SAL_CALL SubstitutePathVariables::initialize(const css::uno::Sequence<css::uno::Any>& /*rArguments*/)
{
std::unique_lock g(m_aMutex);
impl_initialize();
}
// XStringSubstitution
OUString SAL_CALL SubstitutePathVariables::substituteVariables( const OUString& aText, sal_Bool bSubstRequired )
{
std::unique_lock g(m_aMutex);
return impl_substituteVariable( aText, bSubstRequired );
}
OUString SAL_CALL SubstitutePathVariables::reSubstituteVariables( const OUString& aText )
{
std::unique_lock g(m_aMutex);
return impl_reSubstituteVariables( aText );
}
OUString SAL_CALL SubstitutePathVariables::getSubstituteVariableValue( const OUString& aVariable )
{
std::unique_lock g(m_aMutex);
return impl_getSubstituteVariableValue( aVariable );
}
// static
OUString SubstitutePathVariables::GetWorkPath()
{
OUString aWorkPath;
css::uno::Reference< css::container::XHierarchicalNameAccess > xPaths(officecfg::Office::Paths::Paths::get(), css::uno::UNO_QUERY_THROW);
if (!(xPaths->getByHierarchicalName(u"['Work']/WritePath"_ustr) >>= aWorkPath))
// fallback in case config layer does not return a usable work dir value.
aWorkPath = GetWorkVariableValue();
return aWorkPath;
}
// static
OUString SubstitutePathVariables::GetWorkVariableValue()
{
OUString aWorkPath;
std::optional<OUString> x(officecfg::Office::Paths::Variables::Work::get());
if (!x)
{
// fallback to $HOME in case platform dependent config layer does not return
// a usable work dir value.
osl::Security aSecurity;
aSecurity.getHomeDir( aWorkPath );
}
else
aWorkPath = *x;
return aWorkPath;
}
// static
OUString SubstitutePathVariables::GetHomeVariableValue()
{
osl::Security aSecurity;
OUString aHomePath;
aSecurity.getHomeDir( aHomePath );
return aHomePath;
}
// static
OUString SubstitutePathVariables::GetPathVariableValue()
{
OUString aRetStr;
const char* pEnv = getenv( "PATH" );
if ( pEnv )
{
const int PATH_EXTEND_FACTOR = 200;
OUString aTmp;
OUString aPathList( pEnv, strlen( pEnv ), osl_getThreadTextEncoding() );
OUStringBuffer aPathStrBuffer( aPathList.getLength() * PATH_EXTEND_FACTOR / 100 );
bool bAppendSep = false;
sal_Int32 nToken = 0;
do
{
OUString sToken = aPathList.getToken(0, SAL_PATHSEPARATOR, nToken);
if (!sToken.isEmpty() &&
osl::FileBase::getFileURLFromSystemPath( sToken, aTmp ) ==
osl::FileBase::RC::E_None )
{
if ( bAppendSep )
aPathStrBuffer.append( ";" ); // Office uses ';' as path separator
aPathStrBuffer.append( aTmp );
bAppendSep = true;
}
}
while(nToken>=0);
aRetStr = aPathStrBuffer.makeStringAndClear();
}
return aRetStr;
}
OUString SubstitutePathVariables::impl_substituteVariable( const OUString& rText, bool bSubstRequired )
{
// This is maximal recursive depth supported!
const sal_Int32 nMaxRecursiveDepth = 8;
OUString aWorkText = rText;
OUString aResult;
// Use vector with strings to detect endless recursions!
std::vector< OUString > aEndlessRecursiveDetector;
// Search for first occurrence of "$(...".
sal_Int32 nDepth = 0;
bool bSubstitutionCompleted = false;
sal_Int32 nPosition = aWorkText.indexOf( "$(" );
sal_Int32 nLength = 0; // = count of letters from "$(" to ")" in string
bool bVarNotSubstituted = false;
// Have we found any variable like "$(...)"?
if ( nPosition != -1 )
{
// Yes; Get length of found variable.
// If no ")" was found - nLength is set to 0 by default! see before.
sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
if ( nEndPosition != -1 )
nLength = nEndPosition - nPosition + 1;
}
// Is there something to replace ?
bool bWorkRetrieved = false;
bool bWorkDirURLRetrieved = false;
while (nDepth < nMaxRecursiveDepth)
{
while ( ( nPosition != -1 ) && ( nLength > 3 ) ) // "$(" ")"
{
// YES; Get the next variable for replace.
sal_Int32 nReplaceLength = 0;
OUString aReplacement;
OUString aSubString = aWorkText.copy( nPosition, nLength );
// Path variables are not case sensitive!
OUString aSubVarString = aSubString.toAsciiLowerCase();
VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( aSubVarString );
if ( pNTOIIter != m_aPreDefVarMap.end() )
{
// Fixed/Predefined variable found
PreDefVariable nIndex = pNTOIIter->second;
// Determine variable value and length from array/table
if ( nIndex == PREDEFVAR_WORK && !bWorkRetrieved )
{
// Transient value, retrieve it again
m_aPreDefVars.m_FixedVar[ nIndex ] = GetWorkVariableValue();
bWorkRetrieved = true;
}
else if ( nIndex == PREDEFVAR_WORKDIRURL && !bWorkDirURLRetrieved )
{
// Transient value, retrieve it again
m_aPreDefVars.m_FixedVar[ nIndex ] = GetWorkPath();
bWorkDirURLRetrieved = true;
}
// Check preconditions to substitute path variables.
// 1. A path variable can only be substituted if it follows a ';'!
// 2. It's located exactly at the start of the string being substituted!
if (( aFixedVarTable[ int( nIndex ) ].bAbsPath && (( nPosition == 0 ) || (( nPosition > 0 ) && ( aWorkText[nPosition-1] == ';')))) ||
( !aFixedVarTable[ int( nIndex ) ].bAbsPath ))
{
aReplacement = m_aPreDefVars.m_FixedVar[ nIndex ];
nReplaceLength = nLength;
}
}
// Have we found something to replace?
if ( nReplaceLength > 0 )
{
// Yes ... then do it.
aWorkText = aWorkText.replaceAt( nPosition, nReplaceLength, aReplacement );
}
else
{
// Variable not known
bVarNotSubstituted = true;
nPosition += nLength;
}
// Step after replaced text! If no text was replaced (unknown variable!),
// length of aReplacement is 0 ... and we don't step then.
nPosition += aReplacement.getLength();
// We must control index in string before call something at OUString!
// The OUString-implementation don't do it for us :-( but the result is not defined otherwise.
if ( nPosition + 1 > aWorkText.getLength() )
{
// Position is out of range. Break loop!
nPosition = -1;
nLength = 0;
}
else
{
// Else; Position is valid. Search for next variable to replace.
nPosition = aWorkText.indexOf( "$(", nPosition );
// Have we found any variable like "$(...)"?
if ( nPosition != -1 )
{
// Yes; Get length of found variable. If no ")" was found - nLength must set to 0!
nLength = 0;
sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
if ( nEndPosition != -1 )
nLength = nEndPosition - nPosition + 1;
}
}
}
nPosition = aWorkText.indexOf( "$(" );
if ( nPosition == -1 )
{
bSubstitutionCompleted = true;
break; // All variables are substituted
}
else
{
// Check for recursion
const sal_uInt32 nCount = aEndlessRecursiveDetector.size();
for ( sal_uInt32 i=0; i < nCount; i++ )
{
if ( aEndlessRecursiveDetector[i] == aWorkText )
{
if ( bVarNotSubstituted )
break; // Not all variables could be substituted!
else
{
nDepth = nMaxRecursiveDepth;
break; // Recursion detected!
}
}
}
aEndlessRecursiveDetector.push_back( aWorkText );
// Initialize values for next
sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
if ( nEndPosition != -1 )
nLength = nEndPosition - nPosition + 1;
bVarNotSubstituted = false;
++nDepth;
}
}
// Fill return value with result
if ( bSubstitutionCompleted )
{
// Substitution successful!
aResult = aWorkText;
}
else
{
// Substitution not successful!
if ( nDepth == nMaxRecursiveDepth )
{
// recursion depth reached!
if ( bSubstRequired )
{
throw NoSuchElementException( u"Endless recursion detected. Cannot substitute variables!"_ustr, static_cast<cppu::OWeakObject *>(this) );
}
aResult = rText;
}
else
{
// variable in text but unknown!
if ( bSubstRequired )
{
throw NoSuchElementException( u"Unknown variable found!"_ustr, static_cast<cppu::OWeakObject *>(this) );
}
aResult = aWorkText;
}
}
return aResult;
}
OUString SubstitutePathVariables::impl_reSubstituteVariables( const OUString& rURL )
{
OUString aURL;
INetURLObject aUrl( rURL );
if ( !aUrl.HasError() )
aURL = aUrl.GetMainURL( INetURLObject::DecodeMechanism::NONE );
else
{
// Convert a system path to a UCB compliant URL before resubstitution
OUString aTemp;
if ( osl::FileBase::getFileURLFromSystemPath( rURL, aTemp ) == osl::FileBase::E_None )
{
aURL = INetURLObject( aTemp ).GetMainURL( INetURLObject::DecodeMechanism::NONE );
if( aURL.isEmpty() )
return rURL;
}
else
{
// rURL is not a valid URL nor a osl system path. Give up and return error!
return rURL;
}
}
// Get transient predefined path variable $(work) value before starting resubstitution
m_aPreDefVars.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
for (;;)
{
bool bVariableFound = false;
for (auto const & i: m_aReSubstFixedVarOrder)
{
OUString aValue = m_aPreDefVars.m_FixedVar[i.eVariable];
sal_Int32 nPos = aURL.indexOf( aValue );
if ( nPos >= 0 )
{
bool bMatch = true;
if ( !aFixedVarTable[i.eVariable].bAbsPath )
{
// Special path variables as they can occur in the middle of a path. Only match if they
// describe a whole directory and not only a substring of a directory!
// (Ideally, all substitutions should stick to syntactical
// boundaries within the given URL, like not covering only
// part of a URL path segment; however, at least when saving
// an Impress document, one URL that is passed in is of the
// form <file:///.../share/palette%3Bfile:///.../user/
// config/standard.sob>, re-substituted to
// <$(inst)/share/palette%3B$(user)/config/standard.sob>.)
const sal_Unicode* pStr = aURL.getStr();
if ( nPos > 0 )
bMatch = ( aURL[ nPos-1 ] == '/' );
if ( bMatch )
{
if ( nPos + aValue.getLength() < aURL.getLength() )
bMatch = ( pStr[ nPos + aValue.getLength() ] == '/' );
}
}
if ( bMatch )
{
aURL = aURL.replaceAt(
nPos, aValue.getLength(),
m_aPreDefVars.m_FixedVarNames[i.eVariable]);
bVariableFound = true; // Resubstitution not finished yet!
break;
}
}
}
if ( !bVariableFound )
{
return aURL;
}
}
}
// This method support both request schemes "$("<varname>")" or "<varname>".
OUString const & SubstitutePathVariables::impl_getSubstituteVariableValue( const OUString& rVariable )
{
OUString aVariable;
sal_Int32 nPos = rVariable.indexOf( "$(" );
if ( nPos == -1 )
{
// Prepare variable name before hash map access
aVariable = "$(" + rVariable + ")";
}
VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( ( nPos == -1 ) ? aVariable : rVariable );
// Fixed/Predefined variable
if ( pNTOIIter == m_aPreDefVarMap.end() )
{
throw NoSuchElementException(u"Unknown variable!"_ustr, static_cast<cppu::OWeakObject *>(this));
}
PreDefVariable nIndex = pNTOIIter->second;
return m_aPreDefVars.m_FixedVar[static_cast<sal_Int32>(nIndex)];
}
void SubstitutePathVariables::SetPredefinedPathVariables()
{
m_aPreDefVars.m_FixedVar[PREDEFVAR_BRANDBASEURL] = "$BRAND_BASE_DIR";
rtl::Bootstrap::expandMacros(
m_aPreDefVars.m_FixedVar[PREDEFVAR_BRANDBASEURL]);
// Get inspath and userpath from bootstrap mechanism in every case as file URL
::utl::Bootstrap::PathStatus aState;
OUString sVal;
aState = utl::Bootstrap::locateUserData( sVal );
//There can be the valid case that there is no user installation.
//TODO: Is that still the case? (With OOo 3.4, "unopkg sync" was run as part
// of the setup. Then no user installation was required.)
//Therefore we do not assert here.
// It's not possible to detect when an empty value would actually be used.
// (note: getenv is a hack to detect if we're running in a unit test)
// Also, it's okay to have an empty user installation path in case of LOK
if (aState == ::utl::Bootstrap::PATH_EXISTS || getenv("SRC_ROOT") ||
(comphelper::LibreOfficeKit::isActive() && aState == ::utl::Bootstrap::PATH_VALID))
{
m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERPATH ] = sVal;
}
// Set $(inst), $(instpath), $(insturl)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_INSTPATH ] = m_aPreDefVars.m_FixedVar[PREDEFVAR_BRANDBASEURL];
m_aPreDefVars.m_FixedVar[ PREDEFVAR_INSTURL ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_INSTPATH ];
m_aPreDefVars.m_FixedVar[ PREDEFVAR_INST ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_INSTPATH ];
// New variable of hierarchy service (#i32656#)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_BASEINSTURL ]= m_aPreDefVars.m_FixedVar[ PREDEFVAR_INSTPATH ];
// Set $(user), $(userpath), $(userurl)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERURL ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERPATH ];
m_aPreDefVars.m_FixedVar[ PREDEFVAR_USER ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERPATH ];
// New variable of hierarchy service (#i32656#)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERDATAURL ]= m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERPATH ];
// Detect the program directory
// Set $(prog), $(progpath), $(progurl)
INetURLObject aProgObj(
m_aPreDefVars.m_FixedVar[PREDEFVAR_BRANDBASEURL] );
if ( !aProgObj.HasError() && aProgObj.insertName( u"" LIBO_BIN_FOLDER ) )
{
m_aPreDefVars.m_FixedVar[ PREDEFVAR_PROGPATH ] = aProgObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
m_aPreDefVars.m_FixedVar[ PREDEFVAR_PROGURL ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_PROGPATH ];
m_aPreDefVars.m_FixedVar[ PREDEFVAR_PROG ] = m_aPreDefVars.m_FixedVar[ PREDEFVAR_PROGPATH ];
}
// Set $(username)
OUString aSystemUser;
::osl::Security aSecurity;
aSecurity.getUserName( aSystemUser, false );
m_aPreDefVars.m_FixedVar[ PREDEFVAR_USERNAME ] = aSystemUser;
// Detect the language type of the current office
m_aPreDefVars.m_eLanguageType = LANGUAGE_ENGLISH_US;
OUString aLocaleStr( utl::ConfigManager::getUILocale() );
m_aPreDefVars.m_eLanguageType = LanguageTag::convertToLanguageTypeWithFallback( aLocaleStr );
// We used to have an else branch here with a SAL_WARN, but that
// always fired in some unit tests when this code was built with
// debug=t, so it seems fairly pointless, especially as
// m_aPreDefVars.m_eLanguageType has been initialized to a
// default value above anyway.
// Set $(vlang)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_VLANG ] = aLocaleStr;
// Set $(langid)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_LANGID ] = OUString::number( static_cast<sal_uInt16>(m_aPreDefVars.m_eLanguageType) );
// Set the other pre defined path variables
// Set $(work)
m_aPreDefVars.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
m_aPreDefVars.m_FixedVar[ PREDEFVAR_HOME ] = GetHomeVariableValue();
// Set $(workdirurl) this is the value of the path PATH_WORK which doesn't make sense
// anymore because the path settings service has this value! It can deliver this value more
// quickly than the substitution service!
m_aPreDefVars.m_FixedVar[ PREDEFVAR_WORKDIRURL ] = GetWorkPath();
// Set $(path) variable
m_aPreDefVars.m_FixedVar[ PREDEFVAR_PATH ] = GetPathVariableValue();
// Set $(temp)
OUString aTmp;
osl::FileBase::getTempDirURL( aTmp );
m_aPreDefVars.m_FixedVar[ PREDEFVAR_TEMP ] = aTmp;
}
}
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_framework_PathSubstitution_get_implementation(
css::uno::XComponentContext *,
css::uno::Sequence<css::uno::Any> const &)
{
return cppu::acquire(new SubstitutePathVariables());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */