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__
15 #if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
17 #include "wx/archive.h"
18 #include "wx/hashmap.h"
19 #include "wx/filename.h"
21 // some methods from wxZipInputStream and wxZipOutputStream stream do not get
22 // exported/imported when compiled with Mingw versions before 3.4.2. So they
23 // are imported/exported individually as a workaround
24 #if (defined(__GNUWIN32__) || defined(__MINGW32__)) \
25 && (!defined __GNUC__ \
26 || !defined __GNUC_MINOR__ \
27 || !defined __GNUC_PATCHLEVEL__ \
28 || __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 30402)
29 #define WXZIPFIX WXDLLIMPEXP_BASE
34 /////////////////////////////////////////////////////////////////////////////
37 // Compression Method, only 0 (store) and 8 (deflate) are supported here
48 wxZIP_METHOD_TOKENIZE
,
50 wxZIP_METHOD_DEFLATE64
,
51 wxZIP_METHOD_BZIP2
= 12,
52 wxZIP_METHOD_DEFAULT
= 0xffff
55 // Originating File-System.
57 // These are Pkware's values. Note that Info-zip disagree on some of them,
67 wxZIP_SYSTEM_ATARI_ST
,
68 wxZIP_SYSTEM_OS2_HPFS
,
69 wxZIP_SYSTEM_MACINTOSH
,
70 wxZIP_SYSTEM_Z_SYSTEM
,
72 wxZIP_SYSTEM_WINDOWS_NTFS
,
75 wxZIP_SYSTEM_ACORN_RISC
,
77 wxZIP_SYSTEM_ALTERNATE_MVS
,
83 // Dos/Win file attributes
87 wxZIP_A_RDONLY
= 0x01,
88 wxZIP_A_HIDDEN
= 0x02,
89 wxZIP_A_SYSTEM
= 0x04,
90 wxZIP_A_SUBDIR
= 0x10,
96 // Values for the flags field in the zip headers
100 wxZIP_ENCRYPTED
= 0x0001,
101 wxZIP_DEFLATE_NORMAL
= 0x0000, // normal compression
102 wxZIP_DEFLATE_EXTRA
= 0x0002, // extra compression
103 wxZIP_DEFLATE_FAST
= 0x0004, // fast compression
104 wxZIP_DEFLATE_SUPERFAST
= 0x0006, // superfast compression
105 wxZIP_DEFLATE_MASK
= 0x0006,
106 wxZIP_SUMS_FOLLOW
= 0x0008, // crc and sizes come after the data
107 wxZIP_ENHANCED
= 0x0010,
108 wxZIP_PATCH
= 0x0020,
109 wxZIP_STRONG_ENC
= 0x0040,
110 wxZIP_UNUSED
= 0x0F80,
111 wxZIP_RESERVED
= 0xF000
116 class WXDLLIMPEXP_BASE wxZipEntry
;
117 class WXDLLIMPEXP_BASE wxZipInputStream
;
120 /////////////////////////////////////////////////////////////////////////////
123 class WXDLLIMPEXP_BASE wxZipNotifier
126 virtual ~wxZipNotifier() { }
128 virtual void OnEntryUpdated(wxZipEntry
& entry
) = 0;
132 /////////////////////////////////////////////////////////////////////////////
133 // Zip Entry - holds the meta data for a file in the zip
135 class WXDLLIMPEXP_BASE wxZipEntry
: public wxArchiveEntry
138 wxZipEntry(const wxString
& name
= wxEmptyString
,
139 const wxDateTime
& dt
= wxDateTime::Now(),
140 wxFileOffset size
= wxInvalidOffset
);
141 virtual ~wxZipEntry();
143 wxZipEntry(const wxZipEntry
& entry
);
144 wxZipEntry
& operator=(const wxZipEntry
& entry
);
147 wxDateTime
GetDateTime() const { return m_DateTime
; }
148 wxFileOffset
GetSize() const { return m_Size
; }
149 wxFileOffset
GetOffset() const { return m_Offset
; }
150 wxString
GetInternalName() const { return m_Name
; }
151 int GetMethod() const { return m_Method
; }
152 int GetFlags() const { return m_Flags
; }
153 wxUint32
GetCrc() const { return m_Crc
; }
154 wxFileOffset
GetCompressedSize() const { return m_CompressedSize
; }
155 int GetSystemMadeBy() const { return m_SystemMadeBy
; }
156 wxString
GetComment() const { return m_Comment
; }
157 wxUint32
GetExternalAttributes() const { return m_ExternalAttributes
; }
158 wxPathFormat
GetInternalFormat() const { return wxPATH_UNIX
; }
160 const char *GetLocalExtra() const;
161 size_t GetLocalExtraLen() const;
162 const char *GetExtra() const;
163 size_t GetExtraLen() const;
164 wxString
GetName(wxPathFormat format
= wxPATH_NATIVE
) const;
167 inline bool IsDir() const;
168 inline bool IsText() const;
169 inline bool IsReadOnly() const;
170 inline bool IsMadeByUnix() const;
173 void SetDateTime(const wxDateTime
& dt
) { m_DateTime
= dt
; }
174 void SetSize(wxFileOffset size
) { m_Size
= size
; }
175 void SetMethod(int method
) { m_Method
= (wxUint16
)method
; }
176 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
177 void SetExternalAttributes(wxUint32 attr
) { m_ExternalAttributes
= attr
; }
178 void SetSystemMadeBy(int system
);
179 void SetMode(int mode
);
180 void SetExtra(const char *extra
, size_t len
);
181 void SetLocalExtra(const char *extra
, size_t len
);
183 inline void SetName(const wxString
& name
,
184 wxPathFormat format
= wxPATH_NATIVE
);
186 static wxString
GetInternalName(const wxString
& name
,
187 wxPathFormat format
= wxPATH_NATIVE
,
188 bool *pIsDir
= NULL
);
191 void SetIsDir(bool isDir
= true);
192 inline void SetIsReadOnly(bool isReadOnly
= true);
193 inline void SetIsText(bool isText
= true);
195 wxZipEntry
*Clone() const { return ZipClone(); }
197 void SetNotifier(wxZipNotifier
& notifier
);
198 void UnsetNotifier();
201 // Internal attributes
202 enum { TEXT_ATTR
= 1 };
204 // protected Get accessors
205 int GetVersionNeeded() const { return m_VersionNeeded
; }
206 wxFileOffset
GetKey() const { return m_Key
; }
207 int GetVersionMadeBy() const { return m_VersionMadeBy
; }
208 int GetDiskStart() const { return m_DiskStart
; }
209 int GetInternalAttributes() const { return m_InternalAttributes
; }
211 void SetVersionNeeded(int version
) { m_VersionNeeded
= (wxUint16
)version
; }
212 void SetOffset(wxFileOffset offset
) { m_Offset
= offset
; }
213 void SetFlags(int flags
) { m_Flags
= (wxUint16
)flags
; }
214 void SetVersionMadeBy(int version
) { m_VersionMadeBy
= (wxUint8
)version
; }
215 void SetCrc(wxUint32 crc
) { m_Crc
= crc
; }
216 void SetCompressedSize(wxFileOffset size
) { m_CompressedSize
= size
; }
217 void SetKey(wxFileOffset offset
) { m_Key
= offset
; }
218 void SetDiskStart(int start
) { m_DiskStart
= (wxUint16
)start
; }
219 void SetInternalAttributes(int attr
) { m_InternalAttributes
= (wxUint16
)attr
; }
221 virtual wxZipEntry
*ZipClone() const { return new wxZipEntry(*this); }
226 wxArchiveEntry
* DoClone() const { return ZipClone(); }
228 size_t ReadLocal(wxInputStream
& stream
, wxMBConv
& conv
);
229 size_t WriteLocal(wxOutputStream
& stream
, wxMBConv
& conv
) const;
231 size_t ReadCentral(wxInputStream
& stream
, wxMBConv
& conv
);
232 size_t WriteCentral(wxOutputStream
& stream
, wxMBConv
& conv
) const;
234 size_t ReadDescriptor(wxInputStream
& stream
);
235 size_t WriteDescriptor(wxOutputStream
& stream
, wxUint32 crc
,
236 wxFileOffset compressedSize
, wxFileOffset size
);
238 wxUint8 m_SystemMadeBy
; // one of enum wxZipSystem
239 wxUint8 m_VersionMadeBy
; // major * 10 + minor
241 wxUint16 m_VersionNeeded
; // ver needed to extract (20 i.e. v2.0)
243 wxUint16 m_Method
; // compression method (one of wxZipMethod)
244 wxDateTime m_DateTime
;
246 wxFileOffset m_CompressedSize
;
248 wxString m_Name
; // in internal format
249 wxFileOffset m_Key
; // the original offset for copied entries
250 wxFileOffset m_Offset
; // file offset of the entry
253 wxUint16 m_DiskStart
; // for multidisk archives, not unsupported
254 wxUint16 m_InternalAttributes
; // bit 0 set for text files
255 wxUint32 m_ExternalAttributes
; // system specific depends on SystemMadeBy
257 class wxZipMemory
*m_Extra
;
258 class wxZipMemory
*m_LocalExtra
;
260 wxZipNotifier
*m_zipnotifier
;
261 class wxZipWeakLinks
*m_backlink
;
263 friend class wxZipInputStream
;
264 friend class wxZipOutputStream
;
266 DECLARE_DYNAMIC_CLASS(wxZipEntry
)
270 /////////////////////////////////////////////////////////////////////////////
273 WX_DECLARE_LIST_WITH_DECL(wxZipEntry
, wx__ZipEntryList
, class WXDLLIMPEXP_BASE
);
275 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
278 wxZipOutputStream(wxOutputStream
& stream
,
280 wxMBConv
& conv
= wxConvLocal
);
281 virtual WXZIPFIX
~wxZipOutputStream();
283 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
285 bool WXZIPFIX
PutNextEntry(const wxString
& name
,
286 const wxDateTime
& dt
= wxDateTime::Now(),
287 wxFileOffset size
= wxInvalidOffset
);
289 bool WXZIPFIX
PutNextDirEntry(const wxString
& name
,
290 const wxDateTime
& dt
= wxDateTime::Now());
292 bool WXZIPFIX
CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
293 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
295 void WXZIPFIX
Sync();
296 bool WXZIPFIX
CloseEntry();
297 bool WXZIPFIX
Close();
299 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
301 int GetLevel() const { return m_level
; }
302 void WXZIPFIX
SetLevel(int level
);
305 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
306 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
308 // this protected interface isn't yet finalised
309 struct Buffer
{ const char *m_data
; size_t m_size
; };
310 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
312 const Buffer bufs
[]);
313 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
315 bool IsParentSeekable() const
316 { return m_offsetAdjustment
!= wxInvalidOffset
; }
319 bool WXZIPFIX
PutNextEntry(wxArchiveEntry
*entry
);
320 bool WXZIPFIX
CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
321 bool WXZIPFIX
CopyArchiveMetaData(wxArchiveInputStream
& stream
);
323 bool IsOpened() const { return m_comp
|| m_pending
; }
325 bool DoCreate(wxZipEntry
*entry
, bool raw
= false);
326 void CreatePendingEntry(const void *buffer
, size_t size
);
327 void CreatePendingEntry();
329 class wxStoredOutputStream
*m_store
;
330 class wxZlibOutputStream2
*m_deflate
;
331 class wxZipStreamLink
*m_backlink
;
332 wx__ZipEntryList m_entries
;
334 size_t m_initialSize
;
335 wxZipEntry
*m_pending
;
337 wxFileOffset m_headerOffset
;
339 wxFileOffset m_entrySize
;
340 wxUint32 m_crcAccumulator
;
341 wxOutputStream
*m_comp
;
343 wxFileOffset m_offsetAdjustment
;
346 DECLARE_NO_COPY_CLASS(wxZipOutputStream
)
350 /////////////////////////////////////////////////////////////////////////////
353 class WXDLLIMPEXP_BASE wxZipInputStream
: public wxArchiveInputStream
356 typedef wxZipEntry entry_type
;
358 wxZipInputStream(wxInputStream
& stream
, wxMBConv
& conv
= wxConvLocal
);
360 #if 1 //WXWIN_COMPATIBILITY_2_6
361 wxZipInputStream(const wxString
& archive
, const wxString
& file
)
362 : wxArchiveInputStream(OpenFile(archive
), wxConvLocal
) { Init(file
); }
365 virtual WXZIPFIX
~wxZipInputStream();
367 bool OpenEntry(wxZipEntry
& entry
) { return DoOpen(&entry
); }
368 bool WXZIPFIX
CloseEntry();
370 wxZipEntry
*GetNextEntry();
372 wxString WXZIPFIX
GetComment();
373 int WXZIPFIX
GetTotalEntries();
375 virtual wxFileOffset
GetLength() const { return m_entry
.GetSize(); }
378 size_t WXZIPFIX
OnSysRead(void *buffer
, size_t size
);
379 wxFileOffset
OnSysTell() const { return m_decomp
? m_decomp
->TellI() : 0; }
381 #if 1 //WXWIN_COMPATIBILITY_2_6
382 wxFileOffset WXZIPFIX
OnSysSeek(wxFileOffset seek
, wxSeekMode mode
);
385 // this protected interface isn't yet finalised
386 virtual wxInputStream
* WXZIPFIX
OpenDecompressor(wxInputStream
& stream
);
387 virtual bool WXZIPFIX
CloseDecompressor(wxInputStream
*decomp
);
391 void Init(const wxString
& file
);
392 wxInputStream
& OpenFile(const wxString
& archive
);
394 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
396 bool WXZIPFIX
OpenEntry(wxArchiveEntry
& entry
);
398 wxStreamError
ReadLocal(bool readEndRec
= false);
399 wxStreamError
ReadCentral();
401 wxUint32
ReadSignature();
402 bool FindEndRecord();
403 bool LoadEndRecord();
405 bool AtHeader() const { return m_headerSize
== 0; }
406 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
407 bool IsOpened() const { return m_decomp
!= NULL
; }
409 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
411 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
412 bool OpenDecompressor(bool raw
= false);
414 class wxStoredInputStream
*m_store
;
415 class wxZlibInputStream2
*m_inflate
;
416 class wxRawInputStream
*m_rawin
;
417 class wxFFileInputStream
*m_ffile
;
421 wxUint32 m_crcAccumulator
;
422 wxInputStream
*m_decomp
;
423 bool m_parentSeekable
;
424 class wxZipWeakLinks
*m_weaklinks
;
425 class wxZipStreamLink
*m_streamlink
;
426 wxFileOffset m_offsetAdjustment
;
427 wxFileOffset m_position
;
428 wxUint32 m_signature
;
429 size_t m_TotalEntries
;
432 friend bool wxZipOutputStream::CopyEntry(
433 wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
434 friend bool wxZipOutputStream::CopyArchiveMetaData(
435 wxZipInputStream
& inputStream
);
437 #if 1 //WXWIN_COMPATIBILITY_2_6
439 friend class wxZipFSInputStream
;
442 DECLARE_NO_COPY_CLASS(wxZipInputStream
)
446 /////////////////////////////////////////////////////////////////////////////
449 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
450 typedef wxArchiveIterator
<wxZipInputStream
> wxZipIter
;
451 typedef wxArchiveIterator
<wxZipInputStream
,
452 std::pair
<wxString
, wxZipEntry
*> > wxZipPairIter
;
456 /////////////////////////////////////////////////////////////////////////////
459 class WXDLLIMPEXP_BASE wxZipClassFactory
: public wxArchiveClassFactory
462 typedef wxZipEntry entry_type
;
463 typedef wxZipInputStream instream_type
;
464 typedef wxZipOutputStream outstream_type
;
465 typedef wxZipNotifier notifier_type
;
466 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
467 typedef wxZipIter iter_type
;
468 typedef wxZipPairIter pairiter_type
;
471 wxZipEntry
*NewEntry() const
472 { return new wxZipEntry
; }
473 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
474 { return new wxZipInputStream(stream
, GetConv()); }
475 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
476 { return new wxZipOutputStream(stream
, -1, GetConv()); }
478 wxString
GetInternalName(const wxString
& name
,
479 wxPathFormat format
= wxPATH_NATIVE
) const
480 { return wxZipEntry::GetInternalName(name
, format
); }
483 wxArchiveEntry
*DoNewEntry() const
484 { return NewEntry(); }
485 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
486 { return NewStream(stream
); }
487 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
488 { return NewStream(stream
); }
491 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
495 /////////////////////////////////////////////////////////////////////////////
496 // wxZipEntry inlines
498 inline bool wxZipEntry::IsText() const
500 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
503 inline bool wxZipEntry::IsDir() const
505 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
508 inline bool wxZipEntry::IsReadOnly() const
510 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
513 inline bool wxZipEntry::IsMadeByUnix() const
516 (1 << wxZIP_SYSTEM_OPENVMS
) |
517 (1 << wxZIP_SYSTEM_UNIX
) |
518 (1 << wxZIP_SYSTEM_ATARI_ST
) |
519 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
520 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
522 // note: some unix zippers put madeby = dos
523 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
524 && (m_ExternalAttributes
& ~0xFFFF))
525 || ((pattern
>> m_SystemMadeBy
) & 1);
528 inline void wxZipEntry::SetIsText(bool isText
)
531 m_InternalAttributes
|= TEXT_ATTR
;
533 m_InternalAttributes
&= ~TEXT_ATTR
;
536 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
539 SetMode(GetMode() & ~0222);
541 SetMode(GetMode() | 0200);
544 inline void wxZipEntry::SetName(const wxString
& name
,
545 wxPathFormat format
/*=wxPATH_NATIVE*/)
548 m_Name
= GetInternalName(name
, format
, &isDir
);
553 #endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
555 #endif // _WX_WXZIPSTREAM_H__