diff options
Diffstat (limited to 'CPP/7zip/Archive/GZip/GZipHandlerOut.cpp')
-rwxr-xr-x | CPP/7zip/Archive/GZip/GZipHandlerOut.cpp | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp new file mode 100755 index 00000000..cc896016 --- /dev/null +++ b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp @@ -0,0 +1,200 @@ +// 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(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; +} + +}} |