]> git.saurik.com Git - wxWidgets.git/blob - include/wx/zipstrm.h
Sanity check.
[wxWidgets.git] / include / wx / zipstrm.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: zipstrm.h
3 // Purpose: Streams for Zip files
4 // Author: Mike Wetherell
5 // RCS-ID: $Id$
6 // Copyright: (c) Mike Wetherell
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifndef _WX_WXZIPSTREAM_H__
11 #define _WX_WXZIPSTREAM_H__
12
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma interface "zipstrm.h"
15 #endif
16
17 #include "wx/defs.h"
18
19 #if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
20
21 #include "wx/archive.h"
22 #include "wx/hashmap.h"
23 #include "wx/filename.h"
24
25
26 /////////////////////////////////////////////////////////////////////////////
27 // constants
28
29 // Compression Method, only 0 (store) and 8 (deflate) are supported here
30 //
31 enum 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 //
52 enum 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 //
77 enum 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 //
90 enum 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 //
108 class WXDLLIMPEXP_BASE wxZipEntry;
109 class WXDLLIMPEXP_BASE wxZipInputStream;
110
111
112 /////////////////////////////////////////////////////////////////////////////
113 // wxZipNotifier
114
115 class WXDLLIMPEXP_BASE wxZipNotifier
116 {
117 public:
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
127 class WXDLLIMPEXP_BASE wxZipEntry : public wxArchiveEntry
128 {
129 public:
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 = (wxUint16)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);
186
187 wxZipEntry *Clone() const { return ZipClone(); }
188
189 void SetNotifier(wxZipNotifier& notifier);
190 void UnsetNotifier();
191
192 protected:
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 = (wxUint16)version; }
204 void SetOffset(wxFileOffset offset) { m_Offset = offset; }
205 void SetFlags(int flags) { m_Flags = (wxUint16)flags; }
206 void SetVersionMadeBy(int version) { m_VersionMadeBy = (wxUint8)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 = (wxUint16)start; }
211 void SetInternalAttributes(int attr) { m_InternalAttributes = (wxUint16)attr; }
212
213 virtual wxZipEntry *ZipClone() const { return new wxZipEntry(*this); }
214
215 void Notify();
216
217 private:
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;
239 wxFileOffset m_Size;
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;
254
255 friend class wxZipInputStream;
256 friend class wxZipOutputStream;
257
258 DECLARE_DYNAMIC_CLASS(wxZipEntry)
259 };
260
261
262 /////////////////////////////////////////////////////////////////////////////
263 // wxZipOutputStream
264
265 WX_DECLARE_LIST_WITH_DECL(wxZipEntry, _wxZipEntryList, class WXDLLIMPEXP_BASE);
266
267 class WXDLLIMPEXP_BASE wxZipOutputStream : public wxArchiveOutputStream
268 {
269 public:
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
296 protected:
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
309 private:
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
344 class WXDLLIMPEXP_BASE wxZipInputStream : public wxArchiveInputStream
345 {
346 public:
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
363 protected:
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
371 private:
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);
417
418 DECLARE_NO_COPY_CLASS(wxZipInputStream)
419 };
420
421
422 /////////////////////////////////////////////////////////////////////////////
423 // Iterators
424
425 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
426 typedef wxArchiveIterator<wxZipInputStream> wxZipIter;
427 typedef wxArchiveIterator<wxZipInputStream,
428 std::pair<wxString, wxZipEntry*> > wxZipPairIter;
429 #endif
430
431
432 /////////////////////////////////////////////////////////////////////////////
433 // wxZipClassFactory
434
435 class WXDLLIMPEXP_BASE wxZipClassFactory : public wxArchiveClassFactory
436 {
437 public:
438 typedef wxZipEntry entry_type;
439 typedef wxZipInputStream instream_type;
440 typedef wxZipOutputStream outstream_type;
441 typedef wxZipNotifier notifier_type;
442 #if wxUSE_STL || defined WX_TEST_ARCHIVE_ITERATOR
443 typedef wxZipIter iter_type;
444 typedef wxZipPairIter pairiter_type;
445 #endif
446
447 wxZipEntry *NewEntry() const
448 { return new wxZipEntry; }
449 wxZipInputStream *NewStream(wxInputStream& stream) const
450 { return new wxZipInputStream(stream, GetConv()); }
451 wxZipOutputStream *NewStream(wxOutputStream& stream) const
452 { return new wxZipOutputStream(stream, -1, GetConv()); }
453
454 wxString GetInternalName(const wxString& name,
455 wxPathFormat format = wxPATH_NATIVE) const
456 { return wxZipEntry::GetInternalName(name, format); }
457
458 protected:
459 wxArchiveEntry *DoNewEntry() const
460 { return NewEntry(); }
461 wxArchiveInputStream *DoNewStream(wxInputStream& stream) const
462 { return NewStream(stream); }
463 wxArchiveOutputStream *DoNewStream(wxOutputStream& stream) const
464 { return NewStream(stream); }
465
466 private:
467 DECLARE_DYNAMIC_CLASS(wxZipClassFactory)
468 };
469
470
471 /////////////////////////////////////////////////////////////////////////////
472 // wxZipEntry inlines
473
474 inline bool wxZipEntry::IsText() const
475 {
476 return (m_InternalAttributes & TEXT_ATTR) != 0;
477 }
478
479 inline bool wxZipEntry::IsDir() const
480 {
481 return (m_ExternalAttributes & wxZIP_A_SUBDIR) != 0;
482 }
483
484 inline bool wxZipEntry::IsReadOnly() const
485 {
486 return (m_ExternalAttributes & wxZIP_A_RDONLY) != 0;
487 }
488
489 inline bool wxZipEntry::IsMadeByUnix() const
490 {
491 const int pattern =
492 (1 << wxZIP_SYSTEM_OPENVMS) |
493 (1 << wxZIP_SYSTEM_UNIX) |
494 (1 << wxZIP_SYSTEM_ATARI_ST) |
495 (1 << wxZIP_SYSTEM_ACORN_RISC) |
496 (1 << wxZIP_SYSTEM_BEOS) | (1 << wxZIP_SYSTEM_TANDEM);
497
498 // note: some unix zippers put madeby = dos
499 return (m_SystemMadeBy == wxZIP_SYSTEM_MSDOS
500 && (m_ExternalAttributes & ~0xFFFF))
501 || ((pattern >> m_SystemMadeBy) & 1);
502 }
503
504 inline void wxZipEntry::SetIsText(bool isText)
505 {
506 if (isText)
507 m_InternalAttributes |= TEXT_ATTR;
508 else
509 m_InternalAttributes &= ~TEXT_ATTR;
510 }
511
512 inline void wxZipEntry::SetIsReadOnly(bool isReadOnly)
513 {
514 if (isReadOnly)
515 SetMode(GetMode() & ~0222);
516 else
517 SetMode(GetMode() | 0200);
518 }
519
520 inline void wxZipEntry::SetName(const wxString& name,
521 wxPathFormat format /*=wxPATH_NATIVE*/)
522 {
523 bool isDir;
524 m_Name = GetInternalName(name, format, &isDir);
525 SetIsDir(isDir);
526 }
527
528
529 #endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM
530
531 #endif // _WX_WXZIPSTREAM_H__