]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/zipstrm.cpp
use popen() instead of wxExecute(), it works inside wxYield() unlike the latter
[wxWidgets.git] / src / common / zipstrm.cpp
index 0242e357996ba559a04d7c85df1a306ff631ed35..eacd2b1d9c4d6de8dca192dd1d1c8ccb29a0a5df 100644 (file)
@@ -34,7 +34,6 @@
 #include "wx/buffer.h"
 #include "wx/ptr_scpd.h"
 #include "wx/wfstream.h"
 #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)
 #include "zlib.h"
 
 // value for the 'version needed to extract' field (20 means 2.0)
@@ -82,7 +81,12 @@ enum {
 IMPLEMENT_DYNAMIC_CLASS(wxZipEntry, wxArchiveEntry)
 IMPLEMENT_DYNAMIC_CLASS(wxZipClassFactory, wxArchiveClassFactory)
 
 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;
+}
 
 
 /////////////////////////////////////////////////////////////////////////////
 
 
 /////////////////////////////////////////////////////////////////////////////
@@ -470,7 +474,6 @@ class wxZipMemory
 {
 public:
     wxZipMemory() : m_data(NULL), m_size(0), m_capacity(0), m_ref(1) { }
 {
 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; }
 
     wxZipMemory *AddRef() { m_ref++; return this; }
     void Release() { if (--m_ref == 0) delete this; }
@@ -482,6 +485,7 @@ public:
     wxZipMemory *Unique(size_t size);
 
 private:
     wxZipMemory *Unique(size_t size);
 
 private:
+    ~wxZipMemory() { delete m_data; }
 
     char *m_data;
     size_t m_size;
 
     char *m_data;
     size_t m_size;
@@ -548,7 +552,6 @@ class wxZipWeakLinks
 {
 public:
     wxZipWeakLinks() : m_ref(1) { }
 {
 public:
     wxZipWeakLinks() : m_ref(1) { }
-    ~wxZipWeakLinks() { wxASSERT(IsEmpty()); }
 
     void Release(const wxZipInputStream* WXUNUSED(x))
         { if (--m_ref == 0) delete this; }
 
     void Release(const wxZipInputStream* WXUNUSED(x))
         { if (--m_ref == 0) delete this; }
@@ -562,6 +565,7 @@ public:
     bool IsEmpty() const { return m_entries.empty(); }
 
 private:
     bool IsEmpty() const { return m_entries.empty(); }
 
 private:
+    ~wxZipWeakLinks() { wxASSERT(IsEmpty()); }
 
     int m_ref;
     _wxOffsetZipEntryMap m_entries;
 
     int m_ref;
     _wxOffsetZipEntryMap m_entries;
@@ -589,7 +593,7 @@ wxZipEntry::wxZipEntry(
     const wxString& name /*=wxEmptyString*/,
     const wxDateTime& dt /*=wxDateTime::Now()*/,
     wxFileOffset size    /*=wxInvalidOffset*/)
     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),
     m_SystemMadeBy(wxZIP_SYSTEM_MSDOS),
     m_VersionMadeBy(wxMAJOR_VERSION * 10 + wxMINOR_VERSION),
     m_VersionNeeded(VERSION_NEEDED_TO_EXTRACT),
@@ -903,7 +907,7 @@ size_t wxZipEntry::WriteLocal(wxOutputStream& stream, wxMBConv& conv) const
 
     ds << m_VersionNeeded << m_Flags << m_Method;
     ds.Write32(GetDateTime().GetAsDOS());
 
     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_Crc);
     ds.Write32(m_CompressedSize != wxInvalidOffset ? (wxUint32)m_CompressedSize : 0);
     ds.Write32(m_Size != wxInvalidOffset ? (wxUint32)m_Size : 0);
@@ -938,7 +942,7 @@ size_t wxZipEntry::ReadCentral(wxInputStream& stream, wxMBConv& conv)
     ds >> nameLen >> extraLen >> commentLen
        >> m_DiskStart >> m_InternalAttributes >> m_ExternalAttributes;
     SetOffset(ds.Read32());
     ds >> nameLen >> extraLen >> commentLen
        >> m_DiskStart >> m_InternalAttributes >> m_ExternalAttributes;
     SetOffset(ds.Read32());
+
     SetName(ReadString(stream, nameLen, conv), wxPATH_UNIX);
 
     if (extraLen || GetExtraLen()) {
     SetName(ReadString(stream, nameLen, conv), wxPATH_UNIX);
 
     if (extraLen || GetExtraLen()) {
@@ -986,7 +990,7 @@ size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const
 
     ds << commentLen << m_DiskStart << m_InternalAttributes
        << m_ExternalAttributes << (wxUint32)GetOffset();
 
     ds << commentLen << m_DiskStart << m_InternalAttributes
        << m_ExternalAttributes << (wxUint32)GetOffset();
+
     stream.Write(name, nameLen);
     if (extraLen)
         stream.Write(GetExtra(), extraLen);
     stream.Write(name, nameLen);
     if (extraLen)
         stream.Write(GetExtra(), extraLen);
@@ -1003,7 +1007,7 @@ size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const
 size_t wxZipEntry::ReadDescriptor(wxInputStream& stream)
 {
     wxDataInputStream ds(stream);
 size_t wxZipEntry::ReadDescriptor(wxInputStream& stream)
 {
     wxDataInputStream ds(stream);
-    
+
     m_Crc = ds.Read32();
     m_CompressedSize = ds.Read32();
     m_Size = ds.Read32();
     m_Crc = ds.Read32();
     m_CompressedSize = ds.Read32();
     m_Size = ds.Read32();
@@ -1015,7 +1019,7 @@ size_t wxZipEntry::ReadDescriptor(wxInputStream& stream)
         stream.Read(buf, sizeof(buf));
         wxUint32 u1 = CrackUint32(buf);
         wxUint32 u2 = CrackUint32(buf + 4);
         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))
         // look for the signature of the following record to decide which
         if ((u1 == LOCAL_MAGIC || u1 == CENTRAL_MAGIC) &&
             (u2 != LOCAL_MAGIC && u2 != CENTRAL_MAGIC))
@@ -1147,7 +1151,6 @@ class wxZipStreamLink
 {
 public:
     wxZipStreamLink(wxZipOutputStream *stream) : m_ref(1), m_stream(stream) { }
 {
 public:
     wxZipStreamLink(wxZipOutputStream *stream) : m_ref(1), m_stream(stream) { }
-    ~wxZipStreamLink() { }
 
     wxZipStreamLink *AddRef() { m_ref++; return this; }
     wxZipOutputStream *GetOutputStream() const { return m_stream; }
 
     wxZipStreamLink *AddRef() { m_ref++; return this; }
     wxZipOutputStream *GetOutputStream() const { return m_stream; }
@@ -1158,6 +1161,7 @@ public:
         { m_stream = NULL; if (--m_ref == 0) delete this; }
 
 private:
         { m_stream = NULL; if (--m_ref == 0) delete this; }
 
 private:
+    ~wxZipStreamLink() { }
 
     int m_ref;
     wxZipOutputStream *m_stream;
 
     int m_ref;
     wxZipOutputStream *m_stream;
@@ -1237,7 +1241,7 @@ wxZipInputStream::~wxZipInputStream()
     delete m_ffile;
 
     m_weaklinks->Release(this);
     delete m_ffile;
 
     m_weaklinks->Release(this);
-    
+
     if (m_streamlink)
         m_streamlink->Release(this);
 }
     if (m_streamlink)
         m_streamlink->Release(this);
 }
@@ -1321,7 +1325,7 @@ bool wxZipInputStream::LoadEndRecord()
     m_Comment = endrec.GetComment();
 
     // Now find the central-directory. we have the file offset of
     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;
     if (m_parent_i_stream->SeekI(endrec.GetOffset()) != wxInvalidOffset &&
             ReadSignature() == CENTRAL_MAGIC) {
         m_signature = CENTRAL_MAGIC;
@@ -1329,7 +1333,7 @@ bool wxZipInputStream::LoadEndRecord()
         m_offsetAdjustment = 0;
         return true;
     }
         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.
     // 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 +1355,11 @@ bool wxZipInputStream::LoadEndRecord()
 //
 bool wxZipInputStream::FindEndRecord()
 {
 //
 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
     // 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;
         wxLogNull nolog;
         if (m_parent_i_stream->SeekI(-END_SIZE, wxFromEnd) == wxInvalidOffset)
             return false;
@@ -1379,7 +1386,7 @@ bool wxZipInputStream::FindEndRecord()
         size_t len = (size_t)(pos - wxMax(pos - (BUFSIZE - 3), minpos));
         memcpy(buf.data() + len, buf, 3);
         pos -= len;
         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 (m_parent_i_stream->SeekI(pos, wxFromStart) == wxInvalidOffset ||
                 m_parent_i_stream->Read(buf.data(), len).LastRead() != len)
             return false;
@@ -1463,7 +1470,7 @@ wxStreamError wxZipInputStream::ReadLocal(bool readEndRec /*=false*/)
     while (m_signature == CENTRAL_MAGIC) {
         if (m_weaklinks->IsEmpty() && m_streamlink == NULL)
             return wxSTREAM_EOF;
     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)
         m_position += m_entry.ReadCentral(*m_parent_i_stream, GetConv());
         m_signature = 0;
         if (m_parent_i_stream->GetLastError() == wxSTREAM_READ_ERROR)
@@ -1499,7 +1506,7 @@ wxStreamError wxZipInputStream::ReadLocal(bool readEndRec /*=false*/)
         }
         return wxSTREAM_EOF;
     }
         }
         return wxSTREAM_EOF;
     }
