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