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