-            
+
     if (m_signature != LOCAL_MAGIC) {
         wxLogError(_("error reading zip local header"));
         return wxSTREAM_READ_ERROR;
     if (m_signature != LOCAL_MAGIC) {
         wxLogError(_("error reading zip local header"));
         return wxSTREAM_READ_ERROR;
@@ -1550,9 +1557,9 @@ bool wxZipInputStream::DoOpen(wxZipEntry *entry, bool raw)
         // can only open the current entry on a non-seekable stream
         wxCHECK(m_parentSeekable, false);
     }
         // can only open the current entry on a non-seekable stream
         wxCHECK(m_parentSeekable, false);
     }
-    
+
     m_lasterror = wxSTREAM_READ_ERROR;
     m_lasterror = wxSTREAM_READ_ERROR;
-    
+
     if (entry)
         m_entry = *entry;
 
     if (entry)
         m_entry = *entry;
 
@@ -1739,7 +1746,12 @@ size_t wxZipInputStream::OnSysRead(void *buffer, size_t size)
 //
 wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
 {
 //
 wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
 {
-    if (!m_ffile || AtHeader())
+    if (!m_ffile)
+        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
         return wxInvalidOffset;
 
     // NB: since ZIP files don't natively support seeking, we have to
@@ -1754,11 +1766,11 @@ wxFileOffset wxZipInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
     {
         case wxFromCurrent : nextpos = seek + pos; break;
         case wxFromStart : nextpos = seek; break;
     {
         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 */
     }
 
         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);
     if ( nextpos >= pos )
     {
         toskip = (size_t)(nextpos - pos);
@@ -1818,7 +1830,7 @@ wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream,
     m_offsetAdjustment(wxInvalidOffset)
 {
 }
     m_offsetAdjustment(wxInvalidOffset)
 {
 }
-                                
+
 wxZipOutputStream::~wxZipOutputStream()
 {
     Close();
 wxZipOutputStream::~wxZipOutputStream()
 {
     Close();
@@ -1917,7 +1929,7 @@ bool wxZipOutputStream::DoCreate(wxZipEntry *entry, bool raw /*=false*/)
     ds << LOCAL_MAGIC;
 
     // and if this is the first entry test for seekability
     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()) {
         bool logging = wxLog::IsEnabled();
         wxLogNull nolog;
         wxFileOffset here = m_parent_o_stream->TellO();
         bool logging = wxLog::IsEnabled();
         wxLogNull nolog;
         wxFileOffset here = m_parent_o_stream->TellO();