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 : :
30 : : #include "boost/noncopyable.hpp"
31 : : #include "rtl/bootstrap.h"
32 : : #include "rtl/bootstrap.hxx"
33 : : #include <osl/diagnose.h>
34 : : #include <osl/module.h>
35 : : #include <osl/process.h>
36 : : #include <osl/file.hxx>
37 : : #include <osl/mutex.hxx>
38 : : #include <osl/profile.hxx>
39 : : #include <osl/security.hxx>
40 : : #include <rtl/alloc.h>
41 : : #include <rtl/string.hxx>
42 : : #include <rtl/ustrbuf.hxx>
43 : : #include <rtl/ustring.hxx>
44 : : #include <rtl/byteseq.hxx>
45 : : #include <rtl/instance.hxx>
46 : : #include <rtl/malformeduriexception.hxx>
47 : : #include <rtl/uri.hxx>
48 : : #include "rtl/allocator.hxx"
49 : :
50 : : #include <algorithm>
51 : : #include <map>
52 : : #include <memory>
53 : : #include <utility>
54 : :
55 : : #ifdef IOS
56 : : #include <premac.h>
57 : : #import <Foundation/Foundation.h>
58 : : #include <postmac.h>
59 : : #endif
60 : :
61 : : #define MY_STRING_(x) # x
62 : : #define MY_STRING(x) MY_STRING_(x)
63 : :
64 : : extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl(
65 : : rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C();
66 : :
67 : : using osl::DirectoryItem;
68 : : using osl::FileStatus;
69 : :
70 : : using rtl::OString;
71 : : using rtl::OUString;
72 : : using rtl::OUStringToOString;
73 : :
74 : : struct Bootstrap_Impl;
75 : :
76 : : namespace {
77 : :
78 : : static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:";
79 : :
80 : 486 : bool isPathnameUrl(rtl::OUString const & url) {
81 : : return url.matchIgnoreAsciiCaseAsciiL(
82 : 486 : RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME));
83 : : }
84 : :
85 : 166 : bool resolvePathnameUrl(rtl::OUString * url) {
86 : : OSL_ASSERT(url != NULL);
87 [ + - ][ - + ]: 332 : if (!isPathnameUrl(*url) ||
[ # # ][ + - ]
88 : : (osl::FileBase::getFileURLFromSystemPath(
89 [ # # ][ - + ]: 166 : url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)), *url) ==
[ # # ]
90 : : osl::FileBase::E_None))
91 : : {
92 : 166 : return true;
93 : : } else {
94 : 0 : *url = rtl::OUString();
95 : 166 : return false;
96 : : }
97 : : }
98 : :
99 : : enum LookupMode {
100 : : LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP,
101 : : LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION };
102 : :
103 : 191588 : struct ExpandRequestLink {
104 : : ExpandRequestLink const * next;
105 : : Bootstrap_Impl const * file;
106 : : rtl::OUString key;
107 : : };
108 : :
109 : : rtl::OUString expandMacros(
110 : : Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
111 : : ExpandRequestLink const * requestStack);
112 : :
113 : 191588 : rtl::OUString recursivelyExpandMacros(
114 : : Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
115 : : Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
116 : : ExpandRequestLink const * requestStack)
117 : : {
118 [ + + ]: 314978 : for (; requestStack != NULL; requestStack = requestStack->next) {
119 [ + + - + ]: 141209 : if (requestStack->file == requestFile &&
[ - + ]
120 : 17819 : requestStack->key == requestKey)
121 : : {
122 : : return rtl::OUString(
123 [ # # ]: 0 : RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***"));
124 : : }
125 : : }
126 : 191588 : ExpandRequestLink link = { requestStack, requestFile, requestKey };
127 [ + - ]: 191588 : return expandMacros(file, text, mode, &link);
128 : : }
129 : :
130 : : class ParameterMap: private boost::noncopyable {
131 : : public:
132 : : bool get(rtl::OUString const & key, rtl::OUString * value) const;
133 : :
134 : : protected:
135 [ + - ]: 4984 : ParameterMap() {}
136 : :
137 : 4984 : ~ParameterMap() {}
138 : :
139 : : typedef std::map< rtl::OUString, rtl::OUString > Map;
140 : :
141 : : Map map_;
142 : : };
143 : :
144 : 860124 : bool ParameterMap::get(rtl::OUString const & key, rtl::OUString * value) const {
145 : : OSL_ASSERT(value != 0);
146 [ + - ]: 860124 : Map::const_iterator i(map_.find(key));
147 [ + + ]: 860124 : if (i == map_.end()) {
148 : 668694 : return false;
149 : : } else {
150 : 191430 : *value = i->second;
151 : 860124 : return true;
152 : : }
153 : : }
154 : :
155 [ + - ][ + - ]: 1884 : class ExplicitParameterMap: public ParameterMap {
156 : : public:
157 : : bool get(rtl::OUString const & key, rtl::OUString * value) const;
158 : :
159 : : void set(rtl::OUString const & key, rtl::OUString const & value);
160 : :
161 : : private:
162 : : mutable osl::Mutex mutex_;
163 : : };
164 : :
165 : 209827 : bool ExplicitParameterMap::get(rtl::OUString const & key, rtl::OUString * value)
166 : : const
167 : : {
168 [ + - ]: 209827 : osl::MutexGuard g(mutex_);
169 [ + - ][ + - ]: 209827 : return ParameterMap::get(key, value);
170 : : }
171 : :
172 : 1530 : void ExplicitParameterMap::set(
173 : : rtl::OUString const & key, rtl::OUString const & value)
174 : : {
175 [ + - ]: 1530 : osl::MutexGuard g(mutex_);
176 [ + - ][ + - ]: 1530 : map_[key] = value;
177 : 1530 : }
178 : :
179 : : struct ExplicitParameters:
180 : : public rtl::Static< ExplicitParameterMap, ExplicitParameters >
181 : : {};
182 : :
183 : 942 : class CommandLineParameterMap: public ParameterMap {
184 : : public:
185 : : CommandLineParameterMap();
186 : : };
187 : :
188 : 942 : CommandLineParameterMap::CommandLineParameterMap() {
189 [ + - ]: 942 : sal_uInt32 n = osl_getCommandArgCount();
190 [ + + ]: 7815 : for (sal_uInt32 i = 0; i != n; ++i) {
191 : 6873 : rtl::OUString s;
192 [ + - ]: 6873 : osl_getCommandArg(i, &s.pData);
193 : : static char const PREFIX[] = "-env:";
194 [ + + ]: 6873 : if (s.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))) {
195 : 1839 : sal_Int32 j = s.indexOf('=', RTL_CONSTASCII_LENGTH(PREFIX));
196 [ - + ]: 1839 : if (j < 0) {
197 [ # # ]: 0 : map_.erase(s.copy(RTL_CONSTASCII_LENGTH(PREFIX)));
198 : : } else {
199 : : map_[
200 : : s.copy(
201 : : RTL_CONSTASCII_LENGTH(PREFIX),
202 [ + - ]: 3678 : j - RTL_CONSTASCII_LENGTH(PREFIX))] =
203 : 5517 : s.copy(j + 1);
204 : : }
205 : : }
206 : 6873 : }
207 : 942 : }
208 : :
209 : : struct CommandLineParameters:
210 : : public rtl::Static< CommandLineParameterMap, CommandLineParameters >
211 : : {};
212 : :
213 : : }
214 : :
215 : 0 : static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
216 : : {
217 : 0 : OUString fileName;
218 : 0 : osl_bootstrap_getExecutableFile_Impl (&(fileName.pData));
219 : :
220 : 0 : sal_Int32 nDirEnd = fileName.lastIndexOf('/');
221 : : OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
222 : :
223 : 0 : rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd);
224 : 0 : }
225 : :
226 : : static inline bool path_exists( OUString const & path )
227 : : {
228 : : DirectoryItem dirItem;
229 : : return (DirectoryItem::E_None == DirectoryItem::get( path, dirItem ));
230 : : }
231 : :
232 : : //----------------------------------------------------------------------------
233 : : // #111772#
234 : : // ensure the given file url has no final slash
235 : :
236 : 1112 : inline void EnsureNoFinalSlash (rtl::OUString & url)
237 : : {
238 : 1112 : sal_Int32 i = url.getLength();
239 [ - + ][ - + ]: 1112 : if (i > 0 && url[i - 1] == '/') {
[ + - ]
240 : 0 : url = url.copy(0, i - 1);
241 : : }
242 : 1112 : }
243 : :
244 : 3100 : struct Bootstrap_Impl: private ParameterMap
245 : : {
246 : : OUString _iniName;
247 : :
248 : : explicit Bootstrap_Impl (OUString const & rIniName);
249 : :
250 : : bool getValue(
251 : : rtl::OUString const & key, rtl_uString ** value,
252 : : rtl_uString * defaultValue, LookupMode mode, bool override,
253 : : ExpandRequestLink const * requestStack) const;
254 : : bool getDirectValue(
255 : : rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
256 : : ExpandRequestLink const * requestStack) const;
257 : : bool getAmbienceValue(
258 : : rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
259 : : ExpandRequestLink const * requestStack) const;
260 : : void expandValue(
261 : : rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
262 : : Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
263 : : ExpandRequestLink const * requestStack) const;
264 : : };
265 : :
266 : : //----------------------------------------------------------------------------
267 : :
268 : 3100 : Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName )
269 : 3100 : : _iniName (rIniName)
270 : : {
271 : : #if OSL_DEBUG_LEVEL > 1
272 : : OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
273 : : OSL_TRACE("Bootstrap_Impl(): sFile=%s", sFile.getStr());
274 : : #endif /* OSL_DEBUG_LEVEL > 1 */
275 : :
276 : : oslFileHandle handle;
277 [ + + ][ + + ]: 6196 : if (!_iniName.isEmpty() &&
[ + + ]
278 [ + - ]: 3096 : osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read))
279 : : {
280 : 2415 : rtl::ByteSequence seq;
281 : :
282 [ + - ][ + + ]: 41471 : while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq))
283 : : {
284 : 39056 : OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
285 : 39056 : sal_Int32 nIndex = line.indexOf('=');
286 [ + + ]: 39056 : if (nIndex >= 1)
287 : : {
288 : : rtl::OUString sName = OStringToOUString(
289 [ + - ]: 14162 : line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US );
290 : : rtl::OUString sValue = OStringToOUString(
291 [ + - ]: 14162 : line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 );
292 : :
293 : : #if OSL_DEBUG_LEVEL > 1
294 : : OString name_tmp = OUStringToOString(sName, RTL_TEXTENCODING_ASCII_US);
295 : : OString value_tmp = OUStringToOString(sValue, RTL_TEXTENCODING_UTF8);
296 : : OSL_TRACE(
297 : : "pushing: name=%s value=%s",
298 : : name_tmp.getStr(), value_tmp.getStr() );
299 : : #endif /* OSL_DEBUG_LEVEL > 1 */
300 : :
301 [ + - ]: 14162 : map_[sName] = sValue;
302 : : }
303 : 39056 : }
304 [ + - ]: 2415 : osl_closeFile(handle);
305 : : }
306 : : #if OSL_DEBUG_LEVEL > 1
307 : : else
308 : : {
309 : : OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
310 : : OSL_TRACE( "couldn't open file: %s", file_tmp.getStr() );
311 : : }
312 : : #endif /* OSL_DEBUG_LEVEL > 1 */
313 : 3100 : }
314 : :
315 : : namespace {
316 : :
317 : : class BootstrapMap: private boost::noncopyable {
318 : : public:
319 : : BootstrapMap();
320 : :
321 : : ~BootstrapMap();
322 : :
323 : : Bootstrap_Impl * getIni(rtl::OUString const & uri, bool alwaysCreate);
324 : :
325 : : void setBaseIniUri(rtl::OUString const & uri);
326 : :
327 : : Bootstrap_Impl * getBaseIni();
328 : :
329 : : Bootstrap_Impl * getFundamentalIni();
330 : :
331 : : private:
332 : : typedef std::map< rtl::OUString, Bootstrap_Impl * > Map;
333 : :
334 : : osl::Mutex mutex_;
335 : : Map map_;
336 : : rtl::OUString baseIniUri_;
337 : : Bootstrap_Impl * baseIni_;
338 : : bool hasFundamentalIni_;
339 : : Bootstrap_Impl * fundamentalIni_;
340 : : };
341 : :
342 : 942 : BootstrapMap::BootstrapMap():
343 [ + - ][ + - ]: 942 : baseIni_(0), hasFundamentalIni_(false), fundamentalIni_(0)
344 : 942 : {}
345 : :
346 [ + - ]: 942 : BootstrapMap::~BootstrapMap() {
347 [ + + ]: 4042 : for (Map::iterator i(map_.begin()); i != map_.end(); ++i) {
348 [ + - ]: 3100 : delete i->second;
349 : : }
350 : 942 : }
351 : :
352 : 67639 : Bootstrap_Impl * BootstrapMap::getIni(
353 : : rtl::OUString const & uri, bool alwaysCreate)
354 : : {
355 : 67639 : rtl::OUString normUri; // normalize URI if possible
356 : 67639 : DirectoryItem dirItem;
357 : 67639 : FileStatus status(osl_FileStatus_Mask_FileURL);
358 [ + + ][ + - ]: 129595 : if (DirectoryItem::get(uri, dirItem) == DirectoryItem::E_None &&
[ + + ][ + - ]
359 [ + - ]: 61956 : dirItem.getFileStatus(status) == DirectoryItem::E_None)
360 : : {
361 [ + - ]: 61956 : normUri = status.getFileURL();
362 [ + + ]: 5683 : } else if (alwaysCreate) {
363 : 685 : normUri = uri;
364 : : } else {
365 : 4998 : return 0;
366 : : }
367 [ + - ]: 62641 : osl::MutexGuard g(mutex_);
368 [ + - ]: 62641 : Map::iterator i(map_.find(normUri));
369 [ + + ]: 62641 : if (i == map_.end()) {
370 [ + - ][ + - ]: 3100 : std::auto_ptr< Bootstrap_Impl > b(new Bootstrap_Impl(normUri));
371 : : std::pair< Map::iterator, bool > ins(
372 [ + - ]: 3100 : map_.insert(Map::value_type(normUri, b.get())));
373 : 3100 : b.release();
374 : : OSL_ASSERT(ins.second);
375 : 3100 : i = ins.first;
376 : : }
377 [ + - ][ + - ]: 67639 : return i->second;
378 : : }
379 : :
380 : 0 : void BootstrapMap::setBaseIniUri(rtl::OUString const & uri) {
381 : : OSL_ASSERT(!uri.isEmpty());
382 [ # # ]: 0 : osl::MutexGuard g(mutex_);
383 : : OSL_ASSERT(baseIniUri_.isEmpty() && baseIni_ == 0);
384 [ # # ]: 0 : baseIniUri_ = uri;
385 : 0 : }
386 : :
387 : 201308 : Bootstrap_Impl * BootstrapMap::getBaseIni() {
388 [ + - ]: 201308 : osl::MutexGuard g(mutex_);
389 [ + + ]: 201308 : if (baseIni_ == 0) {
390 : 843 : rtl::OUString uri;
391 [ + - ]: 843 : if (baseIniUri_.isEmpty()) {
392 : : #if defined IOS
393 : : // On iOS hardcode the inifile as "rc" in the .app
394 : : // directory. Apps are self-contained anyway, there is no
395 : : // possibility to have several "applications" in the same
396 : : // installation location with different inifiles.
397 : : const char *inifile = [[@"vnd.sun.star.pathname:" stringByAppendingString: [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"rc"]] UTF8String];
398 : : uri = rtl::OUString(inifile, strlen(inifile), RTL_TEXTENCODING_UTF8);
399 : : resolvePathnameUrl(&uri);
400 : : #elif defined ANDROID
401 : : // Apps are self-contained on Android, too, can as well hardcode
402 : : // it as "rc" in the "/assets" directory, i.e. inside the app's
403 : : // .apk (zip) archive as the /assets/rc file.
404 : : uri = rtl::OUString("vnd.sun.star.pathname:/assets/rc");
405 : : resolvePathnameUrl(&uri);
406 : : #else
407 [ + - ]: 1686 : if (CommandLineParameters::get().get(
[ + - + + ]
408 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")),
409 [ + - ]: 1686 : &uri))
410 : : {
411 [ + - ]: 4 : resolvePathnameUrl(&uri);
412 : : } else {
413 : 839 : osl_bootstrap_getExecutableFile_Impl(&uri.pData);
414 : : // Strip potentially two such extensions, to allow for
415 : : // renaming of soffice.bin to soffice.bin.exe so that
416 : : // Visual Studio agrees to start it, if you want to
417 : : // debug it from the start.
418 : : static char const BIN_EXT[] = ".bin";
419 : : static char const EXE_EXT[] = ".exe";
420 [ + + ]: 2517 : for (int i = 0; i < 2; i++) {
421 [ + + ]: 1678 : if (uri.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(BIN_EXT))) {
422 : : uri = uri.copy(
423 : 158 : 0, uri.getLength() - RTL_CONSTASCII_LENGTH(BIN_EXT));
424 [ - + ]: 1520 : } else if (uri.endsWithAsciiL(
425 : : RTL_CONSTASCII_STRINGPARAM(EXE_EXT))) {
426 : : uri = uri.copy(
427 : 0 : 0, uri.getLength() - RTL_CONSTASCII_LENGTH(EXE_EXT));
428 : : }
429 : : }
430 : : uri += rtl::OUString(
431 [ + - ]: 839 : RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE("")));
432 : : }
433 : : #endif
434 : : } else {
435 : 0 : uri = baseIniUri_;
436 : : }
437 [ + - ]: 843 : baseIni_ = getIni(uri, true);
438 : : }
439 [ + - ]: 201308 : return baseIni_;
440 : : }
441 : :
442 : 111757 : Bootstrap_Impl * BootstrapMap::getFundamentalIni() {
443 [ + - ]: 111757 : osl::MutexGuard g(mutex_);
444 [ + + ]: 111757 : if (!hasFundamentalIni_) {
445 : 843 : rtl::OUString uri;
446 : : fundamentalIni_ =
447 : : (getBaseIni()->getValue(
448 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")),
449 [ + - ][ + - ]: 1686 : &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0) &&
[ + - ][ # # ]
[ + - ]
450 [ + - ]: 162 : resolvePathnameUrl(&uri))
451 [ + + ][ + - ]: 1005 : ? getIni(uri, false) : 0;
[ + - ]
452 : 843 : hasFundamentalIni_ = true;
453 : : }
454 [ + - ]: 111757 : return fundamentalIni_;
455 : : }
456 : :
457 : : struct BootstrapMapSingleton:
458 : : public rtl::Static< BootstrapMap, BootstrapMapSingleton >
459 : : {};
460 : :
461 : : }
462 : :
463 : 315064 : bool Bootstrap_Impl::getValue(
464 : : rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue,
465 : : LookupMode mode, bool override, ExpandRequestLink const * requestStack)
466 : : const
467 : : {
468 [ + + + + ]: 629970 : if (mode == LOOKUP_MODE_NORMAL &&
[ + + ]
469 : 314906 : key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP")))
470 : : {
471 : 1001 : mode = LOOKUP_MODE_URE_BOOTSTRAP;
472 : : }
473 [ + + ][ + - ]: 315064 : if (override && getDirectValue(key, value, mode, requestStack)) {
[ + + ]
474 : 196 : return true;
475 : : }
476 [ + + ]: 314868 : if ( key == "_OS" ) {
477 : : rtl_uString_assign(
478 : 2390 : value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_OS)).pData);
479 : 2390 : return true;
480 : : }
481 [ + + ]: 312478 : if ( key == "_ARCH" ) {
482 : : rtl_uString_assign(
483 : 2388 : value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_ARCH)).pData);
484 : 2388 : return true;
485 : : }
486 [ - + ]: 310090 : if ( key == "_CPPU_ENV" ) {
487 : : rtl_uString_assign(
488 : : value,
489 : : (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))).
490 : 0 : pData));
491 : 0 : return true;
492 : : }
493 [ + + ]: 310090 : if ( key == "ORIGIN" ) {
494 : : rtl_uString_assign(
495 : : value,
496 : : _iniName.copy(
497 [ + - ]: 100263 : 0, std::max<sal_Int32>(0, _iniName.lastIndexOf('/'))).pData);
498 : 100263 : return true;
499 : : }
500 [ + + ]: 209827 : if (getAmbienceValue(key, value, mode, requestStack)) {
501 : 30577 : return true;
502 : : }
503 [ - + ]: 179250 : if ( key == "SYSUSERCONFIG" ) {
504 : 0 : rtl::OUString v;
505 [ # # ][ # # ]: 0 : bool b = osl::Security().getConfigDir(v);
[ # # ]
506 : 0 : EnsureNoFinalSlash(v);
507 : 0 : rtl_uString_assign(value, v.pData);
508 : 0 : return b;
509 : : }
510 [ + + ]: 179250 : if ( key == "SYSUSERHOME" ) {
511 : 1112 : rtl::OUString v;
512 [ + - ][ + - ]: 1112 : bool b = osl::Security().getHomeDir(v);
[ + - ]
513 : 1112 : EnsureNoFinalSlash(v);
514 : 1112 : rtl_uString_assign(value, v.pData);
515 : 1112 : return b;
516 : : }
517 [ - + ]: 178138 : if ( key == "SYSBINDIR" ) {
518 : 0 : getExecutableDirectory_Impl(value);
519 : 0 : return true;
520 : : }
521 : 178138 : Bootstrap_Impl * b = BootstrapMapSingleton::get().getBaseIni();
522 [ - + ][ - + ]: 178138 : if (b != this && b->getDirectValue(key, value, mode, requestStack)) {
[ + + ]
523 : 0 : return true;
524 : : }
525 [ + - ][ + + ]: 178138 : if (!override && getDirectValue(key, value, mode, requestStack)) {
[ + + ]
526 : 65700 : return true;
527 : : }
528 [ + + ]: 112438 : if (mode == LOOKUP_MODE_NORMAL) {
529 : 111757 : b = BootstrapMapSingleton::get().getFundamentalIni();
530 [ + - + + ]: 212114 : if (b != 0 && b != this &&
[ + + ][ + + ]
531 : 100357 : b->getDirectValue(key, value, mode, requestStack))
532 : : {
533 : 95115 : return true;
534 : : }
535 : : }
536 [ + + ]: 17323 : if (defaultValue != NULL) {
537 : 1957 : rtl_uString_assign(value, defaultValue);
538 : 1957 : return true;
539 : : }
540 : 15366 : rtl_uString_new(value);
541 : 315064 : return false;
542 : : }
543 : :
544 : 439845 : bool Bootstrap_Impl::getDirectValue(
545 : : rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
546 : : ExpandRequestLink const * requestStack) const
547 : : {
548 : 439845 : rtl::OUString v;
549 [ + + ][ + - ]: 439845 : if (get(key, &v)) {
550 [ + - ]: 161011 : expandValue(value, v, mode, this, key, requestStack);
551 : 161011 : return true;
552 : : } else {
553 : 278834 : return false;
554 : 439845 : }
555 : : }
556 : :
557 : 209827 : bool Bootstrap_Impl::getAmbienceValue(
558 : : rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
559 : : ExpandRequestLink const * requestStack) const
560 : : {
561 : 209827 : rtl::OUString v;
562 [ + - ][ + + ]: 598848 : if (ExplicitParameters::get().get(key, &v) ||
[ + + ][ + + ]
[ + + ][ + - ]
563 [ + - ][ + - ]: 209609 : CommandLineParameters::get().get(key, &v) ||
564 [ + - ]: 179412 : osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None)
565 : : {
566 [ + - ]: 30577 : expandValue(value, v, mode, NULL, key, requestStack);
567 : 30577 : return true;
568 : : } else {
569 : 179250 : return false;
570 : 209827 : }
571 : : }
572 : :
573 : 191588 : void Bootstrap_Impl::expandValue(
574 : : rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
575 : : Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
576 : : ExpandRequestLink const * requestStack) const
577 : : {
578 : : rtl_uString_assign(
579 : : value,
580 : 320 : (mode == LOOKUP_MODE_URE_BOOTSTRAP && isPathnameUrl(text) ?
581 : : text :
582 : : recursivelyExpandMacros(
583 : : this, text,
584 : : (mode == LOOKUP_MODE_URE_BOOTSTRAP ?
585 : : LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION : mode),
586 [ + + - + ]: 191908 : requestFile, requestKey, requestStack)).pData);
[ + + ]
587 : 191588 : }
588 : :
589 : 66634 : rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
590 : : rtl_uString * pIniName
591 : : ) SAL_THROW_EXTERN_C()
592 : : {
593 [ + - ][ + - ]: 66634 : return BootstrapMapSingleton::get().getIni(rtl::OUString(pIniName), false);
594 : : }
595 : :
596 : : //----------------------------------------------------------------------------
597 : :
598 : 67661 : void SAL_CALL rtl_bootstrap_args_close (
599 : : SAL_UNUSED_PARAMETER rtlBootstrapHandle
600 : : ) SAL_THROW_EXTERN_C()
601 : : {
602 : : // do nothing; the BootstrapMap::map_ just keeps growing for now
603 : 67661 : }
604 : :
605 : : //----------------------------------------------------------------------------
606 : :
607 : 14089 : sal_Bool SAL_CALL rtl_bootstrap_get_from_handle(
608 : : rtlBootstrapHandle handle,
609 : : rtl_uString * pName,
610 : : rtl_uString ** ppValue,
611 : : rtl_uString * pDefault
612 : : ) SAL_THROW_EXTERN_C()
613 : : {
614 : : return
615 : : (handle == 0
616 [ + - ]: 6859 : ? BootstrapMapSingleton::get().getBaseIni()
617 : : : static_cast< Bootstrap_Impl * >(handle))->
618 [ + + ][ + - ]: 20948 : getValue(pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, 0);
[ + - ]
619 : : }
620 : :
621 : : //----------------------------------------------------------------------------
622 : :
623 : 583 : void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
624 : : rtlBootstrapHandle handle,
625 : : rtl_uString ** ppIniName
626 : : ) SAL_THROW_EXTERN_C()
627 : : {
628 : : rtl_uString_assign(
629 : : ppIniName,
630 : : ((handle == 0
631 : 267 : ? BootstrapMapSingleton::get().getBaseIni()
632 : : : static_cast<Bootstrap_Impl*>(handle))->
633 [ + + ]: 850 : _iniName.pData));
634 : 583 : }
635 : :
636 : : //----------------------------------------------------------------------------
637 : :
638 : 0 : void SAL_CALL rtl_bootstrap_setIniFileName (
639 : : rtl_uString * pName
640 : : ) SAL_THROW_EXTERN_C()
641 : : {
642 [ # # ][ # # ]: 0 : BootstrapMapSingleton::get().setBaseIniUri(rtl::OUString(pName));
643 : 0 : }
644 : :
645 : : //----------------------------------------------------------------------------
646 : :
647 : 2294 : sal_Bool SAL_CALL rtl_bootstrap_get (
648 : : rtl_uString * pName,
649 : : rtl_uString ** ppValue,
650 : : rtl_uString * pDefault
651 : : ) SAL_THROW_EXTERN_C()
652 : : {
653 : 2294 : return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault);
654 : : }
655 : :
656 : : //----------------------------------------------------------------------------
657 : :
658 : 1530 : void SAL_CALL rtl_bootstrap_set (
659 : : rtl_uString * pName,
660 : : rtl_uString * pValue
661 : : ) SAL_THROW_EXTERN_C()
662 : : {
663 [ + - ][ + - ]: 1530 : ExplicitParameters::get().set(rtl::OUString(pName), rtl::OUString(pValue));
664 : 1530 : }
665 : :
666 : : //----------------------------------------------------------------------------
667 : :
668 : 74476 : void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
669 : : rtlBootstrapHandle handle,
670 : : rtl_uString ** macro
671 : : ) SAL_THROW_EXTERN_C()
672 : : {
673 : : rtl::OUString expanded(
674 : : expandMacros(
675 : : (handle == 0
676 [ + - ]: 13412 : ? BootstrapMapSingleton::get().getBaseIni()
677 : : : static_cast< Bootstrap_Impl * >(handle)),
678 : : *reinterpret_cast< OUString const * >(macro), LOOKUP_MODE_NORMAL,
679 [ + + ][ + - ]: 87888 : 0));
[ + - ]
680 : 74476 : rtl_uString_assign(macro, expanded.pData);
681 : 74476 : }
682 : :
683 : : //----------------------------------------------------------------------------
684 : :
685 : 13412 : void SAL_CALL rtl_bootstrap_expandMacros(
686 : : rtl_uString ** macro )
687 : : SAL_THROW_EXTERN_C()
688 : : {
689 : 13412 : rtl_bootstrap_expandMacros_from_handle(NULL, macro);
690 : 13412 : }
691 : :
692 : 158 : void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded )
693 : : SAL_THROW_EXTERN_C()
694 : : {
695 : : OSL_ASSERT(value != NULL);
696 : 158 : rtl::OUStringBuffer b;
697 [ + + ]: 14694 : for (sal_Int32 i = 0; i < value->length; ++i) {
698 : 14536 : sal_Unicode c = value->buffer[i];
699 [ + - ][ - + ]: 14536 : if (c == '$' || c == '\\') {
700 [ # # ]: 0 : b.append(sal_Unicode('\\'));
701 : : }
702 [ + - ]: 14536 : b.append(c);
703 : : }
704 [ + - ]: 158 : rtl_uString_assign(encoded, b.makeStringAndClear().pData);
705 : 158 : }
706 : :
707 : : namespace {
708 : :
709 : 0 : int hex(sal_Unicode c) {
710 : : return
711 : : c >= '0' && c <= '9' ? c - '0' :
712 : : c >= 'A' && c <= 'F' ? c - 'A' + 10 :
713 [ # # ][ # # ]: 0 : c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
[ # # ][ # # ]
[ # # ][ # # ]
714 : : }
715 : :
716 : 15850317 : sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
717 : : OSL_ASSERT(
718 : : pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL);
719 : 15850317 : sal_Unicode c = text[(*pos)++];
720 [ + + ]: 15850317 : if (c == '\\') {
721 : : int n1, n2, n3, n4;
722 [ + - ][ - + : 392 : if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
# # # # #
# # # ]
[ - + ]
723 : 0 : ((n1 = hex(text[*pos + 1])) >= 0) &&
724 : 0 : ((n2 = hex(text[*pos + 2])) >= 0) &&
725 : 0 : ((n3 = hex(text[*pos + 3])) >= 0) &&
726 : 0 : ((n4 = hex(text[*pos + 4])) >= 0))
727 : : {
728 : 0 : *pos += 5;
729 : 0 : *escaped = true;
730 : : return static_cast< sal_Unicode >(
731 : 0 : (n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
732 [ + - ]: 392 : } else if (*pos < text.getLength()) {
733 : 392 : *escaped = true;
734 : 392 : return text[(*pos)++];
735 : : }
736 : : }
737 : 15849925 : *escaped = false;
738 : 15850317 : return c;
739 : : }
740 : :
741 : 300132 : rtl::OUString lookup(
742 : : Bootstrap_Impl const * file, LookupMode mode, bool override,
743 : : rtl::OUString const & key, ExpandRequestLink const * requestStack)
744 : : {
745 : 300132 : rtl::OUString v;
746 [ + - ]: 1789 : (file == 0 ? BootstrapMapSingleton::get().getBaseIni() : file)->getValue(
747 [ + - ][ + - ]: 301921 : key, &v.pData, NULL, mode, override, requestStack);
[ + + ]
748 : 300132 : return v;
749 : : }
750 : :
751 : 468406 : rtl::OUString expandMacros(
752 : : Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
753 : : ExpandRequestLink const * requestStack)
754 : : {
755 : 468406 : rtl::OUStringBuffer buf;
756 [ + + ]: 10753426 : for (sal_Int32 i = 0; i < text.getLength();) {
757 : : bool escaped;
758 : 10285020 : sal_Unicode c = read(text, &i, &escaped);
759 [ + + ][ + + ]: 10285020 : if (escaped || c != '$') {
760 [ + - ]: 9984392 : buf.append(c);
761 : : } else {
762 [ + - ][ + + ]: 300628 : if (i < text.getLength() && text[i] == '{') {
[ + + ]
763 : 140324 : ++i;
764 : 140324 : sal_Int32 p = i;
765 : 140324 : sal_Int32 nesting = 0;
766 [ + + ]: 982268 : rtl::OUString seg[3];
767 : 140324 : int n = 0;
768 [ + - ]: 3293820 : while (i < text.getLength()) {
769 : 3293820 : sal_Int32 j = i;
770 : 3293820 : c = read(text, &i, &escaped);
771 [ + + ]: 3293820 : if (!escaped) {
772 [ + + + + ]: 3293624 : switch (c) {
773 : : case '{':
774 : 1812 : ++nesting;
775 : 1812 : break;
776 : : case '}':
777 [ + + ]: 142136 : if (nesting == 0) {
778 : 140324 : seg[n++] = text.copy(p, j - p);
779 : 140324 : goto done;
780 : : } else {
781 : 1812 : --nesting;
782 : : }
783 : 1812 : break;
784 : : case ':':
785 [ + + ][ + - ]: 62990 : if (nesting == 0 && n < 2) {
786 : 62018 : seg[n++] = text.copy(p, j - p);
787 : 62018 : p = i;
788 : : }
789 : 3153300 : break;
790 : : }
791 : : }
792 : : }
793 : : done:
794 [ + + ]: 342666 : for (int j = 0; j < n; ++j) {
795 [ + - ]: 202342 : seg[j] = expandMacros(file, seg[j], mode, requestStack);
796 : : }
797 [ + + ]: 140324 : if (n == 1) {
798 [ + - ][ + - ]: 78998 : buf.append(lookup(file, mode, false, seg[0], requestStack));
799 [ + + ][ - + ]: 61326 : } else if (n == 2 && seg[0] == ".link") {
[ - + ]
800 : 0 : osl::File f(seg[1]);
801 : 0 : rtl::ByteSequence seq;
802 : 0 : rtl::OUString line;
803 : 0 : rtl::OUString url;
804 : : // Silently ignore any errors (is that good?):
805 [ # # ]: 0 : if ((f.open(osl_File_OpenFlag_Read) ==
[ # # # # ]
[ # # ][ # # ]
[ # # ]
806 : : osl::FileBase::E_None) &&
807 [ # # ]: 0 : f.readLine(seq) == osl::FileBase::E_None &&
808 : : rtl_convertStringToUString(
809 : : &line.pData,
810 : : reinterpret_cast< char const * >(
811 : 0 : seq.getConstArray()),
812 : : seq.getLength(), RTL_TEXTENCODING_UTF8,
813 : : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
814 : : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
815 : 0 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) &&
816 [ # # ]: 0 : (osl::File::getFileURLFromSystemPath(line, url) ==
817 : : osl::FileBase::E_None))
818 : : {
819 : : try {
820 : : buf.append(
821 [ # # ][ # # ]: 0 : rtl::Uri::convertRelToAbs(seg[1], url));
[ # # ]
822 : 0 : } catch (const rtl::MalformedUriException &) {}
823 [ # # ]: 0 : }
824 [ + + ][ + + ]: 61326 : } else if (n == 3 && seg[0] == ".override") {
[ + + ]
825 : 196 : rtl::Bootstrap b(seg[1]);
826 : : Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
827 : 196 : b.getHandle());
828 : : buf.append(
829 [ + - ][ + - ]: 196 : lookup(f, mode, f != NULL, seg[2], requestStack));
830 : : } else {
831 [ + + ][ - + ]: 61130 : if (n == 3 && seg[1].isEmpty()) {
[ - + ]
832 : : // For backward compatibility, treat ${file::key} the
833 : : // same as just ${file:key}:
834 : 0 : seg[1] = seg[2];
835 : 0 : n = 2;
836 : : }
837 [ + + ]: 61130 : if (n == 2) {
838 : : buf.append(
839 : : lookup(
840 : : static_cast< Bootstrap_Impl * >(
841 : 121268 : rtl::Bootstrap(seg[0]).getHandle()),
842 [ + - ][ + - ]: 60634 : mode, false, seg[1], requestStack));
843 : : } else {
844 : : // Going through osl::Profile, this code erroneously
845 : : // does not recursively expand macros in the resulting
846 : : // replacement text (and if it did, it would fail to
847 : : // detect cycles that pass through here):
848 : : buf.append(
849 : : rtl::OStringToOUString(
850 : : osl::Profile(seg[0]).readString(
851 : : rtl::OUStringToOString(
852 : : seg[1], RTL_TEXTENCODING_UTF8),
853 : : rtl::OUStringToOString(
854 : : seg[2], RTL_TEXTENCODING_UTF8),
855 : : rtl::OString()),
856 [ + - ][ + - ]: 496 : RTL_TEXTENCODING_UTF8));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
857 : : }
858 [ + + ][ # # ]: 561296 : }
859 : : } else {
860 : 160304 : rtl::OUStringBuffer kbuf;
861 [ + + ]: 2277690 : for (; i < text.getLength();) {
862 : 2271477 : sal_Int32 j = i;
863 : 2271477 : c = read(text, &j, &escaped);
864 [ + - ][ + - ]: 2271477 : if (!escaped &&
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ]
865 : : (c == ' ' || c == '$' || c == '-' || c == '/' ||
866 : : c == ';' || c == '\\'))
867 : : {
868 : : break;
869 : : }
870 [ + - ]: 2117386 : kbuf.append(c);
871 : 2271477 : i = j;
872 : : }
873 : : buf.append(
874 : : lookup(
875 : : file, mode, false, kbuf.makeStringAndClear(),
876 [ + - ][ + - ]: 10285020 : requestStack));
[ + - ]
877 : : }
878 : : }
879 : : }
880 [ + - ]: 468406 : return buf.makeStringAndClear();
881 : : }
882 : :
883 : : }
884 : :
885 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|