[Libreoffice-commits] core.git: comphelper/source desktop/source include/comphelper instsetoo_native/CustomTarget_setup.mk

Armin Le Grand Armin.Le.Grand at cib.de
Thu Oct 13 14:46:53 UTC 2016


 comphelper/source/misc/backupfilehelper.cxx |  640 +++++++++++++++++++++++-----
 desktop/source/app/app.cxx                  |   99 +---
 include/comphelper/backupfilehelper.hxx     |   85 +--
 instsetoo_native/CustomTarget_setup.mk      |   16 
 4 files changed, 625 insertions(+), 215 deletions(-)

New commits:
commit 5f55b7d00a70db5dddaa0e74ccef52c021770f95
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Oct 13 14:16:56 2016 +0200

    profilesafe: extended to three modes
    
    Saving configuration is now extended to three
    basic modes, from just saving registrymodifiications
    to adding user-defined config stuff to saving all
    information in the user profile, additionally
    configuration information for Extensions is saved.
    Added configuration entries for this and tested
    saving/restoring.
    
    Change-Id: I79b09c37617803bf656826f76a7e3db79cda49ac
    Reviewed-on: https://gerrit.libreoffice.org/29770
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>

diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index f452213..d5468f4 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 b9e5401..cd3fbfa 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 503bfc6..b1913f9 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 26fc427..5ce4726 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) :


More information about the Libreoffice-commits mailing list