/src/libreoffice/unotools/source/config/bootstrap.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <string_view> |
23 | | |
24 | | #include <config_folders.h> |
25 | | |
26 | | #include <unotools/bootstrap.hxx> |
27 | | |
28 | | #include <rtl/ustring.hxx> |
29 | | #include <rtl/ustrbuf.hxx> |
30 | | #include <sal/log.hxx> |
31 | | #include <osl/file.hxx> |
32 | | #include <osl/diagnose.h> |
33 | | |
34 | | #include <rtl/bootstrap.hxx> |
35 | | #include <osl/process.h> |
36 | | |
37 | | // #define this to true, if remembering defaults is not supported properly |
38 | | #define RTL_BOOTSTRAP_DEFAULTS_BROKEN true |
39 | | |
40 | | constexpr OUString BOOTSTRAP_ITEM_PRODUCT_KEY = u"ProductKey"_ustr; |
41 | | constexpr OUStringLiteral BOOTSTRAP_ITEM_VERSIONFILE = u"Location"; |
42 | | constexpr OUStringLiteral BOOTSTRAP_ITEM_BUILDID = u"buildid"; |
43 | | |
44 | | constexpr OUStringLiteral BOOTSTRAP_ITEM_BASEINSTALLATION = u"BRAND_BASE_DIR"; |
45 | | constexpr OUStringLiteral BOOTSTRAP_ITEM_USERINSTALLATION = u"UserInstallation"; |
46 | | |
47 | | constexpr OUString BOOTSTRAP_ITEM_USERDIR = u"UserDataDir"_ustr; |
48 | | |
49 | | constexpr OUStringLiteral BOOTSTRAP_DEFAULT_BASEINSTALL = u"$SYSBINDIR/.."; |
50 | | |
51 | | constexpr OUString BOOTSTRAP_DIRNAME_USERDIR = u"user"_ustr; |
52 | | |
53 | | typedef char const * AsciiString; |
54 | | |
55 | | namespace utl |
56 | | { |
57 | | |
58 | | // Implementation class: Bootstrap::Impl |
59 | | |
60 | | static OUString makeImplName() |
61 | 7 | { |
62 | 7 | OUString uri; |
63 | 7 | rtl::Bootstrap::get( u"BRAND_BASE_DIR"_ustr, uri); |
64 | 7 | return uri + "/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap"); |
65 | 7 | } |
66 | | |
67 | | class Bootstrap::Impl |
68 | | { |
69 | | const OUString m_aImplName; |
70 | | public: // struct to cache the result of a path lookup |
71 | | struct PathData |
72 | | { |
73 | | OUString path; |
74 | | PathStatus status; |
75 | | |
76 | | PathData() |
77 | 28 | : status(DATA_UNKNOWN) |
78 | 28 | {} |
79 | | }; |
80 | | public: // data members |
81 | | // base install data |
82 | | PathData aBaseInstall_; |
83 | | |
84 | | // user install data |
85 | | PathData aUserInstall_; |
86 | | |
87 | | // INI files |
88 | | PathData aBootstrapINI_; |
89 | | PathData aVersionINI_; |
90 | | |
91 | | // overall status |
92 | | Status status_; |
93 | | |
94 | | public: // construction and initialization |
95 | 7 | Impl() : m_aImplName(makeImplName()) |
96 | 7 | { |
97 | 7 | initialize(); |
98 | 7 | } |
99 | | |
100 | | void initialize(); |
101 | | |
102 | | // access helper |
103 | | OUString getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const; |
104 | | |
105 | 58.3k | const OUString& getImplName() const { return m_aImplName; } |
106 | | |
107 | | private: // implementation |
108 | | bool initBaseInstallationData(rtl::Bootstrap const & _rData); |
109 | | bool initUserInstallationData(rtl::Bootstrap const & _rData); |
110 | | }; |
111 | | |
112 | | namespace |
113 | | { |
114 | | Bootstrap::Impl& theImpl() |
115 | 116k | { |
116 | 116k | static Bootstrap::Impl SINGLETON; |
117 | 116k | return SINGLETON; |
118 | 116k | } |
119 | | } |
120 | | |
121 | | const Bootstrap::Impl& Bootstrap::data() |
122 | 116k | { |
123 | 116k | return theImpl(); |
124 | 116k | } |
125 | | |
126 | | bool Bootstrap::getProcessWorkingDir(OUString &rUrl) |
127 | 21 | { |
128 | 21 | rUrl.clear(); |
129 | 21 | OUString s(u"$OOO_CWD"_ustr); |
130 | 21 | rtl::Bootstrap::expandMacros(s); |
131 | 21 | if (s.isEmpty()) |
132 | 21 | { |
133 | 21 | if (osl_getProcessWorkingDir(&rUrl.pData) == osl_Process_E_None) |
134 | 21 | return true; |
135 | 21 | } |
136 | 0 | else if (s[0] == '1') |
137 | 0 | { |
138 | 0 | rUrl = s.copy(1); |
139 | 0 | return true; |
140 | 0 | } |
141 | 0 | else if (s[0] == '2' && |
142 | 0 | (osl::FileBase::getFileURLFromSystemPath(s.copy(1), rUrl) == |
143 | 0 | osl::FileBase::E_None)) |
144 | 0 | { |
145 | 0 | return true; |
146 | 0 | } |
147 | 0 | return false; |
148 | 21 | } |
149 | | |
150 | | void Bootstrap::reloadData() |
151 | 0 | { |
152 | 0 | theImpl().initialize(); |
153 | 0 | } |
154 | | |
155 | | // helper |
156 | | |
157 | | typedef Bootstrap::PathStatus PathStatus; |
158 | | |
159 | | sal_Unicode const cURLSeparator = '/'; |
160 | | |
161 | | // path status utility function |
162 | | static PathStatus implCheckStatusOfURL(OUString const& _sURL, osl::DirectoryItem& aDirItem) |
163 | 21 | { |
164 | 21 | using namespace osl; |
165 | | |
166 | 21 | PathStatus eStatus = Bootstrap::DATA_UNKNOWN; |
167 | | |
168 | 21 | if (!_sURL.isEmpty()) |
169 | 21 | { |
170 | 21 | switch( DirectoryItem::get(_sURL, aDirItem) ) |
171 | 21 | { |
172 | 7 | case DirectoryItem::E_None: // Success |
173 | 7 | eStatus = Bootstrap::PATH_EXISTS; |
174 | 7 | break; |
175 | | |
176 | 14 | case DirectoryItem::E_NOENT: // No such file or directory |
177 | 14 | eStatus = Bootstrap::PATH_VALID; |
178 | 14 | break; |
179 | | |
180 | 0 | case DirectoryItem::E_INVAL: // the format of the parameters was not valid |
181 | 0 | case DirectoryItem::E_NAMETOOLONG: // File name too long |
182 | 0 | case DirectoryItem::E_NOTDIR: // A component of the path prefix of path is not a directory |
183 | 0 | eStatus = Bootstrap::DATA_INVALID; |
184 | 0 | break; |
185 | | |
186 | | // how to handle these ? |
187 | 0 | case DirectoryItem::E_LOOP: // Too many symbolic links encountered |
188 | 0 | case DirectoryItem::E_ACCES: // permission denied |
189 | | // any other error - what to do ? |
190 | 0 | default: |
191 | 0 | eStatus = Bootstrap::DATA_UNKNOWN; |
192 | 0 | break; |
193 | 21 | } |
194 | 21 | } |
195 | 0 | else |
196 | 0 | { |
197 | 0 | eStatus = Bootstrap::DATA_MISSING; |
198 | 0 | } |
199 | | |
200 | 21 | return eStatus; |
201 | 21 | } |
202 | | |
203 | | static bool implNormalizeURL(OUString & _sURL, osl::DirectoryItem& aDirItem) |
204 | 7 | { |
205 | 7 | using namespace osl; |
206 | | |
207 | 7 | OSL_PRECOND(aDirItem.is(), "Opened DirItem required"); |
208 | | |
209 | 7 | static const sal_uInt32 cosl_FileStatus_Mask = osl_FileStatus_Mask_FileURL; |
210 | | |
211 | 7 | FileStatus aFileStatus(cosl_FileStatus_Mask); |
212 | | |
213 | 7 | if (aDirItem.getFileStatus(aFileStatus) != DirectoryItem::E_None) |
214 | 0 | return false; |
215 | | |
216 | 7 | OUString aNormalizedURL = aFileStatus.getFileURL(); |
217 | | |
218 | 7 | if (aNormalizedURL.isEmpty()) |
219 | 0 | return false; |
220 | | |
221 | | // #109863# sal/osl returns final slash for file URLs contradicting |
222 | | // the URL/URI RFCs. |
223 | 7 | if ( !aNormalizedURL.endsWith(OUStringChar(cURLSeparator)) ) |
224 | 7 | _sURL = aNormalizedURL; |
225 | 0 | else |
226 | 0 | _sURL = aNormalizedURL.copy( 0, aNormalizedURL.getLength()-1 ); |
227 | | |
228 | 7 | return true; |
229 | 7 | } |
230 | | |
231 | | static bool implEnsureAbsolute(OUString & _rsURL) // also strips embedded dots !! |
232 | 21 | { |
233 | 21 | using osl::File; |
234 | | |
235 | 21 | OUString sBasePath; |
236 | 21 | OSL_VERIFY(Bootstrap::getProcessWorkingDir(sBasePath)); |
237 | | |
238 | 21 | OUString sAbsolute; |
239 | 21 | if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute)) |
240 | 21 | { |
241 | 21 | _rsURL = sAbsolute; |
242 | 21 | return true; |
243 | 21 | } |
244 | 0 | else |
245 | 0 | { |
246 | 0 | OSL_FAIL("Could not get absolute file URL for URL"); |
247 | 0 | return false; |
248 | 0 | } |
249 | 21 | } |
250 | | |
251 | | static bool implMakeAbsoluteURL(OUString & _rsPathOrURL) |
252 | 21 | { |
253 | 21 | using namespace osl; |
254 | | |
255 | 21 | bool bURL; |
256 | | |
257 | 21 | OUString sOther; |
258 | | // check if it already was normalized |
259 | 21 | if ( File::E_None == File::getSystemPathFromFileURL(_rsPathOrURL, sOther) ) |
260 | 21 | { |
261 | 21 | bURL = true; |
262 | 21 | } |
263 | | |
264 | 0 | else if ( File::E_None == File::getFileURLFromSystemPath(_rsPathOrURL, sOther) ) |
265 | 0 | { |
266 | 0 | _rsPathOrURL = sOther; |
267 | 0 | bURL = true; |
268 | 0 | } |
269 | 0 | else |
270 | 0 | bURL = false; |
271 | | |
272 | 21 | return bURL && implEnsureAbsolute(_rsPathOrURL); |
273 | 21 | } |
274 | | |
275 | | static PathStatus dbgCheckStatusOfURL(OUString const& _sURL) |
276 | 0 | { |
277 | 0 | using namespace osl; |
278 | 0 |
|
279 | 0 | DirectoryItem aDirItem; |
280 | 0 |
|
281 | 0 | return implCheckStatusOfURL(_sURL,aDirItem); |
282 | 0 | } |
283 | | |
284 | | static PathStatus checkStatusAndNormalizeURL(OUString & _sURL) |
285 | 28 | { |
286 | 28 | using namespace osl; |
287 | | |
288 | 28 | PathStatus eStatus = Bootstrap::DATA_UNKNOWN; |
289 | | |
290 | 28 | if (_sURL.isEmpty()) |
291 | 7 | eStatus = Bootstrap::DATA_MISSING; |
292 | | |
293 | 21 | else if ( !implMakeAbsoluteURL(_sURL) ) |
294 | 0 | eStatus = Bootstrap::DATA_INVALID; |
295 | | |
296 | 21 | else |
297 | 21 | { |
298 | 21 | DirectoryItem aDirItem; |
299 | | |
300 | 21 | eStatus = implCheckStatusOfURL(_sURL,aDirItem); |
301 | | |
302 | 21 | if (eStatus == Bootstrap::PATH_EXISTS && !implNormalizeURL(_sURL,aDirItem)) |
303 | 21 | OSL_FAIL("Unexpected failure getting actual URL for existing object"); |
304 | 21 | } |
305 | 28 | return eStatus; |
306 | 28 | } |
307 | | |
308 | | // helpers to build and check a nested URL |
309 | | static PathStatus getDerivedPath( |
310 | | OUString& _rURL, |
311 | | OUString const& _aBaseURL, PathStatus _aBaseStatus, |
312 | | std::u16string_view _sRelativeURL, |
313 | | rtl::Bootstrap const & _rData, OUString const& _sBootstrapParameter |
314 | | ) |
315 | 58.3k | { |
316 | 58.3k | OUString sDerivedURL; |
317 | 58.3k | OSL_PRECOND(!_rData.getFrom(_sBootstrapParameter,sDerivedURL),"Setting for derived path is already defined"); |
318 | 58.3k | OSL_PRECOND(!_sRelativeURL.empty() && _sRelativeURL[0] != cURLSeparator,"Invalid Relative URL"); |
319 | | |
320 | 58.3k | PathStatus aStatus = _aBaseStatus; |
321 | | |
322 | | // do we have a base path ? |
323 | 58.3k | if (!_aBaseURL.isEmpty()) |
324 | 7 | { |
325 | 7 | OSL_PRECOND(!_aBaseURL.endsWith(OUStringChar(cURLSeparator)), "Unexpected: base URL ends in slash"); |
326 | | |
327 | 7 | sDerivedURL = _aBaseURL + OUStringChar(cURLSeparator) + _sRelativeURL; |
328 | | |
329 | | // a derived (nested) URL can only exist or have a lesser status, if the parent exists |
330 | 7 | if (aStatus == Bootstrap::PATH_EXISTS) |
331 | 7 | aStatus = checkStatusAndNormalizeURL(sDerivedURL); |
332 | | |
333 | 0 | else // the relative appendix must be valid |
334 | 7 | OSL_ASSERT(aStatus != Bootstrap::PATH_VALID || dbgCheckStatusOfURL(sDerivedURL) == Bootstrap::PATH_VALID); |
335 | | |
336 | 7 | _rData.getFrom(_sBootstrapParameter, _rURL, sDerivedURL); |
337 | | |
338 | 7 | OSL_ENSURE(sDerivedURL == _rURL,"Could not set derived URL via Bootstrap default parameter"); |
339 | 7 | SAL_WARN_IF( !(RTL_BOOTSTRAP_DEFAULTS_BROKEN || (_rData.getFrom(_sBootstrapParameter,sDerivedURL) && sDerivedURL==_rURL)), |
340 | 7 | "unotools.config", |
341 | 7 | "Use of default did not affect bootstrap value"); |
342 | 7 | } |
343 | 58.3k | else |
344 | 58.3k | { |
345 | | // clear the result |
346 | 58.3k | _rURL = _aBaseURL; |
347 | | |
348 | | // if we have no data it can't be a valid path |
349 | 58.3k | OSL_ASSERT( aStatus > Bootstrap::PATH_VALID ); |
350 | 58.3k | } |
351 | | |
352 | 58.3k | return aStatus; |
353 | 58.3k | } |
354 | | |
355 | | static PathStatus getDerivedPath( |
356 | | OUString& _rURL, |
357 | | Bootstrap::Impl::PathData const& _aBaseData, |
358 | | std::u16string_view _sRelativeURL, |
359 | | rtl::Bootstrap const & _rData, OUString const& _sBootstrapParameter |
360 | | ) |
361 | 58.3k | { |
362 | 58.3k | return getDerivedPath(_rURL,_aBaseData.path,_aBaseData.status,_sRelativeURL,_rData,_sBootstrapParameter); |
363 | 58.3k | } |
364 | | |
365 | | static OUString getExecutableBaseName() |
366 | 0 | { |
367 | 0 | OUString sExecutable; |
368 | |
|
369 | 0 | if (osl_Process_E_None == osl_getExecutableFile(&sExecutable.pData)) |
370 | 0 | { |
371 | | // split the executable name |
372 | 0 | sal_Int32 nSepIndex = sExecutable.lastIndexOf(cURLSeparator); |
373 | |
|
374 | 0 | sExecutable = sExecutable.copy(nSepIndex + 1); |
375 | | |
376 | | // ... and get the basename (strip the extension) |
377 | 0 | sal_Unicode const cExtensionSep = '.'; |
378 | |
|
379 | 0 | sal_Int32 const nExtIndex = sExecutable.lastIndexOf(cExtensionSep); |
380 | 0 | sal_Int32 const nExtLength = sExecutable.getLength() - nExtIndex - 1; |
381 | 0 | if (0 < nExtIndex && nExtLength < 4) |
382 | 0 | sExecutable = sExecutable.copy(0,nExtIndex); |
383 | 0 | } |
384 | 0 | else |
385 | 0 | SAL_WARN("unotools.config", "Cannot get executable name: osl_getExecutableFile failed"); |
386 | | |
387 | 0 | return sExecutable; |
388 | 0 | } |
389 | | |
390 | | static Bootstrap::PathStatus updateStatus(Bootstrap::Impl::PathData & _rResult) |
391 | 21 | { |
392 | 21 | _rResult.status = checkStatusAndNormalizeURL(_rResult.path); |
393 | 21 | return _rResult.status; |
394 | 21 | } |
395 | | |
396 | | static Bootstrap::PathStatus implGetBootstrapFile(rtl::Bootstrap const & _rData, Bootstrap::Impl::PathData & _rBootstrapFile) |
397 | 7 | { |
398 | 7 | _rData.getIniName(_rBootstrapFile.path); |
399 | | |
400 | 7 | return updateStatus(_rBootstrapFile); |
401 | 7 | } |
402 | | |
403 | | static Bootstrap::PathStatus implGetVersionFile(rtl::Bootstrap const & _rData, Bootstrap::Impl::PathData & _rVersionFile) |
404 | 7 | { |
405 | 7 | _rData.getFrom(BOOTSTRAP_ITEM_VERSIONFILE, _rVersionFile.path); |
406 | | |
407 | 7 | return updateStatus(_rVersionFile); |
408 | 7 | } |
409 | | |
410 | | // Error reporting |
411 | | |
412 | | char const IS_MISSING[] = "is missing"; |
413 | | char const IS_INVALID[] = "is corrupt"; |
414 | | char const PERIOD[] = ". "; |
415 | | |
416 | | static void addFileError(OUStringBuffer& _rBuf, std::u16string_view _aPath, AsciiString _sWhat) |
417 | 0 | { |
418 | 0 | const std::string_view::size_type nLastSep = _aPath.rfind(cURLSeparator); |
419 | 0 | const auto nAfterSep = (nLastSep != std::string_view::npos) ? (nLastSep + 1) : 0; |
420 | 0 | std::u16string_view sSimpleFileName = _aPath.substr(nAfterSep); |
421 | |
|
422 | 0 | _rBuf.append("The configuration file"); |
423 | 0 | _rBuf.append(OUString::Concat(" '") + sSimpleFileName + "' "); |
424 | 0 | _rBuf.appendAscii(_sWhat).append(PERIOD); |
425 | 0 | } |
426 | | |
427 | | static void addMissingDirectoryError(OUStringBuffer& _rBuf, std::u16string_view _aPath) |
428 | 0 | { |
429 | 0 | _rBuf.append(OUString::Concat("The configuration directory '") + _aPath + "' " + |
430 | 0 | IS_MISSING + PERIOD); |
431 | 0 | } |
432 | | |
433 | | static void addUnexpectedError(OUStringBuffer& _rBuf, AsciiString _sExtraInfo = nullptr) |
434 | 0 | { |
435 | 0 | if (nullptr == _sExtraInfo) |
436 | 0 | _sExtraInfo = "An internal failure occurred"; |
437 | |
|
438 | 0 | _rBuf.appendAscii(_sExtraInfo).append(PERIOD); |
439 | 0 | } |
440 | | |
441 | | static Bootstrap::FailureCode describeError(OUStringBuffer& _rBuf, Bootstrap::Impl const& _rData) |
442 | 0 | { |
443 | 0 | Bootstrap::FailureCode eErrCode = Bootstrap::INVALID_BOOTSTRAP_DATA; |
444 | |
|
445 | 0 | _rBuf.append("The program cannot be started. "); |
446 | |
|
447 | 0 | switch (_rData.aUserInstall_.status) |
448 | 0 | { |
449 | 0 | case Bootstrap::PATH_EXISTS: |
450 | 0 | switch (_rData.aBaseInstall_.status) |
451 | 0 | { |
452 | 0 | case Bootstrap::PATH_VALID: |
453 | 0 | addMissingDirectoryError(_rBuf, _rData.aBaseInstall_.path); |
454 | 0 | eErrCode = Bootstrap::MISSING_INSTALL_DIRECTORY; |
455 | 0 | break; |
456 | | |
457 | 0 | case Bootstrap::DATA_INVALID: |
458 | 0 | addUnexpectedError(_rBuf,"The installation path is invalid"); |
459 | 0 | break; |
460 | | |
461 | 0 | case Bootstrap::DATA_MISSING: |
462 | 0 | addUnexpectedError(_rBuf,"The installation path is not available"); |
463 | 0 | break; |
464 | | |
465 | 0 | case Bootstrap::PATH_EXISTS: // seems to be all fine (?) |
466 | 0 | addUnexpectedError(_rBuf,""); |
467 | 0 | break; |
468 | | |
469 | 0 | default: OSL_ASSERT(false); |
470 | 0 | addUnexpectedError(_rBuf); |
471 | 0 | break; |
472 | 0 | } |
473 | 0 | break; |
474 | | |
475 | 0 | case Bootstrap::PATH_VALID: |
476 | 0 | addMissingDirectoryError(_rBuf, _rData.aUserInstall_.path); |
477 | 0 | eErrCode = Bootstrap::MISSING_USER_DIRECTORY; |
478 | 0 | break; |
479 | | |
480 | | // else fall through |
481 | 0 | case Bootstrap::DATA_INVALID: |
482 | 0 | if (_rData.aVersionINI_.status == Bootstrap::PATH_EXISTS) |
483 | 0 | { |
484 | 0 | addFileError(_rBuf, _rData.aVersionINI_.path, IS_INVALID); |
485 | 0 | eErrCode = Bootstrap::INVALID_VERSION_FILE_ENTRY; |
486 | 0 | break; |
487 | 0 | } |
488 | 0 | [[fallthrough]]; |
489 | |
|
490 | 0 | case Bootstrap::DATA_MISSING: |
491 | 0 | switch (_rData.aVersionINI_.status) |
492 | 0 | { |
493 | 0 | case Bootstrap::PATH_EXISTS: |
494 | 0 | addFileError(_rBuf, _rData.aVersionINI_.path, "does not support the current version"); |
495 | 0 | eErrCode = Bootstrap::MISSING_VERSION_FILE_ENTRY; |
496 | 0 | break; |
497 | | |
498 | 0 | case Bootstrap::PATH_VALID: |
499 | 0 | addFileError(_rBuf, _rData.aVersionINI_.path, IS_MISSING); |
500 | 0 | eErrCode = Bootstrap::MISSING_VERSION_FILE; |
501 | 0 | break; |
502 | | |
503 | 0 | default: |
504 | 0 | switch (_rData.aBootstrapINI_.status) |
505 | 0 | { |
506 | 0 | case Bootstrap::PATH_EXISTS: |
507 | 0 | addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_INVALID); |
508 | |
|
509 | 0 | if (_rData.aVersionINI_.status == Bootstrap::DATA_MISSING) |
510 | 0 | eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY; |
511 | 0 | else |
512 | 0 | eErrCode = Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY; |
513 | 0 | break; |
514 | | |
515 | 0 | case Bootstrap::DATA_INVALID: OSL_ASSERT(false); [[fallthrough]]; |
516 | 0 | case Bootstrap::PATH_VALID: |
517 | 0 | addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_MISSING); |
518 | 0 | eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE; |
519 | 0 | break; |
520 | | |
521 | 0 | default: |
522 | 0 | addUnexpectedError(_rBuf); |
523 | 0 | break; |
524 | 0 | } |
525 | 0 | break; |
526 | 0 | } |
527 | 0 | break; |
528 | | |
529 | 0 | default: OSL_ASSERT(false); |
530 | 0 | addUnexpectedError(_rBuf); |
531 | 0 | break; |
532 | 0 | } |
533 | | |
534 | 0 | return eErrCode; |
535 | 0 | } |
536 | | |
537 | | |
538 | | OUString Bootstrap::getProductKey() |
539 | 0 | { |
540 | 0 | OUString const sDefaultProductKey = getExecutableBaseName(); |
541 | |
|
542 | 0 | return data().getBootstrapValue( BOOTSTRAP_ITEM_PRODUCT_KEY, sDefaultProductKey ); |
543 | 0 | } |
544 | | |
545 | | OUString Bootstrap::getProductKey(OUString const& _sDefault) |
546 | 0 | { |
547 | 0 | return data().getBootstrapValue( BOOTSTRAP_ITEM_PRODUCT_KEY, _sDefault ); |
548 | 0 | } |
549 | | |
550 | | OUString Bootstrap::getBuildIdData(OUString const& _sDefault) |
551 | 0 | { |
552 | | // try to open version.ini (versionrc) |
553 | 0 | OUString uri; |
554 | 0 | rtl::Bootstrap::get( u"BRAND_BASE_DIR"_ustr, uri); |
555 | 0 | rtl::Bootstrap aData( uri + "/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ); |
556 | 0 | if ( aData.getHandle() == nullptr ) |
557 | | // version.ini (versionrc) doesn't exist |
558 | 0 | return _sDefault; |
559 | | |
560 | | // read value |
561 | 0 | OUString sBuildId; |
562 | 0 | aData.getFrom(BOOTSTRAP_ITEM_BUILDID,sBuildId,_sDefault); |
563 | 0 | return sBuildId; |
564 | 0 | } |
565 | | |
566 | | Bootstrap::PathStatus Bootstrap::locateBaseInstallation(OUString& _rURL) |
567 | 0 | { |
568 | 0 | Impl::PathData const& aPathData = data().aBaseInstall_; |
569 | |
|
570 | 0 | _rURL = aPathData.path; |
571 | 0 | return aPathData.status; |
572 | 0 | } |
573 | | |
574 | | Bootstrap::PathStatus Bootstrap::locateUserInstallation(OUString& _rURL) |
575 | 0 | { |
576 | 0 | Impl::PathData const& aPathData = data().aUserInstall_; |
577 | |
|
578 | 0 | _rURL = aPathData.path; |
579 | 0 | return aPathData.status; |
580 | 0 | } |
581 | | |
582 | | Bootstrap::PathStatus Bootstrap::locateUserData(OUString& _rURL) |
583 | 58.3k | { |
584 | 58.3k | OUString const csUserDirItem(BOOTSTRAP_ITEM_USERDIR); |
585 | | |
586 | 58.3k | rtl::Bootstrap aData( data().getImplName() ); |
587 | | |
588 | 58.3k | if ( aData.getFrom(csUserDirItem, _rURL) ) |
589 | 0 | { |
590 | 0 | return checkStatusAndNormalizeURL(_rURL); |
591 | 0 | } |
592 | 58.3k | else |
593 | 58.3k | { |
594 | 58.3k | return getDerivedPath(_rURL, data().aUserInstall_ ,BOOTSTRAP_DIRNAME_USERDIR, aData, csUserDirItem); |
595 | 58.3k | } |
596 | 58.3k | } |
597 | | |
598 | | Bootstrap::PathStatus Bootstrap::locateBootstrapFile(OUString& _rURL) |
599 | 0 | { |
600 | 0 | Impl::PathData const& aPathData = data().aBootstrapINI_; |
601 | |
|
602 | 0 | _rURL = aPathData.path; |
603 | 0 | return aPathData.status; |
604 | 0 | } |
605 | | |
606 | | Bootstrap::PathStatus Bootstrap::locateVersionFile(OUString& _rURL) |
607 | 0 | { |
608 | 0 | Impl::PathData const& aPathData = data().aVersionINI_; |
609 | |
|
610 | 0 | _rURL = aPathData.path; |
611 | 0 | return aPathData.status; |
612 | 0 | } |
613 | | |
614 | | Bootstrap::Status Bootstrap::checkBootstrapStatus(OUString& _rDiagnosticMessage, FailureCode& _rErrCode) |
615 | 0 | { |
616 | 0 | Impl const& aData = data(); |
617 | |
|
618 | 0 | Status result = aData.status_; |
619 | | |
620 | | // maybe do further checks here |
621 | |
|
622 | 0 | OUStringBuffer sErrorBuffer; |
623 | 0 | if (result != DATA_OK) |
624 | 0 | _rErrCode = describeError(sErrorBuffer,aData); |
625 | | |
626 | 0 | else |
627 | 0 | _rErrCode = NO_FAILURE; |
628 | |
|
629 | 0 | _rDiagnosticMessage = sErrorBuffer.makeStringAndClear(); |
630 | |
|
631 | 0 | return result; |
632 | 0 | } |
633 | | |
634 | | |
635 | | bool Bootstrap::Impl::initBaseInstallationData(rtl::Bootstrap const & _rData) |
636 | 7 | { |
637 | 7 | _rData.getFrom(BOOTSTRAP_ITEM_BASEINSTALLATION, aBaseInstall_.path, BOOTSTRAP_DEFAULT_BASEINSTALL); |
638 | | |
639 | 7 | bool bResult = (PATH_EXISTS == updateStatus(aBaseInstall_)); |
640 | | |
641 | 7 | implGetBootstrapFile(_rData, aBootstrapINI_); |
642 | | |
643 | 7 | return bResult; |
644 | 7 | } |
645 | | |
646 | | bool Bootstrap::Impl::initUserInstallationData(rtl::Bootstrap const & _rData) |
647 | 7 | { |
648 | 7 | if (_rData.getFrom(BOOTSTRAP_ITEM_USERINSTALLATION, aUserInstall_.path)) |
649 | 0 | { |
650 | 0 | updateStatus(aUserInstall_); |
651 | 0 | } |
652 | 7 | else |
653 | 7 | { |
654 | | // should we do just this |
655 | 7 | aUserInstall_.status = DATA_MISSING; |
656 | | |
657 | | // ... or this - look for a single-user user directory ? |
658 | 7 | OUString const csUserDirItem(BOOTSTRAP_ITEM_USERDIR); |
659 | 7 | OUString sDummy; |
660 | | // look for $BASEINSTALLATION/user only if default UserDir setting is used |
661 | 7 | if (! _rData.getFrom(csUserDirItem, sDummy)) |
662 | 7 | { |
663 | 7 | if ( PATH_EXISTS == getDerivedPath(sDummy, aBaseInstall_, BOOTSTRAP_DIRNAME_USERDIR, _rData, csUserDirItem) ) |
664 | 0 | aUserInstall_ = aBaseInstall_; |
665 | 7 | } |
666 | 7 | } |
667 | | |
668 | 7 | bool bResult = (PATH_EXISTS == aUserInstall_.status); |
669 | | |
670 | 7 | implGetVersionFile(_rData, aVersionINI_); |
671 | | |
672 | 7 | return bResult; |
673 | 7 | } |
674 | | |
675 | | void Bootstrap::Impl::initialize() |
676 | 7 | { |
677 | 7 | rtl::Bootstrap aData( m_aImplName ); |
678 | | |
679 | 7 | if (!initBaseInstallationData(aData)) |
680 | 0 | { |
681 | 0 | status_ = INVALID_BASE_INSTALL; |
682 | 0 | } |
683 | 7 | else if (!initUserInstallationData(aData)) |
684 | 7 | { |
685 | 7 | status_ = INVALID_USER_INSTALL; |
686 | | |
687 | 7 | if (aUserInstall_.status >= DATA_MISSING) |
688 | 7 | { |
689 | 7 | switch (aVersionINI_.status) |
690 | 7 | { |
691 | 0 | case PATH_EXISTS: |
692 | 0 | case PATH_VALID: |
693 | 0 | status_ = MISSING_USER_INSTALL; |
694 | 0 | break; |
695 | | |
696 | 0 | case DATA_INVALID: |
697 | 7 | case DATA_MISSING: |
698 | 7 | status_ = INVALID_BASE_INSTALL; |
699 | 7 | break; |
700 | 0 | default: |
701 | 0 | break; |
702 | 7 | } |
703 | 7 | } |
704 | 7 | } |
705 | 0 | else |
706 | 0 | { |
707 | 0 | status_ = DATA_OK; |
708 | 0 | } |
709 | 7 | } |
710 | | |
711 | | OUString Bootstrap::Impl::getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const |
712 | 0 | { |
713 | 0 | rtl::Bootstrap aData( m_aImplName ); |
714 | |
|
715 | 0 | OUString sResult; |
716 | 0 | aData.getFrom(_sName,sResult,_sDefault); |
717 | 0 | return sResult; |
718 | 0 | } |
719 | | |
720 | | } // namespace utl |
721 | | |
722 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |