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