adium: 13cc6bb3: pidgin-facebookchat @ 732, which fixes s...

evands at pidgin.im evands at pidgin.im
Thu May 6 12:01:01 EDT 2010


-----------------------------------------------------------------
Revision: 13cc6bb35be5b0918abbf059e366c9edd2e08f4c
Ancestor: 6ad3ad43bd53f2084c3880eef72a5fd10c85c234
Author: evands at pidgin.im
Date: 2010-05-06T15:54:22
Branch: im.pidgin.adium
URL: http://d.pidgin.im/viewmtn/revision/info/13cc6bb35be5b0918abbf059e366c9edd2e08f4c

Modified files:
        libpurple/protocols/facebook/facebook.nsi
        libpurple/protocols/facebook/fb_blist.c
        libpurple/protocols/facebook/fb_blist.h
        libpurple/protocols/facebook/fb_connection.c
        libpurple/protocols/facebook/fb_conversation.c
        libpurple/protocols/facebook/fb_friendlist.c
        libpurple/protocols/facebook/fb_info.c
        libpurple/protocols/facebook/fb_managefriends.c
        libpurple/protocols/facebook/fb_messages.c
        libpurple/protocols/facebook/fb_messages.h
        libpurple/protocols/facebook/fb_notifications.c
        libpurple/protocols/facebook/fb_search.c
        libpurple/protocols/facebook/fb_util.c
        libpurple/protocols/facebook/fb_util.h
        libpurple/protocols/facebook/libfacebook.c
        libpurple/protocols/facebook/libfacebook.h
        libpurple/protocols/facebook/pidgin-facebookchat.rc
        libpurple/protocols/facebook/rss.xml

ChangeLog: 

pidgin-facebookchat @ 732, which fixes status message retrieval

-------------- next part --------------
============================================================
--- libpurple/protocols/facebook/facebook.nsi	909394612268d37159a9853b011b2d14d25bceca
+++ libpurple/protocols/facebook/facebook.nsi	97ea60c5d4a321ff9d8ba51c38f2f940518b8b7f
@@ -6,7 +6,7 @@ SetCompress off
 ; todo: SetBrandingImage
 ; HM NIS Edit Wizard helper defines
 !define PRODUCT_NAME "pidgin-facebookchat"
-!define PRODUCT_VERSION "1.64"
+!define PRODUCT_VERSION "1.65"
 !define PRODUCT_PUBLISHER "Eion Robb"
 !define PRODUCT_WEB_SITE "http://pidgin-facebookchat.googlecode.com/"
 !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
============================================================
--- libpurple/protocols/facebook/fb_blist.c	3574e613239518dc6b50c192632e0b956e2e3635
+++ libpurple/protocols/facebook/fb_blist.c	cb0dd67c0da50e91b4b2c27f0008ac45f385afce
@@ -38,7 +38,7 @@ static void set_buddies_offline(PurpleBu
 	}
 }
 
