From 301deecc27a700e5432f8923be63ec71a79b8a52 Mon Sep 17 00:00:00 2001
From: Ryan Norton <wxprojects@comcast.net>
Date: Sun, 21 Dec 2003 04:28:45 +0000
Subject: [PATCH] Committed Mike's Update Patch 862130 wxZlibInput/OutputStream
 gzip support

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24952 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/strmzlib.tex | 44 ++++++++++++++++++++++----------------
 include/wx/zstream.h       |  8 ++++---
 src/common/zstream.cpp     | 28 ++++++++++++++++++++----
 3 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/docs/latex/wx/strmzlib.tex b/docs/latex/wx/strmzlib.tex
index a16745b8fb..d563a50640 100644
--- a/docs/latex/wx/strmzlib.tex
+++ b/docs/latex/wx/strmzlib.tex
@@ -3,8 +3,8 @@
 % -----------------------------------------------------------------------------
 \section{\class{wxZlibInputStream}}\label{wxzlibinputstream}
 
-This stream uncompresses all data read from it. It uses the "filtered"
-stream to get new compressed data.
+This filter stream decompresses a stream that is in zlib or gzip format.
+Note that reading the gzip format requires zlib version 1.2.0 greater.
 
 The stream is not seekable, \helpref{SeekI()}{wxinputstreamseeki} returns
  {\it wxInvalidOffset}. Also \helpref{GetSize()}{wxstreambasegetsize} is
@@ -27,19 +27,23 @@ not supported, it always returns $0$.
 
 \membersection{wxZlibInputStream::wxZlibInputStream}
 
-\func{}{wxZlibInputStream}{\param{wxInputStream\&}{ stream}, \param{int}{ flags = 0}}
+\func{}{wxZlibInputStream}{\param{wxInputStream\&}{ stream}, \param{int}{ flags = wxZLIB\_ZLIB | wxZLIB\_GZIP}}
 
-{\it flags} should be omitted for normal usage. The flag {\it wxZLIB\_NO_HEADER}
- is needed when wxZlibInputStream is used as an 'inflate' decompressor for gzip
-or zip files.
+The {\it flags} wxZLIB\_ZLIB and wxZLIB\_GZIP specify whether the input data
+is in zlib or gzip format. If both are used, bitwise ored, then zlib will
+autodetect the stream type, this is the default.
+If {\it flags} is zero, then the data is assumed to be a raw deflate stream
+without either zlib or gzip headers.
 
-{\it wxZLIB\_NO_HEADER} is currently the only flag:
+The following symbols can be use for the flags:
 
 \begin{verbatim}
 // Flags
 enum {
-    wxZLIB_NO_HEADER = 1   // required for use in Gzip and Zip files
-}
+    wxZLIB_NO_HEADER = 0,   // raw deflate stream, no header or checksum
+    wxZLIB_ZLIB = 1,        // zlib header and checksum
+    wxZLIB_GZIP = 2         // gzip header and checksum, requires zlib 1.2+
+};
 \end{verbatim}
 
 
@@ -48,8 +52,9 @@ enum {
 % -----------------------------------------------------------------------------
 \section{\class{wxZlibOutputStream}}\label{wxzliboutputstream}
 
-This stream compresses all data written to it, and passes the compressed data
-to the "filtered" stream.
+This stream compresses all data written to it. The compressed output can be
+in zlib or gzip format.
+Note that writing the gzip format requires zlib version 1.2.0 greater.
 
 The stream is not seekable, \helpref{SeekO()}{wxoutputstreamseeko} returns
  {\it wxInvalidOffset}.
@@ -72,16 +77,17 @@ The stream is not seekable, \helpref{SeekO()}{wxoutputstreamseeko} returns
 
 \membersection{wxZlibOutputStream::wxZlibOutputStream}
 
-\func{}{wxZlibOutputStream}{\param{wxOutputStream\&}{ stream}, \param{int}{ level = -1}, \param{int}{ flags = 0}}
+\func{}{wxZlibOutputStream}{\param{wxOutputStream\&}{ stream}, \param{int}{ level = -1}, \param{int}{ flags = wxZLIB\_ZLIB}}
 
 Creates a new write-only compressed stream. {\it level} means level of 
 compression. It is number between 0 and 9 (including these values) where
 0 means no compression and 9 best but slowest compression. -1 is default
 value (currently equivalent to 6).
 
-{\it flags} should be omitted for normal usage. The flag {\it wxZLIB\_NO_HEADER}
- suppresses the generation of the zlib header and checksum, and is required
-when wxZlibOutputStream is used as a 'deflate' compressor for gzip or zip files.
+The {\it flags} wxZLIB\_ZLIB and wxZLIB\_GZIP specify whether the output data
+will be in zlib or gzip format. wxZLIB\_ZLIB is the default.
+If {\it flags} is zero, then a raw deflate stream is output without either
+zlib or gzip headers.
 
 The following symbols can be use for the compression level and flags:
 
@@ -92,11 +98,13 @@ enum {
     wxZ_NO_COMPRESSION = 0,
     wxZ_BEST_SPEED = 1,
     wxZ_BEST_COMPRESSION = 9
-}
+};
 
 // Flags
 enum {
-    wxZLIB_NO_HEADER = 1   // required for use in Gzip and Zip files
-}
+    wxZLIB_NO_HEADER = 0,   // raw deflate stream, no header or checksum
+    wxZLIB_ZLIB = 1,        // zlib header and checksum
+    wxZLIB_GZIP = 2         // gzip header and checksum, requires zlib 1.2+
+};
 \end{verbatim}
 
