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_FWD_BASE wxZipEntry
;
116 class WXDLLIMPEXP_FWD_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); }
225 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
); }
287 bool WXZIPFIX
PutNextEntry(const wxString
& name
,
288 const wxDateTime
& dt
= wxDateTime::Now(),
289 wxFileOffset size
= wxInvalidOffset
);
291 bool WXZIPFIX
PutNextDirEntry(const wxString
& name
,
292 const wxDateTime
& dt
= wxDateTime::Now());
294 bool WXZIPFIX
CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
295 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
297 void WXZIPFIX
Sync();
298 bool WXZIPFIX
CloseEntry();
299 bool WXZIPFIX
Close();
301 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
303 int GetLevel() const { return m_level
; }
304 void WXZIPFIX
SetLevel(int level
);
307 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
308 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
310 // this protected interface isn't yet finalised
311 struct Buffer
{ const char *m_data
; size_t m_size
; };
312 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
314 const Buffer bufs
[]);
315 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
317 bool IsParentSeekable() const
318 { return m_offsetAdjustment
!= wxInvalidOffset
; }
321 void Init(int level
);
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 wxZipEntryList_ 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
);
363 wxZipInputStream(wxInputStream
*stream
, wxMBConv
& conv
= wxConvLocal
);
365 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
366 wxZipInputStream(const wxString
& archive
, const wxString
& file
)
367 : wxArchiveInputStream(OpenFile(archive
), wxConvLocal
) { Init(file
); }
370 virtual WXZIPFIX
~wxZipInputStream();
372 bool OpenEntry(wxZipEntry
& entry
) { return DoOpen(&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
);
396 void Init(const wxString
& file
);
397 #if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE
398 static wxInputStream
*OpenFile(const wxString
& archive
);
401 wxArchiveEntry
*DoGetNextEntry() { return GetNextEntry(); }
403 bool WXZIPFIX
OpenEntry(wxArchiveEntry
& entry
);
405 wxStreamError
ReadLocal(bool readEndRec
= false);
406 wxStreamError
ReadCentral();
408 wxUint32
ReadSignature();
409 bool FindEndRecord();
410 bool LoadEndRecord();
412 bool AtHeader() const { return m_headerSize
== 0; }
413 bool AfterHeader() const { return m_headerSize
> 0 && !m_decomp
; }
414 bool IsOpened() const { return m_decomp
!= NULL
; }
416 wxZipStreamLink
*MakeLink(wxZipOutputStream
*out
);
418 bool DoOpen(wxZipEntry
*entry
= NULL
, bool raw
= false);
419 bool OpenDecompressor(bool raw
= false);
421 class wxStoredInputStream
*m_store
;
422 class wxZlibInputStream2
*m_inflate
;
423 class wxRawInputStream
*m_rawin
;
427 wxUint32 m_crcAccumulator
;
428 wxInputStream
*m_decomp
;
429 bool m_parentSeekable
;
430 class wxZipWeakLinks
*m_weaklinks
;
431 class wxZipStreamLink
*m_streamlink
;
432 wxFileOffset m_offsetAdjustment
;
433 wxFileOffset m_position
;
434 wxUint32 m_signature
;
435 size_t m_TotalEntries
;
438 friend bool wxZipOutputStream::CopyEntry(
439 wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
440 friend bool wxZipOutputStream::CopyArchiveMetaData(
441 wxZipInputStream
& inputStream
);
443 #if WXWIN_COMPATIBILITY_2_6
445 friend class wxArchiveFSHandler
;
448 DECLARE_NO_COPY_CLASS(wxZipInputStream
)
452 /////////////////////////////////////////////////////////////////////////////
455 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
456 typedef wxArchiveIterator
<wxZipInputStream
> wxZipIter
;
457 typedef wxArchiveIterator
<wxZipInputStream
,
458 std::pair
<wxString
, wxZipEntry
*> > wxZipPairIter
;
462 /////////////////////////////////////////////////////////////////////////////
465 class WXDLLIMPEXP_BASE wxZipClassFactory
: public wxArchiveClassFactory
468 typedef wxZipEntry entry_type
;
469 typedef wxZipInputStream instream_type
;
470 typedef wxZipOutputStream outstream_type
;
471 typedef wxZipNotifier notifier_type
;
472 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
473 typedef wxZipIter iter_type
;
474 typedef wxZipPairIter pairiter_type
;
479 wxZipEntry
*NewEntry() const
480 { return new wxZipEntry
; }
481 wxZipInputStream
*NewStream(wxInputStream
& stream
) const
482 { return new wxZipInputStream(stream
, GetConv()); }
483 wxZipOutputStream
*NewStream(wxOutputStream
& stream
) const
484 { return new wxZipOutputStream(stream
, -1, GetConv()); }
485 wxZipInputStream
*NewStream(wxInputStream
*stream
) const
486 { return new wxZipInputStream(stream
, GetConv()); }
487 wxZipOutputStream
*NewStream(wxOutputStream
*stream
) const
488 { return new wxZipOutputStream(stream
, -1, GetConv()); }
490 wxString
GetInternalName(const wxString
& name
,
491 wxPathFormat format
= wxPATH_NATIVE
) const
492 { return wxZipEntry::GetInternalName(name
, format
); }
494 const wxChar
* const *GetProtocols(wxStreamProtocolType type
495 = wxSTREAM_PROTOCOL
) const;
498 wxArchiveEntry
*DoNewEntry() const
499 { return NewEntry(); }
500 wxArchiveInputStream
*DoNewStream(wxInputStream
& stream
) const
501 { return NewStream(stream
); }
502 wxArchiveOutputStream
*DoNewStream(wxOutputStream
& stream
) const
503 { return NewStream(stream
); }
504 wxArchiveInputStream
*DoNewStream(wxInputStream
*stream
) const
505 { return NewStream(stream
); }
506 wxArchiveOutputStream
*DoNewStream(wxOutputStream
*stream
) const
507 { return NewStream(stream
); }
510 DECLARE_DYNAMIC_CLASS(wxZipClassFactory
)
514 /////////////////////////////////////////////////////////////////////////////
515 // wxZipEntry inlines
517 inline bool wxZipEntry::IsText() const
519 return (m_InternalAttributes
& TEXT_ATTR
) != 0;
522 inline bool wxZipEntry::IsDir() const
524 return (m_ExternalAttributes
& wxZIP_A_SUBDIR
) != 0;
527 inline bool wxZipEntry::IsReadOnly() const
529 return (m_ExternalAttributes
& wxZIP_A_RDONLY
) != 0;
532 inline bool wxZipEntry::IsMadeByUnix() const
535 (1 << wxZIP_SYSTEM_OPENVMS
) |
536 (1 << wxZIP_SYSTEM_UNIX
) |
537 (1 << wxZIP_SYSTEM_ATARI_ST
) |
538 (1 << wxZIP_SYSTEM_ACORN_RISC
) |
539 (1 << wxZIP_SYSTEM_BEOS
) | (1 << wxZIP_SYSTEM_TANDEM
);
541 // note: some unix zippers put madeby = dos
542 return (m_SystemMadeBy
== wxZIP_SYSTEM_MSDOS
543 && (m_ExternalAttributes
& ~0xFFFF))
544 || ((pattern
>> m_SystemMadeBy
) & 1);
547 inline void wxZipEntry::SetIsText(bool isText
)
550 m_InternalAttributes
|= TEXT_ATTR
;
552 m_InternalAttributes
&= ~TEXT_ATTR
;
555 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly
)
558 SetMode(GetMode() & ~0222);
560 SetMode(GetMode() | 0200);
563 inline void wxZipEntry::SetName(const wxString
& name
,
564 wxPathFormat format
/*=wxPATH_NATIVE*/)
567 m_Name
= GetInternalName(name
, format
, &isDir
);
572 #endif // wxUSE_ZIPSTREAM
574 #endif // _WX_WXZIPSTREAM_H__