Files
easy7zip/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp
Igor Pavlov a145bfc7cf 4.45 beta
2016-05-28 00:15:50 +01:00

203 lines
5.6 KiB
C++
Executable File

// Archive/GZip/OutHandler.cpp
#include "StdAfx.h"
#include "GZipHandler.h"
#include "GZipUpdate.h"
#include "Common/StringConvert.h"
#include "Common/StringToInt.h"
#include "Windows/Time.h"
#include "Windows/FileFind.h"
#include "Windows/PropVariant.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/ParseProperties.h"
using namespace NWindows;
using namespace NTime;
namespace NArchive {
namespace NGZip {
static const UInt32 kNumPassesX1 = 1;
static const UInt32 kNumPassesX7 = 3;
static const UInt32 kNumPassesX9 = 10;
static const UInt32 kNumFastBytesX1 = 32;
static const UInt32 kNumFastBytesX7 = 64;
static const UInt32 kNumFastBytesX9 = 128;
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
{
*timeType = NFileTimeType::kUnix;
return S_OK;
}
static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
}
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
if (numItems != 1)
return E_INVALIDARG;
UInt64 size;
Int32 newData;
Int32 newProperties;
UInt32 indexInArchive;
UInt32 itemIndex = 0;
if (!updateCallback)
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProperties, &indexInArchive));
CItem newItem = m_Item;
newItem.ExtraFlags = 0;
newItem.Flags = 0;
if (IntToBool(newProperties))
{
UInt32 attributes;
FILETIME utcTime;
UString name;
bool isDirectory;
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(itemIndex, kpidAttributes, &propVariant));
if (propVariant.vt == VT_EMPTY)
attributes = 0;
else if (propVariant.vt != VT_UI4)
return E_INVALIDARG;
else
attributes = propVariant.ulVal;
}
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(itemIndex, kpidLastWriteTime, &propVariant));
if (propVariant.vt != VT_FILETIME)
return E_INVALIDARG;
utcTime = propVariant.filetime;
}
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(itemIndex, kpidPath, &propVariant));
if (propVariant.vt == VT_EMPTY)
name.Empty();
else if (propVariant.vt != VT_BSTR)
return E_INVALIDARG;
else
name = propVariant.bstrVal;
}
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(itemIndex, kpidIsFolder, &propVariant));
if (propVariant.vt == VT_EMPTY)
isDirectory = false;
else if (propVariant.vt != VT_BOOL)
return E_INVALIDARG;
else
isDirectory = (propVariant.boolVal != VARIANT_FALSE);
}
if (isDirectory || NFile::NFind::NAttributes::IsDirectory(attributes))
return E_INVALIDARG;
if(!FileTimeToUnixTime(utcTime, newItem.Time))
return E_INVALIDARG;
newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
int dirDelimiterPos = newItem.Name.ReverseFind(CHAR_PATH_SEPARATOR);
if (dirDelimiterPos >= 0)
newItem.Name = newItem.Name.Mid(dirDelimiterPos + 1);
newItem.SetNameIsPresentFlag(!newItem.Name.IsEmpty());
}
if (IntToBool(newData))
{
{
NCOM::CPropVariant propVariant;
RINOK(updateCallback->GetProperty(itemIndex, kpidSize, &propVariant));
if (propVariant.vt != VT_UI8)
return E_INVALIDARG;
size = propVariant.uhVal.QuadPart;
}
newItem.UnPackSize32 = (UInt32)size;
UInt32 level = m_Level;
if (level == 0xFFFFFFFF)
level = 5;
if (m_Method.NumPasses == 0xFFFFFFFF)
m_Method.NumPasses = (level >= 9 ? kNumPassesX9 :
(level >= 7 ? kNumPassesX7 :
kNumPassesX1));
if (m_Method.NumFastBytes == 0xFFFFFFFF)
m_Method.NumFastBytes = (level >= 9 ? kNumFastBytesX9 :
(level >= 7 ? kNumFastBytesX7 :
kNumFastBytesX1));
return UpdateArchive(
EXTERNAL_CODECS_VARS
m_Stream, size, outStream, newItem, m_Method, itemIndex, updateCallback);
}
if (indexInArchive != 0)
return E_INVALIDARG;
if (IntToBool(newProperties))
{
COutArchive outArchive;
outArchive.Create(outStream);
outArchive.WriteHeader(newItem);
RINOK(m_Stream->Seek(m_StreamStartPosition + m_DataOffset, STREAM_SEEK_SET, NULL));
}
else
{
RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL));
}
return CopyStreams(m_Stream, outStream);
}
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
InitMethodProperties();
for (int i = 0; i < numProperties; i++)
{
UString name = names[i];
name.MakeUpper();
const PROPVARIANT &prop = values[i];
if (name[0] == L'X')
{
UInt32 level = 9;
RINOK(ParsePropValue(name.Mid(1), prop, level));
m_Level = level;
}
else if (name.Left(4) == L"PASS")
{
UInt32 num = kNumPassesX9;
RINOK(ParsePropValue(name.Mid(4), prop, num));
m_Method.NumPasses = num;
}
else if (name.Left(2) == L"FB")
{
UInt32 num = kNumFastBytesX9;
RINOK(ParsePropValue(name.Mid(2), prop, num));
m_Method.NumFastBytes = num;
}
else if (name.Left(2) == L"MC")
{
UInt32 num = 0xFFFFFFFF;
RINOK(ParsePropValue(name.Mid(2), prop, num));
m_Method.NumMatchFinderCycles = num;
m_Method.NumMatchFinderCyclesDefined = true;
}
else
return E_INVALIDARG;
}
return S_OK;
}
}}