[libsoup] Remove SoupCoding, SoupCodingGZip, use GZlibDecompressor
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] Remove SoupCoding, SoupCodingGZip, use GZlibDecompressor
- Date: Fri, 10 Dec 2010 11:50:27 +0000 (UTC)
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]