Bug Summary

File:sal/rtl/source/bootstrap.cxx
Location:line 697, column 31
Description:Access to field 'length' results in a dereference of a null pointer (loaded from variable 'value')

Annotated 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" # x
62#define MY_STRING(x)"x" MY_STRING_(x)"x"
63
64extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl(
65 rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C()throw ();
66
67using osl::DirectoryItem;
68using osl::FileStatus;
69
70using rtl::OString;
71using rtl::OUString;
72using rtl::OUStringToOString;
73
74struct Bootstrap_Impl;
75
76namespace {
77
78static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:";
79
80bool isPathnameUrl(rtl::OUString const & url) {
81 return url.matchIgnoreAsciiCaseAsciiL(
82 RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME)(&(VND_SUN_STAR_PATHNAME)[0]), ((sal_Int32)(sizeof (VND_SUN_STAR_PATHNAME
) / sizeof ((VND_SUN_STAR_PATHNAME)[0]))-1)
);
83}
84
85bool resolvePathnameUrl(rtl::OUString * url) {
86 OSL_ASSERT(url != NULL)do { if (true && (!(url != __null))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "86" ": "), "OSL_ASSERT: %s", "url != NULL"); } } while (
false)
;
87 if (!isPathnameUrl(*url) ||
88 (osl::FileBase::getFileURLFromSystemPath(
89 url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)((sal_Int32)((sizeof (VND_SUN_STAR_PATHNAME) / sizeof ((VND_SUN_STAR_PATHNAME
)[0]))-1))
), *url) ==
90 osl::FileBase::E_None))
91 {
92 return true;
93 } else {
94 *url = rtl::OUString();
95 return false;
96 }
97}
98
99enum LookupMode {
100 LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP,
101 LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION };
102
103struct ExpandRequestLink {
104 ExpandRequestLink const * next;
105 Bootstrap_Impl const * file;
106 rtl::OUString key;
107};
108
109rtl::OUString expandMacros(
110 Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
111 ExpandRequestLink const * requestStack);
112
113rtl::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 for (; requestStack != NULL__null; requestStack = requestStack->next) {
119 if (requestStack->file == requestFile &&
120 requestStack->key == requestKey)
121 {
122 return rtl::OUString(
123 RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***")(&("***RECURSION DETECTED***")[0]), ((sal_Int32)((sizeof (
"***RECURSION DETECTED***") / sizeof (("***RECURSION DETECTED***"
)[0]))-1)), (((rtl_TextEncoding) 11))
);
124 }
125 }
126 ExpandRequestLink link = { requestStack, requestFile, requestKey };
127 return expandMacros(file, text, mode, &link);
128}
129
130class ParameterMap: private boost::noncopyable {
131public:
132 bool get(rtl::OUString const & key, rtl::OUString * value) const;
133
134protected:
135 ParameterMap() {}
136
137 ~ParameterMap() {}
138
139 typedef std::map< rtl::OUString, rtl::OUString > Map;
140
141 Map map_;
142};
143
144bool ParameterMap::get(rtl::OUString const & key, rtl::OUString * value) const {
145 OSL_ASSERT(value != 0)do { if (true && (!(value != 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "145" ": "), "OSL_ASSERT: %s", "value != 0"); } } while (
false)
;
146 Map::const_iterator i(map_.find(key));
147 if (i == map_.end()) {
148 return false;
149 } else {
150 *value = i->second;
151 return true;
152 }
153}
154
155class ExplicitParameterMap: public ParameterMap {
156public:
157 bool get(rtl::OUString const & key, rtl::OUString * value) const;
158
159 void set(rtl::OUString const & key, rtl::OUString const & value);
160
161private:
162 mutable osl::Mutex mutex_;
163};
164
165bool ExplicitParameterMap::get(rtl::OUString const & key, rtl::OUString * value)
166 const
167{
168 osl::MutexGuard g(mutex_);
169 return ParameterMap::get(key, value);
170}
171
172void ExplicitParameterMap::set(
173 rtl::OUString const & key, rtl::OUString const & value)
174{
175 osl::MutexGuard g(mutex_);
176 map_[key] = value;
177}
178
179struct ExplicitParameters:
180 public rtl::Static< ExplicitParameterMap, ExplicitParameters >
181{};
182
183class CommandLineParameterMap: public ParameterMap {
184public:
185 CommandLineParameterMap();
186};
187
188CommandLineParameterMap::CommandLineParameterMap() {
189 sal_uInt32 n = osl_getCommandArgCount();
190 for (sal_uInt32 i = 0; i != n; ++i) {
191 rtl::OUString s;
192 osl_getCommandArg(i, &s.pData);
193 static char const PREFIX[] = "-env:";
194 if (s.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX)(&(PREFIX)[0]), ((sal_Int32)(sizeof (PREFIX) / sizeof ((PREFIX
)[0]))-1)
)) {
195 sal_Int32 j = s.indexOf('=', RTL_CONSTASCII_LENGTH(PREFIX)((sal_Int32)((sizeof (PREFIX) / sizeof ((PREFIX)[0]))-1)));
196 if (j < 0) {
197 map_.erase(s.copy(RTL_CONSTASCII_LENGTH(PREFIX)((sal_Int32)((sizeof (PREFIX) / sizeof ((PREFIX)[0]))-1))));
198 } else {
199 map_[
200 s.copy(
201 RTL_CONSTASCII_LENGTH(PREFIX)((sal_Int32)((sizeof (PREFIX) / sizeof ((PREFIX)[0]))-1)),
202 j - RTL_CONSTASCII_LENGTH(PREFIX)((sal_Int32)((sizeof (PREFIX) / sizeof ((PREFIX)[0]))-1)))] =
203 s.copy(j + 1);
204 }
205 }
206 }
207}
208
209struct CommandLineParameters:
210 public rtl::Static< CommandLineParameterMap, CommandLineParameters >
211{};
212
213}
214
215static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
216{
217 OUString fileName;
218 osl_bootstrap_getExecutableFile_Impl (&(fileName.pData));
219
220 sal_Int32 nDirEnd = fileName.lastIndexOf('/');
221 OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory")do { if (true && (!(nDirEnd >= 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "221" ": "), "%s", "Cannot locate executable directory")
; } } while (false)
;
222
223 rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd);
224}
225
226static 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
236inline void EnsureNoFinalSlash (rtl::OUString & url)
237{
238 sal_Int32 i = url.getLength();
239 if (i > 0 && url[i - 1] == '/') {
240 url = url.copy(0, i - 1);
241 }
242}
243
244struct 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
268Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName )
269 : _iniName (rIniName)
270{
271#if OSL_DEBUG_LEVEL1 > 1
272 OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
273 OSL_TRACE("Bootstrap_Impl(): sFile=%s", sFile.getStr())do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "273" ": "), "Bootstrap_Impl(): sFile=%s", sFile.getStr(
)); } } while (false)
;
274#endif /* OSL_DEBUG_LEVEL > 1 */
275
276 oslFileHandle handle;
277 if (!_iniName.isEmpty() &&
278 osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read0x00000001L))
279 {
280 rtl::ByteSequence seq;
281
282 while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq))
283 {
284 OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
285 sal_Int32 nIndex = line.indexOf('=');
286 if (nIndex >= 1)
287 {
288 rtl::OUString sName = OStringToOUString(
289 line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)) );
290 rtl::OUString sValue = OStringToOUString(
291 line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) );
292
293#if OSL_DEBUG_LEVEL1 > 1
294 OString name_tmp = OUStringToOString(sName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
295 OString value_tmp = OUStringToOString(sValue, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)));
296 OSL_TRACE(do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "298" ": "), "pushing: name=%s value=%s", name_tmp.getStr
(), value_tmp.getStr()); } } while (false)
297 "pushing: name=%s value=%s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "298" ": "), "pushing: name=%s value=%s", name_tmp.getStr
(), value_tmp.getStr()); } } while (false)
298 name_tmp.getStr(), value_tmp.getStr() )do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "298" ": "), "pushing: name=%s value=%s", name_tmp.getStr
(), value_tmp.getStr()); } } while (false)
;
299#endif /* OSL_DEBUG_LEVEL > 1 */
300
301 map_[sName] = sValue;
302 }
303 }
304 osl_closeFile(handle);
305 }
306#if OSL_DEBUG_LEVEL1 > 1
307 else
308 {
309 OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
310 OSL_TRACE( "couldn't open file: %s", file_tmp.getStr() )do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "310" ": "), "couldn't open file: %s", file_tmp.getStr()
); } } while (false)
;
311 }
312#endif /* OSL_DEBUG_LEVEL > 1 */
313}
314
315namespace {
316
317class BootstrapMap: private boost::noncopyable {
318public:
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
331private:
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
342BootstrapMap::BootstrapMap():
343 baseIni_(0), hasFundamentalIni_(false), fundamentalIni_(0)
344{}
345
346BootstrapMap::~BootstrapMap() {
347 for (Map::iterator i(map_.begin()); i != map_.end(); ++i) {
348 delete i->second;
349 }
350}
351
352Bootstrap_Impl * BootstrapMap::getIni(
353 rtl::OUString const & uri, bool alwaysCreate)
354{
355 rtl::OUString normUri; // normalize URI if possible
356 DirectoryItem dirItem;
357 FileStatus status(osl_FileStatus_Mask_FileURL0x00000200);
358 if (DirectoryItem::get(uri, dirItem) == DirectoryItem::E_None &&
359 dirItem.getFileStatus(status) == DirectoryItem::E_None)
360 {
361 normUri = status.getFileURL();
362 } else if (alwaysCreate) {
363 normUri = uri;
364 } else {
365 return 0;
366 }
367 osl::MutexGuard g(mutex_);
368 Map::iterator i(map_.find(normUri));
369 if (i == map_.end()) {
370 std::auto_ptr< Bootstrap_Impl > b(new Bootstrap_Impl(normUri));
371 std::pair< Map::iterator, bool > ins(
372 map_.insert(Map::value_type(normUri, b.get())));
373 b.release();
374 OSL_ASSERT(ins.second)do { if (true && (!(ins.second))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "374" ": "), "OSL_ASSERT: %s", "ins.second"); } } while (
false)
;
375 i = ins.first;
376 }
377 return i->second;
378}
379
380void BootstrapMap::setBaseIniUri(rtl::OUString const & uri) {
381 OSL_ASSERT(!uri.isEmpty())do { if (true && (!(!uri.isEmpty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "381" ": "), "OSL_ASSERT: %s", "!uri.isEmpty()"); } } while
(false)
;
382 osl::MutexGuard g(mutex_);
383 OSL_ASSERT(baseIniUri_.isEmpty() && baseIni_ == 0)do { if (true && (!(baseIniUri_.isEmpty() && baseIni_
== 0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "383" ": "), "OSL_ASSERT: %s", "baseIniUri_.isEmpty() && baseIni_ == 0"
); } } while (false)
;
384 baseIniUri_ = uri;
385}
386
387Bootstrap_Impl * BootstrapMap::getBaseIni() {
388 osl::MutexGuard g(mutex_);
389 if (baseIni_ == 0) {
390 rtl::OUString uri;
391 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(((rtl_TextEncoding) 76)));
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 if (CommandLineParameters::get().get(
408 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")(&("INIFILENAME")[0]), ((sal_Int32)((sizeof ("INIFILENAME"
) / sizeof (("INIFILENAME")[0]))-1)), (((rtl_TextEncoding) 11
))
),
409 &uri))
410 {
411 resolvePathnameUrl(&uri);
412 } else {
413 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 for (int i = 0; i < 2; i++) {
421 if (uri.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(BIN_EXT)(&(BIN_EXT)[0]), ((sal_Int32)(sizeof (BIN_EXT) / sizeof (
(BIN_EXT)[0]))-1)
)) {
422 uri = uri.copy(
423 0, uri.getLength() - RTL_CONSTASCII_LENGTH(BIN_EXT)((sal_Int32)((sizeof (BIN_EXT) / sizeof ((BIN_EXT)[0]))-1)));
424 } else if (uri.endsWithAsciiL(
425 RTL_CONSTASCII_STRINGPARAM(EXE_EXT)(&(EXE_EXT)[0]), ((sal_Int32)(sizeof (EXE_EXT) / sizeof (
(EXE_EXT)[0]))-1)
)) {
426 uri = uri.copy(
427 0, uri.getLength() - RTL_CONSTASCII_LENGTH(EXE_EXT)((sal_Int32)((sizeof (EXE_EXT) / sizeof ((EXE_EXT)[0]))-1)));
428 }
429 }
430 uri += rtl::OUString(
431 RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE(""))(&("" "rc")[0]), ((sal_Int32)((sizeof ("" "rc") / sizeof (
("" "rc")[0]))-1)), (((rtl_TextEncoding) 11))
);
432 }
433#endif
434 } else {
435 uri = baseIniUri_;
436 }
437 baseIni_ = getIni(uri, true);
438 }
439 return baseIni_;
440}
441
442Bootstrap_Impl * BootstrapMap::getFundamentalIni() {
443 osl::MutexGuard g(mutex_);
444 if (!hasFundamentalIni_) {
445 rtl::OUString uri;
446 fundamentalIni_ =
447 (getBaseIni()->getValue(
448 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")(&("URE_BOOTSTRAP")[0]), ((sal_Int32)((sizeof ("URE_BOOTSTRAP"
) / sizeof (("URE_BOOTSTRAP")[0]))-1)), (((rtl_TextEncoding) 11
))
),
449 &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0) &&
450 resolvePathnameUrl(&uri))
451 ? getIni(uri, false) : 0;
452 hasFundamentalIni_ = true;
453 }
454 return fundamentalIni_;
455}
456
457struct BootstrapMapSingleton:
458 public rtl::Static< BootstrapMap, BootstrapMapSingleton >
459{};
460
461}
462
463bool 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 if (mode == LOOKUP_MODE_NORMAL &&
469 key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP")(&("URE_BOOTSTRAP")[0]), ((sal_Int32)(sizeof ("URE_BOOTSTRAP"
) / sizeof (("URE_BOOTSTRAP")[0]))-1)
))
470 {
471 mode = LOOKUP_MODE_URE_BOOTSTRAP;
472 }
473 if (override && getDirectValue(key, value, mode, requestStack)) {
474 return true;
475 }
476 if ( key == "_OS" ) {
477 rtl_uString_assign(
478 value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_OS)(&("Linux")[0]), ((sal_Int32)((sizeof ("Linux") / sizeof (
("Linux")[0]))-1)), (((rtl_TextEncoding) 11))
).pData);
479 return true;
480 }
481 if ( key == "_ARCH" ) {
482 rtl_uString_assign(
483 value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_ARCH)(&("x86")[0]), ((sal_Int32)((sizeof ("x86") / sizeof (("x86"
)[0]))-1)), (((rtl_TextEncoding) 11))
).pData);
484 return true;
485 }
486 if ( key == "_CPPU_ENV" ) {
487 rtl_uString_assign(
488 value,
489 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))(&("gcc3")[0]), ((sal_Int32)((sizeof ("gcc3") / sizeof ((
"gcc3")[0]))-1)), (((rtl_TextEncoding) 11))
).
490 pData));
491 return true;
492 }
493 if ( key == "ORIGIN" ) {
494 rtl_uString_assign(
495 value,
496 _iniName.copy(
497 0, std::max<sal_Int32>(0, _iniName.lastIndexOf('/'))).pData);
498 return true;
499 }
500 if (getAmbienceValue(key, value, mode, requestStack)) {
501 return true;
502 }
503 if ( key == "SYSUSERCONFIG" ) {
504 rtl::OUString v;
505 bool b = osl::Security().getConfigDir(v);
506 EnsureNoFinalSlash(v);
507 rtl_uString_assign(value, v.pData);
508 return b;
509 }
510 if ( key == "SYSUSERHOME" ) {
511 rtl::OUString v;
512 bool b = osl::Security().getHomeDir(v);
513 EnsureNoFinalSlash(v);
514 rtl_uString_assign(value, v.pData);
515 return b;
516 }
517 if ( key == "SYSBINDIR" ) {
518 getExecutableDirectory_Impl(value);
519 return true;
520 }
521 Bootstrap_Impl * b = BootstrapMapSingleton::get().getBaseIni();
522 if (b != this && b->getDirectValue(key, value, mode, requestStack)) {
523 return true;
524 }
525 if (!override && getDirectValue(key, value, mode, requestStack)) {
526 return true;
527 }
528 if (mode == LOOKUP_MODE_NORMAL) {
529 b = BootstrapMapSingleton::get().getFundamentalIni();
530 if (b != 0 && b != this &&
531 b->getDirectValue(key, value, mode, requestStack))
532 {
533 return true;
534 }
535 }
536 if (defaultValue != NULL__null) {
537 rtl_uString_assign(value, defaultValue);
538 return true;
539 }
540 rtl_uString_new(value);
541 return false;
542}
543
544bool Bootstrap_Impl::getDirectValue(
545 rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
546 ExpandRequestLink const * requestStack) const
547{
548 rtl::OUString v;
549 if (get(key, &v)) {
550 expandValue(value, v, mode, this, key, requestStack);
551 return true;
552 } else {
553 return false;
554 }
555}
556
557bool Bootstrap_Impl::getAmbienceValue(
558 rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
559 ExpandRequestLink const * requestStack) const
560{
561 rtl::OUString v;
562 if (ExplicitParameters::get().get(key, &v) ||
563 CommandLineParameters::get().get(key, &v) ||
564 osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None)
565 {
566 expandValue(value, v, mode, NULL__null, key, requestStack);
567 return true;
568 } else {
569 return false;
570 }
571}
572
573void 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 (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 requestFile, requestKey, requestStack)).pData);
587}
588
589rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
590 rtl_uString * pIniName
591) SAL_THROW_EXTERN_C()throw ()
592{
593 return BootstrapMapSingleton::get().getIni(rtl::OUString(pIniName), false);
594}
595
596//----------------------------------------------------------------------------
597
598void SAL_CALL rtl_bootstrap_args_close (
599 SAL_UNUSED_PARAMETER__attribute__ ((unused)) rtlBootstrapHandle
600) SAL_THROW_EXTERN_C()throw ()
601{
602 // do nothing; the BootstrapMap::map_ just keeps growing for now
603}
604
605//----------------------------------------------------------------------------
606
607sal_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()throw ()
613{
614 return
615 (handle == 0
616 ? BootstrapMapSingleton::get().getBaseIni()
617 : static_cast< Bootstrap_Impl * >(handle))->
618 getValue(pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, 0);
619}
620
621//----------------------------------------------------------------------------
622
623void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
624 rtlBootstrapHandle handle,
625 rtl_uString ** ppIniName
626) SAL_THROW_EXTERN_C()throw ()
627{
628 rtl_uString_assign(
629 ppIniName,
630 ((handle == 0
631 ? BootstrapMapSingleton::get().getBaseIni()
632 : static_cast<Bootstrap_Impl*>(handle))->
633 _iniName.pData));
634}
635
636//----------------------------------------------------------------------------
637
638void SAL_CALL rtl_bootstrap_setIniFileName (
639 rtl_uString * pName
640) SAL_THROW_EXTERN_C()throw ()
641{
642 BootstrapMapSingleton::get().setBaseIniUri(rtl::OUString(pName));
643}
644
645//----------------------------------------------------------------------------
646
647sal_Bool SAL_CALL rtl_bootstrap_get (
648 rtl_uString * pName,
649 rtl_uString ** ppValue,
650 rtl_uString * pDefault
651) SAL_THROW_EXTERN_C()throw ()
652{
653 return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault);
654}
655
656//----------------------------------------------------------------------------
657
658void SAL_CALL rtl_bootstrap_set (
659 rtl_uString * pName,
660 rtl_uString * pValue
661) SAL_THROW_EXTERN_C()throw ()
662{
663 ExplicitParameters::get().set(rtl::OUString(pName), rtl::OUString(pValue));
664}
665
666//----------------------------------------------------------------------------
667
668void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
669 rtlBootstrapHandle handle,
670 rtl_uString ** macro
671) SAL_THROW_EXTERN_C()throw ()
672{
673 rtl::OUString expanded(
674 expandMacros(
675 (handle == 0
676 ? BootstrapMapSingleton::get().getBaseIni()
677 : static_cast< Bootstrap_Impl * >(handle)),
678 *reinterpret_cast< OUString const * >(macro), LOOKUP_MODE_NORMAL,
679 0));
680 rtl_uString_assign(macro, expanded.pData);
681}
682
683//----------------------------------------------------------------------------
684
685void SAL_CALL rtl_bootstrap_expandMacros(
686 rtl_uString ** macro )
687 SAL_THROW_EXTERN_C()throw ()
688{
689 rtl_bootstrap_expandMacros_from_handle(NULL__null, macro);
690}
691
692void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded )
693 SAL_THROW_EXTERN_C()throw ()
694{
695 OSL_ASSERT(value != NULL)do { if (true && (!(value != __null))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "695" ": "), "OSL_ASSERT: %s", "value != NULL"); } } while
(false)
;
696 rtl::OUStringBuffer b;
697 for (sal_Int32 i = 0; i < value->length; ++i) {
Access to field 'length' results in a dereference of a null pointer (loaded from variable 'value')
698 sal_Unicode c = value->buffer[i];
699 if (c == '$' || c == '\\') {
700 b.append(sal_Unicode('\\'));
701 }
702 b.append(c);
703 }
704 rtl_uString_assign(encoded, b.makeStringAndClear().pData);
705}
706
707namespace {
708
709int hex(sal_Unicode c) {
710 return
711 c >= '0' && c <= '9' ? c - '0' :
712 c >= 'A' && c <= 'F' ? c - 'A' + 10 :
713 c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
714}
715
716sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
717 OSL_ASSERT(do { if (true && (!(pos != __null && *pos >=
0 && *pos < text.getLength() && escaped !=
__null))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN)
, ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "718" ": "), "OSL_ASSERT: %s", "pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL"
); } } while (false)
718 pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL)do { if (true && (!(pos != __null && *pos >=
0 && *pos < text.getLength() && escaped !=
__null))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN)
, ("legacy.osl"), ("/usr/local/src/libreoffice/sal/rtl/source/bootstrap.cxx"
":" "718" ": "), "OSL_ASSERT: %s", "pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL"
); } } while (false)
;
719 sal_Unicode c = text[(*pos)++];
720 if (c == '\\') {
721 int n1, n2, n3, n4;
722 if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
723 ((n1 = hex(text[*pos + 1])) >= 0) &&
724 ((n2 = hex(text[*pos + 2])) >= 0) &&
725 ((n3 = hex(text[*pos + 3])) >= 0) &&
726 ((n4 = hex(text[*pos + 4])) >= 0))
727 {
728 *pos += 5;
729 *escaped = true;
730 return static_cast< sal_Unicode >(
731 (n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
732 } else if (*pos < text.getLength()) {
733 *escaped = true;
734 return text[(*pos)++];
735 }
736 }
737 *escaped = false;
738 return c;
739}
740
741rtl::OUString lookup(
742 Bootstrap_Impl const * file, LookupMode mode, bool override,
743 rtl::OUString const & key, ExpandRequestLink const * requestStack)
744{
745 rtl::OUString v;
746 (file == 0 ? BootstrapMapSingleton::get().getBaseIni() : file)->getValue(
747 key, &v.pData, NULL__null, mode, override, requestStack);
748 return v;
749}
750
751rtl::OUString expandMacros(
752 Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
753 ExpandRequestLink const * requestStack)
754{
755 rtl::OUStringBuffer buf;
756 for (sal_Int32 i = 0; i < text.getLength();) {
757 bool escaped;
758 sal_Unicode c = read(text, &i, &escaped);
759 if (escaped || c != '$') {
760 buf.append(c);
761 } else {
762 if (i < text.getLength() && text[i] == '{') {
763 ++i;
764 sal_Int32 p = i;
765 sal_Int32 nesting = 0;
766 rtl::OUString seg[3];
767 int n = 0;
768 while (i < text.getLength()) {
769 sal_Int32 j = i;
770 c = read(text, &i, &escaped);
771 if (!escaped) {
772 switch (c) {
773 case '{':
774 ++nesting;
775 break;
776 case '}':
777 if (nesting == 0) {
778 seg[n++] = text.copy(p, j - p);
779 goto done;
780 } else {
781 --nesting;
782 }
783 break;
784 case ':':
785 if (nesting == 0 && n < 2) {
786 seg[n++] = text.copy(p, j - p);
787 p = i;
788 }
789 break;
790 }
791 }
792 }
793 done:
794 for (int j = 0; j < n; ++j) {
795 seg[j] = expandMacros(file, seg[j], mode, requestStack);
796 }
797 if (n == 1) {
798 buf.append(lookup(file, mode, false, seg[0], requestStack));
799 } else if (n == 2 && seg[0] == ".link") {
800 osl::File f(seg[1]);
801 rtl::ByteSequence seq;
802 rtl::OUString line;
803 rtl::OUString url;
804 // Silently ignore any errors (is that good?):
805 if ((f.open(osl_File_OpenFlag_Read0x00000001L) ==
806 osl::FileBase::E_None) &&
807 f.readLine(seq) == osl::FileBase::E_None &&
808 rtl_convertStringToUString(
809 &line.pData,
810 reinterpret_cast< char const * >(
811 seq.getConstArray()),
812 seq.getLength(), RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)),
813 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR((sal_uInt32)0x0001) |
814 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR((sal_uInt32)0x0010) |
815 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR((sal_uInt32)0x0100))) &&
816 (osl::File::getFileURLFromSystemPath(line, url) ==
817 osl::FileBase::E_None))
818 {
819 try {
820 buf.append(
821 rtl::Uri::convertRelToAbs(seg[1], url));
822 } catch (const rtl::MalformedUriException &) {}
823 }
824 } else if (n == 3 && seg[0] == ".override") {
825 rtl::Bootstrap b(seg[1]);
826 Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
827 b.getHandle());
828 buf.append(
829 lookup(f, mode, f != NULL__null, seg[2], requestStack));
830 } else {
831 if (n == 3 && seg[1].isEmpty()) {
832 // For backward compatibility, treat ${file::key} the
833 // same as just ${file:key}:
834 seg[1] = seg[2];
835 n = 2;
836 }
837 if (n == 2) {
838 buf.append(
839 lookup(
840 static_cast< Bootstrap_Impl * >(
841 rtl::Bootstrap(seg[0]).getHandle()),
842 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(((rtl_TextEncoding) 76))),
853 rtl::OUStringToOString(
854 seg[2], RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))),
855 rtl::OString()),
856 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))));
857 }
858 }
859 } else {
860 rtl::OUStringBuffer kbuf;
861 for (; i < text.getLength();) {
862 sal_Int32 j = i;
863 c = read(text, &j, &escaped);
864 if (!escaped &&
865 (c == ' ' || c == '$' || c == '-' || c == '/' ||
866 c == ';' || c == '\\'))
867 {
868 break;
869 }
870 kbuf.append(c);
871 i = j;
872 }
873 buf.append(
874 lookup(
875 file, mode, false, kbuf.makeStringAndClear(),
876 requestStack));
877 }
878 }
879 }
880 return buf.makeStringAndClear();
881}
882
883}
884
885/* vim:set shiftwidth=4 softtabstop=4 expandtab: */