[libsoup] Remove SoupCoding, SoupCodingGZip, use GZlibDecompressor



commit 8d77fee770814f33f287b26f2898ed986ff9d3b4
Author: Dan Winship <danw gnome org>
Date:   Fri Dec 10 12:44:59 2010 +0100

    Remove SoupCoding, SoupCodingGZip, use GZlibDecompressor
    
    also add a new test to coding-test for handling content that
    doesn't decode correctly

 libsoup/Makefile.am            |    4 -
 libsoup/soup-coding-gzip.c     |  148 -----------------------
 libsoup/soup-coding-gzip.h     |   33 -----
 libsoup/soup-coding.c          |  258 ----------------------------------------
 libsoup/soup-coding.h          |   92 --------------
 libsoup/soup-content-decoder.c |   37 ++++---
 libsoup/soup-message-io.c      |   54 ++++++++-
 tests/coding-test.c            |   59 +++++++++-
 8 files changed, 127 insertions(+), 558 deletions(-)
---
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index 5ed63f1..a26d820 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -125,10 +125,6 @@ libsoup_2_4_la_SOURCES =		\
 	soup-auth-manager-ntlm.c	\
 	soup-cache.c			\
 	soup-cache-private.h		\
-	soup-coding.h			\
-	soup-coding.c			\
-	soup-coding-gzip.h		\
-	soup-coding-gzip.c		\
 	soup-connection.h		\
 	soup-connection.c		\
 	soup-content-decoder.c		\
diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c
index 7bc6f42..d7ddd77 100644
--- a/libsoup/soup-content-decoder.c
+++ b/libsoup/soup-content-decoder.c
@@ -13,7 +13,6 @@
 #include <gio/gio.h>
 
 #include "soup-content-decoder.h"
-#include "soup-coding-gzip.h"
 #include "soup-enum-types.h"
 #include "soup-message.h"
 #include "soup-message-private.h"
@@ -50,9 +49,11 @@
  **/
 
 struct _SoupContentDecoderPrivate {
-	GHashTable *codings;
+	GHashTable *decoders;
 };
 
+typedef GConverter * (*SoupContentDecoderCreator) (void);
+
 static void soup_content_decoder_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
 
 static void request_queued (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg);
@@ -67,6 +68,12 @@ G_DEFINE_TYPE_WITH_CODE (SoupContentDecoder, soup_content_decoder, G_TYPE_OBJECT
 /* This is constant for now */
 #define ACCEPT_ENCODING_HEADER "gzip"
 
+static GConverter *
+gzip_decoder_creator (void)
+{
+	return (GConverter *)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+}
+
 static void
 soup_content_decoder_init (SoupContentDecoder *decoder)
 {
@@ -74,12 +81,12 @@ soup_content_decoder_init (SoupContentDecoder *decoder)
 						     SOUP_TYPE_CONTENT_DECODER,
 						     SoupContentDecoderPrivate);
 
-	decoder->priv->codings = g_hash_table_new (g_str_hash, g_str_equal);
+	decoder->priv->decoders = g_hash_table_new (g_str_hash, g_str_equal);
 	/* Hardcoded for now */
-	g_hash_table_insert (decoder->priv->codings, "gzip",
-			     GSIZE_TO_POINTER (SOUP_TYPE_CODING_GZIP));
-	g_hash_table_insert (decoder->priv->codings, "x-gzip",
-			     GSIZE_TO_POINTER (SOUP_TYPE_CODING_GZIP));
+	g_hash_table_insert (decoder->priv->decoders, "gzip",
+			     gzip_decoder_creator);
+	g_hash_table_insert (decoder->priv->decoders, "x-gzip",
+			     gzip_decoder_creator);
 }
 
 static void
@@ -105,7 +112,7 @@ finalize (GObject *object)
 {
 	SoupContentDecoder *decoder = SOUP_CONTENT_DECODER (object);
 
-	g_hash_table_destroy (decoder->priv->codings);
+	g_hash_table_destroy (decoder->priv->decoders);
 
 	G_OBJECT_CLASS (soup_content_decoder_parent_class)->finalize (object);
 }
