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
, wxZipEntryList_
, class WXDLLIMPEXP_BASE
);
275 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
278 wxZipOutputStream(wxOutputStream
& stream
,
280 wxMBConv
& conv
= wxConvLocal
);
281 wxZipOutputStream(wxOutputStream
*stream
,
283 wxMBConv
& conv
= wxConvLocal
);
284 virtual WXZIPFIX
~wxZipOutputStream();
286 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
288 bool WXZIPFIX
PutNextEntry(const wxString
& name
,
289 const wxDateTime
& dt
= wxDateTime::Now(),
290 wxFileOffset size
= wxInvalidOffset
);
292 bool WXZIPFIX
PutNextDirEntry(const wxString
& name
,
293 const wxDateTime
& dt
= wxDateTime::Now());
295 bool WXZIPFIX
CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
296 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
298 void WXZIPFIX
Sync();
299 bool WXZIPFIX
CloseEntry();
300 bool WXZIPFIX
Close();
302 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
304 int GetLevel() const { return m_level
; }
305 void WXZIPFIX
SetLevel(int level
);
308 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
309 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
311 // this protected interface isn't yet finalised
312 struct Buffer
{ const char *m_data
; size_t m_size
; };
313 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
315 const Buffer bufs
[]);
316 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
318 bool IsParentSeekable() const
319 { return m_offsetAdjustment
!= wxInvalidOffset
; }
322 void Init(int level
);
324 bool WXZIPFIX
PutNextEntry(wxArchiveEntry
*entry
);
325 bool WXZIPFIX
CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
326 bool WXZIPFIX
CopyArchiveMetaData(wxArchiveInputStream
& stream
);
328 bool IsOpened() const { return m_comp
|| m_pending
; }
330 bool DoCreate(wxZipEntry
*entry
, bool raw
= false);
331 void CreatePendingEntry(const void *buffer
, size_t size
);
332 void CreatePendingEntry();
334 class wxStoredOutputStream
*m_store
;
335 class wxZlibOutputStream2
*m_deflate
;
336 class wxZipStreamLink
*m_backlink
;
337 wxZipEntryList_ m_entries
;
339 size_t m_initialSize
;
340 wxZipEntry
*m_pending
;
342 wxFileOffset m_headerOffset
;
344 wxFileOffset m_entrySize
;
345 wxUint32 m_crcAccumulator
;
346 wxOutputStream
*m_comp
;
348 wxFileOffset m_offsetAdjustment
;
351 DECLARE_NO_COPY_CLASS(wxZipOutputStream
)
355 /////////////////////////////////////////////////////////////////////////////
358 class WXDLLIMPEXP_BASE wxZipInputStream
: public wxArchiveInputStream
361 typedef wxZipEntry entry_type
;
363 wxZipInputStream(wxInputStream
& stream
, wxMBConv
& conv
= wxConvLocal
);
364 wxZipInputStream(wxInputStream
*stream
, wxMBConv
& conv
= wxConvLocal
);
366 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
367 wxZipInputStream(const wxString
& archive
, const wxString
& file
)
368 : wxArchiveInputStream(OpenFile(archive
), wxConvLocal
) { Init(file
); }
371 virtual WXZIPFIX
~wxZipInputStream();
373 bool OpenEntry(wxZipEntry
& entry
) { return DoOpen(&entry
); }
374 bool WXZIPFIX
CloseEntry();
376 wxZipEntry
*GetNextEntry();
378 wxString WXZIPFIX
GetComment();
379 int WXZIPFIX
GetTotalEntries();
381 virtual wxFileOffset
GetLength() const { return m_entry
.GetSize(); }
384 size_t WXZIPFIX
OnSysRead(void *buffer
, size_t size
);
385 wxFileOffset
OnSysTell() const { return m_decomp
? m_decomp
->TellI() : 0; }
387 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
388 wxFileOffset WXZIPFIX
OnSysSeek(wxFileOffset seek
, wxSeekMode mode
);
391 // this protected interface isn't yet finalised
392 virtual wxInputStream
* WXZIPFIX
OpenDecompressor(wxInputStream
& stream
);
393 virtual bool WXZIPFIX
CloseDecompressor(wxInputStream
*decomp
);
397 void Init(const wxString
& file
);
398 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
399 static wxInputStream
*OpenFile(const wxString
& archive
);
402 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
404 bool WXZIPFIX
OpenEntry(wxArchiveEntry
& entry
);
406 wxStreamError
ReadLocal(bool readEndRec
= false);
407 wxStreamError
ReadCentral();
409 wxUint32
ReadSignature();
410 bool FindEndRecord();
411 bool LoadEndRecord();
413 bool AtHeader() const { return m_headerSize
== 0; }
414 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
415 bool IsOpened() const { return m_decomp
!= NULL
; }
417 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
419 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
420 bool OpenDecompressor(bool raw
= false);
422 class wxStoredInputStream
*m_store
;
423 class wxZlibInputStream2
*m_inflate
;
424 class wxRawInputStream
*m_rawin
;
428 wxUint32 m_crcAccumulator
;
429 wxInputStream
*m_decomp
;
430 bool m_parentSeekable
;
431 class wxZipWeakLinks
*m_weaklinks
;
432 class wxZipStreamLink
*m_streamlink
;
433 wxFileOffset m_offsetAdjustment
;
434 wxFileOffset m_position
;
435 wxUint32 m_signature
;
436 size_t m_TotalEntries
;
439 friend bool wxZipOutputStream::CopyEntry(
440 wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
441 friend bool wxZipOutputStream::CopyArchiveMetaData(
442 wxZipInputStream
& inputStream
);
444 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
446 friend class wxZipFSInputStream
;
449 DECLARE_NO_COPY_CLASS(wxZipInputStream
)
453 /////////////////////////////////////////////////////////////////////////////
456 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
457 typedef wxArchiveIterator
<wxZipInputStream
> wxZipIter
;
458 typedef wxArchiveIterator
<wxZipInputStream
,
459 std::pair
<wxString
, wxZipEntry
*> > wxZipPairIter
;
463 /////////////////////////////////////////////////////////////////////////////
466 class WXDLLIMPEXP_BASE wxZipClassFactory
: public wxArchiveClassFactory
469 typedef wxZipEntry entry_type
;
470 typedef wxZipInputStream instream_type
;
471 typedef wxZipOutputStream outstream_type
;
472 typedef wxZipNotifier notifier_type
;
473 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
474 typedef wxZipIter iter_type
;
475 typedef wxZipPairIter pairiter_type
;
480 wxZipEntry
*NewEntry() const
481 { return new wxZipEntry
; }
482 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
483 { return new wxZipInputStream(stream
, GetConv()); }
484 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
485 { return new wxZipOutputStream(stream
, -1, GetConv()); }
486 wxZipInputStream
*NewStream(wxInputStream
*stream
) const
487 { return new wxZipInputStream(stream
, GetConv()); }
488 wxZipOutputStream
*NewStream(wxOutputStream
*stream
) const
489 { return new wxZipOutputStream(stream
, -1, GetConv()); }
491 wxString
GetInternalName(const wxString
& name
,
492 wxPathFormat format
= wxPATH_NATIVE
) const
493 { return wxZipEntry::GetInternalName(name
, format
); }
495 const wxChar
* const *GetProtocols(wxStreamProtocolType type
496 = wxSTREAM_PROTOCOL
) const;
499 wxArchiveEntry
*DoNewEntry() const
500 { return NewEntry(); }
501 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
502 { return NewStream(stream
); }
503 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
504 { return NewStream(stream
); }
505 wxArchiveInputStream
*DoNewStream(wxInputStream
*stream
) const
506 { return NewStream(stream
); }
507 wxArchiveOutputStream
*DoNewStream(wxOutputStream
*stream
) const
508 { return NewStream(stream
); }
511 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
515 /////////////////////////////////////////////////////////////////////////////
516 // wxZipEntry inlines
518 inline bool wxZipEntry::IsText() const
520 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
523 inline bool wxZipEntry::IsDir() const
525 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
528 inline bool wxZipEntry::IsReadOnly() const
530 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
533 inline bool wxZipEntry::IsMadeByUnix() const
536 (1 << wxZIP_SYSTEM_OPENVMS
) |
537 (1 << wxZIP_SYSTEM_UNIX
) |
538 (1 << wxZIP_SYSTEM_ATARI_ST
) |
539 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
540 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
542 // note: some unix zippers put madeby = dos
543 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
544 && (m_ExternalAttributes
& ~0xFFFF))
545 || ((pattern
>> m_SystemMadeBy
) & 1);
548 inline void wxZipEntry::SetIsText(bool isText
)
551 m_InternalAttributes
|= TEXT_ATTR
;
553 m_InternalAttributes
&= ~TEXT_ATTR
;
556 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
559 SetMode(GetMode() & ~0222);
561 SetMode(GetMode() | 0200);
564 inline void wxZipEntry::SetName(const wxString
& name
,
565 wxPathFormat format
/*=wxPATH_NATIVE*/)
568 m_Name
= GetInternalName(name
, format
, &isDir
);
573 #endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
575 #endif // _WX_WXZIPSTREAM_H__