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') |
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 | |
64 | extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl( |
65 | rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C()throw (); |
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 | bool 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 | |
85 | bool 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 | |
99 | enum LookupMode { |
100 | LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP, |
101 | LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION }; |
102 | |
103 | 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 | 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 | 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 | |
130 | class ParameterMap: private boost::noncopyable { |
131 | public: |
132 | bool get(rtl::OUString const & key, rtl::OUString * value) const; |
133 | |
134 | protected: |
135 | ParameterMap() {} |
136 | |
137 | ~ParameterMap() {} |
138 | |
139 | typedef std::map< rtl::OUString, rtl::OUString > Map; |
140 | |
141 | Map map_; |
142 | }; |
143 | |
144 | bool 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 | |
155 | 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 | bool 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 | |
172 | void ExplicitParameterMap::set( |
173 | rtl::OUString const & key, rtl::OUString const & value) |
174 | { |
175 | osl::MutexGuard g(mutex_); |
176 | map_[key] = value; |
177 | } |
178 | |
179 | struct ExplicitParameters: |
180 | public rtl::Static< ExplicitParameterMap, ExplicitParameters > |
181 | {}; |
182 | |
183 | class CommandLineParameterMap: public ParameterMap { |
184 | public: |
185 | CommandLineParameterMap(); |
186 | }; |
187 | |
188 | CommandLineParameterMap::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 | |
209 | struct CommandLineParameters: |
210 | public rtl::Static< CommandLineParameterMap, CommandLineParameters > |
211 | {}; |
212 | |
213 | } |
214 | |
215 | static 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 | |
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 | inline 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 | |
244 | 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 | Bootstrap_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 | |
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 | BootstrapMap::BootstrapMap(): |
343 | baseIni_(0), hasFundamentalIni_(false), fundamentalIni_(0) |
344 | {} |
345 | |
346 | BootstrapMap::~BootstrapMap() { |
347 | for (Map::iterator i(map_.begin()); i != map_.end(); ++i) { |
348 | delete i->second; |
349 | } |
350 | } |
351 | |
352 | Bootstrap_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 | |
380 | void 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 | |
387 | Bootstrap_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 | |
442 | Bootstrap_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 | |
457 | struct BootstrapMapSingleton: |
458 | public rtl::Static< BootstrapMap, BootstrapMapSingleton > |
459 | {}; |
460 | |
461 | } |
462 | |
463 | 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 | 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 | |
544 | bool 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 | |
557 | bool 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 | |
573 | 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 | (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 | |
589 | rtlBootstrapHandle 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 | |
598 | void 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 | |
607 | 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()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 | |
623 | void 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 | |
638 | void 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 | |
647 | sal_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 | |
658 | void 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 | |
668 | void 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 | |
685 | void 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 | |
692 | void 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 | |
707 | namespace { |
708 | |
709 | int 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 | |
716 | sal_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 | |
741 | rtl::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 | |
751 | rtl::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: */ |