mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-20 12:46:44 +01:00
194 lines
5.4 KiB
C++
194 lines
5.4 KiB
C++
![]() |
//
|
||
|
// ZipManipulator.cpp
|
||
|
//
|
||
|
// $Id: //poco/1.4/Zip/src/ZipManipulator.cpp#1 $
|
||
|
//
|
||
|
// Library: Zip
|
||
|
// Package: Manipulation
|
||
|
// Module: ZipManipulator
|
||
|
//
|
||
|
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
|
||
|
// and Contributors.
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person or organization
|
||
|
// obtaining a copy of the software and accompanying documentation covered by
|
||
|
// this license (the "Software") to use, reproduce, display, distribute,
|
||
|
// execute, and transmit the Software, and to prepare derivative works of the
|
||
|
// Software, and to permit third-parties to whom the Software is furnished to
|
||
|
// do so, all subject to the following:
|
||
|
//
|
||
|
// The copyright notices in the Software and this entire statement, including
|
||
|
// the above license grant, this restriction and the following disclaimer,
|
||
|
// must be included in all copies of the Software, in whole or in part, and
|
||
|
// all derivative works of the Software, unless such copies or derivative
|
||
|
// works are solely in the form of machine-executable object code generated by
|
||
|
// a source language processor.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||
|
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||
|
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
// DEALINGS IN THE SOFTWARE.
|
||
|
//
|
||
|
|
||
|
|
||
|
#include "Poco/Zip/ZipManipulator.h"
|
||
|
#include "Poco/Zip/ZipException.h"
|
||
|
#include "Poco/Zip/ZipUtil.h"
|
||
|
#include "Poco/Zip/Add.h"
|
||
|
#include "Poco/Zip/Delete.h"
|
||
|
#include "Poco/Zip/Keep.h"
|
||
|
#include "Poco/Zip/Rename.h"
|
||
|
#include "Poco/Zip/Replace.h"
|
||
|
#include "Poco/Zip/Compress.h"
|
||
|
#include "Poco/Delegate.h"
|
||
|
#include "Poco/File.h"
|
||
|
#include "Poco/FileStream.h"
|
||
|
|
||
|
|
||
|
namespace Poco {
|
||
|
namespace Zip {
|
||
|
|
||
|
|
||
|
ZipManipulator::ZipManipulator(const std::string& zipFile, bool backupOriginalFile):
|
||
|
_zipFile(zipFile),
|
||
|
_backupOriginalFile(backupOriginalFile),
|
||
|
_changes(),
|
||
|
_in(0)
|
||
|
{
|
||
|
Poco::FileInputStream in(zipFile);
|
||
|
_in = new ZipArchive(in);
|
||
|
}
|
||
|
|
||
|
|
||
|
ZipManipulator::~ZipManipulator()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::deleteFile(const std::string& zipPath)
|
||
|
{
|
||
|
const ZipLocalFileHeader& entry = getForChange(zipPath);
|
||
|
addOperation(zipPath, new Delete(entry));
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::replaceFile(const std::string& zipPath, const std::string& localPath)
|
||
|
{
|
||
|
const ZipLocalFileHeader& entry = getForChange(zipPath);
|
||
|
addOperation(zipPath, new Replace(entry, localPath));
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::renameFile(const std::string& zipPath, const std::string& newZipPath)
|
||
|
{
|
||
|
const ZipLocalFileHeader& entry = getForChange(zipPath);
|
||
|
// checked later in Compress too but the earlier one gets the error the better
|
||
|
std::string fn = ZipUtil::validZipEntryFileName(newZipPath);
|
||
|
addOperation(zipPath, new Rename(entry, fn));
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::addFile(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
|
||
|
{
|
||
|
addOperation(zipPath, new Add(zipPath, localPath, cm, cl));
|
||
|
}
|
||
|
|
||
|
|
||
|
ZipArchive ZipManipulator::commit()
|
||
|
{
|
||
|
// write to a tmp file
|
||
|
std::string outFile(_zipFile + ".tmp");
|
||
|
ZipArchive retVal(compress(outFile));
|
||
|
//renaming
|
||
|
{
|
||
|
Poco::File aFile(_zipFile);
|
||
|
if (_backupOriginalFile)
|
||
|
{
|
||
|
Poco::File tmp(_zipFile+".bak");
|
||
|
if (tmp.exists())
|
||
|
tmp.remove();
|
||
|
aFile.renameTo(_zipFile+".bak");
|
||
|
}
|
||
|
else
|
||
|
aFile.remove();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
Poco::File resFile(outFile);
|
||
|
Poco::File zipFile(_zipFile);
|
||
|
if (zipFile.exists())
|
||
|
zipFile.remove();
|
||
|
resFile.renameTo(_zipFile);
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
const ZipLocalFileHeader& ZipManipulator::getForChange(const std::string& zipPath) const
|
||
|
{
|
||
|
ZipArchive::FileHeaders::const_iterator it = _in->findHeader(zipPath);
|
||
|
if (it == _in->headerEnd())
|
||
|
throw ZipManipulationException("entry not found: " + zipPath);
|
||
|
|
||
|
if (_changes.find(zipPath) != _changes.end())
|
||
|
throw ZipManipulationException("A change request exists already for entry " + zipPath);
|
||
|
|
||
|
return it->second;
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::addOperation(const std::string& zipPath, ZipOperation::Ptr ptrOp)
|
||
|
{
|
||
|
std::pair<Changes::iterator, bool> result = _changes.insert(std::make_pair(zipPath, ptrOp));
|
||
|
if (!result.second)
|
||
|
throw ZipManipulationException("A change request exists already for entry " + zipPath);
|
||
|
}
|
||
|
|
||
|
|
||
|
void ZipManipulator::onEDone(const void*, const ZipLocalFileHeader& hdr)
|
||
|
{
|
||
|
EDone(this, hdr);
|
||
|
}
|
||
|
|
||
|
|
||
|
ZipArchive ZipManipulator::compress(const std::string& outFile)
|
||
|
{
|
||
|
// write to a tmp file
|
||
|
Poco::FileInputStream in(_zipFile);
|
||
|
Poco::FileOutputStream out(outFile);
|
||
|
Compress c(out, true);
|
||
|
c.EDone += Poco::Delegate<ZipManipulator, const ZipLocalFileHeader>(this, &ZipManipulator::onEDone);
|
||
|
|
||
|
ZipArchive::FileHeaders::const_iterator it = _in->headerBegin();
|
||
|
for (; it != _in->headerEnd(); ++it)
|
||
|
{
|
||
|
Changes::iterator itC = _changes.find(it->first);
|
||
|
if (itC != _changes.end())
|
||
|
{
|
||
|
itC->second->execute(c, in);
|
||
|
_changes.erase(itC);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Keep k(it->second);
|
||
|
k.execute(c, in);
|
||
|
}
|
||
|
}
|
||
|
//Remaining files are add operations!
|
||
|
Changes::iterator itC = _changes.begin();
|
||
|
for (; itC != _changes.end(); ++itC)
|
||
|
{
|
||
|
itC->second->execute(c, in);
|
||
|
}
|
||
|
_changes.clear();
|
||
|
c.EDone -= Poco::Delegate<ZipManipulator, const ZipLocalFileHeader>(this, &ZipManipulator::onEDone);
|
||
|
in.close();
|
||
|
return c.close();
|
||
|
}
|
||
|
|
||
|
|
||
|
} } // namespace Poco::Zip
|