[libsoup] SoupSession: count redirections and cancel the message after too many



commit 34ae2a292b69321078c5e7d922a39f75e8538d3a
Author: José Millán Soto <jmillan igalia com>
Date:   Fri Jun 4 13:46:31 2010 +0200

    SoupSession: count redirections and cancel the message after too many
    
    and add a test to redirect-test
    
    https://bugzilla.gnome.org/show_bug.cgi?id=604383

 libsoup/soup-message-queue.h |    2 ++
 libsoup/soup-session.c       |   13 +++++++++++--
 libsoup/soup-status.c        |    2 ++
 libsoup/soup-status.h        |    1 +
 tests/redirect-test.c        |   13 +++++++++++--
 5 files changed, 27 insertions(+), 4 deletions(-)
---
diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h
index b7bc5d1..d4376a7 100644
--- a/libsoup/soup-message-queue.h
+++ b/libsoup/soup-message-queue.h
@@ -31,6 +31,8 @@ struct SoupMessageQueueItem {
 	SoupURI *proxy_uri;
 	SoupConnection *conn;
 
+	guint redirection_count;
+
 	guint resolving_proxy_addr : 1;
 	guint resolved_proxy_addr  : 1;
 
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 5143a48..1d5e6f5 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -117,6 +117,8 @@ static void auth_manager_authenticate (SoupAuthManager *manager,
 #define SOUP_SESSION_MAX_CONNS_DEFAULT 10
 #define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2
 
+#define SOUP_SESSION_MAX_REDIRECTION_COUNT 20
+
 #define SOUP_SESSION_USER_AGENT_BASE "libsoup/" PACKAGE_VERSION
 
 G_DEFINE_ABSTRACT_TYPE (SoupSession, soup_session, G_TYPE_OBJECT)
@@ -1092,7 +1094,8 @@ auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg,
 static void
 redirect_handler (SoupMessage *msg, gpointer user_data)
 {
-	SoupSession *session = user_data;
+	SoupMessageQueueItem *item = user_data;
+	SoupSession *session = item->session;
 	const char *new_loc;
 	SoupURI *new_uri;
 
@@ -1100,6 +1103,12 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
 						"Location");
 	g_return_if_fail (new_loc != NULL);
 
+	if (item->redirection_count >= SOUP_SESSION_MAX_REDIRECTION_COUNT) {
+		soup_session_cancel_message (session, msg, SOUP_STATUS_TOO_MANY_REDIRECTS);
+		return;
+	}
+	item->redirection_count++;
+
 	if (msg->status_code == SOUP_STATUS_SEE_OTHER ||
 	    (msg->status_code == SOUP_STATUS_FOUND &&
 	     !SOUP_METHOD_IS_SAFE (msg->method)) ||
@@ -1555,7 +1564,7 @@ queue_message (SoupSession *session, SoupMessage *msg,
 	if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) {
 		soup_message_add_header_handler (
 			msg, "got_body", "Location",
-			G_CALLBACK (redirect_handler), session);
+			G_CALLBACK (redirect_handler), item);
 	}
 
 	g_signal_emit (session, signals[REQUEST_QUEUED], 0, msg);
diff --git a/libsoup/soup-status.c b/libsoup/soup-status.c
index 2fa309a..12473f6 100644
--- a/libsoup/soup-status.c
+++ b/libsoup/soup-status.c
@@ -78,6 +78,7 @@
  * closed the connection unexpectedly
  * @SOUP_STATUS_MALFORMED: Malformed data (usually a programmer error)
  * @SOUP_STATUS_TRY_AGAIN: Used internally
+ * @SOUP_STATUS_TOO_MANY_REDIRECTS: There were too many redirections
  * @SOUP_STATUS_CONTINUE: 100 Continue (HTTP)
  * @SOUP_STATUS_SWITCHING_PROTOCOLS: 101 Switching Protocols (HTTP)
  * @SOUP_STATUS_PROCESSING: 102 Processing (WebDAV)
@@ -185,6 +186,7 @@ static const struct {
 #endif
 	{ SOUP_STATUS_IO_ERROR,                   "Connection terminated unexpectedly" },
 	{ SOUP_STATUS_MALFORMED,                  "Message Corrupt" },
+	{ SOUP_STATUS_TOO_MANY_REDIRECTS,         "Too many redirects" },
 
 	/* Informational */
 	{ SOUP_STATUS_CONTINUE,                   "Continue" },
diff --git a/libsoup/soup-status.h b/libsoup/soup-status.h
index 66e9f1c..0d8b74f 100644
--- a/libsoup/soup-status.h
+++ b/libsoup/soup-status.h
@@ -32,6 +32,7 @@ typedef enum {
 	SOUP_STATUS_IO_ERROR,
 	SOUP_STATUS_MALFORMED,
 	SOUP_STATUS_TRY_AGAIN,
+	SOUP_STATUS_TOO_MANY_REDIRECTS,
 
 	/* HTTP Status Codes */
 	SOUP_STATUS_CONTINUE                        = 100,
diff --git a/tests/redirect-test.c b/tests/redirect-test.c
index cd6f1a5..24aefc4 100644
--- a/tests/redirect-test.c
+++ b/tests/redirect-test.c
@@ -18,6 +18,7 @@ typedef struct {
 	const char *method;
 	const char *path;
 	guint status_code;
+	gboolean repeat;
 } TestRequest;
 
 static struct {
@@ -107,7 +108,10 @@ static struct {
 
 	/* Test behavior with irrecoverably-bad Location header */
 	{ { { "GET", "/bad-no-host", 302 },
-	    { NULL } }, SOUP_STATUS_MALFORMED }
+	    { NULL } }, SOUP_STATUS_MALFORMED },
+
+	{ { { "GET", "/bad-recursive", 302, TRUE },
+	    { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS }
 };
 static const int n_tests = G_N_ELEMENTS (tests);
 
@@ -142,7 +146,7 @@ restarted (SoupMessage *msg, gpointer user_data)
 
 	debug_printf (2, "    %s %s\n", msg->method, uri->path);
 
-	if ((*req)->method)
+	if ((*req)->method && !(*req)->repeat)
 		(*req)++;
 
 	if (!(*req)->method) {
@@ -234,6 +238,11 @@ server_callback (SoupServer *server, SoupMessage *msg,
 			soup_message_headers_replace (msg->response_headers,
 						      "Location",
 						      "/bad with spaces");
+		} else if (!strcmp (path, "/bad-recursive")) {
+			soup_message_set_status (msg, SOUP_STATUS_FOUND);
+			soup_message_headers_replace (msg->response_headers,
+						      "Location",
+						      "/bad-recursive");
 		} else if (!strcmp (path, "/bad-no-host")) {
 			soup_message_set_status (msg, SOUP_STATUS_FOUND);
 			soup_message_headers_replace (msg->response_headers,



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