1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Streams for Zip files
4 // Author: Mike Wetherell
6 // Copyright: (c) Mike Wetherell
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #ifndef _WX_WXZIPSTREAM_H__
11 #define _WX_WXZIPSTREAM_H__
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma interface "zipstrm.h"
19 #if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
21 #include "wx/archive.h"
22 #include "wx/hashmap.h"
23 #include "wx/filename.h"
26 /////////////////////////////////////////////////////////////////////////////
29 // Compression Method, only 0 (store) and 8 (deflate) are supported here
40 wxZIP_METHOD_TOKENIZE
,
42 wxZIP_METHOD_DEFLATE64
,
43 wxZIP_METHOD_BZIP2
= 12,
44 wxZIP_METHOD_DEFAULT
= 0xffff
47 // Originating File-System.
49 // These are Pkware's values. Note that Info-zip disagree on some of them,
59 wxZIP_SYSTEM_ATARI_ST
,
60 wxZIP_SYSTEM_OS2_HPFS
,
61 wxZIP_SYSTEM_MACINTOSH
,
62 wxZIP_SYSTEM_Z_SYSTEM
,
64 wxZIP_SYSTEM_WINDOWS_NTFS
,
67 wxZIP_SYSTEM_ACORN_RISC
,
69 wxZIP_SYSTEM_ALTERNATE_MVS
,
75 // Dos/Win file attributes
79 wxZIP_A_RDONLY
= 0x01,
80 wxZIP_A_HIDDEN
= 0x02,
81 wxZIP_A_SYSTEM
= 0x04,
82 wxZIP_A_SUBDIR
= 0x10,
88 // Values for the flags field in the zip headers
92 wxZIP_ENCRYPTED
= 0x0001,
93 wxZIP_DEFLATE_NORMAL
= 0x0000, // normal compression
94 wxZIP_DEFLATE_EXTRA
= 0x0002, // extra compression
95 wxZIP_DEFLATE_FAST
= 0x0004, // fast compression
96 wxZIP_DEFLATE_SUPERFAST
= 0x0006, // superfast compression
97 wxZIP_DEFLATE_MASK
= 0x0006,
98 wxZIP_SUMS_FOLLOW
= 0x0008, // crc and sizes come after the data
99 wxZIP_ENHANCED
= 0x0010,
100 wxZIP_PATCH
= 0x0020,
101 wxZIP_STRONG_ENC
= 0x0040,
102 wxZIP_UNUSED
= 0x0F80,
103 wxZIP_RESERVED
= 0xF000
108 class WXDLLIMPEXP_BASE wxZipEntry
;
109 class WXDLLIMPEXP_BASE wxZipInputStream
;
112 /////////////////////////////////////////////////////////////////////////////
115 class WXDLLIMPEXP_BASE wxZipNotifier
118 virtual ~wxZipNotifier() { }
120 virtual void OnEntryUpdated(wxZipEntry
& entry
) = 0;
124 /////////////////////////////////////////////////////////////////////////////
125 // Zip Entry - holds the meta data for a file in the zip
127 class WXDLLIMPEXP_BASE wxZipEntry
: public wxArchiveEntry
130 wxZipEntry(const wxString
& name
= wxEmptyString
,
131 const wxDateTime
& dt
= wxDateTime::Now(),
132 wxFileOffset size
= wxInvalidOffset
);
133 virtual ~wxZipEntry();
135 wxZipEntry(const wxZipEntry
& entry
);
136 wxZipEntry
& operator=(const wxZipEntry
& entry
);
139 wxDateTime
GetDateTime() const { return m_DateTime
; }
140 wxFileOffset
GetSize() const { return m_Size
; }
141 wxFileOffset
GetOffset() const { return m_Offset
; }
142 wxString
GetInternalName() const { return m_Name
; }
143 int GetMethod() const { return m_Method
; }
144 int GetFlags() const { return m_Flags
; }
145 wxUint32
GetCrc() const { return m_Crc
; }
146 wxFileOffset
GetCompressedSize() const { return m_CompressedSize
; }
147 int GetSystemMadeBy() const { return m_SystemMadeBy
; }
148 wxString
GetComment() const { return m_Comment
; }
149 wxUint32
GetExternalAttributes() const { return m_ExternalAttributes
; }
150 wxPathFormat
GetInternalFormat() const { return wxPATH_UNIX
; }
152 const char *GetLocalExtra() const;
153 size_t GetLocalExtraLen() const;
154 const char *GetExtra() const;
155 size_t GetExtraLen() const;
156 wxString
GetName(wxPathFormat format
= wxPATH_NATIVE
) const;
159 inline bool IsDir() const;
160 inline bool IsText() const;
161 inline bool IsReadOnly() const;
162 inline bool IsMadeByUnix() const;
165 void SetDateTime(const wxDateTime
& dt
) { m_DateTime
= dt
; }
166 void SetSize(wxFileOffset size
) { m_Size
= size
; }
167 void SetMethod(int method
) { m_Method
= (wxUint16
)method
; }
168 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
169 void SetExternalAttributes(wxUint32 attr
) { m_ExternalAttributes
= attr
; }
170 void SetSystemMadeBy(int system
);
171 void SetMode(int mode
);
172 void SetExtra(const char *extra
, size_t len
);
173 void SetLocalExtra(const char *extra
, size_t len
);
175 inline void SetName(const wxString
& name
,
176 wxPathFormat format
= wxPATH_NATIVE
);
178 static wxString
GetInternalName(const wxString
& name
,
179 wxPathFormat format
= wxPATH_NATIVE
,
180 bool *pIsDir
= NULL
);
183 void SetIsDir(bool isDir
= true);
184 inline void SetIsReadOnly(bool isReadOnly
= true);
185 inline void SetIsText(bool isText
= true);
187 wxZipEntry
*Clone() const { return ZipClone(); }
189 void SetNotifier(wxZipNotifier
& notifier
);
190 void UnsetNotifier();
193 // Internal attributes
194 enum { TEXT_ATTR
= 1 };
196 // protected Get accessors
197 int GetVersionNeeded() const { return m_VersionNeeded
; }
198 wxFileOffset
GetKey() const { return m_Key
; }
199 int GetVersionMadeBy() const { return m_VersionMadeBy
; }
200 int GetDiskStart() const { return m_DiskStart
; }
201 int GetInternalAttributes() const { return m_InternalAttributes
; }
203 void SetVersionNeeded(int version
) { m_VersionNeeded
= (wxUint16
)version
; }
204 void SetOffset(wxFileOffset offset
) { m_Offset
= offset
; }
205 void SetFlags(int flags
) { m_Flags
= (wxUint16
)flags
; }
206 void SetVersionMadeBy(int version
) { m_VersionMadeBy
= (wxUint8
)version
; }
207 void SetCrc(wxUint32 crc
) { m_Crc
= crc
; }
208 void SetCompressedSize(wxFileOffset size
) { m_CompressedSize
= size
; }
209 void SetKey(wxFileOffset offset
) { m_Key
= offset
; }
210 void SetDiskStart(int start
) { m_DiskStart
= (wxUint16
)start
; }
211 void SetInternalAttributes(int attr
) { m_InternalAttributes
= (wxUint16
)attr
; }
213 virtual wxZipEntry
*ZipClone() const { return new wxZipEntry(*this); }
218 wxArchiveEntry
* DoClone() const { return ZipClone(); }
220 size_t ReadLocal(wxInputStream
& stream
, wxMBConv
& conv
);
221 size_t WriteLocal(wxOutputStream
& stream
, wxMBConv
& conv
) const;
223 size_t ReadCentral(wxInputStream
& stream
, wxMBConv
& conv
);
224 size_t WriteCentral(wxOutputStream
& stream
, wxMBConv
& conv
) const;
226 size_t ReadDescriptor(wxInputStream
& stream
);
227 size_t WriteDescriptor(wxOutputStream
& stream
, wxUint32 crc
,
228 wxFileOffset compressedSize
, wxFileOffset size
);
230 wxUint8 m_SystemMadeBy
; // one of enum wxZipSystem
231 wxUint8 m_VersionMadeBy
; // major * 10 + minor
233 wxUint16 m_VersionNeeded
; // ver needed to extract (20 i.e. v2.0)
235 wxUint16 m_Method
; // compression method (one of wxZipMethod)
236 wxDateTime m_DateTime
;
238 wxFileOffset m_CompressedSize
;
240 wxString m_Name
; // in internal format
241 wxFileOffset m_Key
; // the original offset for copied entries
242 wxFileOffset m_Offset
; // file offset of the entry
245 wxUint16 m_DiskStart
; // for multidisk archives, not unsupported
246 wxUint16 m_InternalAttributes
; // bit 0 set for text files
247 wxUint32 m_ExternalAttributes
; // system specific depends on SystemMadeBy
249 class wxZipMemory
*m_Extra
;
250 class wxZipMemory
*m_LocalExtra
;
252 wxZipNotifier
*m_zipnotifier
;
253 class wxZipWeakLinks
*m_backlink
;
255 friend class wxZipInputStream
;
256 friend class wxZipOutputStream
;
258 DECLARE_DYNAMIC_CLASS(wxZipEntry
)
262 /////////////////////////////////////////////////////////////////////////////
265 WX_DECLARE_LIST_WITH_DECL(wxZipEntry
, _wxZipEntryList
, class WXDLLIMPEXP_BASE
);
267 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
270 wxZipOutputStream(wxOutputStream
& stream
,
272 wxMBConv
& conv
= wxConvLocal
);
273 virtual ~wxZipOutputStream();
275 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
277 bool PutNextEntry(const wxString
& name
,
278 const wxDateTime
& dt
= wxDateTime::Now(),
279 wxFileOffset size
= wxInvalidOffset
);
281 bool PutNextDirEntry(const wxString
& name
,
282 const wxDateTime
& dt
= wxDateTime::Now());
284 bool CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
285 bool CopyArchiveMetaData(wxZipInputStream
& inputStream
);
291 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
293 int GetLevel() const { return m_level
; }
294 void SetLevel(int level
);
297 virtual size_t OnSysWrite(const void *buffer
, size_t size
);
298 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
300 struct Buffer
{ const char *m_data
; size_t m_size
; };
301 virtual wxOutputStream
*OpenCompressor(wxOutputStream
& stream
,
303 const Buffer bufs
[]);
304 virtual bool CloseCompressor(wxOutputStream
*comp
);
306 bool IsParentSeekable() const { return m_offsetAdjustment
307 != wxInvalidOffset
; }
310 bool PutNextEntry(wxArchiveEntry
*entry
);
311 bool CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
312 bool CopyArchiveMetaData(wxArchiveInputStream
& stream
);
314 bool IsOpened() const { return m_comp
|| m_pending
; }
316 bool DoCreate(wxZipEntry
*entry
, bool raw
= false);
317 void CreatePendingEntry(const void *buffer
, size_t size
);
318 void CreatePendingEntry();
320 class wxStoredOutputStream
*m_store
;
321 class wxZlibOutputStream2
*m_deflate
;
322 class wxZipStreamLink
*m_backlink
;
323 _wxZipEntryList m_entries
;
325 size_t m_initialSize
;
326 wxZipEntry
*m_pending
;
328 wxFileOffset m_headerOffset
;
330 wxFileOffset m_entrySize
;
331 wxUint32 m_crcAccumulator
;
332 wxOutputStream
*m_comp
;
334 wxFileOffset m_offsetAdjustment
;
337 DECLARE_NO_COPY_CLASS(wxZipOutputStream
)
341 /////////////////////////////////////////////////////////////////////////////
344 class WXDLLIMPEXP_BASE wxZipInputStream
: public wxArchiveInputStream
347 typedef wxZipEntry entry_type
;
349 wxZipInputStream(wxInputStream
& stream
, wxMBConv
& conv
= wxConvLocal
);
350 wxZipInputStream(const wxString
& archive
, const wxString
& file
);
351 virtual ~wxZipInputStream();
353 bool OpenEntry(wxZipEntry
& entry
) { return DoOpen(&entry
); }
356 wxZipEntry
*GetNextEntry();
358 wxString
GetComment();
359 int GetTotalEntries();
361 virtual wxFileOffset
GetLength() const { return m_entry
.GetSize(); }
364 size_t OnSysRead(void *buffer
, size_t size
);
365 wxFileOffset
OnSysTell() const { return m_decomp
? m_decomp
->TellI() : 0; }
366 wxFileOffset
OnSysSeek(wxFileOffset seek
, wxSeekMode mode
);
368 virtual wxInputStream
*OpenDecompressor(wxInputStream
& stream
);
369 virtual bool CloseDecompressor(wxInputStream
*decomp
);
373 wxInputStream
& OpenFile(const wxString
& archive
);
375 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
377 bool OpenEntry(wxArchiveEntry
& entry
);
379 wxStreamError
ReadLocal(bool readEndRec
= false);
380 wxStreamError
ReadCentral();
382 wxUint32
ReadSignature();
383 bool FindEndRecord();
384 bool LoadEndRecord();
386 bool AtHeader() const { return m_headerSize
== 0; }
387 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
388 bool IsOpened() const { return m_decomp
!= NULL
; }
390 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
392 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
393 bool OpenDecompressor(bool raw
= false);
395 class wxStoredInputStream
*m_store
;
396 class wxZlibInputStream2
*m_inflate
;
397 class wxRawInputStream
*m_rawin
;
398 class wxFFileInputStream
*m_ffile
;
402 wxUint32 m_crcAccumulator
;
403 wxInputStream
*m_decomp
;
404 bool m_parentSeekable
;
405 class wxZipWeakLinks
*m_weaklinks
;
406 class wxZipStreamLink
*m_streamlink
;
407 wxFileOffset m_offsetAdjustment
;
408 wxFileOffset m_position
;
409 wxUint32 m_signature
;
410 size_t m_TotalEntries
;
413 friend bool wxZipOutputStream::CopyEntry(
414 wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
415 friend bool wxZipOutputStream::CopyArchiveMetaData(
416 wxZipInputStream
& inputStream
);
418 DECLARE_NO_COPY_CLASS(wxZipInputStream
)
422 /////////////////////////////////////////////////////////////////////////////
425 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
426 typedef wxArchiveIterator
<wxZipInputStream
> wxZipIter
;
427 typedef wxArchiveIterator
<wxZipInputStream
,
428 std::pair
<wxString
, wxZipEntry
*> > wxZipPairIter
;
432 /////////////////////////////////////////////////////////////////////////////
435 class WXDLLIMPEXP_BASE wxZipClassFactory
: public wxArchiveClassFactory
438 typedef wxZipEntry entry_type
;
439 typedef wxZipInputStream instream_type
;
440 typedef wxZipOutputStream outstream_type
;
441 typedef wxZipNotifier notifier_type
;
442 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
443 typedef wxZipIter iter_type
;
444 typedef wxZipPairIter pairiter_type
;
447 wxZipEntry
*NewEntry() const
448 { return new wxZipEntry
; }
449 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
450 { return new wxZipInputStream(stream
, GetConv()); }
451 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
452 { return new wxZipOutputStream(stream
, -1, GetConv()); }
454 wxString
GetInternalName(const wxString
& name
,
455 wxPathFormat format
= wxPATH_NATIVE
) const
456 { return wxZipEntry::GetInternalName(name
, format
); }
459 wxArchiveEntry
*DoNewEntry() const
460 { return NewEntry(); }
461 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
462 { return NewStream(stream
); }
463 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
464 { return NewStream(stream
); }
467 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
471 /////////////////////////////////////////////////////////////////////////////
472 // wxZipEntry inlines
474 inline bool wxZipEntry::IsText() const
476 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
479 inline bool wxZipEntry::IsDir() const
481 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
484 inline bool wxZipEntry::IsReadOnly() const
486 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
489 inline bool wxZipEntry::IsMadeByUnix() const
492 (1 << wxZIP_SYSTEM_OPENVMS
) |
493 (1 << wxZIP_SYSTEM_UNIX
) |
494 (1 << wxZIP_SYSTEM_ATARI_ST
) |
495 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
496 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
498 // note: some unix zippers put madeby = dos
499 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
500 && (m_ExternalAttributes
& ~0xFFFF))
501 || ((pattern
>> m_SystemMadeBy
) & 1);
504 inline void wxZipEntry::SetIsText(bool isText
)
507 m_InternalAttributes
|= TEXT_ATTR
;
509 m_InternalAttributes
&= ~TEXT_ATTR
;
512 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
515 SetMode(GetMode() & ~0222);
517 SetMode(GetMode() | 0200);
520 inline void wxZipEntry::SetName(const wxString
& name
,
521 wxPathFormat format
/*=wxPATH_NATIVE*/)
524 m_Name
= GetInternalName(name
, format
, &isDir
);
529 #endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
531 #endif // _WX_WXZIPSTREAM_H__