[libsoup] SoupContentDecoder: add support for deflate Content-Encoding



commit 6d8ff9731eae9bf57982de273c8a45673996bcb4
Author: Sergio Villar Senin <svillar igalia com>
Date:   Thu Oct 13 18:37:24 2011 +0200

    SoupContentDecoder: add support for deflate Content-Encoding
    
    Claim that we support both gzip and deflate content encodings. Added support
    to handle data compressed with deflate with and without zlib headers.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=661682

 libsoup/soup-content-decoder.c |   10 +++++++++-
 libsoup/soup-message-io.c      |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletions(-)
---
diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c
index 3ab240c..2146612 100644
--- a/libsoup/soup-content-decoder.c
+++ b/libsoup/soup-content-decoder.c
@@ -66,7 +66,7 @@ G_DEFINE_TYPE_WITH_CODE (SoupContentDecoder, soup_content_decoder, G_TYPE_OBJECT
 						soup_content_decoder_session_feature_init))
 
 /* This is constant for now */
-#define ACCEPT_ENCODING_HEADER "gzip"
+#define ACCEPT_ENCODING_HEADER "gzip, deflate"
 
 static GConverter *
 gzip_decoder_creator (void)
@@ -74,6 +74,12 @@ gzip_decoder_creator (void)
 	return (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
 }
 
+static GConverter *
+zlib_decoder_creator (void)
+{
+	return (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
+}
+
 static void
 soup_content_decoder_init (SoupContentDecoder *decoder)
 {
@@ -87,6 +93,8 @@ soup_content_decoder_init (SoupContentDecoder *decoder)
 			     gzip_decoder_creator);
 	g_hash_table_insert (decoder->priv->decoders, "x-gzip",
 			     gzip_decoder_creator);
+	g_hash_table_insert (decoder->priv->decoders, "deflate",
+			     zlib_decoder_creator);
 }
 
 static void
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 4f2e839..b589ef2 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -338,6 +338,7 @@ content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
 	gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
 	char *outbuf;
 	GConverterResult result;
+	gboolean dummy_zlib_header_used = FALSE;
 
 	outbuf_length = MAX (buf->length * 2, 1024);
 	outbuf = g_malloc (outbuf_length);
@@ -357,6 +358,39 @@ content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
 			g_clear_error (error);
 			outbuf_length *= 2;
 			outbuf = g_realloc (outbuf, outbuf_length);
+		} else if (input_cur == 0 &&
+			   !dummy_zlib_header_used &&
+			   G_IS_ZLIB_DECOMPRESSOR (converter) &&
+			   g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA)) {
+
+			GZlibCompressorFormat format;
+			g_object_get (G_OBJECT (converter), "format", &format, NULL);
+
+			if (format == G_ZLIB_COMPRESSOR_FORMAT_ZLIB) {
+				/* Some servers (especially Apache with mod_deflate)
+				 * return RAW compressed data without the zlib headers
+				 * when the client claims to support deflate. For
+				 * those cases use a dummy header (stolen from
+				 * Mozilla's nsHTTPCompressConv.cpp) and try to
+				 * continue uncompressing data.
+				 */
+				static char dummy_zlib_header[2] = { 0x78, 0x9C };
+
+				g_converter_reset (converter);
+				result = g_converter_convert (converter,
+							      dummy_zlib_header, sizeof(dummy_zlib_header),
+							      outbuf + outbuf_cur, outbuf_length - outbuf_cur,
+							      0, &input_used, &outbuf_used, NULL);
+				dummy_zlib_header_used = TRUE;
+				if (result == G_CONVERTER_CONVERTED) {
+					g_clear_error (error);
+					continue;
+				}
+			}
+
+			g_free (outbuf);
+			return NULL;
+
 		} else if (*error) {
 			/* GZlibDecompressor can't ever return
 			 * G_IO_ERROR_PARTIAL_INPUT unless we pass it



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]