X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f44eaed6506856d3aece4b75d13253810a7a9edb..677856c9ef3e4d4f0bb4b9acf71fd8f6a90a2f01:/src/common/zipstrm.cpp diff --git a/src/common/zipstrm.cpp b/src/common/zipstrm.cpp index 0242e35799..92d972002c 100644 --- a/src/common/zipstrm.cpp +++ b/src/common/zipstrm.cpp @@ -7,10 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "zipstrm.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -34,7 +30,7 @@ #include "wx/buffer.h" #include "wx/ptr_scpd.h" #include "wx/wfstream.h" -#include "wx/html/forcelnk.h" +#include "wx/link.h" #include "zlib.h" // value for the 'version needed to extract' field (20 means 2.0) @@ -82,7 +78,7 @@ enum { IMPLEMENT_DYNAMIC_CLASS(wxZipEntry, wxArchiveEntry) IMPLEMENT_DYNAMIC_CLASS(wxZipClassFactory, wxArchiveClassFactory) -FORCE_LINK_ME(zipstrm) +wxFORCE_LINK_THIS_MODULE(zipstrm) ///////////////////////////////////////////////////////////////////////////// @@ -168,7 +164,8 @@ wxStoredInputStream::wxStoredInputStream(wxInputStream& stream) size_t wxStoredInputStream::OnSysRead(void *buffer, size_t size) { - size_t count = wxMin(size, (size_t)(m_len - m_pos)); + size_t count = wx_truncate_cast(size_t, + wxMin(size + wxFileOffset(0), m_len - m_pos + size_t(0))); count = m_parent_i_stream->Read(buffer, count).LastRead(); m_pos += count; @@ -470,7 +467,6 @@ class wxZipMemory { public: wxZipMemory() : m_data(NULL), m_size(0), m_capacity(0), m_ref(1) { } - ~wxZipMemory() { delete m_data; } wxZipMemory *AddRef() { m_ref++; return this; } void Release() { if (--m_ref == 0) delete this; } @@ -482,6 +478,7 @@ public: wxZipMemory *Unique(size_t size); private: + ~wxZipMemory() { delete [] m_data; } char *m_data; size_t m_size; @@ -501,7 +498,7 @@ wxZipMemory *wxZipMemory::Unique(size_t size) } if (zm->m_capacity < size) { - delete zm->m_data; + delete [] zm->m_data; zm->m_data = new char[size]; zm->m_capacity = size; } @@ -542,13 +539,12 @@ static void Unique(wxZipMemory*& zm, size_t size) // Collection of weak references to entries WX_DECLARE_HASH_MAP(long, wxZipEntry*, wxIntegerHash, - wxIntegerEqual, _wxOffsetZipEntryMap); + wxIntegerEqual, wx__OffsetZipEntryMap); class wxZipWeakLinks { public: wxZipWeakLinks() : m_ref(1) { } - ~wxZipWeakLinks() { wxASSERT(IsEmpty()); } void Release(const wxZipInputStream* WXUNUSED(x)) { if (--m_ref == 0) delete this; } @@ -557,27 +553,30 @@ public: wxZipWeakLinks *AddEntry(wxZipEntry *entry, wxFileOffset key); void RemoveEntry(wxFileOffset key) - { m_entries.erase((_wxOffsetZipEntryMap::key_type)key); } + { m_entries.erase(wx_truncate_cast(key_type, key)); } wxZipEntry *GetEntry(wxFileOffset key) const; bool IsEmpty() const { return m_entries.empty(); } private: + typedef wx__OffsetZipEntryMap::key_type key_type; + + ~wxZipWeakLinks() { wxASSERT(IsEmpty()); } int m_ref; - _wxOffsetZipEntryMap m_entries; + wx__OffsetZipEntryMap m_entries; }; wxZipWeakLinks *wxZipWeakLinks::AddEntry(wxZipEntry *entry, wxFileOffset key) { - m_entries[(_wxOffsetZipEntryMap::key_type)key] = entry; + m_entries[wx_truncate_cast(key_type, key)] = entry; m_ref++; return this; } wxZipEntry *wxZipWeakLinks::GetEntry(wxFileOffset key) const { - _wxOffsetZipEntryMap::const_iterator it = - m_entries.find((_wxOffsetZipEntryMap::key_type)key); + wx__OffsetZipEntryMap::const_iterator it = + m_entries.find(wx_truncate_cast(key_type, key)); return it != m_entries.end() ? it->second : NULL; } @@ -589,7 +588,7 @@ wxZipEntry::wxZipEntry( const wxString& name /*=wxEmptyString*/, const wxDateTime& dt /*=wxDateTime::Now()*/, wxFileOffset size /*=wxInvalidOffset*/) - : + : m_SystemMadeBy(wxZIP_SYSTEM_MSDOS), m_VersionMadeBy(wxMAJOR_VERSION * 10 + wxMINOR_VERSION), m_VersionNeeded(VERSION_NEEDED_TO_EXTRACT), @@ -680,6 +679,7 @@ wxString wxZipEntry::GetName(wxPathFormat format /*=wxPATH_NATIVE*/) const { bool isDir = IsDir() && !m_Name.empty(); + // optimisations for common (and easy) cases switch (wxFileName::GetFormat(format)) { case wxPATH_DOS: { @@ -897,19 +897,21 @@ size_t wxZipEntry::WriteLocal(wxOutputStream& stream, wxMBConv& conv) const const wxWX2MBbuf name_buf = conv.cWX2MB(unixName); const char *name = name_buf; if (!name) name = ""; - wxUint16 nameLen = (wxUint16)strlen(name); + wxUint16 nameLen = wx_truncate_cast(wxUint16, strlen(name)); wxDataOutputStream ds(stream); ds << m_VersionNeeded << m_Flags << m_Method; ds.Write32(GetDateTime().GetAsDOS()); - + ds.Write32(m_Crc); - ds.Write32(m_CompressedSize != wxInvalidOffset ? (wxUint32)m_CompressedSize : 0); - ds.Write32(m_Size != wxInvalidOffset ? (wxUint32)m_Size : 0); + ds.Write32(m_CompressedSize != wxInvalidOffset ? + wx_truncate_cast(wxUint32, m_CompressedSize) : 0); + ds.Write32(m_Size != wxInvalidOffset ? + wx_truncate_cast(wxUint32, m_Size) : 0); ds << nameLen; - wxUint16 extraLen = (wxUint16)GetLocalExtraLen(); + wxUint16 extraLen = wx_truncate_cast(wxUint16, GetLocalExtraLen()); ds.Write16(extraLen); stream.Write(name, nameLen); @@ -938,7 +940,7 @@ size_t wxZipEntry::ReadCentral(wxInputStream& stream, wxMBConv& conv) ds >> nameLen >> extraLen >> commentLen >> m_DiskStart >> m_InternalAttributes >> m_ExternalAttributes; SetOffset(ds.Read32()); - + SetName(ReadString(stream, nameLen, conv), wxPATH_UNIX); if (extraLen || GetExtraLen()) { @@ -961,32 +963,32 @@ size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const const wxWX2MBbuf name_buf = conv.cWX2MB(unixName); const char *name = name_buf; if (!name) name = ""; - wxUint16 nameLen = (wxUint16)strlen(name); + wxUint16 nameLen = wx_truncate_cast(wxUint16, strlen(name)); const wxWX2MBbuf comment_buf = conv.cWX2MB(m_Comment); const char *comment = comment_buf; if (!comment) comment = ""; - wxUint16 commentLen = (wxUint16)strlen(comment); + wxUint16 commentLen = wx_truncate_cast(wxUint16, strlen(comment)); - wxUint16 extraLen = (wxUint16)GetExtraLen(); + wxUint16 extraLen = wx_truncate_cast(wxUint16, GetExtraLen()); wxDataOutputStream ds(stream); ds << CENTRAL_MAGIC << m_VersionMadeBy << m_SystemMadeBy; - ds.Write16((wxUint16)GetVersionNeeded()); - ds.Write16((wxUint16)GetFlags()); - ds.Write16((wxUint16)GetMethod()); + ds.Write16(wx_truncate_cast(wxUint16, GetVersionNeeded())); + ds.Write16(wx_truncate_cast(wxUint16, GetFlags())); + ds.Write16(wx_truncate_cast(wxUint16, GetMethod())); ds.Write32(GetDateTime().GetAsDOS()); ds.Write32(GetCrc()); - ds.Write32((wxUint32)GetCompressedSize()); - ds.Write32((wxUint32)GetSize()); + ds.Write32(wx_truncate_cast(wxUint32, GetCompressedSize())); + ds.Write32(wx_truncate_cast(wxUint32, GetSize())); ds.Write16(nameLen); ds.Write16(extraLen); ds << commentLen << m_DiskStart << m_InternalAttributes - << m_ExternalAttributes << (wxUint32)GetOffset(); - + << m_ExternalAttributes << wx_truncate_cast(wxUint32, GetOffset()); + stream.Write(name, nameLen); if (extraLen) stream.Write(GetExtra(), extraLen); @@ -1003,7 +1005,7 @@ size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const size_t wxZipEntry::ReadDescriptor(wxInputStream& stream) { wxDataInputStream ds(stream); - + m_Crc = ds.Read32(); m_CompressedSize = ds.Read32(); m_Size = ds.Read32(); @@ -1015,7 +1017,7 @@ size_t wxZipEntry::ReadDescriptor(wxInputStream& stream) stream.Read(buf, sizeof(buf)); wxUint32 u1 = CrackUint32(buf); wxUint32 u2 = CrackUint32(buf + 4); - + // look for the signature of the following record to decide which if ((u1 == LOCAL_MAGIC || u1 == CENTRAL_MAGIC) && (u2 != LOCAL_MAGIC && u2 != CENTRAL_MAGIC)) @@ -1027,7 +1029,7 @@ size_t wxZipEntry::ReadDescriptor(wxInputStream& stream) { // it's an info-zip record as expected stream.Ungetch(buf + 4, sizeof(buf) - 4); - m_Crc = (wxUint32)m_CompressedSize; + m_Crc = wx_truncate_cast(wxUint32, m_CompressedSize); m_CompressedSize = m_Size; m_Size = u1; return SUMS_SIZE + 4; @@ -1047,8 +1049,8 @@ size_t wxZipEntry::WriteDescriptor(wxOutputStream& stream, wxUint32 crc, wxDataOutputStream ds(stream); ds.Write32(crc); - ds.Write32((wxUint32)compressedSize); - ds.Write32((wxUint32)size); + ds.Write32(wx_truncate_cast(wxUint32, compressedSize)); + ds.Write32(wx_truncate_cast(wxUint32, size)); return SUMS_SIZE; } @@ -1070,13 +1072,20 @@ public: wxFileOffset GetOffset() const { return m_Offset; } wxString GetComment() const { return m_Comment; } - void SetDiskNumber(int num) { m_DiskNumber = (wxUint16)num; } - void SetStartDisk(int num) { m_StartDisk = (wxUint16)num; } - void SetEntriesHere(int num) { m_EntriesHere = (wxUint16)num; } - void SetTotalEntries(int num) { m_TotalEntries = (wxUint16)num; } - void SetSize(wxFileOffset size) { m_Size = (wxUint32)size; } - void SetOffset(wxFileOffset offset) { m_Offset = (wxUint32)offset; } - void SetComment(const wxString& comment) { m_Comment = comment; } + void SetDiskNumber(int num) + { m_DiskNumber = wx_truncate_cast(wxUint16, num); } + void SetStartDisk(int num) + { m_StartDisk = wx_truncate_cast(wxUint16, num); } + void SetEntriesHere(int num) + { m_EntriesHere = wx_truncate_cast(wxUint16, num); } + void SetTotalEntries(int num) + { m_TotalEntries = wx_truncate_cast(wxUint16, num); } + void SetSize(wxFileOffset size) + { m_Size = wx_truncate_cast(wxUint32, size); } + void SetOffset(wxFileOffset offset) + { m_Offset = wx_truncate_cast(wxUint32, offset); } + void SetComment(const wxString& comment) + { m_Comment = comment; } bool Read(wxInputStream& stream, wxMBConv& conv); bool Write(wxOutputStream& stream, wxMBConv& conv) const; @@ -1147,7 +1156,6 @@ class wxZipStreamLink { public: wxZipStreamLink(wxZipOutputStream *stream) : m_ref(1), m_stream(stream) { } - ~wxZipStreamLink() { } wxZipStreamLink *AddRef() { m_ref++; return this; } wxZipOutputStream *GetOutputStream() const { return m_stream; } @@ -1158,6 +1166,7 @@ public: { m_stream = NULL; if (--m_ref == 0) delete this; } private: + ~wxZipStreamLink() { } int m_ref; wxZipOutputStream *m_stream; @@ -1167,8 +1176,9 @@ private: ///////////////////////////////////////////////////////////////////////////// // Input stream -wxDECLARE_SCOPED_PTR(wxZipEntry, _wxZipEntryPtr) -wxDEFINE_SCOPED_PTR (wxZipEntry, _wxZipEntryPtr) +// leave the default wxZipEntryPtr free for users +wxDECLARE_SCOPED_PTR(wxZipEntry, wx__ZipEntryPtr) +wxDEFINE_SCOPED_PTR (wxZipEntry, wx__ZipEntryPtr) // constructor // @@ -1176,20 +1186,22 @@ wxZipInputStream::wxZipInputStream(wxInputStream& stream, wxMBConv& conv /*=wxConvLocal*/) : wxArchiveInputStream(stream, conv) { - m_ffile = NULL; Init(); } -// Compatibility constructor +#if 1 //WXWIN_COMPATIBILITY_2_6 + +// Part of the compatibility constructor, which has been made inline to +// avoid a problem with it not being exported by mingw 3.2.3 // -wxZipInputStream::wxZipInputStream(const wxString& archive, - const wxString& file) - : wxArchiveInputStream(OpenFile(archive), wxConvLocal) +void wxZipInputStream::Init(const wxString& file) { // no error messages wxLogNull nolog; Init(); - _wxZipEntryPtr entry; + m_allowSeeking = true; + m_ffile = wx_static_cast(wxFFileInputStream*, m_parent_i_stream); + wx__ZipEntryPtr entry; if (m_ffile->Ok()) { do { @@ -1205,10 +1217,11 @@ wxZipInputStream::wxZipInputStream(const wxString& archive, wxInputStream& wxZipInputStream::OpenFile(const wxString& archive) { wxLogNull nolog; - m_ffile = new wxFFileInputStream(archive); - return *m_ffile; + return *new wxFFileInputStream(archive); } +#endif // WXWIN_COMPATIBILITY_2_6 + void wxZipInputStream::Init() { m_store = new wxStoredInputStream(*m_parent_i_stream); @@ -1225,6 +1238,10 @@ void wxZipInputStream::Init() m_signature = 0; m_TotalEntries = 0; m_lasterror = m_parent_i_stream->GetLastError(); + m_ffile = NULL; +#if 1 //WXWIN_COMPATIBILITY_2_6 + m_allowSeeking = false; +#endif } wxZipInputStream::~wxZipInputStream() @@ -1237,7 +1254,7 @@ wxZipInputStream::~wxZipInputStream() delete m_ffile; m_weaklinks->Release(this); - + if (m_streamlink) m_streamlink->Release(this); } @@ -1321,7 +1338,7 @@ bool wxZipInputStream::LoadEndRecord() m_Comment = endrec.GetComment(); // Now find the central-directory. we have the file offset of - // the CD, so look there first. + // the CD, so look there first. if (m_parent_i_stream->SeekI(endrec.GetOffset()) != wxInvalidOffset && ReadSignature() == CENTRAL_MAGIC) { m_signature = CENTRAL_MAGIC; @@ -1329,7 +1346,7 @@ bool wxZipInputStream::LoadEndRecord() m_offsetAdjustment = 0; return true; } - + // If it's not there, then it could be that the zip has been appended // to a self extractor, so take the CD size (also in endrec), subtract // it from the file offset of the end-central-directory and look there. @@ -1351,8 +1368,11 @@ bool wxZipInputStream::LoadEndRecord() // bool wxZipInputStream::FindEndRecord() { + if (!m_parent_i_stream->IsSeekable()) + return false; + // usually it's 22 bytes in size and the last thing in the file - { + { wxLogNull nolog; if (m_parent_i_stream->SeekI(-END_SIZE, wxFromEnd) == wxInvalidOffset) return false; @@ -1376,10 +1396,11 @@ bool wxZipInputStream::FindEndRecord() wxFileOffset minpos = wxMax(pos - 65535L, 0); while (pos > minpos) { - size_t len = (size_t)(pos - wxMax(pos - (BUFSIZE - 3), minpos)); + size_t len = wx_truncate_cast(size_t, + pos - wxMax(pos - (BUFSIZE - 3), minpos)); memcpy(buf.data() + len, buf, 3); pos -= len; - + if (m_parent_i_stream->SeekI(pos, wxFromStart) == wxInvalidOffset || m_parent_i_stream->Read(buf.data(), len).LastRead() != len) return false; @@ -1409,7 +1430,7 @@ wxZipEntry *wxZipInputStream::GetNextEntry() if (!IsOk()) return NULL; - _wxZipEntryPtr entry(new wxZipEntry(m_entry)); + wx__ZipEntryPtr entry(new wxZipEntry(m_entry)); entry->m_backlink = m_weaklinks->AddEntry(entry.get(), entry->GetKey()); return entry.release(); } @@ -1463,7 +1484,7 @@ wxStreamError wxZipInputStream::ReadLocal(bool readEndRec /*=false*/) while (m_signature == CENTRAL_MAGIC) { if (m_weaklinks->IsEmpty() && m_streamlink == NULL) return wxSTREAM_EOF; - + m_position += m_entry.ReadCentral(*m_parent_i_stream, GetConv()); m_signature = 0; if (m_parent_i_stream->GetLastError() == wxSTREAM_READ_ERROR) @@ -1499,7 +1520,7 @@ wxStreamError wxZipInputStream::ReadLocal(bool readEndRec /*=false*/) } return wxSTREAM_EOF; } - + if (m_signature != LOCAL_MAGIC) { wxLogError(_("error reading zip local header")); return wxSTREAM_READ_ERROR; @@ -1550,9 +1571,9 @@ bool wxZipInputStream::DoOpen(wxZipEntry *entry, bool raw) // can only open the current entry on a non-seekable stream wxCHECK(m_parentSeekable, false); } - + m_lasterror = wxSTREAM_READ_ERROR; - + if (entry) m_entry = *entry; @@ -1735,11 +1756,20 @@ size_t wxZipInputStream::OnSysRead(void *buffer, size_t size) return count; } +#if 1 //WXWIN_COMPATIBILITY_2_6 + // Borrowed from VS's zip stream (c) 1999 Vaclav Slavik // wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) { - if (!m_ffile || AtHeader()) + // seeking works when the stream is created with the compatibility + // constructor + if (!m_allowSeeking) + return wxInvalidOffset; + if (!IsOpened()) + if ((AtHeader() && !DoOpen()) || !OpenDecompressor()) + m_lasterror = wxSTREAM_READ_ERROR; + if (!IsOk()) return wxInvalidOffset; // NB: since ZIP files don't natively support seeking, we have to @@ -1754,14 +1784,14 @@ wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) { case wxFromCurrent : nextpos = seek + pos; break; case wxFromStart : nextpos = seek; break; - case wxFromEnd : nextpos = GetLength() - 1 + seek; break; + case wxFromEnd : nextpos = GetLength() + seek; break; default : nextpos = pos; break; /* just to fool compiler, never happens */ } - size_t toskip; + wxFileOffset toskip wxDUMMY_INITIALIZE(0); if ( nextpos >= pos ) { - toskip = (size_t)(nextpos - pos); + toskip = nextpos - pos; } else { @@ -1772,17 +1802,17 @@ wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) m_lasterror = wxSTREAM_READ_ERROR; return pos; } - toskip = (size_t)nextpos; + toskip = nextpos; } if ( toskip > 0 ) { - const size_t BUFSIZE = 4096; + const int BUFSIZE = 4096; size_t sz; char buffer[BUFSIZE]; while ( toskip > 0 ) { - sz = wxMin(toskip, BUFSIZE); + sz = wx_truncate_cast(size_t, wxMin(toskip, BUFSIZE)); Read(buffer, sz); toskip -= sz; } @@ -1792,12 +1822,14 @@ wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) return pos; } +#endif // WXWIN_COMPATIBILITY_2_6 + ///////////////////////////////////////////////////////////////////////////// // Output stream #include "wx/listimpl.cpp" -WX_DEFINE_LIST(_wxZipEntryList); +WX_DEFINE_LIST(wx__ZipEntryList) wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream, int level /*=-1*/, @@ -1818,11 +1850,11 @@ wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream, m_offsetAdjustment(wxInvalidOffset) { } - + wxZipOutputStream::~wxZipOutputStream() { Close(); - WX_CLEAR_LIST(_wxZipEntryList, m_entries); + WX_CLEAR_LIST(wx__ZipEntryList, m_entries); delete m_store; delete m_deflate; delete m_pending; @@ -1851,7 +1883,7 @@ bool wxZipOutputStream::PutNextDirEntry( bool wxZipOutputStream::CopyEntry(wxZipEntry *entry, wxZipInputStream& inputStream) { - _wxZipEntryPtr e(entry); + wx__ZipEntryPtr e(entry); return inputStream.DoOpen(e.get(), true) && @@ -1917,15 +1949,19 @@ bool wxZipOutputStream::DoCreate(wxZipEntry *entry, bool raw /*=false*/) ds << LOCAL_MAGIC; // and if this is the first entry test for seekability - if (m_headerOffset == 0) { + if (m_headerOffset == 0 && m_parent_o_stream->IsSeekable()) { +#if wxUSE_LOG bool logging = wxLog::IsEnabled(); wxLogNull nolog; +#endif // wxUSE_LOG wxFileOffset here = m_parent_o_stream->TellO(); if (here != wxInvalidOffset && here >= 4) { if (m_parent_o_stream->SeekO(here - 4) == here - 4) { m_offsetAdjustment = here - 4; +#if wxUSE_LOG wxLog::EnableLogging(logging); +#endif // wxUSE_LOG m_parent_o_stream->SeekO(here); } } @@ -2017,7 +2053,7 @@ bool wxZipOutputStream::CloseCompressor(wxOutputStream *comp) void wxZipOutputStream::CreatePendingEntry(const void *buffer, size_t size) { wxASSERT(IsOk() && m_pending && !m_comp); - _wxZipEntryPtr spPending(m_pending); + wx__ZipEntryPtr spPending(m_pending); m_pending = NULL; Buffer bufs[] = { @@ -2058,7 +2094,7 @@ void wxZipOutputStream::CreatePendingEntry(const void *buffer, size_t size) void wxZipOutputStream::CreatePendingEntry() { wxASSERT(IsOk() && m_pending && !m_comp); - _wxZipEntryPtr spPending(m_pending); + wx__ZipEntryPtr spPending(m_pending); m_pending = NULL; m_lasterror = wxSTREAM_WRITE_ERROR; @@ -2122,7 +2158,7 @@ bool wxZipOutputStream::Close() endrec.SetOffset(m_headerOffset); endrec.SetComment(m_Comment); - _wxZipEntryList::iterator it; + wx__ZipEntryList::iterator it; wxFileOffset size = 0; for (it = m_entries.begin(); it != m_entries.end(); ++it) {