LCOV - code coverage report
Current view: top level - framework/source/services - substitutepathvars.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 472 0.0 %
Date: 2014-04-14 Functions: 0 52 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_folders.h>
      21             : 
      22             : #include <helper/networkdomain.hxx>
      23             : 
      24             : #include <cppuhelper/basemutex.hxx>
      25             : #include <cppuhelper/compbase2.hxx>
      26             : #include <cppuhelper/supportsservice.hxx>
      27             : #include <unotools/configitem.hxx>
      28             : #include <unotools/localfilehelper.hxx>
      29             : #include <unotools/configmgr.hxx>
      30             : 
      31             : #include <unotools/bootstrap.hxx>
      32             : #include <osl/mutex.hxx>
      33             : #include <osl/file.hxx>
      34             : #include <osl/security.hxx>
      35             : #include <osl/socket.hxx>
      36             : #include <osl/process.h>
      37             : #include <i18nlangtag/languagetag.hxx>
      38             : #include <i18nlangtag/mslangid.hxx>
      39             : #include <tools/link.hxx>
      40             : #include <tools/urlobj.hxx>
      41             : #include <tools/resmgr.hxx>
      42             : #include <tools/wldcrd.hxx>
      43             : #include <rtl/ustrbuf.hxx>
      44             : #include <rtl/bootstrap.hxx>
      45             : 
      46             : #include <officecfg/Office/Paths.hxx>
      47             : 
      48             : #include <com/sun/star/lang/XServiceInfo.hpp>
      49             : #include <com/sun/star/container/NoSuchElementException.hpp>
      50             : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
      51             : #include <com/sun/star/util/XStringSubstitution.hpp>
      52             : 
      53             : #include <boost/unordered_map.hpp>
      54             : #include <string.h>
      55             : 
      56             : using namespace com::sun::star::uno;
      57             : using namespace com::sun::star::beans;
      58             : using namespace com::sun::star::util;
      59             : using namespace com::sun::star::lang;
      60             : using namespace com::sun::star::container;
      61             : using namespace framework;
      62             : 
      63             : namespace {
      64             : 
      65             : // Must be zero value based
      66             : enum EnvironmentType
      67             : {
      68             :         ET_HOST = 0             ,
      69             :         ET_YPDOMAIN             ,
      70             :         ET_DNSDOMAIN    ,
      71             :         ET_NTDOMAIN             ,
      72             :         ET_OS                   ,
      73             :         ET_UNKNOWN              ,
      74             :         ET_COUNT
      75             : };
      76             : 
      77             : // Must be zero value based
      78             : enum OperatingSystem
      79             : {
      80             :         OS_WINDOWS = 0,
      81             :         OS_UNIX         ,
      82             :         OS_SOLARIS      ,
      83             :         OS_LINUX        ,
      84             :         OS_UNKNOWN      ,
      85             :         OS_COUNT
      86             : };
      87             : 
      88           0 : struct SubstituteRule
      89             : {
      90           0 :     SubstituteRule()
      91           0 :         : aEnvType(ET_UNKNOWN)
      92           0 :     {}
      93             : 
      94           0 :     SubstituteRule( const OUString& aVarName,
      95             :                     const OUString& aValue,
      96             :                     const com::sun::star::uno::Any& aVal,
      97             :                     EnvironmentType aType )
      98             :         : aSubstVariable(aVarName)
      99             :         , aSubstValue(aValue)
     100             :         , aEnvValue(aVal)
     101           0 :         , aEnvType(aType)
     102           0 :     {}
     103             : 
     104             :     OUString            aSubstVariable;
     105             :     OUString            aSubstValue;
     106             :     com::sun::star::uno::Any aEnvValue;
     107             :     EnvironmentType          aEnvType;
     108             : };
     109             : 
     110             : typedef boost::unordered_map<OUString, SubstituteRule, OUStringHash>
     111             :     SubstituteVariables;
     112             : 
     113             : typedef std::vector< SubstituteRule > SubstituteRuleVector;
     114             : class SubstitutePathVariables_Impl : public utl::ConfigItem
     115             : {
     116             :     public:
     117             :         SubstitutePathVariables_Impl( const Link& aNotifyLink );
     118             :         virtual ~SubstitutePathVariables_Impl();
     119             : 
     120             :         static OperatingSystem GetOperatingSystemFromString( const OUString& );
     121             :         static EnvironmentType GetEnvTypeFromString( const OUString& );
     122             : 
     123             :         void                   GetSharePointsRules( SubstituteVariables& aSubstVarMap );
     124             : 
     125             :         /** is called from the ConfigManager before application ends or from the
     126             :             PropertyChangeListener if the sub tree broadcasts changes. */
     127             :         virtual void Notify( const com::sun::star::uno::Sequence< OUString >& aPropertyNames ) SAL_OVERRIDE;
     128             :         virtual void Commit() SAL_OVERRIDE;
     129             : 
     130             :         private:
     131             :             // Wrapper methods for low-level functions
     132             :             OperatingSystem         GetOperatingSystem();
     133             :             const OUString&    GetYPDomainName();
     134             :             const OUString&    GetDNSDomainName();
     135             :             const OUString&    GetNTDomainName();
     136             :             const OUString&    GetHostName();
     137             : 
     138             :             bool                    FilterRuleSet( const SubstituteRuleVector& aRuleSet, SubstituteRule& aActiveRule );
     139             : 
     140             :             void                    ReadSharePointsFromConfiguration( com::sun::star::uno::Sequence< OUString >& aSharePointsSeq );
     141             :             void                    ReadSharePointRuleSetFromConfiguration( const OUString& aSharePointName,
     142             :                                                                                                                                 const OUString& aSharePointNodeName,
     143             :                                                                                                                                 SubstituteRuleVector& aRuleSet );
     144             : 
     145             :             // Stored values for domains and host
     146             :             bool                    m_bYPDomainRetrieved;
     147             :             OUString           m_aYPDomain;
     148             :             bool                    m_bDNSDomainRetrieved;
     149             :             OUString           m_aDNSDomain;
     150             :             bool                    m_bNTDomainRetrieved;
     151             :             OUString           m_aNTDomain;
     152             :             bool                    m_bHostRetrieved;
     153             :             OUString           m_aHost;
     154             : 
     155             :             Link                    m_aListenerNotify;
     156             :             const OUString     m_aSharePointsNodeName;
     157             :             const OUString     m_aDirPropertyName;
     158             :             const OUString     m_aEnvPropertyName;
     159             :             const OUString     m_aLevelSep;
     160             : };
     161             : 
     162             : enum PreDefVariable
     163             : {
     164             :     PREDEFVAR_INST,
     165             :     PREDEFVAR_PROG,
     166             :     PREDEFVAR_USER,
     167             :     PREDEFVAR_WORK,
     168             :     PREDEFVAR_HOME,
     169             :     PREDEFVAR_TEMP,
     170             :     PREDEFVAR_PATH,
     171             :     PREDEFVAR_LANGID,
     172             :     PREDEFVAR_VLANG,
     173             :     PREDEFVAR_INSTPATH,
     174             :     PREDEFVAR_PROGPATH,
     175             :     PREDEFVAR_USERPATH,
     176             :     PREDEFVAR_INSTURL,
     177             :     PREDEFVAR_PROGURL,
     178             :     PREDEFVAR_USERURL,
     179             :     PREDEFVAR_WORKDIRURL,
     180             :     // New variable of hierachy service (#i32656#)
     181             :     PREDEFVAR_BASEINSTURL,
     182             :     PREDEFVAR_USERDATAURL,
     183             :     PREDEFVAR_BRANDBASEURL,
     184             :     PREDEFVAR_COUNT
     185             : };
     186             : 
     187           0 : struct PredefinedPathVariables
     188             : {
     189             :     // Predefined variables supported by substitute variables
     190             :     LanguageType    m_eLanguageType;                    // Lanuage type of Office
     191             :     OUString   m_FixedVar[ PREDEFVAR_COUNT ];      // Variable value access by PreDefVariable
     192             :     OUString   m_FixedVarNames[ PREDEFVAR_COUNT ]; // Variable name access by PreDefVariable
     193             : };
     194             : 
     195             : struct ReSubstFixedVarOrder
     196             : {
     197             :     sal_Int32       nVarValueLength;
     198             :     PreDefVariable  eVariable;
     199             : 
     200           0 :     bool operator< ( const ReSubstFixedVarOrder& aFixedVarOrder ) const
     201             :     {
     202             :         // Reverse operator< to have high to low ordering
     203           0 :         return ( nVarValueLength > aFixedVarOrder.nVarValueLength );
     204             :     }
     205             : };
     206             : 
     207           0 : struct ReSubstUserVarOrder
     208             : {
     209             :     sal_Int32       nVarValueLength;
     210             :     OUString   aVarName;
     211             : 
     212           0 :     bool operator< ( const ReSubstUserVarOrder& aUserVarOrder ) const
     213             :     {
     214             :         // Reverse operator< to have high to low ordering
     215           0 :         return ( nVarValueLength > aUserVarOrder.nVarValueLength );
     216             :     }
     217             : };
     218             : 
     219             : typedef std::list< ReSubstFixedVarOrder > ReSubstFixedVarOrderVector;
     220             : typedef std::list< ReSubstUserVarOrder > ReSubstUserVarOrderVector;
     221             : typedef ::cppu::WeakComponentImplHelper2<
     222             :     css::util::XStringSubstitution,
     223             :     css::lang::XServiceInfo > SubstitutePathVariables_BASE;
     224             : 
     225             : class SubstitutePathVariables : private cppu::BaseMutex,
     226             :                                 public SubstitutePathVariables_BASE
     227             : {
     228             : friend class SubstitutePathVariables_Impl;
     229             : 
     230             : public:
     231             :     SubstitutePathVariables( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext );
     232             :     virtual ~SubstitutePathVariables();
     233             : 
     234           0 :     virtual OUString SAL_CALL getImplementationName()
     235             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
     236             :     {
     237           0 :         return OUString("com.sun.star.comp.framework.PathSubstitution");
     238             :     }
     239             : 
     240           0 :     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
     241             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
     242             :     {
     243           0 :         return cppu::supportsService(this, ServiceName);
     244             :     }
     245             : 
     246           0 :     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
     247             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
     248             :     {
     249           0 :         css::uno::Sequence< OUString > aSeq(1);
     250           0 :         aSeq[0] = OUString("com.sun.star.util.PathSubstitution");
     251           0 :         return aSeq;
     252             :     }
     253             : 
     254             :     // XStringSubstitution
     255             :     virtual OUString SAL_CALL substituteVariables( const OUString& aText, sal_Bool bSubstRequired )
     256             :         throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     257             :     virtual OUString SAL_CALL reSubstituteVariables( const OUString& aText )
     258             :         throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     259             :     virtual OUString SAL_CALL getSubstituteVariableValue( const OUString& variable )
     260             :         throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     261             : 
     262             : protected:
     263             :     DECL_LINK(implts_ConfigurationNotify, void *);
     264             : 
     265             :     void            SetPredefinedPathVariables( PredefinedPathVariables& );
     266             :     OUString   ConvertOSLtoUCBURL( const OUString& aOSLCompliantURL ) const;
     267             : 
     268             :     // Special case (transient) values can change during runtime!
     269             :     // Don't store them in the pre defined struct
     270             :     OUString   GetWorkPath() const;
     271             :     OUString   GetWorkVariableValue() const;
     272             :     OUString   GetPathVariableValue() const;
     273             : 
     274             :     OUString   GetHomeVariableValue() const;
     275             : 
     276             :     // XStringSubstitution implementation methods
     277             :     OUString impl_substituteVariable( const OUString& aText, bool bSustRequired )
     278             :         throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
     279             :     OUString impl_reSubstituteVariables( const OUString& aText )
     280             :         throw (::com::sun::star::uno::RuntimeException);
     281             :     OUString impl_getSubstituteVariableValue( const OUString& variable )
     282             :         throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
     283             : 
     284             : private:
     285             :     typedef boost::unordered_map<OUString, PreDefVariable, OUStringHash>
     286             :         VarNameToIndexMap;
     287             : 
     288             :     VarNameToIndexMap            m_aPreDefVarMap;         // Mapping from pre-def variable names to enum for array access
     289             :     SubstituteVariables          m_aSubstVarMap;          // Active rule set map indexed by variable name!
     290             :     PredefinedPathVariables      m_aPreDefVars;           // All predefined variables
     291             :     SubstitutePathVariables_Impl m_aImpl;                 // Implementation class that access the configuration
     292             :     ReSubstFixedVarOrderVector   m_aReSubstFixedVarOrder; // To speed up resubstitution fixed variables (order for lookup)
     293             :     ReSubstUserVarOrderVector    m_aReSubstUserVarOrder;  // To speed up resubstitution user variables
     294             :     css::uno::Reference< css::uno::XComponentContext > m_xContext;
     295             : };
     296             : 
     297             : struct FixedVariable
     298             : {
     299             :     const char*     pVarName;
     300             :     sal_Int32       nStrLen;
     301             :     PreDefVariable  nEnumValue;
     302             :     bool            bAbsPath;
     303             : };
     304             : 
     305             : struct TableEntry
     306             : {
     307             :     const char* pOSString;
     308             :     sal_Int32   nStrLen;
     309             : };
     310             : 
     311             : // Table with valid operating system strings
     312             : // Name of the os as char* and the length
     313             : // of the string
     314             : static const TableEntry aOSTable[OS_COUNT] =
     315             : {
     316             :     { RTL_CONSTASCII_STRINGPARAM("WINDOWS") },
     317             :     { RTL_CONSTASCII_STRINGPARAM("UNIX") },
     318             :     { RTL_CONSTASCII_STRINGPARAM("SOLARIS") },
     319             :     { RTL_CONSTASCII_STRINGPARAM("LINUX") },
     320             :     { RTL_CONSTASCII_STRINGPARAM("") } // unknown
     321             : };
     322             : 
     323             : // Table with valid environment variables
     324             : // Name of the environment type as a char* and
     325             : // the length of the string.
     326             : static const TableEntry aEnvTable[ET_COUNT] =
     327             : {
     328             :     { RTL_CONSTASCII_STRINGPARAM("HOST") },
     329             :     { RTL_CONSTASCII_STRINGPARAM("YPDOMAIN") },
     330             :     { RTL_CONSTASCII_STRINGPARAM("DNSDOMAIN") },
     331             :     { RTL_CONSTASCII_STRINGPARAM("NTDOMAIN") },
     332             :     { RTL_CONSTASCII_STRINGPARAM("OS") },
     333             :     { RTL_CONSTASCII_STRINGPARAM("") } // unknown
     334             : };
     335             : 
     336             : // Priority table for the environment types. Lower numbers define
     337             : // a higher priority. Equal numbers has the same priority that means
     338             : // that the first match wins!!
     339             : static const sal_Int16 aEnvPrioTable[ET_COUNT] =
     340             : {
     341             :     1,      // ET_HOST
     342             :     2,      // ET_IPDOMAIN
     343             :     2,      // ET_DNSDOMAIN
     344             :     2,      // ET_NTDOMAIN
     345             :     3,      // ET_OS
     346             :     99,     // ET_UNKNOWN
     347             : };
     348             : 
     349             : // Table with all fixed/predefined variables supported.
     350             : static const FixedVariable aFixedVarTable[] =
     351             : {
     352             :     { RTL_CONSTASCII_STRINGPARAM("$(inst)"),        PREDEFVAR_INST,         true  },
     353             :     { RTL_CONSTASCII_STRINGPARAM("$(prog)"),        PREDEFVAR_PROG,         true  },
     354             :     { RTL_CONSTASCII_STRINGPARAM("$(user)"),        PREDEFVAR_USER,         true  },
     355             :     { RTL_CONSTASCII_STRINGPARAM("$(work)"),        PREDEFVAR_WORK,         true  },      // Special variable (transient)!
     356             :     { RTL_CONSTASCII_STRINGPARAM("$(home)"),        PREDEFVAR_HOME,         true  },
     357             :     { RTL_CONSTASCII_STRINGPARAM("$(temp)"),        PREDEFVAR_TEMP,         true  },
     358             :     { RTL_CONSTASCII_STRINGPARAM("$(path)"),        PREDEFVAR_PATH,         true  },
     359             :     { RTL_CONSTASCII_STRINGPARAM("$(langid)"),      PREDEFVAR_LANGID,       false },
     360             :     { RTL_CONSTASCII_STRINGPARAM("$(vlang)"),       PREDEFVAR_VLANG,        false },
     361             :     { RTL_CONSTASCII_STRINGPARAM("$(instpath)"),    PREDEFVAR_INSTPATH,     true  },
     362             :     { RTL_CONSTASCII_STRINGPARAM("$(progpath)"),    PREDEFVAR_PROGPATH,     true  },
     363             :     { RTL_CONSTASCII_STRINGPARAM("$(userpath)"),    PREDEFVAR_USERPATH,     true  },
     364             :     { RTL_CONSTASCII_STRINGPARAM("$(insturl)"),     PREDEFVAR_INSTURL,      true  },
     365             :     { RTL_CONSTASCII_STRINGPARAM("$(progurl)"),     PREDEFVAR_PROGURL,      true  },
     366             :     { RTL_CONSTASCII_STRINGPARAM("$(userurl)"),     PREDEFVAR_USERURL,      true  },
     367             :     { RTL_CONSTASCII_STRINGPARAM("$(workdirurl)"),  PREDEFVAR_WORKDIRURL,   true  },  // Special variable (transient) and don't use for resubstitution!
     368             :     { RTL_CONSTASCII_STRINGPARAM("$(baseinsturl)"), PREDEFVAR_BASEINSTURL,  true  },
     369             :     { RTL_CONSTASCII_STRINGPARAM("$(userdataurl)"), PREDEFVAR_USERDATAURL,  true  },
     370             :     { RTL_CONSTASCII_STRINGPARAM("$(brandbaseurl)"),PREDEFVAR_BRANDBASEURL, true  }
     371             : };
     372             : 
     373             : //      Implementation helper classes
     374             : 
     375           0 : OperatingSystem SubstitutePathVariables_Impl::GetOperatingSystemFromString( const OUString& aOSString )
     376             : {
     377           0 :     for ( int i = 0; i < OS_COUNT; i++ )
     378             :     {
     379           0 :         if ( aOSString.equalsIgnoreAsciiCaseAsciiL( aOSTable[i].pOSString, aOSTable[i].nStrLen ))
     380           0 :             return (OperatingSystem)i;
     381             :     }
     382             : 
     383           0 :     return OS_UNKNOWN;
     384             : }
     385             : 
     386           0 : EnvironmentType SubstitutePathVariables_Impl::GetEnvTypeFromString( const OUString& aEnvTypeString )
     387             : {
     388           0 :     for ( int i = 0; i < ET_COUNT; i++ )
     389             :     {
     390           0 :         if ( aEnvTypeString.equalsIgnoreAsciiCaseAsciiL( aEnvTable[i].pOSString, aEnvTable[i].nStrLen ))
     391           0 :             return (EnvironmentType)i;
     392             :     }
     393             : 
     394           0 :     return ET_UNKNOWN;
     395             : }
     396             : 
     397           0 : SubstitutePathVariables_Impl::SubstitutePathVariables_Impl( const Link& aNotifyLink ) :
     398             :     utl::ConfigItem( OUString( "Office.Substitution" )),
     399             :     m_bYPDomainRetrieved( false ),
     400             :     m_bDNSDomainRetrieved( false ),
     401             :     m_bNTDomainRetrieved( false ),
     402             :     m_bHostRetrieved( false ),
     403             :     m_aListenerNotify( aNotifyLink ),
     404             :     m_aSharePointsNodeName( OUString( "SharePoints" )),
     405             :     m_aDirPropertyName( OUString( "/Directory" )),
     406             :     m_aEnvPropertyName( OUString( "/Environment" )),
     407           0 :     m_aLevelSep( OUString(  "/" ))
     408             : {
     409             :     // Enable notification mechanism
     410             :     // We need it to get information about changes outside these class on our configuration branch
     411           0 :     Sequence< OUString > aNotifySeq( 1 );
     412           0 :     aNotifySeq[0] = "SharePoints";
     413           0 :     EnableNotification( aNotifySeq, true );
     414           0 : }
     415             : 
     416           0 : SubstitutePathVariables_Impl::~SubstitutePathVariables_Impl()
     417             : {
     418           0 : }
     419             : 
     420           0 : void SubstitutePathVariables_Impl::GetSharePointsRules( SubstituteVariables& aSubstVarMap )
     421             : {
     422           0 :     Sequence< OUString > aSharePointNames;
     423           0 :     ReadSharePointsFromConfiguration( aSharePointNames );
     424             : 
     425           0 :     if ( aSharePointNames.getLength() > 0 )
     426             :     {
     427           0 :         sal_Int32 nSharePoints = 0;
     428             : 
     429             :         // Read SharePoints container from configuration
     430           0 :         while ( nSharePoints < aSharePointNames.getLength() )
     431             :         {
     432           0 :             OUString aSharePointNodeName( m_aSharePointsNodeName );
     433           0 :             aSharePointNodeName += "/";
     434           0 :             aSharePointNodeName += aSharePointNames[ nSharePoints ];
     435             : 
     436           0 :             SubstituteRuleVector aRuleSet;
     437           0 :             ReadSharePointRuleSetFromConfiguration( aSharePointNames[ nSharePoints ], aSharePointNodeName, aRuleSet );
     438           0 :             if ( !aRuleSet.empty() )
     439             :             {
     440             :                 // We have at minimum one rule. Filter the correct rule out of the rule set
     441             :                 // and put into our SubstituteVariable map
     442           0 :                 SubstituteRule aActiveRule;
     443           0 :                 if ( FilterRuleSet( aRuleSet, aActiveRule ))
     444             :                 {
     445             :                     // We have found an active rule
     446           0 :                     aActiveRule.aSubstVariable = aSharePointNames[ nSharePoints ];
     447             :                     aSubstVarMap.insert( SubstituteVariables::value_type(
     448           0 :                     aActiveRule.aSubstVariable, aActiveRule ));
     449           0 :                 }
     450             :             }
     451           0 :             ++nSharePoints;
     452           0 :         }
     453           0 :     }
     454           0 : }
     455             : 
     456           0 : void SubstitutePathVariables_Impl::Notify( const com::sun::star::uno::Sequence< OUString >& /*aPropertyNames*/ )
     457             : {
     458             :     // NOT implemented yet!
     459           0 : }
     460             : 
     461           0 : void SubstitutePathVariables_Impl::Commit()
     462             : {
     463           0 : }
     464             : 
     465             : //      private methods
     466             : 
     467           0 : OperatingSystem SubstitutePathVariables_Impl::GetOperatingSystem()
     468             : {
     469             : #ifdef SOLARIS
     470             :     return OS_SOLARIS;
     471             : #elif defined LINUX
     472           0 :     return OS_LINUX;
     473             : #elif defined WIN32
     474             :     return OS_WINDOWS;
     475             : #elif defined UNIX
     476             :     return OS_UNIX;
     477             : #else
     478             :     return OS_UNKNOWN;
     479             : #endif
     480             : }
     481             : 
     482           0 : const OUString& SubstitutePathVariables_Impl::GetYPDomainName()
     483             : {
     484           0 :     if ( !m_bYPDomainRetrieved )
     485             :     {
     486           0 :         m_aYPDomain = NetworkDomain::GetYPDomainName().toAsciiLowerCase();
     487           0 :         m_bYPDomainRetrieved = true;
     488             :     }
     489             : 
     490           0 :     return m_aYPDomain;
     491             : }
     492             : 
     493           0 : const OUString& SubstitutePathVariables_Impl::GetDNSDomainName()
     494             : {
     495           0 :     if ( !m_bDNSDomainRetrieved )
     496             :     {
     497           0 :         OUString   aTemp;
     498           0 :         osl::SocketAddr aSockAddr;
     499             :         oslSocketResult aResult;
     500             : 
     501           0 :         OUString aHostName = GetHostName();
     502           0 :         osl::SocketAddr::resolveHostname( aHostName, aSockAddr );
     503           0 :         aTemp = aSockAddr.getHostname( &aResult );
     504             : 
     505             :         // DNS domain name begins after the first "."
     506           0 :         sal_Int32 nIndex = aTemp.indexOf( '.' );
     507           0 :         if ( nIndex >= 0 && aTemp.getLength() > nIndex+1 )
     508           0 :             m_aDNSDomain = aTemp.copy( nIndex+1 ).toAsciiLowerCase();
     509             :         else
     510           0 :             m_aDNSDomain = "";
     511             : 
     512           0 :         m_bDNSDomainRetrieved = true;
     513             :     }
     514             : 
     515           0 :     return m_aDNSDomain;
     516             : }
     517             : 
     518           0 : const OUString& SubstitutePathVariables_Impl::GetNTDomainName()
     519             : {
     520           0 :     if ( !m_bNTDomainRetrieved )
     521             :     {
     522           0 :         m_aNTDomain = NetworkDomain::GetNTDomainName().toAsciiLowerCase();
     523           0 :         m_bNTDomainRetrieved = true;
     524             :     }
     525             : 
     526           0 :     return m_aNTDomain;
     527             : }
     528             : 
     529           0 : const OUString& SubstitutePathVariables_Impl::GetHostName()
     530             : {
     531           0 :     if (!m_bHostRetrieved)
     532             :     {
     533             :         oslSocketResult aSocketResult;
     534           0 :         m_aHost = osl::SocketAddr::getLocalHostname( &aSocketResult ).toAsciiLowerCase();
     535             :     }
     536             : 
     537           0 :     return m_aHost;
     538             : }
     539             : 
     540           0 : bool SubstitutePathVariables_Impl::FilterRuleSet( const SubstituteRuleVector& aRuleSet, SubstituteRule& aActiveRule )
     541             : {
     542           0 :     bool bResult = false;
     543             : 
     544           0 :     if ( !aRuleSet.empty() )
     545             :     {
     546           0 :         const sal_uInt32 nCount = aRuleSet.size();
     547             : 
     548           0 :         sal_Int16 nPrioCurrentRule = aEnvPrioTable[ ET_UNKNOWN ];
     549           0 :         for ( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
     550             :         {
     551           0 :             const SubstituteRule& aRule = aRuleSet[nIndex];
     552           0 :             EnvironmentType eEnvType        = aRule.aEnvType;
     553             : 
     554             :             // Check if environment type has a higher priority than current one!
     555           0 :             if ( nPrioCurrentRule > aEnvPrioTable[eEnvType] )
     556             :             {
     557           0 :                 switch ( eEnvType )
     558             :                 {
     559             :                     case ET_HOST:
     560             :                     {
     561           0 :                         OUString aHost = GetHostName();
     562           0 :                         OUString aHostStr;
     563           0 :                         aRule.aEnvValue >>= aHostStr;
     564           0 :                         aHostStr = aHostStr.toAsciiLowerCase();
     565             : 
     566             :                         // Pattern match if domain environment match
     567           0 :                         WildCard aPattern(aHostStr);
     568           0 :                         bool bMatch = aPattern.Matches(aHost);
     569           0 :                         if ( bMatch )
     570             :                         {
     571           0 :                             aActiveRule      = aRule;
     572           0 :                             bResult          = true;
     573           0 :                             nPrioCurrentRule = aEnvPrioTable[eEnvType];
     574           0 :                         }
     575             :                     }
     576           0 :                     break;
     577             : 
     578             :                     case ET_YPDOMAIN:
     579             :                     case ET_DNSDOMAIN:
     580             :                     case ET_NTDOMAIN:
     581             :                     {
     582           0 :                         OUString   aDomain;
     583           0 :                         OUString   aDomainStr;
     584           0 :                         aRule.aEnvValue >>= aDomainStr;
     585           0 :                         aDomainStr = aDomainStr.toAsciiLowerCase();
     586             : 
     587             :                         // Retrieve the correct domain value
     588           0 :                         if ( eEnvType == ET_YPDOMAIN )
     589           0 :                             aDomain = GetYPDomainName();
     590           0 :                         else if ( eEnvType == ET_DNSDOMAIN )
     591           0 :                             aDomain = GetDNSDomainName();
     592             :                         else
     593           0 :                             aDomain = GetNTDomainName();
     594             : 
     595             :                         // Pattern match if domain environment match
     596           0 :                         WildCard aPattern(aDomainStr);
     597           0 :                         bool bMatch = aPattern.Matches(aDomain);
     598           0 :                         if ( bMatch )
     599             :                         {
     600           0 :                             aActiveRule      = aRule;
     601           0 :                             bResult          = true;
     602           0 :                             nPrioCurrentRule = aEnvPrioTable[eEnvType];
     603           0 :                         }
     604             :                     }
     605           0 :                     break;
     606             : 
     607             :                     case ET_OS:
     608             :                     {
     609             :                         // No pattern matching for OS type
     610           0 :                         OperatingSystem eOSType = GetOperatingSystem();
     611             : 
     612           0 :                         sal_Int16 nValue = 0;
     613           0 :                         aRule.aEnvValue >>= nValue;
     614             : 
     615           0 :                         bool            bUnix = ( eOSType == OS_LINUX ) || ( eOSType == OS_SOLARIS );
     616           0 :                         OperatingSystem eRuleOSType = (OperatingSystem)nValue;
     617             : 
     618             :                         // Match if OS identical or rule is set to UNIX and OS is LINUX/SOLARIS!
     619           0 :                         if (( eRuleOSType == eOSType ) || ( eRuleOSType == OS_UNIX && bUnix ))
     620             :                         {
     621           0 :                             aActiveRule      = aRule;
     622           0 :                             bResult          = true;
     623           0 :                             nPrioCurrentRule = aEnvPrioTable[eEnvType];
     624             :                         }
     625             :                     }
     626           0 :                     break;
     627             : 
     628             :                     case ET_UNKNOWN: // nothing to do
     629           0 :                         break;
     630             : 
     631             :                     default:
     632           0 :                         break;
     633             :                 }
     634             :             }
     635             :         }
     636             :     }
     637             : 
     638           0 :     return bResult;
     639             : }
     640             : 
     641           0 : void SubstitutePathVariables_Impl::ReadSharePointsFromConfiguration( Sequence< OUString >& aSharePointsSeq )
     642             : {
     643             :     //returns all the names of all share point nodes
     644           0 :     aSharePointsSeq = GetNodeNames( m_aSharePointsNodeName );
     645           0 : }
     646             : 
     647           0 : void SubstitutePathVariables_Impl::ReadSharePointRuleSetFromConfiguration(
     648             :         const OUString& aSharePointName,
     649             :         const OUString& aSharePointNodeName,
     650             :         SubstituteRuleVector& rRuleSet )
     651             : {
     652           0 :     Sequence< OUString > aSharePointMappingsNodeNames = GetNodeNames( aSharePointNodeName, utl::CONFIG_NAME_LOCAL_PATH );
     653             : 
     654           0 :     sal_Int32 nSharePointMapping = 0;
     655           0 :     while ( nSharePointMapping < aSharePointMappingsNodeNames.getLength() )
     656             :     {
     657           0 :         OUString aSharePointMapping( aSharePointNodeName );
     658           0 :         aSharePointMapping += m_aLevelSep;
     659           0 :         aSharePointMapping += aSharePointMappingsNodeNames[ nSharePointMapping ];
     660             : 
     661             :         // Read SharePointMapping
     662           0 :         OUString aDirValue;
     663           0 :         OUString aDirProperty( aSharePointMapping );
     664           0 :         aDirProperty += m_aDirPropertyName;
     665             : 
     666             :         // Read only the directory property
     667           0 :         Sequence< OUString > aDirPropertySeq( 1 );
     668           0 :         aDirPropertySeq[0] = aDirProperty;
     669             : 
     670           0 :         Sequence< Any > aValueSeq = GetProperties( aDirPropertySeq );
     671           0 :         if ( aValueSeq.getLength() == 1 )
     672           0 :             aValueSeq[0] >>= aDirValue;
     673             : 
     674             :         // Read the environment setting
     675           0 :         OUString aEnvUsed;
     676           0 :         OUString aEnvProperty( aSharePointMapping );
     677           0 :         aEnvProperty += m_aEnvPropertyName;
     678           0 :         Sequence< OUString > aEnvironmentVariable = GetNodeNames( aEnvProperty );
     679             : 
     680             :         // Filter the property which has a value set
     681           0 :         Sequence< OUString > aEnvUsedPropertySeq( aEnvironmentVariable.getLength() );
     682             : 
     683           0 :         OUString aEnvUsePropNameTemplate( aEnvProperty );
     684           0 :         aEnvUsePropNameTemplate += m_aLevelSep;
     685             : 
     686           0 :         for ( sal_Int32 nProperty = 0; nProperty < aEnvironmentVariable.getLength(); nProperty++ )
     687           0 :             aEnvUsedPropertySeq[nProperty] = aEnvUsePropNameTemplate + aEnvironmentVariable[nProperty];
     688             : 
     689           0 :         Sequence< Any > aEnvUsedValueSeq;
     690           0 :         aEnvUsedValueSeq = GetProperties( aEnvUsedPropertySeq );
     691             : 
     692           0 :         OUString aEnvUsedValue;
     693           0 :         for ( sal_Int32 nIndex = 0; nIndex < aEnvironmentVariable.getLength(); nIndex++ )
     694             :         {
     695           0 :             if ( aEnvUsedValueSeq[nIndex] >>= aEnvUsedValue )
     696             :             {
     697           0 :                 aEnvUsed = aEnvironmentVariable[nIndex];
     698           0 :                 break;
     699             :             }
     700             :         }
     701             : 
     702             :         // Decode the environment and optional the operatng system settings
     703           0 :         Any                             aEnvValue;
     704           0 :         EnvironmentType eEnvType = GetEnvTypeFromString( aEnvUsed );
     705           0 :         if ( eEnvType == ET_OS )
     706             :         {
     707           0 :             OperatingSystem eOSType = GetOperatingSystemFromString( aEnvUsedValue );
     708           0 :             aEnvValue <<= (sal_Int16)eOSType;
     709             :         }
     710             :         else
     711           0 :             aEnvValue <<= aEnvUsedValue;
     712             : 
     713             :         // Create rule struct and push it into the rule set
     714           0 :         SubstituteRule aRule( aSharePointName, aDirValue, aEnvValue, eEnvType );
     715           0 :         rRuleSet.push_back( aRule );
     716             : 
     717           0 :         ++nSharePointMapping;
     718           0 :     }
     719           0 : }
     720             : 
     721           0 : SubstitutePathVariables::SubstitutePathVariables( const Reference< XComponentContext >& xContext ) :
     722             :     SubstitutePathVariables_BASE(m_aMutex),
     723             :     m_aImpl( LINK( this, SubstitutePathVariables, implts_ConfigurationNotify )),
     724           0 :     m_xContext( xContext )
     725             : {
     726             :     int i;
     727             : 
     728           0 :     SetPredefinedPathVariables( m_aPreDefVars );
     729           0 :     m_aImpl.GetSharePointsRules( m_aSubstVarMap );
     730             : 
     731             :     // Init the predefined/fixed variable to index hash map
     732           0 :     for ( i = 0; i < PREDEFVAR_COUNT; i++ )
     733             :     {
     734             :         // Store variable name into struct of predefined/fixed variables
     735           0 :         m_aPreDefVars.m_FixedVarNames[i] = OUString::createFromAscii( aFixedVarTable[i].pVarName );
     736             : 
     737             :         // Create hash map entry
     738             :         m_aPreDefVarMap.insert( VarNameToIndexMap::value_type(
     739           0 :             m_aPreDefVars.m_FixedVarNames[i], aFixedVarTable[i].nEnumValue ) );
     740             :     }
     741             : 
     742             :     // Sort predefined/fixed variable to path length
     743           0 :     for ( i = 0; i < PREDEFVAR_COUNT; i++ )
     744             :     {
     745           0 :         if (( i != PREDEFVAR_WORKDIRURL ) && ( i != PREDEFVAR_PATH ))
     746             :         {
     747             :             // Special path variables, don't include into automatic resubstituion search!
     748             :             // $(workdirurl) is not allowed to resubstitute! This variable is the value of path settings entry
     749             :             // and it could be possible that it will be resubstituted by itself!!
     750             :             // Example: WORK_PATH=c:\test, $(workdirurl)=WORK_PATH => WORK_PATH=$(workdirurl) and this cannot be substituted!
     751             :             ReSubstFixedVarOrder aFixedVar;
     752           0 :             aFixedVar.eVariable       = aFixedVarTable[i].nEnumValue;
     753           0 :             aFixedVar.nVarValueLength = m_aPreDefVars.m_FixedVar[(sal_Int32)aFixedVar.eVariable].getLength();
     754           0 :             m_aReSubstFixedVarOrder.push_back( aFixedVar );
     755             :         }
     756             :     }
     757           0 :     m_aReSubstFixedVarOrder.sort();
     758             : 
     759             :     // Sort user variables to path length
     760           0 :     SubstituteVariables::const_iterator pIter;
     761           0 :     for ( pIter = m_aSubstVarMap.begin(); pIter != m_aSubstVarMap.end(); ++pIter )
     762             :     {
     763           0 :         ReSubstUserVarOrder aUserOrderVar;
     764           0 :         aUserOrderVar.aVarName = "$(" + pIter->second.aSubstVariable + ")";
     765           0 :         aUserOrderVar.nVarValueLength = pIter->second.aSubstVariable.getLength();
     766           0 :         m_aReSubstUserVarOrder.push_back( aUserOrderVar );
     767           0 :     }
     768           0 :     m_aReSubstUserVarOrder.sort();
     769           0 : }
     770             : 
     771           0 : SubstitutePathVariables::~SubstitutePathVariables()
     772             : {
     773           0 : }
     774             : 
     775             : // XStringSubstitution
     776           0 : OUString SAL_CALL SubstitutePathVariables::substituteVariables( const OUString& aText, sal_Bool bSubstRequired )
     777             : throw ( NoSuchElementException, RuntimeException, std::exception )
     778             : {
     779           0 :     osl::MutexGuard g(rBHelper.rMutex);
     780           0 :     return impl_substituteVariable( aText, bSubstRequired );
     781             : }
     782             : 
     783           0 : OUString SAL_CALL SubstitutePathVariables::reSubstituteVariables( const OUString& aText )
     784             : throw ( RuntimeException, std::exception )
     785             : {
     786           0 :     osl::MutexGuard g(rBHelper.rMutex);
     787           0 :     return impl_reSubstituteVariables( aText );
     788             : }
     789             : 
     790           0 : OUString SAL_CALL SubstitutePathVariables::getSubstituteVariableValue( const OUString& aVariable )
     791             : throw ( NoSuchElementException, RuntimeException, std::exception )
     792             : {
     793           0 :     osl::MutexGuard g(rBHelper.rMutex);
     794           0 :     return impl_getSubstituteVariableValue( aVariable );
     795             : }
     796             : 
     797             : //      protected methods
     798             : 
     799           0 : IMPL_LINK_NOARG(SubstitutePathVariables, implts_ConfigurationNotify)
     800             : {
     801             :     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
     802           0 :     osl::MutexGuard g(rBHelper.rMutex);
     803             : 
     804           0 :     return 0;
     805             : }
     806             : 
     807           0 : OUString SubstitutePathVariables::ConvertOSLtoUCBURL( const OUString& aOSLCompliantURL ) const
     808             : {
     809           0 :     OUString aResult;
     810           0 :     OUString   aTemp;
     811             : 
     812           0 :     osl::FileBase::getSystemPathFromFileURL( aOSLCompliantURL, aTemp );
     813           0 :     utl::LocalFileHelper::ConvertPhysicalNameToURL( aTemp, aResult );
     814             : 
     815             :     // Not all OSL URL's can be mapped to UCB URL's!
     816           0 :     if ( aResult.isEmpty() )
     817           0 :         return aOSLCompliantURL;
     818             :     else
     819           0 :         return aResult;
     820             : }
     821             : 
     822           0 : OUString SubstitutePathVariables::GetWorkPath() const
     823             : {
     824           0 :     OUString aWorkPath;
     825           0 :     css::uno::Reference< css::container::XHierarchicalNameAccess > xPaths(officecfg::Office::Paths::Paths::get(m_xContext), css::uno::UNO_QUERY_THROW);
     826           0 :     OUString xWork;
     827           0 :     if (!(xPaths->getByHierarchicalName("['Work']/WritePath") >>= xWork))
     828             :         // fallback in case config layer does not return an useable work dir value.
     829           0 :         aWorkPath = GetWorkVariableValue();
     830             : 
     831           0 :     return aWorkPath;
     832             : }
     833             : 
     834           0 : OUString SubstitutePathVariables::GetWorkVariableValue() const
     835             : {
     836           0 :     OUString aWorkPath;
     837           0 :     boost::optional<OUString> x(officecfg::Office::Paths::Variables::Work::get(m_xContext));
     838           0 :     if (!x)
     839             :     {
     840             :         // fallback to $HOME in case platform dependend config layer does not return
     841             :         // an usuable work dir value.
     842           0 :         osl::Security aSecurity;
     843           0 :         aSecurity.getHomeDir( aWorkPath );
     844             :     }
     845             :     else
     846           0 :         aWorkPath = x.get();
     847           0 :     return ConvertOSLtoUCBURL( aWorkPath );
     848             : }
     849             : 
     850           0 : OUString SubstitutePathVariables::GetHomeVariableValue() const
     851             : {
     852           0 :     osl::Security   aSecurity;
     853           0 :     OUString   aHomePath;
     854             : 
     855           0 :     aSecurity.getHomeDir( aHomePath );
     856           0 :     return ConvertOSLtoUCBURL( aHomePath );
     857             : }
     858             : 
     859           0 : OUString SubstitutePathVariables::GetPathVariableValue() const
     860             : {
     861             : 
     862           0 :     OUString aRetStr;
     863           0 :     const char*   pEnv = getenv( "PATH" );
     864             : 
     865           0 :     if ( pEnv )
     866             :     {
     867           0 :         const int PATH_EXTEND_FACTOR = 120;
     868           0 :         OUString       aTmp;
     869           0 :         OUString       aPathList( pEnv, strlen( pEnv ), osl_getThreadTextEncoding() );
     870           0 :         OUStringBuffer aPathStrBuffer( aPathList.getLength() * PATH_EXTEND_FACTOR / 100 );
     871             : 
     872           0 :         bool      bAppendSep = false;
     873           0 :         sal_Int32 nToken = 0;
     874           0 :         do
     875             :         {
     876           0 :             OUString sToken = aPathList.getToken(0, SAL_PATHSEPARATOR, nToken);
     877           0 :             if (!sToken.isEmpty())
     878             :             {
     879           0 :                 osl::FileBase::getFileURLFromSystemPath( sToken, aTmp );
     880           0 :                 if ( bAppendSep )
     881           0 :                     aPathStrBuffer.appendAscii( ";" ); // Office uses ';' as path separator
     882           0 :                 aPathStrBuffer.append( aTmp );
     883           0 :                 bAppendSep = true;
     884           0 :             }
     885             :         }
     886           0 :         while(nToken>=0);
     887             : 
     888           0 :         aRetStr = aPathStrBuffer.makeStringAndClear();
     889             :     }
     890             : 
     891           0 :     return aRetStr;
     892             : }
     893             : 
     894           0 : OUString SubstitutePathVariables::impl_substituteVariable( const OUString& rText, bool bSubstRequired )
     895             : throw ( NoSuchElementException, RuntimeException )
     896             : {
     897             :     // This is maximal recursive depth supported!
     898           0 :     const sal_Int32 nMaxRecursiveDepth = 8;
     899             : 
     900           0 :     OUString   aWorkText = rText;
     901           0 :     OUString   aResult;
     902             : 
     903             :     // Use vector with strings to detect endless recursions!
     904           0 :     std::vector< OUString > aEndlessRecursiveDetector;
     905             : 
     906             :     // Search for first occurrence of "$(...".
     907           0 :     sal_Int32   nDepth = 0;
     908           0 :     bool        bSubstitutionCompleted = false;
     909           0 :     sal_Int32   nPosition = aWorkText.indexOf( "$(" );
     910           0 :     sal_Int32   nLength = 0; // = count of letters from "$(" to ")" in string
     911           0 :     bool        bVarNotSubstituted = false;
     912             : 
     913             :     // Have we found any variable like "$(...)"?
     914           0 :     if ( nPosition != -1 )
     915             :     {
     916             :         // Yes; Get length of found variable.
     917             :         // If no ")" was found - nLength is set to 0 by default! see before.
     918           0 :         sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
     919           0 :         if ( nEndPosition != -1 )
     920           0 :             nLength = nEndPosition - nPosition + 1;
     921             :     }
     922             : 
     923             :     // Is there something to replace ?
     924           0 :     bool bWorkRetrieved       = false;
     925           0 :     bool bWorkDirURLRetrieved = false;
     926           0 :     while ( !bSubstitutionCompleted && nDepth < nMaxRecursiveDepth )
     927             :     {
     928           0 :         while ( ( nPosition != -1 ) && ( nLength > 3 ) ) // "$(" ")"
     929             :         {
     930             :             // YES; Get the next variable for replace.
     931           0 :             sal_Int32     nReplaceLength  = 0;
     932           0 :             OUString aReplacement;
     933           0 :             OUString aSubString      = aWorkText.copy( nPosition, nLength );
     934           0 :             OUString aSubVarString;
     935             : 
     936             :             // Path variables are not case sensitive!
     937           0 :             aSubVarString = aSubString.toAsciiLowerCase();
     938           0 :             VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( aSubVarString );
     939           0 :             if ( pNTOIIter != m_aPreDefVarMap.end() )
     940             :             {
     941             :                 // Fixed/Predefined variable found
     942           0 :                 PreDefVariable nIndex = (PreDefVariable)pNTOIIter->second;
     943             : 
     944             :                 // Determine variable value and length from array/table
     945           0 :                 if ( nIndex == PREDEFVAR_WORK && !bWorkRetrieved )
     946             :                 {
     947             :                     // Transient value, retrieve it again
     948           0 :                     m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ] = GetWorkVariableValue();
     949           0 :                     bWorkRetrieved = true;
     950             :                 }
     951           0 :                 else if ( nIndex == PREDEFVAR_WORKDIRURL && !bWorkDirURLRetrieved )
     952             :                 {
     953             :                     // Transient value, retrieve it again
     954           0 :                     m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ] = GetWorkPath();
     955           0 :                     bWorkDirURLRetrieved = true;
     956             :                 }
     957             : 
     958             :                 // Check preconditions to substitue path variables.
     959             :                 // 1. A path variable can only be substituted if it follows a ';'!
     960             :                 // 2. It's located exactly at the start of the string being substituted!
     961           0 :                 if (( aFixedVarTable[ int( nIndex ) ].bAbsPath && (( nPosition == 0 ) || (( nPosition > 0 ) && ( aWorkText[nPosition-1] == ';')))) ||
     962           0 :             ( !aFixedVarTable[ int( nIndex ) ].bAbsPath ))
     963             :         {
     964           0 :                     aReplacement = m_aPreDefVars.m_FixedVar[ (PreDefVariable)nIndex ];
     965           0 :                     nReplaceLength = nLength;
     966             :                 }
     967             :             }
     968             :             else
     969             :             {
     970             :                 // Extract the variable name and try to find in the user defined variable set
     971           0 :                 OUString aVarName = aSubString.copy( 2, nLength-3 );
     972           0 :                 SubstituteVariables::const_iterator pIter = m_aSubstVarMap.find( aVarName );
     973           0 :                 if ( pIter != m_aSubstVarMap.end() )
     974             :                 {
     975             :                     // Found.
     976           0 :                     aReplacement = pIter->second.aSubstValue;
     977           0 :                     nReplaceLength = nLength;
     978           0 :                 }
     979             :             }
     980             : 
     981             :             // Have we found something to replace?
     982           0 :             if ( nReplaceLength > 0 )
     983             :             {
     984             :                 // Yes ... then do it.
     985           0 :                 aWorkText = aWorkText.replaceAt( nPosition, nReplaceLength, aReplacement );
     986             :             }
     987             :             else
     988             :             {
     989             :                 // Variable not known
     990           0 :                 bVarNotSubstituted = true;
     991           0 :                 nPosition += nLength;
     992             :             }
     993             : 
     994             :             // Step after replaced text! If no text was replaced (unknown variable!),
     995             :             // length of aReplacement is 0 ... and we don't step then.
     996           0 :             nPosition += aReplacement.getLength();
     997             : 
     998             :             // We must control index in string before call something at OUString!
     999             :             // The OUString-implementation don't do it for us :-( but the result is not defined otherwise.
    1000           0 :             if ( nPosition + 1 > aWorkText.getLength() )
    1001             :             {
    1002             :                 // Position is out of range. Break loop!
    1003           0 :                 nPosition = -1;
    1004           0 :                 nLength = 0;
    1005             :             }
    1006             :             else
    1007             :             {
    1008             :                 // Else; Position is valid. Search for next variable to replace.
    1009           0 :                 nPosition = aWorkText.indexOf( "$(", nPosition );
    1010             :                 // Have we found any variable like "$(...)"?
    1011           0 :                 if ( nPosition != -1 )
    1012             :                 {
    1013             :                     // Yes; Get length of found variable. If no ")" was found - nLength must set to 0!
    1014           0 :                     nLength = 0;
    1015           0 :                     sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
    1016           0 :                     if ( nEndPosition != -1 )
    1017           0 :                         nLength = nEndPosition - nPosition + 1;
    1018             :                 }
    1019             :             }
    1020           0 :         }
    1021             : 
    1022           0 :         nPosition = aWorkText.indexOf( "$(" );
    1023           0 :         if ( nPosition == -1 )
    1024             :         {
    1025           0 :             bSubstitutionCompleted = true;
    1026           0 :             break; // All variables are substituted
    1027             :         }
    1028             :         else
    1029             :         {
    1030             :             // Check for recursion
    1031           0 :             const sal_uInt32 nCount = aEndlessRecursiveDetector.size();
    1032           0 :             for ( sal_uInt32 i=0; i < nCount; i++ )
    1033             :             {
    1034           0 :                 if ( aEndlessRecursiveDetector[i] == aWorkText )
    1035             :                 {
    1036           0 :                     if ( bVarNotSubstituted )
    1037           0 :                         break; // Not all variables could be substituted!
    1038             :                     else
    1039             :                     {
    1040           0 :                         nDepth = nMaxRecursiveDepth;
    1041           0 :                         break; // Recursion detected!
    1042             :                     }
    1043             :                 }
    1044             :             }
    1045             : 
    1046           0 :             aEndlessRecursiveDetector.push_back( aWorkText );
    1047             : 
    1048             :             // Initialize values for next
    1049           0 :             sal_Int32 nEndPosition = aWorkText.indexOf( ')', nPosition );
    1050           0 :             if ( nEndPosition != -1 )
    1051           0 :                 nLength = nEndPosition - nPosition + 1;
    1052           0 :             bVarNotSubstituted = false;
    1053           0 :             ++nDepth;
    1054             :         }
    1055             :     }
    1056             : 
    1057             :     // Fill return value with result
    1058           0 :     if ( bSubstitutionCompleted )
    1059             :     {
    1060             :         // Substitution successful!
    1061           0 :         aResult = aWorkText;
    1062             :     }
    1063             :     else
    1064             :     {
    1065             :         // Substitution not successful!
    1066           0 :         if ( nDepth == nMaxRecursiveDepth )
    1067             :         {
    1068             :             // recursion depth reached!
    1069           0 :             if ( bSubstRequired )
    1070             :             {
    1071           0 :                 OUString aMsg( "Endless recursion detected. Cannot substitute variables!" );
    1072           0 :                 throw NoSuchElementException( aMsg, (cppu::OWeakObject *)this );
    1073             :             }
    1074             :             else
    1075           0 :                 aResult = rText;
    1076             :         }
    1077             :         else
    1078             :         {
    1079             :             // variable in text but unknown!
    1080           0 :             if ( bSubstRequired )
    1081             :             {
    1082           0 :                 OUString aMsg( "Unknown variable found!" );
    1083           0 :                 throw NoSuchElementException( aMsg, (cppu::OWeakObject *)this );
    1084             :             }
    1085             :             else
    1086           0 :                 aResult = aWorkText;
    1087             :         }
    1088             :     }
    1089             : 
    1090           0 :     return aResult;
    1091             : }
    1092             : 
    1093           0 : OUString SubstitutePathVariables::impl_reSubstituteVariables( const OUString& rURL )
    1094             : throw ( RuntimeException )
    1095             : {
    1096           0 :     OUString aURL;
    1097             : 
    1098           0 :     INetURLObject aUrl( rURL );
    1099           0 :     if ( !aUrl.HasError() )
    1100           0 :         aURL = aUrl.GetMainURL( INetURLObject::NO_DECODE );
    1101             :     else
    1102             :     {
    1103             :         // Convert a system path to a UCB compliant URL before resubstitution
    1104           0 :         OUString aTemp;
    1105           0 :         if ( osl::FileBase::getFileURLFromSystemPath( rURL, aTemp ) == osl::FileBase::E_None )
    1106             :         {
    1107           0 :             aTemp = ConvertOSLtoUCBURL( aTemp );
    1108           0 :             if ( !aTemp.isEmpty() )
    1109             :             {
    1110           0 :                 aURL = INetURLObject( aTemp ).GetMainURL( INetURLObject::NO_DECODE );
    1111           0 :                 if( aURL.isEmpty() )
    1112           0 :                     return rURL;
    1113             :             }
    1114             :             else
    1115           0 :                 return rURL;
    1116             :         }
    1117             :         else
    1118             :         {
    1119             :             // rURL is not a valid URL nor a osl system path. Give up and return error!
    1120           0 :             return rURL;
    1121           0 :         }
    1122             :     }
    1123             : 
    1124             :     // Get transient predefined path variable $(work) value before starting resubstitution
    1125           0 :     m_aPreDefVars.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
    1126             : 
    1127             :     for (;;)
    1128             :     {
    1129           0 :         bool bVariableFound = false;
    1130             : 
    1131           0 :         for (ReSubstFixedVarOrderVector::const_iterator i(
    1132           0 :                  m_aReSubstFixedVarOrder.begin());
    1133           0 :              i != m_aReSubstFixedVarOrder.end(); ++i)
    1134             :         {
    1135           0 :             OUString aValue = m_aPreDefVars.m_FixedVar[i->eVariable];
    1136           0 :             sal_Int32 nPos = aURL.indexOf( aValue );
    1137           0 :             if ( nPos >= 0 )
    1138             :             {
    1139           0 :                 bool bMatch = true;
    1140           0 :                 if ( i->eVariable == PREDEFVAR_LANGID ||
    1141           0 :                      i->eVariable == PREDEFVAR_VLANG )
    1142             :                 {
    1143             :                     // Special path variables as they can occur in the middle of a path. Only match if they
    1144             :                     // describe a whole directory and not only a substring of a directory!
    1145           0 :                     const sal_Unicode* pStr = aURL.getStr();
    1146             : 
    1147           0 :                     if ( nPos > 0 )
    1148           0 :                         bMatch = ( aURL[ nPos-1 ] == '/' );
    1149             : 
    1150           0 :                     if ( bMatch )
    1151             :                     {
    1152           0 :                         if ( nPos + aValue.getLength() < aURL.getLength() )
    1153           0 :                             bMatch = ( pStr[ nPos + aValue.getLength() ] == '/' );
    1154             :                     }
    1155             :                 }
    1156             : 
    1157           0 :                 if ( bMatch )
    1158             :                 {
    1159           0 :                     aURL = aURL.replaceAt(
    1160             :                         nPos, aValue.getLength(),
    1161           0 :                         m_aPreDefVars.m_FixedVarNames[i->eVariable]);
    1162           0 :                     bVariableFound = true; // Resubstitution not finished yet!
    1163           0 :                     break;
    1164             :                 }
    1165             :             }
    1166           0 :         }
    1167             : 
    1168             :         // This part can be iteratered more than one time as variables can contain variables again!
    1169           0 :         for (ReSubstUserVarOrderVector::const_iterator i(
    1170           0 :                  m_aReSubstUserVarOrder.begin());
    1171           0 :              i != m_aReSubstUserVarOrder.end(); ++i)
    1172             :         {
    1173           0 :             OUString aVarValue = i->aVarName;
    1174           0 :             sal_Int32 nPos = aURL.indexOf( aVarValue );
    1175           0 :             if ( nPos >= 0 )
    1176             :             {
    1177           0 :                 aURL = aURL.replaceAt(
    1178           0 :                     nPos, aVarValue.getLength(), "$(" + aVarValue + ")");
    1179           0 :                 bVariableFound = true;  // Resubstitution not finished yet!
    1180             :             }
    1181           0 :         }
    1182             : 
    1183           0 :         if ( !bVariableFound )
    1184             :         {
    1185           0 :             return aURL;
    1186             :         }
    1187           0 :     }
    1188             : }
    1189             : 
    1190             : // This method support both request schemes "$("<varname>")" or "<varname>".
    1191           0 : OUString SubstitutePathVariables::impl_getSubstituteVariableValue( const OUString& rVariable )
    1192             : throw ( NoSuchElementException, RuntimeException )
    1193             : {
    1194           0 :     OUString aVariable;
    1195             : 
    1196           0 :     sal_Int32 nPos = rVariable.indexOf( "$(" );
    1197           0 :     if ( nPos == -1 )
    1198             :     {
    1199             :         // Prepare variable name before hash map access
    1200           0 :         aVariable = "$(" + rVariable + ")";
    1201             :     }
    1202             : 
    1203           0 :     VarNameToIndexMap::const_iterator pNTOIIter = m_aPreDefVarMap.find( ( nPos == -1 ) ? aVariable : rVariable );
    1204             : 
    1205             :     // Fixed/Predefined variable
    1206           0 :     if ( pNTOIIter != m_aPreDefVarMap.end() )
    1207             :     {
    1208           0 :         PreDefVariable nIndex = (PreDefVariable)pNTOIIter->second;
    1209           0 :         return m_aPreDefVars.m_FixedVar[(sal_Int32)nIndex];
    1210             :     }
    1211             :     else
    1212             :     {
    1213             :         // Prepare variable name before hash map access
    1214           0 :         if ( nPos >= 0 )
    1215             :         {
    1216           0 :             if ( rVariable.getLength() > 3 )
    1217           0 :                 aVariable = rVariable.copy( 2, rVariable.getLength() - 3 );
    1218             :             else
    1219             :             {
    1220           0 :                 OUString aExceptionText("Unknown variable!");
    1221           0 :                 throw NoSuchElementException(aExceptionText, (cppu::OWeakObject *)this);
    1222             :             }
    1223             :         }
    1224             :         else
    1225           0 :             aVariable = rVariable;
    1226             : 
    1227             :         // User defined variable
    1228           0 :         SubstituteVariables::const_iterator pIter = m_aSubstVarMap.find( aVariable );
    1229           0 :         if ( pIter != m_aSubstVarMap.end() )
    1230             :         {
    1231             :             // found!
    1232           0 :             return pIter->second.aSubstValue;
    1233             :         }
    1234             : 
    1235           0 :         OUString aExceptionText("Unknown variable!");
    1236           0 :         throw NoSuchElementException(aExceptionText, (cppu::OWeakObject *)this);
    1237           0 :     }
    1238             : }
    1239             : 
    1240           0 : void SubstitutePathVariables::SetPredefinedPathVariables( PredefinedPathVariables& aPreDefPathVariables )
    1241             : {
    1242             : 
    1243           0 :     aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL] = "$BRAND_BASE_DIR";
    1244             :     rtl::Bootstrap::expandMacros(
    1245           0 :         aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL]);
    1246             : 
    1247             :     // Get inspath and userpath from bootstrap mechanism in every case as file URL
    1248             :     ::utl::Bootstrap::PathStatus aState;
    1249           0 :     OUString              sVal;
    1250             : 
    1251           0 :     aState = utl::Bootstrap::locateUserData( sVal );
    1252             :     //There can be the valid case that there is no user installation.
    1253             :     //TODO: Is that still the case? (With OOo 3.4, "unopkg sync" was run as part
    1254             :     // of the setup. Then no user installation was required.)
    1255             :     //Therefore we do not assert here.
    1256           0 :     if( aState == ::utl::Bootstrap::PATH_EXISTS ) {
    1257           0 :         aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ] = ConvertOSLtoUCBURL( sVal );
    1258             :     }
    1259             : 
    1260             :     // Set $(inst), $(instpath), $(insturl)
    1261           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ] = aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL];
    1262           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTURL ]    = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
    1263           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INST ]       = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
    1264             :     // New variable of hierachy service (#i32656#)
    1265           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_BASEINSTURL ]= aPreDefPathVariables.m_FixedVar[ PREDEFVAR_INSTPATH ];
    1266             : 
    1267             :     // Set $(user), $(userpath), $(userurl)
    1268           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERURL ]    = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
    1269           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USER ]       = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
    1270             :     // New variable of hierachy service (#i32656#)
    1271           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERDATAURL ]= aPreDefPathVariables.m_FixedVar[ PREDEFVAR_USERPATH ];
    1272             : 
    1273             :     // Detect the program directory
    1274             :     // Set $(prog), $(progpath), $(progurl)
    1275             :     INetURLObject aProgObj(
    1276           0 :         aPreDefPathVariables.m_FixedVar[PREDEFVAR_BRANDBASEURL] );
    1277           0 :     if ( !aProgObj.HasError() && aProgObj.insertName( OUString(LIBO_BIN_FOLDER) ) )
    1278             :     {
    1279           0 :         aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ] = aProgObj.GetMainURL(INetURLObject::NO_DECODE);
    1280           0 :         aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGURL ]  = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ];
    1281           0 :         aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROG ]     = aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PROGPATH ];
    1282             :     }
    1283             : 
    1284             :     // Detect the language type of the current office
    1285           0 :     aPreDefPathVariables.m_eLanguageType = LANGUAGE_ENGLISH_US;
    1286           0 :     OUString aLocaleStr( utl::ConfigManager::getLocale() );
    1287           0 :     aPreDefPathVariables.m_eLanguageType = LanguageTag::convertToLanguageTypeWithFallback( aLocaleStr );
    1288             :     // We used to have an else branch here with a SAL_WARN, but that
    1289             :     // always fired in some unit tests when this code was built with
    1290             :     // debug=t, so it seems fairly pointless, especially as
    1291             :     // aPreDefPathVariables.m_eLanguageType has been initialized to a
    1292             :     // default value above anyway.
    1293             : 
    1294             :     // Set $(vlang)
    1295           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_VLANG ] = aLocaleStr;
    1296             : 
    1297             :     // Set $(langid)
    1298           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_LANGID ] = OUString::number( aPreDefPathVariables.m_eLanguageType );
    1299             : 
    1300             :     // Set the other pre defined path variables
    1301             :     // Set $(work)
    1302           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_WORK ] = GetWorkVariableValue();
    1303           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_HOME ] = GetHomeVariableValue();
    1304             : 
    1305             :     // Set $(workdirurl) this is the value of the path PATH_WORK which doesn't make sense
    1306             :     // anymore because the path settings service has this value! It can deliver this value more
    1307             :     // quickly than the substitution service!
    1308           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_WORKDIRURL ] = GetWorkPath();
    1309             : 
    1310             :     // Set $(path) variable
    1311           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_PATH ] = GetPathVariableValue();
    1312             : 
    1313             :     // Set $(temp)
    1314           0 :     OUString aTmp;
    1315           0 :     osl::FileBase::getTempDirURL( aTmp );
    1316           0 :     aPreDefPathVariables.m_FixedVar[ PREDEFVAR_TEMP ] = ConvertOSLtoUCBURL( aTmp );
    1317           0 : }
    1318             : 
    1319           0 : struct Instance {
    1320           0 :     explicit Instance(
    1321             :         css::uno::Reference<css::uno::XComponentContext> const & context):
    1322             :         instance(
    1323           0 :             static_cast<cppu::OWeakObject *>(new SubstitutePathVariables(context)))
    1324             :     {
    1325           0 :     }
    1326             : 
    1327             :     css::uno::Reference<css::uno::XInterface> instance;
    1328             : };
    1329             : 
    1330             : struct Singleton:
    1331             :     public rtl::StaticWithArg<
    1332             :         Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
    1333             : {};
    1334             : 
    1335             : }
    1336             : 
    1337             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
    1338           0 : com_sun_star_comp_framework_PathSubstitution_get_implementation(
    1339             :     css::uno::XComponentContext *context,
    1340             :     css::uno::Sequence<css::uno::Any> const &)
    1341             : {
    1342             :     return cppu::acquire(static_cast<cppu::OWeakObject *>(
    1343           0 :                 Singleton::get(context).instance.get()));
    1344             : }
    1345             : 
    1346             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10