diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipIn.h')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/Archive/Zip/ZipIn.h | 178 |
1 files changed, 122 insertions, 56 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 0565339a..f6b349b1 100755..100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -3,121 +3,187 @@ #ifndef __ZIP_IN_H #define __ZIP_IN_H -#include "Common/MyCom.h" +#include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../Common/InBuffer.h" #include "ZipHeader.h" -#include "ZipItemEx.h" +#include "ZipItem.h" + +API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size); namespace NArchive { namespace NZip { -class CInArchiveException +class CItemEx: public CItem { public: - enum ECauseType - { - kUnexpectedEndOfArchive = 0, - kArchiceHeaderCRCError, - kFileHeaderCRCError, - kIncorrectArchive, - kDataDescroptorsAreNotSupported, - kMultiVolumeArchiveAreNotSupported, - kReadStreamError, - kSeekStreamError - } - Cause; - CInArchiveException(ECauseType cause): Cause(cause) {} + UInt32 LocalFullHeaderSize; // including Name and Extra + + UInt64 GetLocalFullSize() const + { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); } + UInt64 GetDataPosition() const + { return LocalHeaderPos + LocalFullHeaderSize; }; }; -class CInArchiveInfo +struct CInArchiveInfo { -public: - UInt64 Base; - UInt64 StartPosition; - UInt64 FinishPosition; + Int64 Base; /* Base offset of start of archive in stream. + Offsets in headers must be calculated from that Base. + Base is equal to MarkerPos for normal ZIPs. + Base can point to PE stub for some ZIP SFXs. + if CentralDir was read, + Base can be negative, if start of data is not available, + if CentralDirs was not read, + Base = ArcInfo.MarkerPos; */ + + /* The following *Pos variables contain absolute offsets in Stream */ + UInt64 MarkerPos; /* Pos of first signature, it can point to PK00 signature + = MarkerPos2 in most archives + = MarkerPos2 - 4 if there is PK00 signature */ + UInt64 MarkerPos2; // Pos of first local item signature in stream + UInt64 FinishPos; // Finish pos of archive data + 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; + CByteBuffer Comment; - CInArchiveInfo(): Base(0), StartPosition(0) {} - UInt64 GetPhySize() const { return FinishPosition - StartPosition; } + 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; } + void Clear() { Base = 0; - StartPosition = 0; - Comment.SetCapacity(0); + MarkerPos = 0; + MarkerPos2 = 0; + FinishPos = 0; + FileEndPos = 0; + + FirstItemRelatOffset = 0; + CdWasRead = false; + + Comment.Free(); } }; -class CProgressVirt +struct CProgressVirt { -public: - STDMETHOD(SetTotal)(UInt64 numFiles) PURE; - STDMETHOD(SetCompleted)(UInt64 numFiles) PURE; + virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) = 0; + virtual HRESULT SetTotalCD(UInt64 numFiles) = 0; + virtual HRESULT SetCompletedCD(UInt64 numFiles) = 0; }; struct CCdInfo { - // UInt64 NumEntries; + UInt64 NumEntries; UInt64 Size; UInt64 Offset; + + void ParseEcd(const Byte *p); + void ParseEcd64(const Byte *p); }; class CInArchive { - CMyComPtr<IInStream> m_Stream; + CInBuffer _inBuffer; + bool _inBufMode; UInt32 m_Signature; - UInt64 m_StreamStartPosition; UInt64 m_Position; - - bool _inBufMode; - CInBuffer _inBuffer; HRESULT Seek(UInt64 offset); - HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - void ReadFileName(UInt32 nameSize, AString &dest); - + HRESULT IncreaseRealPosition(UInt64 addValue); + HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); - bool ReadBytesAndTestSize(void *data, UInt32 size); - void SafeReadBytes(void *data, UInt32 size); - void ReadBuffer(CByteBuffer &buffer, UInt32 size); + void SafeReadBytes(void *data, unsigned size); + void ReadBuffer(CByteBuffer &buffer, unsigned size); Byte ReadByte(); UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); - bool ReadUInt32(UInt32 &signature); - - void Skip(UInt64 num); - void IncreaseRealPosition(UInt64 addValue); - - void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, + void Skip(unsigned num); + void Skip64(UInt64 num); + void ReadFileName(unsigned nameSize, AString &dest); + + bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber); - HRESULT ReadLocalItem(CItemEx &item); + bool ReadLocalItem(CItemEx &item); 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 ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems); + HRESULT ReadLocals(CObjectVector<CItemEx> &localItems, CProgressVirt *progress); + + HRESULT ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress); public: CInArchiveInfo ArcInfo; + + bool IsArc; bool IsZip64; - bool IsOkHeaders; - + bool HeadersError; + bool HeadersWarning; + bool ExtraMinorError; + bool UnexpectedEnd; + bool NoCentralDir; + + CMyComPtr<IInStream> Stream; + + void Close(); + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress); + + bool IsOpen() const { return Stream != NULL; } + bool AreThereErrors() const { return HeadersError || UnexpectedEnd; } + + bool IsLocalOffsetOK(const CItemEx &item) const + { + if (item.FromLocal) + return true; + return /* ArcInfo.Base >= 0 || */ ArcInfo.Base + (Int64)item.LocalHeaderPos >= 0; + } + HRESULT ReadLocalItemAfterCdItem(CItemEx &item); HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item); - HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - void Close(); - bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); - IInStream* CreateStream(); - bool IsOpen() const { return m_Stream != NULL; } + UInt64 GetOffsetInStream(UInt64 offsetFromArc) const { return ArcInfo.Base + offsetFromArc; } + + bool CanUpdate() const + { + if (AreThereErrors()) + return false; + if (ArcInfo.Base < 0) + return false; + if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base) + 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; + } }; }} |