#include "wx/buffer.h"
#include "wx/ptr_scpd.h"
#include "wx/wfstream.h"
-#include "wx/html/forcelnk.h"
#include "zlib.h"
// value for the 'version needed to extract' field (20 means 2.0)
IMPLEMENT_DYNAMIC_CLASS(wxZipEntry, wxArchiveEntry)
IMPLEMENT_DYNAMIC_CLASS(wxZipClassFactory, wxArchiveClassFactory)
-FORCE_LINK_ME(zipstrm)
+//FORCE_LINK_ME(zipstrm)
+int _wx_link_dummy_func_zipstrm();
+int _wx_link_dummy_func_zipstrm()
+{
+ return 1;
+}
/////////////////////////////////////////////////////////////////////////////
wxZipMemory *Unique(size_t size);
private:
- ~wxZipMemory() { delete m_data; }
+ ~wxZipMemory() { delete [] m_data; }
char *m_data;
size_t m_size;
}
if (zm->m_capacity < size) {
- delete zm->m_data;
+ delete [] zm->m_data;
zm->m_data = new char[size];
zm->m_capacity = size;
}
// Collection of weak references to entries
WX_DECLARE_HASH_MAP(long, wxZipEntry*, wxIntegerHash,
- wxIntegerEqual, _wxOffsetZipEntryMap);
+ wxIntegerEqual, wx__OffsetZipEntryMap);
class wxZipWeakLinks
{
wxZipWeakLinks *AddEntry(wxZipEntry *entry, wxFileOffset key);
void RemoveEntry(wxFileOffset key)
- { m_entries.erase((_wxOffsetZipEntryMap::key_type)key); }
+ { m_entries.erase((wx__OffsetZipEntryMap::key_type)key); }
wxZipEntry *GetEntry(wxFileOffset key) const;
bool IsEmpty() const { return m_entries.empty(); }
~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__OffsetZipEntryMap::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__OffsetZipEntryMap::key_type)key);
return it != m_entries.end() ? it->second : NULL;
}
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),
{
bool isDir = IsDir() && !m_Name.empty();
+ // optimisations for common (and easy) cases
switch (wxFileName::GetFormat(format)) {
case wxPATH_DOS:
{
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 >> nameLen >> extraLen >> commentLen
>> m_DiskStart >> m_InternalAttributes >> m_ExternalAttributes;
SetOffset(ds.Read32());
-
+
SetName(ReadString(stream, nameLen, conv), wxPATH_UNIX);
if (extraLen || GetExtraLen()) {
ds << commentLen << m_DiskStart << m_InternalAttributes
<< m_ExternalAttributes << (wxUint32)GetOffset();
-
+
stream.Write(name, nameLen);
if (extraLen)
stream.Write(GetExtra(), extraLen);
size_t wxZipEntry::ReadDescriptor(wxInputStream& stream)
{
wxDataInputStream ds(stream);
-
+
m_Crc = ds.Read32();
m_CompressedSize = ds.Read32();
m_Size = ds.Read32();
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))
/////////////////////////////////////////////////////////////////////////////
// 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
//
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 {
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);
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()
delete m_ffile;
m_weaklinks->Release(this);
-
+
if (m_streamlink)
m_streamlink->Release(this);
}
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;
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.
//
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;
size_t len = (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;
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();
}
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)
}
return wxSTREAM_EOF;
}
-
+
if (m_signature != LOCAL_MAGIC) {
wxLogError(_("error reading zip local header"));
return wxSTREAM_READ_ERROR;
// 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;
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
{
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;
+ size_t toskip wxDUMMY_INITIALIZE(0);
if ( nextpos >= pos )
{
toskip = (size_t)(nextpos - pos);
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*/,
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;
bool wxZipOutputStream::CopyEntry(wxZipEntry *entry,
wxZipInputStream& inputStream)
{
- _wxZipEntryPtr e(entry);
+ wx__ZipEntryPtr e(entry);
return
inputStream.DoOpen(e.get(), true) &&
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);
}
}
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[] = {
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;
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) {