5
#include "ZipHandler.h"
5
#include "Common/ComTry.h"
7
6
#include "Common/Defs.h"
7
#include "Common/IntToString.h"
8
8
#include "Common/StringConvert.h"
9
#include "Common/ComTry.h"
10
#include "Common/IntToString.h"
10
#include "Windows/PropVariant.h"
12
11
#include "Windows/Time.h"
13
#include "Windows/PropVariant.h"
15
13
#include "../../IPassword.h"
15
#include "../../Common/CreateCoder.h"
16
#include "../../Common/FilterCoder.h"
17
17
#include "../../Common/ProgressUtils.h"
18
18
#include "../../Common/StreamObjects.h"
19
#include "../../Common/CreateCoder.h"
20
#include "../../Common/FilterCoder.h"
22
#include "../../Compress/Copy/CopyCoder.h"
19
#include "../../Common/StreamUtils.h"
21
#include "../../Compress/CopyCoder.h"
22
#include "../../Compress/LzmaDecoder.h"
23
#include "../../Compress/ImplodeDecoder.h"
24
#include "../../Compress/ShrinkDecoder.h"
26
#include "../../Crypto/WzAes.h"
27
#include "../../Crypto/ZipCrypto.h"
28
#include "../../Crypto/ZipStrong.h"
24
30
#include "../Common/ItemNameUtils.h"
25
31
#include "../Common/OutStreamWithCRC.h"
27
#include "../../Compress/Shrink/ShrinkDecoder.h"
28
#include "../../Compress/Implode/ImplodeDecoder.h"
31
#include "../../Crypto/Zip/ZipCipher.h"
32
#include "../../Crypto/WzAES/WzAES.h"
34
#ifdef ZIP_STRONG_SUPORT
35
#include "../../Crypto/ZipStrong/ZipStrong.h"
33
#include "ZipHandler.h"
38
35
using namespace NWindows;
39
using namespace NTime;
41
37
namespace NArchive {
75
71
static const wchar_t *kUnknownOS = L"Unknown";
77
STATPROPSTG kProps[] =
73
STATPROPSTG kProps[] =
79
75
{ NULL, kpidPath, VT_BSTR},
80
{ NULL, kpidIsFolder, VT_BOOL},
76
{ NULL, kpidIsDir, VT_BOOL},
81
77
{ NULL, kpidSize, VT_UI8},
82
{ NULL, kpidPackedSize, VT_UI8},
83
{ NULL, kpidLastWriteTime, VT_FILETIME},
84
{ NULL, kpidCreationTime, VT_FILETIME},
85
{ NULL, kpidLastAccessTime, VT_FILETIME},
78
{ NULL, kpidPackSize, VT_UI8},
79
{ NULL, kpidMTime, VT_FILETIME},
80
{ NULL, kpidCTime, VT_FILETIME},
81
{ NULL, kpidATime, VT_FILETIME},
87
{ NULL, kpidAttributes, VT_UI4},
83
{ NULL, kpidAttrib, VT_UI4},
89
85
{ NULL, kpidEncrypted, VT_BOOL},
90
86
{ NULL, kpidComment, VT_BSTR},
117
111
const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
118
// const wchar_t *kUnknownMethod = L"Unknown";
112
const wchar_t *kBZip2Method = L"BZip2";
113
const wchar_t *kLZMAMethod = L"LZMA";
114
const wchar_t *kJpegMethod = L"Jpeg";
115
const wchar_t *kWavPackMethod = L"WavPack";
119
116
const wchar_t *kPPMdMethod = L"PPMd";
120
117
const wchar_t *kAESMethod = L"AES";
121
118
const wchar_t *kZipCryptoMethod = L"ZipCrypto";
198
196
const CItemEx &item = m_Items[index];
202
prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name));
205
prop = item.IsDirectory();
208
prop = item.UnPackSize;
211
prop = item.PackSize;
199
case kpidPath: prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break;
200
case kpidIsDir: prop = item.IsDir(); break;
201
case kpidSize: prop = item.UnPackSize; break;
202
case kpidPackSize: prop = item.PackSize; break;
213
203
case kpidTimeType:
214
205
FILETIME utcFileTime;
215
206
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kTagTime, utcFileTime))
216
207
prop = (UInt32)NFileTimeType::kWindows;
218
case kpidCreationTime:
221
213
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))
225
case kpidLastAccessTime:
228
220
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))
232
case kpidLastWriteTime:
234
226
FILETIME utcFileTime;
235
227
if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utcFileTime))
237
229
FILETIME localFileTime;
238
if (DosTimeToFileTime(item.Time, localFileTime))
230
if (NTime::DosTimeToFileTime(item.Time, localFileTime))
240
232
if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
241
233
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
311
292
if (methodId < kNumMethods)
312
293
method += kMethods[methodId];
313
else if (methodId == NFileHeader::NCompressionMethod::kWzPPMd)
314
method += kPPMdMethod;
294
else switch (methodId)
318
ConvertUInt64ToString(methodId, s);
296
case NFileHeader::NCompressionMethod::kLZMA:
297
method += kLZMAMethod;
298
if (item.IsLzmaEOS())
301
case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;
302
case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;
303
case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;
304
case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;
308
ConvertUInt64ToString(methodId, s);
334
class CPropgressImp: public CProgressVirt
325
class CProgressImp: public CProgressVirt
336
CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
327
CMyComPtr<IArchiveOpenCallback> _callback;
338
STDMETHOD(SetCompleted)(const UInt64 *numFiles);
339
void Init(IArchiveOpenCallback *openArchiveCallback)
340
{ m_OpenArchiveCallback = openArchiveCallback; }
329
STDMETHOD(SetTotal)(UInt64 numFiles);
330
STDMETHOD(SetCompleted)(UInt64 numFiles);
331
CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
343
STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles)
345
if (m_OpenArchiveCallback)
346
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
350
STDMETHODIMP CHandler::Open(IInStream *inStream,
351
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback)
334
STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles)
337
return _callback->SetTotal(&numFiles, NULL);
341
STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles)
344
return _callback->SetCompleted(&numFiles, NULL);
348
STDMETHODIMP CHandler::Open(IInStream *inStream,
349
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
356
if(!m_Archive.Open(inStream, maxCheckStartPosition))
358
m_ArchiveIsOpen = true;
360
if (openArchiveCallback != NULL)
362
RINOK(openArchiveCallback->SetTotal(NULL, NULL));
364
CPropgressImp propgressImp;
365
propgressImp.Init(openArchiveCallback);
366
RINOK(m_Archive.ReadHeaders(m_Items, &propgressImp));
355
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
356
RINOK(m_Archive.Open(inStream, maxCheckStartPosition));
357
CProgressImp progressImp(callback);
358
return m_Archive.ReadHeaders(m_Items, &progressImp);
360
catch(const CInArchiveException &) { Close(); return S_FALSE; }
361
catch(...) { Close(); throw; }
378
365
STDMETHODIMP CHandler::Close()
381
368
m_Archive.Close();
382
m_ArchiveIsOpen = false;
386
372
//////////////////////////////////////
387
373
// CHandler::DecompressItems
376
public ICompressCoder,
379
NCompress::NLzma::CDecoder *DecoderSpec;
380
CMyComPtr<ICompressCoder> Decoder;
383
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
384
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
389
CLzmaDecoder::CLzmaDecoder()
391
DecoderSpec = new NCompress::NLzma::CDecoder;
392
Decoder = DecoderSpec;
395
HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
396
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
399
RINOK(ReadStream_FALSE(inStream, buf, 9));
400
if (buf[2] != 5 || buf[3] != 0)
402
RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));
403
return Decoder->Code(inStream, outStream, NULL, outSize, progress);
389
406
struct CMethodItem
391
408
UInt16 ZipMethod;
395
412
class CZipDecoder
397
414
NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
398
NCrypto::NWzAES::CDecoder *_aesDecoderSpec;
415
NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec;
416
NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec;
399
418
CMyComPtr<ICompressFilter> _zipCryptoDecoder;
400
CMyComPtr<ICompressFilter> _aesDecoder;
401
#ifdef ZIP_STRONG_SUPORT
402
NCrypto::NZipStrong::CDecoder *_zsDecoderSpec;
403
CMyComPtr<ICompressFilter> _zsDecoder;
419
CMyComPtr<ICompressFilter> _pkAesDecoder;
420
CMyComPtr<ICompressFilter> _wzAesDecoder;
405
422
CFilterCoder *filterStreamSpec;
406
423
CMyComPtr<ISequentialInStream> filterStream;
407
424
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
408
425
CObjectVector<CMethodItem> methodItems;
411
CZipDecoder(): _zipCryptoDecoderSpec(0), _aesDecoderSpec(0), filterStreamSpec(0) {}
429
_zipCryptoDecoderSpec(0),
430
_pkAesDecoderSpec(0),
431
_wzAesDecoderSpec(0),
432
filterStreamSpec(0) {}
414
435
DECL_EXTERNAL_CODECS_LOC_VARS
415
CInArchive &archive, const CItemEx &item,
416
ISequentialOutStream *realOutStream,
417
IArchiveExtractCallback *extractCallback,
436
CInArchive &archive, const CItemEx &item,
437
ISequentialOutStream *realOutStream,
438
IArchiveExtractCallback *extractCallback,
418
439
ICompressProgressInfo *compressProgress,
419
440
UInt32 numThreads, Int32 &res);
422
443
HRESULT CZipDecoder::Decode(
423
444
DECL_EXTERNAL_CODECS_LOC_VARS
424
CInArchive &archive, const CItemEx &item,
425
ISequentialOutStream *realOutStream,
445
CInArchive &archive, const CItemEx &item,
446
ISequentialOutStream *realOutStream,
426
447
IArchiveExtractCallback *extractCallback,
427
448
ICompressProgressInfo *compressProgress,
428
449
UInt32 numThreads, Int32 &res)
488
505
CMyComPtr<ICompressFilter> cryptoFilter;
489
506
if (item.IsEncrypted())
493
510
CWzAesExtraField aesField;
494
511
if (!item.CentralExtra.GetWzAesField(aesField))
496
513
methodId = aesField.Method;
499
_aesDecoderSpec = new NCrypto::NWzAES::CDecoder;
500
_aesDecoder = _aesDecoderSpec;
516
_wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;
517
_wzAesDecoder = _wzAesDecoderSpec;
502
cryptoFilter = _aesDecoder;
519
cryptoFilter = _wzAesDecoder;
503
520
Byte properties = aesField.Strength;
504
RINOK(_aesDecoderSpec->SetDecoderProperties2(&properties, 1));
521
RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));
506
#ifdef ZIP_STRONG_SUPORT
507
523
else if (pkAesMode)
511
_zsDecoderSpec = new NCrypto::NZipStrong::CDecoder;
512
_zsDecoder = _zsDecoderSpec;
527
_pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder;
528
_pkAesDecoder = _pkAesDecoderSpec;
514
cryptoFilter = _zsDecoder;
530
cryptoFilter = _pkAesDecoder;
519
534
if (!_zipCryptoDecoder)
646
659
filterStream = filterStreamSpec;
648
661
filterStreamSpec->Filter = cryptoFilter;
651
RINOK(_aesDecoderSpec->ReadHeader(inStream));
664
result = _wzAesDecoderSpec->ReadHeader(inStream);
653
#ifdef ZIP_STRONG_SUPORT
654
666
else if (pkAesMode)
656
RINOK(_zsDecoderSpec->ReadHeader(inStream));
668
result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize);
672
result = _pkAesDecoderSpec->CheckPassword(passwOK);
673
if (result == S_OK && !passwOK)
661
RINOK(_zipCryptoDecoderSpec->ReadHeader(inStream));
679
result = _zipCryptoDecoderSpec->ReadHeader(inStream);
663
RINOK(filterStreamSpec->SetInStream(inStream));
664
inStreamReleaser.FilterCoder = filterStreamSpec;
665
inStreamNew = filterStream;
669
if (!_aesDecoderSpec->CheckPasswordVerifyCode())
684
RINOK(filterStreamSpec->SetInStream(inStream));
685
inStreamReleaser.FilterCoder = filterStreamSpec;
686
inStreamNew = filterStream;
689
if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())
674
inStreamNew = inStream;
675
result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
695
inStreamNew = inStream;
697
result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
676
698
if (result == S_FALSE)
700
if (result == E_NOTIMPL)
702
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
680
708
bool crcOK = true;
681
709
bool authOk = true;
683
711
crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
686
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAES::kMacSize));
687
if (_aesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
714
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));
715
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
691
res = ((crcOK && authOk) ?
719
res = ((crcOK && authOk) ?
692
720
NArchive::NExtract::NOperationResult::kOK :
693
721
NArchive::NExtract::NOperationResult::kCRCError);