1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Streams for Zip files
4 // Author: Mike Wetherell
5 // Copyright: (c) Mike Wetherell
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
9 #ifndef _WX_WXZIPSTREAM_H__
10 #define _WX_WXZIPSTREAM_H__
16 #include "wx/archive.h"
17 #include "wx/filename.h"
19 // some methods from wxZipInputStream and wxZipOutputStream stream do not get
20 // exported/imported when compiled with Mingw versions before 3.4.2. So they
21 // are imported/exported individually as a workaround
22 #if (defined(__GNUWIN32__) || defined(__MINGW32__)) \
23 && (!defined __GNUC__ \
24 || !defined __GNUC_MINOR__ \
25 || !defined __GNUC_PATCHLEVEL__ \
26 || __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 30402)
27 #define WXZIPFIX WXDLLIMPEXP_BASE
32 /////////////////////////////////////////////////////////////////////////////
35 // Compression Method, only 0 (store) and 8 (deflate) are supported here
46 wxZIP_METHOD_TOKENIZE
,
48 wxZIP_METHOD_DEFLATE64
,
49 wxZIP_METHOD_BZIP2
= 12,
50 wxZIP_METHOD_DEFAULT
= 0xffff
53 // Originating File-System.
55 // These are Pkware's values. Note that Info-zip disagree on some of them,
65 wxZIP_SYSTEM_ATARI_ST
,
66 wxZIP_SYSTEM_OS2_HPFS
,
67 wxZIP_SYSTEM_MACINTOSH
,
68 wxZIP_SYSTEM_Z_SYSTEM
,
70 wxZIP_SYSTEM_WINDOWS_NTFS
,
73 wxZIP_SYSTEM_ACORN_RISC
,
75 wxZIP_SYSTEM_ALTERNATE_MVS
,
81 // Dos/Win file attributes
85 wxZIP_A_RDONLY
= 0x01,
86 wxZIP_A_HIDDEN
= 0x02,
87 wxZIP_A_SYSTEM
= 0x04,
88 wxZIP_A_SUBDIR
= 0x10,
94 // Values for the flags field in the zip headers
98 wxZIP_ENCRYPTED
= 0x0001,
99 wxZIP_DEFLATE_NORMAL
= 0x0000, // normal compression
100 wxZIP_DEFLATE_EXTRA
= 0x0002, // extra compression
101 wxZIP_DEFLATE_FAST
= 0x0004, // fast compression
102 wxZIP_DEFLATE_SUPERFAST
= 0x0006, // superfast compression
103 wxZIP_DEFLATE_MASK
= 0x0006,
104 wxZIP_SUMS_FOLLOW
= 0x0008, // crc and sizes come after the data
105 wxZIP_ENHANCED
= 0x0010,
106 wxZIP_PATCH
= 0x0020,
107 wxZIP_STRONG_ENC
= 0x0040,
108 wxZIP_UNUSED
= 0x0F80,
109 wxZIP_RESERVED
= 0xF000
114 class WXDLLIMPEXP_FWD_BASE wxZipEntry
;
115 class WXDLLIMPEXP_FWD_BASE wxZipInputStream
;
118 /////////////////////////////////////////////////////////////////////////////
121 class WXDLLIMPEXP_BASE wxZipNotifier
124 virtual ~wxZipNotifier() { }
126 virtual void OnEntryUpdated(wxZipEntry
& entry
) = 0;
130 /////////////////////////////////////////////////////////////////////////////
131 // Zip Entry - holds the meta data for a file in the zip
133 class WXDLLIMPEXP_BASE wxZipEntry
: public wxArchiveEntry
136 wxZipEntry(const wxString
& name
= wxEmptyString
,
137 const wxDateTime
& dt
= wxDateTime::Now(),
138 wxFileOffset size
= wxInvalidOffset
);
139 virtual ~wxZipEntry();
141 wxZipEntry(const wxZipEntry
& entry
);
142 wxZipEntry
& operator=(const wxZipEntry
& entry
);
145 wxDateTime
GetDateTime() const { return m_DateTime
; }
146 wxFileOffset
GetSize() const { return m_Size
; }
147 wxFileOffset
GetOffset() const { return m_Offset
; }
148 wxString
GetInternalName() const { return m_Name
; }
149 int GetMethod() const { return m_Method
; }
150 int GetFlags() const { return m_Flags
; }
151 wxUint32
GetCrc() const { return m_Crc
; }
152 wxFileOffset
GetCompressedSize() const { return m_CompressedSize
; }
153 int GetSystemMadeBy() const { return m_SystemMadeBy
; }
154 wxString
GetComment() const { return m_Comment
; }
155 wxUint32
GetExternalAttributes() const { return m_ExternalAttributes
; }
156 wxPathFormat
GetInternalFormat() const { return wxPATH_UNIX
; }
158 const char *GetLocalExtra() const;
159 size_t GetLocalExtraLen() const;
160 const char *GetExtra() const;
161 size_t GetExtraLen() const;
162 wxString
GetName(wxPathFormat format
= wxPATH_NATIVE
) const;
165 inline bool IsDir() const;
166 inline bool IsText() const;
167 inline bool IsReadOnly() const;
168 inline bool IsMadeByUnix() const;
171 void SetDateTime(const wxDateTime
& dt
) { m_DateTime
= dt
; }
172 void SetSize(wxFileOffset size
) { m_Size
= size
; }
173 void SetMethod(int method
) { m_Method
= (wxUint16
)method
; }
174 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
175 void SetExternalAttributes(wxUint32 attr
) { m_ExternalAttributes
= attr
; }
176 void SetSystemMadeBy(int system
);
177 void SetMode(int mode
);
178 void SetExtra(const char *extra
, size_t len
);
179 void SetLocalExtra(const char *extra
, size_t len
);
181 inline void SetName(const wxString
& name
,
182 wxPathFormat format
= wxPATH_NATIVE
);
184 static wxString
GetInternalName(const wxString
& name
,
185 wxPathFormat format
= wxPATH_NATIVE
,
186 bool *pIsDir
= NULL
);
189 void SetIsDir(bool isDir
= true);
190 inline void SetIsReadOnly(bool isReadOnly
= true);
191 inline void SetIsText(bool isText
= true);
193 wxZipEntry
*Clone() const { return ZipClone(); }
195 void SetNotifier(wxZipNotifier
& notifier
);
196 void UnsetNotifier();
199 // Internal attributes
200 enum { TEXT_ATTR
= 1 };
202 // protected Get accessors
203 int GetVersionNeeded() const { return m_VersionNeeded
; }
204 wxFileOffset
GetKey() const { return m_Key
; }
205 int GetVersionMadeBy() const { return m_VersionMadeBy
; }
206 int GetDiskStart() const { return m_DiskStart
; }
207 int GetInternalAttributes() const { return m_InternalAttributes
; }
209 void SetVersionNeeded(int version
) { m_VersionNeeded
= (wxUint16
)version
; }
210 void SetOffset(wxFileOffset offset
) { m_Offset
= offset
; }
211 void SetFlags(int flags
) { m_Flags
= (wxUint16
)flags
; }
212 void SetVersionMadeBy(int version
) { m_VersionMadeBy
= (wxUint8
)version
; }
213 void SetCrc(wxUint32 crc
) { m_Crc
= crc
; }
214 void SetCompressedSize(wxFileOffset size
) { m_CompressedSize
= size
; }
215 void SetKey(wxFileOffset offset
) { m_Key
= offset
; }
216 void SetDiskStart(int start
) { m_DiskStart
= (wxUint16
)start
; }
217 void SetInternalAttributes(int attr
) { m_InternalAttributes
= (wxUint16
)attr
; }
219 virtual wxZipEntry
*ZipClone() const { return new wxZipEntry(*this); }
224 wxArchiveEntry
* DoClone() const { return ZipClone(); }
226 size_t ReadLocal(wxInputStream
& stream
, wxMBConv
& conv
);
227 size_t WriteLocal(wxOutputStream
& stream
, wxMBConv
& conv
) const;
229 size_t ReadCentral(wxInputStream
& stream
, wxMBConv
& conv
);
230 size_t WriteCentral(wxOutputStream
& stream
, wxMBConv
& conv
) const;
232 size_t ReadDescriptor(wxInputStream
& stream
);
233 size_t WriteDescriptor(wxOutputStream
& stream
, wxUint32 crc
,
234 wxFileOffset compressedSize
, wxFileOffset size
);
236 wxUint8 m_SystemMadeBy
; // one of enum wxZipSystem
237 wxUint8 m_VersionMadeBy
; // major * 10 + minor
239 wxUint16 m_VersionNeeded
; // ver needed to extract (20 i.e. v2.0)
241 wxUint16 m_Method
; // compression method (one of wxZipMethod)
242 wxDateTime m_DateTime
;
244 wxFileOffset m_CompressedSize
;
246 wxString m_Name
; // in internal format
247 wxFileOffset m_Key
; // the original offset for copied entries
248 wxFileOffset m_Offset
; // file offset of the entry
251 wxUint16 m_DiskStart
; // for multidisk archives, not unsupported
252 wxUint16 m_InternalAttributes
; // bit 0 set for text files
253 wxUint32 m_ExternalAttributes
; // system specific depends on SystemMadeBy
255 class wxZipMemory
*m_Extra
;
256 class wxZipMemory
*m_LocalExtra
;
258 wxZipNotifier
*m_zipnotifier
;
259 class wxZipWeakLinks
*m_backlink
;
261 friend class wxZipInputStream
;
262 friend class wxZipOutputStream
;
264 DECLARE_DYNAMIC_CLASS(wxZipEntry
)
268 /////////////////////////////////////////////////////////////////////////////
271 WX_DECLARE_LIST_WITH_DECL(wxZipEntry
, wxZipEntryList_
, class WXDLLIMPEXP_BASE
);
273 class WXDLLIMPEXP_BASE wxZipOutputStream
: public wxArchiveOutputStream
276 wxZipOutputStream(wxOutputStream
& stream
,
278 wxMBConv
& conv
= wxConvLocal
);
279 wxZipOutputStream(wxOutputStream
*stream
,
281 wxMBConv
& conv
= wxConvLocal
);
282 virtual WXZIPFIX
~wxZipOutputStream();
284 bool PutNextEntry(wxZipEntry
*entry
) { return DoCreate(entry
); }
286 bool WXZIPFIX
PutNextEntry(const wxString
& name
,
287 const wxDateTime
& dt
= wxDateTime::Now(),
288 wxFileOffset size
= wxInvalidOffset
);
290 bool WXZIPFIX
PutNextDirEntry(const wxString
& name
,
291 const wxDateTime
& dt
= wxDateTime::Now());
293 bool WXZIPFIX
CopyEntry(wxZipEntry
*entry
, wxZipInputStream
& inputStream
);
294 bool WXZIPFIX
CopyArchiveMetaData(wxZipInputStream
& inputStream
);
296 void WXZIPFIX
Sync();
297 bool WXZIPFIX
CloseEntry();
298 bool WXZIPFIX
Close();
300 void SetComment(const wxString
& comment
) { m_Comment
= comment
; }
302 int GetLevel() const { return m_level
; }
303 void WXZIPFIX
SetLevel(int level
);
306 virtual size_t WXZIPFIX
OnSysWrite(const void *buffer
, size_t size
);
307 virtual wxFileOffset
OnSysTell() const { return m_entrySize
; }
309 // this protected interface isn't yet finalised
310 struct Buffer
{ const char *m_data
; size_t m_size
; };
311 virtual wxOutputStream
* WXZIPFIX
OpenCompressor(wxOutputStream
& stream
,
313 const Buffer bufs
[]);
314 virtual bool WXZIPFIX
CloseCompressor(wxOutputStream
*comp
);
316 bool IsParentSeekable() const
317 { return m_offsetAdjustment
!= wxInvalidOffset
; }
320 void Init(int level
);
322 bool WXZIPFIX
PutNextEntry(wxArchiveEntry
*entry
);
323 bool WXZIPFIX
CopyEntry(wxArchiveEntry
*entry
, wxArchiveInputStream
& stream
);
324 bool WXZIPFIX
CopyArchiveMetaData(wxArchiveInputStream
& stream
);
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
;
348 bool m_endrecWritten
;
350 wxDECLARE_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 wxDECLARE_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__