]> git.saurik.com Git - wxWidgets.git/blame - include/wx/zipstrm.h
added ZIP classes by M.J.Wetherell (patch 1030239)
[wxWidgets.git] / include / wx / zipstrm.h
CommitLineData
5526e819 1/////////////////////////////////////////////////////////////////////////////
00375592
VZ
2// Name: zipstrm.h
3// Purpose: Streams for Zip files
4// Author: Mike Wetherell
5// RCS-ID: $Id$
6// Copyright: (c) Mike Wetherell
65571936 7// Licence: wxWindows licence
5526e819
VS
8/////////////////////////////////////////////////////////////////////////////
9
00375592
VZ
10#ifndef _WX_WXZIPSTREAM_H__
11#define _WX_WXZIPSTREAM_H__
5526e819 12
12028905 13#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
5279a24d 14#pragma interface "zipstrm.h"
5526e819
VS
15#endif
16
d1af991f 17#include "wx/defs.h"
5526e819 18
00375592 19#if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
d1af991f 20
00375592
VZ
21#include "wx/archive.h"
22#include "wx/hashmap.h"
23#include "wx/filename.h"
5526e819 24
5526e819 25
00375592
VZ
26/////////////////////////////////////////////////////////////////////////////
27// constants
28
29// Compression Method, only 0 (store) and 8 (deflate) are supported here
30//
31enum wxZipMethod
32{
33 wxZIP_METHOD_STORE,
34 wxZIP_METHOD_SHRINK,
35 wxZIP_METHOD_REDUCE1,
36 wxZIP_METHOD_REDUCE2,
37 wxZIP_METHOD_REDUCE3,
38 wxZIP_METHOD_REDUCE4,
39 wxZIP_METHOD_IMPLODE,
40 wxZIP_METHOD_TOKENIZE,
41 wxZIP_METHOD_DEFLATE,
42 wxZIP_METHOD_DEFLATE64,
43 wxZIP_METHOD_BZIP2 = 12,
44 wxZIP_METHOD_DEFAULT = 0xffff
45};
46
47// Originating File-System.
48//
49// These are Pkware's values. Note that Info-zip disagree on some of them,
50// most notably NTFS.
51//
52enum wxZipSystem
53{
54 wxZIP_SYSTEM_MSDOS,
55 wxZIP_SYSTEM_AMIGA,
56 wxZIP_SYSTEM_OPENVMS,
57 wxZIP_SYSTEM_UNIX,
58 wxZIP_SYSTEM_VM_CMS,
59 wxZIP_SYSTEM_ATARI_ST,
60 wxZIP_SYSTEM_OS2_HPFS,
61 wxZIP_SYSTEM_MACINTOSH,
62 wxZIP_SYSTEM_Z_SYSTEM,
63 wxZIP_SYSTEM_CPM,
64 wxZIP_SYSTEM_WINDOWS_NTFS,
65 wxZIP_SYSTEM_MVS,
66 wxZIP_SYSTEM_VSE,
67 wxZIP_SYSTEM_ACORN_RISC,
68 wxZIP_SYSTEM_VFAT,
69 wxZIP_SYSTEM_ALTERNATE_MVS,
70 wxZIP_SYSTEM_BEOS,
71 wxZIP_SYSTEM_TANDEM,
72 wxZIP_SYSTEM_OS_400
73};
74
75// Dos/Win file attributes
76//
77enum wxZipAttributes
78{
79 wxZIP_A_RDONLY = 0x01,
80 wxZIP_A_HIDDEN = 0x02,
81 wxZIP_A_SYSTEM = 0x04,
82 wxZIP_A_SUBDIR = 0x10,
83 wxZIP_A_ARCH = 0x20,
84
85 wxZIP_A_MASK = 0x37
86};
87
88// Values for the flags field in the zip headers
89//
90enum wxZipFlags
91{
92 wxZIP_ENCRYPTED = 0x0001,
93 wxZIP_DEFLATE_NORMAL = 0x0000, // normal compression
94 wxZIP_DEFLATE_EXTRA = 0x0002, // extra compression
95 wxZIP_DEFLATE_FAST = 0x0004, // fast compression
96 wxZIP_DEFLATE_SUPERFAST = 0x0006, // superfast compression
97 wxZIP_DEFLATE_MASK = 0x0006,
98 wxZIP_SUMS_FOLLOW = 0x0008, // crc and sizes come after the data
99 wxZIP_ENHANCED = 0x0010,
100 wxZIP_PATCH = 0x0020,
101 wxZIP_STRONG_ENC = 0x0040,
102 wxZIP_UNUSED = 0x0F80,
103 wxZIP_RESERVED = 0xF000
104};
105
106// Forward decls
107//
108class WXDLLIMPEXP_BASE wxZipEntry;
109class WXDLLIMPEXP_BASE wxZipInputStream;
110
111
112/////////////////////////////////////////////////////////////////////////////
113// wxZipNotifier
5526e819 114
00375592 115class WXDLLIMPEXP_BASE wxZipNotifier
5526e819 116{
f6bcfd97 117public:
00375592
VZ
118 virtual ~wxZipNotifier() { }
119
120 virtual void OnEntryUpdated(wxZipEntry& entry) = 0;
121};
122
123
124/////////////////////////////////////////////////////////////////////////////
125// Zip Entry - holds the meta data for a file in the zip
126
127class WXDLLIMPEXP_BASE wxZipEntry : public wxArchiveEntry
128{
129public:
130 wxZipEntry(const wxString& name = wxEmptyString,
131 const wxDateTime& dt = wxDateTime::Now(),
132 wxFileOffset size = wxInvalidOffset);
133 virtual ~wxZipEntry();
134
135 wxZipEntry(const wxZipEntry& entry);
136 wxZipEntry& operator=(const wxZipEntry& entry);
137
138 // Get accessors
139 wxDateTime GetDateTime() const { return m_DateTime; }
140 wxFileOffset GetSize() const { return m_Size; }
141 wxFileOffset GetOffset() const { return m_Offset; }
142 wxString GetInternalName() const { return m_Name; }
143 int GetMethod() const { return m_Method; }
144 int GetFlags() const { return m_Flags; }
145 wxUint32 GetCrc() const { return m_Crc; }
146 wxFileOffset GetCompressedSize() const { return m_CompressedSize; }
147 int GetSystemMadeBy() const { return m_SystemMadeBy; }
148 wxString GetComment() const { return m_Comment; }
149 wxUint32 GetExternalAttributes() const { return m_ExternalAttributes; }
150 wxPathFormat GetInternalFormat() const { return wxPATH_UNIX; }
151 int GetMode() const;
152 const char *GetLocalExtra() const;
153 size_t GetLocalExtraLen() const;
154 const char *GetExtra() const;
155 size_t GetExtraLen() const;
156 wxString GetName(wxPathFormat format = wxPATH_NATIVE) const;
157
158 // is accessors
159 inline bool IsDir() const;
160 inline bool IsText() const;
161 inline bool IsReadOnly() const;
162 inline bool IsMadeByUnix() const;
163
164 // set accessors
165 void SetDateTime(const wxDateTime& dt) { m_DateTime = dt; }
166 void SetSize(wxFileOffset size) { m_Size = size; }
167 void SetMethod(int method) { m_Method = method; }
168 void SetComment(const wxString& comment) { m_Comment = comment; }
169 void SetExternalAttributes(wxUint32 attr ) { m_ExternalAttributes = attr; }
170 void SetSystemMadeBy(int system);
171 void SetMode(int mode);
172 void SetExtra(const char *extra, size_t len);
173 void SetLocalExtra(const char *extra, size_t len);
174
175 inline void SetName(const wxString& name,
176 wxPathFormat format = wxPATH_NATIVE);
177
178 static wxString GetInternalName(const wxString& name,
179 wxPathFormat format = wxPATH_NATIVE,
180 bool *pIsDir = NULL);
181
182 // set is accessors
183 void SetIsDir(bool isDir = true);
184 inline void SetIsReadOnly(bool isReadOnly = true);
185 inline void SetIsText(bool isText = true);
f6bcfd97 186
00375592
VZ
187 wxZipEntry *Clone() const { return ZipClone(); }
188
189 void SetNotifier(wxZipNotifier& notifier);
190 void UnsetNotifier();
f6bcfd97
BP
191
192protected:
00375592
VZ
193 // Internal attributes
194 enum { TEXT_ATTR = 1 };
195
196 // protected Get accessors
197 int GetVersionNeeded() const { return m_VersionNeeded; }
198 wxFileOffset GetKey() const { return m_Key; }
199 int GetVersionMadeBy() const { return m_VersionMadeBy; }
200 int GetDiskStart() const { return m_DiskStart; }
201 int GetInternalAttributes() const { return m_InternalAttributes; }
202
203 void SetVersionNeeded(int version) { m_VersionNeeded = version; }
204 void SetOffset(wxFileOffset offset) { m_Offset = offset; }
205 void SetFlags(int flags) { m_Flags = flags; }
206 void SetVersionMadeBy(int version) { m_VersionMadeBy = version; }
207 void SetCrc(wxUint32 crc) { m_Crc = crc; }
208 void SetCompressedSize(wxFileOffset size) { m_CompressedSize = size; }
209 void SetKey(wxFileOffset offset) { m_Key = offset; }
210 void SetDiskStart(int start) { m_DiskStart = start; }
211 void SetInternalAttributes(int attr) { m_InternalAttributes = attr; }
212
213 virtual wxZipEntry *ZipClone() const { return new wxZipEntry(*this); }
214
215 void Notify();
f6bcfd97
BP
216
217private:
00375592
VZ
218 wxArchiveEntry* DoClone() const { return ZipClone(); }
219
220 size_t ReadLocal(wxInputStream& stream, wxMBConv& conv);
221 size_t WriteLocal(wxOutputStream& stream, wxMBConv& conv) const;
222
223 size_t ReadCentral(wxInputStream& stream, wxMBConv& conv);
224 size_t WriteCentral(wxOutputStream& stream, wxMBConv& conv) const;
225
226 size_t ReadDescriptor(wxInputStream& stream);
227 size_t WriteDescriptor(wxOutputStream& stream, wxUint32 crc,
228 wxFileOffset compressedSize, wxFileOffset size);
229
230 wxUint8 m_SystemMadeBy; // one of enum wxZipSystem
231 wxUint8 m_VersionMadeBy; // major * 10 + minor
232
233 wxUint16 m_VersionNeeded; // ver needed to extract (20 i.e. v2.0)
234 wxUint16 m_Flags;
235 wxUint16 m_Method; // compression method (one of wxZipMethod)
236 wxDateTime m_DateTime;
237 wxUint32 m_Crc;
238 wxFileOffset m_CompressedSize;
588066b7 239 wxFileOffset m_Size;
00375592
VZ
240 wxString m_Name; // in internal format
241 wxFileOffset m_Key; // the original offset for copied entries
242 wxFileOffset m_Offset; // file offset of the entry
243
244 wxString m_Comment;
245 wxUint16 m_DiskStart; // for multidisk archives, not unsupported
246 wxUint16 m_InternalAttributes; // bit 0 set for text files
247 wxUint32 m_ExternalAttributes; // system specific depends on SystemMadeBy
248
249 class wxZipMemory *m_Extra;
250 class wxZipMemory *m_LocalExtra;
251
252 wxZipNotifier *m_zipnotifier;
253 class wxZipWeakLinks *m_backlink;
f6bcfd97 254
00375592
VZ
255 friend class wxZipInputStream;
256 friend class wxZipOutputStream;
257
258 DECLARE_DYNAMIC_CLASS(wxZipEntry)
259};
260
261
262/////////////////////////////////////////////////////////////////////////////
263// wxZipOutputStream
264
265WX_DECLARE_LIST_WITH_DECL(wxZipEntry, _wxZipEntryList, class WXDLLIMPEXP_BASE);
266
267class WXDLLIMPEXP_BASE wxZipOutputStream : public wxArchiveOutputStream
268{
269public:
270 wxZipOutputStream(wxOutputStream& stream,
271 int level = -1,
272 wxMBConv& conv = wxConvLocal);
273 virtual ~wxZipOutputStream();
274
275 bool PutNextEntry(wxZipEntry *entry) { return DoCreate(entry); }
276
277 bool PutNextEntry(const wxString& name,
278 const wxDateTime& dt = wxDateTime::Now(),
279 wxFileOffset size = wxInvalidOffset);
280
281 bool PutNextDirEntry(const wxString& name,
282 const wxDateTime& dt = wxDateTime::Now());
283
284 bool CopyEntry(wxZipEntry *entry, wxZipInputStream& inputStream);
285 bool CopyArchiveMetaData(wxZipInputStream& inputStream);
286
287 void Sync();
288 bool CloseEntry();
289 bool Close();
290
291 void SetComment(const wxString& comment) { m_Comment = comment; }
292
293 int GetLevel() const { return m_level; }
294 void SetLevel(int level);
295
296protected:
297 virtual size_t OnSysWrite(const void *buffer, size_t size);
298 virtual wxFileOffset OnSysTell() const { return m_entrySize; }
299
300 struct Buffer { const char *m_data; size_t m_size; };
301 virtual wxOutputStream *OpenCompressor(wxOutputStream& stream,
302 wxZipEntry& entry,
303 const Buffer bufs[]);
304 virtual bool CloseCompressor(wxOutputStream *comp);
305
306 bool IsParentSeekable() const { return m_offsetAdjustment
307 != wxInvalidOffset; }
308
309private:
310 bool PutNextEntry(wxArchiveEntry *entry);
311 bool CopyEntry(wxArchiveEntry *entry, wxArchiveInputStream& stream);
312 bool CopyArchiveMetaData(wxArchiveInputStream& stream);
313
314 bool IsOpened() const { return m_comp || m_pending; }
315
316 bool DoCreate(wxZipEntry *entry, bool raw = false);
317 void CreatePendingEntry(const void *buffer, size_t size);
318 void CreatePendingEntry();
319
320 class wxStoredOutputStream *m_store;
321 class wxZlibOutputStream2 *m_deflate;
322 class wxZipStreamLink *m_backlink;
323 _wxZipEntryList m_entries;
324 char *m_initialData;
325 size_t m_initialSize;
326 wxZipEntry *m_pending;
327 bool m_raw;
328 wxFileOffset m_headerOffset;
329 size_t m_headerSize;
330 wxFileOffset m_entrySize;
331 wxUint32 m_crcAccumulator;
332 wxOutputStream *m_comp;
333 int m_level;
334 wxFileOffset m_offsetAdjustment;
335 wxString m_Comment;
336
337 DECLARE_NO_COPY_CLASS(wxZipOutputStream)
338};
339
340
341/////////////////////////////////////////////////////////////////////////////
342// wxZipInputStream
343
344class WXDLLIMPEXP_BASE wxZipInputStream : public wxArchiveInputStream
345{
346public:
347 typedef wxZipEntry entry_type;
348
349 wxZipInputStream(wxInputStream& stream, wxMBConv& conv = wxConvLocal);
350 wxZipInputStream(const wxString& archive, const wxString& file);
351 virtual ~wxZipInputStream();
352
353 bool OpenEntry(wxZipEntry& entry) { return DoOpen(&entry); }
354 bool CloseEntry();
355
356 wxZipEntry *GetNextEntry();
357
358 wxString GetComment();
359 int GetTotalEntries();
360
361 virtual wxFileOffset GetLength() const { return m_entry.GetSize(); }
362
363protected:
364 size_t OnSysRead(void *buffer, size_t size);
365 wxFileOffset OnSysTell() const { return m_decomp ? m_decomp->TellI() : 0; }
366 wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
367
368 virtual wxInputStream *OpenDecompressor(wxInputStream& stream);
369 virtual bool CloseDecompressor(wxInputStream *decomp);
370
371private:
372 void Init();
373 wxInputStream& OpenFile(const wxString& archive);
374
375 wxArchiveEntry *DoGetNextEntry() { return GetNextEntry(); }
376
377 bool OpenEntry(wxArchiveEntry& entry);
378
379 wxStreamError ReadLocal(bool readEndRec = false);
380 wxStreamError ReadCentral();
381
382 wxUint32 ReadSignature();
383 bool FindEndRecord();
384 bool LoadEndRecord();
385
386 bool AtHeader() const { return m_headerSize == 0; }
387 bool AfterHeader() const { return m_headerSize > 0 && !m_decomp; }
388 bool IsOpened() const { return m_decomp != NULL; }
389
390 wxZipStreamLink *MakeLink(wxZipOutputStream *out);
391
392 bool DoOpen(wxZipEntry *entry = NULL, bool raw = false);
393 bool OpenDecompressor(bool raw = false);
394
395 class wxStoredInputStream *m_store;
396 class wxZlibInputStream2 *m_inflate;
397 class wxRawInputStream *m_rawin;
398 class wxFFileInputStream *m_ffile;
399 wxZipEntry m_entry;
400 bool m_raw;
401 size_t m_headerSize;
402 wxUint32 m_crcAccumulator;
403 wxInputStream *m_decomp;
404 bool m_parentSeekable;
405 class wxZipWeakLinks *m_weaklinks;
406 class wxZipStreamLink *m_streamlink;
407 wxFileOffset m_offsetAdjustment;
408 wxFileOffset m_position;
409 wxUint32 m_signature;
410 size_t m_TotalEntries;
411 wxString m_Comment;
412
413 friend bool wxZipOutputStream::CopyEntry(
414 wxZipEntry *entry, wxZipInputStream& inputStream);
415 friend bool wxZipOutputStream::CopyArchiveMetaData(
416 wxZipInputStream& inputStream);
22f3361e
VZ
417
418 DECLARE_NO_COPY_CLASS(wxZipInputStream)
5526e819
VS
419};
420
421
00375592
VZ
422/////////////////////////////////////////////////////////////////////////////
423// wxZipClassFactory
5526e819 424
00375592
VZ
425class WXDLLIMPEXP_BASE wxZipClassFactory : public wxArchiveClassFactory
426{
427public:
428 wxZipEntry *NewEntry() const
429 { return new wxZipEntry; }
430 wxZipInputStream *NewStream(wxInputStream& stream) const
431 { return new wxZipInputStream(stream, GetConv()); }
432 wxZipOutputStream *NewStream(wxOutputStream& stream) const
433 { return new wxZipOutputStream(stream, -1, GetConv()); }
434
435 wxString GetInternalName(const wxString& name,
436 wxPathFormat format = wxPATH_NATIVE) const
437 { return wxZipEntry::GetInternalName(name, format); }
438
439protected:
440 wxArchiveEntry *DoNewEntry() const
441 { return NewEntry(); }
442 wxArchiveInputStream *DoNewStream(wxInputStream& stream) const
443 { return NewStream(stream); }
444 wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const
445 { return NewStream(stream); }
446
447private:
448 DECLARE_DYNAMIC_CLASS(wxZipClassFactory)
449};
450
451
452/////////////////////////////////////////////////////////////////////////////
453// Iterators
454
455#if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
456typedef wxArchiveIterator<wxZipInputStream> wxZipIter;
457typedef wxArchiveIterator<wxZipInputStream,
458 std::pair<wxString, wxZipEntry*> > wxZipPairIter;
cab1a605 459#endif
00375592
VZ
460
461
462/////////////////////////////////////////////////////////////////////////////
463// wxZipEntry inlines
464
465bool wxZipEntry::IsText() const
466{
467 return (m_InternalAttributes & TEXT_ATTR) != 0;
468}
469
470bool wxZipEntry::IsDir() const
471{
472 return (m_ExternalAttributes & wxZIP_A_SUBDIR) != 0;
473}
474
475bool wxZipEntry::IsReadOnly() const
476{
477 return (m_ExternalAttributes & wxZIP_A_RDONLY) != 0;
478}
479
480bool wxZipEntry::IsMadeByUnix() const
481{
482 const int pattern =
483 (1 << wxZIP_SYSTEM_OPENVMS) |
484 (1 << wxZIP_SYSTEM_UNIX) |
485 (1 << wxZIP_SYSTEM_ATARI_ST) |
486 (1 << wxZIP_SYSTEM_ACORN_RISC) |
487 (1 << wxZIP_SYSTEM_BEOS) | (1 << wxZIP_SYSTEM_TANDEM);
488
489 // note: some unix zippers put madeby = dos
490 return (m_SystemMadeBy == wxZIP_SYSTEM_MSDOS
491 && (m_ExternalAttributes & ~0xFFFF))
492 || ((pattern >> m_SystemMadeBy) & 1);
493}
494
495void wxZipEntry::SetIsText(bool isText)
496{
497 if (isText)
498 m_InternalAttributes |= TEXT_ATTR;
499 else
500 m_InternalAttributes &= ~TEXT_ATTR;
501}
502
503void wxZipEntry::SetIsReadOnly(bool isReadOnly)
504{
505 if (isReadOnly)
506 SetMode(GetMode() & ~0222);
507 else
508 SetMode(GetMode() | 0200);
509}
510
511void wxZipEntry::SetName(const wxString& name,
512 wxPathFormat format /*=wxPATH_NATIVE*/)
513{
514 bool isDir;
515 m_Name = GetInternalName(name, format, &isDir);
516 SetIsDir(isDir);
517}
518
519
520#endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
521
522#endif // _WX_WXZIPSTREAM_H__