diff --git a/include/wx/zstream.h b/include/wx/zstream.h
index 66be16c5df..20def98569 100644
--- a/include/wx/zstream.h
+++ b/include/wx/zstream.h
@@ -31,12 +31,14 @@ enum {
 
 // Flags
 enum {
-    wxZLIB_NO_HEADER = 1   // required for use in Gzip and Zip files
+    wxZLIB_NO_HEADER = 1,   // raw deflate stream, no header or checksum
+    wxZLIB_ZLIB = 2,        // zlib header and checksum
+    wxZLIB_GZIP = 3         // gzip header and checksum, requires zlib 1.2+
 };
 
 class WXDLLIMPEXP_BASE wxZlibInputStream: public wxFilterInputStream {
  public:
-  wxZlibInputStream(wxInputStream& stream, int flags = 0);
+  wxZlibInputStream(wxInputStream& stream, int flags = wxZLIB_ZLIB | wxZLIB_GZIP);
   virtual ~wxZlibInputStream();
 
   char Peek() { return wxInputStream::Peek(); }
@@ -57,7 +59,7 @@ class WXDLLIMPEXP_BASE wxZlibInputStream: public wxFilterInputStream {
 
 class WXDLLIMPEXP_BASE wxZlibOutputStream: public wxFilterOutputStream {
  public:
-  wxZlibOutputStream(wxOutputStream& stream, int level = -1, int flags = 0);
+  wxZlibOutputStream(wxOutputStream& stream, int level = -1, int flags = wxZLIB_ZLIB);
   virtual ~wxZlibOutputStream();
 
   void Sync() { DoFlush(false); }
diff --git a/src/common/zstream.cpp b/src/common/zstream.cpp
index c9d2b701c5..678b0d7485 100644
--- a/src/common/zstream.cpp
+++ b/src/common/zstream.cpp
@@ -68,7 +68,17 @@ wxZlibInputStream::wxZlibInputStream(wxInputStream& stream, int flags)
       m_inflate->next_in = NULL;
       m_inflate->next_out = NULL;
 
-      int bits = (flags & wxZLIB_NO_HEADER) ? -MAX_WBITS : MAX_WBITS;
+      wxASSERT((flags & ~(wxZLIB_ZLIB | wxZLIB_GZIP)) == 0);
+ 
+      // when autodetecting between gzip & zlib, silently drop gzip flag
+      // if the version of zlib doesn't support it
+      if (flags == (wxZLIB_ZLIB | wxZLIB_GZIP)
+              && strcmp(zlib_version, "1.2.") < 0)
+        flags &= ~wxZLIB_GZIP;
+
+      int bits = flags ? MAX_WBITS : -MAX_WBITS;
+      if (flags & wxZLIB_GZIP)
+        bits |= (flags & wxZLIB_ZLIB) ? 0x20 : 0x10;
 
       if (inflateInit2(m_inflate, bits) == Z_OK)
         return;
@@ -126,7 +136,10 @@ size_t wxZlibInputStream::OnSysRead(void *buffer, size_t size)
     }
     m_lasterror = wxSTREAM_EOF;
   } else if (err != Z_OK) {
-    wxLogError(_("Can't read from inflate stream (zlib error %d)."), err);
+    wxString msg(m_inflate->msg, *wxConvCurrent);
+    if (!msg)
+      msg.Format(_("zlib error %d"), err);
+    wxLogError(_("Can't read from inflate stream: %s\n"), msg.c_str());
     m_lasterror = wxSTREAM_READ_ERROR;
   }
 
@@ -169,7 +182,11 @@ wxZlibOutputStream::wxZlibOutputStream(wxOutputStream& stream,
         m_deflate->next_out = m_z_buffer;
         m_deflate->avail_out = m_z_size;
 
-        int bits = (flags & wxZLIB_NO_HEADER) ? -MAX_WBITS : MAX_WBITS;
+        wxASSERT(flags == 0 || flags == wxZLIB_ZLIB || flags == wxZLIB_GZIP);
+ 
+        int bits = flags ? MAX_WBITS : -MAX_WBITS;
+        if (flags & wxZLIB_GZIP)
+            bits |= 0x10;
 
         if (deflateInit2(m_deflate, level, Z_DEFLATED, bits, 
                          8, Z_DEFAULT_STRATEGY) == Z_OK)
@@ -253,7 +270,10 @@ size_t wxZlibOutputStream::OnSysWrite(const void *buffer, size_t size)
 
   if (err != Z_OK) {
     m_lasterror = wxSTREAM_WRITE_ERROR;
-    wxLogError(_("Can't write to deflate stream (zlib error %d)."), err);
+    wxString msg(m_deflate->msg, *wxConvCurrent);
+    if (!msg)
+      msg.Format(_("zlib error %d"), err);
+    wxLogError(_("Can't write to deflate stream: %s\n"), msg.c_str());
   }
 
   size -= m_deflate->avail_in;
-- 
2.50.0

