summaryrefslogtreecommitdiff
path: root/desktop/source/app
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/app')
-rw-r--r--desktop/source/app/app.cxx153
-rw-r--r--desktop/source/app/check_ext_deps.cxx19
2 files changed, 157 insertions, 15 deletions
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index c3152ee79805..84f60b8eef55 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -152,6 +152,145 @@ static sal_Bool _bCrashReporterEnabled = sal_True;
static ::rtl::OUString getBrandSharePreregBundledPathURL();
#endif
+namespace {
+
+void removeTree(OUString const & url) {
+ osl::Directory dir(url);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ return; //TODO: SAL_WARN if recursive
+ default:
+ throw css::uno::RuntimeException(
+ "cannot open directory " + url,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ for (;;) {
+ osl::DirectoryItem i;
+ osl::FileBase::RC rc = dir.getNextItem(i, SAL_MAX_UINT32);
+ if (rc == osl::FileBase::E_NOENT) {
+ break;
+ }
+ if (rc != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ "cannot iterate directory " + url,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ osl::FileStatus stat(
+ osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
+ osl_FileStatus_Mask_FileURL);
+ if (i.getFileStatus(stat) != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ "cannot stat in directory " + url,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (stat.getFileType() == osl::FileStatus::Directory) { //TODO: symlinks
+ removeTree(stat.getFileURL());
+ } else {
+ if (osl::File::remove(stat.getFileURL()) != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ "cannot remove " + stat.getFileURL(),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ }
+}
+
+// Remove any existing UserInstallation's user/extensions/bundled cache
+// remaining from old installations. Apparently due to the old
+// share/prereg/bundled mechanism (disabled since
+// 5c47e5f63a79a9e72ec4a100786b1bbf65137ed4 "fdo#51252 Disable copying
+// share/prereg/bundled to avoid startup crashes"), that cache could contain
+// corrupted information (like a UNO component registered twice, which got
+// changed from active to passive registration in one LO version, but the
+// version of the corresponding bundled extension only incremented in a later LO
+// version). At least in theory, this function could be removed again once no
+// UserInstallation can be poisoned by that old share/prereg/bundled mechanism
+// any more. (But then Desktop::SynchronizeExtensionRepositories might need to
+// be revisited, see 2d2b19dea1ab401b1b4971ff5b12b87bb11fd666 "Force
+// ExtensionManager resync when the implementation changes" which effectively
+// got reverted again now. Now, a mismatch between a UserInstallation's
+// user/extensions/bundled and an installation's share/extensions will always be
+// detected here and lead to a removal of user/extensions/bundled, so that
+// Desktop::SynchronizeExtensionRepositories will then definitely resync
+// share/extensions.)
+void refreshBundledExtensionsDir() {
+ OUString buildId(
+ "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}");
+ rtl::Bootstrap::expandMacros(buildId); //TODO: detect failure
+ OUString dir("$BUNDLED_EXTENSIONS_USER");
+ rtl::Bootstrap::expandMacros(dir); //TODO: detect failure
+ OUString url(dir + "/buildid");
+ osl::File f(url);
+ switch (f.open(osl_File_OpenFlag_Read)) {
+ case osl::FileBase::E_None:
+ {
+ rtl::ByteSequence s1;
+ osl::FileBase::RC rc = f.readLine(s1);
+ if (f.close() != osl::FileBase::E_None) {
+ SAL_WARN("desktop", "cannot close " + url + " after reading");
+ }
+ if (rc != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ "cannot read from " + url,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OUString s2(
+ reinterpret_cast< char const * >(s1.getConstArray()),
+ s1.getLength(), RTL_TEXTENCODING_ISO_8859_1);
+ // using ISO 8859-1 avoids any and all conversion errors; the
+ // content should only be a subset of ASCII, anyway
+ if (s2 == buildId) {
+ return;
+ }
+ break;
+ }
+ case osl::FileBase::E_NOENT:
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ "cannot open " + url + " for reading",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ removeTree(dir);
+ switch (osl::Directory::createPath(dir)) {
+ case osl::FileBase::E_None:
+ case osl::FileBase::E_EXIST:
+ break;
+ default:
+ throw css::uno::RuntimeException(
+ "cannot create path " + dir,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create) !=
+ osl::FileBase::E_None)
+ {
+ throw css::uno::RuntimeException(
+ "cannot open " + url + " for writing",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ OString buf(OUStringToOString(buildId, RTL_TEXTENCODING_UTF8));
+ // using UTF-8 avoids almost all conversion errors (and buildid
+ // containing single surrogate halves should never happen, anyway); the
+ // content should only be a subset of ASCII, anyway
+ sal_uInt64 n;
+ if (f.write(buf.getStr(), buf.getLength(), n) != osl::FileBase::E_None
+ || n != static_cast< sal_uInt32 >(buf.getLength()))
+ {
+ throw css::uno::RuntimeException(
+ "cannot write to " + url,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (f.close() != osl::FileBase::E_None) {
+ throw css::uno::RuntimeException(
+ "cannot close " + url + " after writing",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+}
+
// ----------------------------------------------------------------------------
ResMgr* Desktop::GetDesktopResManager()
@@ -633,6 +772,8 @@ void Desktop::Init()
RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" );
SetBootstrapStatus(BS_OK);
+ refreshBundledExtensionsDir();
+
// Check for lastsynchronized file for bundled extensions in the user directory
// and test if synchronzation is necessary!
#ifndef ANDROID
@@ -1607,14 +1748,10 @@ int Desktop::Main()
// Check if bundled or shared extensions were added /removed
// and process those extensions (has to be done before checking
// the extension dependencies!
- bool newInst = newInstallation();
- SynchronizeExtensionRepositories(newInst);
- if ( newInst )
- {
- bool bAbort = CheckExtensionDependencies();
- if ( bAbort )
- return EXIT_FAILURE;
- }
+ SynchronizeExtensionRepositories();
+ bool bAbort = CheckExtensionDependencies();
+ if ( bAbort )
+ return EXIT_FAILURE;
{
::comphelper::ComponentContext aContext( xSMgr );
diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx
index 04b5cd75b1d6..dd01d9bbf4e5 100644
--- a/desktop/source/app/check_ext_deps.cxx
+++ b/desktop/source/app/check_ext_deps.cxx
@@ -347,9 +347,9 @@ static void impl_setNeedsCompatCheck()
// to check if we need checking the dependencies of the extensions again, we compare
// the build id of the office with the one of the last check
//------------------------------------------------------------------------------
-bool Desktop::newInstallation()
+static bool impl_needsCompatCheck()
{
- bool bNewInst = false;
+ bool bNeedsCheck = false;
rtl::OUString aLastCheckBuildID;
rtl::OUString aCurrentBuildID( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) );
rtl::Bootstrap::expandMacros( aCurrentBuildID );
@@ -371,18 +371,18 @@ bool Desktop::newInstallation()
result >>= aLastCheckBuildID;
if ( aLastCheckBuildID != aCurrentBuildID )
{
- bNewInst = true;
+ bNeedsCheck = true;
result <<= aCurrentBuildID;
pset->setPropertyValue( OUString("LastCompatibilityCheckID"), result );
Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges();
}
#ifdef DEBUG
- bNewInst = true;
+ bNeedsCheck = true;
#endif
}
catch (const com::sun::star::uno::Exception&) {}
- return bNewInst;
+ return bNeedsCheck;
}
//------------------------------------------------------------------------------
@@ -390,6 +390,11 @@ bool Desktop::newInstallation()
// When there are unresolved issues, we can't continue with startup
sal_Bool Desktop::CheckExtensionDependencies()
{
+ if (!impl_needsCompatCheck())
+ {
+ return false;
+ }
+
uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext();
bool bDependenciesValid = impl_checkDependencies( xContext );
@@ -408,10 +413,10 @@ sal_Bool Desktop::CheckExtensionDependencies()
return false;
}
-void Desktop::SynchronizeExtensionRepositories(bool force)
+void Desktop::SynchronizeExtensionRepositories()
{
RTL_LOGFILE_CONTEXT(aLog,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories");
- dp_misc::syncRepositories( force, new SilentCommandEnv( this ) );
+ dp_misc::syncRepositories( new SilentCommandEnv( this ) );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */