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

Generated by: LCOV version 1.10