/soc/2015/jgeboski/facebook: 5ba291680ac4: facebook: compare che...

James Geboski <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 5ba291680ac4ff9b996d7ab75254519a5f35cfc8
Author:	 James Geboski <[email protected]>
Date:	 2015-06-06 02:13 -0400
Branch:	 facebook
URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/5ba291680ac4

Description:

facebook: compare checksums before fetching icons

diffstat:

 libpurple/protocols/facebook/api.c      |   27 +++-
 libpurple/protocols/facebook/api.h      |    1 +
 libpurple/protocols/facebook/facebook.c |   22 ++-
 libpurple/protocols/facebook/http.c     |  227 +++++++++++++++++++++++++++++++-
 libpurple/protocols/facebook/http.h     |   45 ++++++
 5 files changed, 311 insertions(+), 11 deletions(-)

diffs (truncated from 500 to 300 lines):

diff --git a/libpurple/protocols/facebook/api.c b/libpurple/protocols/facebook/api.c
--- a/libpurple/protocols/facebook/api.c
+++ b/libpurple/protocols/facebook/api.c
@@ -965,12 +965,20 @@ fb_api_auth(FbApi *api, const gchar *use
 }
 
 static void
+fb_api_cb_contacts_free(FbApiUser *user)
+{
+	g_free(user->csum);
+	g_free(user);
+}
+
+static void
 fb_api_cb_contacts(PurpleHttpConnection *con, PurpleHttpResponse *res,
                    gpointer data)
 {
 	const gchar *str;
 	FbApi *api = data;
 	FbApiUser user;
+	FbHttpParams *params;
 	GError *err = NULL;
 	GList *elms = NULL;
 	GList *l;
@@ -987,12 +995,23 @@ fb_api_cb_contacts(PurpleHttpConnection 
 		return;
 	}
 
+	params = fb_http_params_new_parse("http://www.google.com/index.php?text=hello%20world#world", TRUE);
+	fb_http_params_free(params);
+
+	params = fb_http_params_new_parse("http://www.google.com/?text=hi", TRUE);
+	fb_http_params_free(params);
+
+	params = fb_http_params_new_parse("text=hello%20world", FALSE);
+	fb_http_params_free(params);
+
 	arr = fb_json_node_get_arr(root, expr, &err);
 	FB_API_ERROR_CHK(api, err, goto finish);
 	elms = json_array_get_elements(arr);
 
 	for (l = elms; l != NULL; l = l->next) {
 		node = l->data;
+		memset(&user, 0, sizeof user);
+
 		str = fb_json_node_get_str(node, "$.represented_profile.id",
 		                           &err);
 		FB_API_ERROR_CHK(api, err, goto finish);
@@ -1008,6 +1027,12 @@ fb_api_cb_contacts(PurpleHttpConnection 
 		FB_API_ERROR_CHK(api, err, goto finish);
 		user.icon = str;
 
+		params = fb_http_params_new_parse(user.icon, TRUE);
+		str = fb_http_params_get_str(params, "oh", &err);
+		user.csum = g_strdup(str);
+		fb_http_params_free(params);
+		FB_API_ERROR_CHK(api, err, goto finish);
+
 		mptr = g_memdup(&user, sizeof user);
 		users = g_slist_prepend(users, mptr);
 	}
@@ -1016,7 +1041,7 @@ fb_api_cb_contacts(PurpleHttpConnection 
 
 finish:
 	g_list_free(elms);
-	g_slist_free_full(users, g_free);
+	g_slist_free_full(users, (GDestroyNotify) fb_api_cb_contacts_free);
 	json_node_free(root);
 }
 
diff --git a/libpurple/protocols/facebook/api.h b/libpurple/protocols/facebook/api.h
--- a/libpurple/protocols/facebook/api.h
+++ b/libpurple/protocols/facebook/api.h
@@ -129,6 +129,7 @@ struct _FbApiUser
 	FbId uid;
 	const gchar *name;
 	const gchar *icon;
+	gchar *csum;
 };
 
 struct _FbApiHttpInfo
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
--- a/libpurple/protocols/facebook/facebook.c
+++ b/libpurple/protocols/facebook/facebook.c
@@ -166,15 +166,18 @@ static void
 fb_cb_icon_fetch(PurpleHttpConnection *con, PurpleHttpResponse *res,
                  gpointer data)
 {
+	const gchar *csum;
 	const gchar *name;
 	const gchar *str;
 	FbApi *api;
+	FbHttpParams *params;
 	GError *err;
 	gsize size;
 	guchar *idata;
 	PurpleAccount *acct;
 	PurpleBuddy *bdy = data;
 	PurpleConnection *gc;
+	PurpleHttpRequest *req;
 
 	acct = purple_buddy_get_account(bdy);
 	gc = purple_account_get_connection(acct);
@@ -186,17 +189,24 @@ fb_cb_icon_fetch(PurpleHttpConnection *c
 		return;
 	}
 
+	req = purple_http_conn_get_request(con);
+	str = purple_http_request_get_url(req);
+	params = fb_http_params_new_parse(str, TRUE);
+	csum = fb_http_params_get_str(params, "oh", &err);
+
 	name = purple_buddy_get_name(bdy);
 	str = purple_http_response_get_data(res, &size);
+	idata = g_memdup(str, size);
 
-	idata = g_memdup(str, size);
-	purple_buddy_icons_set_for_user(acct, name, idata, size, NULL);
+	purple_buddy_icons_set_for_user(acct, name, idata, size, csum);
+	fb_http_params_free(params);
 }
 
 static void
 fb_cb_api_contacts(FbApi *api, GSList *users, gpointer data)
 {
 	const gchar *alias;
+	const gchar *csum;
 	FbApiUser *user;
 	FbId muid;
 	gchar uid[FB_ID_STRMAX];
@@ -234,9 +244,15 @@ fb_cb_api_contacts(FbApi *api, GSList *u
 		if (bdy == NULL) {
 			bdy = purple_buddy_new(acct, uid, user->name);
 			purple_blist_add_buddy(bdy, NULL, grp, NULL);
+			purple_http_get(gc, fb_cb_icon_fetch, bdy, user->icon);
+			continue;
 		}
 
-		purple_http_get(gc, fb_cb_icon_fetch, bdy, user->icon);
+		csum = purple_buddy_icons_get_checksum_for_user(bdy);
+
+		if (!purple_strequal(csum, user->csum)) {
+			purple_http_get(gc, fb_cb_icon_fetch, bdy, user->icon);
+		}
 	}
 
 	purple_connection_update_progress(gc, _("Connecting"), 3, 4);
diff --git a/libpurple/protocols/facebook/http.c b/libpurple/protocols/facebook/http.c
--- a/libpurple/protocols/facebook/http.c
+++ b/libpurple/protocols/facebook/http.c
@@ -19,6 +19,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "internal.h"
+
+#include <string.h>
+
 #include "http.h"
 
 GQuark
@@ -55,6 +59,68 @@ fb_http_params_new(void)
         return g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 }
 
+FbHttpParams *
+fb_http_params_new_parse(const gchar *data, gboolean isurl)
+{
+	const gchar *tail;
+	gchar *key;
+	gchar **ps;
+	gchar *val;
+	guint i;
+	FbHttpParams *params;
+
+	params = fb_http_params_new();
+
+	if (data == NULL) {
+		return params;
+	}
+
+	if (isurl) {
+		data = strchr(data, '?');
+
+		if (data++ == NULL) {
+			return params;
+		}
+
+		tail = strchr(data, '#');
+
+		if (tail != NULL) {
+			data = g_strndup(data, tail - data);
+		} else {
+			data = g_strdup(data);
+		}
+	}
+
+	ps = g_strsplit(data, "&", 0);
+
+	for (i = 0; ps[i] != NULL; i++) {
+		key = ps[i];
+		val = strchr(ps[i], '=');
+
+		if (val == NULL) {
+			continue;
+		}
+
+		*(val++) = 0;
+		key = g_uri_unescape_string(key, NULL);
+		val = g_uri_unescape_string(val, NULL);
+		g_hash_table_replace(params, key, val);
+	}
+
+	if (isurl) {
+		g_free((gchar*) data);
+	}
+
+	g_strfreev(ps);
+	return params;
+}
+
+void
+fb_http_params_free(FbHttpParams *params)
+{
+	g_hash_table_destroy(params);
+}
+
 gchar *
 fb_http_params_close(FbHttpParams *params, gsize *size)
 {
@@ -85,12 +151,159 @@ fb_http_params_close(FbHttpParams *param
 		*size = ret->len;
 	}
 
-	g_hash_table_destroy(params);
+	fb_http_params_free(params);
 	return g_string_free(ret, FALSE);
 }
 
+static const gchar *
+fb_http_params_get(FbHttpParams *params, const gchar *name, GError **error)
+{
+	const gchar *ret;
+
+	ret = g_hash_table_lookup(params, name);
+
+	if (ret == NULL) {
+		g_set_error(error, FB_HTTP_ERROR, FB_HTTP_ERROR_NOMATCH,
+		            _("No matches for %s"), name);
+		return NULL;
+	}
+
+	return ret;
+}
+
+gboolean
+fb_http_params_get_bool(FbHttpParams *params, const gchar *name,
+                        GError **error)
+{
+	const gchar *val;
+
+	val = fb_http_params_get(params, name, error);
+
+	if (val == NULL) {
+		return FALSE;
+	}
+
+	return g_ascii_strcasecmp(val, "TRUE") == 0;
+}
+
+gdouble
+fb_http_params_get_dbl(FbHttpParams *params, const gchar *name,
+                       GError **error)
+{
+	const gchar *val;
+
+	val = fb_http_params_get(params, name, error);
+
+	if (val == NULL) {
+		return 0.0;
+	}
+
+	return g_ascii_strtod(val, NULL);
+}
+
+gint64
+fb_http_params_get_int(FbHttpParams *params, const gchar *name,
+                       GError **error)
+{
+	const gchar *val;
+
+	val = fb_http_params_get(params, name, error);
+
+	if (val == NULL) {
+		return 0;
+	}
+
+	return g_ascii_strtoll(val, NULL, 10);
+}
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.