diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipIn.h')
-rw-r--r-- | CPP/7zip/Archive/Zip/ZipIn.h | 261 |
1 files changed, 213 insertions, 48 deletions
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; } }; |