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