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 \
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-coding-gzip.c: "gzip" coding
- *
- * Copyright (C) 2005 Novell, Inc.
- * Copyright (C) 2008 Red Hat, Inc.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-coding-gzip.h"
-
-#include <zlib.h>
-
-typedef struct {
- z_stream stream;
-
-} SoupCodingGzipPrivate;
-#define SOUP_CODING_GZIP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_CODING_GZIP, SoupCodingGzipPrivate))
-
-G_DEFINE_TYPE (SoupCodingGzip, soup_coding_gzip, SOUP_TYPE_CODING)
-
-static void constructed (GObject *object);
-static void finalize (GObject *object);
-static SoupCodingStatus apply_into (SoupCoding *coding,
- gconstpointer input, gsize input_length,
- gsize *input_used,
- gpointer output, gsize output_length,
- gsize *output_used,
- gboolean done, GError **error);
-
-static void
-soup_coding_gzip_init (SoupCodingGzip *gzip)
-{
- SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (gzip);
-
- priv->stream.zalloc = Z_NULL;
- priv->stream.zfree = Z_NULL;
- priv->stream.opaque = Z_NULL;
-}
-
-static void
-soup_coding_gzip_class_init (SoupCodingGzipClass *gzip_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gzip_class);
- SoupCodingClass *coding_class = SOUP_CODING_CLASS (gzip_class);
-
- g_type_class_add_private (gzip_class, sizeof (SoupCodingGzipPrivate));
-
- coding_class->name = "gzip";
-
- object_class->constructed = constructed;
- object_class->finalize = finalize;
-
- coding_class->apply_into = apply_into;
-}
-
-static void
-constructed (GObject *object)
-{
- SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (object);
-
- /* All of these values are the defaults according to the zlib
- * documentation. "16" is a magic number that means gzip
- * instead of zlib.
- */
- if (SOUP_CODING (object)->direction == SOUP_CODING_ENCODE) {
- deflateInit2 (&priv->stream, Z_DEFAULT_COMPRESSION,
- Z_DEFLATED, MAX_WBITS | 16, 8,
- Z_DEFAULT_STRATEGY);
- } else
- inflateInit2 (&priv->stream, MAX_WBITS | 16);
-}
-
-static void
-finalize (GObject *object)
-{
- SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (object);
-
- if (SOUP_CODING (object)->direction == SOUP_CODING_ENCODE)
- deflateEnd (&priv->stream);
- else
- inflateEnd (&priv->stream);
-
- G_OBJECT_CLASS (soup_coding_gzip_parent_class)->finalize (object);
-}
-
-static SoupCodingStatus
-apply_into (SoupCoding *coding,
- gconstpointer input, gsize input_length, gsize *input_used,
- gpointer output, gsize output_length, gsize *output_used,
- gboolean done, GError **error)
-{
- SoupCodingGzipPrivate *priv = SOUP_CODING_GZIP_GET_PRIVATE (coding);
- int ret;
-
- priv->stream.avail_in = input_length;
- priv->stream.next_in = (gpointer)input;
- priv->stream.total_in = 0;
-
- priv->stream.avail_out = output_length;
- priv->stream.next_out = output;
- priv->stream.total_out = 0;
-
- if (coding->direction == SOUP_CODING_ENCODE)
- ret = deflate (&priv->stream, done ? Z_FINISH : Z_NO_FLUSH);
- else
- ret = inflate (&priv->stream, Z_SYNC_FLUSH);
-
- *input_used = priv->stream.total_in;
- *output_used = priv->stream.total_out;
-
- switch (ret) {
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- case Z_STREAM_ERROR:
- g_set_error_literal (error, SOUP_CODING_ERROR,
- SOUP_CODING_ERROR_DATA_ERROR,
- priv->stream.msg ? priv->stream.msg : "Bad data");
- return SOUP_CODING_STATUS_ERROR;
-
- case Z_BUF_ERROR:
- case Z_MEM_ERROR:
- g_set_error_literal (error, SOUP_CODING_ERROR,
- SOUP_CODING_ERROR_INTERNAL_ERROR,
- priv->stream.msg ? priv->stream.msg : "Internal error");
- return SOUP_CODING_STATUS_ERROR;
-
- case Z_STREAM_END:
- /* Discard any trailing junk, for compatibility with
- * other browsers. FIXME: this really belongs in
- * soup-message-io, but it's not possible to do there
- * with the current API.
- */
- *input_used = input_length;
- return SOUP_CODING_STATUS_COMPLETE;
-
- case Z_OK:
- default:
- if (*output_used == output_length &&
- *input_used < input_length)
- return SOUP_CODING_STATUS_NEED_SPACE;
- else
- return SOUP_CODING_STATUS_OK;
- }
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2005 Novell, Inc.
- * Copyright (C) 2008 Red Hat, Inc.
- */
-
-#ifndef SOUP_CODING_GZIP_H
-#define SOUP_CODING_GZIP_H 1
-
-#include "soup-coding.h"
-
-#define SOUP_TYPE_CODING_GZIP (soup_coding_gzip_get_type ())
-#define SOUP_CODING_GZIP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_CODING_GZIP, SoupCodingGzip))
-#define SOUP_CODING_GZIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CODING_GZIP, SoupCodingGzipClass))
-#define SOUP_IS_CODING_GZIP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_CODING_GZIP))
-#define SOUP_IS_CODING_GZIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CODING_GZIP))
-#define SOUP_CODING_GZIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CODING_GZIP, SoupCodingGzipClass))
-
-typedef struct {
- SoupCoding parent;
-
-} SoupCodingGzip;
-
-typedef struct {
- SoupCodingClass parent_class;
-
-} SoupCodingGzipClass;
-
-GType soup_coding_gzip_get_type (void);
-
-SoupCoding *soup_coding_gzip_new (SoupCodingDirection direction);
-
-#endif /* SOUP_CODING_GZIP_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-coding.c: Data encoding/decoding class
- *
- * Copyright (C) 2005 Novell, Inc.
- * Copyright (C) 2008 Red Hat, Inc.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-coding.h"
-#include "soup-enum-types.h"
-#include "soup-session-feature.h"
-
-static void soup_coding_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
-
-G_DEFINE_TYPE_WITH_CODE (SoupCoding, soup_coding, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
- soup_coding_session_feature_init))
-
-enum {
- PROP_0,
-
- PROP_DIRECTION,
-
- LAST_PROP
-};
-
-static void set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec);
-static void get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec);
-
-static SoupBuffer *apply (SoupCoding *coding,
- gconstpointer input, gsize input_length,
- gboolean done, GError **error);
-
-static void
-soup_coding_class_init (SoupCodingClass *coding_class)
-{
- GObjectClass *object_class = (GObjectClass *)coding_class;
-
- object_class->set_property = set_property;
- object_class->get_property = get_property;
-
- coding_class->apply = apply;
-
- /* properties */
- g_object_class_install_property (
- object_class, PROP_DIRECTION,
-#if 0
- g_param_spec_enum (SOUP_CODING_DIRECTION,
-#else
- g_param_spec_uint (SOUP_CODING_DIRECTION,
-#endif
- "Direction",
- "Whether to encode or decode",
- 0, 2,
- SOUP_CODING_ENCODE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-soup_coding_session_feature_init (SoupSessionFeatureInterface *feature_interface,
- gpointer interface_data)
-{
- ;
-}
-
-static void
-soup_coding_init (SoupCoding *coding)
-{
- ;
-}
-
-static void
-set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- SoupCoding *coding = SOUP_CODING (object);
-
- switch (prop_id) {
- case PROP_DIRECTION:
-#if 0
- coding->direction = g_value_get_enum (value);
-#else
- coding->direction = g_value_get_uint (value);
-#endif
- break;
- default:
- break;
- }
-}
-
-static void
-get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- SoupCoding *coding = SOUP_CODING (object);
-
- switch (prop_id) {
- case PROP_DIRECTION:
-#if 0
- g_value_set_enum (value, coding->direction);
-#else
- g_value_set_uint (value, coding->direction);
-#endif
- break;
- default:
- break;
- }
-}
-
-static SoupBuffer *
-apply (SoupCoding *coding,
- gconstpointer input, gsize input_length,
- gboolean done, GError **error)
-{
- gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
- char *outbuf;
- SoupCodingStatus status;
-
- if (coding->direction == SOUP_CODING_ENCODE)
- outbuf_length = MAX (input_length / 2, 1024);
- else
- outbuf_length = MAX (input_length * 2, 1024);
- outbuf = g_malloc (outbuf_length);
- outbuf_cur = input_cur = 0;
-
- do {
- status = soup_coding_apply_into (
- coding,
- (guchar *)input + input_cur, input_length - input_cur,
- &input_used,
- outbuf + outbuf_cur, outbuf_length - outbuf_cur,
- &outbuf_used,
- done, error);
- input_cur += input_used;
- outbuf_cur += outbuf_used;
-
- switch (status) {
- case SOUP_CODING_STATUS_OK:
- case SOUP_CODING_STATUS_COMPLETE:
- break;
-
- case SOUP_CODING_STATUS_NEED_SPACE:
- outbuf_length *= 2;
- outbuf = g_realloc (outbuf, outbuf_length);
- break;
-
- case SOUP_CODING_STATUS_ERROR:
- default:
- g_free (outbuf);
- return NULL;
- }
- } while (input_cur < input_length ||
- (done && status != SOUP_CODING_STATUS_COMPLETE));
-
- if (outbuf_cur)
- return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
- else {
- g_free (outbuf);
- return NULL;
- }
-}
-
-/**
- * soup_coding_apply:
- * @coding: a #SoupCoding
- * @input: input data
- * @input_length: length of @input
- * @done: %TRUE if this is the last piece of data to encode/decode
- * @error: error pointer
- *
- * Applies @coding to @input_length bytes of data from @input, and
- * returns a new #SoupBuffer containing the encoded/decoded data. If
- * @done is %FALSE, the encoder may buffer some or all of the data in
- * @input rather than outputting it right away. If @done is %TRUE, the
- * encoder will flush any buffered data, and (if possible) verify that
- * the input has reached the end of the stream.
- *
- * Return value: a #SoupBuffer containing the encoded/decoded data, or
- * %NULL if no data can be returned at this point, or if an error
- * occurred. (If you pass %NULL for @error, there is no way to
- * distinguish the latter two cases).
- **/
-SoupBuffer *
-soup_coding_apply (SoupCoding *coding,
- gconstpointer input, gsize input_length,
- gboolean done, GError **error)
-{
- g_return_val_if_fail (SOUP_IS_CODING (coding), NULL);
-
- return SOUP_CODING_GET_CLASS (coding)->apply (
- coding, input, input_length, done, error);
-}
-
-/**
- * SoupCodingStatus:
- * @SOUP_CODING_STATUS_OK: Success
- * @SOUP_CODING_STATUS_ERROR: An error occurred
- * @SOUP_CODING_STATUS_NEED_SPACE: Output buffer was too small to
- * output any data.
- * @SOUP_CODING_STATUS_COMPLETE: The stream end has been reached and
- * the output buffer contains the last bytes of encoded/decoded data.
- *
- * The result from a call to soup_coding_apply_into().
- **/
-
-/**
- * soup_coding_apply_into:
- * @coding: a #SoupCoding
- * @input: input data
- * @input_length: length of @input
- * @input_used: on return, contains the number of bytes of @input that
- * were encoded/decoded.
- * @output: output buffer
- * @output_length: length of @output
- * @output_used: on return, contains the number of bytes of @output that
- * were filled with encoded/decoded data.
- * @done: %TRUE if this is the last piece of data to encode/decode
- * @error: error pointer
- *
- * Applies @coding to @input_length bytes of data from @input, and
- * outputs between %0 and @output_length encoded/decoded bytes into
- * @output. @input and @output may not overlap.
- *
- * Return value: the status; %SOUP_CODING_STATUS_OK on intermediate
- * success, %SOUP_CODING_STATUS_COMPLETE if the stream has been fully
- * encoded/decoded, %SOUP_CODING_STATUS_NEED_SPACE if a larger
- * @output_length is required to make progress, or
- * %SOUP_CODING_STATUS_ERROR on error (in which case @error will be
- * set).
- **/
-SoupCodingStatus
-soup_coding_apply_into (SoupCoding *coding,
- gconstpointer input, gsize input_length, gsize *input_used,
- gpointer output, gsize output_length, gsize *output_used,
- gboolean done, GError **error)
-{
- g_return_val_if_fail (SOUP_IS_CODING (coding), 0);
-
- return SOUP_CODING_GET_CLASS (coding)->apply_into (
- coding, input, input_length, input_used,
- output, output_length, output_used,
- done, error);
-}
-
-GQuark
-soup_coding_error_quark (void)
-{
- static GQuark error;
- if (!error)
- error = g_quark_from_static_string ("soup_coding_error_quark");
- return error;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2005, Novell, Inc.
- * Copyright (C) 2008, Red Hat, Inc.
- */
-
-#ifndef SOUP_CODING_H
-#define SOUP_CODING_H 1
-
-#include <libsoup/soup-types.h>
-#include <libsoup/soup-message-body.h>
-
-#define SOUP_TYPE_CODING (soup_coding_get_type ())
-#define SOUP_CODING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CODING, SoupCoding))
-#define SOUP_CODING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CODING, SoupCodingClass))
-#define SOUP_IS_CODING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CODING))
-#define SOUP_IS_CODING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CODING))
-#define SOUP_CODING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CODING, SoupCodingClass))
-
-typedef enum {
- SOUP_CODING_ENCODE,
- SOUP_CODING_DECODE
-} SoupCodingDirection;
-
-typedef enum {
- SOUP_CODING_STATUS_OK,
- SOUP_CODING_STATUS_ERROR,
- SOUP_CODING_STATUS_NEED_SPACE,
- SOUP_CODING_STATUS_COMPLETE,
-} SoupCodingStatus;
-
-typedef struct {
- GObject parent;
-
- SoupCodingDirection direction;
-} SoupCoding;
-
-typedef struct {
- GObjectClass parent_class;
-
- const char *name;
-
- SoupBuffer * (*apply) (SoupCoding *coding,
- gconstpointer input,
- gsize input_length,
- gboolean done,
- GError **error);
- SoupCodingStatus (*apply_into) (SoupCoding *coding,
- gconstpointer input,
- gsize input_length,
- gsize *input_used,
- gpointer output,
- gsize output_length,
- gsize *output_used,
- gboolean done,
- GError **error);
-
- /* Padding for future expansion */
- void (*_libsoup_reserved1) (void);
- void (*_libsoup_reserved2) (void);
- void (*_libsoup_reserved3) (void);
- void (*_libsoup_reserved4) (void);
-} SoupCodingClass;
-
-#define SOUP_CODING_DIRECTION "direction"
-
-GType soup_coding_get_type (void);
-
-SoupBuffer *soup_coding_apply (SoupCoding *coding,
- gconstpointer input,
- gsize input_length,
- gboolean done,
- GError **error);
-SoupCodingStatus soup_coding_apply_into (SoupCoding *coding,
- gconstpointer input,
- gsize input_length,
- gsize *input_used,
- gpointer output,
- gsize output_length,
- gsize *output_used,
- gboolean done,
- GError **error);
-
-#define SOUP_CODING_ERROR soup_coding_error_quark()
-GQuark soup_coding_error_quark (void);
-
-typedef enum {
- SOUP_CODING_ERROR_DATA_ERROR,
- SOUP_CODING_ERROR_INTERNAL_ERROR
-} SoupCodingError;
-
-#endif /* SOUP_CODING_H */
#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"
**/
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);
/* 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)
{
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
{
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);
}
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");
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;
}
}
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);
#include <stdlib.h>
#include <string.h>
-#include "soup-coding.h"
#include "soup-connection.h"
#include "soup-message.h"
#include "soup-message-private.h"
}
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;
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);
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;
}
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)) {
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);
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);
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,
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);