mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-12 03:09:57 -06:00
22.00
This commit is contained in:
217
CPP/7zip/Archive/GzHandler.cpp
Normal file → Executable file
217
CPP/7zip/Archive/GzHandler.cpp
Normal file → Executable file
@@ -475,6 +475,7 @@ class CHandler:
|
||||
NDecoder::CCOMCoder *_decoderSpec;
|
||||
|
||||
CSingleMethodProps _props;
|
||||
CHandlerTimeOptions _timeOptions;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP4(
|
||||
@@ -487,8 +488,15 @@ public:
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
CHandler()
|
||||
CHandler():
|
||||
_isArc(false),
|
||||
_decoderSpec(NULL)
|
||||
{}
|
||||
|
||||
void CreateDecoder()
|
||||
{
|
||||
if (_decoder)
|
||||
return;
|
||||
_decoderSpec = new NDecoder::CCOMCoder;
|
||||
_decoder = _decoderSpec;
|
||||
}
|
||||
@@ -528,7 +536,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
prop = v;
|
||||
@@ -567,12 +575,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
|
||||
break;
|
||||
// case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break;
|
||||
case kpidMTime:
|
||||
// gzip specification: MTIME = 0 means no time stamp is available.
|
||||
if (_item.Time != 0)
|
||||
{
|
||||
FILETIME utc;
|
||||
NTime::UnixTimeToFileTime(_item.Time, utc);
|
||||
prop = utc;
|
||||
}
|
||||
PropVariant_SetFrom_UnixTime(prop, _item.Time);
|
||||
break;
|
||||
case kpidTimeType:
|
||||
if (_item.Time != 0)
|
||||
prop = (UInt32)NFileTimeType::kUnix;
|
||||
break;
|
||||
case kpidSize:
|
||||
{
|
||||
@@ -644,6 +653,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
try
|
||||
{
|
||||
Close();
|
||||
CreateDecoder();
|
||||
_decoderSpec->SetInStream(stream);
|
||||
_decoderSpec->InitInStream(true);
|
||||
RINOK(_item.ReadHeader(_decoderSpec));
|
||||
@@ -672,7 +682,8 @@ STDMETHODIMP CHandler::Close()
|
||||
_headerSize = 0;
|
||||
|
||||
_stream.Release();
|
||||
_decoderSpec->ReleaseInStream();
|
||||
if (_decoder)
|
||||
_decoderSpec->ReleaseInStream();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -699,6 +710,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
extractCallback->PrepareOperation(askMode);
|
||||
|
||||
CreateDecoder();
|
||||
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
@@ -873,21 +886,99 @@ static const Byte kHostOS =
|
||||
NHostOS::kUnix;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
|
||||
{
|
||||
return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);
|
||||
}
|
||||
|
||||
static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
|
||||
{
|
||||
return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);
|
||||
}
|
||||
|
||||
static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,
|
||||
const CItem &item,
|
||||
bool needTime,
|
||||
bool needCrc,
|
||||
const UInt64 *unpackSize)
|
||||
{
|
||||
NCOM::CPropVariant timeProp;
|
||||
NCOM::CPropVariant sizeProp;
|
||||
if (needTime)
|
||||
{
|
||||
FILETIME ft;
|
||||
NTime::UnixTimeToFileTime(item.Time, ft);
|
||||
timeProp.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix);
|
||||
}
|
||||
if (unpackSize)
|
||||
{
|
||||
sizeProp = *unpackSize;
|
||||
RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));
|
||||
}
|
||||
if (needCrc)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
prop = item.Crc;
|
||||
RINOK(ReportItemProp(reportArcProp, kpidCRC, &prop));
|
||||
}
|
||||
{
|
||||
RINOK(ReportItemProp(reportArcProp, kpidMTime, &timeProp));
|
||||
}
|
||||
|
||||
RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));
|
||||
|
||||
if (unpackSize)
|
||||
{
|
||||
RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));
|
||||
}
|
||||
{
|
||||
RINOK(ReportArcProp(reportArcProp, kpidComboMTime, &timeProp));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
static HRESULT UpdateArchive(
|
||||
ISequentialOutStream *outStream,
|
||||
UInt64 unpackSize,
|
||||
CItem &item,
|
||||
const CSingleMethodProps &props,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
const CHandlerTimeOptions &timeOptions,
|
||||
IArchiveUpdateCallback *updateCallback
|
||||
// , IArchiveUpdateCallbackArcProp *reportArcProp
|
||||
)
|
||||
{
|
||||
UInt64 complexity = 0;
|
||||
RINOK(updateCallback->SetTotal(unpackSize));
|
||||
RINOK(updateCallback->SetCompleted(&complexity));
|
||||
|
||||
UInt64 unpackSizeReal;
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
|
||||
RINOK(updateCallback->GetStream(0, &fileInStream));
|
||||
|
||||
if (!fileInStream)
|
||||
return S_FALSE;
|
||||
|
||||
{
|
||||
CMyComPtr<IStreamGetProps> getProps;
|
||||
fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps);
|
||||
if (getProps)
|
||||
{
|
||||
FILETIME mTime;
|
||||
UInt64 size;
|
||||
if (getProps->GetProps(&size, NULL, NULL, &mTime, NULL) == S_OK)
|
||||
{
|
||||
unpackSize = size;
|
||||
if (timeOptions.Write_MTime.Val)
|
||||
NTime::FileTime_To_UnixTime(mTime, item.Time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt64 complexity = 0;
|
||||
RINOK(updateCallback->SetTotal(unpackSize));
|
||||
RINOK(updateCallback->SetCompleted(&complexity));
|
||||
|
||||
CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC;
|
||||
CMyComPtr<ISequentialInStream> crcStream(inStreamSpec);
|
||||
inStreamSpec->SetStream(fileInStream);
|
||||
@@ -911,14 +1002,50 @@ static HRESULT UpdateArchive(
|
||||
RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));
|
||||
|
||||
item.Crc = inStreamSpec->GetCRC();
|
||||
item.Size32 = (UInt32)inStreamSpec->GetSize();
|
||||
unpackSizeReal = inStreamSpec->GetSize();
|
||||
item.Size32 = (UInt32)unpackSizeReal;
|
||||
RINOK(item.WriteFooter(outStream));
|
||||
}
|
||||
/*
|
||||
if (reportArcProp)
|
||||
{
|
||||
RINOK(ReportArcProps(reportArcProp,
|
||||
item,
|
||||
props._Write_MTime, // item.Time != 0,
|
||||
true, // writeCrc
|
||||
&unpackSizeReal));
|
||||
}
|
||||
*/
|
||||
return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
{
|
||||
*timeType = NFileTimeType::kUnix;
|
||||
/*
|
||||
if (_item.Time != 0)
|
||||
{
|
||||
we set NFileTimeType::kUnix in precision,
|
||||
and we return NFileTimeType::kUnix in kpidTimeType
|
||||
so GetFileTimeType() value is not used in any version of 7-zip.
|
||||
}
|
||||
else // (_item.Time == 0)
|
||||
{
|
||||
kpidMTime and kpidTimeType are not defined
|
||||
before 22.00 : GetFileTimeType() value is used in GetUpdatePairInfoList();
|
||||
22.00 : GetFileTimeType() value is not used
|
||||
}
|
||||
*/
|
||||
|
||||
UInt32 t;
|
||||
t = NFileTimeType::kUnix;
|
||||
if (_isArc ? (_item.Time == 0) : !_timeOptions.Write_MTime.Val)
|
||||
{
|
||||
t = GET_FileTimeType_NotDefined_for_GetFileTimeType;
|
||||
// t = k_PropVar_TimePrec_1ns; // failed in 7-Zip 21
|
||||
// t = (UInt32)(Int32)NFileTimeType::kNotDefined; // failed in 7-Zip 21
|
||||
}
|
||||
*timeType = t;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -936,6 +1063,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
|
||||
|
||||
/*
|
||||
CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp;
|
||||
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp);
|
||||
*/
|
||||
|
||||
CItem newItem;
|
||||
|
||||
if (!IntToBool(newProps))
|
||||
@@ -945,11 +1077,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
else
|
||||
{
|
||||
newItem.HostOS = kHostOS;
|
||||
if (_timeOptions.Write_MTime.Val)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));
|
||||
if (prop.vt == VT_FILETIME)
|
||||
NTime::FileTimeToUnixTime(prop.filetime, newItem.Time);
|
||||
NTime::FileTime_To_UnixTime(prop.filetime, newItem.Time);
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
newItem.Time = 0;
|
||||
else
|
||||
@@ -990,7 +1123,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
}
|
||||
return UpdateArchive(outStream, size, newItem, _props, updateCallback);
|
||||
return UpdateArchive(outStream, size, newItem, _props, _timeOptions, updateCallback);
|
||||
}
|
||||
|
||||
if (indexInArchive != 0)
|
||||
@@ -1022,6 +1155,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL));
|
||||
|
||||
/*
|
||||
if (reportArcProp)
|
||||
ReportArcProps(reportArcProp, newItem,
|
||||
_props._Write_MTime,
|
||||
false, // writeCrc
|
||||
NULL); // unpacksize
|
||||
*/
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, progress);
|
||||
|
||||
COM_TRY_END
|
||||
@@ -1029,16 +1170,48 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
_timeOptions.Init();
|
||||
_props.Init();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
const PROPVARIANT &value = values[i];
|
||||
{
|
||||
bool processed = false;
|
||||
RINOK(_timeOptions.Parse(name, value, processed));
|
||||
if (processed)
|
||||
{
|
||||
if (_timeOptions.Write_CTime.Val ||
|
||||
_timeOptions.Write_ATime.Val)
|
||||
return E_INVALIDARG;
|
||||
if ( _timeOptions.Prec != (UInt32)(Int32)-1
|
||||
&& _timeOptions.Prec != k_PropVar_TimePrec_0
|
||||
&& _timeOptions.Prec != k_PropVar_TimePrec_Unix
|
||||
&& _timeOptions.Prec != k_PropVar_TimePrec_HighPrec
|
||||
&& _timeOptions.Prec != k_PropVar_TimePrec_Base)
|
||||
return E_INVALIDARG;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RINOK(_props.SetProperty(name, value));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
IsArc_Gz)
|
||||
k_Signature, 0,
|
||||
NArcInfoFlags::kKeepName
|
||||
| NArcInfoFlags::kMTime
|
||||
| NArcInfoFlags::kMTime_Default
|
||||
, TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)
|
||||
| TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix)
|
||||
, IsArc_Gz)
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user