@@ -116,8 +123,8 @@ soup_content_decoder_got_headers_cb (SoupMessage *msg, SoupContentDecoder *decod
 	SoupMessagePrivate *msgpriv = SOUP_MESSAGE_GET_PRIVATE (msg);
 	const char *header;
 	GSList *encodings, *e;
-	GType coding_type;
-	SoupCoding *coding;
+	SoupContentDecoderCreator converter_creator;
+	GConverter *converter;
 
 	header = soup_message_headers_get_list (msg->response_headers,
 						"Content-Encoding");
@@ -132,7 +139,7 @@ soup_content_decoder_got_headers_cb (SoupMessage *msg, SoupContentDecoder *decod
 		return;
 
 	for (e = encodings; e; e = e->next) {
-		if (!g_hash_table_lookup (decoder->priv->codings, e->data)) {
+		if (!g_hash_table_lookup (decoder->priv->decoders, e->data)) {
 			soup_header_free_list (encodings);
 			return;
 		}
@@ -147,17 +154,15 @@ soup_content_decoder_got_headers_cb (SoupMessage *msg, SoupContentDecoder *decod
 	}
 
 	for (e = encodings; e; e = e->next) {
-		coding_type = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (decoder->priv->codings, e->data));
-		coding = g_object_new (coding_type,
-				       SOUP_CODING_DIRECTION, SOUP_CODING_DECODE,
-				       NULL);
+		converter_creator = g_hash_table_lookup (decoder->priv->decoders, e->data);
+		converter = converter_creator ();
 
 		/* Content-Encoding lists the codings in the order
 		 * they were applied in, so we put decoders in reverse
 		 * order so the last-applied will be the first
 		 * decoded.
 		 */
-		msgpriv->decoders = g_slist_prepend (msgpriv->decoders, coding);
+		msgpriv->decoders = g_slist_prepend (msgpriv->decoders, converter);
 	}
 	soup_header_free_list (encodings);
 
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 865f208..d78aa39 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -12,7 +12,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "soup-coding.h"
 #include "soup-connection.h"
 #include "soup-message.h"
 #include "soup-message-private.h"
@@ -358,10 +357,56 @@ read_metadata (SoupMessage *msg, gboolean to_blank)
 }
 
 static SoupBuffer *
+content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
+{
+	gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
+	char *outbuf;
+	GConverterResult result;
+
+	outbuf_length = MAX (buf->length * 2, 1024);
+	outbuf = g_malloc (outbuf_length);
+	outbuf_cur = input_cur = 0;
+
+	do {
+		result = g_converter_convert (
+			converter,
+			buf->data + input_cur, buf->length - input_cur,
+			outbuf + outbuf_cur, outbuf_length - outbuf_cur,
+			0, &input_used, &outbuf_used, error);
+		input_cur += input_used;
+		outbuf_cur += outbuf_used;
+
+		if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NO_SPACE) ||
+		    (!*error && outbuf_cur == outbuf_length)) {
+			g_clear_error (error);
+			outbuf_length *= 2;
+			outbuf = g_realloc (outbuf, outbuf_length);
+		} else if (*error) {
+			/* GZlibDecompressor can't ever return
+			 * G_IO_ERROR_PARTIAL_INPUT unless we pass it
+			 * input_length = 0, which we don't. Other
+			 * converters might of course, so eventually
+			 * this code needs to be rewritten to deal
+			 * with that.
+			 */
+			g_free (outbuf);
+			return NULL;
+		}
+	} while (input_cur < buf->length && result != G_CONVERTER_FINISHED);
+
+	if (outbuf_cur)
+		return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
+	else {
+		g_free (outbuf);
+		return NULL;
+	}
+}
+
+static SoupBuffer *
 content_decode (SoupMessage *msg, SoupBuffer *buf)
 {
 	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
-	SoupCoding *decoder;
+	GConverter *decoder;
 	SoupBuffer *decoded;
 	GError *error = NULL;
 	GSList *d;
@@ -369,10 +414,9 @@ content_decode (SoupMessage *msg, SoupBuffer *buf)
 	for (d = priv->decoders; d; d = d->next) {
 		decoder = d->data;
 
-		decoded = soup_coding_apply (decoder, buf->data, buf->length,
-					     FALSE, &error);
+		decoded = content_decode_one (buf, decoder, &error);
 		if (error) {
-			if (g_error_matches (error, SOUP_CODING_ERROR, SOUP_CODING_ERROR_INTERNAL_ERROR))
+			if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED))
 				g_warning ("Content-Decoding error: %s\n", error->message);
 			g_error_free (error);
 
diff --git a/tests/coding-test.c b/tests/coding-test.c
index b587a2c..f3bd852 100644
--- a/tests/coding-test.c
+++ b/tests/coding-test.c
@@ -26,7 +26,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
 		 const char *path, GHashTable *query,
 		 SoupClientContext *context, gpointer data)
 {
-	const char *accept_encoding, *junk;
+	const char *accept_encoding, *junk, *noencode;
 	GSList *codings;
 	char *file = NULL, *contents;
 	gsize length;
@@ -51,6 +51,16 @@ server_callback (SoupServer *server, SoupMessage *msg,
 	}
 	soup_header_free_list (codings);
 
+	noencode = soup_message_headers_get_one (msg->request_headers,
+						 "X-No-Encode");
+	if (noencode) {
+		/* Force it to send the ungzipped version, even though
+		 * we already added "Content-Encoding: gzip"
+		 */
+		g_free (file);
+		file = NULL;
+	}
+
 	if (!file)
 		file = g_strdup_printf (SRCDIR "/resources%s", path);
 	if (!g_file_get_contents (file, &contents, &length, NULL)) {
@@ -80,13 +90,14 @@ static void
 do_coding_test (void)
 {
 	SoupSession *session;
-	SoupMessage *msg, *msgz, *msgj;
+	SoupMessage *msg, *msgz, *msgj, *msgn;
 	SoupURI *uri;
 	const char *coding;
 
 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
 	uri = soup_uri_new_with_base (base_uri, "/mbox");
 
+
 	debug_printf (1, "GET /mbox, plain\n");
 	msg = soup_message_new_from_uri ("GET", uri);
 	soup_session_send_message (session, msg);
@@ -106,6 +117,7 @@ do_coding_test (void)
 		errors++;
 	}
 
+
 	debug_printf (1, "GET /mbox, Accept-Encoding: gzip\n");
 	soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
 	msgz = soup_message_new_from_uri ("GET", uri);
@@ -138,6 +150,7 @@ do_coding_test (void)
 		errors++;
 	}
 
+
 	debug_printf (1, "GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
 	msgj = soup_message_new_from_uri ("GET", uri);
 	soup_message_headers_append (msgj->request_headers,
@@ -171,9 +184,51 @@ do_coding_test (void)
 		errors++;
 	}
 
+
+	debug_printf (1, "GET /mbox, Accept-Encoding: gzip, with server error\n");
+	msgn = soup_message_new_from_uri ("GET", uri);
+	soup_message_headers_append (msgn->request_headers,
+				     "X-No-Encode", "true");
+	soup_session_send_message (session, msgn);
+	if (!SOUP_STATUS_IS_SUCCESSFUL (msgn->status_code)) {
+		debug_printf (1, "  Unexpected status %d %s\n",
+			      msgn->status_code, msgn->reason_phrase);
+		errors++;
+	}
+	coding = soup_message_headers_get_one (msgn->response_headers, "Content-Encoding");
+	if (!coding || g_ascii_strcasecmp (coding, "gzip") != 0) {
+		debug_printf (1, "  Unexpected Content-Encoding: %s\n",
+			      coding ? coding : "(none)");
+		errors++;
+	}
+	/* Since the content wasn't actually gzip-encoded, decoding it
+	 * should have failed and so the flag won't be set.
+	 */
+	if (soup_message_get_flags (msgn) & SOUP_MESSAGE_CONTENT_DECODED) {
+		debug_printf (1, "  SOUP_MESSAGE_CONTENT_DECODED set!\n");
+		errors++;
+	}
+	/* Failed content-decoding should have left the body untouched
+	 * from what the server sent... which happens to be the
+	 * uncompressed data.
+	 */
+	if (msg->response_body->length != msgn->response_body->length) {
+		debug_printf (1, "  Message length mismatch: %lu (plain) vs %lu (mis-encoded)\n",
+			      (gulong)msg->response_body->length,
+			      (gulong)msgn->response_body->length);
+		errors++;
+	} else if (memcmp (msg->response_body->data,
+			   msgn->response_body->data,
+			   msg->response_body->length) != 0) {
+		debug_printf (1, "  Message data mismatch (plain/misencoded)\n");
+		errors++;
+	}
+
+
 	g_object_unref (msg);
 	g_object_unref (msgz);
 	g_object_unref (msgj);
+	g_object_unref (msgn);
 	soup_uri_free (uri);
 
 	soup_test_session_abort_unref (session);



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