diff options
-rw-r--r-- | comphelper/source/misc/backupfilehelper.cxx | 640 | ||||
-rw-r--r-- | desktop/source/app/app.cxx | 99 | ||||
-rw-r--r-- | include/comphelper/backupfilehelper.hxx | 85 | ||||
-rw-r--r-- | instsetoo_native/CustomTarget_setup.mk | 16 |
4 files changed, 625 insertions, 215 deletions
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx index f45221351710..d5468f4cdce5 100644 --- a/comphelper/source/misc/backupfilehelper.cxx +++ b/comphelper/source/misc/backupfilehelper.cxx @@ -27,11 +27,12 @@ #include <zlib.h> using namespace css; -typedef std::shared_ptr< osl::File > FileSharedPtr; static const sal_uInt32 BACKUP_FILE_HELPER_BLOCK_SIZE = 16384; namespace { + typedef std::shared_ptr< osl::File > FileSharedPtr; + OUString splitAtLastToken(const OUString& rSrc, sal_Unicode aToken, OUString& rRight) { const sal_Int32 nIndex(rSrc.lastIndexOf(aToken)); @@ -170,6 +171,41 @@ namespace return false; } + OUString createFileURL(const OUString& rURL, const OUString& rName, const OUString& rExt) + { + OUString aRetval; + + if (!rURL.isEmpty() && !rName.isEmpty()) + { + aRetval = rURL; + aRetval += "/"; + aRetval += rName; + + if (!rExt.isEmpty()) + { + aRetval += "."; + aRetval += rExt; + } + } + + return aRetval; + } + + OUString createPackURL(const OUString& rURL, const OUString& rName) + { + OUString aRetval; + + if (!rURL.isEmpty() && !rName.isEmpty()) + { + aRetval = rURL; + aRetval += "/"; + aRetval += rName; + aRetval += ".pack"; + } + + return aRetval; + } + bool fileExists(const OUString& rBaseURL) { if (!rBaseURL.isEmpty()) @@ -181,6 +217,51 @@ namespace return false; } + + void scanDirsAndFiles( + const OUString& rDirURL, + std::set< OUString >& rDirs, + std::set< std::pair< OUString, OUString > >& rFiles) + { + if (!rDirURL.isEmpty()) + { + osl::Directory aDirectory(rDirURL); + + if (osl::FileBase::E_None == aDirectory.open()) + { + osl::DirectoryItem aDirectoryItem; + + while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem)) + { + osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName); + + if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus)) + { + if (aFileStatus.isDirectory()) + { + const OUString aFileName(aFileStatus.getFileName()); + + if (!aFileName.isEmpty()) + { + rDirs.insert(aFileName); + } + } + else if (aFileStatus.isRegular()) + { + OUString aFileName(aFileStatus.getFileName()); + OUString aExtension; + aFileName = splitAtLastToken(aFileName, '.', aExtension); + + if (!aFileName.isEmpty()) + { + rFiles.insert(std::pair< OUString, OUString >(aFileName, aExtension)); + } + } + } + } + } + } + } } namespace @@ -1176,61 +1257,134 @@ namespace comphelper sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10; bool BackupFileHelper::mbExitWasCalled = false; - BackupFileHelper::BackupFileHelper( - const OUString& rBaseURL, - sal_uInt16 nNumBackups) - : mrBaseURL(rBaseURL), - mnNumBackups(::std::min(::std::max(nNumBackups, sal_uInt16(1)), mnMaxAllowedBackups)), - maBase(), - maName(), - maExt() + BackupFileHelper::BackupFileHelper() + : maInitialBaseURL(), + maUserConfigBaseURL(), + maRegModName(), + maExt(), + maDirs(), + maFiles(), + mnNumBackups(2), + mnMode(0), + mbActive(false), + mbExtensions(true), + mbCompress(true) { - } + OUString sTokenOut; - void BackupFileHelper::setExitWasCalled() - { - mbExitWasCalled = true; - } + // read configuration item 'SecureUserConfig' -> bool on/off + if (rtl::Bootstrap::get("SecureUserConfig", sTokenOut)) + { + mbActive = sTokenOut.toBoolean(); + } - bool BackupFileHelper::getExitWasCalled() - { - return mbExitWasCalled; - } + if (mbActive && rtl::Bootstrap::get("SecureUserConfigNumCopies", sTokenOut)) + { + const sal_uInt16 nConfigNumCopies(static_cast<sal_uInt16>(sTokenOut.toUInt32())); - bool BackupFileHelper::getSecureUserConfig(sal_uInt16& rnSecureUserConfigNumCopies) - { - // init to not active - bool bRetval(false); - rnSecureUserConfigNumCopies = 0; - OUString sTokenOut; + // limit to range [1..mnMaxAllowedBackups] + mnNumBackups = ::std::min(::std::max(nConfigNumCopies, mnNumBackups), mnMaxAllowedBackups); + } - if (rtl::Bootstrap::get("SecureUserConfig", sTokenOut)) + if (mbActive && rtl::Bootstrap::get("SecureUserConfigMode", sTokenOut)) { - bRetval = sTokenOut.toBoolean(); + const sal_uInt16 nMode(static_cast<sal_uInt16>(sTokenOut.toUInt32())); + + // limit to range [0..2] + mnMode = ::std::min(nMode, sal_uInt16(2)); } - if (bRetval && rtl::Bootstrap::get("SecureUserConfigNumCopies", sTokenOut)) + if (mbActive && rtl::Bootstrap::get("SecureUserConfigExtensions", sTokenOut)) { - rnSecureUserConfigNumCopies = static_cast< sal_uInt16 >(sTokenOut.toUInt32()); + mbExtensions = sTokenOut.toBoolean(); } - return bRetval; + if (mbActive && rtl::Bootstrap::get("SecureUserConfigCompress", sTokenOut)) + { + mbCompress = sTokenOut.toBoolean(); + } + + if (mbActive) + { + // try to access user layer configuration file URL, the one that + // points to registrymodifications.xcu + OUString conf("${CONFIGURATION_LAYERS}"); + rtl::Bootstrap::expandMacros(conf); + const OUString aTokenUser("user:"); + sal_Int32 nStart(conf.indexOf(aTokenUser)); + + if (-1 != nStart) + { + nStart += aTokenUser.getLength(); + sal_Int32 nEnd(conf.indexOf(' ', nStart)); + + if (-1 == nEnd) + { + nEnd = conf.getLength(); + } + + maInitialBaseURL = conf.copy(nStart, nEnd - nStart); + maInitialBaseURL.startsWith("!", &maInitialBaseURL); + } + + if (maInitialBaseURL.isEmpty()) + { + // if not found, we are out of business + mbActive = false; + } + } + + if (mbActive) + { + // split to path_to_user_config (maUserConfigBaseURL), + // name_of_regMod (maRegModName) + // and extension (maExt) + if (maUserConfigBaseURL.isEmpty() && !maInitialBaseURL.isEmpty()) + { + // split URL at extension and at last path separator + maUserConfigBaseURL = splitAtLastToken(splitAtLastToken(maInitialBaseURL, '.', maExt), '/', maRegModName); + } + + mbActive = !maUserConfigBaseURL.isEmpty() && !maRegModName.isEmpty(); + } } - bool BackupFileHelper::tryPush(bool bCompress) + void BackupFileHelper::setExitWasCalled() + { + mbExitWasCalled = true; + } + + bool BackupFileHelper::getExitWasCalled() + { + return mbExitWasCalled; + } + + bool BackupFileHelper::tryPush() { bool bDidPush(false); - if (splitBaseURL()) + if (mbActive) { - // ensure directory existence - osl::Directory::createPath(getPackDirName()); + const OUString aPackURL(getPackURL()); - // try push for base file (usually registrymodifications) - bDidPush = tryPush_basefile(bCompress); + // ensure dir and file vectors + fillDirFileInfo(); + + // proccess all files in question recursively + if (!maDirs.empty() || !maFiles.empty()) + { + bDidPush = tryPush_Files( + maDirs, + maFiles, + maUserConfigBaseURL, + aPackURL); + } // Try Push of ExtensionInfo - bDidPush |= tryPush_extensionInfo(bCompress); + if (mbExtensions) + { + bDidPush |= tryPush_extensionInfo(aPackURL); + } } return bDidPush; @@ -1240,13 +1394,28 @@ namespace comphelper { bool bPopPossible(false); - if (splitBaseURL()) + if (mbActive) { - // try for base file (usually registrymodifications) - bPopPossible = isPopPossible_basefile(); + const OUString aPackURL(getPackURL()); + + // ensure dir and file vectors + fillDirFileInfo(); + + // proccess all files in question recursively + if (!maDirs.empty() || !maFiles.empty()) + { + bPopPossible = isPopPossible_files( + maDirs, + maFiles, + maUserConfigBaseURL, + aPackURL); + } // try for ExtensionInfo - bPopPossible |= isPopPossible_extensionInfo(); + if (mbExtensions) + { + bPopPossible |= isPopPossible_extensionInfo(aPackURL); + } } return bPopPossible; @@ -1256,53 +1425,116 @@ namespace comphelper { bool bDidPop(false); - if (splitBaseURL()) + if (mbActive) { - // try for base file (usually registrymodifications) - bDidPop = tryPop_basefile(); + const OUString aPackURL(getPackURL()); + + // ensure dir and file vectors + fillDirFileInfo(); + + // proccess all files in question recursively + if (!maDirs.empty() || !maFiles.empty()) + { + bDidPop = tryPop_files( + maDirs, + maFiles, + maUserConfigBaseURL, + aPackURL); + } // try for ExtensionInfo - bDidPop |= tryPop_extensionInfo(); + if (mbExtensions) + { + bDidPop |= tryPop_extensionInfo(aPackURL); + } if (bDidPop) { // try removal of evtl. empty directory - osl::Directory::remove(getPackDirName()); + osl::Directory::remove(aPackURL); } } return bDidPop; } - bool BackupFileHelper::splitBaseURL() + /////////////////// helpers /////////////////////// + + const rtl::OUString BackupFileHelper::getPackURL() const + { + return rtl::OUString(maUserConfigBaseURL + "/pack"); + } + + /////////////////// file push helpers /////////////////////// + + bool BackupFileHelper::tryPush_Files( + const std::set< OUString >& rDirs, + const std::set< std::pair< OUString, OUString > >& rFiles, + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL // target dir without trailing '/' + ) { - if (maBase.isEmpty() && !mrBaseURL.isEmpty()) + bool bDidPush(false); + osl::Directory::createPath(rTargetURL); + + // proccess files + for (const auto& file : rFiles) { - // split URL at extension and at last path separator - maBase = splitAtLastToken(splitAtLastToken(mrBaseURL, '.', maExt), '/', maName); + bDidPush |= tryPush_file( + rSourceURL, + rTargetURL, + file.first, + file.second); } - return !maBase.isEmpty() && !maName.isEmpty(); - } + // proccess dirs + for (const auto& dir : rDirs) + { + OUString aNewSourceURL(rSourceURL + "/" + dir); + OUString aNewTargetURL(rTargetURL + "/" + dir); + std::set< OUString > aNewDirs; + std::set< std::pair< OUString, OUString > > aNewFiles; - const rtl::OUString BackupFileHelper::getPackDirName() const - { - return rtl::OUString(maBase + "/pack"); - } + scanDirsAndFiles( + aNewSourceURL, + aNewDirs, + aNewFiles); - const rtl::OUString BackupFileHelper::getPackFileName(const rtl::OUString& rFileName) const - { - return rtl::OUString(getPackDirName() + "/" + rFileName + ".pack"); + if (!aNewDirs.empty() || !aNewFiles.empty()) + { + bDidPush |= tryPush_Files( + aNewDirs, + aNewFiles, + aNewSourceURL, + aNewTargetURL); + } + } + + if (!bDidPush) + { + // try removal of evtl. empty directory + osl::Directory::remove(rTargetURL); + } + + return bDidPush; } - bool BackupFileHelper::tryPush_basefile(bool bCompress) + bool BackupFileHelper::tryPush_file( + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL, // target dir without trailing '/' + const OUString& rName, // filename + const OUString& rExt // extension (or empty) + ) { - if (fileExists(mrBaseURL)) + const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); + + if (fileExists(aFileURL)) { - PackedFile aPackedFile(getPackFileName(maName)); - FileSharedPtr aBaseFile(new osl::File(mrBaseURL)); + const OUString aPackURL(createPackURL(rTargetURL, rName)); + PackedFile aPackedFile(aPackURL); + FileSharedPtr aBaseFile(new osl::File(aFileURL)); - if (aPackedFile.tryPush(aBaseFile, bCompress)) + if (aPackedFile.tryPush(aBaseFile, mbCompress)) { // reduce to allowed number and flush aPackedFile.tryReduceToNumBackups(mnNumBackups); @@ -1315,37 +1547,66 @@ namespace comphelper return false; } - bool BackupFileHelper::tryPush_extensionInfo(bool bCompress) + /////////////////// file pop possibilities helper /////////////////////// + + bool BackupFileHelper::isPopPossible_files( + const std::set< OUString >& rDirs, + const std::set< std::pair< OUString, OUString > >& rFiles, + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL // target dir without trailing '/' + ) { - ExtensionInfo aExtensionInfo; - OUString aTempURL; - bool bRetval(false); + bool bPopPossible(false); - // create current configuration and write to temp file - it exists until deleted - if (aExtensionInfo.createTempFile(aTempURL)) + // proccess files + for (const auto& file : rFiles) { - PackedFile aPackedFile(getPackFileName("ExtensionInfo")); - FileSharedPtr aBaseFile(new osl::File(aTempURL)); + bPopPossible |= isPopPossible_file( + rSourceURL, + rTargetURL, + file.first, + file.second); + } + + // proccess dirs + for (const auto& dir : rDirs) + { + OUString aNewSourceURL(rSourceURL + "/" + dir); + OUString aNewTargetURL(rTargetURL + "/" + dir); + std::set< OUString > aNewDirs; + std::set< std::pair< OUString, OUString > > aNewFiles; + + scanDirsAndFiles( + aNewSourceURL, + aNewDirs, + aNewFiles); - if (aPackedFile.tryPush(aBaseFile, bCompress)) + if (!aNewDirs.empty() || !aNewFiles.empty()) { - // reduce to allowed number and flush - aPackedFile.tryReduceToNumBackups(mnNumBackups); - aPackedFile.flush(); - bRetval = true; + bPopPossible |= isPopPossible_files( + aNewDirs, + aNewFiles, + aNewSourceURL, + aNewTargetURL); } } - // delete temp file (in all cases) - osl::File::remove(aTempURL); - return bRetval; + return bPopPossible; } - bool BackupFileHelper::isPopPossible_basefile() + bool BackupFileHelper::isPopPossible_file( + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL, // target dir without trailing '/' + const OUString& rName, // filename + const OUString& rExt // extension (or empty) + ) { - if (fileExists(mrBaseURL)) + const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); + + if (fileExists(aFileURL)) { - PackedFile aPackedFile(getPackFileName(maName)); + const OUString aPackURL(createPackURL(rTargetURL, rName)); + PackedFile aPackedFile(aPackURL); return !aPackedFile.empty(); } @@ -1353,20 +1614,73 @@ namespace comphelper return false; } - bool BackupFileHelper::isPopPossible_extensionInfo() + /////////////////// file pop helpers /////////////////////// + + bool BackupFileHelper::tryPop_files( + const std::set< OUString >& rDirs, + const std::set< std::pair< OUString, OUString > >& rFiles, + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL // target dir without trailing '/' + ) { - // extensionInfo always exists internally, no test needed - PackedFile aPackedFile(getPackFileName("ExtensionInfo")); + bool bDidPop(false); - return !aPackedFile.empty(); + // proccess files + for (const auto& file : rFiles) + { + bDidPop |= tryPop_file( + rSourceURL, + rTargetURL, + file.first, + file.second); + } + + // proccess dirs + for (const auto& dir : rDirs) + { + OUString aNewSourceURL(rSourceURL + "/" + dir); + OUString aNewTargetURL(rTargetURL + "/" + dir); + std::set< OUString > aNewDirs; + std::set< std::pair< OUString, OUString > > aNewFiles; + + scanDirsAndFiles( + aNewSourceURL, + aNewDirs, + aNewFiles); + + if (!aNewDirs.empty() || !aNewFiles.empty()) + { + bDidPop |= tryPop_files( + aNewDirs, + aNewFiles, + aNewSourceURL, + aNewTargetURL); + } + } + + if (bDidPop) + { + // try removal of evtl. empty directory + osl::Directory::remove(rTargetURL); + } + + return bDidPop; } - bool BackupFileHelper::tryPop_basefile() + bool BackupFileHelper::tryPop_file( + const OUString& rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL, // target dir without trailing '/' + const OUString& rName, // filename + const OUString& rExt // extension (or empty) + ) { - if (fileExists(mrBaseURL)) + const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); + + if (fileExists(aFileURL)) { - // try Pop for base file (usually registrymodifications) - PackedFile aPackedFile(getPackFileName(maName)); + // try Pop for base file + const OUString aPackURL(createPackURL(rTargetURL, rName)); + PackedFile aPackedFile(aPackURL); if (!aPackedFile.empty()) { @@ -1385,8 +1699,8 @@ namespace comphelper { // copy over existing file by first deleting original // and moving the temp file to old original - osl::File::remove(mrBaseURL); - osl::File::move(aTempURL, mrBaseURL); + osl::File::remove(aFileURL); + osl::File::move(aTempURL, aFileURL); // reduce to allowed number and flush aPackedFile.tryReduceToNumBackups(mnNumBackups); @@ -1404,10 +1718,55 @@ namespace comphelper return false; } - bool BackupFileHelper::tryPop_extensionInfo() + /////////////////// ExtensionInfo helpers /////////////////////// + + bool BackupFileHelper::tryPush_extensionInfo( + const OUString& rTargetURL // target dir without trailing '/' + ) + { + ExtensionInfo aExtensionInfo; + OUString aTempURL; + bool bRetval(false); + + // create current configuration and write to temp file - it exists until deleted + if (aExtensionInfo.createTempFile(aTempURL)) + { + const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + PackedFile aPackedFile(aPackURL); + FileSharedPtr aBaseFile(new osl::File(aTempURL)); + + if (aPackedFile.tryPush(aBaseFile, mbCompress)) + { + // reduce to allowed number and flush + aPackedFile.tryReduceToNumBackups(mnNumBackups); + aPackedFile.flush(); + bRetval = true; + } + } + + // delete temp file (in all cases) + osl::File::remove(aTempURL); + return bRetval; + } + + bool BackupFileHelper::isPopPossible_extensionInfo( + const OUString& rTargetURL // target dir without trailing '/' + ) + { + // extensionInfo always exists internally, no test needed + const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + PackedFile aPackedFile(aPackURL); + + return !aPackedFile.empty(); + } + + bool BackupFileHelper::tryPop_extensionInfo( + const OUString& rTargetURL // target dir without trailing '/' + ) { // extensionInfo always exists internally, no test needed - PackedFile aPackedFile(getPackFileName("ExtensionInfo")); + const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + PackedFile aPackedFile(aPackURL); if (!aPackedFile.empty()) { @@ -1436,7 +1795,9 @@ namespace comphelper aCurrentExtensionInfo.createCurrent(); - // now we have loaded and current ExtensionInfo and may react on differences + // now we have loaded last_working (aLoadedExtensionInfo) and + // current (aCurrentExtensionInfo) ExtensionInfo and may react on + // differences by de/activating these as needed @@ -1460,6 +1821,95 @@ namespace comphelper return false; } + + /////////////////// FileDirInfo helpers /////////////////////// + + void BackupFileHelper::fillDirFileInfo() + { + if (!maDirs.empty() || !maFiles.empty()) + { + // already done + return; + } + + // fill dir and file info list to work with dependent on work mode + switch (mnMode) + { + case 0: + { + // add registrymodifications (the orig file in maInitialBaseURL) + maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt)); + break; + } + case 1: + { + // add registrymodifications (the orig file in maInitialBaseURL) + maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt)); + + // Add a selection of dirs containing User-Defined and thus + // valuable configuration information (see https://wiki.documentfoundation.org/UserProfile). + // This is clearly discussable in every single point and may be adapted/corrected + // over time. Main focus is to secure User-Defined/adapted values + + // User-defined substitution table (Tools/AutoCorrect) + maDirs.insert("autocorr"); + + // User-Defined AutoText (Edit/AutoText) + maDirs.insert("autotext"); + + // User-defined Macros + maDirs.insert("basic"); + + // User-adapted toolbars for modules + maDirs.insert("config"); + + // Initial and User-defined Databases + maDirs.insert("database"); + + // User-Defined Galleries + maDirs.insert("gallery"); + + // most part of registry files + maDirs.insert("registry"); + + // User-Defined Scripts + maDirs.insert("Scripts"); + + // Template files + maDirs.insert("template"); + + // Custom Dictionaries + maDirs.insert("wordbook"); + + // Questionable - where and how is Extension stuff held and how + // does this interact with enabled/disabled states which are extra handled? + // Keep out of business until deeper evaluated + // maDirs.insert("extensions"); + // maDirs.insert("uno-packages"); + break; + } + case 2: + { + // whole directory. To do so, scan directory and exclude some dirs + // from which we know they do not need to be secured explicitely. This + // should alrteady include registrymodifications, too. + scanDirsAndFiles( + maUserConfigBaseURL, + maDirs, + maFiles); + + // not really needed, can be abandoned + maDirs.erase("psprint"); + + // not really needed, can be abandoned + maDirs.erase("store"); + + // not really needed, can be abandoned + maDirs.erase("temp"); + break; + } + } + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index b9e5401c7246..cd3fbfa96326 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -818,42 +818,6 @@ OUString Desktop::CreateErrorMsgString( return MakeStartupErrorMessage( aMsg ); } -// helper method to test if SecureUserConfig is active, detect the num copies -// and extract the User's config directory URL -bool testSecureUserConfigActive(sal_uInt16& rnSecureUserConfigNumCopies, OUString& raUserConfigDir) -{ - // read configuration from soffice.ini - if(comphelper::BackupFileHelper::getSecureUserConfig(rnSecureUserConfigNumCopies)) - { - // try to asccess user layer configuration file - OUString conf("${CONFIGURATION_LAYERS}"); - rtl::Bootstrap::expandMacros(conf); - const OUString aTokenUser("user:"); - sal_Int32 nStart(conf.indexOf(aTokenUser)); - - if (-1 != nStart) - { - nStart += aTokenUser.getLength(); - sal_Int32 nEnd(conf.indexOf(' ', nStart)); - - if (-1 == nEnd) - { - nEnd = conf.getLength(); - } - - raUserConfigDir = conf.copy(nStart, nEnd - nStart); - raUserConfigDir.startsWith("!", &raUserConfigDir); - } - - if (!raUserConfigDir.isEmpty()) - { - return true; - } - } - - return false; -} - void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError, OUString const & aErrorMessage ) { @@ -987,43 +951,37 @@ void Desktop::HandleBootstrapErrors( } else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN ) { - // test if SecureUserConfig is active - sal_uInt16 nSecureUserConfigNumCopies(0); - OUString aUserConfigDir; bool bFireOriginalError(true); + comphelper::BackupFileHelper aBackupFileHelper; - if (testSecureUserConfigActive(nSecureUserConfigNumCopies, aUserConfigDir)) + // crerate BackupFileHelper and check if active and if pop is possible + if (aBackupFileHelper.isPopPossible()) { - comphelper::BackupFileHelper aBackupFileHelper(aUserConfigDir, nSecureUserConfigNumCopies); + // for linux (and probably others?) we need to instantiate XDesktop2 + // to be able to open a *.ui-file based dialog, so do this here locally. + // does no harm on win, so better always do this (in error case only anyways) + Reference< XComponentContext > xLocalContext = ::comphelper::getProcessComponentContext(); + Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xLocalContext); + + ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore( + Application::GetDefDialogParent(), + "QueryTryToRestoreConfigurationDialog", + "desktop/ui/querytrytorestoreconfigurationdialog.ui"); - if (aBackupFileHelper.isPopPossible()) + if (aQueryShouldRestore.get()) { - // for linux (and probably others?) we need to instantiate XDesktop2 - // to be able to open a *.ui-file based dialog, so do this here locally. - // does no harm on win, so better always do this (in error case only anyways) - Reference< XComponentContext > xLocalContext = ::comphelper::getProcessComponentContext(); - Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xLocalContext); - - ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore( - Application::GetDefDialogParent(), - "QueryTryToRestoreConfigurationDialog", - "desktop/ui/querytrytorestoreconfigurationdialog.ui"); - - if (aQueryShouldRestore.get()) + if (!aErrorMessage.isEmpty()) { - if (!aErrorMessage.isEmpty()) - { - OUString aPrimaryText(aQueryShouldRestore->get_primary_text()); + OUString aPrimaryText(aQueryShouldRestore->get_primary_text()); - aPrimaryText += "\n(\"" + aErrorMessage + "\")"; - aQueryShouldRestore->set_primary_text(aPrimaryText); - } + aPrimaryText += "\n(\"" + aErrorMessage + "\")"; + aQueryShouldRestore->set_primary_text(aPrimaryText); + } - if (RET_YES == aQueryShouldRestore->Execute()) - { - aBackupFileHelper.tryPop(); - bFireOriginalError = false; - } + if (RET_YES == aQueryShouldRestore->Execute()) + { + aBackupFileHelper.tryPop(); + bFireOriginalError = false; } } } @@ -1863,16 +1821,9 @@ int Desktop::doShutdown() // Test if SecureUserConfig is active. If yes and we are at this point, regular shutdown // is in progress and the currently used configuration was working. Try to secure this // working configuration for later eventually necessary restores - sal_uInt16 nSecureUserConfigNumCopies(0); - OUString aUserConfigDir; + comphelper::BackupFileHelper aBackupFileHelper; - if (testSecureUserConfigActive(nSecureUserConfigNumCopies, aUserConfigDir)) - { - // try to push registrymodifications.xcu - comphelper::BackupFileHelper aBackupFileHelper(aUserConfigDir, nSecureUserConfigNumCopies); - - aBackupFileHelper.tryPush(); - } + aBackupFileHelper.tryPush(); } // The acceptors in the AcceptorMap must be released (in DeregisterServices) diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx index 503bfc672549..b1913f901822 100644 --- a/include/comphelper/backupfilehelper.hxx +++ b/include/comphelper/backupfilehelper.hxx @@ -16,6 +16,7 @@ #include <rtl/ustring.hxx> #include <osl/file.hxx> #include <memory> +#include <set> namespace comphelper { @@ -59,11 +60,20 @@ namespace comphelper { private: // internal data - const OUString& mrBaseURL; - sal_uInt16 mnNumBackups; - OUString maBase; - OUString maName; - OUString maExt; + OUString maInitialBaseURL; + OUString maUserConfigBaseURL; + OUString maRegModName; + OUString maExt; + + std::set< OUString > maDirs; + std::set< std::pair< OUString, OUString > > maFiles; + + sal_uInt16 mnNumBackups; + sal_uInt16 mnMode; + + bool mbActive; + bool mbExtensions; + bool mbCompress; // internal flag if _exit() was called already - a hint to evtl. // not create copies of potentially not well-defined data. This @@ -78,51 +88,26 @@ namespace comphelper static sal_uInt16 mnMaxAllowedBackups; public: - /** Constructor to handle Backups of the given file - * - * @param rxContext - * ComponentContext to use internally; needs to be handed - * over due to usages after DeInit() and thus no access - * anymore using comphelper::getProcessComponentContext() - * @param rBaseURL - * URL to an existing file that needs to be backed up - * - * @param nNumBackups - * Specifies the maximum number of backups to allow for - * the file. This value gets truncated to [1..max] where - * max currently is 10 and defined in the implementation. - * It is used in tryPush() and tryPop() calls to cleanup/ - * reduce the number of existing backups + /** Constructor to handle Backups of the given file, will internally + * detect configuration values and URL to initial registrymodifications + * and thus the User configuration directory */ - BackupFileHelper( - const OUString& rBaseURL, - sal_uInt16 nNumBackups = 5); + BackupFileHelper(); // allow to set static global flag when app had to call _exit() static void setExitWasCalled(); static bool getExitWasCalled(); - // static helper to read config values - these are derived from - // soffice.ini due to cui not being available in all cases. The - // boolean SecureUserConfig is returned. - // Default for SecureUserConfig is false - // Default for SecureUserConfigNumCopies is 0 (zero) - static bool getSecureUserConfig(sal_uInt16& rnSecureUserConfigNumCopies); - /** tries to create a new backup, if there is none yet, or if the * last differs from the base file. It will then put a new verion * on the 'stack' of copies and evtl. delete the oldest backup. * Also may cleanup older backups when NumBackups given in the * constructor has changed. * - * @param bCompress - * Defines if the new backup will be compressed when - * added. Default is true - * * @return bool * returns true if a new backup was actually created */ - bool tryPush(bool bCompress = true); + bool tryPush(); /** finds out if a restore is possible * @@ -143,15 +128,27 @@ namespace comphelper private: // internal helper methods - bool splitBaseURL(); - const rtl::OUString getPackDirName() const; - const rtl::OUString getPackFileName(const rtl::OUString& rFileName) const; - bool tryPush_basefile(bool bCompress); - bool tryPush_extensionInfo(bool bCompress); - bool isPopPossible_basefile(); - bool isPopPossible_extensionInfo(); - bool tryPop_basefile(); - bool tryPop_extensionInfo(); + const rtl::OUString getPackURL() const; + + // file push helpers + bool tryPush_Files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL); + bool tryPush_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt); + + // file pop possibilities helper + bool isPopPossible_files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL); + static bool isPopPossible_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt); + + // file pop helpers + bool tryPop_files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL); + bool tryPop_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt); + + // ExtensionInfo helpers + bool tryPush_extensionInfo(const OUString& rTargetURL); + static bool isPopPossible_extensionInfo(const OUString& rTargetURL); + bool tryPop_extensionInfo(const OUString& rTargetURL); + + // FileDirInfo helpers + void fillDirFileInfo(); }; } diff --git a/instsetoo_native/CustomTarget_setup.mk b/instsetoo_native/CustomTarget_setup.mk index 26fc42792a03..5ce472632cdf 100644 --- a/instsetoo_native/CustomTarget_setup.mk +++ b/instsetoo_native/CustomTarget_setup.mk @@ -104,7 +104,16 @@ $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_ ) > $@ # for release-builds (building installers) adjust values in openoffice.lst.in -# Added 'SecureUserConfig' flags to enable and safe three registrymodifications.xcu versions +# Added 'SecureUserConfig' flags to enable and safe user config files +# SecureUserConfig : boolean - switches securing on/off - default false +# SecureUserConfigCompress : boolean - defines if backup data will be compressed - default true +# SecureUserConfigNumCopies : integer - defines how many compressed copies of saved content will be kept - default 2 +# SecureUserConfigMode: integer - defines what to secure, default is 0 +# 0 : only registrymodifications.xcu +# 1 : a selected amount of user-defined configs +# 2 : everything in the user config directory +# SecureUserConfigExtensions: boolean - defines to also safe the extension configuration (which extensions +# are installed, which are activated) - default is true $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_rcfile,soffice) : $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),ECH,1) ( \ @@ -120,7 +129,10 @@ $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_ && echo 'ProgressTextColor=255,255,255' \ && echo 'URE_BOOTSTRAP=$${ORIGIN}/$(call gb_Helper_get_rcfile,fundamental)' \ && echo 'SecureUserConfig=true' \ - && echo 'SecureUserConfigNumCopies=3' \ + && echo 'SecureUserConfigCompress=true' \ + && echo 'SecureUserConfigNumCopies=2' \ + && echo 'SecureUserConfigMode=0' \ + && echo 'SecureUserConfigExtensions=true' \ ) > $@ $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_rcfile,uno) : |