X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/edef87c8274bd4cadcccc4ff107aeb1815e48460..0b7dce5480b8cf7ce4368122744d853f7a684e34:/src/common/zipstrm.cpp diff --git a/src/common/zipstrm.cpp b/src/common/zipstrm.cpp index 93bbef9f88..6a6ea742c0 100644 --- a/src/common/zipstrm.cpp +++ b/src/common/zipstrm.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: zipstrm.cpp +// Name: src/common/zipstrm.cpp // Purpose: Streams for Zip files // Author: Mike Wetherell // RCS-ID: $Id$ @@ -11,26 +11,25 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif +#if wxUSE_ZIPSTREAM + +#include "wx/zipstrm.h" + #ifndef WX_PRECOMP - #include "wx/defs.h" + #include "wx/hashmap.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/utils.h" #endif -#if wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM - -#include "wx/zipstrm.h" -#include "wx/log.h" -#include "wx/intl.h" #include "wx/datstrm.h" #include "wx/zstream.h" #include "wx/mstream.h" -#include "wx/utils.h" -#include "wx/buffer.h" #include "wx/ptr_scpd.h" #include "wx/wfstream.h" -#include "wx/link.h" #include "zlib.h" // value for the 'version needed to extract' field (20 means 2.0) @@ -78,8 +77,6 @@ enum { IMPLEMENT_DYNAMIC_CLASS(wxZipEntry, wxArchiveEntry) IMPLEMENT_DYNAMIC_CLASS(wxZipClassFactory, wxArchiveClassFactory) -wxFORCE_LINK_THIS_MODULE(zipstrm) - ///////////////////////////////////////////////////////////////////////////// // Helpers @@ -88,6 +85,9 @@ wxFORCE_LINK_THIS_MODULE(zipstrm) // static wxString ReadString(wxInputStream& stream, wxUint16 len, wxMBConv& conv) { + if (len == 0) + return wxEmptyString; + #if wxUSE_UNICODE wxCharBuffer buf(len); stream.Read(buf.data(), len); @@ -112,12 +112,20 @@ static inline wxUint32 CrackUint32(const char *m) return (n[3] << 24) | (n[2] << 16) | (n[1] << 8) | n[0]; } +// Decode a little endian wxUint16 number from a character array +// +static inline wxUint16 CrackUint16(const char *m) +{ + const unsigned char *n = (const unsigned char*)m; + return (n[1] << 8) | n[0]; +} + // Temporarily lower the logging level in debug mode to avoid a warning // from SeekI about seeking on a stream with data written back to it. // static wxFileOffset QuietSeek(wxInputStream& stream, wxFileOffset pos) { -#ifdef __WXDEBUG__ +#if defined(__WXDEBUG__) && wxUSE_LOG wxLogLevel level = wxLog::GetLogLevel(); wxLog::SetLogLevel(wxLOG_Debug - 1); wxFileOffset result = stream.SeekI(pos); @@ -129,6 +137,34 @@ static wxFileOffset QuietSeek(wxInputStream& stream, wxFileOffset pos) } +///////////////////////////////////////////////////////////////////////////// +// Class factory + +wxZipClassFactory g_wxZipClassFactory; + +wxZipClassFactory::wxZipClassFactory() +{ + if (this == &g_wxZipClassFactory) + PushFront(); +} + +const wxChar * const * +wxZipClassFactory::GetProtocols(wxStreamProtocolType type) const +{ + static const wxChar *protocols[] = { _T("zip"), NULL }; + static const wxChar *mimetypes[] = { _T("application/zip"), NULL }; + static const wxChar *fileexts[] = { _T(".zip"), _T(".htb"), NULL }; + static const wxChar *empty[] = { NULL }; + + switch (type) { + case wxSTREAM_PROTOCOL: return protocols; + case wxSTREAM_MIMETYPE: return mimetypes; + case wxSTREAM_FILEEXT: return fileexts; + default: return empty; + } +} + + ///////////////////////////////////////////////////////////////////////////// // Read a zip header @@ -169,26 +205,26 @@ wxZipHeader::wxZipHeader(wxInputStream& stream, size_t size) m_ok = m_size == size; } -wxUint8 wxZipHeader::Read8() +inline wxUint8 wxZipHeader::Read8() { wxASSERT(m_pos < m_size); - return *wx_reinterpret_cast(wxUint8*, m_data + m_pos++); + return m_data[m_pos++]; } -wxUint16 wxZipHeader::Read16() +inline wxUint16 wxZipHeader::Read16() { wxASSERT(m_pos + 2 <= m_size); - wxUint16 n = *wx_reinterpret_cast(wxUint16*, m_data + m_pos); + wxUint16 n = CrackUint16(m_data + m_pos); m_pos += 2; - return wxUINT16_SWAP_ON_BE(n); + return n; } -wxUint32 wxZipHeader::Read32() +inline wxUint32 wxZipHeader::Read32() { wxASSERT(m_pos + 4 <= m_size); - wxUint32 n = *wx_reinterpret_cast(wxUint32*, m_data + m_pos); + wxUint32 n = CrackUint32(m_data + m_pos); m_pos += 4; - return wxUINT32_SWAP_ON_BE(n); + return n; } @@ -604,7 +640,7 @@ static void Unique(wxZipMemory*& zm, size_t size) // Collection of weak references to entries WX_DECLARE_HASH_MAP(long, wxZipEntry*, wxIntegerHash, - wxIntegerEqual, wx__OffsetZipEntryMap) + wxIntegerEqual, wxOffsetZipEntryMap_); class wxZipWeakLinks { @@ -625,10 +661,10 @@ public: private: ~wxZipWeakLinks() { wxASSERT(IsEmpty()); } - typedef wx__OffsetZipEntryMap::key_type key_type; + typedef wxOffsetZipEntryMap_::key_type key_type; int m_ref; - wx__OffsetZipEntryMap m_entries; + wxOffsetZipEntryMap_ m_entries; wxSUPPRESS_GCC_PRIVATE_DTOR_WARNING(wxZipWeakLinks) }; @@ -642,7 +678,7 @@ wxZipWeakLinks *wxZipWeakLinks::AddEntry(wxZipEntry *entry, wxFileOffset key) wxZipEntry *wxZipWeakLinks::GetEntry(wxFileOffset key) const { - wx__OffsetZipEntryMap::const_iterator it = + wxOffsetZipEntryMap_::const_iterator it = m_entries.find(wx_truncate_cast(key_type, key)); return it != m_entries.end() ? it->second : NULL; } @@ -751,7 +787,7 @@ wxString wxZipEntry::GetName(wxPathFormat format /*=wxPATH_NATIVE*/) const case wxPATH_DOS: { wxString name(isDir ? m_Name + _T("\\") : m_Name); - for (size_t i = name.length() - 1; i > 0; --i) + for (size_t i = 0; i < name.length(); i++) if (name[i] == _T('/')) name[i] = _T('\\'); return name; @@ -968,7 +1004,7 @@ size_t wxZipEntry::ReadLocal(wxInputStream& stream, wxMBConv& conv) size_t wxZipEntry::WriteLocal(wxOutputStream& stream, wxMBConv& conv) const { wxString unixName = GetName(wxPATH_UNIX); - const wxWX2MBbuf name_buf = conv.cWX2MB(unixName); + const wxWX2MBbuf name_buf = unixName.mb_str(conv); const char *name = name_buf; if (!name) name = ""; wxUint16 nameLen = wx_truncate_cast(wxUint16, strlen(name)); @@ -1044,12 +1080,12 @@ size_t wxZipEntry::ReadCentral(wxInputStream& stream, wxMBConv& conv) size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const { wxString unixName = GetName(wxPATH_UNIX); - const wxWX2MBbuf name_buf = conv.cWX2MB(unixName); + const wxWX2MBbuf name_buf = unixName.mb_str(conv); const char *name = name_buf; if (!name) name = ""; wxUint16 nameLen = wx_truncate_cast(wxUint16, strlen(name)); - const wxWX2MBbuf comment_buf = conv.cWX2MB(m_Comment); + const wxWX2MBbuf comment_buf = m_Comment.mb_str(conv); const char *comment = comment_buf; if (!comment) comment = ""; wxUint16 commentLen = wx_truncate_cast(wxUint16, strlen(comment)); @@ -1100,7 +1136,7 @@ size_t wxZipEntry::ReadDescriptor(wxInputStream& stream) if (m_Crc == SUMS_MAGIC) { wxZipHeader buf(stream, 8); - wxUint32 u1 = buf.GetSize() >= 4 ? buf.Read32() : LOCAL_MAGIC; + wxUint32 u1 = buf.GetSize() >= 4 ? buf.Read32() : (wxUint32)LOCAL_MAGIC; wxUint32 u2 = buf.GetSize() == 8 ? buf.Read32() : 0; // look for the signature of the following record to decide which @@ -1199,7 +1235,7 @@ wxZipEndRec::wxZipEndRec() bool wxZipEndRec::Write(wxOutputStream& stream, wxMBConv& conv) const { - const wxWX2MBbuf comment_buf = conv.cWX2MB(m_Comment); + const wxWX2MBbuf comment_buf = m_Comment.mb_str(conv); const char *comment = comment_buf; if (!comment) comment = ""; wxUint16 commentLen = (wxUint16)strlen(comment); @@ -1269,8 +1305,8 @@ private: // Input stream // leave the default wxZipEntryPtr free for users -wxDECLARE_SCOPED_PTR(wxZipEntry, wx__ZipEntryPtr) -wxDEFINE_SCOPED_PTR (wxZipEntry, wx__ZipEntryPtr) +wxDECLARE_SCOPED_PTR(wxZipEntry, wxZipEntryPtr_) +wxDEFINE_SCOPED_PTR (wxZipEntry, wxZipEntryPtr_) // constructor // @@ -1281,7 +1317,14 @@ wxZipInputStream::wxZipInputStream(wxInputStream& stream, Init(); } -#if 1 //WXWIN_COMPATIBILITY_2_6 +wxZipInputStream::wxZipInputStream(wxInputStream *stream, + wxMBConv& conv /*=wxConvLocal*/) + : wxArchiveInputStream(stream, conv) +{ + Init(); +} + +#if WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE // Part of the compatibility constructor, which has been made inline to // avoid a problem with it not being exported by mingw 3.2.3 @@ -1292,10 +1335,11 @@ void wxZipInputStream::Init(const wxString& file) wxLogNull nolog; Init(); m_allowSeeking = true; - m_ffile = wx_static_cast(wxFFileInputStream*, m_parent_i_stream); - wx__ZipEntryPtr entry; + wxFFileInputStream *ffile; + ffile = static_cast(m_parent_i_stream); + wxZipEntryPtr_ entry; - if (m_ffile->Ok()) { + if (ffile->Ok()) { do { entry.reset(GetNextEntry()); } @@ -1306,13 +1350,13 @@ void wxZipInputStream::Init(const wxString& file) m_lasterror = wxSTREAM_READ_ERROR; } -wxInputStream& wxZipInputStream::OpenFile(const wxString& archive) +wxInputStream* wxZipInputStream::OpenFile(const wxString& archive) { wxLogNull nolog; - return *new wxFFileInputStream(archive); + return new wxFFileInputStream(archive); } -#endif // WXWIN_COMPATIBILITY_2_6 +#endif // WXWIN_COMPATIBILITY_2_6 && wxUSE_FFILE void wxZipInputStream::Init() { @@ -1330,8 +1374,7 @@ 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 +#if WXWIN_COMPATIBILITY_2_6 m_allowSeeking = false; #endif } @@ -1343,7 +1386,6 @@ wxZipInputStream::~wxZipInputStream() delete m_store; delete m_inflate; delete m_rawin; - delete m_ffile; m_weaklinks->Release(this); @@ -1405,9 +1447,7 @@ bool wxZipInputStream::LoadEndRecord() else { wxLogNull nolog; wxFileOffset pos = m_parent_i_stream->TellI(); - // FIXME - //if (pos != wxInvalidOffset) - if (pos >= 0 && pos <= LONG_MAX) + if (pos != wxInvalidOffset) m_offsetAdjustment = m_position = pos; return true; } @@ -1423,11 +1463,13 @@ bool wxZipInputStream::LoadEndRecord() m_TotalEntries = endrec.GetTotalEntries(); m_Comment = endrec.GetComment(); + wxUint32 magic = m_TotalEntries ? CENTRAL_MAGIC : END_MAGIC; + // Now find the central-directory. we have the file offset of // the CD, so look there first. if (m_parent_i_stream->SeekI(endrec.GetOffset()) != wxInvalidOffset && - ReadSignature() == CENTRAL_MAGIC) { - m_signature = CENTRAL_MAGIC; + ReadSignature() == magic) { + m_signature = magic; m_position = endrec.GetOffset(); m_offsetAdjustment = 0; return true; @@ -1437,8 +1479,8 @@ bool wxZipInputStream::LoadEndRecord() // 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. if (m_parent_i_stream->SeekI(endPos - endrec.GetSize()) - != wxInvalidOffset && ReadSignature() == CENTRAL_MAGIC) { - m_signature = CENTRAL_MAGIC; + != wxInvalidOffset && ReadSignature() == magic) { + m_signature = magic; m_position = endPos - endrec.GetSize(); m_offsetAdjustment = m_position - endrec.GetOffset(); return true; @@ -1516,7 +1558,7 @@ wxZipEntry *wxZipInputStream::GetNextEntry() if (!IsOk()) return NULL; - wx__ZipEntryPtr entry(new wxZipEntry(m_entry)); + wxZipEntryPtr_ entry(new wxZipEntry(m_entry)); entry->m_backlink = m_weaklinks->AddEntry(entry.get(), entry->GetKey()); return entry.release(); } @@ -1609,22 +1651,20 @@ wxStreamError wxZipInputStream::ReadLocal(bool readEndRec /*=false*/) return wxSTREAM_EOF; } - if (m_signature != LOCAL_MAGIC) { - wxLogError(_("error reading zip local header")); - return wxSTREAM_READ_ERROR; - } - - m_headerSize = m_entry.ReadLocal(*m_parent_i_stream, GetConv()); - m_signature = 0; - m_entry.SetOffset(m_position); - m_entry.SetKey(m_position); + if (m_signature == LOCAL_MAGIC) { + m_headerSize = m_entry.ReadLocal(*m_parent_i_stream, GetConv()); + m_signature = 0; + m_entry.SetOffset(m_position); + m_entry.SetKey(m_position); - if (!m_headerSize) { - return wxSTREAM_READ_ERROR; - } else { - m_TotalEntries++; - return wxSTREAM_NO_ERROR; + if (m_headerSize) { + m_TotalEntries++; + return wxSTREAM_NO_ERROR; + } } + + wxLogError(_("error reading zip local header")); + return wxSTREAM_READ_ERROR; } wxUint32 wxZipInputStream::ReadSignature() @@ -1845,7 +1885,7 @@ size_t wxZipInputStream::OnSysRead(void *buffer, size_t size) return count; } -#if 1 //WXWIN_COMPATIBILITY_2_6 +#if WXWIN_COMPATIBILITY_2_6 // Borrowed from VS's zip stream (c) 1999 Vaclav Slavik // @@ -1917,32 +1957,46 @@ wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode) // Output stream #include "wx/listimpl.cpp" -WX_DEFINE_LIST(wx__ZipEntryList) +WX_DEFINE_LIST(wxZipEntryList_) wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream, int level /*=-1*/, wxMBConv& conv /*=wxConvLocal*/) - : wxArchiveOutputStream(stream, conv), - m_store(new wxStoredOutputStream(stream)), - m_deflate(NULL), - m_backlink(NULL), - m_initialData(new char[OUTPUT_LATENCY]), - m_initialSize(0), - m_pending(NULL), - m_raw(false), - m_headerOffset(0), - m_headerSize(0), - m_entrySize(0), - m_comp(NULL), - m_level(level), - m_offsetAdjustment(wxInvalidOffset) + : wxArchiveOutputStream(stream, conv) { + Init(level); +} + +wxZipOutputStream::wxZipOutputStream(wxOutputStream *stream, + int level /*=-1*/, + wxMBConv& conv /*=wxConvLocal*/) + : wxArchiveOutputStream(stream, conv) +{ + Init(level); +} + +void wxZipOutputStream::Init(int level) +{ + m_store = new wxStoredOutputStream(*m_parent_o_stream); + m_deflate = NULL; + m_backlink = NULL; + m_initialData = new char[OUTPUT_LATENCY]; + m_initialSize = 0; + m_pending = NULL; + m_raw = false; + m_headerOffset = 0; + m_headerSize = 0; + m_entrySize = 0; + m_comp = NULL; + m_level = level; + m_offsetAdjustment = wxInvalidOffset; + m_endrecWritten = false; } wxZipOutputStream::~wxZipOutputStream() { Close(); - WX_CLEAR_LIST(wx__ZipEntryList, m_entries); + WX_CLEAR_LIST(wxZipEntryList_, m_entries); delete m_store; delete m_deflate; delete m_pending; @@ -1971,7 +2025,7 @@ bool wxZipOutputStream::PutNextDirEntry( bool wxZipOutputStream::CopyEntry(wxZipEntry *entry, wxZipInputStream& inputStream) { - wx__ZipEntryPtr e(entry); + wxZipEntryPtr_ e(entry); return inputStream.DoOpen(e.get(), true) && @@ -1997,7 +2051,7 @@ bool wxZipOutputStream::CopyEntry(wxArchiveEntry *entry, return false; } - return CopyEntry(zipEntry, wx_static_cast(wxZipInputStream&, stream)); + return CopyEntry(zipEntry, static_cast(stream)); } bool wxZipOutputStream::CopyArchiveMetaData(wxZipInputStream& inputStream) @@ -2011,7 +2065,7 @@ bool wxZipOutputStream::CopyArchiveMetaData(wxZipInputStream& inputStream) bool wxZipOutputStream::CopyArchiveMetaData(wxArchiveInputStream& stream) { - return CopyArchiveMetaData(wx_static_cast(wxZipInputStream&, stream)); + return CopyArchiveMetaData(static_cast(stream)); } void wxZipOutputStream::SetLevel(int level) @@ -2141,7 +2195,7 @@ bool wxZipOutputStream::CloseCompressor(wxOutputStream *comp) void wxZipOutputStream::CreatePendingEntry(const void *buffer, size_t size) { wxASSERT(IsOk() && m_pending && !m_comp); - wx__ZipEntryPtr spPending(m_pending); + wxZipEntryPtr_ spPending(m_pending); m_pending = NULL; Buffer bufs[] = { @@ -2182,7 +2236,7 @@ void wxZipOutputStream::CreatePendingEntry(const void *buffer, size_t size) void wxZipOutputStream::CreatePendingEntry() { wxASSERT(IsOk() && m_pending && !m_comp); - wx__ZipEntryPtr spPending(m_pending); + wxZipEntryPtr_ spPending(m_pending); m_pending = NULL; m_lasterror = wxSTREAM_WRITE_ERROR; @@ -2236,8 +2290,12 @@ bool wxZipOutputStream::Close() { CloseEntry(); - if (m_lasterror == wxSTREAM_WRITE_ERROR || m_entries.size() == 0) + if (m_lasterror == wxSTREAM_WRITE_ERROR + || (m_entries.size() == 0 && m_endrecWritten)) + { + wxFilterOutputStream::Close(); return false; + } wxZipEndRec endrec; @@ -2246,7 +2304,7 @@ bool wxZipOutputStream::Close() endrec.SetOffset(m_headerOffset); endrec.SetComment(m_Comment); - wx__ZipEntryList::iterator it; + wxZipEntryList_::iterator it; wxFileOffset size = 0; for (it = m_entries.begin(); it != m_entries.end(); ++it) { @@ -2259,7 +2317,9 @@ bool wxZipOutputStream::Close() endrec.Write(*m_parent_o_stream, GetConv()); m_lasterror = m_parent_o_stream->GetLastError(); - if (!IsOk()) + m_endrecWritten = true; + + if (!wxFilterOutputStream::Close() || !IsOk()) return false; m_lasterror = wxSTREAM_EOF; return true; @@ -2368,4 +2428,4 @@ size_t wxZipOutputStream::OnSysWrite(const void *buffer, size_t size) return m_comp->LastWrite(); } -#endif // wxUSE_ZLIB && wxUSE_STREAMS && wxUSE_ZIPSTREAM +#endif // wxUSE_ZIPSTREAM