xref: /AOO41X/main/unotools/source/config/bootstrap.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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