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: */
|