diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-06-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:54 +0300 |
commit | 54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch) | |
tree | c3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive/Rar | |
parent | 0713a3ab803e57401f18432148b4139e5fe6e5dd (diff) |
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive/Rar')
-rw-r--r-- | CPP/7zip/Archive/Rar/RarHandler.cpp | 149 | ||||
-rw-r--r-- | CPP/7zip/Archive/Rar/RarHandler.h | 17 | ||||
-rw-r--r-- | CPP/7zip/Archive/Rar/RarItem.h | 8 |
3 files changed, 119 insertions, 55 deletions
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index c26d72f9..516e5d7f 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const return a; } -static const char *kHostOS[] = +static const char * const kHostOS[] = { "MS DOS" , "OS/2" @@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) } #define READ_TIME(_mask_, _ttt_) \ - { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; } + { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; } #define READ_TIME_2(_mask_, _def_, _ttt_) \ _def_ = ((_mask_ & 8) != 0); if (_def_) \ @@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) { item.IsAltStream = true; item.Name.Empty(); - item.UnicodeName = L".ACL"; + item.UnicodeName.SetFromAscii(".ACL"); } else if (item.Name == "STM" && size != 0 && (size & 1) == 0) { @@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass RINOK(getTextPassword->CryptoGetTextPassword(&password)) unsigned len = 0; if (password) - len = MyStringLen((BSTR)password); + len = MyStringLen(password); CByteBuffer buffer(len * 2); for (unsigned i = 0; i < len; i++) { @@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass error = k_ErrorType_Corrupted; ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset); } + + ArcInfo.EndOfArchive_was_Read = true; } m_Position += processed; FinishCryptoBlock(); @@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item); if (okItem) { - if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize)) + if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize)) { error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError); return S_OK; @@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop); if (_arcInfo.Is_DataCRC_Defined()) { - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); s += "VolCRC"; } prop = s; @@ -1008,27 +1009,28 @@ public: { _first = true; _newStyle = newStyle; - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); UString basePart = name; + if (dotPos >= 0) { UString ext = name.Ptr(dotPos + 1); - if (ext.IsEqualToNoCase(L"rar")) + if (ext.IsEqualTo_Ascii_NoCase("rar")) { _afterPart = name.Ptr(dotPos); basePart = name.Left(dotPos); } - else if (ext.IsEqualToNoCase(L"exe")) + else if (ext.IsEqualTo_Ascii_NoCase("exe")) { - _afterPart = L".rar"; + _afterPart.SetFromAscii(".rar"); basePart = name.Left(dotPos); } else if (!_newStyle) { - if (ext.IsEqualToNoCase(L"000") || - ext.IsEqualToNoCase(L"001") || - ext.IsEqualToNoCase(L"r00") || - ext.IsEqualToNoCase(L"r01")) + if (ext.IsEqualTo_Ascii_NoCase("000") || + ext.IsEqualTo_Ascii_NoCase("001") || + ext.IsEqualTo_Ascii_NoCase("r00") || + ext.IsEqualTo_Ascii_NoCase("r01")) { _afterPart.Empty(); _first = false; @@ -1042,18 +1044,21 @@ public: if (!_newStyle) { _afterPart.Empty(); - _unchangedPart = basePart + UString(L"."); - _changedPart = L"r00"; + _unchangedPart = basePart; + _unchangedPart += L'.'; + _changedPart.SetFromAscii("r00"); return true; } if (basePart.IsEmpty()) return false; unsigned i = basePart.Len(); + do if (!IsDigit(basePart[i - 1])) break; while (--i); + _unchangedPart = basePart.Left(i); _changedPart = basePart.Ptr(i); return true; @@ -1071,34 +1076,59 @@ public: UString GetNextName() { - UString newName; if (_newStyle || !_first) { - for (int i = (int)_changedPart.Len() - 1; i >= 0; i--) + unsigned i = _changedPart.Len(); + for (;;) { - wchar_t c = _changedPart[i]; + wchar_t c = _changedPart[--i]; if (c == L'9') { c = L'0'; - newName.InsertAtFront(c); + _changedPart.ReplaceOneCharAtPos(i, c); if (i == 0) - newName.InsertAtFront(L'1'); + { + _changedPart.InsertAtFront(L'1'); + break; + } continue; } c++; - newName = UString(c) + newName; - i--; - for (; i >= 0; i--) - newName.InsertAtFront(_changedPart[i]); + _changedPart.ReplaceOneCharAtPos(i, c); break; } - _changedPart = newName; } + _first = false; return _unchangedPart + _changedPart + _afterPart; } }; +static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize) +{ + areThereNonZeros = false; + numZeros = 0; + const size_t kBufSize = 1 << 9; + Byte buf[kBufSize]; + for (;;) + { + UInt32 size = 0; + HRESULT(stream->Read(buf, kBufSize, &size)); + if (size == 0) + return S_OK; + for (UInt32 i = 0; i < size; i++) + if (buf[i] != 0) + { + areThereNonZeros = true; + numZeros += i; + return S_OK; + } + numZeros += size; + if (numZeros > maxSize) + return S_OK; + } +} + HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) @@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream, RINOK(archive.Open(inStream, maxCheckStartPosition)); _isArc = true; CItem item; + for (;;) { if (archive.m_Position > endPos) @@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream, _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; break; } + EErrorType error; // bool decryptionError; // AString errorMessageLoc; bool filled; HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error); + if (error != k_ErrorType_OK) { if (error == k_ErrorType_UnexpectedEnd) @@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream, // AddErrorMessage(errorMessageLoc); } RINOK(result); + if (!filled) { if (error == k_ErrorType_DecryptionError && _items.IsEmpty()) return S_FALSE; + + if (archive.ArcInfo.ExtraZeroTail_is_Possible()) + { + /* if there is recovery record for multivolume archive, + RAR adds 18 bytes (ZERO bytes) at the end for alignment. + We must skip these bytes to prevent phySize warning. */ + RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL)); + bool areThereNonZeros; + UInt64 numZeros; + const UInt64 maxSize = 1 << 12; + RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize)); + if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize) + archive.ArcInfo.EndPos += numZeros; + } break; } + if (item.IgnoreItem()) continue; bool needAdd = true; + if (item.IsSplitBefore()) { if (!_refItems.IsEmpty()) @@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream, needAdd = false; } } + if (needAdd) { CRefItem refItem; @@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream, refItem.VolumeIndex = _arcs.Size(); _refItems.Add(refItem); } + _items.Add(item); + if (openCallback && _items.Size() % 100 == 0) { UInt64 numFiles = _items.Size(); @@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream, /* int baseFileIndex = -1; - for (int i = 0; i < _refItems.Size(); i++) + for (unsigned i = 0; i < _refItems.Size(); i++) { CItem &item = _items[_refItems[i].ItemIndex]; if (item.IsAltStream) @@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems == 0) return S_OK; unsigned lastIndex = 0; - CRecordVector<int> importantIndexes; + CRecordVector<unsigned> importantIndexes; CRecordVector<bool> extractStatuses; for (UInt32 t = 0; t < numItems; t++) @@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - CFilterCoder *filterStreamSpec = new CFilterCoder; + CFilterCoder *filterStreamSpec = new CFilterCoder(false); CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL; @@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // unpackedPos += 0; CMyComPtr<ISequentialInStream> inStream; + if (item.IsEncrypted()) { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; + if (item.UnPackVersion >= 29) { if (!rar29CryptoDecoder) { rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; rar29CryptoDecoder = rar29CryptoDecoderSpec; - // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder)); } rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); + /* CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &cryptoProperties)); - RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); + */ + RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); filterStreamSpec->Filter = rar29CryptoDecoder; } else if (item.UnPackVersion >= 20) @@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder; rar20CryptoDecoder = rar20CryptoDecoderSpec; - // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder)); } filterStreamSpec->Filter = rar20CryptoDecoder; } @@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } - RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, - &cryptoSetPassword)); + + RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); @@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UString unicodePassword; unsigned len = 0; if (password) - len = MyStringLen((BSTR)password); + len = MyStringLen(password); CByteBuffer buffer(len * 2); for (unsigned i = 0; i < len; i++) { @@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); } + filterStreamSpec->SetInStream(folderInStream); + filterStreamSpec->SetOutStreamSize(NULL); inStream = filterStream; } else { inStream = folderInStream; } + CMyComPtr<ICompressCoder> commonCoder; + switch(item.Method) { case '0': @@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, mi.Coder.Release(); if (item.UnPackVersion <= 40) { - UInt32 methodID = 0x040300; + UInt32 methodID = 0x40300; if (item.UnPackVersion < 20) methodID += 1; else if (item.UnPackVersion < 29) methodID += 2; else methodID += 3; - RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false)); + RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder)); } if (mi.Coder == 0) @@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } + HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); + if (item.IsEncrypted()) filterStreamSpec->ReleaseInStream(); if (result == S_FALSE) @@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, IMPL_ISetCompressCodecsInfo -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Rar", "rar r00", 0, 3, - NHeader::kMarkerSize, SIGNATURE, +REGISTER_ARC_I( + "Rar", "rar r00", 0, 3, + kMarker, 0, NArcInfoFlags::kFindSignature, - CreateArc }; - -REGISTER_ARC(Rar) + NULL) }} diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index 81191be9..dd3daa5d 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -1,4 +1,4 @@ -// Rar/Handler.h +// RarHandler.h #ifndef __RAR_HANDLER_H #define __RAR_HANDLER_H @@ -24,18 +24,25 @@ struct CInArcInfo UInt32 EndFlags; UInt32 VolNumber; UInt32 DataCRC; + bool EndOfArchive_was_Read; - CInArcInfo(): EndFlags(0) {} + CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {} UInt64 GetPhySize() const { return EndPos - StartPos; } - bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } - bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; } + bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } + bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + // kLock + bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } - bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; } + // kAuthenticity + bool IsRecovery() const { return (Flags & NHeader::NArchive::kRecovery) != 0; } bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } + bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; } bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; } + bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); } bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; } diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h index 56d25f2c..13daa1cb 100644 --- a/CPP/7zip/Archive/Rar/RarItem.h +++ b/CPP/7zip/Archive/Rar/RarItem.h @@ -84,10 +84,10 @@ struct CItem CItem() { Clear(); } - UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }; - // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }; - UInt64 GetCommentPosition() const { return Position + MainPartSize; }; - UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }; + UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; } + // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; } + UInt64 GetCommentPosition() const { return Position + MainPartSize; } + UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; } }; }} |