1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_unotools.hxx" 26 27 #include <stdio.h> 28 29 #include "unotools/bootstrap.hxx" 30 31 // --------------------------------------------------------------------------------------- 32 #include <rtl/ustring.hxx> 33 #include <rtl/ustrbuf.hxx> 34 #include <osl/file.hxx> 35 #include <osl/mutex.hxx> 36 #include <osl/diagnose.h> 37 // --------------------------------------------------------------------------------------- 38 #include <rtl/bootstrap.hxx> 39 #include <osl/process.h> // for osl_getExecutableFile 40 #include "tools/getprocessworkingdir.hxx" 41 42 // --------------------------------------------------------------------------------------- 43 // #define this to a non-zero value, if remembering defaults is not supported properly 44 #define RTL_BOOTSTRAP_DEFAULTS_BROKEN 1 45 46 // --------------------------------------------------------------------------------------- 47 #define BOOTSTRAP_DATA_NAME SAL_CONFIGFILE("bootstrap") 48 49 #define BOOTSTRAP_ITEM_PRODUCT_KEY "ProductKey" 50 #define BOOTSTRAP_ITEM_PRODUCT_SOURCE "ProductSource" 51 #define BOOTSTRAP_ITEM_VERSIONFILE "Location" 52 #define BOOTSTRAP_ITEM_BUILDID "buildid" 53 54 #define BOOTSTRAP_ITEM_BASEINSTALLATION "BaseInstallation" 55 #define BOOTSTRAP_ITEM_USERINSTALLATION "UserInstallation" 56 57 #define BOOTSTRAP_ITEM_SHAREDIR "SharedDataDir" 58 #define BOOTSTRAP_ITEM_USERDIR "UserDataDir" 59 60 #define BOOTSTRAP_DEFAULT_BASEINSTALL "$SYSBINDIR/.." 61 62 #define BOOTSTRAP_DIRNAME_SHAREDIR "share" 63 #define BOOTSTRAP_DIRNAME_USERDIR "user" 64 65 #define VERSIONFILE_SECTION "Versions" 66 #define VERSIONFILE_ITEM_SCSREVISION "Revision" 67 68 #define SETUP_DATA_NAME SAL_CONFIGFILE("setup") 69 #define SETUP_ITEM_ALLUSERS "ALLUSERS" 70 // --------------------------------------------------------------------------------------- 71 typedef char const * AsciiString; 72 // --------------------------------------------------------------------------------------- 73 74 namespace utl 75 { 76 // --------------------------------------------------------------------------------------- 77 using ::rtl::OUString; 78 using ::rtl::OUStringBuffer; 79 using ::rtl::OString; 80 81 // --------------------------------------------------------------------------------------- 82 // Implementation class: Bootstrap::Impl 83 // --------------------------------------------------------------------------------------- 84 85 class Bootstrap::Impl 86 { 87 OUString const m_aImplName; 88 public: // struct to cache the result of a path lookup 89 struct PathData 90 { 91 OUString path; 92 PathStatus status; 93 94 PathData() 95 : path() 96 , status(DATA_UNKNOWN) 97 {} 98 }; 99 public: // data members 100 // base install data 101 PathData aBaseInstall_; 102 103 // user install data 104 PathData aUserInstall_; 105 106 // INI files 107 PathData aBootstrapINI_; 108 PathData aVersionINI_; 109 110 // overall status 111 Status status_; 112 113 public: // construction and initialization 114 explicit 115 Impl(OUString const& _aImplName) 116 : m_aImplName(_aImplName) 117 { 118 status_ = initialize(); 119 } 120 121 Status initialize(); 122 123 // access helper 124 OUString getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const; 125 sal_Bool getVersionValue(OUString const& _sName, OUString& _rValue, OUString const& _sDefault) const; 126 127 OUString getImplName() const { return m_aImplName; } 128 129 private: // implementation 130 bool initBaseInstallationData(rtl::Bootstrap& _rData); 131 bool initUserInstallationData(rtl::Bootstrap& _rData); 132 }; 133 // --------------------------------------------------------------------------------------- 134 static OUString getExecutableDirectory(); 135 // --------------------------------------------------------------------------------------- 136 137 static Bootstrap::Impl* s_pData = NULL; 138 139 Bootstrap::Impl const& Bootstrap::data() 140 { 141 142 if (!s_pData) 143 { 144 using namespace osl; 145 MutexGuard aGuard( Mutex::getGlobalMutex() ); 146 147 // static Impl s_theData(getExecutableDirectory() + OUString(RTL_CONSTASCII_USTRINGPARAM("/"BOOTSTRAP_DATA_NAME))); 148 // s_pData = &s_theData; 149 rtl::OUString uri; 150 rtl::Bootstrap::get( 151 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BRAND_BASE_DIR")), uri); 152 s_pData = new Impl(uri + OUString(RTL_CONSTASCII_USTRINGPARAM( "/program/" BOOTSTRAP_DATA_NAME))); 153 } 154 return *s_pData; 155 } 156 157 void Bootstrap::reloadData() 158 { 159 if (s_pData != NULL) { 160 delete s_pData; 161 s_pData = NULL; 162 } 163 } 164 165 // --------------------------------------------------------------------------------------- 166 // helper 167 // --------------------------------------------------------------------------------------- 168 169 typedef Bootstrap::PathStatus PathStatus; 170 171 sal_Unicode const cURLSeparator = '/'; 172 173 // --------------------------------------------------------------------------------------- 174 static 175 inline 176 OUString getURLSeparator() 177 { 178 static OUString theSep(&cURLSeparator,1); 179 return theSep; 180 } 181 182 // --------------------------------------------------------------------------------------- 183 // path status utility function 184 static 185 PathStatus implCheckStatusOfURL(OUString const& _sURL, osl::DirectoryItem& aDirItem) 186 { 187 using namespace osl; 188 189 PathStatus eStatus = Bootstrap::DATA_UNKNOWN; 190 191 if (_sURL.getLength() != 0) 192 { 193 switch( DirectoryItem::get(_sURL, aDirItem) ) 194 { 195 case DirectoryItem::E_None: // Success 196 eStatus = Bootstrap::PATH_EXISTS; 197 break; 198 199 case DirectoryItem::E_NOENT: // No such file or directory<br> 200 eStatus = Bootstrap::PATH_VALID; 201 break; 202 203 case DirectoryItem::E_INVAL: // the format of the parameters was not valid<br> 204 case DirectoryItem::E_NAMETOOLONG: // File name too long<br> 205 case DirectoryItem::E_NOTDIR: // A component of the path prefix of path is not a directory<p> 206 eStatus = Bootstrap::DATA_INVALID; 207 break; 208 209 // how to handle these ? 210 case DirectoryItem::E_LOOP: // Too many symbolic links encountered<br> 211 case DirectoryItem::E_ACCES: // permission denied<br> 212 // any other error - what to do ? 213 default: 214 eStatus = Bootstrap::DATA_UNKNOWN; 215 break; 216 } 217 } 218 else 219 eStatus = Bootstrap::DATA_MISSING; 220 221 return eStatus; 222 } 223 // --------------------------------------------------------------------------------------- 224 225 static 226 bool implNormalizeURL(OUString & _sURL, osl::DirectoryItem& aDirItem) 227 { 228 using namespace osl; 229 230 OSL_PRECOND(aDirItem.is(), "Opened DirItem required"); 231 232 static const sal_uInt32 cFileStatusMask = FileStatusMask_FileURL; 233 234 FileStatus aFileStatus(cFileStatusMask); 235 236 if (aDirItem.getFileStatus(aFileStatus) != DirectoryItem::E_None) 237 return false; 238 239 OUString aNormalizedURL = aFileStatus.getFileURL(); 240 241 if (aNormalizedURL.getLength() == 0) 242 return false; 243 244 // #109863# sal/osl returns final slash for file URLs contradicting 245 // the URL/URI RFCs. 246 if ( aNormalizedURL.getStr()[aNormalizedURL.getLength()-1] != cURLSeparator ) 247 _sURL = aNormalizedURL; 248 else 249 _sURL = aNormalizedURL.copy( 0, aNormalizedURL.getLength()-1 ); 250 251 return true; 252 } 253 // --------------------------------------------------------------------------------------- 254 static 255 bool implEnsureAbsolute(OUString & _rsURL) // also strips embedded dots !! 256 { 257 using osl::File; 258 259 OUString sBasePath; 260 OSL_VERIFY(tools::getProcessWorkingDir(&sBasePath)); 261 262 OUString sAbsolute; 263 if ( File::E_None == File::getAbsoluteFileURL(sBasePath, _rsURL, sAbsolute)) 264 { 265 _rsURL = sAbsolute; 266 return true; 267 } 268 else 269 { 270 OSL_ENSURE(false, "Could not get absolute file URL for URL"); 271 return false; 272 } 273 } 274 /* old code to strip embedded dots 275 static OUString const sDots(RTL_CONSTASCII_USTRINGPARAM("/..")); 276 277 sal_Int32 nDotsIndex = _rsURL.indexOf(sDots); 278 while (nDotsIndex >= 0) 279 { 280 OSL_ASSERT(_rsURL.indexOf(sDots) == nDotsIndex); 281 282 sal_Int32 nStripIndex = _rsURL.lastIndexOf(cURLSeparator,nDotsIndex); 283 if (nStripIndex < 0 || nStripIndex+1 == nDotsIndex) 284 { 285 OSL_TRACE("Invalid use of dots in bootstrap URL"); 286 return false; 287 } 288 _rsURL = _rsURL.copy(0,nStripIndex) + _rsURL.copy(nDotsIndex + sDots.getLength()); 289 290 nDotsIndex = _rsURL.indexOf(sDots,nStripIndex); 291 } 292 return true; 293 } 294 295 */ 296 // --------------------------------------------------------------------------------------- 297 298 static 299 bool implMakeAbsoluteURL(OUString & _rsPathOrURL) 300 { 301 using namespace osl; 302 303 bool bURL; 304 305 OUString sOther; 306 // check if it already was normalized 307 if ( File::E_None == File::getSystemPathFromFileURL(_rsPathOrURL, sOther) ) 308 { 309 bURL = true; 310 } 311 312 else if ( File::E_None == File::getFileURLFromSystemPath(_rsPathOrURL, sOther) ) 313 { 314 _rsPathOrURL = sOther; 315 bURL = true; 316 } 317 else 318 bURL = false; 319 320 return bURL && implEnsureAbsolute(_rsPathOrURL); 321 } 322 // --------------------------------------------------------------------------------------- 323 #if OSL_DEBUG_LEVEL > 0 324 static 325 PathStatus dbgCheckStatusOfURL(OUString const& _sURL) 326 { 327 using namespace osl; 328 329 DirectoryItem aDirItem; 330 331 return implCheckStatusOfURL(_sURL,aDirItem); 332 } 333 // --------------------------------------------------------------------------------------- 334 #endif 335 336 static 337 PathStatus checkStatusAndNormalizeURL(OUString & _sURL) 338 { 339 using namespace osl; 340 341 PathStatus eStatus = Bootstrap::DATA_UNKNOWN; 342 343 if (_sURL.getLength() == 0) 344 eStatus = Bootstrap::DATA_MISSING; 345 346 else if ( !implMakeAbsoluteURL(_sURL) ) 347 eStatus = Bootstrap::DATA_INVALID; 348 349 else 350 { 351 DirectoryItem aDirItem; 352 353 eStatus = implCheckStatusOfURL(_sURL,aDirItem); 354 355 if (eStatus == Bootstrap::PATH_EXISTS) 356 { 357 if (!implNormalizeURL(_sURL,aDirItem)) 358 OSL_ENSURE(false,"Unexpected failure getting actual URL for existing object"); 359 } 360 } 361 return eStatus; 362 } 363 364 365 // ---------------------------------------------------------------------------------- 366 // helpers to build and check a nested URL 367 static 368 PathStatus getDerivedPath( 369 OUString& _rURL, 370 OUString const& _aBaseURL, PathStatus _aBaseStatus, 371 OUString const& _sRelativeURL, 372 rtl::Bootstrap& _rData, OUString const& _sBootstrapParameter 373 ) 374 { 375 OUString sDerivedURL; 376 377 OSL_PRECOND(!_rData.getFrom(_sBootstrapParameter,sDerivedURL),"Setting for derived path is already defined"); 378 OSL_PRECOND(_sRelativeURL.getLength() != 0 && _sRelativeURL[0] != cURLSeparator,"Invalid Relative URL"); 379 380 PathStatus aStatus = _aBaseStatus; 381 382 // do we have a base path ? 383 if (_aBaseURL.getLength()) 384 { 385 OSL_PRECOND(_aBaseURL[_aBaseURL.getLength()-1] != cURLSeparator,"Unexpected: base URL ends in slash"); 386 387 sDerivedURL = _aBaseURL + getURLSeparator() + _sRelativeURL; 388 389 // a derived (nested) URL can only exist or have a lesser status, if the parent exists 390 if (aStatus == Bootstrap::PATH_EXISTS) 391 aStatus = checkStatusAndNormalizeURL(sDerivedURL); 392 393 else // the relative appendix must be valid 394 OSL_ASSERT(aStatus != Bootstrap::PATH_VALID || dbgCheckStatusOfURL(sDerivedURL) == Bootstrap::PATH_VALID); 395 396 _rData.getFrom(_sBootstrapParameter, _rURL, sDerivedURL); 397 398 OSL_ENSURE(sDerivedURL == _rURL,"Could not set derived URL via Bootstrap default parameter"); 399 OSL_POSTCOND(RTL_BOOTSTRAP_DEFAULTS_BROKEN || 400 _rData.getFrom(_sBootstrapParameter,sDerivedURL) && sDerivedURL==_rURL,"Use of default did not affect bootstrap value"); 401 } 402 else 403 { 404 // clear the result 405 _rURL = _aBaseURL; 406 407 // if we have no data it can't be a valid path 408 OSL_ASSERT( aStatus > Bootstrap::PATH_VALID ); 409 } 410 411 412 return aStatus; 413 } 414 415 // ---------------------------------------------------------------------------------- 416 static 417 inline 418 PathStatus getDerivedPath( 419 OUString& _rURL, 420 Bootstrap::Impl::PathData const& _aBaseData, 421 OUString const& _sRelativeURL, 422 rtl::Bootstrap& _rData, OUString const& _sBootstrapParameter 423 ) 424 { 425 return getDerivedPath(_rURL,_aBaseData.path,_aBaseData.status,_sRelativeURL,_rData,_sBootstrapParameter); 426 } 427 428 // --------------------------------------------------------------------------------------- 429 430 static 431 OUString getExecutableBaseName() 432 { 433 OUString sExecutable; 434 435 if (osl_Process_E_None == osl_getExecutableFile(&sExecutable.pData)) 436 { 437 // split the executable name 438 sal_Int32 nSepIndex = sExecutable.lastIndexOf(cURLSeparator); 439 440 sExecutable = sExecutable.copy(nSepIndex + 1); 441 442 // ... and get the basename (strip the extension) 443 sal_Unicode const cExtensionSep = '.'; 444 445 sal_Int32 const nExtIndex = sExecutable.lastIndexOf(cExtensionSep); 446 sal_Int32 const nExtLength = sExecutable.getLength() - nExtIndex - 1; 447 if (0 < nExtIndex && nExtLength < 4) 448 sExecutable = sExecutable.copy(0,nExtIndex); 449 } 450 else 451 OSL_TRACE("Cannot get executable name: osl_getExecutableFile failed\n"); 452 453 return sExecutable; 454 } 455 456 // --------------------------------------------------------------------------------------- 457 static 458 OUString getExecutableDirectory() 459 { 460 OUString sFileName; 461 OSL_VERIFY(osl_Process_E_None == osl_getExecutableFile(&sFileName.pData)); 462 463 sal_Int32 nDirEnd = sFileName.lastIndexOf(cURLSeparator); 464 465 OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory"); 466 467 return sFileName.copy(0,nDirEnd); 468 } 469 470 // ---------------------------------------------------------------------------------- 471 472 static 473 inline 474 Bootstrap::PathStatus updateStatus(Bootstrap::Impl::PathData & _rResult) 475 { 476 return _rResult.status = checkStatusAndNormalizeURL(_rResult.path); 477 } 478 // --------------------------------------------------------------------------------------- 479 480 static 481 Bootstrap::PathStatus implGetBootstrapFile(rtl::Bootstrap& _rData, Bootstrap::Impl::PathData & _rBootstrapFile) 482 { 483 _rData.getIniName(_rBootstrapFile.path); 484 485 return updateStatus(_rBootstrapFile); 486 } 487 // --------------------------------------------------------------------------------------- 488 489 static 490 Bootstrap::PathStatus implGetVersionFile(rtl::Bootstrap& _rData, Bootstrap::Impl::PathData & _rVersionFile) 491 { 492 OUString const csVersionFileItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_VERSIONFILE)); 493 494 _rData.getFrom(csVersionFileItem,_rVersionFile.path); 495 496 return updateStatus(_rVersionFile); 497 } 498 // --------------------------------------------------------------------------------------- 499 // Error reporting 500 501 static char const IS_MISSING[] = "is missing"; 502 static char const IS_INVALID[] = "is corrupt"; 503 static char const PERIOD[] = ". "; 504 505 // --------------------------------------------------------------------------------------- 506 static void addFileError(OUStringBuffer& _rBuf, OUString const& _aPath, AsciiString _sWhat) 507 { 508 OUString sSimpleFileName = _aPath.copy(1 +_aPath.lastIndexOf(cURLSeparator)); 509 510 _rBuf.appendAscii("The configuration file"); 511 _rBuf.appendAscii(" '").append(sSimpleFileName).appendAscii("' "); 512 _rBuf.appendAscii(_sWhat).appendAscii(PERIOD); 513 } 514 // --------------------------------------------------------------------------------------- 515 516 static void addMissingDirectoryError(OUStringBuffer& _rBuf, OUString const& _aPath) 517 { 518 _rBuf.appendAscii("The configuration directory"); 519 _rBuf.appendAscii(" '").append(_aPath).appendAscii("' "); 520 _rBuf.appendAscii(IS_MISSING).appendAscii(PERIOD); 521 } 522 // --------------------------------------------------------------------------------------- 523 524 static void addUnexpectedError(OUStringBuffer& _rBuf, AsciiString _sExtraInfo = NULL) 525 { 526 if (NULL == _sExtraInfo) 527 _sExtraInfo = "An internal failure occurred"; 528 529 _rBuf.appendAscii(_sExtraInfo).appendAscii(PERIOD); 530 } 531 // --------------------------------------------------------------------------------------- 532 533 static Bootstrap::FailureCode describeError(OUStringBuffer& _rBuf, Bootstrap::Impl const& _rData) 534 { 535 Bootstrap::FailureCode eErrCode = Bootstrap::INVALID_BOOTSTRAP_DATA; 536 537 _rBuf.appendAscii("The program cannot be started. "); 538 539 switch (_rData.aUserInstall_.status) 540 { 541 case Bootstrap::PATH_EXISTS: 542 switch (_rData.aBaseInstall_.status) 543 { 544 case Bootstrap::PATH_VALID: 545 addMissingDirectoryError(_rBuf, _rData.aBaseInstall_.path); 546 eErrCode = Bootstrap::MISSING_INSTALL_DIRECTORY; 547 break; 548 549 case Bootstrap::DATA_INVALID: 550 addUnexpectedError(_rBuf,"The installation path is invalid"); 551 break; 552 553 case Bootstrap::DATA_MISSING: 554 addUnexpectedError(_rBuf,"The installation path is not available"); 555 break; 556 557 case Bootstrap::PATH_EXISTS: // seems to be all fine (?) 558 addUnexpectedError(_rBuf,""); 559 break; 560 561 default: OSL_ASSERT(false); 562 addUnexpectedError(_rBuf); 563 break; 564 } 565 break; 566 567 case Bootstrap::PATH_VALID: 568 addMissingDirectoryError(_rBuf, _rData.aUserInstall_.path); 569 eErrCode = Bootstrap::MISSING_USER_DIRECTORY; 570 break; 571 572 // else fall through 573 case Bootstrap::DATA_INVALID: 574 if (_rData.aVersionINI_.status == Bootstrap::PATH_EXISTS) 575 { 576 addFileError(_rBuf, _rData.aVersionINI_.path, IS_INVALID); 577 eErrCode = Bootstrap::INVALID_VERSION_FILE_ENTRY; 578 break; 579 } 580 // else fall through 581 582 case Bootstrap::DATA_MISSING: 583 switch (_rData.aVersionINI_.status) 584 { 585 case Bootstrap::PATH_EXISTS: 586 addFileError(_rBuf, _rData.aVersionINI_.path, "does not support the current version"); 587 eErrCode = Bootstrap::MISSING_VERSION_FILE_ENTRY; 588 break; 589 590 case Bootstrap::PATH_VALID: 591 addFileError(_rBuf, _rData.aVersionINI_.path, IS_MISSING); 592 eErrCode = Bootstrap::MISSING_VERSION_FILE; 593 break; 594 595 default: 596 switch (_rData.aBootstrapINI_.status) 597 { 598 case Bootstrap::PATH_EXISTS: 599 addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_INVALID); 600 601 if (_rData.aVersionINI_.status == Bootstrap::DATA_MISSING) 602 eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY; 603 else 604 eErrCode = Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY; 605 break; 606 607 case Bootstrap::DATA_INVALID: OSL_ASSERT(false); 608 case Bootstrap::PATH_VALID: 609 addFileError(_rBuf, _rData.aBootstrapINI_.path, IS_MISSING); 610 eErrCode = Bootstrap::MISSING_BOOTSTRAP_FILE; 611 break; 612 613 default: 614 addUnexpectedError(_rBuf); 615 break; 616 } 617 break; 618 } 619 break; 620 621 default: OSL_ASSERT(false); 622 addUnexpectedError(_rBuf); 623 break; 624 } 625 626 return eErrCode; 627 } 628 // --------------------------------------------------------------------------------------- 629 // --------------------------------------------------------------------------------------- 630 // class Bootstrap 631 // --------------------------------------------------------------------------------------- 632 633 OUString Bootstrap::getProductKey() 634 { 635 OUString const csProductKeyItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_KEY)); 636 637 OUString const sDefaultProductKey = getExecutableBaseName(); 638 639 return data().getBootstrapValue( csProductKeyItem, sDefaultProductKey ); 640 } 641 // --------------------------------------------------------------------------------------- 642 643 OUString Bootstrap::getProductKey(OUString const& _sDefault) 644 { 645 OUString const csProductKeyItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_KEY)); 646 647 return data().getBootstrapValue( csProductKeyItem, _sDefault ); 648 } 649 // --------------------------------------------------------------------------------------- 650 651 OUString Bootstrap::getProductSource(OUString const& _sDefault) 652 { 653 OUString const csProductSourceItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_PRODUCT_SOURCE)); 654 655 OUString sProductSource; 656 // read ProductSource from version.ini (versionrc) 657 data().getVersionValue( csProductSourceItem, sProductSource, _sDefault ); 658 return sProductSource; 659 } 660 // --------------------------------------------------------------------------------------- 661 662 OUString Bootstrap::getBuildIdData(OUString const& _sDefault) 663 { 664 OUString const csBuildIdItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_BUILDID)); 665 666 OUString sBuildId; 667 // read buildid from version.ini (versionrc), if it doesn't exist or buildid is empty 668 if ( data().getVersionValue( csBuildIdItem, sBuildId, _sDefault ) != sal_True || 669 sBuildId.getLength() == 0 ) 670 // read buildid from bootstrap.ini (bootstraprc) 671 sBuildId = data().getBootstrapValue( csBuildIdItem, _sDefault ); 672 return sBuildId; 673 } 674 // --------------------------------------------------------------------------------------- 675 676 OUString Bootstrap::getRevisionInfo() 677 { 678 OUString const _sDefault; 679 OUString const csRevisionItem(RTL_CONSTASCII_USTRINGPARAM(VERSIONFILE_ITEM_SCSREVISION)); 680 681 OUString sRevisionNumber; 682 // read buildid from version.ini (versionrc), if it doesn't exist or buildid is empty 683 if ( data().getVersionValue( csRevisionItem, sRevisionNumber, _sDefault ) != sal_True || 684 sRevisionNumber.getLength() == 0 ) 685 // read buildid from bootstrap.ini (bootstraprc) 686 sRevisionNumber = data().getBootstrapValue( csRevisionItem, _sDefault ); 687 return sRevisionNumber; 688 } 689 690 // --------------------------------------------------------------------------------------- 691 692 OUString Bootstrap::getAllUsersValue(OUString const& _sDefault) 693 { 694 OUString const csAllUsersItem(RTL_CONSTASCII_USTRINGPARAM(SETUP_ITEM_ALLUSERS)); 695 696 rtl::Bootstrap aData( getExecutableDirectory() + OUString( RTL_CONSTASCII_USTRINGPARAM( "/" SETUP_DATA_NAME ) ) ); 697 OUString sResult; 698 aData.getFrom( csAllUsersItem, sResult, _sDefault ); 699 return sResult; 700 } 701 // --------------------------------------------------------------------------------------- 702 703 Bootstrap::PathStatus Bootstrap::locateBaseInstallation(OUString& _rURL) 704 { 705 Impl::PathData const& aPathData = data().aBaseInstall_; 706 707 _rURL = aPathData.path; 708 return aPathData.status; 709 } 710 // --------------------------------------------------------------------------------------- 711 712 PathStatus Bootstrap::locateUserInstallation(OUString& _rURL) 713 { 714 Impl::PathData const& aPathData = data().aUserInstall_; 715 716 _rURL = aPathData.path; 717 return aPathData.status; 718 } 719 // --------------------------------------------------------------------------------------- 720 721 PathStatus Bootstrap::locateSharedData(OUString& _rURL) 722 { 723 OUString const csShareDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_SHAREDIR)); 724 725 rtl::Bootstrap aData( data().getImplName() ); 726 727 if ( aData.getFrom(csShareDirItem, _rURL) ) 728 { 729 return checkStatusAndNormalizeURL(_rURL); 730 } 731 else 732 { 733 OUString const csShareDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_SHAREDIR)); 734 return getDerivedPath(_rURL, data().aBaseInstall_, csShareDir, aData, csShareDirItem); 735 } 736 } 737 // --------------------------------------------------------------------------------------- 738 739 PathStatus Bootstrap::locateUserData(OUString& _rURL) 740 { 741 OUString const csUserDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERDIR)); 742 743 rtl::Bootstrap aData( data().getImplName() ); 744 745 if ( aData.getFrom(csUserDirItem, _rURL) ) 746 { 747 return checkStatusAndNormalizeURL(_rURL); 748 } 749 else 750 { 751 OUString const csUserDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_USERDIR)); 752 return getDerivedPath(_rURL, data().aUserInstall_ ,csUserDir, aData, csUserDirItem); 753 } 754 } 755 // --------------------------------------------------------------------------------------- 756 757 PathStatus Bootstrap::locateBootstrapFile(OUString& _rURL) 758 { 759 Impl::PathData const& aPathData = data().aBootstrapINI_; 760 761 _rURL = aPathData.path; 762 return aPathData.status; 763 } 764 // --------------------------------------------------------------------------------------- 765 766 PathStatus Bootstrap::locateVersionFile(OUString& _rURL) 767 { 768 Impl::PathData const& aPathData = data().aVersionINI_; 769 770 _rURL = aPathData.path; 771 return aPathData.status; 772 } 773 // --------------------------------------------------------------------------------------- 774 775 Bootstrap::Status Bootstrap::checkBootstrapStatus(OUString& _rDiagnosticMessage) 776 { 777 FailureCode eDummyCode(NO_FAILURE); 778 779 return checkBootstrapStatus(_rDiagnosticMessage,eDummyCode); 780 } 781 // --------------------------------------------------------------------------------------- 782 783 Bootstrap::Status Bootstrap::checkBootstrapStatus(rtl::OUString& _rDiagnosticMessage, FailureCode& _rErrCode) 784 { 785 Impl const& aData = data(); 786 787 Status result = aData.status_; 788 789 // maybe do further checks here 790 791 OUStringBuffer sErrorBuffer; 792 if (result != DATA_OK) 793 _rErrCode = describeError(sErrorBuffer,aData); 794 795 else 796 _rErrCode = NO_FAILURE; 797 798 _rDiagnosticMessage = sErrorBuffer.makeStringAndClear(); 799 800 return result; 801 } 802 803 // --------------------------------------------------------------------------------------- 804 // class Bootstrap::Impl 805 // --------------------------------------------------------------------------------------- 806 807 bool Bootstrap::Impl::initBaseInstallationData(rtl::Bootstrap& _rData) 808 { 809 OUString const csBaseInstallItem( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_BASEINSTALLATION) ); 810 OUString const csBaseInstallDefault( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DEFAULT_BASEINSTALL) ); 811 812 _rData.getFrom(csBaseInstallItem, aBaseInstall_.path, csBaseInstallDefault); 813 814 bool bResult = (PATH_EXISTS == updateStatus(aBaseInstall_)); 815 816 implGetBootstrapFile(_rData, aBootstrapINI_); 817 818 return bResult; 819 } 820 // --------------------------------------------------------------------------------------- 821 822 bool Bootstrap::Impl::initUserInstallationData(rtl::Bootstrap& _rData) 823 { 824 OUString const csUserInstallItem( RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERINSTALLATION) ); 825 826 if (_rData.getFrom(csUserInstallItem, aUserInstall_.path)) 827 { 828 updateStatus(aUserInstall_); 829 } 830 else 831 { 832 // should we do just this 833 aUserInstall_.status = DATA_MISSING; 834 835 // .. or this - look for a single-user user directory ? 836 OUString const csUserDirItem(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_ITEM_USERDIR)); 837 OUString sDummy; 838 // look for $BASEINSTALLATION/user only if default UserDir setting is used 839 if (! _rData.getFrom(csUserDirItem, sDummy)) 840 { 841 OUString const csUserDir(RTL_CONSTASCII_USTRINGPARAM(BOOTSTRAP_DIRNAME_USERDIR)); 842 843 if ( PATH_EXISTS == getDerivedPath(sDummy, aBaseInstall_, csUserDir, _rData, csUserDirItem) ) 844 aUserInstall_ = aBaseInstall_; 845 } 846 } 847 848 bool bResult = (PATH_EXISTS == aUserInstall_.status); 849 850 implGetVersionFile(_rData, aVersionINI_); 851 852 return bResult; 853 } 854 // --------------------------------------------------------------------------------------- 855 856 Bootstrap::Status Bootstrap::Impl::initialize() 857 { 858 Bootstrap::Status result; 859 860 rtl::Bootstrap aData( m_aImplName ); 861 862 if (!initBaseInstallationData(aData)) 863 { 864 result = INVALID_BASE_INSTALL; 865 } 866 else if (!initUserInstallationData(aData)) 867 { 868 result = INVALID_USER_INSTALL; 869 870 if (aUserInstall_.status >= DATA_MISSING) 871 { 872 switch (aVersionINI_.status) 873 { 874 case PATH_EXISTS: 875 case PATH_VALID: 876 result = MISSING_USER_INSTALL; 877 break; 878 879 case DATA_INVALID: 880 case DATA_MISSING: 881 result = INVALID_BASE_INSTALL; 882 break; 883 default: 884 break; 885 } 886 } 887 } 888 else 889 { 890 result = DATA_OK; 891 } 892 return result; 893 } 894 // --------------------------------------------------------------------------------------- 895 896 OUString Bootstrap::Impl::getBootstrapValue(OUString const& _sName, OUString const& _sDefault) const 897 { 898 rtl::Bootstrap aData( m_aImplName ); 899 900 OUString sResult; 901 aData.getFrom(_sName,sResult,_sDefault); 902 return sResult; 903 } 904 // --------------------------------------------------------------------------------------- 905 906 sal_Bool Bootstrap::Impl::getVersionValue(OUString const& _sName, OUString& _rValue, OUString const& _sDefault) const 907 { 908 // try to open version.ini (versionrc) 909 rtl::OUString uri; 910 rtl::Bootstrap::get( 911 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BRAND_BASE_DIR")), uri); 912 rtl::Bootstrap aData( uri + 913 OUString(RTL_CONSTASCII_USTRINGPARAM( "/program/" SAL_CONFIGFILE("version"))) ); 914 if ( aData.getHandle() == NULL ) 915 // version.ini (versionrc) doesn't exist 916 return sal_False; 917 918 // read value 919 aData.getFrom(_sName,_rValue,_sDefault); 920 return sal_True; 921 } 922 // --------------------------------------------------------------------------------------- 923 924 } // namespace utl 925 926