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

Generated by: LCOV version 1.10