-static void buddy_icon_cb(FacebookAccount *fba, gchar *data, gsize data_len,
+static void buddy_icon_cb(FacebookAccount *fba, const gchar *data, gsize data_len,
 		gpointer user_data)
 {
 	gchar *buddyname;
@@ -110,23 +110,18 @@ static GList *get_buddies(FacebookAccoun
 	return buddies;
 }
 
-static void process_buddy_icon(FacebookAccount *fba, PurpleBuddy *buddy,
-	JsonObject *userInfo)
+static void process_buddy_icon(FacebookAccount *fba, FacebookBuddy *fbuddy,
+	const gchar *buddy_icon_url)
 {
-	FacebookBuddy *fbuddy;
-	gchar *buddy_icon_url;
+	PurpleBuddy *buddy;
 	gchar *icon_host;
 	gchar *icon_path, *real_path;
 	gchar *search_tmp;
 
-	fbuddy = buddy->proto_data;
+	buddy = fbuddy->buddy;
 	
-	/* Set the buddy icon (if it hasn't changed) */
-	buddy_icon_url = g_strdup(json_node_get_string(json_object_get_member(
-			userInfo, "thumbSrc")));
 	/* Seperate the URL into pieces */
 	purple_url_parse(buddy_icon_url, &icon_host, NULL, &icon_path, NULL, NULL);
-	g_free(buddy_icon_url);
 	
 	if (icon_path != NULL && icon_path[0] != '/')
 	{
@@ -155,7 +150,13 @@ static void process_buddy_icon(FacebookA
 			/* bigger icon at /profile6/1845/74/n800753867_2878.jpg */
 			search_tmp = strstr(icon_path, "/q");
 			if (search_tmp)
-				*(search_tmp + 1) = 'n';			
+				*(search_tmp + 1) = 'n';
+			else
+			{
+				search_tmp = strstr(icon_path, "_q.jpg");
+				if (search_tmp)
+					*(search_tmp + 1) = 'n';
+			}
 			purple_debug_info("facebook", "buddy %s has a new buddy icon at http://%s%s\n", buddy->name, icon_host, icon_path);
 			/* Fetch their icon */
 			fb_post_or_get(fba, FB_METHOD_GET, icon_host,
@@ -215,10 +216,13 @@ static void process_buddies(FacebookAcco
 	for (cur = buddies; cur != NULL; cur = cur->next)
 	{
 		PurpleBuddy *buddy;
+		FacebookBuddy *fbuddy;
 
 		buddy = (PurpleBuddy *)cur->data;
+		fbuddy = buddy->proto_data;
 
-		process_buddy_icon(fba, buddy, userInfo);
+		process_buddy_icon(fba, fbuddy, json_node_get_string(
+			json_object_get_member(userInfo, "thumbSrc")));
 
 		purple_presence_set_idle(purple_buddy_get_presence(buddy),
 				idle, 0);
@@ -272,7 +276,7 @@ static void process_notifications(Facebo
 	}
 }
 
-static void got_status_stream_cb(FacebookAccount *fba, gchar *data,
+static void got_status_stream_cb(FacebookAccount *fba, const gchar *data,
 		gsize data_len, gpointer userdata)
 {
 	gchar *error = NULL;
@@ -317,7 +321,7 @@ static void got_status_stream_cb(Faceboo
 			objnode, "html"));
 	//purple_debug_misc("facebook", "html data\n%s\n", html);
 	
-	messages = g_strsplit(html, "/h3>", -1);
+	messages = g_strsplit(html, "/h6>", -1);
 	for(i = 0; messages[i]; i++)
 	{
 		message = messages[i];
@@ -389,7 +393,7 @@ static void got_status_stream_cb(Faceboo
 	json_parser_free(parser);
 }
 
-static void got_buddy_list_cb(FacebookAccount *fba, gchar *data,
+static void got_buddy_list_cb(FacebookAccount *fba, const gchar *data,
 		gsize data_len, gpointer userdata)
 {
 	GSList *buddies_list;
@@ -531,6 +535,85 @@ gboolean fb_get_buddy_list(gpointer data
 	return TRUE;
 }
 
+static void got_full_buddy_list(FacebookAccount *fba, const gchar *data,
+		gsize data_len, gpointer userdata)
+{
+	int i;
+	PurpleGroup *fb_group;
+	JsonParser *parser;
+	gchar *error = NULL;
+	JsonObject *objnode, *node;
+	JsonArray *entries;
+	
+	purple_debug_info("facebook", "parsing full buddy list\n");
+
+	if (fba == NULL)
+		return;
+
+	parser = fb_get_parser(data, data_len);
+	if (parser == NULL)
+		return;
+
+	purple_debug_misc("facebook", "full buddy list\n%s\n", data);
+
+	objnode = fb_get_json_object(parser, &error);
+	if (!json_object_has_member(objnode, "payload"))
+	{
+		json_parser_free(parser);
+		return;
+	}
+	objnode = json_node_get_object(json_object_get_member(
+			objnode, "payload"));
+	if (!json_object_has_member(objnode, "entries"))
+	{
+		json_parser_free(parser);
+		return;
+	}
+	entries = json_node_get_array(json_object_get_member(
+			objnode, "entries"));
+			
+	fb_group = purple_find_group(DEFAULT_GROUP_NAME);
+	if (fb_group == NULL)
+	{
+		fb_group = purple_group_new(DEFAULT_GROUP_NAME);
+		purple_blist_add_group(fb_group, NULL);
+	}
+	for(i = 0; i < json_array_get_length(entries); i++)
+	{
+		node = json_node_get_object(json_array_get_element(entries, i));
+		const gchar *type = json_node_get_string(json_object_get_member(node, "ty"));
+		if (type[0] != 'u')
+			continue;
+		const gchar *uid = json_node_get_string(json_object_get_member(node, "i"));
+		if (purple_find_buddy(fba->account, uid))
+			continue;
+		
+		const gchar *name = json_node_get_string(json_object_get_member(node, "t"));
+		PurpleBuddy *buddy = purple_buddy_new(fba->account, uid, name);
+		purple_blist_add_buddy(buddy, NULL, fb_group, NULL);
+		FacebookBuddy *fbuddy = g_new0(FacebookBuddy, 1);
+		fbuddy->buddy = buddy;
+		fbuddy->fba = fba;
+		fbuddy->uid = atoll(uid);
+		fbuddy->name = g_strdup(name);
+		buddy->proto_data = fbuddy;
+		
+		const gchar *thumb_url = json_node_get_string(json_object_get_member(node, "it"));
+		process_buddy_icon(fba, fbuddy, thumb_url);
+	}
+
+	json_parser_free(parser);	
+}
+
+void fb_get_full_buddy_list(FacebookAccount *fba)
+{
+	gchar *url;
+	
+	url = g_strdup_printf("/ajax/typeahead_search.php?u=%" G_GINT64_FORMAT "&__a=1", fba->uid);
+	fb_post_or_get(fba, FB_METHOD_GET, NULL, url, NULL, got_full_buddy_list, NULL, FALSE);
+	g_free(url);
+}
+
 void fb_blist_poke_buddy(PurpleBlistNode *node, gpointer data)
 {
 	PurpleBuddy *buddy;
@@ -594,6 +677,7 @@ void fb_blist_init(FacebookAccount *fba)
 	fba->buddy_list_timer = purple_timeout_add_seconds(60,
 			fb_get_buddy_list, fba);
 
+	fb_get_full_buddy_list(fba);
 }
 
 void fb_blist_destroy(FacebookAccount *fba)
============================================================
--- libpurple/protocols/facebook/fb_blist.h	e77ea2b71a92a022052a1083631d810b540385b4
+++ libpurple/protocols/facebook/fb_blist.h	a663d54c3277085efa235c39cbc950faf816c05c
@@ -32,4 +32,6 @@ void fb_blist_destroy(FacebookAccount *f
 void fb_blist_init(FacebookAccount *fba);
 void fb_blist_destroy(FacebookAccount *fba);
 
+void fb_get_full_buddy_list(FacebookAccount *fba);
+
 #endif /* FACEBOOK_BLIST_H */
============================================================
--- libpurple/protocols/facebook/fb_connection.c	c1ecafbe42cd0342e8d0ab24a052e0258c85e3d5
+++ libpurple/protocols/facebook/fb_connection.c	51f2c6c9baa639ede1d17c752fd02b4ca7ba8187
@@ -21,6 +21,7 @@ static void fb_attempt_connection(Facebo
 #include "fb_connection.h"
 
 static void fb_attempt_connection(FacebookConnection *);
+static void fb_next_connection(FacebookAccount *fba);
 
 #ifdef HAVE_ZLIB
 #include <zlib.h>
@@ -98,6 +99,8 @@ static gchar *fb_gunzip(const guchar *gz
 
 	return g_string_free(output_string, FALSE);
 }
+#else /* !HAVE_ZLIB */
+#warning You really want to compile with -DHAVE_ZLIB
 #endif
 
 void fb_connection_destroy(FacebookConnection *fbconn)
@@ -227,10 +230,12 @@ static void fb_post_or_get_readdata_cb(g
 		PurpleInputCondition cond)
 {
 	FacebookConnection *fbconn;
+	FacebookAccount *fba;
 	gchar buf[4096];
 	ssize_t len;
 
 	fbconn = data;
+	fba = fbconn->fba;
 
 	if (fbconn->method & FB_METHOD_SSL) {
 		len = purple_ssl_read(fbconn->ssl_conn,
@@ -290,6 +295,8 @@ static void fb_post_or_get_readdata_cb(g
 	fb_connection_process_data(fbconn);
 
 	fb_connection_destroy(fbconn);
+	
+	fb_next_connection(fba);
 }
 
 static void fb_post_or_get_ssl_readdata_cb (gpointer data,
@@ -593,9 +600,25 @@ void fb_post_or_get(FacebookAccount *fba
 	fbconn->fd = -1;
 	fbconn->connection_keepalive = keepalive;
 	fbconn->request_time = time(NULL);
-	fba->conns = g_slist_prepend(fba->conns, fbconn);
+	
+	g_queue_push_head(fba->waiting_conns, fbconn);
+	fb_next_connection(fba);
+}
 
-	fb_attempt_connection(fbconn);
+static void fb_next_connection(FacebookAccount *fba)
+{
+	FacebookConnection *fbconn;
+	
+	g_return_if_fail(fba != NULL);	
+	
+	if (!g_queue_is_empty(fba->waiting_conns))
+	{
+		if(g_slist_length(fba->conns) < FB_MAX_CONNECTIONS)
+		{
+			fbconn = g_queue_pop_tail(fba->waiting_conns);
+			fb_attempt_connection(fbconn);
+		}
+	}
 }
 
 static void fb_attempt_connection(FacebookConnection *fbconn)
@@ -621,6 +644,8 @@ static void fb_attempt_connection(Facebo
 	 * runs at blinding speed.  Slow it down. */
 	/* TODO/FIXME: this doesn't retry properly on non-ssl connections */
 #endif
+	
+	fba->conns = g_slist_prepend(fba->conns, fbconn);
 
 	if (fbconn->method & FB_METHOD_SSL) {
 		fbconn->ssl_conn = purple_ssl_connect(fba->account, fbconn->hostname,
============================================================
--- libpurple/protocols/facebook/fb_conversation.c	74b428320820601cd596b8496f17af90b5631045
+++ libpurple/protocols/facebook/fb_conversation.c	2dece593f09b3a8e8a8f18a0b26daad0b9a52240
@@ -91,7 +91,7 @@ void fb_conversation_handle_message(Face
  * HISTORY CODE                                                              *
  *****************************************************************************/
 
-static void fb_history_fetch_cb(FacebookAccount *fba, gchar *data,
+static void fb_history_fetch_cb(FacebookAccount *fba, const gchar *data,
 	gsize data_len, gpointer userdata)
 {
 	JsonParser *parser;
============================================================
--- libpurple/protocols/facebook/fb_friendlist.c	008d6195eb30a403d41c4755c98c5402de4fac31
+++ libpurple/protocols/facebook/fb_friendlist.c	f79866a79682445e0b77bd3d7cfaf014817cfc97
@@ -81,7 +81,7 @@ static void handle_move_request(Facebook
 	g_free(request);
 }
 
-static void create_list_cb(FacebookAccount *fba, gchar *data,
+static void create_list_cb(FacebookAccount *fba, const gchar *data,
 	gsize data_len, gpointer userdata)
 {
 	// NOTE: this method can also be used for movements between
============================================================
--- libpurple/protocols/facebook/fb_info.c	ddcf349b1b8238ecd2ee0a9729a599b8d73fafda
+++ libpurple/protocols/facebook/fb_info.c	67afa65f38125540d235bda3b66cd7dceb54ddd1
@@ -49,7 +49,7 @@ static gchar *fb_remove_useless_stripped
 	return output;
 }
 
-static void fb_get_info_cb(FacebookAccount *fba, gchar *data, gsize data_len, gpointer user_data)
+static void fb_get_info_cb(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer user_data)
 {
 	PurpleNotifyUserInfo *user_info;
 	PurpleBuddyIcon *buddy_icon;
============================================================
--- libpurple/protocols/facebook/fb_managefriends.c	711a945a595b2c353cfa8991e9546b7b90828048
+++ libpurple/protocols/facebook/fb_managefriends.c	46d4a0dc588110af5c4d9ceef4cf8369af7e8586
@@ -77,7 +77,7 @@ static void fb_auth_reject_cb(gpointer d
 	g_free(buddy_uid);
 }
 
-static void fb_check_friend_request_cb(FacebookAccount *fba, gchar *data,
+static void fb_check_friend_request_cb(FacebookAccount *fba, const gchar *data,
 		gsize data_len, gpointer user_data)
 {
 	const char *uid_pre_text = "class=\"confirm\" id=\"friend_connect_";
@@ -89,7 +89,7 @@ static void fb_check_friend_request_cb(F
 	gchar *msg;
 	gchar *msg_plain;
 	FacebookBuddy *buddy;
-	gchar *search_start = data;
+	const gchar *search_start = data;
 
 	g_return_if_fail(data_len > 0);
 	g_return_if_fail(data != NULL);
============================================================
--- libpurple/protocols/facebook/fb_messages.c	9e4b7c098e5407d1d6eafbf51c9f3cc4773e2a24
+++ libpurple/protocols/facebook/fb_messages.c	a68e3d53c5d9556d30ff11a48f4c70fdf56f189a
@@ -40,7 +40,6 @@ static gboolean fb_resend_im_fom(Faceboo
 
 static gboolean fb_send_im_fom(FacebookOutgoingMessage *msg);
 static gboolean fb_resend_im_fom(FacebookOutgoingMessage *msg);
-static gboolean fb_get_new_messages(FacebookAccount *fba);
 
 static FacebookOutgoingMessage *fb_msg_create(FacebookAccount *fba)
 {
@@ -150,7 +149,7 @@ static void parse_new_messages(PurpleCon
 	}
 }
 								  
-static void got_new_messages(FacebookAccount *fba, gchar *data,
+static void got_new_messages(FacebookAccount *fba, const gchar *data,
 		gsize data_len, gpointer userdata)
 {
 	JsonParser *parser;
@@ -258,7 +257,7 @@ static void got_new_messages(FacebookAcc
  * called ONCE and only ONCE.  After that the timers will take care of
  * themselves until final cleanup.
  */
-static gboolean fb_get_new_messages(FacebookAccount *fba)
+gboolean fb_get_new_messages(FacebookAccount *fba)
 {
 	time_t now;
 	gchar *fetch_url;
@@ -304,7 +303,7 @@ static gboolean fb_get_new_messages(Face
 	return FALSE;
 }
 
-static void fb_send_im_cb(FacebookAccount *fba, gchar *data, gsize data_len, gpointer user_data)
+static void fb_send_im_cb(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer user_data)
 {
 	FacebookOutgoingMessage *msg = user_data;
 	JsonParser *parser;
@@ -405,7 +404,7 @@ int fb_send_im(PurpleConnection *pc, con
 	return 1;
 }
 
-void got_reconnect_json(FacebookAccount *fba, gchar *data, gsize data_len, gpointer userdata)
+void got_reconnect_json(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer userdata)
 {
 	JsonParser *parser;
 	JsonObject *objnode;
@@ -462,7 +461,7 @@ gboolean fb_reconnect(FacebookAccount *f
 	return FALSE;
 }
 
-static void got_form_id_page(FacebookAccount *fba, gchar *data, gsize data_len, gpointer userdata)
+static void got_form_id_page(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer userdata)
 {
 	const gchar *start_text = "id=\"post_form_id\" name=\"post_form_id\" value=\"";
 	const gchar *dtsg_start = "fb_dtsg:\"";
@@ -471,6 +470,7 @@ static void got_form_id_page(FacebookAcc
 	gchar *post_form_id;
 	gchar *channel = NULL;
 	gchar *tmp = NULL;
+	FacebookFunc callback;
 	
 	/* NULL data crashes on Windows */
 	if (data == NULL)
@@ -516,22 +516,16 @@ static void got_form_id_page(FacebookAcc
 		g_free(fba->channel_number);
 		fba->channel_number = channel;
 	}
-
-	tmp = g_strdup_printf("visibility=true&post_form_id=%s", post_form_id);
-	fb_post_or_get(fba, FB_METHOD_POST, "apps.facebook.com", "/ajax/chat/settings.php", tmp, NULL, NULL, FALSE);
-	g_free(tmp);
 	
-	if (channel == NULL)
+	if (userdata)
 	{
-		/* Grab new channel number */
-		fb_reconnect(fba);
-	} else {
-		fb_get_new_messages(fba);
+		callback = userdata;
+		callback(fba);
 	}
 }
 
-gboolean fb_get_post_form_id(FacebookAccount *fba)
+gboolean fb_get_post_form_id(FacebookAccount *fba, FacebookFunc callback)
 {
-	fb_post_or_get(fba, FB_METHOD_GET, NULL, "/presence/popout.php", NULL, got_form_id_page, NULL, FALSE);
+	fb_post_or_get(fba, FB_METHOD_GET, NULL, "/presence/popout.php", NULL, got_form_id_page, callback, FALSE);
 	return FALSE;
 }
============================================================
--- libpurple/protocols/facebook/fb_messages.h	aaab76c0a6d161f4e6e522833e4aae633a952997
+++ libpurple/protocols/facebook/fb_messages.h	7ecfce3f7074f5876a23403922ec0ae691eaedde
@@ -23,11 +23,13 @@
 
 #include "libfacebook.h"
 
-gboolean fb_get_post_form_id(FacebookAccount *fba);
+gboolean fb_get_post_form_id(FacebookAccount *fba, FacebookFunc callback);
 gboolean fb_reconnect(FacebookAccount *fba);
 int fb_send_im(PurpleConnection *pc, const gchar *who, const gchar *message,
 		PurpleMessageFlags flags);
 
 void fb_cancel_resending_messages(FacebookAccount *fba);
 
+gboolean fb_get_new_messages(FacebookAccount *fba);
+
 #endif /* FACEBOOK_MESSAGES_H */
============================================================
--- libpurple/protocols/facebook/fb_notifications.c	4dfffc8a8452bc56f856c94b2dec1e27d6287ca4
+++ libpurple/protocols/facebook/fb_notifications.c	3358d387fd6f063dd96182632bf38084f62bdcf3
@@ -21,7 +21,7 @@
 #include "fb_notifications.h"
 #include "fb_connection.h"
 
-static void fb_got_notifications_cb(FacebookAccount *fba, gchar *url_text, gsize len, gpointer userdata)
+static void fb_got_notifications_cb(FacebookAccount *fba, const gchar *url_text, gsize len, gpointer userdata)
 {
 	gchar *salvaged;
 	time_t last_fetch_time;
@@ -138,7 +138,7 @@ static void fb_got_notifications_cb(Face
 	}
 }
 
-static void find_feed_url_cb(FacebookAccount *fba, gchar *data, gsize data_len, gpointer userdata)
+static void find_feed_url_cb(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer userdata)
 {
 	const gchar *search_string = "/feeds/notifications.php";
 	gchar *feed_url;
============================================================
--- libpurple/protocols/facebook/fb_search.c	7e2e0235ae16731b82bb781e8e1d05c3b78a4c5a
+++ libpurple/protocols/facebook/fb_search.c	5fe1103a70f6d161889aa7658b41b35399fac8a0
@@ -42,12 +42,13 @@ static void fb_searchresults_info_buddy(
 		fb_get_info(pc, g_list_nth_data(row, 0));
 }
 
-static void fb_found_friends(FacebookAccount *fba, gchar *data,
+static void fb_found_friends(FacebookAccount *fba, const gchar *data,
 		gsize data_len, gpointer user_data)
 {
 	PurpleNotifySearchResults *results;
 	PurpleNotifySearchColumn *column;
-	gchar *id, *tmp, *stripped, *last_id_pos = 0, *id_pos = data;
+	gchar *id, *tmp, *stripped;
+	const gchar *id_pos = data, *last_id_pos = 0;
 	gchar *search_term = user_data;
 	const gchar *id_search_term =
 			"facebook.com/inbox/?compose&amp;id="; /* " */
============================================================
--- libpurple/protocols/facebook/fb_util.c	db25bbe26ed405a613ac050b45a0567df3ee5aa8
+++ libpurple/protocols/facebook/fb_util.c	892bc0b45bd3472256d7c28b4e3952a760abbabd
@@ -283,3 +283,19 @@ gchar *fb_replace_styled_text(const gcha
 #endif /*__ARM_EABI__*/
 }
 
+gchar *fb_md5_encode(const gchar *string)
+{
+	PurpleCipher *cipher;
+	PurpleCipherContext *context;
+	gchar md5Hash[33];
+	
+	cipher = purple_ciphers_find_cipher("md5");
+	context = purple_cipher_context_new(cipher, NULL);
+
+	purple_cipher_context_append(context, (guchar *)string, strlen(string));
+	purple_cipher_context_digest_to_str(context, sizeof(md5Hash), md5Hash, NULL);
+	purple_cipher_context_destroy(context);
+	
+	return g_strdup(md5Hash);
+}
+
============================================================
--- libpurple/protocols/facebook/fb_util.h	97d1d52c6ee49b764654ac3ae448284bfa071c81
+++ libpurple/protocols/facebook/fb_util.h	2b0447d3d889abed3c90b5c633c11edab4179255
@@ -24,6 +24,8 @@
 #include "libfacebook.h"
 #include "fb_json.h"
 
+#include <cipher.h>
+
 JsonParser *fb_get_parser(const gchar *data, gsize data_len);
 JsonObject *fb_get_json_object(JsonParser *parser, char **error_message);
 
@@ -31,6 +33,7 @@ gint64 fb_time_kludge(gint64 initial_tim
 gchar *fb_strdup_withhtml(const gchar *src);
 gchar *fb_convert_unicode(const gchar *input);
 gint64 fb_time_kludge(gint64 initial_time);
+gchar *fb_md5_encode(const gchar *string);
 
 #endif /* FACEBOOK_UTIL_H */
 
============================================================
--- libpurple/protocols/facebook/libfacebook.c	fa11c84086db93bf96b87de14a10d37ddc540995
+++ libpurple/protocols/facebook/libfacebook.c	26b3f5f2fae2cd652f04d3dfd42b1c83525e6c51
@@ -29,7 +29,7 @@
 #include "fb_search.h"
 #include "fb_friendlist.h"
 
-static void fb_login_cb(FacebookAccount *fba, gchar *response, gsize len,
+static void fb_login_cb(FacebookAccount *fba, const gchar *response, gsize len,
 		gpointer userdata);
 static void fb_close(PurpleConnection *pc);
 static void fb_buddy_free(PurpleBuddy *buddy);
@@ -96,6 +96,23 @@ static GList *fb_statuses(PurpleAccount 
 	return types;
 }
 
+void fb_post_form_id_cb(FacebookAccount *fba)
+{
+	gchar *tmp;
+	
+	tmp = g_strdup_printf("visibility=true&post_form_id=%s", fba->post_form_id);
+	fb_post_or_get(fba, FB_METHOD_POST, "apps.facebook.com", "/ajax/chat/settings.php", tmp, NULL, NULL, FALSE);
+	g_free(tmp);
+	
+	if (fba->channel_number == NULL)
+	{
+		/* Grab new channel number */
+		fb_reconnect(fba);
+	} else {
+		fb_get_new_messages(fba);
+	}
+}
+
 static gboolean fb_get_messages_failsafe(FacebookAccount *fba)
 {
 	if (fba->last_messages_download_time < (time(NULL) - (60*5))) {
@@ -103,7 +120,7 @@ static gboolean fb_get_messages_failsafe
 		 * something is probably wrong */
 		purple_debug_warning("facebook",
 				"executing message check failsafe\n");
-		fb_get_post_form_id(fba);
+		fb_get_post_form_id(fba, fb_post_form_id_cb);
 	}
 
 	return TRUE;
@@ -173,7 +190,7 @@ void fb_login_captcha_ok_cb(PurpleConnec
 	fba->captcha_session = NULL;
 }
 
-static void fb_login_captcha_image_cb(FacebookAccount *fba, gchar *response, 
+static void fb_login_captcha_image_cb(FacebookAccount *fba, const gchar *response, 
 		gsize len, gpointer userdata)
 {
 	PurpleRequestFields *fields;
@@ -200,7 +217,7 @@ static void fb_login_captcha_image_cb(Fa
 	);
 }
 
-static void fb_login_captcha_cb(FacebookAccount *fba, gchar *response, 
+static void fb_login_captcha_cb(FacebookAccount *fba, const gchar *response, 
 		gsize len, gpointer userdata)
 {
 	const gchar *challenge_start = "challenge : '";
@@ -220,7 +237,7 @@ static void fb_login_captcha_cb(Facebook
 	}
 }
 
-static void fb_login_cb(FacebookAccount *fba, gchar *response, gsize len,
+static void fb_login_cb(FacebookAccount *fba, const gchar *response, gsize len,
 		gpointer userdata)
 {
 	gchar *user_cookie;
@@ -305,7 +322,7 @@ static void fb_login_cb(FacebookAccount 
 	purple_connection_set_state(fba->pc, PURPLE_CONNECTED);
 
 	/* This will kick off our long-poll message retrieval loop */
-	fb_get_post_form_id(fba);
+	fb_get_post_form_id(fba, &fb_post_form_id_cb);
 	fb_check_friend_requests(fba);
 
 	/* periodically check for people adding you to their facebook friend list */
@@ -337,13 +354,62 @@ static void fb_login_cb(FacebookAccount 
 	fb_conversation_init(fba);
 }
 
-static void fb_login(PurpleAccount *account)
+gboolean fb_do_http_login(FacebookAccount *fba, 
+		FacebookProxyCallbackFunc callback_func, gpointer user_data)
 {
-	FacebookAccount *fba;
 	gchar *postdata, *encoded_username, *encoded_password, *encoded_charset_test;
 	const gchar* const *languages;
 	const gchar *locale;
 	
+	if (fba == NULL)
+		return FALSE;
+	
+	/* Error localized in libpurple jabber.c */
+	if (!purple_ssl_is_supported()) {
+		purple_connection_error_reason (fba->pc,
+										PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+										_("Server requires TLS/SSL for login.  No TLS/SSL support found."));
+		return FALSE;
+	}
+	
+	if (fba->cookie_table == NULL)
+		fba->cookie_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	if (fba->hostname_ip_cache == NULL)
+		fba->hostname_ip_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	if (fba->waiting_conns == NULL)
+		fba->waiting_conns = g_queue_new();
+	
+	g_hash_table_replace(fba->cookie_table, g_strdup("test_cookie"), g_strdup("1"));
+	g_hash_table_replace(fba->cookie_table, g_strdup("lsd"), g_strdup("abcde"));
+	
+	encoded_username = g_strdup(purple_url_encode(purple_account_get_username(fba->account)));
+	encoded_password = g_strdup(purple_url_encode(purple_account_get_password(fba->account)));
+	encoded_charset_test = g_strdup(purple_url_encode("EUR,?,EUR,?,?,?,?"));
+	languages = g_get_language_names();
+	locale = languages[0];
+	if (locale == NULL || g_str_equal(locale, "C"))
+		locale = "en_US";
+	
+	postdata = g_strdup_printf("charset_test=%s&locale=%s&email=%s&pass=%s&"
+							   "pass_placeHolder=Password&persistent=1&"
+							   "login=Login&charset_test=%s&lsd=abcde",
+							   encoded_charset_test, locale, encoded_username, 
+							   encoded_password, encoded_charset_test);
+	g_free(encoded_username);
+	g_free(encoded_password);
+	g_free(encoded_charset_test);
+	
+	fb_post_or_get(fba, FB_METHOD_POST | FB_METHOD_SSL, "login.facebook.com",
+				   "/login.php?login_attempt=1&_fb_noscript=1", postdata, callback_func, user_data, FALSE);
+	g_free(postdata);
+	
+	return TRUE;
+}
+
+static void fb_login(PurpleAccount *account)
+{
+	FacebookAccount *fba;
+	
 	/* Create account and initialize state */
 	fba = g_new0(FacebookAccount, 1);
 	fba->account = account;
@@ -359,44 +425,12 @@ static void fb_login(PurpleAccount *acco
 	fba->auth_buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
 			g_free, NULL);
 
-	g_hash_table_replace(fba->cookie_table, g_strdup("test_cookie"),
-			g_strdup("1"));
-
 	account->gc->proto_data = fba;
 
-	/* Error localized in libpurple jabber.c */
-	if (!purple_ssl_is_supported()) {
-		purple_connection_error_reason (purple_account_get_connection(account),
-				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-				_("Server requires TLS/SSL for login.  No TLS/SSL support found."));
-		return;
-	}
-
 	purple_connection_set_state(fba->pc, PURPLE_CONNECTING);
 	purple_connection_update_progress(fba->pc, _("Connecting"), 1, 3);
 
-	encoded_username = g_strdup(purple_url_encode(
-			purple_account_get_username(fba->account)));
-	encoded_password = g_strdup(purple_url_encode(
-			purple_account_get_password(fba->account)));
-	encoded_charset_test = g_strdup(purple_url_encode("EUR,?,EUR,?,?,?,?"));
-	languages = g_get_language_names();
-	locale = languages[0];
-	if (locale == NULL || g_str_equal(locale, "C"))
-		locale = "en_US";
-
-	g_hash_table_replace(fba->cookie_table, g_strdup("lsd"), g_strdup("abcde"));
-
-	postdata = g_strdup_printf(
-			"charset_test=%s&locale=%s&email=%s&pass=%s&pass_placeHolder=Password&persistent=1&login=Login&charset_test=%s&lsd=abcde",
-			encoded_charset_test, locale, encoded_username, encoded_password, encoded_charset_test);
-	g_free(encoded_username);
-	g_free(encoded_password);
-	g_free(encoded_charset_test);
-
-	fb_post_or_get(fba, FB_METHOD_POST | FB_METHOD_SSL, "login.facebook.com",
-			"/login.php?login_attempt=1&_fb_noscript=1", postdata, fb_login_cb, NULL, FALSE);
-	g_free(postdata);
+	fb_do_http_login(fba, fb_login_cb, NULL);
 }
 
 static void fb_close(PurpleConnection *pc)
@@ -438,7 +472,14 @@ static void fb_close(PurpleConnection *p
 	if (fba->perpetual_messages_timer) {
 		purple_timeout_remove(fba->perpetual_messages_timer);
 	}
-
+	
+	purple_debug_info("facebook", "destroying %d waiting connections\n",
+					  g_queue_get_length(fba->waiting_conns));
+	
+	while (!g_queue_is_empty(fba->waiting_conns))
+		fb_connection_destroy(g_queue_pop_tail(fba->waiting_conns));
+	g_queue_free(fba->waiting_conns);
+	
 	purple_debug_info("facebook", "destroying %d incomplete connections\n",
 			g_slist_length(fba->conns));
 
@@ -457,6 +498,7 @@ static void fb_close(PurpleConnection *p
 		fb_cancel_resending_messages(fba);
 	}
 
+	g_hash_table_destroy(fba->sent_messages_hash);
 	g_hash_table_destroy(fba->cookie_table);
 	g_hash_table_destroy(fba->hostname_ip_cache);
 	g_hash_table_destroy(fba->auth_buddies);
@@ -548,9 +590,13 @@ static void fb_set_status_p(PurpleAccoun
 	FacebookAccount *fba = account->gc->proto_data;
 
 	/* if "away" set idle */
-	if (fba && purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_AWAY)
+	if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_AWAY)
 	{
-		fba->is_idle = TRUE;	
+		if (fba)
+		{
+			fba->is_idle = TRUE;
+		}
+		return;
 	}
 
 	/* first check that we actually want to set this through Pidgin */
============================================================
--- libpurple/protocols/facebook/libfacebook.h	f4be461d1adef3dd6cec62c050ba9e9f3953f3cf
+++ libpurple/protocols/facebook/libfacebook.h	c7f920d377b94b738396470d9fe9a34ba09fcbbf
@@ -21,10 +21,13 @@
 #ifndef LIBFACEBOOK_H
 #define LIBFACEBOOK_H
 
-#define FACEBOOK_PLUGIN_VERSION "1.64"
+#define FACEBOOK_PLUGIN_VERSION "1.65"
 #define FACEBOOK_PLUGIN_ID "prpl-bigbrownchunx-facebookim"
 #define FACEBOOK_CAPTCHA_SITE "6LezHAAAAAAAADqVjseQ3ctG3ocfQs2Elo1FTa_a"
 
+/* Maximum number of simultaneous connections to a server */
+#define FB_MAX_CONNECTIONS 32
+
 #include <glib.h>
 
 #include <errno.h>
@@ -77,12 +80,14 @@ typedef struct _FacebookBuddy FacebookBu
 typedef struct _FacebookAccount FacebookAccount;
 typedef struct _FacebookBuddy FacebookBuddy;
 
-typedef void (*FacebookProxyCallbackFunc)(FacebookAccount *fba, gchar *data, gsize data_len, gpointer user_data);
+typedef void (*FacebookProxyCallbackFunc)(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer user_data);
+typedef void (*FacebookFunc)(FacebookAccount *fba);
 
 struct _FacebookAccount {
 	PurpleAccount *account;
 	PurpleConnection *pc;
 	GSList *conns; /**< A list of all active FacebookConnections */
+	GQueue *waiting_conns; /**< A list of all FacebookConnections waiting to process */
 	GSList *dns_queries;
 	GHashTable *cookie_table;
 	gchar *post_form_id;
@@ -122,4 +127,8 @@ struct _FacebookBuddy {
 	gchar *thumb_url;
 };
 
+
+gboolean fb_do_http_login(FacebookAccount *fba, 
+		FacebookProxyCallbackFunc callback_func, gpointer user_data);
+
 #endif /* LIBFACEBOOK_H */
============================================================
--- libpurple/protocols/facebook/pidgin-facebookchat.rc	7315a1099a7e1134eee2f5d9079b10f38583caeb
+++ libpurple/protocols/facebook/pidgin-facebookchat.rc	ad98bb312d865fa1422790bf78d4e9d3730582f8
@@ -1,7 +1,7 @@ 1 VERSIONINFO
 
 1 VERSIONINFO
-FILEVERSION 1,64,0,0
-PRODUCTVERSION 1,64,0,0
+FILEVERSION 1,65,0,0
+PRODUCTVERSION 1,65,0,0
 FILEOS 0x40004 // VOS_NT_WINDOWS32
 FILETYPE 0x2 // VFT_DLL
 {
@@ -12,8 +12,8 @@ BLOCK "StringFileInfo"
 		VALUE "CompanyName", "Eion Robb\0"
 		VALUE "FileDescription",  "Facebook Chat plugin for Pidgin\0"
 		VALUE "ProductName", "pidgin-facebookchat\0"
-		VALUE "FileVersion", "1.64\0"
-		VALUE "ProductVersion", "1.64\0"
+		VALUE "FileVersion", "1.65\0"
+		VALUE "ProductVersion", "1.65\0"
 		VALUE "InternalName", "pidgin-facebookchat\0"
 		VALUE "OriginalFilename", "libfacebook.dll\0"
 		VALUE "Comments", "http://pidgin-facebookchat.googlecode.com/\0"
============================================================
--- libpurple/protocols/facebook/rss.xml	18460f314830faedf07748921a27b26307716023
+++ libpurple/protocols/facebook/rss.xml	567c3aa5d4fa196f8211764630cd6d709b89aa31
@@ -13,6 +13,37 @@
 			<width>48</width><height>48</height>
 		</image>
 		<item>
+			<title>Version 1.65</title>
+			<link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c53</link>
+			<description><![CDATA[Hi all. Been a wee while since the last version of the plugin.  This version has a 
+			fix for newer buddy icons being too small, and also downloads all your offline 
+			buddies as well as your online ones.<br/>
+			Download from usual place<br/>
+			<a href="http://code.google.com/p/pidgin-facebookchat/wiki/Downloads">http://code.google.com/p/pidgin-facebookchat/wiki/Downloads</a><br/>
+			<br/>
+			Also, in case you haven't heard, Facebook has come out with an XMPP interface (so 
+			you dont *have* to use this plugin to connect to FB anymore).  I'm currently 
+			working on rewriting a new, more stable version 2.0 of the plugin, which will use 
+			XMPP, while filling in some of the gaps of features that you're all used to by now :)<br/>]]></description>
+			<pubDate>Fri 26 Feb 2010 14:40:29 +1300</pubDate>
+			<guid isPermaLink="true">http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c53</guid>
+		</item>
+		<item>
+			<title>Version 1.64</title>
+			<link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c52</link>
+			<description><![CDATA[I've just dropped v1.64 out for download at<br/>
+			<a href="http://code.google.com/p/pidgin-facebookchat/wiki/Downloads">http://code.google.com/p/pidgin-facebookchat/wiki/Downloads</a><br/>
+			<br/>
+			It fixes up some really annoying things like buddy icons not working and some strange status message stuffs.<br/>
+			<br/>
+			Changelog:<br/>
+			<a href="http://code.google.com/p/pidgin-facebookchat/wiki/Changelog">http://code.google.com/p/pidgin-facebookchat/wiki/Changelog</a><br/>
+			<br/>
+			(Apologies to rss feed subscribers for the slow post) ]]></description>
+			<pubDate>Fri 4 December 2009 17:43:30 +1300</pubDate>
+			<guid isPermaLink="true">http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c52</guid>
+		</item>
+		<item>
 			<title>Version 1.63</title>
 			<link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c51</link>
 			<description><![CDATA[Just pushed out v1.63 which fixes up a few of the little annoying things that didn't 


More information about the Commits mailing list