Kaydet (Commit) 7db23b63 authored tarafından Armin Le Grand's avatar Armin Le Grand

profilesafe: Collect copies in single *.pack file

Enhanced helper classes for BackupFileHelper to
allow writing a stack of rescued last valid
configuration files to a single file package.
Added configuration values for enabling this and
defining the number of entries, added max entry
limitation. Using FileSize and CRC32 now to dectect
if config file did change. To make this work I added
sorting to writing the configuration so that with no
change the same configuration file is written.
Use std::vector for better mem performance for sorting,
defined static const for buffer size of manipulation,
prepare inflate/deflate usages. Fixes to setPos, warnings

Change-Id: Ib286e2a3f25b0085a1e3ae4f50c9ff1ff3a5dcf5
üst 9fa4eff9
......@@ -643,18 +643,22 @@ Components::~Components()
(*i)->setAlive(false);
}
// test backup of registrymodifications
static bool bFeatureSecureUserConfig(true);
if (!bExitWasCalled &&
bFeatureSecureUserConfig &&
ModificationTarget::File == modificationTarget_ &&
!modificationFileUrl_.isEmpty())
{
static sal_uInt16 nNumCopies(5);
comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nNumCopies);
// test backup of registrymodifications
sal_uInt16 nSecureUserConfigNumCopies(0);
// read configuration from soffice.ini
const bool bSecureUserConfig(comphelper::BackupFileHelper::getSecureUserConfig(nSecureUserConfigNumCopies));
aBackupFileHelper.tryPush();
if (bSecureUserConfig)
{
comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nSecureUserConfigNumCopies);
aBackupFileHelper.tryPush();
}
}
}
......
......@@ -400,6 +400,16 @@ void writeNode(
}
}
// helpers to allow sorting of configmgr::Modifications::Node
typedef std::pair< const rtl::OUString, configmgr::Modifications::Node > ModNodePairEntry;
struct PairEntrySorter
{
bool operator() (const ModNodePairEntry* pValue1, const ModNodePairEntry* pValue2) const
{
return pValue1->first.compareTo(pValue2->first) < 0;
}
};
void writeModifications(
Components & components, TempFile &handle,
OUString const & parentPathRepresentation,
......@@ -459,11 +469,27 @@ void writeModifications(
OUString pathRep(
parentPathRepresentation + "/" +
Data::createSegment(node->getTemplateName(), nodeName));
for (const auto & i : modifications.children)
// copy configmgr::Modifications::Node's to a sortable list. Use pointers
// to just reference the data instead of copying it
std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
ModNodePairEntryVector.reserve(modifications.children.size());
for (const auto& rCand : modifications.children)
{
ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order
// instead of random as from the unordered map
for (const auto & i : ModNodePairEntryVector)
{
writeModifications(
components, handle, pathRep, node, i.first,
node->getMember(i.first), i.second);
components, handle, pathRep, node, i->first,
node->getMember(i->first), i->second);
}
}
}
......@@ -601,9 +627,31 @@ void writeModFile(
//TODO: Do not write back information about those removed items that did not
// come from the .xcs/.xcu files, anyway (but had been added dynamically
// instead):
for (Modifications::Node::Children::const_iterator j(
data.modifications.getRoot().children.begin());
j != data.modifications.getRoot().children.end(); ++j)
// For profilesafemode it is necessary to detect changes in the
// registrymodifications file, this is done based on file size in bytes and crc32.
// Unfortunately this write is based on writing unordered map entries, which creates
// valid and semantically equal XML-Files, bubt with different crc32 checksums. For
// the future usage it will be preferrable to have easily comparable config files
// which is guaranteed by writing the entries in sorted order. Indeed with this change
// (and in the recursive writeModifications call) the same config files get written
// copy configmgr::Modifications::Node's to a sortable list. Use pointers
// to just reference the data instead of copying it
std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
ModNodePairEntryVector.reserve(data.modifications.getRoot().children.size());
for (const auto& rCand : data.modifications.getRoot().children)
{
ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order
// instead of random as from the unordered map
for (const auto& j : ModNodePairEntryVector)
{
writeModifications(
components, tmp, "", rtl::Reference< Node >(), j->first,
......
......@@ -948,11 +948,13 @@ void Desktop::HandleBootstrapErrors(
else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
{
// test restore of registrymodifications
static bool bFeatureSecureUserConfig(true);
static sal_uInt16 nNumCopies(5);
sal_uInt16 nSecureUserConfigNumCopies(0);
bool bFireOriginalError(true);
if (bFeatureSecureUserConfig)
// read configuration from soffice.ini
const bool bSecureUserConfig(comphelper::BackupFileHelper::getSecureUserConfig(nSecureUserConfigNumCopies));
if (bSecureUserConfig)
{
// try to asccess user layer configuration file
OUString conf("${CONFIGURATION_LAYERS}");
......@@ -977,7 +979,7 @@ void Desktop::HandleBootstrapErrors(
if (!aUser.isEmpty())
{
comphelper::BackupFileHelper aBackupFileHelper(aUser, nNumCopies);
comphelper::BackupFileHelper aBackupFileHelper(aUser, nSecureUserConfigNumCopies);
if (aBackupFileHelper.isPopPossible())
{
......
......@@ -15,6 +15,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
#include <osl/file.hxx>
#include <memory>
namespace comphelper
{
......@@ -45,12 +46,11 @@ namespace comphelper
{
private:
// internal data
const OUString& mrBaseURL;
sal_uInt16 mnNumBackups;
OUString maBase;
OUString maExt;
osl::File maBaseFile;
bool mbBaseFileIsOpen;
const OUString& mrBaseURL;
sal_uInt16 mnNumBackups;
OUString maBase;
OUString maName;
OUString maExt;
// internal flag if _exit() was called already - a hint to evtl.
// not create copies of potentially not well-defined data. This
......@@ -67,6 +67,10 @@ namespace comphelper
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
*
......@@ -77,12 +81,21 @@ namespace comphelper
* It is used in tryPush() and tryPop() calls to cleanup/
* reduce the number of existing backups
*/
BackupFileHelper(const OUString& rBaseURL, sal_uInt16 nNumBackups = 5);
BackupFileHelper(
const OUString& rBaseURL,
sal_uInt16 nNumBackups = 5);
// allow to set flag when app had to call _exit()
// 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.
......@@ -113,14 +126,9 @@ namespace comphelper
private:
// internal helper methods
rtl::OUString getName(sal_uInt16 n);
bool firstExists();
void pop();
void push();
bool isDifferentOrNew();
bool equalsBase(osl::File& rLastFile);
bool splitBaseURL();
bool baseFileOpen();
bool baseFileExists();
rtl::OUString getName();
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment