/cpw/tomkiewicz/http: 35a2f951a850: Cookies support (reading)

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Wed Oct 17 11:33:19 EDT 2012


Changeset: 35a2f951a850255c8f082580e341cbd104e7d6f1
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-10-17 17:33 +0200
Branch:	 default
URL: http://hg.pidgin.im/cpw/tomkiewicz/http/rev/35a2f951a850

Description:

Cookies support (reading)

diffstat:

 libpurple/http.c            |  181 +++++++++++++++++++++++++++++++++++++++++++-
 libpurple/http.h            |   80 ++++++++++++++++--
 libpurple/protocols/gg/gg.c |    4 -
 3 files changed, 248 insertions(+), 17 deletions(-)

diffs (truncated from 411 to 300 lines):

diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -59,6 +59,7 @@ struct _PurpleHttpRequest
 	gchar *url;
 	gchar *method;
 	PurpleHttpHeaders *headers;
+	PurpleHttpCookieJar *cookie_jar;
 
 	int timeout;
 	int max_redirects;
@@ -121,6 +122,13 @@ struct _PurpleHttpHeaders
 	GHashTable *by_name;
 };
 
+struct _PurpleHttpCookieJar
+{
+	int ref_count;
+
+	GHashTable *tab;
+};
+
 static PurpleHttpConnection * purple_http_connection_new(
 	PurpleHttpRequest *request, PurpleConnection *gc);
 static void purple_http_connection_terminate(PurpleHttpConnection *hc);
@@ -128,6 +136,10 @@ static void purple_http_connection_termi
 static PurpleHttpResponse * purple_http_response_new(void);
 static void purple_http_response_free(PurpleHttpResponse *response);
 
+static void purple_http_cookie_jar_parse(PurpleHttpCookieJar *cookie_jar,
+	GList *values);
+gchar * purple_http_cookie_jar_dump(PurpleHttpCookieJar *cjar);
+
 static PurpleHttpURL * purple_http_url_parse(const char *url);
 static void purple_http_url_free(PurpleHttpURL *parsed_url);
 static void purple_http_url_relative(PurpleHttpURL *base_url,
@@ -160,7 +172,7 @@ static void purple_http_headers_free(Pur
 static void purple_http_headers_add(PurpleHttpHeaders *hdrs, const gchar *key,
 	const gchar *value);
 static const GList * purple_http_headers_get_all(PurpleHttpHeaders *hdrs);
-static const GList * purple_http_headers_get_all_by_name(
+static GList * purple_http_headers_get_all_by_name(
 	PurpleHttpHeaders *hdrs, const gchar *key);
 static const gchar * purple_http_headers_get(PurpleHttpHeaders *hdrs,
 	const gchar *key);
@@ -254,7 +266,8 @@ static const GList * purple_http_headers
 	return hdrs->list;
 }
 
-static const GList * purple_http_headers_get_all_by_name(
+/* return const */
+static GList * purple_http_headers_get_all_by_name(
 	PurpleHttpHeaders *hdrs, const gchar *key)
 {
 	GList *values;
@@ -466,6 +479,8 @@ static void _purple_http_gen_headers(Pur
 			kvp->key, (gchar*)kvp->value);
 	}
 
+	/* TODO: sending cookies */
+
 	g_string_append_printf(h, "\r\n");
 
 	if (purple_debug_is_unsafe() && purple_debug_is_verbose()) {
@@ -761,6 +776,19 @@ static void _purple_http_recv(gpointer _
 			g_free(hdrs);
 		}
 
+		purple_http_cookie_jar_parse(hc->request->cookie_jar,
+			purple_http_headers_get_all_by_name(
+				hc->response->headers, "Set-Cookie"));
+
+		if (purple_debug_is_unsafe() && purple_debug_is_verbose() &&
+			!purple_http_cookie_jar_is_empty(
+				hc->request->cookie_jar)) {
+			gchar *cookies = purple_http_cookie_jar_dump(
+				hc->request->cookie_jar);
+			purple_debug_misc("http", "Cookies: %s\n", cookies);
+			g_free(cookies);
+		}
+
 		if (hc->response->code == 407) {
 			_purple_http_error(hc, _("Invalid proxy credentials"));
 			return;
@@ -1174,6 +1202,13 @@ PurpleHttpRequest * purple_http_conn_get
 	return http_conn->request;
 }
 
+PurpleHttpCookieJar * purple_http_conn_get_cookie_jar(
+	PurpleHttpConnection *http_conn)
+{
+	return purple_http_request_get_cookie_jar(purple_http_conn_get_request(
+		http_conn));
+}
+
 PurpleConnection * purple_http_conn_get_purple_connection(
 	PurpleHttpConnection *http_conn)
 {
@@ -1182,6 +1217,127 @@ PurpleConnection * purple_http_conn_get_
 	return http_conn->gc;
 }
 
+/*** Cookie jar API ***********************************************************/
+
+void purple_http_cookie_jar_free(PurpleHttpCookieJar *cookie_jar);
+
+PurpleHttpCookieJar * purple_http_cookie_jar_new(void)
+{
+	PurpleHttpCookieJar *cjar = g_new0(PurpleHttpCookieJar, 1);
+
+	cjar->ref_count = 1;
+	cjar->tab = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+		g_free);
+
+	return cjar;
+}
+
+void purple_http_cookie_jar_free(PurpleHttpCookieJar *cookie_jar)
+{
+	g_hash_table_destroy(cookie_jar->tab);
+	g_free(cookie_jar);
+}
+
+void purple_http_cookie_jar_ref(PurpleHttpCookieJar *cookie_jar)
+{
+	g_return_if_fail(cookie_jar != NULL);
+
+	cookie_jar->ref_count++;
+}
+
+PurpleHttpCookieJar * purple_http_cookie_jar_unref(
+	PurpleHttpCookieJar *cookie_jar)
+{
+	if (cookie_jar == NULL)
+		return NULL;
+
+	g_return_val_if_fail(cookie_jar->ref_count > 0, NULL);
+
+	cookie_jar->ref_count--;
+	if (cookie_jar->ref_count > 0)
+		return cookie_jar;
+
+	purple_http_cookie_jar_free(cookie_jar);
+	return NULL;
+}
+
+static void purple_http_cookie_jar_parse(PurpleHttpCookieJar *cookie_jar,
+	GList *values)
+{
+	values = g_list_first(values);
+	while (values) {
+		const gchar *cookie = values->data;
+		const gchar *eqsign, *semicolon;
+		gchar *name, *value;
+		values = g_list_next(values);
+
+		eqsign = strchr(cookie, '=');
+		semicolon = strchr(cookie, ';');
+
+		if (eqsign == NULL || eqsign == cookie ||
+			(semicolon != NULL && semicolon < eqsign)) {
+			if (purple_debug_is_unsafe())
+				purple_debug_warning("http",
+					"Invalid cookie: [%s]\n", cookie);
+			else
+				purple_debug_warning("http", "Invalid cookie.");
+		}
+
+		name = g_strndup(cookie, eqsign - cookie);
+		eqsign++;
+		if (semicolon != NULL)
+			value = g_strndup(eqsign, semicolon - eqsign);
+		else
+			value = g_strdup(eqsign);
+
+		/* TODO: parse removing a cookie */
+		purple_http_cookie_jar_set(cookie_jar, name, value);
+
+		g_free(name);
+		g_free(value);
+	}
+}
+
+void purple_http_cookie_jar_set(PurpleHttpCookieJar *cookie_jar,
+	const gchar *name, const gchar *value)
+{
+	g_return_if_fail(cookie_jar != NULL);
+	g_return_if_fail(name != NULL);
+
+	if (value != NULL)
+		g_hash_table_insert(cookie_jar->tab, g_strdup(name), g_strdup(value));
+	else
+		g_hash_table_remove(cookie_jar->tab, name);
+}
+
+const gchar * purple_http_cookie_jar_get(PurpleHttpCookieJar *cookie_jar,
+	const gchar *name)
+{
+	return g_hash_table_lookup(cookie_jar->tab, name);
+}
+
+gchar * purple_http_cookie_jar_dump(PurpleHttpCookieJar *cjar)
+{
+	GHashTableIter it;
+	gchar *key, *value;
+	GString *str = g_string_new("");
+
+	g_hash_table_iter_init(&it, cjar->tab);
+	while (g_hash_table_iter_next(&it, (gpointer*)&key, (gpointer*)&value))
+		g_string_append_printf(str, "%s: %s\n", key, value);
+
+	if (str->len > 0)
+		g_string_truncate(str, str->len - 1);
+	return g_string_free(str, FALSE);
+}
+
+gboolean purple_http_cookie_jar_is_empty(PurpleHttpCookieJar *cookie_jar)
+{
+	g_return_val_if_fail(cookie_jar != NULL, TRUE);
+
+	return g_hash_table_size(cookie_jar->tab) == 0;
+}
+
 /*** Request API **************************************************************/
 
 static void purple_http_request_free(PurpleHttpRequest *request);
@@ -1197,6 +1353,7 @@ PurpleHttpRequest * purple_http_request_
 	request->ref_count = 1;
 	request->url = g_strdup(url);
 	request->headers = purple_http_headers_new();
+	request->cookie_jar = purple_http_cookie_jar_new();
 
 	request->timeout = PURPLE_HTTP_REQUEST_DEFAULT_TIMEOUT;
 	request->max_redirects = PURPLE_HTTP_REQUEST_DEFAULT_MAX_REDIRECTS;
@@ -1209,6 +1366,7 @@ PurpleHttpRequest * purple_http_request_
 static void purple_http_request_free(PurpleHttpRequest *request)
 {
 	purple_http_headers_free(request->headers);
+	purple_http_cookie_jar_unref(request->cookie_jar);
 	g_free(request->url);
 	g_free(request);
 }
@@ -1301,6 +1459,25 @@ int purple_http_request_get_max_redirect
 	return request->max_redirects;
 }
 
+void purple_http_request_set_cookie_jar(PurpleHttpRequest *request,
+	PurpleHttpCookieJar *cookie_jar)
+{
+	g_return_if_fail(request != NULL);
+	g_return_if_fail(cookie_jar != NULL);
+
+	purple_http_cookie_jar_ref(cookie_jar);
+	purple_http_cookie_jar_unref(request->cookie_jar);
+	request->cookie_jar = cookie_jar;
+}
+
+PurpleHttpCookieJar * purple_http_request_get_cookie_jar(
+	PurpleHttpRequest *request)
+{
+	g_return_val_if_fail(request != NULL, NULL);
+
+	return request->cookie_jar;
+}
+
 void purple_http_request_set_http11(PurpleHttpRequest *request, gboolean http11)
 {
 	g_return_if_fail(request != NULL);
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -51,7 +51,7 @@ typedef struct _PurpleHttpResponse Purpl
  * An collection of cookies, got from HTTP response or provided for HTTP
  * request.
  */
-typedef struct _PurpleHTTPCookieJar PurpleHTTPCookieJar;
+typedef struct _PurpleHttpCookieJar PurpleHttpCookieJar;
 
 /**
  * An callback called after performing (successfully or not) HTTP request.
@@ -167,6 +167,15 @@ PurpleHttpRequest * purple_http_conn_get
 	PurpleHttpConnection *http_conn);
 
 /**
+ * Gets cookie jar used within connection.
+ *
+ * @param http_conn The HTTP connection.
+ * @return          The cookie jar.
+ */
+PurpleHttpCookieJar * purple_http_conn_get_cookie_jar(
+	PurpleHttpConnection *http_conn);
+
+/**
  * Gets PurpleConnection tied with specified HTTP connection.
  *
  * @param http_conn The HTTP connection.
@@ -183,20 +192,58 @@ PurpleConnection * purple_http_conn_get_
 /**************************************************************************/
 /*@{*/
 



More information about the Commits mailing list