2016-09-01 16:16:39 +02:00
|
|
|
/* -*- 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/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sal/config.h>
|
2016-10-12 13:25:54 +02:00
|
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
#include <com/sun/star/uno/Sequence.hxx>
|
|
|
|
#include <com/sun/star/uno/Reference.hxx>
|
|
|
|
#include <com/sun/star/deployment/XPackage.hpp>
|
|
|
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
|
|
|
#include <com/sun/star/deployment/XExtensionManager.hpp>
|
|
|
|
#include <com/sun/star/task/XAbortChannel.hpp>
|
|
|
|
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
|
|
|
|
#include <com/sun/star/deployment/ExtensionManager.hpp>
|
2016-09-01 16:16:39 +02:00
|
|
|
#include <rtl/ustring.hxx>
|
2016-09-23 18:21:54 +02:00
|
|
|
#include <rtl/bootstrap.hxx>
|
|
|
|
#include <comphelper/backupfilehelper.hxx>
|
|
|
|
#include <rtl/crc.h>
|
2016-10-12 10:55:53 +02:00
|
|
|
#include <algorithm>
|
2016-09-23 18:21:54 +02:00
|
|
|
#include <deque>
|
2016-10-12 13:25:54 +02:00
|
|
|
#include <vector>
|
2016-09-28 18:14:51 +02:00
|
|
|
#include <zlib.h>
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
using namespace css;
|
2016-09-28 18:14:51 +02:00
|
|
|
static const sal_uInt32 BACKUP_FILE_HELPER_BLOCK_SIZE = 16384;
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
namespace
|
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
typedef std::shared_ptr< osl::File > FileSharedPtr;
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
OUString splitAtLastToken(const OUString& rSrc, sal_Unicode aToken, OUString& rRight)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
const sal_Int32 nIndex(rSrc.lastIndexOf(aToken));
|
|
|
|
OUString aRetval;
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
if (-1 == nIndex)
|
|
|
|
{
|
|
|
|
aRetval = rSrc;
|
|
|
|
}
|
|
|
|
else if (nIndex > 0)
|
|
|
|
{
|
|
|
|
aRetval = rSrc.copy(0, nIndex);
|
|
|
|
}
|
2016-09-15 12:27:28 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
if (rSrc.getLength() > nIndex + 1)
|
|
|
|
{
|
|
|
|
rRight = rSrc.copy(nIndex + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return aRetval;
|
2016-09-15 12:27:28 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt32 createCrc32(FileSharedPtr& rCandidate, sal_uInt32 nOffset)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt32 nCrc32(0);
|
|
|
|
|
|
|
|
if (rCandidate && osl::File::E_None == rCandidate->open(osl_File_OpenFlag_Read))
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt64 nBytesTransfer(0);
|
|
|
|
sal_uInt64 nSize(0);
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
rCandidate->getSize(nSize);
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
rCandidate->close();
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
return nCrc32;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
|
|
|
|
bool read_sal_uInt32(FileSharedPtr& rFile, sal_uInt32& rTarget)
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[4];
|
|
|
|
sal_uInt64 nBaseRead(0);
|
|
|
|
|
|
|
|
// read rTarget
|
|
|
|
if (osl::File::E_None == rFile->read(static_cast<void*>(aArray), 4, nBaseRead) && 4 == nBaseRead)
|
|
|
|
{
|
2016-10-14 09:11:38 +01:00
|
|
|
//This is untainted data which comes from a controlled source
|
|
|
|
//so, using a byte-swapping pattern which coverity doesn't
|
|
|
|
//detect as such
|
|
|
|
//http://security.coverity.com/blog/2014/Apr/on-detecting-heartbleed-with-static-analysis.html
|
|
|
|
rTarget = aArray[0]; rTarget <<= 8;
|
|
|
|
rTarget |= aArray[1]; rTarget <<= 8;
|
|
|
|
rTarget |= aArray[2]; rTarget <<= 8;
|
|
|
|
rTarget |= aArray[3];
|
2016-10-12 13:25:54 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool write_sal_uInt32(oslFileHandle& rHandle, sal_uInt32 nSource)
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[4];
|
|
|
|
sal_uInt64 nBaseWritten(0);
|
|
|
|
|
|
|
|
// write nSource
|
|
|
|
aArray[0] = sal_uInt8((nSource & 0xff000000) >> 24);
|
|
|
|
aArray[1] = sal_uInt8((nSource & 0x00ff0000) >> 16);
|
|
|
|
aArray[2] = sal_uInt8((nSource & 0x0000ff00) >> 8);
|
|
|
|
aArray[3] = sal_uInt8(nSource & 0x000000ff);
|
|
|
|
|
|
|
|
if (osl_File_E_None == osl_writeFile(rHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_OString(FileSharedPtr& rFile, OString& rTarget)
|
|
|
|
{
|
|
|
|
sal_uInt32 nLength(0);
|
|
|
|
|
|
|
|
if (!read_sal_uInt32(rFile, nLength))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector< sal_Char > aTarget(nLength);
|
|
|
|
sal_uInt64 nBaseRead(0);
|
|
|
|
|
|
|
|
// read rTarget
|
|
|
|
if (osl::File::E_None == rFile->read(static_cast<void*>(&aTarget[0]), nLength, nBaseRead) && nLength == nBaseRead)
|
|
|
|
{
|
|
|
|
rTarget = OString(&aTarget[0], static_cast< sal_Int32 >(nLength));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool write_OString(oslFileHandle& rHandle, const OString& rSource)
|
|
|
|
{
|
|
|
|
const sal_uInt32 nLength(rSource.getLength());
|
|
|
|
|
|
|
|
if (!write_sal_uInt32(rHandle, nLength))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_uInt64 nBaseWritten(0);
|
|
|
|
|
|
|
|
if (osl_File_E_None == osl_writeFile(rHandle, static_cast<const void*>(rSource.getStr()), nLength, &nBaseWritten) && nLength == nBaseWritten)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
bool fileExists(const OUString& rBaseURL)
|
|
|
|
{
|
|
|
|
if (!rBaseURL.isEmpty())
|
|
|
|
{
|
|
|
|
FileSharedPtr aBaseFile(new osl::File(rBaseURL));
|
|
|
|
|
|
|
|
return (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read));
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-13 14:16:56 +02:00
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
bool dirExists(const OUString& rDirURL)
|
|
|
|
{
|
|
|
|
if (!rDirURL.isEmpty())
|
|
|
|
{
|
|
|
|
osl::Directory aDirectory(rDirURL);
|
|
|
|
|
|
|
|
return (osl::FileBase::E_None == aDirectory.open());
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
|
|
|
|
bool deleteDirRecursively(const OUString& rDirURL)
|
|
|
|
{
|
|
|
|
std::set< OUString > aDirs;
|
|
|
|
std::set< std::pair< OUString, OUString > > aFiles;
|
|
|
|
|
|
|
|
scanDirsAndFiles(
|
|
|
|
rDirURL,
|
|
|
|
aDirs,
|
|
|
|
aFiles);
|
|
|
|
|
|
|
|
for (const auto& dir : aDirs)
|
|
|
|
{
|
|
|
|
const OUString aNewDirURL(rDirURL + "/" + dir);
|
|
|
|
|
|
|
|
deleteDirRecursively(aNewDirURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& file : aFiles)
|
|
|
|
{
|
|
|
|
OUString aNewFileURL(rDirURL + "/" + file.first);
|
|
|
|
|
|
|
|
if (!file.second.isEmpty())
|
|
|
|
{
|
|
|
|
aNewFileURL += ".";
|
|
|
|
aNewFileURL += file.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
osl::File::remove(aNewFileURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return osl::FileBase::E_None == osl::Directory::remove(rDirURL);
|
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
enum PackageState { REGISTERED, NOT_REGISTERED, AMBIGUOUS, NOT_AVAILABLE };
|
|
|
|
|
|
|
|
class ExtensionInfoEntry
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
PackageState meState; // REGISTERED, NOT_REGISTERED, AMBIGUOUS, NOT_AVAILABLE
|
|
|
|
OString maRepositoryName; // user|shared|bundled
|
|
|
|
OString maName;
|
|
|
|
OString maIdentifier;
|
|
|
|
OString maVersion;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ExtensionInfoEntry()
|
|
|
|
: meState(NOT_AVAILABLE),
|
|
|
|
maRepositoryName(),
|
|
|
|
maName(),
|
|
|
|
maIdentifier(),
|
|
|
|
maVersion()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ExtensionInfoEntry(const uno::Reference< deployment::XPackage >& rxPackage)
|
|
|
|
: meState(NOT_AVAILABLE),
|
|
|
|
maRepositoryName(OUStringToOString(rxPackage->getRepositoryName(), RTL_TEXTENCODING_ASCII_US)),
|
|
|
|
maName(OUStringToOString(rxPackage->getName(), RTL_TEXTENCODING_ASCII_US)),
|
|
|
|
maIdentifier(OUStringToOString(rxPackage->getIdentifier().Value, RTL_TEXTENCODING_ASCII_US)),
|
|
|
|
maVersion(OUStringToOString(rxPackage->getVersion(), RTL_TEXTENCODING_ASCII_US))
|
|
|
|
{
|
|
|
|
const beans::Optional< beans::Ambiguous< sal_Bool > > option(
|
|
|
|
rxPackage->isRegistered(uno::Reference< task::XAbortChannel >(),
|
|
|
|
uno::Reference< ucb::XCommandEnvironment >()));
|
|
|
|
|
|
|
|
if (option.IsPresent)
|
|
|
|
{
|
|
|
|
::beans::Ambiguous< sal_Bool > const& reg = option.Value;
|
|
|
|
|
|
|
|
if (reg.IsAmbiguous)
|
|
|
|
{
|
|
|
|
meState = AMBIGUOUS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meState = reg.Value ? REGISTERED : NOT_REGISTERED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meState = NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator<(const ExtensionInfoEntry& rComp) const
|
|
|
|
{
|
|
|
|
if (0 == maRepositoryName.compareTo(rComp.maRepositoryName))
|
|
|
|
{
|
|
|
|
if (0 == maName.compareTo(rComp.maName))
|
|
|
|
{
|
|
|
|
if (0 == maVersion.compareTo(rComp.maVersion))
|
|
|
|
{
|
|
|
|
if (0 == maIdentifier.compareTo(rComp.maIdentifier))
|
|
|
|
{
|
|
|
|
return meState < rComp.meState;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0 > maIdentifier.compareTo(rComp.maIdentifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0 > maVersion.compareTo(rComp.maVersion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0 > maName.compareTo(rComp.maName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0 > maRepositoryName.compareTo(rComp.maRepositoryName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_entry(FileSharedPtr& rFile)
|
|
|
|
{
|
|
|
|
// read meState
|
|
|
|
sal_uInt32 nState(0);
|
|
|
|
|
|
|
|
if (read_sal_uInt32(rFile, nState))
|
|
|
|
{
|
|
|
|
meState = static_cast< PackageState >(nState);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read maRepositoryName;
|
|
|
|
if (!read_OString(rFile, maRepositoryName))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read maName;
|
|
|
|
if (!read_OString(rFile, maName))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read maIdentifier;
|
|
|
|
if (!read_OString(rFile, maIdentifier))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read maVersion;
|
|
|
|
if (!read_OString(rFile, maVersion))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool write_entry(oslFileHandle& rHandle) const
|
|
|
|
{
|
|
|
|
// write meState
|
|
|
|
const sal_uInt32 nState(meState);
|
|
|
|
|
|
|
|
if (!write_sal_uInt32(rHandle, nState))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write maRepositoryName
|
|
|
|
if (!write_OString(rHandle, maRepositoryName))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write maName;
|
|
|
|
if (!write_OString(rHandle, maName))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write maIdentifier;
|
|
|
|
if (!write_OString(rHandle, maIdentifier))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write maVersion;
|
|
|
|
if (!write_OString(rHandle, maVersion))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
|
|
|
|
bool isEnabled() const
|
|
|
|
{
|
|
|
|
return REGISTERED == meState;
|
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef ::std::vector< ExtensionInfoEntry > ExtensionInfoEntryVector;
|
|
|
|
|
|
|
|
class ExtensionInfo
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
ExtensionInfoEntryVector maEntries;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ExtensionInfo()
|
|
|
|
: maEntries()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
// clear all data
|
|
|
|
maEntries.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void createCurrent()
|
|
|
|
{
|
|
|
|
// clear all data
|
|
|
|
reset();
|
|
|
|
|
|
|
|
// create content from current extension configuration
|
|
|
|
uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
|
|
|
|
uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
|
|
|
|
uno::Reference< deployment::XExtensionManager > m_xExtensionManager = deployment::ExtensionManager::get(xContext);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
xAllPackages = m_xExtensionManager->getAllExtensions(uno::Reference< task::XAbortChannel >(),
|
|
|
|
uno::Reference< ucb::XCommandEnvironment >());
|
|
|
|
}
|
|
|
|
catch (const deployment::DeploymentException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const ucb::CommandFailedException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const ucb::CommandAbortedException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const lang::IllegalArgumentException & e)
|
|
|
|
{
|
|
|
|
throw uno::RuntimeException(e.Message, e.Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (sal_Int32 i = 0; i < xAllPackages.getLength(); ++i)
|
|
|
|
{
|
|
|
|
uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
|
|
|
|
|
|
|
|
for (sal_Int32 j = 0; j < xPackageList.getLength(); ++j)
|
|
|
|
{
|
|
|
|
uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
|
|
|
|
|
|
|
|
if (xPackage.is())
|
|
|
|
{
|
|
|
|
maEntries.push_back(ExtensionInfoEntry(xPackage));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!maEntries.empty())
|
|
|
|
{
|
|
|
|
// sort the list
|
|
|
|
std::sort(maEntries.begin(), maEntries.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_entries(FileSharedPtr& rFile)
|
|
|
|
{
|
|
|
|
// read NumExtensionEntries
|
|
|
|
sal_uInt32 nExtEntries(0);
|
|
|
|
|
|
|
|
if (!read_sal_uInt32(rFile, nExtEntries))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (sal_uInt32 a(0); a < nExtEntries; a++)
|
|
|
|
{
|
|
|
|
ExtensionInfoEntry aNewEntry;
|
|
|
|
|
|
|
|
if (aNewEntry.read_entry(rFile))
|
|
|
|
{
|
|
|
|
maEntries.push_back(aNewEntry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool write_entries(oslFileHandle& rHandle) const
|
|
|
|
{
|
|
|
|
const sal_uInt32 nExtEntries(maEntries.size());
|
|
|
|
|
|
|
|
if (!write_sal_uInt32(rHandle, nExtEntries))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& a : maEntries)
|
|
|
|
{
|
|
|
|
if (!a.write_entry(rHandle))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool createTempFile(OUString& rTempFileName)
|
|
|
|
{
|
|
|
|
oslFileHandle aHandle;
|
|
|
|
bool bRetval(false);
|
|
|
|
|
|
|
|
// create current configuration
|
|
|
|
if (maEntries.empty())
|
|
|
|
{
|
|
|
|
createCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
|
|
|
|
bool areThereEnabledExtensions() const
|
|
|
|
{
|
|
|
|
for (const auto& a : maEntries)
|
|
|
|
{
|
|
|
|
if (a.isEnabled())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void disableAll()
|
|
|
|
{
|
|
|
|
// create content from current extension configuration
|
|
|
|
uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
|
|
|
|
uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
|
|
|
|
uno::Reference< deployment::XExtensionManager > m_xExtensionManager = deployment::ExtensionManager::get(xContext);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
xAllPackages = m_xExtensionManager->getAllExtensions(uno::Reference< task::XAbortChannel >(),
|
|
|
|
uno::Reference< ucb::XCommandEnvironment >());
|
|
|
|
}
|
|
|
|
catch (const deployment::DeploymentException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const ucb::CommandFailedException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const ucb::CommandAbortedException &)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch (const lang::IllegalArgumentException & e)
|
|
|
|
{
|
|
|
|
throw uno::RuntimeException(e.Message, e.Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (sal_Int32 i = 0; i < xAllPackages.getLength(); ++i)
|
|
|
|
{
|
|
|
|
uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
|
|
|
|
|
|
|
|
for (sal_Int32 j = 0; j < xPackageList.getLength(); ++j)
|
|
|
|
{
|
|
|
|
uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
|
|
|
|
|
|
|
|
if (xPackage.is())
|
|
|
|
{
|
|
|
|
const beans::Optional< beans::Ambiguous< sal_Bool > > option(
|
|
|
|
xPackage->isRegistered(uno::Reference< task::XAbortChannel >(),
|
|
|
|
uno::Reference< ucb::XCommandEnvironment >()));
|
|
|
|
bool bEnabled(false);
|
|
|
|
|
|
|
|
if (option.IsPresent)
|
|
|
|
{
|
|
|
|
::beans::Ambiguous< sal_Bool > const& reg = option.Value;
|
|
|
|
|
|
|
|
if (!reg.IsAmbiguous)
|
|
|
|
{
|
|
|
|
bEnabled = reg.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bEnabled)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
m_xExtensionManager->disableExtension(
|
|
|
|
xPackage,
|
|
|
|
uno::Reference< task::XAbortChannel >(),
|
|
|
|
uno::Reference< ucb::XCommandEnvironment >());
|
|
|
|
}
|
|
|
|
catch (const ::ucb::CommandAbortedException &)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
};
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
namespace
|
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
class PackedFileEntry
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
private:
|
2016-10-12 13:25:54 +02:00
|
|
|
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)
|
|
|
|
bool mbDoCompress; // flag if this file is scheduled to be compredded when written
|
2016-09-28 18:14:51 +02:00
|
|
|
|
|
|
|
bool copy_content_straight(oslFileHandle& rTargetHandle)
|
|
|
|
{
|
|
|
|
if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt64 nBytesTransfer(0);
|
2016-09-29 18:00:35 +02:00
|
|
|
sal_uInt64 nSize(getPackFileSize());
|
2016-09-28 18:14:51 +02:00
|
|
|
|
|
|
|
// 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 (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nSize -= nToTransfer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
maFile->close();
|
|
|
|
return (0 == nSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copy_content_compress(oslFileHandle& rTargetHandle)
|
|
|
|
{
|
|
|
|
if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt64 nBytesTransfer(0);
|
2016-09-29 18:00:35 +02:00
|
|
|
sal_uInt64 nSize(getPackFileSize());
|
2016-09-28 18:14:51 +02:00
|
|
|
std::unique_ptr< z_stream > zstream(new z_stream);
|
|
|
|
memset(zstream.get(), 0, sizeof(*zstream));
|
|
|
|
|
|
|
|
if (Z_OK == deflateInit(zstream.get(), 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);
|
|
|
|
|
|
|
|
while (bOkay && nSize != 0)
|
|
|
|
{
|
|
|
|
const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
|
|
|
|
|
|
|
|
if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
zstream->avail_in = nToTransfer;
|
|
|
|
zstream->next_in = reinterpret_cast<unsigned char*>(aArray);
|
|
|
|
|
|
|
|
do {
|
|
|
|
zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
|
|
|
|
zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
|
|
|
|
#if !defined Z_PREFIX
|
|
|
|
const sal_Int64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
|
|
|
|
#else
|
|
|
|
const sal_Int64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH));
|
|
|
|
#endif
|
|
|
|
if (Z_STREAM_ERROR == nRetval)
|
|
|
|
{
|
|
|
|
bOkay = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
|
|
|
|
|
|
|
|
if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
|
|
|
|
{
|
|
|
|
bOkay = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (bOkay && 0 == zstream->avail_out);
|
|
|
|
|
|
|
|
if (!bOkay)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nSize -= nToTransfer;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined Z_PREFIX
|
|
|
|
deflateEnd(zstream.get());
|
|
|
|
#else
|
|
|
|
z_deflateEnd(zstream.get());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
maFile->close();
|
|
|
|
|
|
|
|
// get compressed size and add to entry
|
|
|
|
if (mnFullFileSize == mnPackFileSize && mnFullFileSize == zstream->total_in)
|
|
|
|
{
|
|
|
|
mnPackFileSize = zstream->total_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0 == nSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copy_content_uncompress(oslFileHandle& rTargetHandle)
|
|
|
|
{
|
|
|
|
if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read))
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE];
|
|
|
|
sal_uInt64 nBytesTransfer(0);
|
|
|
|
sal_uInt64 nSize(getPackFileSize());
|
|
|
|
std::unique_ptr< z_stream > zstream(new z_stream);
|
|
|
|
memset(zstream.get(), 0, sizeof(*zstream));
|
|
|
|
|
|
|
|
if (Z_OK == inflateInit(zstream.get()))
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
while (bOkay && nSize != 0)
|
|
|
|
{
|
|
|
|
const sal_uInt64 nToTransfer(std::min(nSize, (sal_uInt64)BACKUP_FILE_HELPER_BLOCK_SIZE));
|
|
|
|
|
|
|
|
if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
zstream->avail_in = nToTransfer;
|
|
|
|
zstream->next_in = reinterpret_cast<unsigned char*>(aArray);
|
|
|
|
|
|
|
|
do {
|
|
|
|
zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE;
|
|
|
|
zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer);
|
|
|
|
#if !defined Z_PREFIX
|
|
|
|
const sal_Int64 nRetval(inflate(zstream.get(), Z_NO_FLUSH));
|
|
|
|
#else
|
|
|
|
const sal_Int64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH));
|
|
|
|
#endif
|
|
|
|
if (Z_STREAM_ERROR == nRetval)
|
|
|
|
{
|
|
|
|
bOkay = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out);
|
|
|
|
|
|
|
|
if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable)
|
|
|
|
{
|
|
|
|
bOkay = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (bOkay && 0 == zstream->avail_out);
|
|
|
|
|
|
|
|
if (!bOkay)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nSize -= nToTransfer;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined Z_PREFIX
|
|
|
|
deflateEnd(zstream.get());
|
|
|
|
#else
|
|
|
|
z_deflateEnd(zstream.get());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
maFile->close();
|
|
|
|
return (0 == nSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
public:
|
2016-09-29 18:00:35 +02:00
|
|
|
// create new, uncompressed entry
|
2016-09-23 18:21:54 +02:00
|
|
|
PackedFileEntry(
|
2016-09-28 18:14:51 +02:00
|
|
|
sal_uInt32 nFullFileSize,
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt32 nCrc32,
|
2016-09-28 18:14:51 +02:00
|
|
|
FileSharedPtr& rFile,
|
|
|
|
bool bDoCompress)
|
|
|
|
: mnFullFileSize(nFullFileSize),
|
|
|
|
mnPackFileSize(nFullFileSize),
|
2016-09-29 18:00:35 +02:00
|
|
|
mnOffset(0),
|
2016-09-23 18:21:54 +02:00
|
|
|
mnCrc32(nCrc32),
|
2016-09-28 18:14:51 +02:00
|
|
|
maFile(rFile),
|
|
|
|
mbDoCompress(bDoCompress)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-29 18:00:35 +02:00
|
|
|
// create entry to be loaded as header (read_header)
|
2016-09-23 18:21:54 +02:00
|
|
|
PackedFileEntry()
|
2016-09-28 18:14:51 +02:00
|
|
|
: mnFullFileSize(0),
|
|
|
|
mnPackFileSize(0),
|
2016-09-23 18:21:54 +02:00
|
|
|
mnOffset(0),
|
|
|
|
mnCrc32(0),
|
2016-09-28 18:14:51 +02:00
|
|
|
maFile(),
|
|
|
|
mbDoCompress(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_uInt32 getFullFileSize() const
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
return mnFullFileSize;
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
sal_uInt32 getPackFileSize() const
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
return mnPackFileSize;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt32 getOffset() const
|
|
|
|
{
|
|
|
|
return mnOffset;
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
void setOffset(sal_uInt32 nOffset)
|
|
|
|
{
|
|
|
|
mnOffset = nOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static sal_uInt32 getEntrySize()
|
|
|
|
{
|
|
|
|
return 12;
|
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt32 getCrc32() const
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
return mnCrc32;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
bool read_header(FileSharedPtr& rFile)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
if (!rFile)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
return false;
|
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
maFile = rFile;
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// read and compute full file size
|
|
|
|
if (!read_sal_uInt32(rFile, mnFullFileSize))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-28 18:14:51 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// read and compute entry crc32
|
|
|
|
if (!read_sal_uInt32(rFile, mnCrc32))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// read and compute packed size
|
|
|
|
if (!read_sal_uInt32(rFile, mnPackFileSize))
|
|
|
|
{
|
|
|
|
return false;
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
return true;
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
bool write_header(oslFileHandle& rHandle) const
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// write full file size
|
2016-10-12 13:25:54 +02:00
|
|
|
if (!write_sal_uInt32(rHandle, mnFullFileSize))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
// write crc32
|
2016-10-12 13:25:54 +02:00
|
|
|
if (!write_sal_uInt32(rHandle, mnCrc32))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
// write packed file size
|
2016-10-12 13:25:54 +02:00
|
|
|
if (!write_sal_uInt32(rHandle, mnPackFileSize))
|
2016-09-28 18:14:51 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
return true;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
bool copy_content(oslFileHandle& rTargetHandle, bool bUncompress)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
if (bUncompress)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
if (getFullFileSize() == getPackFileSize())
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// not compressed, just copy
|
|
|
|
return copy_content_straight(rTargetHandle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// compressed, need to uncompress on copy
|
|
|
|
return copy_content_uncompress(rTargetHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (0 == getOffset())
|
|
|
|
{
|
|
|
|
if (mbDoCompress)
|
|
|
|
{
|
|
|
|
// compressed wanted, need to compress on copy
|
|
|
|
return copy_content_compress(rTargetHandle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not compressed, straight copy
|
|
|
|
return copy_content_straight(rTargetHandle);
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
return copy_content_straight(rTargetHandle);
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
typedef ::std::deque< PackedFileEntry > PackedFileEntryVector;
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
class PackedFile
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
private:
|
|
|
|
const OUString maURL;
|
|
|
|
PackedFileEntryVector maPackedFileEntryVector;
|
|
|
|
bool mbChanged;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PackedFile(const OUString& rURL)
|
|
|
|
: maURL(rURL),
|
|
|
|
maPackedFileEntryVector(),
|
|
|
|
mbChanged(false)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
FileSharedPtr aSourceFile(new osl::File(rURL));
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
if (osl::File::E_None == aSourceFile->open(osl_File_OpenFlag_Read))
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
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++)
|
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// create new entry, read header (size, crc and PackedSize),
|
2016-09-23 18:21:54 +02:00
|
|
|
// set offset and source file
|
|
|
|
PackedFileEntry aEntry;
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
if (aEntry.read_header(aSourceFile))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
|
|
|
// add to local data
|
|
|
|
maPackedFileEntryVector.push_back(aEntry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// error
|
|
|
|
nEntries = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == nEntries)
|
|
|
|
{
|
|
|
|
// on read error clear local data
|
|
|
|
maPackedFileEntryVector.clear();
|
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// calculate and set offsets to file binary content
|
|
|
|
sal_uInt32 nHeaderSize(8);
|
|
|
|
|
|
|
|
nHeaderSize += maPackedFileEntryVector.size() * PackedFileEntry::getEntrySize();
|
|
|
|
|
|
|
|
sal_uInt32 nOffset(nHeaderSize);
|
|
|
|
|
|
|
|
for (auto& b : maPackedFileEntryVector)
|
|
|
|
{
|
|
|
|
b.setOffset(nOffset);
|
|
|
|
nOffset += b.getPackFileSize();
|
|
|
|
}
|
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aSourceFile->close();
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
if (maPackedFileEntryVector.empty())
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
// on error or no data get rid of pack file
|
|
|
|
osl::File::remove(maURL);
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
bool flush()
|
|
|
|
{
|
|
|
|
bool bRetval(true);
|
|
|
|
|
|
|
|
if (maPackedFileEntryVector.empty())
|
|
|
|
{
|
|
|
|
// get rid of (now?) empty pack file
|
|
|
|
osl::File::remove(maURL);
|
|
|
|
}
|
|
|
|
else if (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;
|
|
|
|
OUString aTempURL;
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// open target temp file - it exists until deleted
|
2016-09-23 18:21:54 +02:00
|
|
|
if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
|
|
|
|
{
|
|
|
|
sal_uInt8 aArray[4];
|
|
|
|
sal_uInt64 nBaseWritten(0);
|
|
|
|
|
|
|
|
aArray[0] = 'P';
|
|
|
|
aArray[1] = 'A';
|
|
|
|
aArray[2] = 'C';
|
|
|
|
aArray[3] = 'K';
|
|
|
|
|
|
|
|
// write File_ID
|
|
|
|
if (osl_File_E_None == osl_writeFile(aHandle, static_cast<const void*>(aArray), 4, &nBaseWritten) && 4 == nBaseWritten)
|
|
|
|
{
|
|
|
|
const sal_uInt32 nSize(maPackedFileEntryVector.size());
|
|
|
|
|
|
|
|
// write number of entries
|
2016-10-12 13:25:54 +02:00
|
|
|
if (write_sal_uInt32(aHandle, nSize))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
if (bRetval)
|
|
|
|
{
|
|
|
|
// 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
|
2016-10-12 13:25:54 +02:00
|
|
|
// is written. To do so, write placeholders here
|
|
|
|
sal_uInt32 nWriteSize(0);
|
|
|
|
|
|
|
|
nWriteSize += maPackedFileEntryVector.size() * PackedFileEntry::getEntrySize();
|
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
aArray[0] = aArray[1] = aArray[2] = aArray[3] = 0;
|
|
|
|
|
|
|
|
for (sal_uInt32 a(0); bRetval && a < nWriteSize; a++)
|
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
if (osl_File_E_None != osl_writeFile(aHandle, static_cast<const void*>(aArray), 1, &nBaseWritten) || 1 != nBaseWritten)
|
2016-09-28 18:14:51 +02:00
|
|
|
{
|
|
|
|
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)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// seek back to header start (at position 8)
|
|
|
|
if (osl_File_E_None != osl_setFilePos(aHandle, osl_Pos_Absolut, sal_Int64(8)))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
|
|
|
bRetval = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bRetval)
|
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// write headers
|
|
|
|
for (auto& candidate : maPackedFileEntryVector)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
if (!candidate.write_header(aHandle))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-09-28 18:14:51 +02:00
|
|
|
// error
|
2016-09-23 18:21:54 +02:00
|
|
|
bRetval = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// close temp file (in all cases) - it exists until deleted
|
2016-09-23 18:21:54 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRetval;
|
|
|
|
}
|
|
|
|
|
2016-09-29 18:00:35 +02:00
|
|
|
bool tryPush(FileSharedPtr& rFileCandidate, bool bCompress)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
sal_uInt64 nFileSize(0);
|
|
|
|
|
|
|
|
if (rFileCandidate && osl::File::E_None == rFileCandidate->open(osl_File_OpenFlag_Read))
|
|
|
|
{
|
|
|
|
rFileCandidate->getSize(nFileSize);
|
|
|
|
rFileCandidate->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == nFileSize)
|
|
|
|
{
|
|
|
|
// empty file offered
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
bool bNeedToAdd(false);
|
|
|
|
sal_uInt32 nCrc32(0);
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
if (maPackedFileEntryVector.empty())
|
|
|
|
{
|
|
|
|
// no backup yet, add as 1st backup
|
|
|
|
bNeedToAdd = true;
|
|
|
|
}
|
|
|
|
else
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
// already backups there, check if different from last entry
|
|
|
|
const PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// check if file is different
|
2016-09-28 18:14:51 +02:00
|
|
|
if (aLastEntry.getFullFileSize() != static_cast<sal_uInt32>(nFileSize))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
if (bNeedToAdd)
|
|
|
|
{
|
|
|
|
// create crc32 if not yet done
|
|
|
|
if (0 == nCrc32)
|
|
|
|
{
|
|
|
|
nCrc32 = createCrc32(rFileCandidate, 0);
|
|
|
|
}
|
|
|
|
|
2016-09-29 18:00:35 +02:00
|
|
|
// create a file entry for a new file. Offset is set automatically
|
|
|
|
// to 0 to mark the entry as new file entry
|
2016-09-23 18:21:54 +02:00
|
|
|
maPackedFileEntryVector.push_back(
|
|
|
|
PackedFileEntry(
|
|
|
|
static_cast< sal_uInt32 >(nFileSize),
|
|
|
|
nCrc32,
|
2016-09-28 18:14:51 +02:00
|
|
|
rFileCandidate,
|
2016-09-29 18:00:35 +02:00
|
|
|
bCompress));
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
mbChanged = true;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
return bNeedToAdd;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
bool tryPop(oslFileHandle& rHandle)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
bool bRetval(false);
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
if (!maPackedFileEntryVector.empty())
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
// already backups there, check if different from last entry
|
|
|
|
PackedFileEntry& aLastEntry = maPackedFileEntryVector.back();
|
|
|
|
|
2016-09-28 18:14:51 +02:00
|
|
|
// here the uncompress flag has to be determined, true
|
|
|
|
// means to add the file compressed, false means to add it
|
|
|
|
// uncompressed
|
|
|
|
bRetval = aLastEntry.copy_content(rHandle, true);
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
if (bRetval)
|
|
|
|
{
|
|
|
|
maPackedFileEntryVector.pop_back();
|
|
|
|
mbChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRetval;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryReduceToNumBackups(sal_uInt16 nNumBackups)
|
|
|
|
{
|
|
|
|
while (maPackedFileEntryVector.size() > nNumBackups)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
maPackedFileEntryVector.pop_front();
|
|
|
|
mbChanged = true;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
bool empty()
|
|
|
|
{
|
|
|
|
return maPackedFileEntryVector.empty();
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
};
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
namespace comphelper
|
|
|
|
{
|
|
|
|
sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
|
|
|
|
bool BackupFileHelper::mbExitWasCalled = false;
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
BackupFileHelper::BackupFileHelper()
|
|
|
|
: maInitialBaseURL(),
|
|
|
|
maUserConfigBaseURL(),
|
|
|
|
maRegModName(),
|
|
|
|
maExt(),
|
|
|
|
maDirs(),
|
|
|
|
maFiles(),
|
|
|
|
mnNumBackups(2),
|
2016-10-13 18:31:51 +02:00
|
|
|
mnMode(1),
|
2016-10-13 14:16:56 +02:00
|
|
|
mbActive(false),
|
|
|
|
mbExtensions(true),
|
|
|
|
mbCompress(true)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
OUString sTokenOut;
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// read configuration item 'SecureUserConfig' -> bool on/off
|
|
|
|
if (rtl::Bootstrap::get("SecureUserConfig", sTokenOut))
|
|
|
|
{
|
|
|
|
mbActive = sTokenOut.toBoolean();
|
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive && rtl::Bootstrap::get("SecureUserConfigNumCopies", sTokenOut))
|
|
|
|
{
|
|
|
|
const sal_uInt16 nConfigNumCopies(static_cast<sal_uInt16>(sTokenOut.toUInt32()));
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// limit to range [1..mnMaxAllowedBackups]
|
|
|
|
mnNumBackups = ::std::min(::std::max(nConfigNumCopies, mnNumBackups), mnMaxAllowedBackups);
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive && rtl::Bootstrap::get("SecureUserConfigMode", sTokenOut))
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const sal_uInt16 nMode(static_cast<sal_uInt16>(sTokenOut.toUInt32()));
|
|
|
|
|
|
|
|
// limit to range [0..2]
|
|
|
|
mnMode = ::std::min(nMode, sal_uInt16(2));
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive && rtl::Bootstrap::get("SecureUserConfigExtensions", sTokenOut))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
mbExtensions = sTokenOut.toBoolean();
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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();
|
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
void BackupFileHelper::setExitWasCalled()
|
|
|
|
{
|
|
|
|
mbExitWasCalled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::getExitWasCalled()
|
|
|
|
{
|
|
|
|
return mbExitWasCalled;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::tryPush()
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
bool bDidPush(false);
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aPackURL(getPackURL());
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// ensure dir and file vectors
|
|
|
|
fillDirFileInfo();
|
|
|
|
|
|
|
|
// proccess all files in question recursively
|
|
|
|
if (!maDirs.empty() || !maFiles.empty())
|
|
|
|
{
|
|
|
|
bDidPush = tryPush_Files(
|
|
|
|
maDirs,
|
|
|
|
maFiles,
|
|
|
|
maUserConfigBaseURL,
|
|
|
|
aPackURL);
|
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
return bDidPush;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::tryPushExtensionInfo()
|
|
|
|
{
|
|
|
|
bool bDidPush(false);
|
|
|
|
|
|
|
|
if (mbActive && mbExtensions)
|
|
|
|
{
|
|
|
|
const OUString aPackURL(getPackURL());
|
|
|
|
|
|
|
|
bDidPush = tryPush_extensionInfo(aPackURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return bDidPush;
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
bool BackupFileHelper::isPopPossible()
|
|
|
|
{
|
|
|
|
bool bPopPossible(false);
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
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);
|
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
return bPopPossible;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::isPopPossibleExtensionInfo()
|
|
|
|
{
|
|
|
|
bool bPopPossible(false);
|
|
|
|
|
|
|
|
if (mbActive && mbExtensions)
|
|
|
|
{
|
|
|
|
const OUString aPackURL(getPackURL());
|
|
|
|
|
|
|
|
bPopPossible = isPopPossible_extensionInfo(aPackURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return bPopPossible;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::tryPop()
|
|
|
|
{
|
|
|
|
bool bDidPop(false);
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (mbActive)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
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);
|
|
|
|
}
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
if (bDidPop)
|
2016-10-13 14:16:56 +02:00
|
|
|
{
|
2016-10-13 18:31:51 +02:00
|
|
|
// try removal of evtl. empty directory
|
|
|
|
osl::Directory::remove(aPackURL);
|
2016-10-13 14:16:56 +02:00
|
|
|
}
|
2016-10-13 18:31:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return bDidPop;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::tryPopExtensionInfo()
|
|
|
|
{
|
|
|
|
bool bDidPop(false);
|
|
|
|
|
|
|
|
if (mbActive && mbExtensions)
|
|
|
|
{
|
|
|
|
const OUString aPackURL(getPackURL());
|
|
|
|
|
|
|
|
bDidPop = tryPop_extensionInfo(aPackURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
|
|
|
if (bDidPop)
|
|
|
|
{
|
|
|
|
// try removal of evtl. empty directory
|
2016-10-13 14:16:56 +02:00
|
|
|
osl::Directory::remove(aPackURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDidPop;
|
|
|
|
}
|
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
bool BackupFileHelper::isTryDisableAllExtensionsPossible()
|
|
|
|
{
|
|
|
|
// return true if there is an eabled extension that can be disabled
|
|
|
|
ExtensionInfo aCurrentExtensionInfo;
|
|
|
|
|
|
|
|
aCurrentExtensionInfo.createCurrent();
|
|
|
|
return aCurrentExtensionInfo.areThereEnabledExtensions();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackupFileHelper::tryDisableAllExtensions()
|
|
|
|
{
|
|
|
|
// disable all still enabled extensions. No need to
|
|
|
|
// createCurrent() again, just do it now
|
|
|
|
ExtensionInfo::disableAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackupFileHelper::isTryResetCustomizationsPossible()
|
|
|
|
{
|
|
|
|
// return true if not all of the customization selection dirs are deleted
|
|
|
|
return
|
|
|
|
dirExists(maUserConfigBaseURL + "/config") || // UI config stuff
|
|
|
|
dirExists(maUserConfigBaseURL + "/registry") || // most of the registry stuff
|
|
|
|
dirExists(maUserConfigBaseURL + "/psprint") || // not really needed, can be abandoned
|
|
|
|
dirExists(maUserConfigBaseURL + "/store") || // not really needed, can be abandoned
|
|
|
|
dirExists(maUserConfigBaseURL + "/temp") || // not really needed, can be abandoned
|
|
|
|
dirExists(maUserConfigBaseURL + "/pack") || // own backup dir
|
|
|
|
fileExists(maUserConfigBaseURL + "/registrymodifications.xcu"); // personal registry stuff
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackupFileHelper::tryResetCustomizations()
|
|
|
|
{
|
|
|
|
// delete all of the customization selection dirs
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/config");
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/registry");
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/psprint");
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/store");
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/temp");
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL + "/pack");
|
|
|
|
osl::File::remove(maUserConfigBaseURL + "/registrymodifications.xcu");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackupFileHelper::tryResetUserProfile()
|
|
|
|
{
|
|
|
|
// completely delete the current UserProfile
|
|
|
|
deleteDirRecursively(maUserConfigBaseURL);
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
/////////////////// 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 '/'
|
|
|
|
)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
bool bDidPush(false);
|
|
|
|
osl::Directory::createPath(rTargetURL);
|
|
|
|
|
|
|
|
// proccess files
|
|
|
|
for (const auto& file : rFiles)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
bDidPush |= tryPush_file(
|
|
|
|
rSourceURL,
|
|
|
|
rTargetURL,
|
|
|
|
file.first,
|
|
|
|
file.second);
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// 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;
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
scanDirsAndFiles(
|
|
|
|
aNewSourceURL,
|
|
|
|
aNewDirs,
|
|
|
|
aNewFiles);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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;
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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)
|
|
|
|
)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aFileURL(createFileURL(rSourceURL, rName, rExt));
|
|
|
|
|
|
|
|
if (fileExists(aFileURL))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aPackURL(createPackURL(rTargetURL, rName));
|
|
|
|
PackedFile aPackedFile(aPackURL);
|
|
|
|
FileSharedPtr aBaseFile(new osl::File(aFileURL));
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (aPackedFile.tryPush(aBaseFile, mbCompress))
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
// reduce to allowed number and flush
|
|
|
|
aPackedFile.tryReduceToNumBackups(mnNumBackups);
|
|
|
|
aPackedFile.flush();
|
|
|
|
|
|
|
|
return true;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
/////////////////// 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 '/'
|
|
|
|
)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
bool bPopPossible(false);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// proccess files
|
|
|
|
for (const auto& file : rFiles)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
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);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
if (!aNewDirs.empty() || !aNewFiles.empty())
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
bPopPossible |= isPopPossible_files(
|
|
|
|
aNewDirs,
|
|
|
|
aNewFiles,
|
|
|
|
aNewSourceURL,
|
|
|
|
aNewTargetURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
return bPopPossible;
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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)
|
|
|
|
)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aFileURL(createFileURL(rSourceURL, rName, rExt));
|
|
|
|
|
|
|
|
if (fileExists(aFileURL))
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aPackURL(createPackURL(rTargetURL, rName));
|
|
|
|
PackedFile aPackedFile(aPackURL);
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
return !aPackedFile.empty();
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
/////////////////// 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 '/'
|
|
|
|
)
|
2016-10-12 13:25:54 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
bool bDidPop(false);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// 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;
|
2016-10-12 13:25:54 +02:00
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
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)
|
|
|
|
)
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aFileURL(createFileURL(rSourceURL, rName, rExt));
|
|
|
|
|
|
|
|
if (fileExists(aFileURL))
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-10-13 14:16:56 +02:00
|
|
|
// try Pop for base file
|
|
|
|
const OUString aPackURL(createPackURL(rTargetURL, rName));
|
|
|
|
PackedFile aPackedFile(aPackURL);
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
if (!aPackedFile.empty())
|
2016-09-01 16:16:39 +02:00
|
|
|
{
|
2016-09-23 18:21:54 +02:00
|
|
|
oslFileHandle aHandle;
|
|
|
|
OUString aTempURL;
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// open target temp file - it exists until deleted
|
2016-09-23 18:21:54 +02:00
|
|
|
if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
|
|
|
|
{
|
|
|
|
bool bRetval(aPackedFile.tryPop(aHandle));
|
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// close temp file (in all cases) - it exists until deleted
|
2016-09-23 18:21:54 +02:00
|
|
|
osl_closeFile(aHandle);
|
|
|
|
|
|
|
|
if (bRetval)
|
|
|
|
{
|
|
|
|
// copy over existing file by first deleting original
|
|
|
|
// and moving the temp file to old original
|
2016-10-13 14:16:56 +02:00
|
|
|
osl::File::remove(aFileURL);
|
|
|
|
osl::File::move(aTempURL, aFileURL);
|
2016-09-23 18:21:54 +02:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
return bRetval;
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-09-23 18:21:54 +02:00
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
/////////////////// 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 '/'
|
|
|
|
)
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
// extensionInfo always exists internally, no test needed
|
2016-10-13 14:16:56 +02:00
|
|
|
const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo"));
|
|
|
|
PackedFile aPackedFile(aPackURL);
|
2016-10-12 13:25:54 +02:00
|
|
|
|
|
|
|
if (!aPackedFile.empty())
|
2016-09-23 18:21:54 +02:00
|
|
|
{
|
2016-10-12 13:25:54 +02:00
|
|
|
oslFileHandle aHandle;
|
|
|
|
OUString aTempURL;
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// open target temp file - it exists until deleted
|
|
|
|
if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL))
|
|
|
|
{
|
|
|
|
bool bRetval(aPackedFile.tryPop(aHandle));
|
2016-09-01 16:16:39 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
// close temp file (in all cases) - it exists until deleted
|
|
|
|
osl_closeFile(aHandle);
|
2016-09-23 18:21:54 +02:00
|
|
|
|
2016-10-12 13:25:54 +02:00
|
|
|
if (bRetval)
|
|
|
|
{
|
|
|
|
// last config is in temp file, load it to ExtensionInfo
|
|
|
|
ExtensionInfo aLoadedExtensionInfo;
|
|
|
|
FileSharedPtr aBaseFile(new osl::File(aTempURL));
|
|
|
|
|
|
|
|
if (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read))
|
|
|
|
{
|
|
|
|
if (aLoadedExtensionInfo.read_entries(aBaseFile))
|
|
|
|
{
|
|
|
|
ExtensionInfo aCurrentExtensionInfo;
|
|
|
|
|
|
|
|
aCurrentExtensionInfo.createCurrent();
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// now we have loaded last_working (aLoadedExtensionInfo) and
|
|
|
|
// current (aCurrentExtensionInfo) ExtensionInfo and may react on
|
|
|
|
// differences by de/activating these as needed
|
2016-10-12 13:25:54 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
return bRetval;
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 18:21:54 +02:00
|
|
|
return false;
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
2016-10-13 14:16:56 +02:00
|
|
|
|
|
|
|
/////////////////// FileDirInfo helpers ///////////////////////
|
|
|
|
|
|
|
|
void BackupFileHelper::fillDirFileInfo()
|
|
|
|
{
|
|
|
|
if (!maDirs.empty() || !maFiles.empty())
|
|
|
|
{
|
|
|
|
// already done
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
// Information about the configuration and the role/purpose of directories in
|
|
|
|
// the UserConfiguration is taken from: https://wiki.documentfoundation.org/UserProfile
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// fill dir and file info list to work with dependent on work mode
|
|
|
|
switch (mnMode)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
2016-10-13 18:31:51 +02:00
|
|
|
// simple mode: add just registrymodifications
|
|
|
|
// (the orig file in maInitialBaseURL)
|
2016-10-13 14:16:56 +02:00
|
|
|
maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
{
|
2016-10-13 18:31:51 +02:00
|
|
|
// defined mode: Add a selection of dirs containing User-Defined and thus
|
|
|
|
// valuable configuration information.
|
2016-10-13 14:16:56 +02:00
|
|
|
// This is clearly discussable in every single point and may be adapted/corrected
|
|
|
|
// over time. Main focus is to secure User-Defined/adapted values
|
|
|
|
|
2016-10-13 18:31:51 +02:00
|
|
|
// add registrymodifications (the orig file in maInitialBaseURL)
|
|
|
|
maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt));
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
// 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
|
2016-10-13 18:31:51 +02:00
|
|
|
//
|
2016-10-13 14:16:56 +02:00
|
|
|
// 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");
|
2016-10-13 18:31:51 +02:00
|
|
|
|
|
|
|
// exclude own backup dir to avoid recursion
|
|
|
|
maDirs.erase("pack");
|
|
|
|
|
2016-10-13 14:16:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-01 16:16:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|