From 6d8ff9731eae9bf57982de273c8a45673996bcb4 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Thu, 13 Oct 2011 18:37:24 +0200 Subject: [PATCH] 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 deletion(-) 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 -- 2.7.4