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__
17 #include "wx/archive.h"
18 #include "wx/filename.h"
20 // some methods from wxZipInputStream and wxZipOutputStream stream do not get
21 // exported/imported when compiled with Mingw versions before 3.4.2. So they
22 // are imported/exported individually as a workaround
23 #if (defined(__GNUWIN32__) || defined(__MINGW32__)) \
24 && (!defined __GNUC__ \
25 || !defined __GNUC_MINOR__ \
26 || !defined __GNUC_PATCHLEVEL__ \
27 || __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 30402)
28 #define WXZIPFIX WXDLLIMPEXP_BASE
33 /////////////////////////////////////////////////////////////////////////////
36 // Compression Method, only 0 (store) and 8 (deflate) are supported here
47 wxZIP_METHOD_TOKENIZE
,
49 wxZIP_METHOD_DEFLATE64
,
50 wxZIP_METHOD_BZIP2
= 12,
51 wxZIP_METHOD_DEFAULT
= 0xffff
54 // Originating File-System.
56 // These are Pkware's values. Note that Info-zip disagree on some of them,
66 wxZIP_SYSTEM_ATARI_ST
,
67 wxZIP_SYSTEM_OS2_HPFS
,
68 wxZIP_SYSTEM_MACINTOSH
,
69 wxZIP_SYSTEM_Z_SYSTEM
,
71 wxZIP_SYSTEM_WINDOWS_NTFS
,
74 wxZIP_SYSTEM_ACORN_RISC
,
76 wxZIP_SYSTEM_ALTERNATE_MVS
,
82 // Dos/Win file attributes
86 wxZIP_A_RDONLY
= 0x01,
87 wxZIP_A_HIDDEN
= 0x02,
88 wxZIP_A_SYSTEM
= 0x04,
89 wxZIP_A_SUBDIR
= 0x10,
95 // Values for the flags field in the zip headers
99 wxZIP_ENCRYPTED
= 0x0001,
100 wxZIP_DEFLATE_NORMAL
= 0x0000, // normal compression
101 wxZIP_DEFLATE_EXTRA
= 0x0002, // extra compression
102 wxZIP_DEFLATE_FAST
= 0x0004, // fast compression
103 wxZIP_DEFLATE_SUPERFAST
= 0x0006, // superfast compression
104 wxZIP_DEFLATE_MASK
= 0x0006,
105 wxZIP_SUMS_FOLLOW
= 0x0008, // crc and sizes come after the data
106 wxZIP_ENHANCED
= 0x0010,
107 wxZIP_PATCH
= 0x0020,
108 wxZIP_STRONG_ENC
= 0x0040,
109 wxZIP_UNUSED
= 0x0F80,
110 wxZIP_RESERVED
= 0xF000
115 class WXDLLIMPEXP_BASE wxZipEntry
;
116 class WXDLLIMPEXP_BASE wxZipInputStream
;
119 /////////////////////////////////////////////////////////////////////////////
122 class WXDLLIMPEXP_BASE wxZipNotifier
125 virtual ~wxZipNotifier() { }
127 virtual void OnEntryUpdated(wxZipEntry
& entry
) = 0;
131 /////////////////////////////////////////////////////////////////////////////
132 // Zip Entry - holds the meta data for a file in the zip
134 class WXDLLIMPEXP_BASE wxZipEntry
: public wxArchiveEntry
137 wxZipEntry(const wxString
& name
= wxEmptyString
,
138 const wxDateTime
& dt
= wxDateTime::Now(),
139 wxFileOffset size
= wxInvalidOffset
);
140 virtual ~wxZipEntry();
142 wxZipEntry(const wxZipEntry
& entry
);
143 wxZipEntry
& operator=(const wxZipEntry
& entry
);
146 wxDateTime
GetDateTime() const { return m_DateTime
; }
147 wxFileOffset
GetSize() const { return m_Size
; }
148 wxFileOffset
GetOffset() const { return m_Offset
; }
149 wxString
GetInternalName() const { return m_Name
; }
150 int GetMethod() const { return m_Method
; }
151 int GetFlags() const { return m_Flags
; }
152 wxUint32
GetCrc() const { return m_Crc
; }
153 wxFileOffset
GetCompressedSize() const { return m_CompressedSize
; }
154 int GetSystemMadeBy() const { return m_SystemMadeBy
; }
155 wxString
GetComment() const { return m_Comment
; }
156 wxUint32
GetExternalAttributes() const { return m_ExternalAttributes
; }
157 wxPathFormat
GetInternalFormat() const { return wxPATH_UNIX
; }
159 const char *GetLocalExtra() const;
160 size_t GetLocalExtraLen() const;
161 const char *GetExtra() const;
162 size_t GetExtraLen() const;
163 wxString
GetName(wxPathFormat format
= wxPATH_NATIVE
) const;
166 inline bool IsDir() const;
167 inline bool IsText() const;
168 inline bool IsReadOnly() const;
169 inline bool IsMadeByUnix() const;
172 void SetDateTime(const wxDateTime
& dt
) { m_DateTime
= dt
; }
173 void SetSize(wxFileOffset size
) { m_Size
= size
; }
174 void SetMethod(int method
) { m_Method
= (wxUint16
)method
; }
175 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
176 void SetExternalAttributes(wxUint32 attr
) { m_ExternalAttributes
= attr
; }
177 void SetSystemMadeBy(int system
);
178 void SetMode(int mode
);
179 void SetExtra(const char *extra
, size_t len
);
180 void SetLocalExtra(const char *extra
, size_t len
);
182 inline void SetName(const wxString
& name
,
183 wxPathFormat format
= wxPATH_NATIVE
);
185 static wxString
GetInternalName(const wxString
& name
,
186 wxPathFormat format
= wxPATH_NATIVE
,
187 bool *pIsDir
= NULL
);
190 void SetIsDir(bool isDir
= true);
191 inline void SetIsReadOnly(bool isReadOnly
= true);
192 inline void SetIsText(bool isText
= true);
194 wxZipEntry
*Clone() const { return ZipClone(); }
196 void SetNotifier(wxZipNotifier
& notifier
);
197 void UnsetNotifier();
200 // Internal attributes
201 enum { TEXT_ATTR
= 1 };
203 // protected Get accessors
204 int GetVersionNeeded() const { return m_VersionNeeded
; }
205 wxFileOffset
GetKey() const { return m_Key
; }
206 int GetVersionMadeBy() const { return m_VersionMadeBy
; }
207 int GetDiskStart() const { return m_DiskStart
; }
208 int GetInternalAttributes() const { return m_InternalAttributes
; }
210 void SetVersionNeeded(int version
) { m_VersionNeeded
= (wxUint16
)version
; }
211 void SetOffset(wxFileOffset offset
) { m_Offset
= offset
; }
212 void SetFlags(int flags
) { m_Flags
= (wxUint16
)flags
; }
213 void SetVersionMadeBy(int version
) { m_VersionMadeBy
= (wxUint8
)version
; }
214 void SetCrc(wxUint32 crc
) { m_Crc
= crc
; }
215 void SetCompressedSize(wxFileOffset size
) { m_CompressedSize
= size
; }
216 void SetKey(wxFileOffset offset
) { m_Key
= offset
; }
217 void SetDiskStart(int start
) { m_DiskStart
= (wxUint16
)start
; }
218 void SetInternalAttributes(int attr
) { m_InternalAttributes
= (wxUint16
)attr
; }
220 virtual wxZipEntry
*ZipClone() const { return new wxZipEntry(*this); }
224 wxArchiveEntry
* DoClone() const { return ZipClone(); }
227 size_t ReadLocal(wxInputStream
& stream
, wxMBConv
& conv
);
228 size_t WriteLocal(wxOutputStream
& stream
, wxMBConv
& conv
) const;
230 size_t ReadCentral(wxInputStream
& stream
, wxMBConv
& conv
);
231 size_t WriteCentral(wxOutputStream
& stream
, wxMBConv
& conv
) const;
233 size_t ReadDescriptor(wxInputStream
& stream
);
234 size_t WriteDescriptor(wxOutputStream
& stream
, wxUint32 crc
,
235 wxFileOffset compressedSize
, wxFileOffset size
);
237 wxUint8 m_SystemMadeBy
; // one of enum wxZipSystem
238 wxUint8 m_VersionMadeBy
; // major * 10 + minor
240 wxUint16 m_VersionNeeded
; // ver needed to extract (20 i.e. v2.0)
242 wxUint16 m_Method
; // compression method (one of wxZipMethod)
243 wxDateTime m_DateTime
;
245 wxFileOffset m_CompressedSize
;
247 wxString m_Name
; // in internal format
248 wxFileOffset m_Key
; // the original offset for copied entries
249 wxFileOffset m_Offset
; // file offset of the entry
252 wxUint16 m_DiskStart
; // for multidisk archives, not unsupported
253 wxUint16 m_InternalAttributes
; // bit 0 set for text files
254 wxUint32 m_ExternalAttributes
; // system specific depends on SystemMadeBy
256 class wxZipMemory
*m_Extra
;
257 class wxZipMemory
*m_LocalExtra
;
259 wxZipNotifier
*m_zipnotifier
;
260 class wxZipWeakLinks
*m_backlink
;
262 friend class wxZipInputStream
;
263 friend class wxZipOutputStream
;
265 DECLARE_DYNAMIC_CLASS(wxZipEntry
)
269 /////////////////////////////////////////////////////////////////////////////
272 WX_DECLARE_LIST_WITH_DECL(wxZipEntry
, wxZipEntryList_
, class WXDLLIMPEXP_BASE
);
274 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
277 wxZipOutputStream(wxOutputStream
& stream
,
279 wxMBConv
& conv
= wxConvLocal
);
280 wxZipOutputStream(wxOutputStream
*stream
,
282 wxMBConv
& conv
= wxConvLocal
);
283 virtual WXZIPFIX
~wxZipOutputStream();
285 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
286 bool WXZIPFIX
PutNextEntry(wxArchiveEntry
*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
CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
297 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
298 bool WXZIPFIX
CopyArchiveMetaData(wxArchiveInputStream
& stream
);
300 void WXZIPFIX
Sync();
301 bool WXZIPFIX
CloseEntry();
302 bool WXZIPFIX
Close();
304 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
306 int GetLevel() const { return m_level
; }
307 void WXZIPFIX
SetLevel(int level
);
310 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
311 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
313 // this protected interface isn't yet finalised
314 struct Buffer
{ const char *m_data
; size_t m_size
; };
315 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
317 const Buffer bufs
[]);
318 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
320 bool IsParentSeekable() const
321 { return m_offsetAdjustment
!= wxInvalidOffset
; }
324 void Init(int level
);
326 bool IsOpened() const { return m_comp
|| m_pending
; }
328 bool DoCreate(wxZipEntry
*entry
, bool raw
= false);
329 void CreatePendingEntry(const void *buffer
, size_t size
);
330 void CreatePendingEntry();
332 class wxStoredOutputStream
*m_store
;
333 class wxZlibOutputStream2
*m_deflate
;
334 class wxZipStreamLink
*m_backlink
;
335 wxZipEntryList_ m_entries
;
337 size_t m_initialSize
;
338 wxZipEntry
*m_pending
;
340 wxFileOffset m_headerOffset
;
342 wxFileOffset m_entrySize
;
343 wxUint32 m_crcAccumulator
;
344 wxOutputStream
*m_comp
;
346 wxFileOffset m_offsetAdjustment
;
349 DECLARE_NO_COPY_CLASS(wxZipOutputStream
)
353 /////////////////////////////////////////////////////////////////////////////
356 class WXDLLIMPEXP_BASE wxZipInputStream
: public wxArchiveInputStream
359 typedef wxZipEntry entry_type
;
361 wxZipInputStream(wxInputStream
& stream
, wxMBConv
& conv
= wxConvLocal
);
362 wxZipInputStream(wxInputStream
*stream
, wxMBConv
& conv
= wxConvLocal
);
364 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
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
OpenEntry(wxArchiveEntry
& entry
);
373 bool WXZIPFIX
CloseEntry();
375 wxZipEntry
*GetNextEntry();
377 wxString WXZIPFIX
GetComment();
378 int WXZIPFIX
GetTotalEntries();
380 virtual wxFileOffset
GetLength() const { return m_entry
.GetSize(); }
383 size_t WXZIPFIX
OnSysRead(void *buffer
, size_t size
);
384 wxFileOffset
OnSysTell() const { return m_decomp
? m_decomp
->TellI() : 0; }
386 #if WXWIN_COMPATIBILITY_2_6
387 wxFileOffset WXZIPFIX
OnSysSeek(wxFileOffset seek
, wxSeekMode mode
);
390 // this protected interface isn't yet finalised
391 virtual wxInputStream
* WXZIPFIX
OpenDecompressor(wxInputStream
& stream
);
392 virtual bool WXZIPFIX
CloseDecompressor(wxInputStream
*decomp
);
394 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
398 void Init(const wxString
& file
);
399 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
400 static wxInputStream
*OpenFile(const wxString
& archive
);
403 wxStreamError
ReadLocal(bool readEndRec
= false);
404 wxStreamError
ReadCentral();
406 wxUint32
ReadSignature();
407 bool FindEndRecord();
408 bool LoadEndRecord();
410 bool AtHeader() const { return m_headerSize
== 0; }
411 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
412 bool IsOpened() const { return m_decomp
!= NULL
; }
414 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
416 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
417 bool OpenDecompressor(bool raw
= false);
419 class wxStoredInputStream
*m_store
;
420 class wxZlibInputStream2
*m_inflate
;
421 class wxRawInputStream
*m_rawin
;
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 WXWIN_COMPATIBILITY_2_6
443 friend class wxArchiveFSHandler
;
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
;
477 wxZipEntry
*NewEntry() const
478 { return new wxZipEntry
; }
479 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
480 { return new wxZipInputStream(stream
, GetConv()); }
481 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
482 { return new wxZipOutputStream(stream
, -1, GetConv()); }
483 wxZipInputStream
*NewStream(wxInputStream
*stream
) const
484 { return new wxZipInputStream(stream
, GetConv()); }
485 wxZipOutputStream
*NewStream(wxOutputStream
*stream
) const
486 { return new wxZipOutputStream(stream
, -1, GetConv()); }
488 wxString
GetInternalName(const wxString
& name
,
489 wxPathFormat format
= wxPATH_NATIVE
) const
490 { return wxZipEntry::GetInternalName(name
, format
); }
492 const wxChar
* const *GetProtocols(wxStreamProtocolType type
493 = wxSTREAM_PROTOCOL
) const;
496 wxArchiveEntry
*DoNewEntry() const
497 { return NewEntry(); }
498 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
499 { return NewStream(stream
); }
500 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
501 { return NewStream(stream
); }
502 wxArchiveInputStream
*DoNewStream(wxInputStream
*stream
) const
503 { return NewStream(stream
); }
504 wxArchiveOutputStream
*DoNewStream(wxOutputStream
*stream
) const
505 { return NewStream(stream
); }
508 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
512 /////////////////////////////////////////////////////////////////////////////
513 // wxZipEntry inlines
515 inline bool wxZipEntry::IsText() const
517 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
520 inline bool wxZipEntry::IsDir() const
522 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
525 inline bool wxZipEntry::IsReadOnly() const
527 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
530 inline bool wxZipEntry::IsMadeByUnix() const
533 (1 << wxZIP_SYSTEM_OPENVMS
) |
534 (1 << wxZIP_SYSTEM_UNIX
) |
535 (1 << wxZIP_SYSTEM_ATARI_ST
) |
536 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
537 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
539 // note: some unix zippers put madeby = dos
540 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
541 && (m_ExternalAttributes
& ~0xFFFF))
542 || ((pattern
>> m_SystemMadeBy
) & 1);
545 inline void wxZipEntry::SetIsText(bool isText
)
548 m_InternalAttributes
|= TEXT_ATTR
;
550 m_InternalAttributes
&= ~TEXT_ATTR
;
553 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
556 SetMode(GetMode() & ~0222);
558 SetMode(GetMode() | 0200);
561 inline void wxZipEntry::SetName(const wxString
& name
,
562 wxPathFormat format
/*=wxPATH_NATIVE*/)
565 m_Name
= GetInternalName(name
, format
, &isDir
);
570 #endif // wxUSE_ZIPSTREAM
572 #endif // _WX_WXZIPSTREAM_H__