/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// set offset in source file - should be zero due to crc32 should // only be needed to be created for new entries, gets loaded with old // ones if (osl::File::E_None == rCandidate->setPos(osl_Pos_Absolut, sal_Int64(nOffset)))
{ while (nSize != 0)
{ const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE)));
if (osl::File::E_None == rCandidate->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) && nBytesTransfer == nToTransfer)
{ // add to crc and reduce size
nCrc32 = rtl_crc32(nCrc32, static_cast<void*>(aArray), static_cast<sal_uInt32>(nBytesTransfer));
nSize -= nToTransfer;
} else
{ // error - reset to zero again
nSize = nCrc32 = 0;
}
}
}
if (!aAttrUrl.isEmpty())
{ for (constauto& enable : rToBeEnabled)
{ if (-1 != aAttrUrl.indexOf(enable.getName()))
{ if (!bEnabled)
{ // needs to be enabled
rElement->removeAttribute(u"revoked"_ustr);
bChanged = true;
}
}
}
for (constauto& disable : rToBeDisabled)
{ if (-1 != aAttrUrl.indexOf(disable.getName()))
{ if (bEnabled)
{ // needs to be disabled
rElement->setAttribute(u"revoked"_ustr, u"true"_ustr);
bChanged = true;
}
}
}
}
} else
{
uno::Reference< xml::dom::XNodeList > aList = rElement->getChildNodes();
if (aList.is())
{ const sal_Int32 nLength(aList->getLength());
for (sal_Int32 a(0); a < nLength; a++)
{ const uno::Reference< xml::dom::XElement > aChild(aList->item(a), uno::UNO_QUERY);
// set output stream and do the serialization
xSaxWriter->setOutputStream(xOutStrm);
xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >());
// get URL from temp file
OUString aTempURL = xTempFile->getUri();
// copy back file if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) return;
if (DirectoryHelper::fileExists(rUnoPackagReg))
{
osl::File::remove(rUnoPackagReg);
}
// create current configuration if (maEntries.empty())
{
createUsingXExtensionManager();
}
// open target temp file and write current configuration to it - it exists until deleted if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &rTempFileName))
{
bRetval = write_entries(aHandle);
// close temp file - it exists until deleted
osl_closeFile(aHandle);
}
return bRetval;
}
bool areThereEnabledExtensions() const
{ for (constauto& a : maEntries)
{ if (a.isEnabled())
{ returntrue;
}
}
returnfalse;
}
};
}
namespace
{ class PackedFileEntry
{ private:
sal_uInt32 mnFullFileSize; // size in bytes of unpacked original file
sal_uInt32 mnPackFileSize; // size in bytes in file backup package (smaller if compressed, same if not)
sal_uInt32 mnOffset; // offset in File (zero identifies new file)
sal_uInt32 mnCrc32; // checksum
FileSharedPtr maFile; // file where to find the data (at offset) boolconst mbDoCompress; // flag if this file is scheduled to be compressed when written
// set offset in source file - when this is zero, a new file is to be added if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
{ while (nSize != 0)
{ const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE)));
if (Z_OK == deflateInit(&zstream, Z_BEST_COMPRESSION))
{ // set offset in source file - when this is zero, a new file is to be added if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
{ bool bOkay(true);
if (Z_OK == inflateInit(&zstream))
{ // set offset in source file - when this is zero, a new file is to be added if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset())))
{ bool bOkay(true);
if (osl::File::E_None == aSourceFile->open(osl_File_OpenFlag_Read))
{
sal_uInt64 nBaseLen(0);
aSourceFile->getSize(nBaseLen);
// we need at least File_ID and num entries -> 8byte if (8 < nBaseLen)
{
sal_uInt8 aArray[4];
sal_uInt64 nBaseRead(0);
// read and check File_ID if (osl::File::E_None == aSourceFile->read(static_cast< void* >(aArray), 4, nBaseRead) && 4 == nBaseRead)
{ if ('P' == aArray[0] && 'A' == aArray[1] && 'C' == aArray[2] && 'K' == aArray[3])
{ // read and compute num entries in this file if (osl::File::E_None == aSourceFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
{
sal_uInt32 nEntries((sal_uInt32(aArray[0]) << 24) + (sal_uInt32(aArray[1]) << 16) + (sal_uInt32(aArray[2]) << 8) + sal_uInt32(aArray[3]));
// if there are entries (and less than max), read them if (nEntries >= 1 && nEntries <= 10)
{ for (sal_uInt32 a(0); a < nEntries; a++)
{ // create new entry, read header (size, crc and PackedSize), // set offset and source file
PackedFileEntry aEntry;
if (aEntry.read_header(aSourceFile))
{ // add to local data
maPackedFileEntryVector.push_back(aEntry);
} else
{ // error
nEntries = 0;
}
}
if (0 == nEntries)
{ // on read error clear local data
maPackedFileEntryVector.clear();
} else
{ // calculate and set offsets to file binary content
sal_uInt32 nHeaderSize(8);
for (auto& b : maPackedFileEntryVector)
{
b.setOffset(nOffset);
nOffset += b.getPackFileSize();
}
}
}
}
}
}
}
aSourceFile->close();
}
if (maPackedFileEntryVector.empty())
{ // on error or no data get rid of pack file
osl::File::remove(maURL);
}
}
void flush()
{ bool bRetval(true);
if (maPackedFileEntryVector.empty())
{ // get rid of (now?) empty pack file
osl::File::remove(maURL);
} elseif (mbChanged)
{ // need to create a new pack file, do this in a temp file to which data // will be copied from local file (so keep it here until this is done)
oslFileHandle aHandle = nullptr;
OUString aTempURL;
// open target temp file - it exists until deleted if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
{
sal_uInt8 aArray[4];
sal_uInt64 nBaseWritten(0);
// write number of entries if (write_sal_uInt32(aHandle, nSize))
{ // write placeholder for headers. Due to the fact that // PackFileSize for newly added files gets set during // writing the content entry, write headers after content // is written. To do so, write placeholders here
sal_uInt32 nWriteSize(0);
for (sal_uInt32 a(0); bRetval && a < nWriteSize; a++)
{ if (osl_File_E_None != osl_writeFile(aHandle, static_cast<constvoid*>(aArray), 1, &nBaseWritten) || 1 != nBaseWritten)
{
bRetval = false;
}
}
if (bRetval)
{ // write contents - this may adapt PackFileSize for new // files for (auto& candidate : maPackedFileEntryVector)
{ if (!candidate.copy_content(aHandle, false))
{
bRetval = false; break;
}
}
}
if (bRetval)
{ // seek back to header start (at position 8) if (osl_File_E_None != osl_setFilePos(aHandle, osl_Pos_Absolut, sal_Int64(8)))
{
bRetval = false;
}
}
if (bRetval)
{ // write headers for (constauto& candidate : maPackedFileEntryVector)
{ if (!candidate.write_header(aHandle))
{ // error
bRetval = false; break;
}
}
}
}
}
}
// close temp file (in all cases) - it exists until deleted
osl_closeFile(aHandle);
if (bRetval)
{ // copy over existing file by first deleting original // and moving the temp file to old original
osl::File::remove(maURL);
osl::File::move(aTempURL, maURL);
}
// delete temp file (in all cases - it may be moved already)
osl::File::remove(aTempURL);
}
}
if (maPackedFileEntryVector.empty())
{ // no backup yet, add as 1st backup
bNeedToAdd = true;
} else
{ // already backups there, check if different from last entry const PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
// check if file is different if (aLastEntry.getFullFileSize() != static_cast<sal_uInt32>(nFileSize))
{ // different size, different file
bNeedToAdd = true;
} else
{ // same size, check crc32
nCrc32 = createCrc32(rFileCandidate, 0);
if (nCrc32 != aLastEntry.getCrc32())
{ // different crc, different file
bNeedToAdd = true;
}
}
}
if (bNeedToAdd)
{ // create crc32 if not yet done if (0 == nCrc32)
{
nCrc32 = createCrc32(rFileCandidate, 0);
}
// create a file entry for a new file. Offset is set automatically // to 0 to mark the entry as new file entry
maPackedFileEntryVector.emplace_back( static_cast< sal_uInt32 >(nFileSize),
nCrc32,
rFileCandidate,
bCompress);
mbChanged = true;
}
return bNeedToAdd;
}
bool tryPop(oslFileHandle& rHandle)
{ if (maPackedFileEntryVector.empty()) returnfalse;
// already backups there, check if different from last entry
PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
// here the uncompress flag has to be determined, true // means to add the file compressed, false means to add it // uncompressed bool bRetval = aLastEntry.copy_content(rHandle, true);
if (bRetval)
{
maPackedFileEntryVector.pop_back();
mbChanged = true;
}
const OUString& BackupFileHelper::getInitialBaseURL()
{ if (maInitialBaseURL.isEmpty())
{ // try to access user layer configuration file URL, the one that // points to registrymodifications.xcu
OUString conf(u"${CONFIGURATION_LAYERS}"_ustr);
rtl::Bootstrap::expandMacros(conf); static constexpr OUString aTokenUser(u"user:"_ustr);
sal_Int32 nStart(conf.indexOf(aTokenUser));
if (!maInitialBaseURL.isEmpty())
{ // split URL at extension and at last path separator
maUserConfigBaseURL = DirectoryHelper::splitAtLastToken(
DirectoryHelper::splitAtLastToken(maInitialBaseURL, '.', maExt), '/',
maRegModName);
}
if (!maUserConfigBaseURL.isEmpty())
{ // check if SafeModeDir exists
mbSafeModeDirExists = DirectoryHelper::dirExists(maUserConfigBaseURL + "/" + getSafeModeName());
}
maUserConfigWorkURL = maUserConfigBaseURL;
if (mbSafeModeDirExists)
{ // adapt work URL to do all repair op's in the correct directory
maUserConfigWorkURL += "/" + getSafeModeName();
}
}
if (mbActive)
{ // ensure existence
getInitialBaseURL();
// if not found, we are out of business (maExt may be empty)
mbActive = !maInitialBaseURL.isEmpty() && !maUserConfigBaseURL.isEmpty() && !maRegModName.isEmpty();
}
if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigNumCopies"_ustr, sTokenOut))
{ const sal_uInt16 nConfigNumCopies(static_cast<sal_uInt16>(sTokenOut.toUInt32()));
// limit to range [1..mnMaxAllowedBackups]
mnNumBackups = std::clamp(mnNumBackups, nConfigNumCopies, mnMaxAllowedBackups);
}
if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigMode"_ustr, sTokenOut))
{ const sal_uInt16 nMode(static_cast<sal_uInt16>(sTokenOut.toUInt32()));
// limit to range [0..2]
mnMode = std::min(nMode, sal_uInt16(2));
}
if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigExtensions"_ustr, sTokenOut))
{
mbExtensions = sTokenOut.toBoolean();
}
void BackupFileHelper::reactOnSafeMode(bool bSafeMode)
{ // ensure existence of needed paths
getInitialBaseURL();
if (maUserConfigBaseURL.isEmpty()) return;
if (bSafeMode)
{ if (!mbSafeModeDirExists)
{
std::set< OUString > aExcludeList;
// do not move SafeMode directory itself
aExcludeList.insert(getSafeModeName());
// init SafeMode by creating the 'SafeMode' directory and moving // all stuff there. All repairs will happen there. Both Dirs have to exist. // extend maUserConfigWorkURL as needed
maUserConfigWorkURL = maUserConfigBaseURL + "/" + getSafeModeName();
// switch local flag, maUserConfigWorkURL is already reset
mbSafeModeDirExists = true;
}
} else
{ if (mbSafeModeDirExists)
{ // SafeMode has ended, return to normal mode by moving all content // from 'SafeMode' directory back to UserDirectory and deleting it. // Both Dirs have to exist
std::set< OUString > aExcludeList;
// switch local flag and reset maUserConfigWorkURL
mbSafeModeDirExists = false;
maUserConfigWorkURL = maUserConfigBaseURL;
}
}
}
void BackupFileHelper::tryPush()
{ // no push when SafeModeDir exists, it may be Office's exit after SafeMode // where SafeMode flag is already deleted, but SafeModeDir cleanup is not // done yet (is done at next startup) if (!mbActive || mbSafeModeDirExists) return;
const OUString aPackURL(getPackURL());
// ensure dir and file vectors
fillDirFileInfo();
// process all files in question recursively if (!maDirs.empty() || !maFiles.empty())
{
tryPush_Files(
maDirs,
maFiles,
maUserConfigWorkURL,
aPackURL);
}
}
void BackupFileHelper::tryPushExtensionInfo()
{ // no push when SafeModeDir exists, it may be Office's exit after SafeMode // where SafeMode flag is already deleted, but SafeModeDir cleanup is not // done yet (is done at next startup) if (mbActive && mbExtensions && !mbSafeModeDirExists)
{ const OUString aPackURL(getPackURL());
// process all files in question recursively if (!maDirs.empty() || !maFiles.empty())
{
bDidPop = tryPop_files(
maDirs,
maFiles,
maUserConfigWorkURL,
aPackURL);
}
if (bDidPop)
{ // try removal of evtl. empty directory
osl::Directory::remove(aPackURL);
}
}
if (bDidPop)
{ // try removal of evtl. empty directory
osl::Directory::remove(aPackURL);
}
}
bool BackupFileHelper::isTryDisableAllExtensionsPossible()
{ // check if there are still enabled extension which can be disabled, // but as we are now in SafeMode, use XML infos for this since the // extensions are not loaded from XExtensionManager class ExtensionInfo aExtensionInfo;
void BackupFileHelper::tryDisableAllExtensions()
{ // disable all still enabled extensions, // but as we are now in SafeMode, use XML infos for this since the // extensions are not loaded from XExtensionManager
ExtensionInfo aCurrentExtensionInfo; const ExtensionInfoEntryVector aToBeEnabled{};
ExtensionInfoEntryVector aToBeDisabled;
const std::vector< OUString >& BackupFileHelper::getCustomizationDirNames()
{ static std::vector< OUString > aDirNames =
{
u"config"_ustr, // UI config stuff
u"registry"_ustr, // most of the registry stuff
u"psprint"_ustr, // not really needed, can be abandoned
u"store"_ustr, // not really needed, can be abandoned
u"temp"_ustr, // not really needed, can be abandoned
u"pack"_ustr // own backup dir
};
xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr,
u"DisableOpenGL"_ustr, u"true"_ustr));
xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/Misc"_ustr,
u"UseOpenCL"_ustr, u"false"_ustr)); // Do not disable Skia entirely, just force its CPU-based raster mode.
xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr,
u"ForceSkia"_ustr, u"false"_ustr));
xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr,
u"ForceSkiaRaster"_ustr, u"true"_ustr));
OUString aTempURL;
{ // use the scope to make sure that the temp file gets properly closed before move
// write back
uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDocument, uno::UNO_QUERY);
if (!xSerializer.is()) return;
// create a SAXWriter
uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext);
uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(xContext);
xTempFile->setRemoveFile(false); // avoid removal of tempfile when leaving the scope
uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream();
// set output stream and do the serialization
xSaxWriter->setOutputStream(xOutStrm);
xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >());
// get URL from temp file
aTempURL = xTempFile->getUri();
}
// copy back file if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) return;
if (DirectoryHelper::fileExists(aRegistryModifications))
{
osl::File::remove(aRegistryModifications);
}
int result = osl::File::move(aTempURL, aRegistryModifications);
SAL_WARN_IF(result != osl::FileBase::E_None, "comphelper.backupfilehelper", "could not copy back modified Extension configuration file");
}
bool BackupFileHelper::isTryResetCustomizationsPossible()
{ // return true if not all of the customization selection dirs or files are deleted const std::vector< OUString >& rDirs = getCustomizationDirNames();
for (constauto& a : rDirs)
{ if (DirectoryHelper::dirExists(maUserConfigWorkURL + "/" + a))
{ returntrue;
}
}
if (aPackedFile.tryPush(aBaseFile, mbCompress))
{ // reduce to allowed number and flush
aPackedFile.tryReduceToNumBackups(mnNumBackups);
aPackedFile.flush();
returntrue;
}
}
returnfalse;
}
/////////////////// file pop possibilities helper ///////////////////////
bool BackupFileHelper::isPopPossible_files( const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles,
std::u16string_view rSourceURL, // source dir without trailing '/'
std::u16string_view rTargetURL // target dir without trailing '/'
)
{ bool bPopPossible(false);
// process files for (constauto& file : rFiles)
{
bPopPossible |= isPopPossible_file(
rSourceURL,
rTargetURL,
file.first,
file.second);
}
if (bDidPop)
{ // try removal of evtl. empty directory
osl::Directory::remove(rTargetURL);
}
return bDidPop;
}
bool BackupFileHelper::tryPop_file(
std::u16string_view rSourceURL, // source dir without trailing '/'
std::u16string_view rTargetURL, // target dir without trailing '/'
std::u16string_view rName, // filename
std::u16string_view rExt // extension (or empty)
)
{ const OUString aFileURL(createFileURL(rSourceURL, rName, rExt));
if (!DirectoryHelper::fileExists(aFileURL)) returnfalse;
// try Pop for base file const OUString aPackURL(createPackURL(rTargetURL, rName));
PackedFile aPackedFile(aPackURL);
if (aPackedFile.empty()) returnfalse;
oslFileHandle aHandle;
OUString aTempURL;
// open target temp file - it exists until deleted if (osl::File::E_None != osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) returnfalse;
bool bRetval(aPackedFile.tryPop(aHandle));
// close temp file (in all cases) - it exists until deleted
osl_closeFile(aHandle);
if (bRetval)
{ // copy over existing file by first deleting original // and moving the temp file to old original
osl::File::remove(aFileURL);
osl::File::move(aTempURL, aFileURL);
// reduce to allowed number and flush
aPackedFile.tryReduceToNumBackups(mnNumBackups);
aPackedFile.flush();
}
// delete temp file (in all cases - it may be moved already)
osl::File::remove(aTempURL);
bool BackupFileHelper::tryPush_extensionInfo(
std::u16string_view 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, u"ExtensionInfo"));
PackedFile aPackedFile(aPackURL);
FileSharedPtr aBaseFile = std::make_shared<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(
std::u16string_view rTargetURL // target dir without trailing '/'
)
{ // extensionInfo always exists internally, no test needed const OUString aPackURL(createPackURL(rTargetURL, u"ExtensionInfo"));
PackedFile aPackedFile(aPackURL);
return !aPackedFile.empty();
}
bool BackupFileHelper::tryPop_extensionInfo(
std::u16string_view rTargetURL // target dir without trailing '/'
)
{ // extensionInfo always exists internally, no test needed const OUString aPackURL(createPackURL(rTargetURL, u"ExtensionInfo"));
PackedFile aPackedFile(aPackURL);
if (aPackedFile.empty()) returnfalse;
oslFileHandle aHandle;
OUString aTempURL;
// open target temp file - it exists until deleted if (osl::File::E_None != osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) returnfalse;
bool bRetval(aPackedFile.tryPop(aHandle));
// close temp file (in all cases) - it exists until deleted
osl_closeFile(aHandle);
if (bRetval)
{ // last config is in temp file, load it to ExtensionInfo
ExtensionInfo aLoadedExtensionInfo;
FileSharedPtr aBaseFile = std::make_shared<osl::File>(aTempURL);
if (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read))
{ if (aLoadedExtensionInfo.read_entries(aBaseFile))
{ // get current extension info, but from XML config files
ExtensionInfo aCurrentExtensionInfo;
// now we have loaded last_working (aLoadedExtensionInfo) and // current (aCurrentExtensionInfo) ExtensionInfo and may react on // differences by de/activating these as needed const ExtensionInfoEntryVector& aUserEntries = aCurrentExtensionInfo.getExtensionInfoEntryVector(); const ExtensionInfoEntryVector& rLoadedVector = aLoadedExtensionInfo.getExtensionInfoEntryVector();
ExtensionInfoEntryVector aToBeDisabled;
ExtensionInfoEntryVector aToBeEnabled;
for (constauto& rLoadedInfo : rLoadedVector)
{ if (rCurrentInfo.isSameExtension(rLoadedInfo))
{
pLoadedInfo = &rLoadedInfo; break;
}
}
if (nullptr != pLoadedInfo)
{ // loaded info contains information about the Extension rCurrentInfo constbool bCurrentEnabled(rCurrentInfo.isEnabled()); constbool bLoadedEnabled(pLoadedInfo->isEnabled());
if (bCurrentEnabled && !bLoadedEnabled)
{
aToBeDisabled.push_back(rCurrentInfo);
} elseif (!bCurrentEnabled && bLoadedEnabled)
{
aToBeEnabled.push_back(rCurrentInfo);
}
} else
{ // There is no loaded info about the Extension rCurrentInfo. // It needs to be disabled if (rCurrentInfo.isEnabled())
{
aToBeDisabled.push_back(rCurrentInfo);
}
}
}
if (!aToBeDisabled.empty() || !aToBeEnabled.empty())
{
ExtensionInfo::changeEnableDisableStateInXML(maUserConfigWorkURL, aToBeEnabled, aToBeDisabled);
}
bRetval = true;
}
}
// reduce to allowed number and flush
aPackedFile.tryReduceToNumBackups(mnNumBackups);
aPackedFile.flush();
}
// delete temp file (in all cases - it may be moved already)
osl::File::remove(aTempURL);
// fill dir and file info list to work with dependent on work mode switch (mnMode)
{ case 0:
{ // simple mode: add just registrymodifications // (the orig file in maInitialBaseURL)
maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt)); break;
} case 1:
{ // defined mode: Add a selection of dirs containing User-Defined and thus // valuable configuration information. // This is clearly discussable in every single point and may be adapted/corrected // over time. Main focus is to secure User-Defined/adapted values
// add registrymodifications (the orig file in maInitialBaseURL)
maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt));
// 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 explicitly. This // should already include registrymodifications, too.
DirectoryHelper::scanDirsAndFiles(
maUserConfigWorkURL,
maDirs,
maFiles);
// should not exist, but for the case an error occurred and it got // copied somehow, avoid further recursive copying/saving
maDirs.erase(u"SafeMode"_ustr);
// not really needed, can be abandoned
maDirs.erase(u"psprint"_ustr);
// not really needed, can be abandoned
maDirs.erase(u"store"_ustr);
// not really needed, can be abandoned
maDirs.erase(u"temp"_ustr);
// exclude own backup dir to avoid recursion
maDirs.erase(u"pack"_ustr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.