diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2016-05-10 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:59 +0300 |
commit | 66ac98bb02ac0fadd2a0e3266ea39279984580a3 (patch) | |
tree | c14c790212474e8b51df443d686b202cfe6b2315 /CPP | |
parent | c20d013055085bf49b4c93b2c617030b10c1fb4d (diff) |
16.0016.00
Diffstat (limited to 'CPP')
81 files changed, 2349 insertions, 824 deletions
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index fc527be6..0634768b 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -93,6 +93,8 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d Byte external = archive->ReadByte(); if (external != 0) { + if (!dataVector) + ThrowIncorrect(); CNum dataIndex = archive->ReadNum(); if (dataIndex >= dataVector->Size()) ThrowIncorrect(); @@ -761,6 +763,8 @@ void CInArchive::ReadUnpackInfo( folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; numCodersOutStreams += numCoders; folders.FoStartPackStreamIndex[fo] = packStreamIndex; + if (numPackStreams > folders.NumPackStreams - packStreamIndex) + ThrowIncorrect(); packStreamIndex += numPackStreams; folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } @@ -770,6 +774,8 @@ void CInArchive::ReadUnpackInfo( folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; folders.CodersData.CopyFrom(startBufPtr, dataSize); + + // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); } WaitId(NID::kCodersUnpackSize); diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 7e9478fc..e1c7aad8 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -380,29 +380,33 @@ static inline bool IsExeFilter(CMethodId m) return false; } -static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f) +static unsigned Get_FilterGroup_for_Folder( + CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter) { CFilterMode2 m; m.Id = 0; m.Delta = 0; m.Encrypted = f.IsEncrypted(); - const CCoderInfo &coder = f.Coders[f.UnpackCoder]; - - if (coder.MethodID == k_Delta) + if (extractFilter) { - if (coder.Props.Size() == 1) + const CCoderInfo &coder = f.Coders[f.UnpackCoder]; + + if (coder.MethodID == k_Delta) { - m.Delta = (unsigned)coder.Props[0] + 1; - m.Id = k_Delta; + if (coder.Props.Size() == 1) + { + m.Delta = (unsigned)coder.Props[0] + 1; + m.Id = k_Delta; + } + } + else if (IsExeFilter(coder.MethodID)) + { + m.Id = (UInt32)coder.MethodID; + if (m.Id == k_BCJ2) + m.Id = k_BCJ; + m.SetDelta(); } - } - else if (IsExeFilter(coder.MethodID)) - { - m.Id = (UInt32)coder.MethodID; - if (m.Id == k_BCJ2) - m.Id = k_BCJ; - m.SetDelta(); } return GetGroup(filters, m); @@ -1577,7 +1581,7 @@ HRESULT Update( return E_NOTIMPL; */ - UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0; + UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); @@ -1591,8 +1595,21 @@ HRESULT Update( CRecordVector<CFilterMode2> filters; CObjectVector<CSolidGroup> groups; bool thereAreRepacks = false; + + bool useFilters = options.UseFilters; + if (useFilters) + { + const CCompressionMethodMode &method = *options.Method; + + FOR_VECTOR (i, method.Methods) + if (IsFilterMethod(method.Methods[i].Id)) + { + useFilters = false; + break; + } + } - if (db != 0) + if (db) { fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); unsigned i; @@ -1638,16 +1655,18 @@ HRESULT Update( CFolderEx f; db->ParseFolderEx(i, f); - bool isEncrypted = f.IsEncrypted(); - - unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f); + const bool isEncrypted = f.IsEncrypted(); + const bool needCopy = (numCopyItems == numUnpackStreams); + const bool extractFilter = (useFilters || needCopy); + + unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter); while (groupIndex >= groups.Size()) groups.AddNew(); groups[groupIndex].folderRefs.Add(rep); - if (numCopyItems == numUnpackStreams) + if (needCopy) complexity += db->GetFolderFullPackSize(i); else { @@ -1732,22 +1751,8 @@ HRESULT Update( // ---------- Split files to groups ---------- - bool useFilters = options.UseFilters; const CCompressionMethodMode &method = *options.Method; - if (useFilters) - for (i = 0; i < method.Methods.Size(); i++) - if (IsFilterMethod(method.Methods[i].Id)) - { - useFilters = false; - break; - } - - /* - if (!method.Bonds.IsEmpty()) - useFilters = false; - */ - for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -2156,7 +2161,13 @@ HRESULT Update( #ifndef _7ZIP_ST if (options.MultiThreadMixer) { + // 16.00: hang was fixed : for case if decoding was not finished. + // We close CBinderInStream and it calls CStreamBinder::CloseRead() + inStreamSizeCount.Release(); + sbInStream.Release(); + threadDecoder.WaitExecuteFinish(); + HRESULT decodeRes = threadDecoder.Result; // if (res == k_My_HRESULT_CRC_ERROR) if (decodeRes == S_FALSE) diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 9c841545..31aa5e1d 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -348,15 +348,19 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, CMyComPtr<IInStream> nextStream = inStream; bool prevChecked = false; + UString startVolName; + bool startVolName_was_Requested = false; UInt64 numItems = 0; unsigned numTempVolumes = 0; // try { - while (nextStream != NULL) + while (nextStream) { CDatabaseEx db; db.Stream = nextStream; + HRESULT res = archive.Open(db, maxCheckStartPosition); + _errorInHeaders |= archive.HeaderError; _errorInHeaders |= archive.ErrorInNames; _unexpectedEnd |= archive.UnexpectedEnd; @@ -426,6 +430,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, for (;;) { const COtherArc *otherArc = NULL; + if (!prevChecked) { if (numTempVolumes == 0) @@ -449,18 +454,35 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, } } } + if (!otherArc) { const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo; if (ai.IsThereNext()) otherArc = &ai.NextArc; } + if (!otherArc) break; if (!openVolumeCallback) break; // printf("\n%s", otherArc->FileName); const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP); + + if (!startVolName_was_Requested) + { + // some "bad" cab example can contain the link to itself. + startVolName_was_Requested = true; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt == VT_BSTR) + startVolName = prop.bstrVal; + } + if (fullName == startVolName) + break; + } + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_OK) break; diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index e39dbab5..2798bd71 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -578,14 +578,16 @@ HRESULT CDatabase::Open(IInStream *inStream) if (item.IsDir() || numCabs > 1) continue; bool isMsiName; - UString msiName = ConvertName(item.Name, isMsiName); + const UString msiName = ConvertName(item.Name, isMsiName); if (isMsiName && !msiName.IsEmpty()) { - bool isThereExt = (msiName.Find(L'.') >= 0); + // bool isThereExt = (msiName.Find(L'.') >= 0); bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") || !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe") - || !isMsiSpec && !isThereExt) + // || !isMsiSpec && !isThereExt + ) + { numCabs++; MainSubfile = i; diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 2a80e255..09952ac8 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -34,48 +34,35 @@ static const Byte k_Base64Table[256] = { - 64,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,62,77,64,77,63,52,53,54,55,56,57,58,59,60,61,77,77,77,77,77,77, - 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, - 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, - 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 + 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63, + 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77, + 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77, + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77 }; static Byte *Base64ToBin(Byte *dest, const char *src) { UInt32 val = 1; - UInt32 c = k_Base64Table[(Byte)(*src++)]; for (;;) { - /* - UInt32 c = (Byte)(*src++); - if (c >= 'A') - { - if (c <= 'Z') c -= 'A'; - else if (c >= 'a' && c <= 'z') c -= 'a' - 26; - else continue; - } - else if (c >= '0') - { - if (c <= '9') c += 52 - '0'; - else if (c == '=') break; - else continue; - } - else if (c == '+') c = 62; - else if (c == '/') c = 63; - else if (c == 0) break; - else continue; - */ + UInt32 c = k_Base64Table[(Byte)(*src++)]; - // UInt32 c = k_Base64Table[(Byte)(*src++)]; if (c < 64) { val = (val << 6) | c; - c = k_Base64Table[(Byte)(*src++)]; if ((val & ((UInt32)1 << 24)) == 0) continue; dest[0] = (Byte)(val >> 16); @@ -85,19 +72,41 @@ static Byte *Base64ToBin(Byte *dest, const char *src) val = 1; continue; } - if (c == 64) + + if (c == 65) // space + continue; + + if (c == 64) // '=' break; - c = k_Base64Table[(Byte)(*src++)]; + + if (c == 66 && val == 1) // end of string + return dest; + + return NULL; } - if (val >= ((UInt32)1 << 12)) + if (val < (1 << 12)) + return NULL; + + if (val & (1 << 18)) { - if (val >= ((UInt32)1 << 18)) - *dest++ = (Byte)(val >> 16); - *dest++ = (Byte)(val); + *dest++ = (Byte)(val >> 10); + *dest++ = (Byte)(val >> 2); + } + else if (k_Base64Table[(Byte)(*src++)] != 64) // '=' + return NULL; + else + *dest++ = (Byte)(val >> 4); + + for (;;) + { + Byte c = k_Base64Table[(Byte)(*src++)]; + if (c == 65) // space + continue; + if (c == 66) // end of string + return dest; + return NULL; } - - return dest; } @@ -720,7 +729,13 @@ HRESULT CHandler::Open2(IInStream *stream) return S_FALSE; destLen = dataString->Len() / 4 * 3 + 4; rawBuf.Alloc(destLen); - destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf); + { + const Byte *endPtr = Base64ToBin(rawBuf, *dataString); + if (!endPtr) + return S_FALSE; + destLen = (unsigned)(endPtr - rawBuf); + } + #ifdef DMG_SHOW_RAW CExtraFile &extra = _extras.AddNew(); { diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index e54b1477..53e941c7 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp @@ -87,6 +87,9 @@ struct CPartType static const CPartType kPartTypes[] = { // { 0x0, 0, "Unused" }, + + { 0x21686148, 0, "BIOS Boot" }, + { 0xC12A7328, 0, "EFI System" }, { 0x024DEE41, 0, "MBR" }, @@ -98,10 +101,13 @@ static const CPartType kPartTypes[] = // { 0x37AFFC90, 0, "IBM GPFS" }, // { 0xE75CAF8F, 0, "Windows Storage Spaces" }, - { 0x83BD6B9D, 0, "FreeBSD Boot" }, + { 0x0FC63DAF, 0, "Linux Data" }, + { 0x0657FD6D, 0, "Linux Swap" }, + + { 0x83BD6B9D, 0, "FreeBSD Boot" }, { 0x516E7CB4, 0, "FreeBSD Data" }, { 0x516E7CB5, 0, "FreeBSD Swap" }, - { 0x516E7CB6, "ufs", "FreeBSD UFS" }, + { 0x516E7CB6, "ufs", "FreeBSD UFS" }, { 0x516E7CB8, 0, "FreeBSD Vinum" }, { 0x516E7CB8, "zfs", "FreeBSD ZFS" }, @@ -335,6 +341,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; s += c; } + if (s.IsEmpty()) + { + char temp[16]; + ConvertUInt32ToString(index, temp); + s.AddAscii(temp); + } { int typeIndex = FindPartType(item.Type); s += L'.'; diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index 8459280d..057a2d79 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -987,7 +987,9 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents item.GroupID = Get32(r + 0x24); item.AdminFlags = r[0x28]; item.OwnerFlags = r[0x29]; + */ item.FileMode = Get16(r + 0x2A); + /* item.special.iNodeNum = Get16(r + 0x2C); // or .linkCount item.FileType = Get32(r + 0x30); item.FileCreator = Get32(r + 0x34); @@ -1572,6 +1574,9 @@ HRESULT CHandler::ExtractZlibFile( UInt32 size = GetUi32(tableBuf + i * 8 + 4); + if (size > buf.Size() || size > kCompressionBlockSize + 1) + return S_FALSE; + RINOK(ReadStream_FALSE(inStream, buf, size)); if ((buf[0] & 0xF) == 0xF) diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index 2603afdb..ce154264 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -79,7 +79,7 @@ struct CDirRecord while (rem >= 5) { unsigned len = p[2]; - if (len > rem) + if (len < 3 || len > rem) return 0; if (p[0] == 'N' && p[1] == 'M' && p[3] == 1) { diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index e4ac2a42..121cd67c 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -110,7 +110,7 @@ HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) { _filterCoder = new CFilterCoder(false); CMyComPtr<ICompressCoder> coder = _filterCoder; - _filterCoder->Filter = new CBcjCoder(false); + _filterCoder->Filter = new NCompress::NBcj::CCoder(false); _bcjStream = _filterCoder; } } diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp index 68243129..0bbf6094 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -59,7 +59,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) { _filter = new CFilterCoder(false); _filterInStream = _filter; - _filter->Filter = new CBcjCoder(false); + _filter->Filter = new NCompress::NBcj::CCoder(false); } RINOK(_filter->SetInStream(_codecInStream)); _decoderInStream = _filterInStream; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index 6ca87df4..e04a97a8 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -88,7 +88,7 @@ enum EW_SENDMESSAGE, // SendMessage EW_ISWINDOW, // IsWindow EW_GETDLGITEM, // GetDlgItem - EW_SETCTLCOLORS, // SerCtlColors + EW_SETCTLCOLORS, // SetCtlColors EW_SETBRANDINGIMAGE, // SetBrandingImage EW_CREATEFONT, // CreateFont EW_SHOWWINDOW, // ShowWindow, EnableWindow, HideWindow @@ -1155,9 +1155,13 @@ bool CInArchive::IsGoodString(UInt32 param) const if (param == 0) return true; const Byte *p = _data + _stringsPos; + unsigned c; if (IsUnicode) - return (Get16(p + param * 2 - 2)) == 0; - return p[param - 1] == 0; + c = Get16(p + param * 2 - 2); + else + c = p[param - 1]; + // some files have '\\' character before string? + return (c == 0 || c == '\\'); } bool CInArchive::AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const @@ -1509,7 +1513,7 @@ static const UInt32 CMD_REF_Pre = (1 << 2); static const UInt32 CMD_REF_Show = (1 << 3); static const UInt32 CMD_REF_Leave = (1 << 4); static const UInt32 CMD_REF_OnFunc = (1 << 5); -static const UInt32 CMD_REF_Section = (1 << 6); +static const UInt32 CMD_REF_Section = (1 << 6); static const UInt32 CMD_REF_InitPluginDir = (1 << 7); // static const UInt32 CMD_REF_Creator = (1 << 5); // _Pre is used instead static const unsigned CMD_REF_OnFunc_NumShifts = 28; // it uses for onFunc too @@ -3357,7 +3361,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) #ifdef NSIS_SCRIPT s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; - AddParam(params[0]); + AddParam(params[0]); #endif break; @@ -3571,15 +3575,16 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) AddParam(params[0]); - SmallSpaceComment(); - /* for (int i = 1; i < 3; i++) AddParam_UInt(params[i]); */ if (params[3] != 0) + { + SmallSpaceComment(); AddParam(params[3]); + } #endif diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 498784b8..d8e6808b 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -421,7 +421,11 @@ public: const char *kRemoveStr = "$INSTDIR\\"; if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr)) + { s.Delete(0, MyStringLen(kRemoveStr)); + if (s[0] == L'\\') + s.DeleteFrontal(1); + } if (item.IsUninstaller && ExeStub.Size() == 0) s += L".nsis"; return s; diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index fa4bbc9c..25f4c8a6 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -1148,8 +1148,16 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r return false; if (usaOffset >= 0x30) // NTFS 3.1+ - if (Get32(p + 0x2C) != recNumber) - return false; + { + UInt32 iii = Get32(p + 0x2C); + if (iii != recNumber) + { + // ntfs-3g probably writes 0 (that probably is incorrect value) to this field for unused records. + // so we support that "bad" case. + if (iii != 0) + return false; + } + } UInt16 usn = Get16(p + usaOffset); // PRF(printf("\nusn = %d", usn)); diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 28562007..160648f6 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -347,8 +347,8 @@ struct CSection CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} - // const UInt32 GetSize() const { return PSize; } - const UInt32 GetSize() const { return MyMin(PSize, VSize); } + const UInt32 GetSizeExtract() const { return PSize; } + const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } void UpdateTotalSize(UInt32 &totalSize) const { @@ -362,8 +362,8 @@ struct CSection int Compare(const CSection &s) const { RINOZ(MyCompare(Pa, s.Pa)); - UInt32 size1 = GetSize(); - UInt32 size2 = s.GetSize(); + UInt32 size1 = GetSizeExtract(); + UInt32 size2 = s.GetSizeExtract(); return MyCompare(size1, size2); } }; @@ -1045,7 +1045,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch (propID) { case kpidPath: prop = MultiByteToUnicodeString(item.Name); break; - case kpidSize: prop = (UInt64)item.GetSize(); break; + case kpidSize: prop = (UInt64)item.PSize; break; case kpidPackSize: prop = (UInt64)item.PSize; break; case kpidVirtualSize: prop = (UInt64)item.VSize; break; case kpidOffset: prop = item.Pa; break; @@ -1898,7 +1898,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchiveOpenCallback *callback) { const CSection § = _sections[sectionIndex]; - const size_t fileSize = sect.GetSize(); + const size_t fileSize = sect.GetSizeMin(); if (fileSize > kFileSizeMax) return S_FALSE; @@ -1926,6 +1926,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi _oneLang = true; bool stringsOk = true; size_t maxOffset = 0; + FOR_VECTOR (i, specItems) { const CTableItem &item1 = specItems[i]; @@ -2007,6 +2008,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi } // PrintError("ver.Parse error"); } + item.Enabled = true; _items.Add(item); } @@ -2041,7 +2043,10 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi UInt32 mask = (1 << numBits) - 1; size_t end = ((maxOffset + mask) & ~mask); - if (/* end < sect.VSize && */ end <= sect.GetSize()) + // PSize can be much larger than VSize in some exe installers. + // it contains archive data after PE resources. + // So we need to use PSize here! + if (/* end < sect.VSize && */ end <= sect.PSize) { CSection sect2; sect2.Flags = 0; @@ -2059,7 +2064,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX // the code for .rsrc_2 is commented. - sect2.PSize = sect.GetSize() - (UInt32)maxOffset; + sect2.PSize = sect.PSize - (UInt32)maxOffset; if (sect2.PSize != 0) { @@ -2473,7 +2478,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else if (mixItem.ResourceIndex >= 0) size = _items[mixItem.ResourceIndex].GetSize(); else - size = _sections[mixItem.SectionIndex].GetSize(); + size = _sections[mixItem.SectionIndex].GetSizeExtract(); totalSize += size; } extractCallback->SetTotal(totalSize); @@ -2549,7 +2554,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else { - currentItemSize = sect.GetSize(); + currentItemSize = sect.GetSizeExtract(); if (!testMode && !outStream) continue; diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index 131f2c9b..959c2e36 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -2333,6 +2333,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { UInt64 total = 0; + bool isThereUndefinedSize = false; bool thereAreLinks = false; { @@ -2342,9 +2343,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, unsigned index = allFilesMode ? t : indices[t]; const CRefItem &ref = _refs[index]; const CItem &item = _items[ref.Item]; + const CItem &lastItem = _items[ref.Last]; extractStatuses[index] |= kStatus_Extract; - total += item.Size; + + if (!lastItem.Is_UnknownSize()) + total += lastItem.Size; + else + isThereUndefinedSize = true; if (ref.Link >= 0) { @@ -2352,11 +2358,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if ((unsigned)ref.Link < index) { - const CItem &linkItem = _items[_refs[(unsigned)ref.Link].Item]; + const CRefItem &linkRef = _refs[(unsigned)ref.Link]; + const CItem &linkItem = _items[linkRef.Item]; if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize) { if (extractStatuses[(unsigned)ref.Link] == 0) - total += linkItem.Size; + { + const CItem &lastLinkItem = _items[linkRef.Last]; + if (!lastLinkItem.Is_UnknownSize()) + total += lastLinkItem.Size; + else + isThereUndefinedSize = true; + } extractStatuses[(unsigned)ref.Link] |= kStatus_Link; thereAreLinks = true; } @@ -2375,11 +2388,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, while (j > solidLimit) { j--; - const CItem &item2 = _items[_refs[j].Item]; + const CRefItem &ref2 = _refs[j]; + const CItem &item2 = _items[ref2.Item]; if (!item2.IsService()) { if (extractStatuses[j] == 0) - total += item2.Size; + { + const CItem &lastItem2 = _items[ref2.Last]; + if (!lastItem2.Is_UnknownSize()) + total += lastItem2.Size; + else + isThereUndefinedSize = true; + } extractStatuses[j] |= kStatus_Skip; if (!item2.IsSolid()) break; @@ -2415,13 +2435,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, while (j > solidLimit) { j--; - const CItem &item2 = _items[_refs[j].Item]; + const CRefItem &ref2 = _refs[j]; + const CItem &item2 = _items[ref2.Item]; if (!item2.IsService()) { if (extractStatuses[j] != 0) break; extractStatuses[j] = kStatus_Skip; - total += item2.Size; + { + const CItem &lastItem2 = _items[ref2.Last]; + if (!lastItem2.Is_UnknownSize()) + total += lastItem2.Size; + else + isThereUndefinedSize = true; + } if (!item2.IsSolid()) break; } @@ -2449,7 +2476,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } - RINOK(extractCallback->SetTotal(total)); + if (total != 0 || !isThereUndefinedSize) + { + RINOK(extractCallback->SetTotal(total)); + } } @@ -2502,8 +2532,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CRefItem *ref = &_refs[index]; const CItem *item = &_items[ref->Item]; + const CItem &lastItem = _items[ref->Last]; + + curUnpackSize = 0; + if (!lastItem.Is_UnknownSize()) + curUnpackSize = lastItem.Size; - curUnpackSize = item->Size; curPackSize = GetPackSize(index); RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); @@ -2532,11 +2566,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { const CRefItem &ref2 = _refs[index2]; const CItem &item2 = _items[ref2.Item]; + const CItem &lastItem2 = _items[ref2.Last]; if (!item2.IsSolid()) { item = &item2; ref = &ref2; - curUnpackSize = item->Size; + if (!lastItem2.Is_UnknownSize()) + curUnpackSize = lastItem2.Size; + else + curUnpackSize = 0; curPackSize = GetPackSize(index2); } else if ((unsigned)index2 < index) diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 3b5924b4..6f3e0a0c 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -953,6 +953,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val NCOM::CPropVariant prop; const CRefItem &refItem = _refItems[index]; const CItem &item = _items[refItem.ItemIndex]; + const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + /* const CItem *mainItem = &item; if (item.BaseFileIndex >= 0) @@ -972,7 +974,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; + case kpidSize: if (lastItem.Is_Size_Defined()) prop = lastItem.Size; break; case kpidPackSize: prop = GetPackSize(index); break; case kpidMTime: RarTimeToProp(item.MTime, prop); break; case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break; @@ -985,7 +987,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break; case kpidCRC: { - const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC); break; } @@ -1378,34 +1379,52 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CRecordVector<unsigned> importantIndexes; CRecordVector<bool> extractStatuses; + bool isThereUndefinedSize = false; + for (UInt32 t = 0; t < numItems; t++) { unsigned index = allFilesMode ? t : indices[t]; - const CRefItem &refItem = _refItems[index]; - const CItem &item = _items[refItem.ItemIndex]; - censoredTotalUnPacked += item.Size; - // censoredTotalPacked += item.PackSize; + + { + const CRefItem &refItem = _refItems[index]; + const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1]; + + if (item.Is_Size_Defined()) + censoredTotalUnPacked += item.Size; + else + isThereUndefinedSize = true; + + // censoredTotalPacked += item.PackSize; + } + unsigned j; for (j = lastIndex; j <= index; j++) // if (!_items[_refItems[j].ItemIndex].IsSolid()) if (!IsSolid(j)) lastIndex = j; + for (j = lastIndex; j <= index; j++) { const CRefItem &refItem = _refItems[j]; - const CItem &item = _items[refItem.ItemIndex]; + const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1]; - // const CItem &item = _items[j]; - - importantTotalUnPacked += item.Size; + if (item.Is_Size_Defined()) + importantTotalUnPacked += item.Size; + else + isThereUndefinedSize = true; // importantTotalPacked += item.PackSize; importantIndexes.Add(j); extractStatuses.Add(j == index); } + lastIndex = index + 1; } - RINOK(extractCallback->SetTotal(importantTotalUnPacked)); + if (importantTotalUnPacked != 0 || !isThereUndefinedSize) + { + RINOK(extractCallback->SetTotal(importantTotalUnPacked)); + } + UInt64 currentImportantTotalUnPacked = 0; UInt64 currentImportantTotalPacked = 0; UInt64 currentUnPackSize, currentPackSize; @@ -1431,13 +1450,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lps->Init(extractCallback, false); bool solidStart = true; - for (unsigned i = 0; i < importantIndexes.Size(); i++, + + for (unsigned i = 0;; + i++, currentImportantTotalUnPacked += currentUnPackSize, currentImportantTotalPacked += currentPackSize) { lps->InSize = currentImportantTotalPacked; lps->OutSize = currentImportantTotalUnPacked; RINOK(lps->SetCur()); + + if (i >= importantIndexes.Size()) + break; + CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; @@ -1452,8 +1477,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CRefItem &refItem = _refItems[index]; const CItem &item = _items[refItem.ItemIndex]; - - currentUnPackSize = item.Size; + const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + + UInt64 outSize = (UInt64)(Int64)-1; + currentUnPackSize = 0; + if (lastItem.Is_Size_Defined()) + { + outSize = lastItem.Size; + currentUnPackSize = outSize; + } currentPackSize = GetPackSize(index); @@ -1678,12 +1710,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; } - HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); + HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, progress); if (item.IsEncrypted()) filterStreamSpec->ReleaseInStream(); - const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + if (outSize == (UInt64)(Int64)-1) + currentUnPackSize = outStreamSpec->GetSize(); + int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ? NExtract::NOperationResult::kOK: NExtract::NOperationResult::kCRCError; diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h index 13daa1cb..10e21c57 100644 --- a/CPP/7zip/Archive/Rar/RarItem.h +++ b/CPP/7zip/Archive/Rar/RarItem.h @@ -42,6 +42,8 @@ struct CItem Byte Salt[8]; + bool Is_Size_Defined() const { return Size != (UInt64)(Int64)-1; } + bool IsEncrypted() const { return (Flags & NHeader::NFile::kEncrypted) != 0; } bool IsSolid() const { return (Flags & NHeader::NFile::kSolid) != 0; } bool IsCommented() const { return (Flags & NHeader::NFile::kComment) != 0; } diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 23187064..4ca417e0 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -187,11 +187,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) UInt64 size; { + /* NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; + */ + RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } _totalSize += size; @@ -217,11 +221,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (!stream) break; { + /* NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; + */ + RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } _totalSize += size; _sizes.Add(size); diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index a051a271..908f2356 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -389,7 +389,10 @@ HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc return S_FALSE; CFile &file = Files.Back(); const CLogVol &vol = LogVols[volIndex]; - CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex]; + unsigned partitionRef = lad.Location.PartitionRef; + if (partitionRef >= vol.PartitionMaps.Size()) + return S_FALSE; + CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; UInt32 key = lad.Location.Pos; UInt32 value; diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 910de06d..e6bc21f6 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -475,14 +475,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPackSize: { - UInt64 size = 0; if (si) { if (!si->Resource.IsSolidSmall()) - { - size = si->Resource.PackSize; - prop = size; - } + prop = si->Resource.PackSize; else { if (si->Resource.SolidIndex >= 0) @@ -493,12 +489,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } } } + else if (!item.IsDir) + prop = (UInt64)0; + break; } case kpidSize: { - UInt64 size = 0; if (si) { if (si->Resource.IsSolid()) @@ -507,22 +505,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { if (si->Resource.SolidIndex >= 0) { - CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex]; + const CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex]; prop = ss.UnpackSize; } } else - { - size = si->Resource.PackSize; - prop = size; - } + prop = si->Resource.PackSize; } else - { - size = si->Resource.UnpackSize; - prop = size; - } + prop = si->Resource.UnpackSize; } + else if (!item.IsDir) + prop = (UInt64)0; + break; } diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 11f4b444..318be190 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -10,6 +10,8 @@ #include "../../Common/Defs.h" #include "../../Common/IntToString.h" +#include "../../Windows/PropVariant.h" + #include "../ICoder.h" #include "../Common/CWrappers.h" @@ -21,7 +23,9 @@ #include "IArchive.h" +#ifndef EXTRACT_ONLY #include "Common/HandlerOut.h" +#endif #include "XzHandler.h" @@ -83,14 +87,19 @@ class CHandler: CMyComPtr<IInStream> _stream; CMyComPtr<ISequentialInStream> _seqStream; - UInt32 _filterId; AString _methodsString; + #ifndef EXTRACT_ONLY + + UInt32 _filterId; + void Init() { _filterId = 0; CMultiMethodProps::Init(); } + + #endif HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); @@ -126,9 +135,12 @@ public: CHandler::CHandler() { + #ifndef EXTRACT_ONLY Init(); + #endif } + static const Byte kProps[] = { kpidSize, diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 092dcbc9..75034de0 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -12,6 +12,7 @@ #include "../../IPassword.h" #include "../../Common/FilterCoder.h" +#include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" @@ -142,14 +143,19 @@ static const Byte kProps[] = kpidCRC, kpidMethod, kpidHostOS, - kpidUnpackVer + kpidUnpackVer, + kpidVolumeIndex }; static const Byte kArcProps[] = { kpidEmbeddedStubSize, kpidBit64, - kpidComment + kpidComment, + kpidTotalPhySize, + kpidIsVolume, + kpidVolumeIndex, + kpidNumVolumes }; CHandler::CHandler() @@ -175,18 +181,23 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break; case kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; - case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break; - case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */ - prop = m_Archive.ArcInfo.Base; break; + + case kpidPhySize: prop = m_Archive.GetPhySize(); break; + case kpidOffset: prop = m_Archive.GetOffset(); break; case kpidEmbeddedStubSize: { - UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); + UInt64 stubSize = m_Archive.GetEmbeddedStubSize(); if (stubSize != 0) prop = stubSize; break; } + case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTotalSize(); break; + case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break; + case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break; + case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break; + case kpidWarningFlags: { UInt32 v = 0; @@ -197,6 +208,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } + case kpidError: + { + if (!m_Archive.Vols.MissingName.IsEmpty()) + { + UString s; + s.SetFromAscii("Missing volume : "); + s += m_Archive.Vols.MissingName; + prop = s; + } + break; + } + case kpidErrorFlags: { UInt32 v = 0; @@ -209,7 +232,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) but the stream has access only to zip part. In that case we ignore UnavailableStart error. maybe we must show warning in that case. */ - UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); + UInt64 stubSize = m_Archive.GetEmbeddedStubSize(); if (stubSize < (UInt64)-m_Archive.ArcInfo.Base) v |= kpv_ErrorFlags_UnavailableStart; } @@ -429,6 +452,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidUnpackVer: prop = (UInt32)item.ExtractVersion.Version; break; + + case kpidVolumeIndex: + prop = item.Disk; + break; } prop.Detach(value); @@ -436,30 +463,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -class CProgressImp: public CProgressVirt -{ - CMyComPtr<IArchiveOpenCallback> _callback; -public: - virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes); - virtual HRESULT SetTotalCD(UInt64 numFiles); - virtual HRESULT SetCompletedCD(UInt64 numFiles); - CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} -}; - -HRESULT CProgressImp::SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) -{ - return _callback->SetCompleted(&numFiles, &numBytes); -} - -HRESULT CProgressImp::SetTotalCD(UInt64 numFiles) -{ - return _callback->SetTotal(&numFiles, NULL); -} - -HRESULT CProgressImp::SetCompletedCD(UInt64 numFiles) -{ - return _callback->SetCompleted(&numFiles, NULL); -} STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) @@ -468,9 +471,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, try { Close(); - RINOK(m_Archive.Open(inStream, maxCheckStartPosition)); - CProgressImp progressImp(callback); - return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL); + HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_Items); + if (res != S_OK) + { + m_Items.Clear(); + m_Archive.ClearRefs(); + } + return res; } catch(...) { Close(); throw; } COM_TRY_END @@ -483,8 +490,6 @@ STDMETHODIMP CHandler::Close() return S_OK; } -////////////////////////////////////// -// CHandler::DecompressItems class CLzmaDecoder: public ICompressCoder, @@ -550,6 +555,8 @@ struct CMethodItem CMyComPtr<ICompressCoder> Coder; }; + + class CZipDecoder { NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec; @@ -584,6 +591,24 @@ public: Int32 &res); }; + +static HRESULT SkipStreamData(ISequentialInStream *stream, UInt64 size) +{ + const size_t kBufSize = 1 << 12; + Byte buf[kBufSize]; + for (;;) + { + if (size == 0) + return S_OK; + size_t curSize = kBufSize; + if (curSize > size) + curSize = (size_t)size; + RINOK(ReadStream_FALSE(stream, buf, curSize)); + size -= curSize; + } +} + + HRESULT CZipDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS CInArchive &archive, const CItemEx &item, @@ -634,9 +659,11 @@ HRESULT CZipDecoder::Decode( outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(needCRC); - UInt64 authenticationPos; - - CMyComPtr<ISequentialInStream> inStream; + CMyComPtr<ISequentialInStream> packStream; + + CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(limitedStreamSpec); + { UInt64 packSize = item.PackSize; if (wzAesMode) @@ -645,9 +672,14 @@ HRESULT CZipDecoder::Decode( return S_OK; packSize -= NCrypto::NWzAes::kMacSize; } - UInt64 dataPos = item.GetDataPosition(); - inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); - authenticationPos = dataPos + packSize; + RINOK(archive.GetItemStream(item, true, packStream)); + if (!packStream) + { + res = NExtract::NOperationResult::kUnavailable; + return S_OK; + } + limitedStreamSpec->SetStream(packStream); + limitedStreamSpec->Init(packSize); } CMyComPtr<ICompressFilter> cryptoFilter; @@ -912,9 +944,15 @@ HRESULT CZipDecoder::Decode( bool authOk = true; if (needCRC) crcOK = (outStreamSpec->GetCRC() == item.Crc); + if (wzAesMode) { - inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize)); + const UInt64 rem = limitedStreamSpec->GetRem(); + if (rem != 0) + if (SkipStreamData(inStream, rem) != S_OK) + authOk = false; + + limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) authOk = false; } @@ -988,16 +1026,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable)); continue; } + if (!item.FromLocal) { - HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); + bool isAvail = true; + HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail); if (res == S_FALSE) { if (item.IsDir() || realOutStream || testMode) { RINOK(extractCallback->PrepareOperation(askMode)); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError)); + RINOK(extractCallback->SetOperationResult( + isAvail ? + NExtract::NOperationResult::kHeadersError : + NExtract::NOperationResult::kUnavailable)); } continue; } @@ -1034,6 +1077,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(res)) } + lps->InSize = currentTotalPacked; lps->OutSize = currentTotalUnPacked; return lps->SetCur(); diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 82e46eb6..fead0192 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -18,9 +18,8 @@ namespace NSignature const UInt32 kEcd = 0x06054B50; const UInt32 kEcd64 = 0x06064B50; const UInt32 kEcd64Locator = 0x07064B50; - - // const UInt32 kSpan = 0x08074B50; - const UInt32 kNoSpan = 0x30304b50; // PK00, replaces kSpan, if there is only 1 segment + const UInt32 kSpan = 0x08074B50; + const UInt32 kNoSpan = 0x30304B50; // PK00, replaces kSpan, if there is only 1 segment } const unsigned kLocalHeaderSize = 4 + 26; // including signature diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 2ba7e3fa..fe5200f7 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -5,8 +5,11 @@ // #include <stdio.h> #include "../../../Common/DynamicBuffer.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/PropVariant.h" -#include "../../Common/LimitedStreams.h" #include "../../Common/StreamUtils.h" #include "../IArchive.h" @@ -17,100 +20,133 @@ #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) +#define G16(offs, v) v = Get16(p + (offs)) +#define G32(offs, v) v = Get32(p + (offs)) +#define G64(offs, v) v = Get64(p + (offs)) + namespace NArchive { namespace NZip { struct CEcd { - UInt16 thisDiskNumber; - UInt16 startCDDiskNumber; - UInt16 numEntriesInCDOnThisDisk; - UInt16 numEntriesInCD; - UInt32 cdSize; - UInt32 cdStartOffset; - UInt16 commentSize; + UInt16 ThisDisk; + UInt16 CdDisk; + UInt16 NumEntries_in_ThisDisk; + UInt16 NumEntries; + UInt32 Size; + UInt32 Offset; + UInt16 CommentSize; - void Parse(const Byte *p); - - bool IsEmptyArc() + bool IsEmptyArc() const { - return thisDiskNumber == 0 && startCDDiskNumber == 0 && - numEntriesInCDOnThisDisk == 0 && numEntriesInCD == 0 && cdSize == 0 - && cdStartOffset == 0 // test it + return ThisDisk == 0 + && CdDisk == 0 + && NumEntries_in_ThisDisk == 0 + && NumEntries == 0 + && Size == 0 + && Offset == 0 // test it ; } + + void Parse(const Byte *p); // (p) doesn't include signature }; void CEcd::Parse(const Byte *p) { - thisDiskNumber = Get16(p); - startCDDiskNumber = Get16(p + 2); - numEntriesInCDOnThisDisk = Get16(p + 4); - numEntriesInCD = Get16(p + 6); - cdSize = Get32(p + 8); - cdStartOffset = Get32(p + 12); - commentSize = Get16(p + 16); + // (p) doesn't include signature + G16(0, ThisDisk); + G16(2, CdDisk); + G16(4, NumEntries_in_ThisDisk); + G16(6, NumEntries); + G32(8, Size); + G32(12, Offset); + G16(16, CommentSize); } -struct CEcd64 + +void CCdInfo::ParseEcd32(const Byte *p) { - UInt16 versionMade; - UInt16 versionNeedExtract; - UInt32 thisDiskNumber; - UInt32 startCDDiskNumber; - UInt64 numEntriesInCDOnThisDisk; - UInt64 numEntriesInCD; - UInt64 cdSize; - UInt64 cdStartOffset; - - void Parse(const Byte *p); - CEcd64() { memset(this, 0, sizeof(*this)); } -}; + // (p) includes signature + p += 4; + G16(0, ThisDisk); + G16(2, CdDisk); + G16(4, NumEntries_in_ThisDisk); + G16(6, NumEntries); + G32(8, Size); + G32(12, Offset); + G16(16, CommentSize); +} -void CEcd64::Parse(const Byte *p) +void CCdInfo::ParseEcd64e(const Byte *p) { - versionMade = Get16(p); - versionNeedExtract = Get16(p + 2); - thisDiskNumber = Get32(p + 4); - startCDDiskNumber = Get32(p + 8); - numEntriesInCDOnThisDisk = Get64(p + 12); - numEntriesInCD = Get64(p + 20); - cdSize = Get64(p + 28); - cdStartOffset = Get64(p + 36); + // (p) exclude signature + G16(0, VersionMade); + G16(2, VersionNeedExtract); + G32(4, ThisDisk); + G32(8, CdDisk); + + G64(12, NumEntries_in_ThisDisk); + G64(20, NumEntries); + G64(28, Size); + G64(36, Offset); } -HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) + +struct CLocator { - _inBufMode = false; - Close(); - RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos)); - RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); + UInt32 Ecd64Disk; + UInt32 NumDisks; + UInt64 Ecd64Offset; + + CLocator(): Ecd64Disk(0), NumDisks(0), Ecd64Offset(0) {} - // printf("\nOpen offset = %d", (int)m_Position); - RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit)); - RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); - Stream = stream; - return S_OK; + void Parse(const Byte *p) + { + G32(0, Ecd64Disk); + G64(4, Ecd64Offset); + G32(12, NumDisks); + } +}; + + + + +void CInArchive::ClearRefs() +{ + StreamRef.Release(); + Stream = NULL; + StartStream = NULL; + Callback = NULL; + + Vols.Clear(); } void CInArchive::Close() { + _processedCnt = 0; IsArc = false; + IsArcOpen = false; + IsMultiVol = false; + UseDisk_in_SingleVol = false; + EcdVolIndex = 0; HeadersError = false; HeadersWarning = false; ExtraMinorError = false; UnexpectedEnd = false; NoCentralDir = false; IsZip64 = false; - Stream.Release(); + MarkerIsFound = false; + + ClearRefs(); } + HRESULT CInArchive::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); } + static bool CheckDosTime(UInt32 dosTime) { if (dosTime == 0) @@ -134,7 +170,8 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) UInt32 value = Get32(p); - if (value == NSignature::kNoSpan) + if (value == NSignature::kNoSpan + || value == NSignature::kSpan) { p += 4; size -= 4; @@ -250,28 +287,35 @@ static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal) return res; } -HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLimit) + + +HRESULT CInArchive::FindMarker(IInStream *stream, const UInt64 *searchLimit) { - ArcInfo.Clear(); ArcInfo.MarkerPos = m_Position; ArcInfo.MarkerPos2 = m_Position; if (searchLimit && *searchLimit == 0) { - const unsigned kStartBufSize = kMarkerSize; - Byte startBuf[kStartBufSize]; - size_t processed = kStartBufSize; + Byte startBuf[kMarkerSize]; + size_t processed = kMarkerSize; RINOK(ReadStream(stream, startBuf, &processed)); m_Position += processed; if (processed < kMarkerSize) return S_FALSE; m_Signature = Get32(startBuf); + if (m_Signature != NSignature::kEcd && m_Signature != NSignature::kLocalFileHeader) { if (m_Signature != NSignature::kNoSpan) - return S_FALSE; - size_t processed = kStartBufSize; + { + if (m_Signature != NSignature::kSpan) + return S_FALSE; + if (m_Position != 4) // we don't support multivol archives with sfx stub + return S_FALSE; + ArcInfo.IsSpanMode = true; + } + size_t processed = kMarkerSize; RINOK(ReadStream(stream, startBuf, &processed)); m_Position += processed; if (processed < kMarkerSize) @@ -283,9 +327,8 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim ArcInfo.MarkerPos2 += 4; } - // we use weak test in case of *searchLimit == 0) + // we use weak test in case of (*searchLimit == 0) // since error will be detected later in Open function - // m_Position = ArcInfo.MarkerPos2 + 4; return S_OK; // maybe we need to search backward. } @@ -302,9 +345,17 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes)); m_Position += numReadBytes; numBytesInBuffer += numReadBytes; - bool isFinished = (numBytesInBuffer != kBufSize); + const bool isFinished = (numBytesInBuffer != kBufSize); - size_t limit = (isFinished ? numBytesInBuffer : numBytesInBuffer - kCheckSize); + size_t limit = numBytesInBuffer;; + if (isFinished) + { + if (limit == 0) + break; + limit--; + } + else + limit -= kCheckSize; if (searchLimit && curScanPos + limit > *searchLimit) limit = (size_t)(*searchLimit - curScanPos + 1); @@ -328,7 +379,8 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim m_Signature = Get32(buf + pos); ArcInfo.MarkerPos += curScanPos + pos; ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; - if (m_Signature == NSignature::kNoSpan) + if (m_Signature == NSignature::kNoSpan + || m_Signature == NSignature::kSpan) { m_Signature = Get32(buf + pos + 4); ArcInfo.MarkerPos2 += 4; @@ -349,13 +401,86 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim return S_FALSE; } -HRESULT CInArchive::IncreaseRealPosition(Int64 addValue) + +HRESULT CInArchive::IncreaseRealPosition(Int64 addValue, bool &isFinished) { - return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); + isFinished = false; + if (!IsMultiVol) + return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); + + for (;;) + { + if (addValue == 0) + return S_OK; + if (addValue > 0) + { + if (Vols.StreamIndex < 0) + return S_FALSE; + if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) + { + isFinished = true; + return S_OK; + } + { + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; + if (!s.Stream) + { + isFinished = true; + return S_OK; + } + if (m_Position > s.Size) + return S_FALSE; + UInt64 rem = s.Size - m_Position; + if ((UInt64)addValue <= rem) + return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); + RINOK(Stream->Seek(s.Size, STREAM_SEEK_SET, &m_Position)); + addValue -= rem; + Stream = NULL; + Vols.StreamIndex++; + if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) + { + isFinished = true; + return S_OK; + } + } + const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; + if (!s2.Stream) + { + isFinished = true; + return S_OK; + } + Stream = s2.Stream; + m_Position = 0; + RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position)); + } + else + { + if (!Stream) + return S_FALSE; + { + if (m_Position >= (UInt64)(-addValue)) + return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); + addValue += m_Position; + RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position)); + m_Position = 0; + Stream = NULL; + if (--Vols.StreamIndex < 0) + return S_FALSE; + } + const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; + if (!s2.Stream) + return S_FALSE; + Stream = s2.Stream; + m_Position = s2.Size; + RINOK(Stream->Seek(s2.Size, STREAM_SEEK_SET, &m_Position)); + } + } } + class CUnexpectEnd {}; + HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { size_t realProcessedSize = size; @@ -376,18 +501,46 @@ HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) void CInArchive::SafeReadBytes(void *data, unsigned size) { size_t processed = size; - if (_inBufMode) - { - processed = _inBuffer.ReadBytes((Byte *)data, size); - m_Position += processed; - } + + HRESULT result = S_OK; + + if (!_inBufMode) + result = ReadStream(Stream, data, &processed); else { - HRESULT result = ReadStream(Stream, data, &processed); - m_Position += processed; - if (result != S_OK) - throw CSystemException(result); + for (;;) + { + processed = _inBuffer.ReadBytes((Byte *)data, size); + if (processed != 0 + || IsMultiVol + || !CanStartNewVol + || Vols.StreamIndex < 0 + || (unsigned)Vols.StreamIndex >= Vols.Streams.Size()) + break; + Vols.StreamIndex++; + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; + if (!s.Stream) + break; + // if (Vols.NeedSeek) + { + result = s.Stream->Seek(0, STREAM_SEEK_SET, NULL); + m_Position = 0; + if (result != S_OK) + break; + Vols.NeedSeek = false; + } + _inBuffer.SetStream(s.Stream); + _inBuffer.Init(); + } + CanStartNewVol = false; } + + m_Position += processed; + _processedCnt += processed; + + if (result != S_OK) + throw CSystemException(result); + if (processed != size) throw CUnexpectEnd(); } @@ -410,12 +563,15 @@ UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeReadBytes(buf, 2); return Get UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeReadBytes(buf, 4); return Get32(buf); } UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeReadBytes(buf, 8); return Get64(buf); } +// we use Skip() inside headers only, so no need for stream change in multivol. + void CInArchive::Skip(unsigned num) { if (_inBufMode) { size_t skip = _inBuffer.Skip(num); m_Position += skip; + _processedCnt += skip; if (skip != num) throw CUnexpectEnd(); } @@ -440,16 +596,18 @@ void CInArchive::ReadFileName(unsigned size, AString &s) s.Empty(); return; } - char *p = s.GetBuf(size); - SafeReadBytes(p, size); + SafeReadBytes(s.GetBuf(size), size); s.ReleaseBuf_CalcLen(size); } + bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) { extraBlock.Clear(); + UInt32 remain = extraSize; + while (remain >= 4) { CExtraSubBlock subBlock; @@ -509,6 +667,7 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, } remain -= dataSize; } + if (remain != 0) { ExtraMinorError = true; @@ -516,12 +675,17 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, // so we don't return false, but just set warning flag // return false; } + Skip(remain); return true; } + bool CInArchive::ReadLocalItem(CItemEx &item) { + item.Disk = 0; + if (IsMultiVol && Vols.StreamIndex >= 0) + item.Disk = Vols.StreamIndex; const unsigned kPureHeaderSize = kLocalHeaderSize - 4; Byte p[kPureHeaderSize]; SafeReadBytes(p, kPureHeaderSize); @@ -534,14 +698,14 @@ bool CInArchive::ReadLocalItem(CItemEx &item) item.ExtractVersion.Version = p[0]; item.ExtractVersion.HostOS = p[1]; - item.Flags = Get16(p + 2); - item.Method = Get16(p + 4); - item.Time = Get32(p + 6); - item.Crc = Get32(p + 10); - item.PackSize = Get32(p + 14); - item.Size = Get32(p + 18); - unsigned nameSize = Get16(p + 22); - unsigned extraSize = Get16(p + 24); + G16(2, item.Flags); + G16(4, item.Method); + G32(6, item.Time); + G32(10, item.Crc); + G32(14, item.PackSize); + G32(18, item.Size); + const unsigned nameSize = Get16(p + 22); + const unsigned extraSize = Get16(p + 24); ReadFileName(nameSize, item.Name); item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize; @@ -581,6 +745,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) return item.LocalFullHeaderSize <= ((UInt32)1 << 16); } + static bool FlagsAreSame(const CItem &i1, const CItem &i2) { if (i1.Method != i2.Method) @@ -597,9 +762,16 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2) if (i1.Method <= NFileHeader::NCompressionMethod::kImploded) mask = 0x7FFF; } + + // we can ignore utf8 flag, if name is ascii + if ((i1.Flags ^ i2.Flags) & NFileHeader::NFlags::kUtf8) + if (i1.Name.IsAscii() && i2.Name.IsAscii()) + mask &= ~NFileHeader::NFlags::kUtf8; + return ((i1.Flags & mask) == (i2.Flags & mask)); } + // #ifdef _WIN32 static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2) { @@ -623,6 +795,7 @@ static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2) } // #endif + static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) { if (!FlagsAreSame(cdItem, localItem)) @@ -670,16 +843,52 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) return true; } -HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) + +HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) { + isAvail = true; if (item.FromLocal) return S_OK; try { - UInt64 offset = ArcInfo.Base + item.LocalHeaderPos; - if (ArcInfo.Base < 0 && (Int64)offset < 0) - return S_FALSE; - RINOK(Seek(offset)); + UInt64 offset = item.LocalHeaderPos; + + if (IsMultiVol) + { + if (item.Disk >= Vols.Streams.Size()) + { + isAvail = false; + return S_FALSE; + } + IInStream *str2 = Vols.Streams[item.Disk].Stream; + if (!str2) + { + isAvail = false; + return S_FALSE; + } + RINOK(str2->Seek(offset, STREAM_SEEK_SET, NULL)); + Stream = str2; + Vols.StreamIndex = item.Disk; + } + else + { + if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex) + { + isAvail = false; + return S_FALSE; + } + Stream = StreamRef; + + offset += ArcInfo.Base; + if (ArcInfo.Base < 0 && (Int64)offset < 0) + { + isAvail = false; + return S_FALSE; + } + RINOK(Seek(offset)); + } + + CItemEx localItem; if (ReadUInt32() != NSignature::kLocalFileHeader) return S_FALSE; @@ -694,6 +903,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) return S_OK; } + HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) { const unsigned kBufSize = (1 << 12); @@ -726,7 +936,8 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) item.Crc = Get32(buf + i + 4); item.PackSize = descriptorPackSize; item.Size = Get32(buf + i + 12); - return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize))); + bool isFinished; + return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)), isFinished); } } } @@ -739,15 +950,18 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) } } + HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) { if (item.FromLocal) return S_OK; try { - RINOK(ReadLocalItemAfterCdItem(item)); + bool isAvail = true; + RINOK(ReadLocalItemAfterCdItem(item, isAvail)); if (item.HasDescriptor()) { + // pkzip's version without descriptor is not supported RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize)); if (ReadUInt32() != NSignature::kDataDescriptor) return S_FALSE; @@ -775,6 +989,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) return S_OK; } + HRESULT CInArchive::ReadCdItem(CItemEx &item) { item.FromCentral = true; @@ -785,30 +1000,24 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) item.MadeByVersion.HostOS = p[1]; item.ExtractVersion.Version = p[2]; item.ExtractVersion.HostOS = p[3]; - item.Flags = Get16(p + 4); - item.Method = Get16(p + 6); - item.Time = Get32(p + 8); - item.Crc = Get32(p + 12); - item.PackSize = Get32(p + 16); - item.Size = Get32(p + 20); + G16(4, item.Flags); + G16(6, item.Method); + G32(8, item.Time); + G32(12, item.Crc); + G32(16, item.PackSize); + G32(20, item.Size); const unsigned nameSize = Get16(p + 24); const unsigned extraSize = Get16(p + 26); const unsigned commentSize = Get16(p + 28); - UInt32 diskNumberStart = Get16(p + 30); - item.InternalAttrib = Get16(p + 32); - item.ExternalAttrib = Get32(p + 34); - item.LocalHeaderPos = Get32(p + 38); + G16(30, item.Disk); + G16(32, item.InternalAttrib); + G32(34, item.ExternalAttrib); + G32(38, item.LocalHeaderPos); ReadFileName(nameSize, item.Name); if (extraSize > 0) - { - ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, - item.LocalHeaderPos, diskNumberStart); - } + ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk); - if (diskNumberStart != 0) - return E_NOTIMPL; - // May be these strings must be deleted /* if (item.IsDir()) @@ -819,19 +1028,6 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) return S_OK; } -void CCdInfo::ParseEcd(const Byte *p) -{ - NumEntries = Get16(p + 10); - Size = Get32(p + 12); - Offset = Get32(p + 16); -} - -void CCdInfo::ParseEcd64(const Byte *p) -{ - NumEntries = Get64(p + 24); - Size = Get64(p + 40); - Offset = Get64(p + 48); -} HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) { @@ -847,155 +1043,256 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) UInt64 mainSize = Get64(buf + 4); if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32)) return S_FALSE; - cdInfo.ParseEcd64(buf); + cdInfo.ParseEcd64e(buf + 12); return S_OK; } -HRESULT CInArchive::FindCd(CCdInfo &cdInfo) + +HRESULT CInArchive::FindCd(bool checkOffsetMode) { - UInt64 endPosition; - RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPosition)); + CCdInfo &cdInfo = Vols.ecd; + + UInt64 endPos; + + RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPos)); const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; - UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax; + const UInt32 bufSize = (endPos < kBufSizeMax) ? (UInt32)endPos : kBufSizeMax; if (bufSize < kEcdSize) return S_FALSE; CByteArr byteBuffer(bufSize); - UInt64 startPosition = endPosition - bufSize; - RINOK(Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position)); - if (m_Position != startPosition) + const UInt64 startPos = endPos - bufSize; + RINOK(Stream->Seek(startPos, STREAM_SEEK_SET, &m_Position)); + if (m_Position != startPos) return S_FALSE; RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize)); - const Byte *buf = byteBuffer; - for (UInt32 i = bufSize - kEcdSize;; i--) + for (UInt32 i = bufSize - kEcdSize + 1;;) { - if (buf[i] != 0x50) + if (i == 0) + return S_FALSE; + + const Byte *buf = byteBuffer; + + for (;;) { - if (i == 0) return S_FALSE; i--; - if (buf[i] != 0x50) - { - if (i == 0) return S_FALSE; - continue; - } + if (buf[i] == 0x50) + break; + if (i == 0) + return S_FALSE; } - if (Get32(buf + i) == NSignature::kEcd) + + if (Get32(buf + i) != NSignature::kEcd) + continue; + + cdInfo.ParseEcd32(buf + i); + + if (i >= kEcd64Locator_Size) { - if (i >= kEcd64_FullSize + kEcd64Locator_Size) + const Byte *locatorPtr = buf + i - kEcd64Locator_Size; + if (Get32(locatorPtr) == NSignature::kEcd64Locator) { - const Byte *locator = buf + i - kEcd64Locator_Size; - if (Get32(locator) == NSignature::kEcd64Locator && - Get32(locator + 4) == 0) // number of the disk with the start of the zip64 ECD + CLocator locator; + locator.Parse(locatorPtr + 4); + if ((cdInfo.ThisDisk == locator.NumDisks - 1 || cdInfo.ThisDisk == 0xFFFF) + && locator.Ecd64Disk < locator.NumDisks) { - // Most of the zip64 use fixed size Zip64 ECD + if (locator.Ecd64Disk != cdInfo.ThisDisk && cdInfo.ThisDisk != 0xFFFF) + return E_NOTIMPL; - UInt64 ecd64Offset = Get64(locator + 8); - UInt64 absEcd64 = endPosition - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); + // Most of the zip64 use fixed size Zip64 ECD + // we try relative backward reading. + + UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); + if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) { - const Byte *ecd64 = locator - kEcd64_FullSize; - if (Get32(ecd64) == NSignature::kEcd64 && - Get64(ecd64 + 4) == kEcd64_MainSize) + const Byte *ecd64 = locatorPtr - kEcd64_FullSize; + if (Get32(ecd64) == NSignature::kEcd64) { - cdInfo.ParseEcd64(ecd64); - ArcInfo.Base = absEcd64 - ecd64Offset; - return S_OK; + UInt64 mainEcd64Size = Get64(ecd64 + 4); + if (mainEcd64Size == kEcd64_MainSize) + { + cdInfo.ParseEcd64e(ecd64 + 12); + ArcInfo.Base = absEcd64 - locator.Ecd64Offset; + // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; + return S_OK; + } } } - + // some zip64 use variable size Zip64 ECD. - // we try to find it - if (absEcd64 != ecd64Offset) + // we try to use absolute offset from locator. + + if (absEcd64 != locator.Ecd64Offset) { - if (TryEcd64(ecd64Offset, cdInfo) == S_OK) + if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK) { ArcInfo.Base = 0; + // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } } - if (ArcInfo.MarkerPos != 0 && - ArcInfo.MarkerPos + ecd64Offset != absEcd64) + + // for variable Zip64 ECD with for archives with offset != 0. + + if (checkOffsetMode + && ArcInfo.MarkerPos != 0 + && ArcInfo.MarkerPos + locator.Ecd64Offset != absEcd64) { - if (TryEcd64(ArcInfo.MarkerPos + ecd64Offset, cdInfo) == S_OK) + if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK) { ArcInfo.Base = ArcInfo.MarkerPos; + // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; return S_OK; } } } } - if (Get32(buf + i + 4) == 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber; + } + + // bool isVolMode = (Vols.EndVolIndex != -1); + // UInt32 searchDisk = (isVolMode ? Vols.EndVolIndex : 0); + + if (/* searchDisk == thisDisk && */ cdInfo.CdDisk <= cdInfo.ThisDisk) + { + // if (isVolMode) + { + if (cdInfo.CdDisk != cdInfo.ThisDisk) + return S_OK; + } + + UInt64 absEcdPos = endPos - bufSize + i; + UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; + ArcInfo.Base = 0; + // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; + if (absEcdPos != cdEnd) { - cdInfo.ParseEcd(buf + i); - UInt64 absEcdPos = endPosition - bufSize + i; - UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; - ArcInfo.Base = 0; - if (absEcdPos != cdEnd) + /* + if (cdInfo.Offset <= 16 && cdInfo.Size != 0) { - /* - if (cdInfo.Offset <= 16 && cdInfo.Size != 0) - { - // here we support some rare ZIP files with Central directory at the start - ArcInfo.Base = 0; - } - else - */ - ArcInfo.Base = absEcdPos - cdEnd; + // here we support some rare ZIP files with Central directory at the start + ArcInfo.Base = 0; } - return S_OK; + else + */ + ArcInfo.Base = absEcdPos - cdEnd; } + return S_OK; } - if (i == 0) - return S_FALSE; } } -HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress) +HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize) { items.Clear(); - RINOK(Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); - if (m_Position != cdOffset) - return S_FALSE; + + ISequentialInStream *stream; + + if (!IsMultiVol) + { + stream = this->StartStream; + Vols.StreamIndex = -1; + RINOK(this->StartStream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); + if (m_Position != cdOffset) + return S_FALSE; + } + else + { + if (cdInfo.CdDisk >= Vols.Streams.Size()) + return S_FALSE; + IInStream *str2 = Vols.Streams[cdInfo.CdDisk].Stream; + if (!str2) + return S_FALSE; + RINOK(str2->Seek(cdOffset, STREAM_SEEK_SET, NULL)); + stream = str2; + Vols.NeedSeek = false; + Vols.StreamIndex = cdInfo.CdDisk; + m_Position = cdOffset; + } + + _inBuffer.SetStream(stream); _inBuffer.Init(); _inBufMode = true; - while (m_Position - cdOffset < cdSize) + _processedCnt = 0; + + while (_processedCnt < cdSize) { + CanStartNewVol = true; if (ReadUInt32() != NSignature::kCentralFileHeader) return S_FALSE; - CItemEx cdItem; - RINOK(ReadCdItem(cdItem)); - items.Add(cdItem); - if (progress && (items.Size() & 0xFFF) == 0) - RINOK(progress->SetCompletedCD(items.Size())); + { + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + items.Add(cdItem); + } + if (Callback && (items.Size() & 0xFFF) == 0) + { + const UInt64 numFiles = items.Size(); + RINOK(Callback->SetCompleted(&numFiles, NULL)); + } } - return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE; + + CanStartNewVol = true; + + return (_processedCnt == cdSize) ? S_OK : S_FALSE; } -HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress) + +HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize) { - CCdInfo cdInfo; - RINOK(FindCd(cdInfo)); + bool checkOffsetMode = true; + + if (IsMultiVol) + { + if (Vols.EndVolIndex == -1) + return S_FALSE; + Stream = Vols.Streams[Vols.EndVolIndex].Stream; + if (!Vols.StartIsZip) + checkOffsetMode = false; + } + else + Stream = StartStream; + + if (!Vols.ecd_wasRead) + { + RINOK(FindCd(checkOffsetMode)); + } + + CCdInfo &cdInfo = Vols.ecd; + HRESULT res = S_FALSE; + cdSize = cdInfo.Size; cdOffset = cdInfo.Offset; - if (progress) - progress->SetTotalCD(cdInfo.NumEntries); - res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress); - if (res == S_FALSE && ArcInfo.Base == 0) + cdDisk = cdInfo.CdDisk; + + if (Callback) { - res = TryReadCd(items, ArcInfo.MarkerPos + cdOffset, cdSize, progress); + RINOK(Callback->SetTotal(&cdInfo.NumEntries, NULL)); + } + + const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base); + res = TryReadCd(items, cdInfo, base + cdOffset, cdSize); + + if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos) + { + // do we need that additional attempt to read cd? + res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize); if (res == S_OK) ArcInfo.Base = ArcInfo.MarkerPos; } + return res; } -static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset) + +static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item) { unsigned left = 0, right = items.Size(); for (;;) @@ -1003,42 +1300,66 @@ static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset) if (left >= right) return -1; unsigned index = (left + right) / 2; - UInt64 position = items[index].LocalHeaderPos; - if (offset == position) + const CItemEx &item2 = items[index]; + if (item.Disk < item2.Disk) + right = index; + else if (item.Disk > item2.Disk) + left = index + 1; + else if (item.LocalHeaderPos == item2.LocalHeaderPos) return index; - if (offset < position) + else if (item.LocalHeaderPos < item2.LocalHeaderPos) right = index; else left = index + 1; } } -bool IsStrangeItem(const CItem &item) +static bool IsStrangeItem(const CItem &item) { return item.Name.Len() > (1 << 14) || item.Method > (1 << 8); } -HRESULT CInArchive::ReadLocals( - CObjectVector<CItemEx> &items, CProgressVirt *progress) +HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) { items.Clear(); + while (m_Signature == NSignature::kLocalFileHeader) { CItemEx item; - item.LocalHeaderPos = m_Position - 4 - ArcInfo.MarkerPos; + item.LocalHeaderPos = m_Position - 4; + if (!IsMultiVol) + item.LocalHeaderPos -= ArcInfo.MarkerPos; + // we write ralative LocalHeaderPos here. Later we can correct it to real Base. + try { ReadLocalItem(item); item.FromLocal = true; + bool isFinished = false; + if (item.HasDescriptor()) ReadLocalItemDescriptor(item); else { - RINOK(IncreaseRealPosition(item.PackSize)); + /* + if (IsMultiVol) + { + const int kStep = 10000; + RINOK(IncreaseRealPosition(-kStep, isFinished)); + RINOK(IncreaseRealPosition(item.PackSize + kStep, isFinished)); + } + else + */ + RINOK(IncreaseRealPosition(item.PackSize, isFinished)); } + items.Add(item); + + if (isFinished) + throw CUnexpectEnd(); + m_Signature = ReadUInt32(); } catch (CUnexpectEnd &) @@ -1048,34 +1369,364 @@ HRESULT CInArchive::ReadLocals( throw; } - if (progress && (items.Size() & 0xFF) == 0) - RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos)); + if (Callback && (items.Size() & 0xFF) == 0) + { + const UInt64 numFiles = items.Size(); + UInt64 numBytes = 0; + // if (!sMultiVol) + numBytes = item.LocalHeaderPos; + RINOK(Callback->SetCompleted(&numFiles, &numBytes)); + } } if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader) if (IsStrangeItem(items[0])) return S_FALSE; + + return S_OK; +} + + + +HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) +{ + UString name; + { + NWindows::NCOM::CPropVariant prop; + RINOK(volCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + return S_OK; + name = prop.bstrVal; + } + + UString base = name; + int dotPos = name.ReverseFind_Dot(); + + if (dotPos < 0) + return S_OK; + + base.DeleteFrom(dotPos + 1); + + const UString ext = name.Ptr(dotPos + 1); + StartVolIndex = (Int32)(-1); + + if (ext.IsEmpty()) + return S_OK; + else + { + wchar_t c = ext[0]; + IsUpperCase = (c >= 'A' && c <= 'Z'); + if (ext.IsEqualTo_Ascii_NoCase("zip")) + { + BaseName = base; + StartIsZ = true; + StartIsZip = true; + return S_OK; + } + else if (ext.IsEqualTo_Ascii_NoCase("exe")) + { + StartIsExe = true; + BaseName = base; + StartVolIndex = 0; + } + else if (ext[0] == 'z' || ext[0] == 'Z') + { + if (ext.Len() < 3) + return S_OK; + const wchar_t *end = NULL; + UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end); + if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30)) + return S_OK; + StartVolIndex = volNum - 1; + BaseName = base; + StartIsZ = true; + } + else + return S_OK; + } + + UString volName = BaseName; + volName.AddAscii(IsUpperCase ? "ZIP" : "zip"); + HRESULT result = volCallback->GetStream(volName, &ZipStream); + if (result == S_FALSE || !ZipStream) + { + if (MissingName.IsEmpty()) + MissingName = volName; + return S_OK; + } + + return result; +} + + +HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, + unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols) +{ + numMissingVols = 0; + + for (unsigned i = start;; i++) + { + if (lastDisk >= 0 && i >= (unsigned)lastDisk) + break; + + if (i < Vols.Streams.Size()) + if (Vols.Streams[i].Stream) + continue; + + CMyComPtr<IInStream> stream; + + if ((int)i == zipDisk) + { + stream = Vols.ZipStream; + } + else if ((int)i == Vols.StartVolIndex) + { + stream = StartStream; + } + else + { + UString volName = Vols.BaseName; + { + volName += (wchar_t)(Vols.IsUpperCase ? 'Z' : 'z'); + { + char s[32]; + ConvertUInt32ToString(i + 1, s); + unsigned len = (unsigned)strlen(s); + while (len < 2) + { + volName += (wchar_t)'0'; + len++; + } + volName.AddAscii(s); + } + } + + HRESULT result = volCallback->GetStream(volName, &stream); + if (result != S_OK && result != S_FALSE) + return result; + if (result == S_FALSE || !stream) + { + if (Vols.MissingName.IsEmpty()) + Vols.MissingName = volName; + numMissingVols++; + if (numMissingVols > numMissingVolsMax) + return S_OK; + if (lastDisk == -1 && numMissingVols != 0) + return S_OK; + continue; + } + } + + UInt64 size; + + UInt64 pos; + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos)); + RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); + RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL)); + + while (i >= Vols.Streams.Size()) + Vols.Streams.AddNew(); + + CVols::CSubStreamInfo &ss = Vols.Streams[i]; + Vols.NumVols++; + ss.Stream = stream; + ss.Size = size; + + if ((int)i == zipDisk) + { + Vols.EndVolIndex = Vols.Streams.Size() - 1; + break; + } + } + return S_OK; } +HRESULT CInArchive::ReadVols() +{ + CMyComPtr<IArchiveOpenVolumeCallback> volCallback; + + Callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volCallback); + if (!volCallback) + return S_OK; + + RINOK(Vols.ParseArcName(volCallback)); + + int startZIndex = Vols.StartVolIndex; + + if (!Vols.StartIsZ) + { + // if (!Vols.StartIsExe) + return S_OK; + } + + int zipDisk = -1; + int cdDisk = -1; + + if (Vols.StartIsZip) + Vols.ZipStream = StartStream; + + bool cdOK = false; + + if (Vols.ZipStream) + { + Stream = Vols.ZipStream; + HRESULT res = FindCd(true); + CCdInfo &ecd = Vols.ecd; + if (res == S_OK) + { + zipDisk = ecd.ThisDisk; + Vols.ecd_wasRead = true; + if (ecd.ThisDisk == 0 + || ecd.ThisDisk >= ((UInt32)1 << 30) + || ecd.ThisDisk < ecd.CdDisk) + return S_OK; + cdDisk = ecd.CdDisk; + if (Vols.StartVolIndex < 0) + Vols.StartVolIndex = ecd.ThisDisk; + // Vols.StartVolIndex = ecd.ThisDisk; + // Vols.EndVolIndex = ecd.ThisDisk; + unsigned numMissingVols; + if (cdDisk == zipDisk) + cdOK = true; + else + { + RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols)); + if (numMissingVols == 0) + cdOK = false; + } + } + else if (res != S_FALSE) + return res; + } + + if (Vols.Streams.Size() > 0) + IsMultiVol = true; + + if (Vols.StartVolIndex < 0) + return S_OK; + + unsigned numMissingVols; + + if (cdDisk != 0) + { + RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, 1 << 10, numMissingVols)); + } + + if (Vols.ZipStream) + { + if (Vols.Streams.IsEmpty()) + if (zipDisk > (1 << 10)) + return S_OK; + RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); + } + + if (!Vols.Streams.IsEmpty()) + { + IsMultiVol = true; + /* + if (cdDisk) + IsMultiVol = true; + */ + if (startZIndex >= 0) + { + if (Vols.Streams.Size() >= (unsigned)startZIndex) + { + for (unsigned i = 0; i < (unsigned)startZIndex; i++) + if (!Vols.Streams[i].Stream) + { + Vols.StartParsingVol = startZIndex; + break; + } + } + } + } + + return S_OK; +} + + + + + + + +HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + + for (;;) + { + if (StreamIndex < 0) + return S_OK; + if ((unsigned)StreamIndex >= Streams.Size()) + return S_OK; + const CVols::CSubStreamInfo &s = Streams[StreamIndex]; + if (!s.Stream) + return S_FALSE; + if (NeedSeek) + { + RINOK(s.Stream->Seek(0, STREAM_SEEK_SET, NULL)); + NeedSeek = false; + } + UInt32 realProcessedSize = 0; + HRESULT res = s.Stream->Read(data, size, &realProcessedSize); + if (processedSize) + *processedSize = realProcessedSize; + if (res != S_OK) + return res; + if (realProcessedSize != 0) + return res; + StreamIndex++; + NeedSeek = true; + } +} + +STDMETHODIMP CVolStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return Vols->Read(data, size, processedSize); +} + + + + #define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF) ecd64. n = ecd. n; #define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n; -HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress) + +HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) { - items.Clear(); + HRESULT res = S_OK; + + bool localsWereRead = false; + UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0; + UInt32 cdDisk = 0; + if (!_inBuffer.Create(1 << 15)) + return E_OUTOFMEMORY; + + if (!MarkerIsFound) + { + IsArc = true; + res = ReadCd(items, cdDisk, cdRelatOffset, cdSize); + if (res == S_OK) + m_Signature = ReadUInt32(); + } + else + { + // m_Signature must be kLocalFileHeader or kEcd // m_Position points to next byte after signature RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); - if (!_inBuffer.Create(1 << 15)) - return E_OUTOFMEMORY; _inBuffer.SetStream(Stream); bool needReadCd = true; - bool localsWereRead = false; + if (m_Signature == NSignature::kEcd) { // It must be empty archive or backware archive @@ -1097,9 +1748,6 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position)); } - UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0; - HRESULT res = S_OK; - if (needReadCd) { CItemEx firstItem; @@ -1116,7 +1764,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p } IsArc = true; - res = ReadCd(items, cdRelatOffset, cdSize, progress); + res = ReadCd(items, cdDisk, cdRelatOffset, cdSize); if (res == S_OK) m_Signature = ReadUInt32(); } @@ -1130,16 +1778,27 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p if (res == S_OK) { // we can't read local items here to keep _inBufMode state - firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base; - int index = FindItem(items, firstItem.LocalHeaderPos); - if (index == -1) - res = S_FALSE; - else if (!AreItemsEqual(firstItem, items[index])) + if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base) res = S_FALSE; - ArcInfo.CdWasRead = true; - ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; + else + { + firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base; + int index = FindItem(items, firstItem); + if (index == -1) + res = S_FALSE; + else if (!AreItemsEqual(firstItem, items[index])) + res = S_FALSE; + else + { + ArcInfo.CdWasRead = true; + ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos; + } + } } } + } + + CObjectVector<CItemEx> cdItems; @@ -1148,19 +1807,32 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p if (res == S_FALSE) { - // CD doesn't match firstItem so we clear items and read Locals. + // CD doesn't match firstItem, + // so we clear items and read Locals. items.Clear(); localsWereRead = true; _inBufMode = false; ArcInfo.Base = ArcInfo.MarkerPos; + + if (IsMultiVol) + { + Vols.StreamIndex = Vols.StartParsingVol; + if (Vols.StartParsingVol >= (int)Vols.Streams.Size()) + return S_FALSE; + Stream = Vols.Streams[Vols.StartParsingVol].Stream; + if (!Stream) + return S_FALSE; + } + RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position)); m_Signature = ReadUInt32(); - - RINOK(ReadLocals(items, progress)); + RINOK(ReadLocals(items)); + if (m_Signature != NSignature::kCentralFileHeader) { - m_Position -= 4; + // if (!UnexpectedEnd) + m_Position -= 4; NoCentralDir = true; HeadersError = true; return S_OK; @@ -1168,15 +1840,24 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p _inBufMode = true; _inBuffer.Init(); + cdAbsOffset = m_Position - 4; + cdDisk = Vols.StreamIndex; for (;;) { CItemEx cdItem; + CanStartNewVol = true; + RINOK(ReadCdItem(cdItem)); + cdItems.Add(cdItem); - if (progress && (cdItems.Size() & 0xFFF) == 0) - RINOK(progress->SetCompletedCD(items.Size())); + if (Callback && (cdItems.Size() & 0xFFF) == 0) + { + const UInt64 numFiles = items.Size(); + RINOK(Callback->SetCompleted(&numFiles, NULL)); + } + CanStartNewVol = true; m_Signature = ReadUInt32(); if (m_Signature != NSignature::kCentralFileHeader) break; @@ -1193,95 +1874,159 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p } } - CEcd64 ecd64; + + + CCdInfo ecd64; + CLocator locator; bool isZip64 = false; - UInt64 ecd64AbsOffset = m_Position - 4; + const UInt64 ecd64AbsOffset = m_Position - 4; + int ecd64Disk = -1; if (m_Signature == NSignature::kEcd64) { + ecd64Disk = Vols.StreamIndex; + IsZip64 = isZip64 = true; - UInt64 recordSize = ReadUInt64(); - const unsigned kBufSize = kEcd64_MainSize; - Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); - ecd64.Parse(buf); + { + const UInt64 recordSize = ReadUInt64(); + if (recordSize < kEcd64_MainSize) + { + HeadersError = true; + return S_OK; + } + + { + const unsigned kBufSize = kEcd64_MainSize; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + ecd64.ParseEcd64e(buf); + } + + Skip64(recordSize - kEcd64_MainSize); + } - Skip64(recordSize - kEcd64_MainSize); - m_Signature = ReadUInt32(); - if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) - return E_NOTIMPL; + m_Signature = ReadUInt32(); - if (needSetBase) + if (m_Signature != NSignature::kEcd64Locator) + { + HeadersError = true; + return S_OK; + } + { - ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset; - cdRelatOffset = ecd64.cdStartOffset; - needSetBase = false; + const unsigned kBufSize = 16; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + locator.Parse(buf); } - if (ecd64.numEntriesInCDOnThisDisk != numCdItems || - ecd64.numEntriesInCD != numCdItems || - ecd64.cdSize != cdSize || - (ecd64.cdStartOffset != cdRelatOffset && - (!items.IsEmpty()))) - return S_FALSE; + m_Signature = ReadUInt32(); } - if (m_Signature == NSignature::kEcd64Locator) + + if (m_Signature != NSignature::kEcd) { - if (!isZip64) - return S_FALSE; - /* UInt32 startEndCDDiskNumber = */ ReadUInt32(); - UInt64 ecd64RelatOffset = ReadUInt64(); - /* UInt32 numberOfDisks = */ ReadUInt32(); - if (ecd64AbsOffset != ArcInfo.Base + ecd64RelatOffset) - return S_FALSE; - m_Signature = ReadUInt32(); + HeadersError = true; + return S_OK; } + - if (m_Signature != NSignature::kEcd) - return S_FALSE; + // ---------- ECD ---------- - const unsigned kBufSize = kEcdSize - 4; - Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); CEcd ecd; - ecd.Parse(buf); + { + const unsigned kBufSize = kEcdSize - 4; + Byte buf[kBufSize]; + SafeReadBytes(buf, kBufSize); + ecd.Parse(buf); + } - COPY_ECD_ITEM_16(thisDiskNumber); - COPY_ECD_ITEM_16(startCDDiskNumber); - COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk); - COPY_ECD_ITEM_16(numEntriesInCD); - COPY_ECD_ITEM_32(cdSize); - COPY_ECD_ITEM_32(cdStartOffset); + COPY_ECD_ITEM_16(ThisDisk); + COPY_ECD_ITEM_16(CdDisk); + COPY_ECD_ITEM_16(NumEntries_in_ThisDisk); + COPY_ECD_ITEM_16(NumEntries); + COPY_ECD_ITEM_32(Size); + COPY_ECD_ITEM_32(Offset); - if (needSetBase) + if (IsMultiVol) { - ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset; - cdRelatOffset = ecd64.cdStartOffset; - needSetBase = false; + if (cdDisk != (int)ecd64.CdDisk) + HeadersError = true; } + else if (needSetBase) + { + if (isZip64) + { + if (ecd64Disk == Vols.StartVolIndex) + { + ArcInfo.Base = ecd64AbsOffset - locator.Ecd64Offset; + // cdRelatOffset = ecd64.Offset; + needSetBase = false; + } + } + else + { + if ((int)cdDisk == Vols.StartVolIndex) + { + ArcInfo.Base = cdAbsOffset - ecd64.Offset; + cdRelatOffset = ecd64.Offset; + needSetBase = false; + } + } + } + + EcdVolIndex = ecd64.ThisDisk; - if (localsWereRead && (UInt64)ArcInfo.Base != ArcInfo.MarkerPos) + if (!IsMultiVol) { - UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base; - for (unsigned i = 0; i < items.Size(); i++) - items[i].LocalHeaderPos += delta; + UseDisk_in_SingleVol = true; + + if (localsWereRead) + { + if ((UInt64)ArcInfo.Base != ArcInfo.MarkerPos) + { + const UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base; + FOR_VECTOR (i, items) + items[i].LocalHeaderPos += delta; + } + + if (EcdVolIndex != 0) + { + FOR_VECTOR (i, items) + items[i].Disk = EcdVolIndex; + } + } } + if (isZip64) + { + if (ecd64.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset + // || ecd64.NumEntries_in_ThisDisk != numCdItems + || ecd64.NumEntries != numCdItems + || ecd64.Size != cdSize + || (ecd64.Offset != cdRelatOffset && !items.IsEmpty())) + { + HeadersError = true; + return S_OK; + } + } // ---------- merge Central Directory Items ---------- if (!cdItems.IsEmpty()) { - for (unsigned i = 0; i < cdItems.Size(); i++) + CObjectVector<CItemEx> items2; + + FOR_VECTOR (i, cdItems) { const CItemEx &cdItem = cdItems[i]; - int index = FindItem(items, cdItem.LocalHeaderPos); + int index = FindItem(items, cdItem); if (index == -1) { - items.Add(cdItem); + items2.Add(cdItem); + HeadersError = true; continue; } CItemEx &item = items[index]; @@ -1292,9 +2037,11 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p // item.ExtractVersion != cdItem.ExtractVersion || !FlagsAreSame(item, cdItem) || item.Crc != cdItem.Crc) + { + HeadersError = true; continue; + } - // item.LocalHeaderPos = cdItem.LocalHeaderPos; // item.Name = cdItem.Name; item.MadeByVersion = cdItem.MadeByVersion; item.CentralExtra = cdItem.CentralExtra; @@ -1303,33 +2050,47 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p item.Comment = cdItem.Comment; item.FromCentral = cdItem.FromCentral; } + + items += items2; } - if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) - return E_NOTIMPL; - + + if (ecd.NumEntries < ecd.NumEntries_in_ThisDisk) + HeadersError = true; + + if (ecd.ThisDisk == 0) + { + // if (isZip64) + { + if (ecd.NumEntries != ecd.NumEntries_in_ThisDisk) + HeadersError = true; + } + } + + if (ecd.NumEntries > items.Size()) + HeadersError = true; + if (isZip64) { - if (ecd64.numEntriesInCDOnThisDisk != items.Size()) + if (ecd64.NumEntries != items.Size()) HeadersError = true; } else { // old 7-zip could store 32-bit number of CD items to 16-bit field. - if ((UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)numCdItems || - (UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)items.Size()) + /* + if ((UInt16)ecd64.NumEntries == (UInt16)items.Size()) HeadersError = true; + */ } - ReadBuffer(ArcInfo.Comment, ecd.commentSize); + ReadBuffer(ArcInfo.Comment, ecd.CommentSize); _inBufMode = false; _inBuffer.Free(); - if ( - (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) || - (UInt32)ecd64.cdSize != (UInt32)cdSize || - ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset && - (!items.IsEmpty()))) + if ((UInt16)ecd64.NumEntries != (UInt16)numCdItems + || (UInt32)ecd64.Size != (UInt32)cdSize + || ((UInt32)ecd64.Offset != (UInt32)cdRelatOffset && !items.IsEmpty())) { // return S_FALSE; HeadersError = true; @@ -1340,39 +2101,170 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p } -HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress) + +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, + IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items) { - HRESULT res; - try + _inBufMode = false; + items.Clear(); + + Close(); + ArcInfo.Clear(); + + UInt64 startPos; + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &startPos)); + RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos)); + m_Position = ArcInfo.FileEndPos; + + StartStream = stream; + Callback = callback; + + bool volWasRequested = false; + + if (callback + && (startPos == 0 || !searchLimit || *searchLimit != 0)) { - res = ReadHeaders2(items, progress); + volWasRequested = true; + RINOK(ReadVols()); } - catch (const CInBufferException &e) { res = e.ErrorCode; } - catch (const CUnexpectEnd &) + + if (IsMultiVol && Vols.StartVolIndex != 0) { - if (items.IsEmpty()) - return S_FALSE; - UnexpectedEnd = true; - res = S_OK; + Stream = Vols.Streams[0].Stream; + if (Stream) + { + m_Position = 0; + RINOK(Stream->Seek(0, STREAM_SEEK_SET, NULL)); + UInt64 limit = 0; + HRESULT res = FindMarker(Stream, &limit); + if (res == S_OK) + MarkerIsFound = true; + else if (res != S_FALSE) + return res; + } + } + else + { + // printf("\nOpen offset = %u\n", (unsigned)startPos); + RINOK(stream->Seek(startPos, STREAM_SEEK_SET, NULL)); + m_Position = startPos; + HRESULT res = FindMarker(stream, searchLimit); + UInt64 curPos = m_Position; + if (res == S_OK) + MarkerIsFound = true; + else + { + // if (res != S_FALSE) + return res; + } + + MarkerIsFound = true; + + if (ArcInfo.IsSpanMode && !volWasRequested) + { + RINOK(ReadVols()); + } + + if (IsMultiVol && (unsigned)Vols.StartVolIndex < Vols.Streams.Size()) + { + Stream = Vols.Streams[Vols.StartVolIndex].Stream; + if (!Stream) + IsMultiVol = false; + else + { + RINOK(Stream->Seek(curPos, STREAM_SEEK_SET, NULL)); + m_Position = curPos; + } + } + else + IsMultiVol = false; + + if (!IsMultiVol) + { + RINOK(stream->Seek(curPos, STREAM_SEEK_SET, NULL)); + m_Position = curPos; + StreamRef = stream; + Stream = stream; + } } - catch (...) + + { + HRESULT res; + try + { + res = ReadHeaders2(items); + } + catch (const CInBufferException &e) { res = e.ErrorCode; } + catch (const CUnexpectEnd &) + { + if (items.IsEmpty()) + return S_FALSE; + UnexpectedEnd = true; + res = S_OK; + } + catch (...) + { + _inBufMode = false; + throw; + } + + if (IsMultiVol) + { + ArcInfo.FinishPos = ArcInfo.FileEndPos; + if ((unsigned)Vols.StreamIndex < Vols.Streams.Size()) + if (m_Position < Vols.Streams[Vols.StreamIndex].Size) + ArcInfo.ThereIsTail = true; + } + else + { + ArcInfo.FinishPos = m_Position; + ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > m_Position); + } + _inBufMode = false; - throw; + IsArcOpen = true; + if (!IsMultiVol) + Vols.Streams.Clear(); + return res; } - ArcInfo.FinishPos = m_Position; - _inBufMode = false; - return res; } -ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) + +HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream) { - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> stream(streamSpec); - Stream->Seek(ArcInfo.Base + position, STREAM_SEEK_SET, NULL); - streamSpec->SetStream(Stream); - streamSpec->Init(size); - return stream.Detach(); + stream.Release(); + + UInt64 pos = item.LocalHeaderPos; + if (seekPackData) + pos += item.LocalFullHeaderSize; + + if (!IsMultiVol) + { + if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex) + return S_OK; + pos += ArcInfo.Base; + RINOK(StreamRef->Seek(pos, STREAM_SEEK_SET, NULL)); + stream = StreamRef; + return S_OK; + } + + if (item.Disk >= Vols.Streams.Size()) + return S_OK; + + IInStream *str2 = Vols.Streams[item.Disk].Stream; + if (!str2) + return S_OK; + RINOK(str2->Seek(pos, STREAM_SEEK_SET, NULL)); + + Vols.NeedSeek = false; + Vols.StreamIndex = item.Disk; + + CVolStream *volsStreamSpec = new CVolStream; + volsStreamSpec->Vols = &Vols; + stream = volsStreamSpec; + + return S_OK; } }} diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 734d3bcb..9b10905e 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -28,6 +28,7 @@ public: { return LocalHeaderPos + LocalFullHeaderSize; } }; + struct CInArchiveInfo { Int64 Base; /* Base offset of start of archive in stream. @@ -40,74 +41,195 @@ struct CInArchiveInfo Base = ArcInfo.MarkerPos; */ /* The following *Pos variables contain absolute offsets in Stream */ - UInt64 MarkerPos; /* Pos of first signature, it can point to PK00 signature + + UInt64 MarkerPos; /* Pos of first signature, it can point to kSpan/kNoSpan signature = MarkerPos2 in most archives - = MarkerPos2 - 4 if there is PK00 signature */ + = MarkerPos2 - 4 if there is kSpan/kNoSpan signature */ UInt64 MarkerPos2; // Pos of first local item signature in stream - UInt64 FinishPos; // Finish pos of archive data + UInt64 FinishPos; // Finish pos of archive data in starting volume UInt64 FileEndPos; // Finish pos of stream UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base). = 0 in most archives = size of stub for some SFXs */ bool CdWasRead; + bool IsSpanMode; + bool ThereIsTail; + + // UInt32 BaseVolIndex; CByteBuffer Comment; - CInArchiveInfo(): Base(0), MarkerPos(0), MarkerPos2(0), FinishPos(0), FileEndPos(0), - FirstItemRelatOffset(0), CdWasRead(false) {} - - UInt64 GetPhySize() const { return FinishPos - Base; } - UInt64 GetEmbeddedStubSize() const - { - if (CdWasRead) - return FirstItemRelatOffset; - return MarkerPos2 - Base; - } - bool ThereIsTail() const { return FileEndPos > FinishPos; } + CInArchiveInfo(): + Base(0), + MarkerPos(0), + MarkerPos2(0), + FinishPos(0), + FileEndPos(0), + FirstItemRelatOffset(0), + CdWasRead(false), + IsSpanMode(false), + ThereIsTail(false) + // BaseVolIndex(0) + {} + void Clear() { + // BaseVolIndex = 0; Base = 0; MarkerPos = 0; MarkerPos2 = 0; FinishPos = 0; FileEndPos = 0; + ThereIsTail = false; FirstItemRelatOffset = 0; + CdWasRead = false; + IsSpanMode = false; Comment.Free(); } }; -struct CProgressVirt -{ - virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) = 0; - virtual HRESULT SetTotalCD(UInt64 numFiles) = 0; - virtual HRESULT SetCompletedCD(UInt64 numFiles) = 0; -}; struct CCdInfo { + // 64 + UInt16 VersionMade; + UInt16 VersionNeedExtract; + + // old zip + UInt32 ThisDisk; + UInt32 CdDisk; + UInt64 NumEntries_in_ThisDisk; UInt64 NumEntries; UInt64 Size; UInt64 Offset; - void ParseEcd(const Byte *p); - void ParseEcd64(const Byte *p); + UInt16 CommentSize; + + CCdInfo() { memset(this, 0, sizeof(*this)); } + + void ParseEcd32(const Byte *p); // (p) includes signature + void ParseEcd64e(const Byte *p); // (p) exclude signature }; + +class CVols +{ +public: + + struct CSubStreamInfo + { + CMyComPtr<IInStream> Stream; + UInt64 Size; + + CSubStreamInfo(): Size(0) {} + }; + + CObjectVector<CSubStreamInfo> Streams; + int StreamIndex; + bool NeedSeek; + + CMyComPtr<IInStream> ZipStream; + + bool StartIsExe; // is .exe + bool StartIsZ; // is .zip or .zNN + bool StartIsZip; // is .zip + bool IsUpperCase; + Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN + + Int32 StartParsingVol; // if we need local parsing, we must use that stream + unsigned NumVols; + + int EndVolIndex; // index of last volume (ecd volume), + // -1, if is not multivol + + UString BaseName; // including '.' + + UString MissingName; + + CCdInfo ecd; + bool ecd_wasRead; + + void Clear() + { + StreamIndex = -1; + NeedSeek = false; + + + StartIsExe = false; + StartIsZ = false; + StartIsZip = false; + IsUpperCase = false; + + StartVolIndex = -1; + StartParsingVol = 0; + NumVols = 0; + EndVolIndex = -1; + + BaseName.Empty(); + MissingName.Empty(); + + ecd_wasRead = false; + + Streams.Clear(); + ZipStream.Release(); + } + + HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback); + + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); + + UInt64 GetTotalSize() const + { + UInt64 total = 0; + FOR_VECTOR (i, Streams) + total += Streams[i].Size; + return total; + } +}; + + +class CVolStream: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + CVols *Vols; + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + + class CInArchive { CInBuffer _inBuffer; bool _inBufMode; UInt32 m_Signature; UInt64 m_Position; + + UInt64 _processedCnt; + bool CanStartNewVol; + + CMyComPtr<IInStream> StreamRef; + IInStream *Stream; + IInStream *StartStream; + + bool IsArcOpen; + + HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback, + unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols); + HRESULT ReadVols(); + HRESULT Seek(UInt64 offset); - HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - HRESULT IncreaseRealPosition(Int64 addValue); + HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit); + HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished); HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); void SafeReadBytes(void *data, unsigned size); @@ -126,12 +248,14 @@ class CInArchive HRESULT ReadLocalItemDescriptor(CItemEx &item); HRESULT ReadCdItem(CItemEx &item); HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo); - HRESULT FindCd(CCdInfo &cdInfo); - HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress); - HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress); - HRESULT ReadLocals(CObjectVector<CItemEx> &localItems, CProgressVirt *progress); + HRESULT FindCd(bool checkOffsetMode); + HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize); + HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize); + HRESULT ReadLocals(CObjectVector<CItemEx> &localItems); - HRESULT ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress); + HRESULT ReadHeaders2(CObjectVector<CItemEx> &items); + + HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream); public: CInArchiveInfo ArcInfo; @@ -142,46 +266,87 @@ public: bool ExtraMinorError; bool UnexpectedEnd; bool NoCentralDir; + + bool MarkerIsFound; + + bool IsMultiVol; + bool UseDisk_in_SingleVol; + UInt32 EcdVolIndex; + + CVols Vols; + + IArchiveOpenCallback *Callback; + + CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {} + + UInt64 GetPhySize() const + { + if (IsMultiVol) + return ArcInfo.FinishPos; + else + return ArcInfo.FinishPos - ArcInfo.Base; + } + + UInt64 GetOffset() const + { + if (IsMultiVol) + return 0; + else + return ArcInfo.Base; + } + - CMyComPtr<IInStream> Stream; - + void ClearRefs(); void Close(); - HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress); + HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items); + HRESULT ReadHeaders(CObjectVector<CItemEx> &items); - bool IsOpen() const { return Stream != NULL; } - bool AreThereErrors() const { return HeadersError || UnexpectedEnd; } + bool IsOpen() const { return IsArcOpen; } + + bool AreThereErrors() const + { + return HeadersError + || UnexpectedEnd + || !Vols.MissingName.IsEmpty(); + } bool IsLocalOffsetOK(const CItemEx &item) const { if (item.FromLocal) return true; - return /* ArcInfo.Base >= 0 || */ ArcInfo.Base + (Int64)item.LocalHeaderPos >= 0; + return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0; + } + + UInt64 GetEmbeddedStubSize() const + { + if (ArcInfo.CdWasRead) + return ArcInfo.FirstItemRelatOffset; + if (IsMultiVol) + return 0; + return ArcInfo.MarkerPos2 - ArcInfo.Base; } - HRESULT ReadLocalItemAfterCdItem(CItemEx &item); + + HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail); HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item); - ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream); - UInt64 GetOffsetInStream(UInt64 offsetFromArc) const { return ArcInfo.Base + offsetFromArc; } + IInStream *GetBaseStream() { return StreamRef; } bool CanUpdate() const { - if (AreThereErrors()) - return false; - if (ArcInfo.Base < 0) - return false; - if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base) + if (AreThereErrors() + || IsMultiVol + || ArcInfo.Base < 0 + || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base + || ArcInfo.ThereIsTail + || GetEmbeddedStubSize() != 0) return false; // 7-zip probably can update archives with embedded stubs. // we just disable that feature for more safety. - if (ArcInfo.GetEmbeddedStubSize() != 0) - return false; - if (ArcInfo.ThereIsTail()) - return false; return true; } }; diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 5f078b60..c134ec79 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -199,6 +199,8 @@ public: UInt64 PackSize; UInt32 Time; UInt32 Crc; + + UInt32 Disk; AString Name; diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index 2be783e6..6674189f 100644 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -12,10 +12,11 @@ namespace NZip { static const Byte k_Signature[] = { 4, 0x50, 0x4B, 0x03, 0x04, 4, 0x50, 0x4B, 0x05, 0x06, + 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; REGISTER_ARC_IO( - "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1, + "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1, k_Signature, 0, NArcInfoFlags::kFindSignature | diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 3128939e..1546a2af 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -52,16 +52,6 @@ static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size, return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress); } -static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, - const CUpdateRange &range, ICompressProgressInfo *progress) -{ - UInt64 position; - RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position)); - RINOK(CopyBlockToArchive(inStream, range.Size, outArchive, progress)); - return progress->SetRatioInfo(&range.Size, &range.Size); -} - - static void SetFileHeader( COutArchive &archive, const CCompressionMethodMode &options, @@ -358,9 +348,12 @@ static HRESULT UpdateItemOldData( return E_NOTIMPL; // use old name size. - // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize); - CUpdateRange range(inArchive->GetOffsetInStream(itemEx.GetDataPosition()), itemEx.PackSize); + CMyComPtr<ISequentialInStream> packStream; + RINOK(inArchive->GetItemStream(itemEx, true, packStream)); + if (!packStream) + return E_NOTIMPL; + // we keep ExternalAttrib and some another properties from old archive // item.ExternalAttrib = ui.Attrib; @@ -378,19 +371,27 @@ static HRESULT UpdateItemOldData( archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes()); archive.WriteLocalHeader(item); - RINOK(WriteRange(inArchive->Stream, archive, range, progress)); - complexity += range.Size; + + RINOK(CopyBlockToArchive(packStream, itemEx.PackSize, archive, progress)); + + complexity += itemEx.PackSize; } else { - CUpdateRange range(inArchive->GetOffsetInStream(itemEx.LocalHeaderPos), itemEx.GetLocalFullSize()); + CMyComPtr<ISequentialInStream> packStream; + RINOK(inArchive->GetItemStream(itemEx, false, packStream)); + if (!packStream) + return E_NOTIMPL; // set new header position item.LocalHeaderPos = archive.GetCurPos(); - RINOK(WriteRange(inArchive->Stream, archive, range, progress)); - complexity += range.Size; - archive.MoveCurPos(range.Size); + const UInt64 rangeSize = itemEx.GetLocalFullSize(); + + RINOK(CopyBlockToArchive(packStream, rangeSize, archive, progress)); + + complexity += rangeSize; + archive.MoveCurPos(rangeSize); } return S_OK; @@ -1191,10 +1192,11 @@ HRESULT Update( if (inArchive) { - if (inArchive->ArcInfo.Base > 0 && !removeSfx) + if (!inArchive->IsMultiVol && inArchive->ArcInfo.Base > 0 && !removeSfx) { - RINOK(inArchive->Stream->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStreamReal, inArchive->ArcInfo.Base, NULL)); + IInStream *baseStream = inArchive->GetBaseStream(); + RINOK(baseStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(baseStream, outStreamReal, inArchive->ArcInfo.Base, NULL)); } } @@ -1210,11 +1212,12 @@ HRESULT Update( if (inArchive) { - if ((Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base) + if (!inArchive->IsMultiVol && (Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base) { - RINOK(inArchive->Stream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); + IInStream *baseStream = inArchive->GetBaseStream(); + RINOK(baseStream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL)); UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base; - RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStream, embStubSize, NULL)); + RINOK(NCompress::CopyStream_ExactSize(baseStream, outStream, embStubSize, NULL)); outArchive.MoveCurPos(embStubSize); } } diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index c7962167..8e032561 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -5,16 +5,19 @@ #include <string.h> #include "LimitedStreams.h" -#include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; - UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); + { + const UInt64 rem = _size - _pos; + if (size > rem) + size = (UInt32)rem; + } HRESULT result = S_OK; - if (sizeToRead > 0) + if (size != 0) { - result = _stream->Read(data, sizeToRead, &realProcessedSize); + result = _stream->Read(data, size, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; @@ -34,9 +37,11 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi return S_OK; // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF } - UInt64 rem = _size - _virtPos; - if (rem < size) - size = (UInt32)rem; + { + const UInt64 rem = _size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } UInt64 newPos = _startOffset + _virtPos; if (newPos != _physPos) { diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index b521eeb9..fb1ac3cd 100644 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -30,6 +30,7 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } + UInt64 GetRem() const { return _size - _pos; } bool WasFinished() const { return _wasFinished; } }; diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index 04222e49..56f1b02f 100644 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -783,7 +783,7 @@ void CState::ThreadFunc() } packSize = Decoder->Base.BitDecoder.GetProcessedSize(); } - catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } + catch(const CInBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } if (res != S_OK) { @@ -809,7 +809,7 @@ void CState::ThreadFunc() res = S_FALSE; } } - catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } + catch(const COutBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } if (res != S_OK) { diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index bf05f59f..05d6fa16 100644 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -214,11 +214,13 @@ public: HRESULT Flush() { return m_OutStream.Flush(); } + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) #ifndef _7ZIP_ST - MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties) - #else - MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) #endif + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderProperties) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp index 0dd6ec9a..6e960366 100644 --- a/CPP/7zip/Compress/BZip2Register.cpp +++ b/CPP/7zip/Compress/BZip2Register.cpp @@ -5,14 +5,21 @@ #include "../Common/RegisterCodec.h" #include "BZip2Decoder.h" +#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY) +#include "BZip2Encoder.h" +#endif -REGISTER_CODEC_CREATE(CreateDec, NCompress::NBZip2::CDecoder) +namespace NCompress { +namespace NBZip2 { + +REGISTER_CODEC_CREATE(CreateDec, CDecoder) #if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY) -#include "BZip2Encoder.h" -REGISTER_CODEC_CREATE(CreateEnc, NCompress::NBZip2::CEncoder) +REGISTER_CODEC_CREATE(CreateEnc, CEncoder) #else #define CreateEnc NULL #endif REGISTER_CODEC_2(BZip2, CreateDec, CreateEnc, 0x40202, "BZip2") + +}} diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp index ef37ae0c..7a48f91c 100644 --- a/CPP/7zip/Compress/Bcj2Register.cpp +++ b/CPP/7zip/Compress/Bcj2Register.cpp @@ -6,9 +6,12 @@ #include "Bcj2Coder.h" -REGISTER_CODEC_CREATE_2(CreateCodec, NCompress::NBcj2::CDecoder(), ICompressCoder2) +namespace NCompress { +namespace NBcj2 { + +REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2) #ifndef EXTRACT_ONLY -REGISTER_CODEC_CREATE_2(CreateCodecOut, NCompress::NBcj2::CEncoder(), ICompressCoder2) +REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2) #else #define CreateCodecOut NULL #endif @@ -17,3 +20,5 @@ REGISTER_CODEC_VAR { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false }; REGISTER_CODEC(BCJ2) + +}} diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp index 37815dce..32aa1762 100644 --- a/CPP/7zip/Compress/BcjCoder.cpp +++ b/CPP/7zip/Compress/BcjCoder.cpp @@ -4,16 +4,21 @@ #include "BcjCoder.h" -STDMETHODIMP CBcjCoder::Init() +namespace NCompress { +namespace NBcj { + +STDMETHODIMP CCoder::Init() { _bufferPos = 0; x86_Convert_Init(_prevMask); return S_OK; } -STDMETHODIMP_(UInt32) CBcjCoder::Filter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size) { UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode); _bufferPos += processed; return processed; } + +}} diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h index 275fd4f2..7883906e 100644 --- a/CPP/7zip/Compress/BcjCoder.h +++ b/CPP/7zip/Compress/BcjCoder.h @@ -9,7 +9,10 @@ #include "../ICoder.h" -class CBcjCoder: +namespace NCompress { +namespace NBcj { + +class CCoder: public ICompressFilter, public CMyUnknownImp { @@ -17,10 +20,12 @@ class CBcjCoder: UInt32 _prevMask; int _encode; public: - MY_UNKNOWN_IMP; + MY_UNKNOWN_IMP1(ICompressFilter); INTERFACE_ICompressFilter(;) - CBcjCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); } + CCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); } }; +}} + #endif diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp index 83c6830f..f06dcfe9 100644 --- a/CPP/7zip/Compress/BcjRegister.cpp +++ b/CPP/7zip/Compress/BcjRegister.cpp @@ -6,7 +6,12 @@ #include "BcjCoder.h" +namespace NCompress { +namespace NBcj { + REGISTER_FILTER_E(BCJ, - CBcjCoder(false), - CBcjCoder(true), + CCoder(false), + CCoder(true), 0x3030103, "BCJ") + +}} diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp index 0bf39b79..d0e75e83 100644 --- a/CPP/7zip/Compress/BranchMisc.cpp +++ b/CPP/7zip/Compress/BranchMisc.cpp @@ -4,15 +4,20 @@ #include "BranchMisc.h" -STDMETHODIMP CBranchCoder::Init() +namespace NCompress { +namespace NBranch { + +STDMETHODIMP CCoder::Init() { _bufferPos = 0; return S_OK; } -STDMETHODIMP_(UInt32) CBranchCoder::Filter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size) { UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode); _bufferPos += processed; return processed; } + +}} diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h index bbb5add9..66fc23d2 100644 --- a/CPP/7zip/Compress/BranchMisc.h +++ b/CPP/7zip/Compress/BranchMisc.h @@ -13,7 +13,10 @@ typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding); EXTERN_C_END -class CBranchCoder: +namespace NCompress { +namespace NBranch { + +class CCoder: public ICompressFilter, public CMyUnknownImp { @@ -21,10 +24,12 @@ class CBranchCoder: int _encode; Func_Bra BraFunc; public: - MY_UNKNOWN_IMP; + MY_UNKNOWN_IMP1(ICompressFilter); INTERFACE_ICompressFilter(;) - CBranchCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {} + CCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {} }; +}} + #endif diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp index e1fcff6d..6331c1b9 100644 --- a/CPP/7zip/Compress/BranchRegister.cpp +++ b/CPP/7zip/Compress/BranchRegister.cpp @@ -8,9 +8,12 @@ #include "BranchMisc.h" +namespace NCompress { +namespace NBranch { + #define CREATE_BRA(n) \ - REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CBranchCoder(n ## _Convert, false)) \ - REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CBranchCoder(n ## _Convert, true)) \ + REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(n ## _Convert, false)) \ + REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(n ## _Convert, true)) \ CREATE_BRA(PPC) CREATE_BRA(IA64) @@ -34,3 +37,5 @@ REGISTER_CODECS_VAR }; REGISTER_CODECS(Branch) + +}} diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp index f5620d6c..4c11806e 100644 --- a/CPP/7zip/Compress/ByteSwap.cpp +++ b/CPP/7zip/Compress/ByteSwap.cpp @@ -8,12 +8,15 @@ #include "../Common/RegisterCodec.h" +namespace NCompress { +namespace NByteSwap { + class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressFilter); INTERFACE_ICompressFilter(;) }; @@ -22,7 +25,7 @@ class CByteSwap4: public CMyUnknownImp { public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressFilter); INTERFACE_ICompressFilter(;) }; @@ -85,3 +88,5 @@ REGISTER_CODECS_VAR }; REGISTER_CODECS(ByteSwap) + +}} diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp index 703c52ca..7141ab58 100644 --- a/CPP/7zip/Compress/CopyRegister.cpp +++ b/CPP/7zip/Compress/CopyRegister.cpp @@ -6,6 +6,10 @@ #include "CopyCoder.h" -REGISTER_CODEC_CREATE(CreateCodec, NCompress::CCopyCoder()) +namespace NCompress { + +REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder()) REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy") + +} diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp index 4b2cf0f7..14d20bb3 100644 --- a/CPP/7zip/Compress/Deflate64Register.cpp +++ b/CPP/7zip/Compress/Deflate64Register.cpp @@ -6,13 +6,21 @@ #include "DeflateDecoder.h" -REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder64()) - #if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) #include "DeflateEncoder.h" -REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder64()) +#endif + +namespace NCompress { +namespace NDeflate { + +REGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder64()) + +#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) +REGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder64()) #else #define CreateEnc NULL #endif REGISTER_CODEC_2(Deflate64, CreateDec, CreateEnc, 0x40109, "Deflate64") + +}} diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h index 0b29737f..5b2dd32d 100644 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -92,14 +92,16 @@ public: const UInt64 *outSize, ICompressProgressInfo *progress); #ifndef NO_READ_FROM_CODER - MY_UNKNOWN_IMP4( + MY_UNKNOWN_IMP5( + ICompressCoder, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream ) #else - MY_UNKNOWN_IMP1( + MY_UNKNOWN_IMP2( + ICompressCoder, ICompressGetInStreamProcessedSize) #endif diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index 62423a34..6c4ae4fc 100644 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -190,7 +190,7 @@ class CCOMCoder : public CCoder { public: - MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties) CCOMCoder(): CCoder(false) {}; STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); @@ -204,7 +204,7 @@ class CCOMCoder64 : public CCoder { public: - MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties) CCOMCoder64(): CCoder(true) {}; STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp index 32221fcc..387be6ed 100644 --- a/CPP/7zip/Compress/DeflateRegister.cpp +++ b/CPP/7zip/Compress/DeflateRegister.cpp @@ -5,14 +5,21 @@ #include "../Common/RegisterCodec.h" #include "DeflateDecoder.h" +#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) +#include "DeflateEncoder.h" +#endif -REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder) +namespace NCompress { +namespace NDeflate { + +REGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder) #if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) -#include "DeflateEncoder.h" -REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder) +REGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder) #else #define CreateEnc NULL #endif REGISTER_CODEC_2(Deflate, CreateDec, CreateEnc, 0x40108, "Deflate") + +}} diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp index d90f62f5..3986ae4f 100644 --- a/CPP/7zip/Compress/DeltaFilter.cpp +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -10,6 +10,9 @@ #include "../Common/RegisterCodec.h" +namespace NCompress { +namespace NDelta { + struct CDelta { unsigned _delta; @@ -22,7 +25,7 @@ struct CDelta #ifndef EXTRACT_ONLY -class CDeltaEncoder: +class CEncoder: public ICompressFilter, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, @@ -30,25 +33,25 @@ class CDeltaEncoder: public CMyUnknownImp { public: - MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + MY_UNKNOWN_IMP3(ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties) INTERFACE_ICompressFilter(;) STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); }; -STDMETHODIMP CDeltaEncoder::Init() +STDMETHODIMP CEncoder::Init() { DeltaInit(); return S_OK; } -STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) { Delta_Encode(_state, _delta, data, size); return size; } -STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) { UInt32 delta = _delta; for (UInt32 i = 0; i < numProps; i++) @@ -75,7 +78,7 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP return S_OK; } -STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte prop = (Byte)(_delta - 1); return outStream->Write(&prop, 1, NULL); @@ -84,31 +87,31 @@ STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream #endif -class CDeltaDecoder: +class CDecoder: public ICompressFilter, public ICompressSetDecoderProperties2, CDelta, public CMyUnknownImp { public: - MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + MY_UNKNOWN_IMP2(ICompressFilter, ICompressSetDecoderProperties2) INTERFACE_ICompressFilter(;) STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; -STDMETHODIMP CDeltaDecoder::Init() +STDMETHODIMP CDecoder::Init() { DeltaInit(); return S_OK; } -STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) { Delta_Decode(_state, _delta, data, size); return size; } -STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) { if (size != 1) return E_INVALIDARG; @@ -118,6 +121,8 @@ STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size REGISTER_FILTER_E(Delta, - CDeltaDecoder(), - CDeltaEncoder(), + CDecoder(), + CEncoder(), 3, "Delta") + +}} diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h index f0fb74d3..8ff6e838 100644 --- a/CPP/7zip/Compress/Lzma2Encoder.h +++ b/CPP/7zip/Compress/Lzma2Encoder.h @@ -20,7 +20,7 @@ class CEncoder: { CLzma2EncHandle _encoder; public: - MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp index d684d9d0..8f279ebf 100644 --- a/CPP/7zip/Compress/Lzma2Register.cpp +++ b/CPP/7zip/Compress/Lzma2Register.cpp @@ -10,8 +10,13 @@ #include "Lzma2Encoder.h" #endif +namespace NCompress { +namespace NLzma2 { + REGISTER_CODEC_E(LZMA2, - NCompress::NLzma2::CDecoder(), - NCompress::NLzma2::CEncoder(), + CDecoder(), + CEncoder(), 0x21, "LZMA2") + +}} diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h index 3ed067f1..f919ac2c 100644 --- a/CPP/7zip/Compress/LzmaEncoder.h +++ b/CPP/7zip/Compress/LzmaEncoder.h @@ -21,7 +21,7 @@ class CEncoder: CLzmaEncHandle _encoder; UInt64 _inputProcessed; public: - MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) + MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp index c12416f2..c802a99f 100644 --- a/CPP/7zip/Compress/LzmaRegister.cpp +++ b/CPP/7zip/Compress/LzmaRegister.cpp @@ -10,8 +10,13 @@ #include "LzmaEncoder.h" #endif +namespace NCompress { +namespace NLzma { + REGISTER_CODEC_E(LZMA, - NCompress::NLzma::CDecoder(), - NCompress::NLzma::CEncoder(), + CDecoder(), + CEncoder(), 0x30101, "LZMA") + +}} diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h index fb74cf57..671a5353 100644 --- a/CPP/7zip/Compress/PpmdEncoder.h +++ b/CPP/7zip/Compress/PpmdEncoder.h @@ -41,7 +41,8 @@ class CEncoder : CPpmd7 _ppmd; CEncProps _props; public: - MY_UNKNOWN_IMP2( + MY_UNKNOWN_IMP3( + ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp index 17f84bd0..a3ebb5f3 100644 --- a/CPP/7zip/Compress/PpmdRegister.cpp +++ b/CPP/7zip/Compress/PpmdRegister.cpp @@ -10,8 +10,13 @@ #include "PpmdEncoder.h" #endif +namespace NCompress { +namespace NPpmd { + REGISTER_CODEC_E(PPMD, - NCompress::NPpmd::CDecoder(), - NCompress::NPpmd::CEncoder(), + CDecoder(), + CEncoder(), 0x30401, "PPMD") + +}} diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index 496400a4..832eb112 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -154,7 +154,7 @@ HRESULT CDecoder::WriteBuf() FOR_VECTOR (i, _tempFilters) { CTempFilter *filter = _tempFilters[i]; - if (filter == NULL) + if (!filter) continue; if (filter->NextWindow) { @@ -187,8 +187,10 @@ HRESULT CDecoder::WriteBuf() while (i + 1 < _tempFilters.Size()) { CTempFilter *nextFilter = _tempFilters[i + 1]; - if (nextFilter == NULL || nextFilter->BlockStart != blockStart || - nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow) + if (!nextFilter + || nextFilter->BlockStart != blockStart + || nextFilter->BlockSize != outBlockRef.Size + || nextFilter->NextWindow) break; _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size); ExecuteFilter(++i, outBlockRef); @@ -203,7 +205,7 @@ HRESULT CDecoder::WriteBuf() for (unsigned j = i; j < _tempFilters.Size(); j++) { CTempFilter *filter = _tempFilters[j]; - if (filter != NULL && filter->NextWindow) + if (filter && filter->NextWindow) filter->NextWindow = false; } _wrPtr = writtenBorder; @@ -273,7 +275,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) for (i = 0; i < _tempFilters.Size(); i++) { _tempFilters[i - numEmptyItems] = _tempFilters[i]; - if (_tempFilters[i] == NULL) + if (!_tempFilters[i]) numEmptyItems++; if (numEmptyItems > 0) _tempFilters[i] = NULL; @@ -865,21 +867,21 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream { try { - if (inSize == NULL || outSize == NULL) + if (!inSize) return E_INVALIDARG; - if (_vmData == 0) + if (!_vmData) { _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax); - if (_vmData == 0) + if (!_vmData) return E_OUTOFMEMORY; _vmCode = _vmData + kVmDataSizeMax; } - if (_window == 0) + if (!_window) { _window = (Byte *)::MidAlloc(kWindowSize); - if (_window == 0) + if (!_window) return E_OUTOFMEMORY; } if (!m_InBitStream.BitDecoder.Create(1 << 20)) @@ -893,7 +895,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream _outStream = outStream; // CCoderReleaser coderReleaser(this); - _unpackSize = *outSize; + _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1; return CodeReal(progress); } catch(const CInBufferException &e) { return e.ErrorCode; } diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp index 2f3a1138..e1bc3d9b 100644 --- a/CPP/7zip/Compress/RarCodecsRegister.cpp +++ b/CPP/7zip/Compress/RarCodecsRegister.cpp @@ -9,7 +9,9 @@ #include "Rar3Decoder.h" #include "Rar5Decoder.h" -#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder()) +namespace NCompress { + +#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NRar ## x::CDecoder()) CREATE_CODEC(1) CREATE_CODEC(2) @@ -27,3 +29,5 @@ REGISTER_CODECS_VAR }; REGISTER_CODECS(Rar) + +} diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp index a89d323c..80b7e67c 100644 --- a/CPP/7zip/Compress/ShrinkDecoder.cpp +++ b/CPP/7zip/Compress/ShrinkDecoder.cpp @@ -1,7 +1,10 @@ // ShrinkDecoder.cpp + #include "StdAfx.h" +#include <stdio.h> + #include "../../../C/Alloc.h" #include "../Common/InBuffer.h" @@ -13,8 +16,8 @@ namespace NCompress { namespace NShrink { -static const UInt32 kBufferSize = (1 << 20); -static const int kNumMinBits = 9; +static const UInt32 kBufferSize = (1 << 18); +static const unsigned kNumMinBits = 9; HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) @@ -32,109 +35,121 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * outBuffer.SetStream(outStream); outBuffer.Init(); + { + unsigned i; + for (i = 0; i < 257; i++) + _parents[i] = (UInt16)i; + for (; i < kNumItems; i++) + _parents[i] = kNumItems; + for (i = 0; i < kNumItems; i++) + _suffixes[i] = 0; + } + UInt64 prevPos = 0; - int numBits = kNumMinBits; - UInt32 head = 257; - bool needPrev = false; - UInt32 lastSymbol = 0; - - int i; - for (i = 0; i < kNumItems; i++) - _parents[i] = 0; - for (i = 0; i < kNumItems; i++) - _suffixes[i] = 0; - for (i = 0; i < 257; i++) - _isFree[i] = false; - for (; i < kNumItems; i++) - _isFree[i] = true; + unsigned numBits = kNumMinBits; + unsigned head = 257; + int lastSym = -1; + Byte lastChar2 = 0; for (;;) { - UInt32 symbol = inBuffer.ReadBits(numBits); + UInt32 sym = inBuffer.ReadBits(numBits); + if (inBuffer.ExtraBitsWereRead()) break; - if (_isFree[symbol]) - return S_FALSE; - if (symbol == 256) + + if (sym == 256) { - UInt32 symbol = inBuffer.ReadBits(numBits); - if (symbol == 1) + sym = inBuffer.ReadBits(numBits); + if (sym == 1) { - if (numBits < kNumMaxBits) - numBits++; + if (numBits >= kNumMaxBits) + return S_FALSE; + numBits++; + continue; } - else if (symbol == 2) + if (sym != 2) + return S_FALSE; { - if (needPrev) - _isFree[head - 1] = true; + unsigned i; for (i = 257; i < kNumItems; i++) - _isParent[i] = false; + _stack[i] = 0; for (i = 257; i < kNumItems; i++) - if (!_isFree[i]) - _isParent[_parents[i]] = true; + { + unsigned par = _parents[i]; + if (par != kNumItems) + _stack[par] = 1; + } for (i = 257; i < kNumItems; i++) - if (!_isParent[i]) - _isFree[i] = true; + if (_stack[i] == 0) + _parents[i] = kNumItems; + head = 257; - while (head < kNumItems && !_isFree[head]) - head++; - if (head < kNumItems) + + continue; + } + } + + bool needPrev = false; + if (head < kNumItems && lastSym >= 0) + { + while (head < kNumItems && _parents[head] != kNumItems) + head++; + if (head < kNumItems) + { + if (head == (unsigned)lastSym) { - needPrev = true; - _isFree[head] = false; - _parents[head] = (UInt16)lastSymbol; - head++; + // we need to fix the code for that case + // _parents[head] is not allowed to link to itself + return E_NOTIMPL; } + needPrev = true; + _parents[head] = (UInt16)lastSym; + _suffixes[head] = (Byte)lastChar2; + head++; } - else - return S_FALSE; - continue; } - UInt32 cur = symbol; - i = 0; - int corectionIndex = -1; + + if (_parents[sym] == kNumItems) + return S_FALSE; + + lastSym = sym; + unsigned cur = sym; + unsigned i = 0; + while (cur >= 256) { - if (cur == head - 1) - corectionIndex = i; _stack[i++] = _suffixes[cur]; cur = _parents[cur]; } + _stack[i++] = (Byte)cur; + lastChar2 = (Byte)cur; + if (needPrev) - { _suffixes[head - 1] = (Byte)cur; - if (corectionIndex >= 0) - _stack[corectionIndex] = (Byte)cur; - } - while (i > 0) - outBuffer.WriteByte((_stack[--i])); - while (head < kNumItems && !_isFree[head]) - head++; - if (head < kNumItems) - { - needPrev = true; - _isFree[head] = false; - _parents[head] = (UInt16)symbol; - head++; - } - else - needPrev = false; - lastSymbol = symbol; - UInt64 nowPos = outBuffer.GetProcessedSize(); - if (progress != NULL && nowPos - prevPos > (1 << 18)) + do + outBuffer.WriteByte(_stack[--i]); + while (i); + + if (progress) { - prevPos = nowPos; - UInt64 packSize = inBuffer.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&packSize, &nowPos)); + const UInt64 nowPos = outBuffer.GetProcessedSize(); + if (nowPos - prevPos >= (1 << 18)) + { + prevPos = nowPos; + const UInt64 packSize = inBuffer.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &nowPos)); + } } } + return outBuffer.Flush(); } STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { try { return CodeReal(inStream, outStream, inSize, outSize, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h index 9bbecd41..42e5eee7 100644 --- a/CPP/7zip/Compress/ShrinkDecoder.h +++ b/CPP/7zip/Compress/ShrinkDecoder.h @@ -10,8 +10,8 @@ namespace NCompress { namespace NShrink { -const int kNumMaxBits = 13; -const UInt32 kNumItems = 1 << kNumMaxBits; +const unsigned kNumMaxBits = 13; +const unsigned kNumItems = 1 << kNumMaxBits; class CDecoder : public ICompressCoder, @@ -20,8 +20,6 @@ class CDecoder : UInt16 _parents[kNumItems]; Byte _suffixes[kNumItems]; Byte _stack[kNumItems]; - bool _isFree[kNumItems]; - bool _isParent[kNumItems]; public: MY_UNKNOWN_IMP diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h index 4bd7d291..84e07ac9 100644 --- a/CPP/7zip/Crypto/7zAes.h +++ b/CPP/7zip/Crypto/7zAes.h @@ -86,7 +86,8 @@ class CEncoder: public ICryptoResetInitVector { public: - MY_UNKNOWN_IMP3( + MY_UNKNOWN_IMP4( + ICompressFilter, ICryptoSetPassword, ICompressWriteCoderProperties, // ICryptoResetSalt, @@ -104,7 +105,8 @@ class CDecoder: public ICompressSetDecoderProperties2 { public: - MY_UNKNOWN_IMP2( + MY_UNKNOWN_IMP3( + ICompressFilter, ICryptoSetPassword, ICompressSetDecoderProperties2) STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp index f1916cb1..f9d59699 100644 --- a/CPP/7zip/Crypto/7zAesRegister.cpp +++ b/CPP/7zip/Crypto/7zAesRegister.cpp @@ -6,7 +6,12 @@ #include "7zAes.h" +namespace NCrypto { +namespace N7z { + REGISTER_FILTER_E(7zAES, - NCrypto::N7z::CDecoder(), - NCrypto::N7z::CEncoder(), + CDecoder(), + CEncoder(), 0x6F10701, "7zAES") + +}} diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h index 289935eb..84c21de3 100644 --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -30,7 +30,7 @@ class CAesCbcCoder: public: CAesCbcCoder(bool encodeMode, unsigned keySize); - MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties) + MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties) INTERFACE_ICompressFilter(;) diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp index 34035da6..28006835 100644 --- a/CPP/7zip/Crypto/MyAesReg.cpp +++ b/CPP/7zip/Crypto/MyAesReg.cpp @@ -6,7 +6,11 @@ #include "MyAes.h" +namespace NCrypto { + REGISTER_FILTER_E(AES256CBC, - NCrypto::CAesCbcDecoder(32), - NCrypto::CAesCbcEncoder(32), + CAesCbcDecoder(32), + CAesCbcEncoder(32), 0x6F00181, "AES256CBC") + +} diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 803a327a..4c0dbc77 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -304,14 +304,25 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) */ unsigned namePos = 0; + + unsigned numLevels = 0; + for (unsigned j = 0; j < len; j++) { wchar_t c = s[j]; if (c == WCHAR_PATH_SEPARATOR || c == L'/') { - name.SetFrom(s + namePos, j - namePos); - curItem = AddDir(curItem, -1, name); + const unsigned kLevelLimit = 1 << 10; + if (numLevels <= kLevelLimit) + { + if (numLevels == kLevelLimit) + name.SetFromAscii("[LONG_PATH]"); + else + name.SetFrom(s + namePos, j - namePos); + curItem = AddDir(curItem, -1, name); + } namePos = j + 1; + numLevels++; } } diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 1bd202ed..61a781af 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -1053,7 +1053,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; unsigned numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) - throw CArcCmdLineException("The command must be spcified"); + throw CArcCmdLineException("The command must be specified"); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index 359835d3..fd2807ac 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -43,6 +43,7 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) switch (propID) { case kpidName: prop = _subArchiveName; break; + // case kpidSize: prop = _subArchiveSize; break; // we don't use it now } else switch (propID) diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index e323abd2..4081b0a6 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -1632,6 +1632,36 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) #endif { + #ifndef _SFX + + bool isZip = false; + bool isRar = false; + + const wchar_t c = extension[0]; + if (c == 'z' || c == 'Z' || c == 'r' || c == 'R') + { + bool isNumber = false; + for (unsigned k = 1;; k++) + { + const wchar_t d = extension[k]; + if (d == 0) + break; + if (d < '0' || d > '9') + { + isNumber = false; + break; + } + isNumber = true; + } + if (isNumber) + if (c == 'z' || c == 'Z') + isZip = true; + else + isRar = true; + } + + #endif + FOR_VECTOR (i, op.codecs->Formats) { const CArcInfoEx &ai = op.codecs->Formats[i]; @@ -1647,7 +1677,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) isPrearcExt = true; #endif - if (ai.FindExtension(extension) >= 0) + if (ai.FindExtension(extension) >= 0 + #ifndef _SFX + || isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip") + || isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar") + #endif + ) { // PrintNumber("orderIndices.Insert", i); orderIndices.Insert(numFinded++, i); diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 74660186..a0e692d0 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -98,6 +98,8 @@ void CInfo::Load() OverwriteMode = NOverwriteMode::kAsk; OverwriteMode_Force = false; + SplitDest.Val = true; + Paths.Clear(); CS_LOCK diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index d94e28e6..4e4ac221 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -295,7 +295,7 @@ static bool IsItArcExt(const UString &ext) return false; } -static UString GetSubFolderNameForExtract(const UString &arcName) +UString GetSubFolderNameForExtract(const UString &arcName) { int dotPos = arcName.ReverseFind_Dot(); if (dotPos < 0) diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index a262029f..6d5662de 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -46,7 +46,7 @@ void CPanelCallbackImp::OnTab() _app->RefreshTitle(); } -void CPanelCallbackImp::SetFocusToPath(int index) +void CPanelCallbackImp::SetFocusToPath(unsigned index) { int newPanelIndex = index; if (g_App.NumPanels == 1) @@ -60,10 +60,10 @@ void CPanelCallbackImp::SetFocusToPath(int index) void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); } void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); } void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); } -void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); } +void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitlePanel(_index); } void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); } void CPanelCallbackImp::DragEnd() { _app->DragEnd(); } -void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); } +void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitlePanel(_index, always); } void CApp::ReloadLang() { @@ -115,11 +115,14 @@ void CApp::SetListSettings() #endif HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, - bool &archiveIsOpened, bool &encrypted) + bool needOpenArc, + bool &archiveIsOpened, bool &encrypted) { - if (PanelsCreated[panelIndex]) + if (Panels[panelIndex].PanelCreated) return S_OK; + m_PanelCallbackImp[panelIndex].Init(this, panelIndex); + UString path; if (mainPath.IsEmpty()) { @@ -128,13 +131,16 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr } else path = mainPath; + int id = 1000 + 100 * panelIndex; - RINOK(Panels[panelIndex].Create(_window, _window, - id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted)); - PanelsCreated[panelIndex] = true; - return S_OK; + + return Panels[panelIndex].Create(_window, _window, + id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, + needOpenArc, + archiveIsOpened, encrypted); } + static void CreateToolbar(HWND parent, NControl::CImageList &imageList, NControl::CToolBar &toolBar, @@ -165,6 +171,7 @@ static void CreateToolbar(HWND parent, toolBar.SetImageList(0, imageList); } + struct CButtonInfo { int CommandID; @@ -273,9 +280,11 @@ void CApp::SaveToolbarChanges() MoveSubWindows(); } + void MyLoadMenu(); -HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted) + +HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted) { _window.Attach(hwnd); @@ -292,9 +301,9 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma ReadToolbar(); ReloadToolbars(); - int i; + unsigned i; for (i = 0; i < kNumPanelsMax; i++) - PanelsCreated[i] = false; + Panels[i].PanelCreated = false; AppState.Read(); @@ -316,33 +325,52 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma } for (i = 0; i < kNumPanelsMax; i++) - if (NumPanels > 1 || i == LastFocusedPanel) + { + unsigned panelIndex = i; + if (needOpenArc && LastFocusedPanel == 1) + panelIndex = 1 - i; + + bool isMainPanel = (panelIndex == LastFocusedPanel); + + if (NumPanels > 1 || isMainPanel) { if (NumPanels == 1) - Panels[i]._xSize = xSizes[0] + xSizes[1]; + Panels[panelIndex]._xSize = xSizes[0] + xSizes[1]; bool archiveIsOpened2 = false; bool encrypted2 = false; - bool mainPanel = (i == LastFocusedPanel); - RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", arcFormat, archiveIsOpened2, encrypted2)); - if (mainPanel) + UString path; + if (isMainPanel) + path = mainPath; + + RINOK(CreateOnePanel(panelIndex, path, arcFormat, + isMainPanel && needOpenArc, + archiveIsOpened2, encrypted2)); + + if (isMainPanel) { archiveIsOpened = archiveIsOpened2; encrypted = encrypted2; + if (needOpenArc && !archiveIsOpened2) + return S_OK; } } + } SetFocusedPanel(LastFocusedPanel); Panels[LastFocusedPanel].SetFocusToList(); return S_OK; } + HRESULT CApp::SwitchOnOffOnePanel() { if (NumPanels == 1) { NumPanels++; bool archiveIsOpened, encrypted; - RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), archiveIsOpened, encrypted)); + RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), + false, // needOpenArc + archiveIsOpened, encrypted)); Panels[1 - LastFocusedPanel].Enable(true); Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL); } @@ -530,7 +558,7 @@ static bool IsFsPath(const FString &path) void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { - int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &srcPanel = Panels[srcPanelIndex]; CPanel &destPanel = Panels[destPanelIndex]; @@ -854,7 +882,7 @@ int CApp::GetFocusedPanelIndex() const { if (hwnd == 0) return 0; - for (int i = 0; i < kNumPanelsMax; i++) + for (unsigned i = 0; i < kNumPanelsMax; i++) { if (PanelsCreated[i] && ((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd)) @@ -906,7 +934,7 @@ void CApp::RefreshTitle(bool always) NWindows::MySetWindowText(_window, path); } -void CApp::RefreshTitle(int panelIndex, bool always) +void CApp::RefreshTitlePanel(unsigned panelIndex, bool always) { if (panelIndex != GetFocusedPanelIndex()) return; diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index dedbd821..9cc1066b 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -14,7 +14,7 @@ class CApp; extern CApp g_App; extern HWND g_HWND; -const int kNumPanelsMax = 2; +const unsigned kNumPanelsMax = 2; extern bool g_IsSmallScreen; @@ -32,15 +32,15 @@ enum class CPanelCallbackImp: public CPanelCallback { CApp *_app; - int _index; + unsigned _index; public: - void Init(CApp *app, int index) + void Init(CApp *app, unsigned index) { _app = app; _index = index; } virtual void OnTab(); - virtual void SetFocusToPath(int index); + virtual void SetFocusToPath(unsigned index); virtual void OnCopy(bool move, bool copyToSame); virtual void OnSetSameFolder(); virtual void OnSetSubFolder(); @@ -111,8 +111,8 @@ public: NWindows::CWindow _window; bool ShowSystemMenu; // bool ShowDeletedFiles; - int NumPanels; - int LastFocusedPanel; + unsigned NumPanels; + unsigned LastFocusedPanel; bool ShowStandardToolbar; bool ShowArchiveToolbar; @@ -122,7 +122,6 @@ public: CAppState AppState; CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax]; CPanel Panels[kNumPanelsMax]; - bool PanelsCreated[kNumPanelsMax]; NWindows::NControl::CImageList _buttonsImageList; @@ -151,13 +150,13 @@ public: _dropTargetSpec->App = (this); } - void SetFocusedPanel(int index) + void SetFocusedPanel(unsigned index) { LastFocusedPanel = index; _dropTargetSpec->TargetPanelIndex = LastFocusedPanel; } - void DragBegin(int panelIndex) + void DragBegin(unsigned panelIndex) { _dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex; _dropTargetSpec->SrcPanelIndex = panelIndex; @@ -174,16 +173,16 @@ public: void OnSetSameFolder(int srcPanelIndex); void OnSetSubFolder(int srcPanelIndex); - HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted); - HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted); + HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, bool &archiveIsOpened, bool &encrypted); + HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted); void Read(); void Save(); void Release(); // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); } void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); } - int GetFocusedPanelIndex() const { return LastFocusedPanel; } - bool IsPanelVisible(int index) const { return (NumPanels > 1 || index == LastFocusedPanel); } + unsigned GetFocusedPanelIndex() const { return LastFocusedPanel; } + bool IsPanelVisible(unsigned index) const { return (NumPanels > 1 || index == LastFocusedPanel); } CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; } // File Menu @@ -235,9 +234,9 @@ public: void RefreshView() { GetFocusedPanel().OnReload(); } void RefreshAllPanels() { - for (int i = 0; i < NumPanels; i++) + for (unsigned i = 0; i < NumPanels; i++) { - int index = i; + unsigned index = i; if (NumPanels == 1) index = LastFocusedPanel; Panels[index].OnReload(); @@ -247,9 +246,9 @@ public: /* void SysIconsWereChanged() { - for (int i = 0; i < NumPanels; i++) + for (unsigned i = 0; i < NumPanels; i++) { - int index = i; + unsigned index = i; if (NumPanels == 1) index = LastFocusedPanel; Panels[index].SysIconsWereChanged(); @@ -280,7 +279,7 @@ public: } void SetPanels_AutoRefresh_Mode() { - for (int i = 0; i < kNumPanelsMax; i++) + for (unsigned i = 0; i < kNumPanelsMax; i++) Panels[i].Set_AutoRefresh_Mode(AutoRefresh_Mode); } @@ -347,7 +346,7 @@ public: UString PrevTitle; void RefreshTitle(bool always = false); void RefreshTitleAlways() { RefreshTitle(true); } - void RefreshTitle(int panelIndex, bool always = false); + void RefreshTitlePanel(unsigned panelIndex, bool always = false); void MoveSubWindows(); }; diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index f91dda09..35b757dd 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -157,6 +157,7 @@ static bool g_CanChangeSplitter = false; static UInt32 g_SplitterPos = 0; static CSplitterPos g_Splitter; static bool g_PanelsInfoDefined = false; +static bool g_WindowWasCreated = false; static int g_StartCaptureMousePos; static int g_StartCaptureSplitterPos; @@ -238,8 +239,9 @@ static BOOL InitInstance(int nCmdShow) if (windowPosIsRead) { - // x = rect.left; - // y = rect.top; + x = info.rect.left; + y = info.rect.top; + xSize = RECT_SIZE_X(info.rect); ySize = RECT_SIZE_Y(info.rect); } @@ -258,6 +260,7 @@ static BOOL InitInstance(int nCmdShow) info.numPanels = kNumDefaultPanels; info.currentPanel = 0; } + g_App.NumPanels = info.numPanels; g_App.LastFocusedPanel = info.currentPanel; @@ -832,7 +835,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) needOpenFile = true; } - HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted); + HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, + needOpenFile, + archiveIsOpened, encrypted); if (res == E_ABORT) return -1; @@ -852,6 +857,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ErrorMessage(message); return -1; } + + g_WindowWasCreated = true; // g_SplitterPos = 0; @@ -867,9 +874,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) RevokeDragDrop(hWnd); g_App._dropTarget.Release(); - g_App.Save(); + if (g_WindowWasCreated) + g_App.Save(); + g_App.Release(); - SaveWindowInfo(hWnd); + + if (g_WindowWasCreated) + SaveWindowInfo(hWnd); g_ExitEventLauncher.Exit(true); PostQuitMessage(0); diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index 07f046e1..ac12a0eb 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -333,7 +333,7 @@ void CApp::Link() const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index); UString path = srcPath; { - int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index 96a34af8..a80fd049 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -74,6 +74,7 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, const UString ¤tFolderPrefix, const UString &arcFormat, CPanelCallback *panelCallback, CAppState *appState, + bool needOpenArc, bool &archiveIsOpened, bool &encrypted) { _mainWindow = mainWindow; @@ -100,10 +101,15 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted)); + if (needOpenArc && !archiveIsOpened) + return S_OK; + if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE, 0, 0, _xSize, 260, parentWindow, (HMENU)(UINT_PTR)id, g_hInstance)) return E_FAIL; + PanelCreated = true; + return S_OK; } @@ -525,7 +531,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) _statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID); // _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1); - int sizes[] = {160, 250, 350, -1}; + const int sizes[] = {220, 320, 420, -1}; _statusBar.SetParts(4, sizes); // _statusBar2.SetParts(5, sizes); @@ -834,18 +840,20 @@ void CPanel::AddToArchive() // KillSelection(); } -static UString GetSubFolderNameForExtract(const UString &arcPath) +// function from ContextMenu.cpp +UString GetSubFolderNameForExtract(const UString &arcPath); + +static UString GetSubFolderNameForExtract2(const UString &arcPath) { - UString s = arcPath; - int slashPos = s.ReverseFind_PathSepar(); - int dotPos = s.ReverseFind_Dot(); - if (dotPos <= slashPos + 1) - s += L'~'; - else + int slashPos = arcPath.ReverseFind_PathSepar(); + UString s; + UString name = arcPath; + if (slashPos >= 0) { - s.DeleteFrom(dotPos); - s.TrimRight(); + s = arcPath.Left(slashPos + 1); + name = arcPath.Ptr(slashPos + 1); } + s += GetSubFolderNameForExtract(name); return s; } @@ -885,7 +893,7 @@ void CPanel::ExtractArchives() UString outFolder = GetFsPath(); if (indices.Size() == 1) - outFolder += GetSubFolderNameForExtract(GetItemRelPath(indices[0])); + outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0])); else outFolder += L'*'; outFolder.Add_PathSepar(); diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index fc74d556..261388de 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -57,7 +57,7 @@ const int kParentIndex = -1; struct CPanelCallback { virtual void OnTab() = 0; - virtual void SetFocusToPath(int index) = 0; + virtual void SetFocusToPath(unsigned index) = 0; virtual void OnCopy(bool move, bool copyToSame) = 0; virtual void OnSetSameFolder() = 0; virtual void OnSetSubFolder() = 0; @@ -222,6 +222,7 @@ struct CSelectedState UString FocusedName; bool SelectFocused; UStringVector SelectedNames; + CSelectedState(): FocusedItem(-1), SelectFocused(false) {} }; @@ -377,6 +378,8 @@ public: bool _thereAreDeletedItems; bool _markDeletedItems; + bool PanelCreated; + HWND GetParent(); UInt32 GetRealIndex(const LVITEMW &item) const @@ -460,8 +463,8 @@ public: HRESULT BindToPathAndRefresh(const UString &path); void OpenDrivesFolder(); - void SetBookmark(int index); - void OpenBookmark(int index); + void SetBookmark(unsigned index); + void OpenBookmark(unsigned index); void LoadFullPath(); void LoadFullPathAndShow(); @@ -477,7 +480,9 @@ public: const UString ¤tFolderPrefix, const UString &arcFormat, CPanelCallback *panelCallback, - CAppState *appState, bool &archiveIsOpened, bool &encrypted); + CAppState *appState, + bool needOpenArc, + bool &archiveIsOpened, bool &encrypted); void SetFocusToList(); void SetFocusToLastRememberedItem(); @@ -496,6 +501,7 @@ public: _flatMode(false), _flatModeForDisk(false), _flatModeForArc(false), + PanelCreated(false), // _showNtfsStrems_Mode(false), // _showNtfsStrems_ModeForDisk(false), diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 0cd08d4c..befd19f5 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -16,6 +16,7 @@ #include "../Common/ArchiveName.h" #include "../Common/CompressCall.h" +#include "../Common/ExtractingFilePath.h" #include "MessagesDialog.h" @@ -350,7 +351,10 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) if (isFSFolder) s = GetItemRelPath(index); else + { s = GetItemName(index); + s = Get_Correct_FsFile_Name(s); + } names.Add(fs2us(dirPrefix) + s); } if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names)) @@ -470,7 +474,7 @@ void CDropTarget::PositionCursor(POINTL ptl) { POINT pt2 = pt; App->_window.ScreenToClient(&pt2); - for (int i = 0; i < kNumPanelsMax; i++) + for (unsigned i = 0; i < kNumPanelsMax; i++) if (App->IsPanelVisible(i)) if (App->Panels[i].IsEnabled()) if (ChildWindowFromPointEx(App->_window, pt2, @@ -478,7 +482,7 @@ void CDropTarget::PositionCursor(POINTL ptl) { m_Panel = &App->Panels[i]; m_IsAppTarget = false; - if (i == SrcPanelIndex) + if ((int)i == SrcPanelIndex) { m_PanelDropIsAllowed = false; return; diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index e4fbb5b3..91b6feb1 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -263,12 +263,12 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path) return S_OK; } -void CPanel::SetBookmark(int index) +void CPanel::SetBookmark(unsigned index) { _appState->FastFolders.SetString(index, _currentFolderPrefix); } -void CPanel::OpenBookmark(int index) +void CPanel::OpenBookmark(unsigned index) { BindToPathAndRefresh(_appState->FastFolders.GetString(index)); } diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index a8c0d352..7aaa97b1 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -189,7 +189,7 @@ void CApp::Split() UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); UString path = srcPath; - int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) @@ -367,7 +367,7 @@ void CApp::Combine() UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); UString path = srcPath; - int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); + unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp index 2c343b31..4b662f52 100644 --- a/CPP/Common/CrcReg.cpp +++ b/CPP/Common/CrcReg.cpp @@ -34,7 +34,7 @@ class CCrcHasher: public: CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); } - MY_UNKNOWN_IMP1(ICompressSetCoderProperties) + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) INTERFACE_IHasher(;) STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); }; diff --git a/CPP/Common/DynLimBuf.cpp b/CPP/Common/DynLimBuf.cpp index 388c5952..1d1d99dc 100644 --- a/CPP/Common/DynLimBuf.cpp +++ b/CPP/Common/DynLimBuf.cpp @@ -71,7 +71,7 @@ CDynLimBuf &CDynLimBuf::operator+=(const char *s) throw() size_t n = _pos + len; if (n - _size < _size) { - size_t n = _sizeLimit; + n = _sizeLimit; if (n - _size > _size) n = _size * 2; } diff --git a/CPP/Common/Sha1Reg.cpp b/CPP/Common/Sha1Reg.cpp index eedb7e29..1400c989 100644 --- a/CPP/Common/Sha1Reg.cpp +++ b/CPP/Common/Sha1Reg.cpp @@ -18,7 +18,7 @@ class CSha1Hasher: public: CSha1Hasher() { Sha1_Init(&_sha); } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(IHasher) INTERFACE_IHasher(;) }; diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp index 6c822cc7..66941699 100644 --- a/CPP/Common/Sha256Reg.cpp +++ b/CPP/Common/Sha256Reg.cpp @@ -18,7 +18,7 @@ class CSha256Hasher: public: CSha256Hasher() { Sha256_Init(&_sha); } - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(IHasher) INTERFACE_IHasher(;) }; diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp index d1a51338..33b52493 100644 --- a/CPP/Common/XzCrc64Reg.cpp +++ b/CPP/Common/XzCrc64Reg.cpp @@ -19,7 +19,7 @@ class CXzCrc64Hasher: public: CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {} - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(IHasher) INTERFACE_IHasher(;) }; |