X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bddd7a8d8953cf4c09e56c13e1bfcc594ba0267e..eba99da4c0563e6508761272a1e1f1b791d0af6b:/include/wx/zipstrm.h diff --git a/include/wx/zipstrm.h b/include/wx/zipstrm.h index b8a098c0e0..976a17050b 100644 --- a/include/wx/zipstrm.h +++ b/include/wx/zipstrm.h @@ -1,61 +1,531 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: zipstream.h -// Purpose: wxZipInputStream for reading files from ZIP archive -// Author: Vaclav Slavik -// Copyright: (c) 1999 Vaclav Slavik -// Licence: wxWindows Licence +// Name: zipstrm.h +// Purpose: Streams for Zip files +// Author: Mike Wetherell +// RCS-ID: $Id$ +// Copyright: (c) Mike Wetherell +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifndef __ZIPSTREAM_H__ -#define __ZIPSTREAM_H__ +#ifndef _WX_WXZIPSTREAM_H__ +#define _WX_WXZIPSTREAM_H__ -#if defined(__GNUG__) && !defined(__APPLE__) +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "zipstrm.h" #endif #include "wx/defs.h" -#if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB +#if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM -#include "wx/stream.h" +#include "wx/archive.h" +#include "wx/hashmap.h" +#include "wx/filename.h" -//-------------------------------------------------------------------------------- -// wxZipInputStream -// This class is input stream from ZIP archive. The archive -// must be local file (accessible via FILE*) -//-------------------------------------------------------------------------------- +///////////////////////////////////////////////////////////////////////////// +// constants + +// Compression Method, only 0 (store) and 8 (deflate) are supported here +// +enum wxZipMethod +{ + wxZIP_METHOD_STORE, + wxZIP_METHOD_SHRINK, + wxZIP_METHOD_REDUCE1, + wxZIP_METHOD_REDUCE2, + wxZIP_METHOD_REDUCE3, + wxZIP_METHOD_REDUCE4, + wxZIP_METHOD_IMPLODE, + wxZIP_METHOD_TOKENIZE, + wxZIP_METHOD_DEFLATE, + wxZIP_METHOD_DEFLATE64, + wxZIP_METHOD_BZIP2 = 12, + wxZIP_METHOD_DEFAULT = 0xffff +}; + +// Originating File-System. +// +// These are Pkware's values. Note that Info-zip disagree on some of them, +// most notably NTFS. +// +enum wxZipSystem +{ + wxZIP_SYSTEM_MSDOS, + wxZIP_SYSTEM_AMIGA, + wxZIP_SYSTEM_OPENVMS, + wxZIP_SYSTEM_UNIX, + wxZIP_SYSTEM_VM_CMS, + wxZIP_SYSTEM_ATARI_ST, + wxZIP_SYSTEM_OS2_HPFS, + wxZIP_SYSTEM_MACINTOSH, + wxZIP_SYSTEM_Z_SYSTEM, + wxZIP_SYSTEM_CPM, + wxZIP_SYSTEM_WINDOWS_NTFS, + wxZIP_SYSTEM_MVS, + wxZIP_SYSTEM_VSE, + wxZIP_SYSTEM_ACORN_RISC, + wxZIP_SYSTEM_VFAT, + wxZIP_SYSTEM_ALTERNATE_MVS, + wxZIP_SYSTEM_BEOS, + wxZIP_SYSTEM_TANDEM, + wxZIP_SYSTEM_OS_400 +}; + +// Dos/Win file attributes +// +enum wxZipAttributes +{ + wxZIP_A_RDONLY = 0x01, + wxZIP_A_HIDDEN = 0x02, + wxZIP_A_SYSTEM = 0x04, + wxZIP_A_SUBDIR = 0x10, + wxZIP_A_ARCH = 0x20, + + wxZIP_A_MASK = 0x37 +}; + +// Values for the flags field in the zip headers +// +enum wxZipFlags +{ + wxZIP_ENCRYPTED = 0x0001, + wxZIP_DEFLATE_NORMAL = 0x0000, // normal compression + wxZIP_DEFLATE_EXTRA = 0x0002, // extra compression + wxZIP_DEFLATE_FAST = 0x0004, // fast compression + wxZIP_DEFLATE_SUPERFAST = 0x0006, // superfast compression + wxZIP_DEFLATE_MASK = 0x0006, + wxZIP_SUMS_FOLLOW = 0x0008, // crc and sizes come after the data + wxZIP_ENHANCED = 0x0010, + wxZIP_PATCH = 0x0020, + wxZIP_STRONG_ENC = 0x0040, + wxZIP_UNUSED = 0x0F80, + wxZIP_RESERVED = 0xF000 +}; + +// Forward decls +// +class WXDLLIMPEXP_BASE wxZipEntry; +class WXDLLIMPEXP_BASE wxZipInputStream; + + +///////////////////////////////////////////////////////////////////////////// +// wxZipNotifier + +class WXDLLIMPEXP_BASE wxZipNotifier +{ +public: + virtual ~wxZipNotifier() { } + + virtual void OnEntryUpdated(wxZipEntry& entry) = 0; +}; + + +///////////////////////////////////////////////////////////////////////////// +// Zip Entry - holds the meta data for a file in the zip -class WXDLLIMPEXP_BASE wxZipInputStream : public wxInputStream +class WXDLLIMPEXP_BASE wxZipEntry : public wxArchiveEntry { public: + wxZipEntry(const wxString& name = wxEmptyString, + const wxDateTime& dt = wxDateTime::Now(), + wxFileOffset size = wxInvalidOffset); + virtual ~wxZipEntry(); + + wxZipEntry(const wxZipEntry& entry); + wxZipEntry& operator=(const wxZipEntry& entry); + + // Get accessors + wxDateTime GetDateTime() const { return m_DateTime; } + wxFileOffset GetSize() const { return m_Size; } + wxFileOffset GetOffset() const { return m_Offset; } + wxString GetInternalName() const { return m_Name; } + int GetMethod() const { return m_Method; } + int GetFlags() const { return m_Flags; } + wxUint32 GetCrc() const { return m_Crc; } + wxFileOffset GetCompressedSize() const { return m_CompressedSize; } + int GetSystemMadeBy() const { return m_SystemMadeBy; } + wxString GetComment() const { return m_Comment; } + wxUint32 GetExternalAttributes() const { return m_ExternalAttributes; } + wxPathFormat GetInternalFormat() const { return wxPATH_UNIX; } + int GetMode() const; + const char *GetLocalExtra() const; + size_t GetLocalExtraLen() const; + const char *GetExtra() const; + size_t GetExtraLen() const; + wxString GetName(wxPathFormat format = wxPATH_NATIVE) const; + + // is accessors + inline bool IsDir() const; + inline bool IsText() const; + inline bool IsReadOnly() const; + inline bool IsMadeByUnix() const; + + // set accessors + void SetDateTime(const wxDateTime& dt) { m_DateTime = dt; } + void SetSize(wxFileOffset size) { m_Size = size; } + void SetMethod(int method) { m_Method = (wxUint16)method; } + void SetComment(const wxString& comment) { m_Comment = comment; } + void SetExternalAttributes(wxUint32 attr ) { m_ExternalAttributes = attr; } + void SetSystemMadeBy(int system); + void SetMode(int mode); + void SetExtra(const char *extra, size_t len); + void SetLocalExtra(const char *extra, size_t len); + + inline void SetName(const wxString& name, + wxPathFormat format = wxPATH_NATIVE); + + static wxString GetInternalName(const wxString& name, + wxPathFormat format = wxPATH_NATIVE, + bool *pIsDir = NULL); + + // set is accessors + void SetIsDir(bool isDir = true); + inline void SetIsReadOnly(bool isReadOnly = true); + inline void SetIsText(bool isText = true); + + wxZipEntry *Clone() const { return ZipClone(); } + + void SetNotifier(wxZipNotifier& notifier); + void UnsetNotifier(); + +protected: + // Internal attributes + enum { TEXT_ATTR = 1 }; + + // protected Get accessors + int GetVersionNeeded() const { return m_VersionNeeded; } + wxFileOffset GetKey() const { return m_Key; } + int GetVersionMadeBy() const { return m_VersionMadeBy; } + int GetDiskStart() const { return m_DiskStart; } + int GetInternalAttributes() const { return m_InternalAttributes; } + + void SetVersionNeeded(int version) { m_VersionNeeded = (wxUint16)version; } + void SetOffset(wxFileOffset offset) { m_Offset = offset; } + void SetFlags(int flags) { m_Flags = (wxUint16)flags; } + void SetVersionMadeBy(int version) { m_VersionMadeBy = (wxUint8)version; } + void SetCrc(wxUint32 crc) { m_Crc = crc; } + void SetCompressedSize(wxFileOffset size) { m_CompressedSize = size; } + void SetKey(wxFileOffset offset) { m_Key = offset; } + void SetDiskStart(int start) { m_DiskStart = (wxUint16)start; } + void SetInternalAttributes(int attr) { m_InternalAttributes = (wxUint16)attr; } + + virtual wxZipEntry *ZipClone() const { return new wxZipEntry(*this); } + + void Notify(); + +private: + wxArchiveEntry* DoClone() const { return ZipClone(); } + + size_t ReadLocal(wxInputStream& stream, wxMBConv& conv); + size_t WriteLocal(wxOutputStream& stream, wxMBConv& conv) const; + + size_t ReadCentral(wxInputStream& stream, wxMBConv& conv); + size_t WriteCentral(wxOutputStream& stream, wxMBConv& conv) const; + + size_t ReadDescriptor(wxInputStream& stream); + size_t WriteDescriptor(wxOutputStream& stream, wxUint32 crc, + wxFileOffset compressedSize, wxFileOffset size); + + wxUint8 m_SystemMadeBy; // one of enum wxZipSystem + wxUint8 m_VersionMadeBy; // major * 10 + minor + + wxUint16 m_VersionNeeded; // ver needed to extract (20 i.e. v2.0) + wxUint16 m_Flags; + wxUint16 m_Method; // compression method (one of wxZipMethod) + wxDateTime m_DateTime; + wxUint32 m_Crc; + wxFileOffset m_CompressedSize; + wxFileOffset m_Size; + wxString m_Name; // in internal format + wxFileOffset m_Key; // the original offset for copied entries + wxFileOffset m_Offset; // file offset of the entry + + wxString m_Comment; + wxUint16 m_DiskStart; // for multidisk archives, not unsupported + wxUint16 m_InternalAttributes; // bit 0 set for text files + wxUint32 m_ExternalAttributes; // system specific depends on SystemMadeBy + + class wxZipMemory *m_Extra; + class wxZipMemory *m_LocalExtra; + + wxZipNotifier *m_zipnotifier; + class wxZipWeakLinks *m_backlink; + + friend class wxZipInputStream; + friend class wxZipOutputStream; + + DECLARE_DYNAMIC_CLASS(wxZipEntry) +}; + + +///////////////////////////////////////////////////////////////////////////// +// wxZipOutputStream + +WX_DECLARE_LIST_WITH_DECL(wxZipEntry, _wxZipEntryList, class WXDLLIMPEXP_BASE); + +class WXDLLIMPEXP_BASE wxZipOutputStream : public wxArchiveOutputStream +{ +public: + wxZipOutputStream(wxOutputStream& stream, + int level = -1, + wxMBConv& conv = wxConvLocal); + virtual ~wxZipOutputStream(); + + bool PutNextEntry(wxZipEntry *entry) { return DoCreate(entry); } + + bool PutNextEntry(const wxString& name, + const wxDateTime& dt = wxDateTime::Now(), + wxFileOffset size = wxInvalidOffset); + + bool PutNextDirEntry(const wxString& name, + const wxDateTime& dt = wxDateTime::Now()); + + bool CopyEntry(wxZipEntry *entry, wxZipInputStream& inputStream); + bool CopyArchiveMetaData(wxZipInputStream& inputStream); + + void Sync(); + bool CloseEntry(); + bool Close(); + + void SetComment(const wxString& comment) { m_Comment = comment; } + + int GetLevel() const { return m_level; } + void SetLevel(int level); + +protected: + virtual size_t OnSysWrite(const void *buffer, size_t size); + virtual wxFileOffset OnSysTell() const { return m_entrySize; } + + struct Buffer { const char *m_data; size_t m_size; }; + virtual wxOutputStream *OpenCompressor(wxOutputStream& stream, + wxZipEntry& entry, + const Buffer bufs[]); + virtual bool CloseCompressor(wxOutputStream *comp); + + bool IsParentSeekable() const { return m_offsetAdjustment + != wxInvalidOffset; } + +private: + bool PutNextEntry(wxArchiveEntry *entry); + bool CopyEntry(wxArchiveEntry *entry, wxArchiveInputStream& stream); + bool CopyArchiveMetaData(wxArchiveInputStream& stream); + + bool IsOpened() const { return m_comp || m_pending; } + + bool DoCreate(wxZipEntry *entry, bool raw = false); + void CreatePendingEntry(const void *buffer, size_t size); + void CreatePendingEntry(); + + class wxStoredOutputStream *m_store; + class wxZlibOutputStream2 *m_deflate; + class wxZipStreamLink *m_backlink; + _wxZipEntryList m_entries; + char *m_initialData; + size_t m_initialSize; + wxZipEntry *m_pending; + bool m_raw; + wxFileOffset m_headerOffset; + size_t m_headerSize; + wxFileOffset m_entrySize; + wxUint32 m_crcAccumulator; + wxOutputStream *m_comp; + int m_level; + wxFileOffset m_offsetAdjustment; + wxString m_Comment; + + DECLARE_NO_COPY_CLASS(wxZipOutputStream) +}; + + +///////////////////////////////////////////////////////////////////////////// +// wxZipInputStream + +class WXDLLIMPEXP_BASE wxZipInputStream : public wxArchiveInputStream +{ +public: + typedef wxZipEntry entry_type; + + wxZipInputStream(wxInputStream& stream, wxMBConv& conv = wxConvLocal); wxZipInputStream(const wxString& archive, const wxString& file); - // archive is name of .zip archive, file is name of file to be extracted. - // Remember that archive must be local file accesible via fopen, fread functions! - ~wxZipInputStream(); + virtual ~wxZipInputStream(); + + bool OpenEntry(wxZipEntry& entry) { return DoOpen(&entry); } + bool CloseEntry(); + + wxZipEntry *GetNextEntry(); + + wxString GetComment(); + int GetTotalEntries(); - virtual size_t GetSize() const {return m_Size;} - virtual bool Eof() const; + virtual wxFileOffset GetLength() const { return m_entry.GetSize(); } protected: - virtual size_t OnSysRead(void *buffer, size_t bufsize); - virtual off_t OnSysSeek(off_t seek, wxSeekMode mode); - virtual off_t OnSysTell() const {return m_Pos;} + size_t OnSysRead(void *buffer, size_t size); + wxFileOffset OnSysTell() const { return m_decomp ? m_decomp->TellI() : 0; } + wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode); + + virtual wxInputStream *OpenDecompressor(wxInputStream& stream); + virtual bool CloseDecompressor(wxInputStream *decomp); private: - size_t m_Size; - off_t m_Pos; + void Init(); + wxInputStream& OpenFile(const wxString& archive); + + wxArchiveEntry *DoGetNextEntry() { return GetNextEntry(); } + + bool OpenEntry(wxArchiveEntry& entry); + + wxStreamError ReadLocal(bool readEndRec = false); + wxStreamError ReadCentral(); - // this void* is handle of archive . I'm sorry it is void and not proper - // type but I don't want to make unzip.h header public. - void *m_Archive; + wxUint32 ReadSignature(); + bool FindEndRecord(); + bool LoadEndRecord(); + + bool AtHeader() const { return m_headerSize == 0; } + bool AfterHeader() const { return m_headerSize > 0 && !m_decomp; } + bool IsOpened() const { return m_decomp != NULL; } + + wxZipStreamLink *MakeLink(wxZipOutputStream *out); + + bool DoOpen(wxZipEntry *entry = NULL, bool raw = false); + bool OpenDecompressor(bool raw = false); + + class wxStoredInputStream *m_store; + class wxZlibInputStream2 *m_inflate; + class wxRawInputStream *m_rawin; + class wxFFileInputStream *m_ffile; + wxZipEntry m_entry; + bool m_raw; + size_t m_headerSize; + wxUint32 m_crcAccumulator; + wxInputStream *m_decomp; + bool m_parentSeekable; + class wxZipWeakLinks *m_weaklinks; + class wxZipStreamLink *m_streamlink; + wxFileOffset m_offsetAdjustment; + wxFileOffset m_position; + wxUint32 m_signature; + size_t m_TotalEntries; + wxString m_Comment; + + friend bool wxZipOutputStream::CopyEntry( + wxZipEntry *entry, wxZipInputStream& inputStream); + friend bool wxZipOutputStream::CopyArchiveMetaData( + wxZipInputStream& inputStream); DECLARE_NO_COPY_CLASS(wxZipInputStream) }; -#endif - // wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB +///////////////////////////////////////////////////////////////////////////// +// Iterators + +#if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR +typedef wxArchiveIterator<wxZipInputStream> wxZipIter; +typedef wxArchiveIterator<wxZipInputStream, + std::pair<wxString, wxZipEntry*> > wxZipPairIter; +#endif + + +///////////////////////////////////////////////////////////////////////////// +// wxZipClassFactory + +class WXDLLIMPEXP_BASE wxZipClassFactory : public wxArchiveClassFactory +{ +public: + typedef wxZipEntry entry_type; + typedef wxZipInputStream instream_type; + typedef wxZipOutputStream outstream_type; + typedef wxZipNotifier notifier_type; +#if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR + typedef wxZipIter iter_type; + typedef wxZipPairIter pairiter_type; +#endif + + wxZipEntry *NewEntry() const + { return new wxZipEntry; } + wxZipInputStream *NewStream(wxInputStream& stream) const + { return new wxZipInputStream(stream, GetConv()); } + wxZipOutputStream *NewStream(wxOutputStream& stream) const + { return new wxZipOutputStream(stream, -1, GetConv()); } + + wxString GetInternalName(const wxString& name, + wxPathFormat format = wxPATH_NATIVE) const + { return wxZipEntry::GetInternalName(name, format); } + +protected: + wxArchiveEntry *DoNewEntry() const + { return NewEntry(); } + wxArchiveInputStream *DoNewStream(wxInputStream& stream) const + { return NewStream(stream); } + wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const + { return NewStream(stream); } + +private: + DECLARE_DYNAMIC_CLASS(wxZipClassFactory) +}; + + +///////////////////////////////////////////////////////////////////////////// +// wxZipEntry inlines + +inline bool wxZipEntry::IsText() const +{ + return (m_InternalAttributes & TEXT_ATTR) != 0; +} + +inline bool wxZipEntry::IsDir() const +{ + return (m_ExternalAttributes & wxZIP_A_SUBDIR) != 0; +} + +inline bool wxZipEntry::IsReadOnly() const +{ + return (m_ExternalAttributes & wxZIP_A_RDONLY) != 0; +} + +inline bool wxZipEntry::IsMadeByUnix() const +{ + const int pattern = + (1 << wxZIP_SYSTEM_OPENVMS) | + (1 << wxZIP_SYSTEM_UNIX) | + (1 << wxZIP_SYSTEM_ATARI_ST) | + (1 << wxZIP_SYSTEM_ACORN_RISC) | + (1 << wxZIP_SYSTEM_BEOS) | (1 << wxZIP_SYSTEM_TANDEM); + + // note: some unix zippers put madeby = dos + return (m_SystemMadeBy == wxZIP_SYSTEM_MSDOS + && (m_ExternalAttributes & ~0xFFFF)) + || ((pattern >> m_SystemMadeBy) & 1); +} + +inline void wxZipEntry::SetIsText(bool isText) +{ + if (isText) + m_InternalAttributes |= TEXT_ATTR; + else + m_InternalAttributes &= ~TEXT_ATTR; +} + +inline void wxZipEntry::SetIsReadOnly(bool isReadOnly) +{ + if (isReadOnly) + SetMode(GetMode() & ~0222); + else + SetMode(GetMode() | 0200); +} + +inline void wxZipEntry::SetName(const wxString& name, + wxPathFormat format /*=wxPATH_NATIVE*/) +{ + bool isDir; + m_Name = GetInternalName(name, format, &isDir); + SetIsDir(isDir); +} + + +#endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM -#endif - // __ZIPSTREAM_H__ +#endif // _WX_WXZIPSTREAM_H__