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"
25 // some methods from wxZipInputStream and wxZipOutputStream stream do not get
26 // exported/imported when compiled with Mingw versions before 3.4.2. So they
27 // are imported/exported individually as a workaround
28 #if (defined(__GNUWIN32__) || defined(__MINGW32__)) \
29 && (!defined __GNUC__ \
30 || !defined __GNUC_MINOR__ \
31 || !defined __GNUC_PATCHLEVEL__ \
32 || __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 30402)
33 #define WXZIPFIX WXDLLIMPEXP_BASE
38 /////////////////////////////////////////////////////////////////////////////
41 // Compression Method, only 0 (store) and 8 (deflate) are supported here
52 wxZIP_METHOD_TOKENIZE
,
54 wxZIP_METHOD_DEFLATE64
,
55 wxZIP_METHOD_BZIP2
= 12,
56 wxZIP_METHOD_DEFAULT
= 0xffff
59 // Originating File-System.
61 // These are Pkware's values. Note that Info-zip disagree on some of them,
71 wxZIP_SYSTEM_ATARI_ST
,
72 wxZIP_SYSTEM_OS2_HPFS
,
73 wxZIP_SYSTEM_MACINTOSH
,
74 wxZIP_SYSTEM_Z_SYSTEM
,
76 wxZIP_SYSTEM_WINDOWS_NTFS
,
79 wxZIP_SYSTEM_ACORN_RISC
,
81 wxZIP_SYSTEM_ALTERNATE_MVS
,
87 // Dos/Win file attributes
91 wxZIP_A_RDONLY
= 0x01,
92 wxZIP_A_HIDDEN
= 0x02,
93 wxZIP_A_SYSTEM
= 0x04,
94 wxZIP_A_SUBDIR
= 0x10,
100 // Values for the flags field in the zip headers
104 wxZIP_ENCRYPTED
= 0x0001,
105 wxZIP_DEFLATE_NORMAL
= 0x0000, // normal compression
106 wxZIP_DEFLATE_EXTRA
= 0x0002, // extra compression
107 wxZIP_DEFLATE_FAST
= 0x0004, // fast compression
108 wxZIP_DEFLATE_SUPERFAST
= 0x0006, // superfast compression
109 wxZIP_DEFLATE_MASK
= 0x0006,
110 wxZIP_SUMS_FOLLOW
= 0x0008, // crc and sizes come after the data
111 wxZIP_ENHANCED
= 0x0010,
112 wxZIP_PATCH
= 0x0020,
113 wxZIP_STRONG_ENC
= 0x0040,
114 wxZIP_UNUSED
= 0x0F80,
115 wxZIP_RESERVED
= 0xF000
120 class WXDLLIMPEXP_BASE wxZipEntry
;
121 class WXDLLIMPEXP_BASE wxZipInputStream
;
124 /////////////////////////////////////////////////////////////////////////////
127 class WXDLLIMPEXP_BASE wxZipNotifier
130 virtual ~wxZipNotifier() { }
132 virtual void OnEntryUpdated(wxZipEntry
& entry
) = 0;
136 /////////////////////////////////////////////////////////////////////////////
137 // Zip Entry - holds the meta data for a file in the zip
139 class WXDLLIMPEXP_BASE wxZipEntry
: public wxArchiveEntry
142 wxZipEntry(const wxString
& name
= wxEmptyString
,
143 const wxDateTime
& dt
= wxDateTime::Now(),
144 wxFileOffset size
= wxInvalidOffset
);
145 virtual ~wxZipEntry();
147 wxZipEntry(const wxZipEntry
& entry
);
148 wxZipEntry
& operator=(const wxZipEntry
& entry
);
151 wxDateTime
GetDateTime() const { return m_DateTime
; }
152 wxFileOffset
GetSize() const { return m_Size
; }
153 wxFileOffset
GetOffset() const { return m_Offset
; }
154 wxString
GetInternalName() const { return m_Name
; }
155 int GetMethod() const { return m_Method
; }
156 int GetFlags() const { return m_Flags
; }
157 wxUint32
GetCrc() const { return m_Crc
; }
158 wxFileOffset
GetCompressedSize() const { return m_CompressedSize
; }
159 int GetSystemMadeBy() const { return m_SystemMadeBy
; }
160 wxString
GetComment() const { return m_Comment
; }
161 wxUint32
GetExternalAttributes() const { return m_ExternalAttributes
; }
162 wxPathFormat
GetInternalFormat() const { return wxPATH_UNIX
; }
164 const char *GetLocalExtra() const;
165 size_t GetLocalExtraLen() const;
166 const char *GetExtra() const;
167 size_t GetExtraLen() const;
168 wxString
GetName(wxPathFormat format
= wxPATH_NATIVE
) const;
171 inline bool IsDir() const;
172 inline bool IsText() const;
173 inline bool IsReadOnly() const;
174 inline bool IsMadeByUnix() const;
177 void SetDateTime(const wxDateTime
& dt
) { m_DateTime
= dt
; }
178 void SetSize(wxFileOffset size
) { m_Size
= size
; }
179 void SetMethod(int method
) { m_Method
= (wxUint16
)method
; }
180 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
181 void SetExternalAttributes(wxUint32 attr
) { m_ExternalAttributes
= attr
; }
182 void SetSystemMadeBy(int system
);
183 void SetMode(int mode
);
184 void SetExtra(const char *extra
, size_t len
);
185 void SetLocalExtra(const char *extra
, size_t len
);
187 inline void SetName(const wxString
& name
,
188 wxPathFormat format
= wxPATH_NATIVE
);
190 static wxString
GetInternalName(const wxString
& name
,
191 wxPathFormat format
= wxPATH_NATIVE
,
192 bool *pIsDir
= NULL
);
195 void SetIsDir(bool isDir
= true);
196 inline void SetIsReadOnly(bool isReadOnly
= true);
197 inline void SetIsText(bool isText
= true);
199 wxZipEntry
*Clone() const { return ZipClone(); }
201 void SetNotifier(wxZipNotifier
& notifier
);
202 void UnsetNotifier();
205 // Internal attributes
206 enum { TEXT_ATTR
= 1 };
208 // protected Get accessors
209 int GetVersionNeeded() const { return m_VersionNeeded
; }
210 wxFileOffset
GetKey() const { return m_Key
; }
211 int GetVersionMadeBy() const { return m_VersionMadeBy
; }
212 int GetDiskStart() const { return m_DiskStart
; }
213 int GetInternalAttributes() const { return m_InternalAttributes
; }
215 void SetVersionNeeded(int version
) { m_VersionNeeded
= (wxUint16
)version
; }
216 void SetOffset(wxFileOffset offset
) { m_Offset
= offset
; }
217 void SetFlags(int flags
) { m_Flags
= (wxUint16
)flags
; }
218 void SetVersionMadeBy(int version
) { m_VersionMadeBy
= (wxUint8
)version
; }
219 void SetCrc(wxUint32 crc
) { m_Crc
= crc
; }
220 void SetCompressedSize(wxFileOffset size
) { m_CompressedSize
= size
; }
221 void SetKey(wxFileOffset offset
) { m_Key
= offset
; }
222 void SetDiskStart(int start
) { m_DiskStart
= (wxUint16
)start
; }
223 void SetInternalAttributes(int attr
) { m_InternalAttributes
= (wxUint16
)attr
; }
225 virtual wxZipEntry
*ZipClone() const { return new wxZipEntry(*this); }
230 wxArchiveEntry
* DoClone() const { return ZipClone(); }
232 size_t ReadLocal(wxInputStream
& stream
, wxMBConv
& conv
);
233 size_t WriteLocal(wxOutputStream
& stream
, wxMBConv
& conv
) const;
235 size_t ReadCentral(wxInputStream
& stream
, wxMBConv
& conv
);
236 size_t WriteCentral(wxOutputStream
& stream
, wxMBConv
& conv
) const;
238 size_t ReadDescriptor(wxInputStream
& stream
);
239 size_t WriteDescriptor(wxOutputStream
& stream
, wxUint32 crc
,
240 wxFileOffset compressedSize
, wxFileOffset size
);
242 wxUint8 m_SystemMadeBy
; // one of enum wxZipSystem
243 wxUint8 m_VersionMadeBy
; // major * 10 + minor
245 wxUint16 m_VersionNeeded
; // ver needed to extract (20 i.e. v2.0)
247 wxUint16 m_Method
; // compression method (one of wxZipMethod)
248 wxDateTime m_DateTime
;
250 wxFileOffset m_CompressedSize
;
252 wxString m_Name
; // in internal format
253 wxFileOffset m_Key
; // the original offset for copied entries
254 wxFileOffset m_Offset
; // file offset of the entry
257 wxUint16 m_DiskStart
; // for multidisk archives, not unsupported
258 wxUint16 m_InternalAttributes
; // bit 0 set for text files
259 wxUint32 m_ExternalAttributes
; // system specific depends on SystemMadeBy
261 class wxZipMemory
*m_Extra
;
262 class wxZipMemory
*m_LocalExtra
;
264 wxZipNotifier
*m_zipnotifier
;
265 class wxZipWeakLinks
*m_backlink
;
267 friend class wxZipInputStream
;
268 friend class wxZipOutputStream
;
270 DECLARE_DYNAMIC_CLASS(wxZipEntry
)
274 /////////////////////////////////////////////////////////////////////////////
277 WX_DECLARE_LIST_WITH_DECL(wxZipEntry
, wx__ZipEntryList
, class WXDLLIMPEXP_BASE
);
279 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
282 wxZipOutputStream(wxOutputStream
& stream
,
284 wxMBConv
& conv
= wxConvLocal
);
285 virtual WXZIPFIX
~wxZipOutputStream();
287 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
289 bool WXZIPFIX
PutNextEntry(const wxString
& name
,
290 const wxDateTime
& dt
= wxDateTime::Now(),
291 wxFileOffset size
= wxInvalidOffset
);
293 bool WXZIPFIX
PutNextDirEntry(const wxString
& name
,
294 const wxDateTime
& dt
= wxDateTime::Now());
296 bool WXZIPFIX
CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
297 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
299 void WXZIPFIX
Sync();
300 bool WXZIPFIX
CloseEntry();
301 bool WXZIPFIX
Close();
303 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
305 int GetLevel() const { return m_level
; }
306 void WXZIPFIX
SetLevel(int level
);
309 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
310 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
312 // this protected interface isn't yet finalised
313 struct Buffer
{ const char *m_data
; size_t m_size
; };
314 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
316 const Buffer bufs
[]);
317 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
319 bool IsParentSeekable() const
320 { return m_offsetAdjustment
!= wxInvalidOffset
; }
323 bool WXZIPFIX
PutNextEntry(wxArchiveEntry
*entry
);
324 bool WXZIPFIX
CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
325 bool WXZIPFIX
CopyArchiveMetaData(wxArchiveInputStream
& stream
);
327 bool IsOpened() const { return m_comp
|| m_pending
; }
329 bool DoCreate(wxZipEntry
*entry
, bool raw
= false);
330 void CreatePendingEntry(const void *buffer
, size_t size
);
331 void CreatePendingEntry();
333 class wxStoredOutputStream
*m_store
;
334 class wxZlibOutputStream2
*m_deflate
;
335 class wxZipStreamLink
*m_backlink
;
336 wx__ZipEntryList m_entries
;
338 size_t m_initialSize
;
339 wxZipEntry
*m_pending
;
341 wxFileOffset m_headerOffset
;
343 wxFileOffset m_entrySize
;
344 wxUint32 m_crcAccumulator
;
345 wxOutputStream
*m_comp
;
347 wxFileOffset m_offsetAdjustment
;
350 DECLARE_NO_COPY_CLASS(wxZipOutputStream
)
354 /////////////////////////////////////////////////////////////////////////////
357 class WXDLLIMPEXP_BASE wxZipInputStream
: public wxArchiveInputStream
360 typedef wxZipEntry entry_type
;
362 wxZipInputStream(wxInputStream
& stream
, wxMBConv
& conv
= wxConvLocal
);
364 #if 1 //WXWIN_COMPATIBILITY_2_6
365 wxZipInputStream(const wxString
& archive
, const wxString
& file
)
366 : wxArchiveInputStream(OpenFile(archive
), wxConvLocal
) { Init(file
); }
369 virtual WXZIPFIX
~wxZipInputStream();
371 bool OpenEntry(wxZipEntry
& entry
) { return DoOpen(&entry
); }
372 bool WXZIPFIX
CloseEntry();
374 wxZipEntry
*GetNextEntry();
376 wxString WXZIPFIX
GetComment();
377 int WXZIPFIX
GetTotalEntries();
379 virtual wxFileOffset
GetLength() const { return m_entry
.GetSize(); }
382 size_t WXZIPFIX
OnSysRead(void *buffer
, size_t size
);
383 wxFileOffset
OnSysTell() const { return m_decomp
? m_decomp
->TellI() : 0; }
385 #if 1 //WXWIN_COMPATIBILITY_2_6
386 wxFileOffset WXZIPFIX
OnSysSeek(wxFileOffset seek
, wxSeekMode mode
);
389 // this protected interface isn't yet finalised
390 virtual wxInputStream
* WXZIPFIX
OpenDecompressor(wxInputStream
& stream
);
391 virtual bool WXZIPFIX
CloseDecompressor(wxInputStream
*decomp
);
395 void Init(const wxString
& file
);
396 wxInputStream
& OpenFile(const wxString
& archive
);
398 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
400 bool WXZIPFIX
OpenEntry(wxArchiveEntry
& entry
);
402 wxStreamError
ReadLocal(bool readEndRec
= false);
403 wxStreamError
ReadCentral();
405 wxUint32
ReadSignature();
406 bool FindEndRecord();
407 bool LoadEndRecord();
409 bool AtHeader() const { return m_headerSize
== 0; }
410 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
411 bool IsOpened() const { return m_decomp
!= NULL
; }
413 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
415 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
416 bool OpenDecompressor(bool raw
= false);
418 class wxStoredInputStream
*m_store
;
419 class wxZlibInputStream2
*m_inflate
;
420 class wxRawInputStream
*m_rawin
;
421 class wxFFileInputStream
*m_ffile
;
425 wxUint32 m_crcAccumulator
;
426 wxInputStream
*m_decomp
;
427 bool m_parentSeekable
;
428 class wxZipWeakLinks
*m_weaklinks
;
429 class wxZipStreamLink
*m_streamlink
;
430 wxFileOffset m_offsetAdjustment
;
431 wxFileOffset m_position
;
432 wxUint32 m_signature
;
433 size_t m_TotalEntries
;
436 friend bool wxZipOutputStream::CopyEntry(
437 wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
438 friend bool wxZipOutputStream::CopyArchiveMetaData(
439 wxZipInputStream
& inputStream
);
441 #if 1 //WXWIN_COMPATIBILITY_2_6
443 friend class wxZipFSInputStream
;
446 DECLARE_NO_COPY_CLASS(wxZipInputStream
)
450 /////////////////////////////////////////////////////////////////////////////
453 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
454 typedef wxArchiveIterator
<wxZipInputStream
> wxZipIter
;
455 typedef wxArchiveIterator
<wxZipInputStream
,
456 std::pair
<wxString
, wxZipEntry
*> > wxZipPairIter
;
460 /////////////////////////////////////////////////////////////////////////////
463 class WXDLLIMPEXP_BASE wxZipClassFactory
: public wxArchiveClassFactory
466 typedef wxZipEntry entry_type
;
467 typedef wxZipInputStream instream_type
;
468 typedef wxZipOutputStream outstream_type
;
469 typedef wxZipNotifier notifier_type
;
470 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
471 typedef wxZipIter iter_type
;
472 typedef wxZipPairIter pairiter_type
;
475 wxZipEntry
*NewEntry() const
476 { return new wxZipEntry
; }
477 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
478 { return new wxZipInputStream(stream
, GetConv()); }
479 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
480 { return new wxZipOutputStream(stream
, -1, GetConv()); }
482 wxString
GetInternalName(const wxString
& name
,
483 wxPathFormat format
= wxPATH_NATIVE
) const
484 { return wxZipEntry::GetInternalName(name
, format
); }
487 wxArchiveEntry
*DoNewEntry() const
488 { return NewEntry(); }
489 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
490 { return NewStream(stream
); }
491 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
492 { return NewStream(stream
); }
495 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
499 /////////////////////////////////////////////////////////////////////////////
500 // wxZipEntry inlines
502 inline bool wxZipEntry::IsText() const
504 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
507 inline bool wxZipEntry::IsDir() const
509 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
512 inline bool wxZipEntry::IsReadOnly() const
514 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
517 inline bool wxZipEntry::IsMadeByUnix() const
520 (1 << wxZIP_SYSTEM_OPENVMS
) |
521 (1 << wxZIP_SYSTEM_UNIX
) |
522 (1 << wxZIP_SYSTEM_ATARI_ST
) |
523 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
524 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
526 // note: some unix zippers put madeby = dos
527 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
528 && (m_ExternalAttributes
& ~0xFFFF))
529 || ((pattern
>> m_SystemMadeBy
) & 1);
532 inline void wxZipEntry::SetIsText(bool isText
)
535 m_InternalAttributes
|= TEXT_ATTR
;
537 m_InternalAttributes
&= ~TEXT_ATTR
;
540 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
543 SetMode(GetMode() & ~0222);
545 SetMode(GetMode() | 0200);
548 inline void wxZipEntry::SetName(const wxString
& name
,
549 wxPathFormat format
/*=wxPATH_NATIVE*/)
552 m_Name
= GetInternalName(name
, format
, &isDir
);
557 #endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
559 #endif // _WX_WXZIPSTREAM_H__