adium: 9f8d02d7: pidgin-facebookchat at r620.
zacw at adiumx.com
zacw at adiumx.com
Sun Jul 12 22:30:37 EDT 2009
-----------------------------------------------------------------
Revision: 9f8d02d7c2a00b146da385054661d2e467eb46f2
Ancestor: 534ffccfd244372a8f2569168b1bc15b8c9d9054
Author: zacw at adiumx.com
Date: 2009-07-13T02:28:54
Branch: im.pidgin.adium
URL: http://d.pidgin.im/viewmtn/revision/info/9f8d02d7c2a00b146da385054661d2e467eb46f2
Added files:
libpurple/protocols/facebook/fb_friendlist.c
libpurple/protocols/facebook/fb_friendlist.h
Modified files:
libpurple/protocols/facebook/Makefile.am
libpurple/protocols/facebook/facebook.nsi
libpurple/protocols/facebook/fb_blist.c
libpurple/protocols/facebook/fb_blist.h
libpurple/protocols/facebook/fb_conversation.c
libpurple/protocols/facebook/fb_info.c
libpurple/protocols/facebook/fb_managefriends.c
libpurple/protocols/facebook/fb_messages.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
ChangeLog:
pidgin-facebookchat at r620.
-------------- next part --------------
============================================================
--- libpurple/protocols/facebook/fb_friendlist.c 75b0969a59d34b7145d1fe3c6e4121ab9f2d9ed3
+++ libpurple/protocols/facebook/fb_friendlist.c 75b0969a59d34b7145d1fe3c6e4121ab9f2d9ed3
@@ -0,0 +1,467 @@
+/*
+ * libfacebook
+ *
+ * libfacebook is the property of its developers. See the COPYRIGHT file
+ * for more details.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fb_friendlist.h"
+#include "fb_connection.h"
+#include "libfacebook.h"
+#include "fb_util.h"
+
+typedef struct _MoveRequest MoveRequest;
+struct _MoveRequest {
+ char *old_group;
+ char *new_group;
+ char *who;
+};
+
+/******************************************************************************/
+/* Friend list modification methods */
+/******************************************************************************/
+static void handle_move_request(FacebookAccount *fba, MoveRequest *request)
+{
+ const gchar *old_list_id;
+ const gchar *new_list_id;
+ gchar *postdata;
+ gboolean remove_flist, no_original_list;
+ const gchar *command;
+
+ purple_debug_info("facebook",
+ "handling movement of %s from %s to %s\n",
+ request->who, request->old_group, request->new_group);
+
+ old_list_id = fb_get_list_id(fba, request->old_group);
+ new_list_id = fb_get_list_id(fba, request->new_group);
+
+ remove_flist = !new_list_id || !strcmp(new_list_id, "-1");
+ no_original_list = !old_list_id || !strcmp(old_list_id, "-1");
+
+ if (remove_flist) {
+ command = "&remove_fl=true";
+ } else if (no_original_list) {
+ command = "&add_fl=true";
+ } else {
+ command = "&move_fl=true";
+ }
+
+ postdata = g_strdup_printf(
+ "post_form_id=%s&drag_uid=%s&user=%" G_GINT64_FORMAT
+ "&new_flid=%s&old_flid=%s%s",
+ fba->post_form_id,
+ request->who,
+ fba->uid,
+ remove_flist ? "" : new_list_id,
+ no_original_list ? "" : old_list_id,
+ command);
+
+ fb_post_or_get(fba, FB_METHOD_POST, NULL,
+ "/ajax/chat/buddy_list_settings.php",
+ postdata, NULL, NULL, FALSE);
+
+ g_free(postdata);
+
+ g_free(request->who);
+ g_free(request->old_group);
+ g_free(request->new_group);
+ g_free(request);
+}
+
+static void create_list_cb(FacebookAccount *fba, gchar *data,
+ gsize data_len, gpointer userdata)
+{
+ // NOTE: this method can also be used for movements between
+ // friend lists if necessary.
+
+ JsonParser *parser;
+ JsonObject *objnode;
+ MoveRequest *request;
+
+ // Parse out old data.
+ parser = fb_get_parser(data, data_len);
+ if (parser == NULL) {
+ return;
+ }
+
+ objnode = fb_get_json_object(parser, NULL);
+ if (!objnode ||
+ !json_object_has_member(objnode, "payload"))
+ {
+ g_object_unref(parser);
+ return;
+ }
+
+ objnode = json_node_get_object(json_object_get_member(
+ objnode, "payload"));
+ fb_process_friend_lists(fba, objnode);
+
+ g_object_unref(parser);
+
+ // Move Friend
+ request = (MoveRequest *) userdata;
+ if (request) {
+ handle_move_request(fba, request);
+ }
+}
+
+static void create_friend_list(FacebookAccount *fba, const gchar *new_group,
+ MoveRequest *request)
+{
+ gchar *postdata;
+ gchar *new_group_escaped;
+
+ purple_debug_info("facebook", "creating friend list %s\n", new_group);
+
+ new_group_escaped = fb_strdup_withhtml(new_group);
+
+ postdata = g_strdup_printf(
+ "post_form_id=%s&create=%s&user=%" G_GINT64_FORMAT,
+ fba->post_form_id,
+ new_group_escaped,
+ fba->uid);
+
+ fb_post_or_get(fba, FB_METHOD_POST, NULL,
+ "/ajax/chat/buddy_list_settings.php",
+ postdata, create_list_cb, request, FALSE);
+
+ g_free(postdata);
+ g_free(new_group_escaped);
+}
+
+void fb_group_buddy_move(PurpleConnection *pc, const char *who,
+ const char *old_group, const char *new_group)
+{
+ FacebookAccount *fba;
+ MoveRequest *request;
+ const gchar *new_list_id;
+
+ fba = pc->proto_data;
+
+ purple_debug_info("facebook", "handling move of %s from %s to %s\n",
+ who, old_group, new_group);
+
+ // Don't do anything if groups are not actually changing.
+ if (!strcmp(old_group, new_group)) {
+ purple_debug_info("facebook", "groups are same, not moving\n");
+ return;
+ }
+
+ // Facebook doesn't support moving yourself because you can't be in a
+ // friend list. Let buddy list be updated as appropriate.
+ if (atoll(who) == fba->uid) {
+ purple_debug_info("facebook",
+ "moving self, do not update server\n");
+ return;
+ }
+
+ request = g_new0(MoveRequest, 1);
+ request->old_group = g_strdup(old_group);
+ request->new_group = g_strdup(new_group);
+ request->who = g_strdup(who);
+
+ new_list_id = fb_get_list_id(fba, request->new_group);
+ if (new_list_id) {
+ handle_move_request(fba, request);
+ } else {
+ create_friend_list(fba, new_group, request);
+ }
+}
+
+void fb_buddy_remove(PurpleConnection *pc, PurpleBuddy *buddy,
+ PurpleGroup *group)
+{
+ // This method should only remove a buddy from a friend list.
+ // Nothing more. It should not defriend a user ever. See issue
+ // #185 for a good explaination of why this is a bad idea.
+ //
+ // Moreover, defriending is such a rare operation that we should
+ // never make it easy. Facebook intentionally hides such a action
+ // behind multiple layers of links and dialogs.
+ //
+ // If the plugin is ever to perform an actual defriending, it needs
+ // to provide a dialog and user prompt at the absolute bare minimum.
+ FacebookAccount *fba;
+
+ purple_debug_info("facebook", "handing removal of buddy %s\n",
+ buddy->name);
+
+ fba = pc->proto_data;
+
+ fb_group_buddy_move(pc, buddy->name, purple_group_get_name(group),
+ DEFAULT_GROUP_NAME);
+}
+
+void fb_group_rename(PurpleConnection *pc, const char *old_name,
+ PurpleGroup *group, GList *moved_buddies)
+{
+ purple_debug_info("facebook",
+ "handling group rename of %s to %s\n",
+ old_name, purple_group_get_name(group));
+
+ // We don't do anything here. Facebook's AJAX API for renaming groups
+ // is horribly, horribly overcomplicated. There is no simple rename
+ // call, instead you must also pass in all the current data about the
+ // friend list and port it over. While it is possible to implement
+ // this, it is risky and could potentially destroy a friend list if
+ // the API changes. That's a Bad Thing(tm). Given the risk involved
+ // with this operation and how rare it is, it's not worth it.
+ //
+ // The problem is compounded by the fact that renaming groups triggers
+ // all sorts of weird behaviors in Pidgin. Renaming to a new name is
+ // simple. Renaming to an existing group name (hence a merge)
+ // triggers completely different behavior with calls to group_buddy
+ // before the call to rename. This completely defeats the purpose of
+ // having a rename function because group_buddy is called instead.
+ //
+ // Thus, the final decision is to use the buddy_move call.
+
+ // TODO: warn users that renaming has no effect here.
+}
+
+void fb_group_remove(PurpleConnection *pc, PurpleGroup *group)
+{
+ purple_debug_info("facebook", "got group removal of %s\n",
+ purple_group_get_name(group));
+
+ // We don't do anything here. This is because a group rename also
+ // fires a group removal event. This assumes that the new group is
+ // equivalent to the old group, but Facebook friend lists are much more
+ // than simple groups- they are privacy control lists too. There is
+ // no easy way to port the settings between groups. Better off not
+ // deleting, and the user can do the cleanup with their browser.
+}
+
+/******************************************************************************/
+/* Friend list fetch methods */
+/******************************************************************************/
+
+const gchar *fb_get_list_id(FacebookAccount *fba, const gchar *list_name)
+{
+ if (!strcmp(list_name, DEFAULT_GROUP_NAME)) {
+ return "-1";
+ }
+
+ return g_hash_table_lookup(fba->friend_lists_reverse, list_name);
+}
+
+gboolean fb_process_friend_lists(FacebookAccount *fba,
+ JsonObject *buddy_list)
+{
+ JsonObject *fl_obj;
+ GList *friend_list_ids, *cur;
+
+ purple_debug_info("facebook", "processing friend list data\n");
+
+ if (!json_object_has_member(buddy_list, "flData"))
+ {
+ purple_debug_info("facebook", "no friend list data\n");
+ return FALSE;
+ }
+
+
+ fl_obj = json_node_get_object(json_object_get_member(
+ buddy_list, "flData"));
+ friend_list_ids = json_object_get_members(fl_obj);
+ for (cur = friend_list_ids; cur != NULL; cur = cur->next)
+ {
+ const gchar *id;
+ const gchar *name;
+ JsonObject *data;
+
+ id = (gchar *) cur->data;
+ data = json_node_get_object(json_object_get_member(
+ fl_obj, id));
+ name = json_node_get_string(json_object_get_member(
+ data, "n"));
+ if (name) {
+ // Either -1 isnt a valid JSON string or JSON-glib does
+ // this wrong. I'm too tired to tell the difference.
+ if (!strcmp(id, "_1")) {
+ id = "-1";
+ }
+ purple_debug_info("facebook",
+ "got friend list %s with id %s\n",
+ name, id);
+ g_hash_table_insert(fba->friend_lists,
+ g_strdup(id), g_strdup(name));
+ g_hash_table_insert(fba->friend_lists_reverse,
+ g_strdup(name), g_strdup(id));
+ }
+ }
+
+ g_list_free(friend_list_ids);
+
+ return TRUE;
+}
+
+static void destroy_buddy(gpointer key, gpointer value, gpointer data)
+{
+ PurpleBuddy *buddy;
+ gchar *group_name;
+ FacebookAccount *fba;
+
+ buddy = (PurpleBuddy *) value;
+ group_name = (gchar *) key;
+ fba = (FacebookAccount *) data;
+
+ purple_debug_info("facebook", "removing %s from group %s\n",
+ buddy->name, group_name);
+ if (atoll(buddy->name) == fba->uid) {
+ purple_debug_info("facebook", "not removing self from %s\n",
+ group_name);
+ return;
+ }
+
+ purple_blist_remove_buddy(buddy);
+}
+
+static PurpleBuddy *add_buddy(FacebookAccount *fba,
+ const gchar *friend_list_id, const gchar *uid, GHashTable *cur_groups)
+{
+ const gchar *group_name;
+ PurpleGroup *fb_group;
+ PurpleBuddy *buddy;
+
+ group_name = g_hash_table_lookup(fba->friend_lists, friend_list_id);
+ if (!group_name || !strcmp(group_name, "")) {
+ purple_debug_info("facebook",
+ "did not find name of list %s\n",
+ friend_list_id);
+ group_name = DEFAULT_GROUP_NAME;
+ }
+
+ // Initialize group as necessary.
+ fb_group = purple_find_group(group_name);
+ if (fb_group == NULL)
+ {
+ purple_debug_info("facebook", "adding friend list %s\n",
+ group_name);
+ fb_group = purple_group_new(group_name);
+ purple_blist_add_group(fb_group, NULL);
+ }
+
+ buddy = (PurpleBuddy *)g_hash_table_lookup(cur_groups, group_name);
+ if (!buddy) {
+ purple_debug_info("facebook", "adding %s to %s\n",
+ uid, group_name);
+ buddy = purple_buddy_new(fba->account, uid, NULL);
+ purple_blist_add_buddy(buddy, NULL, fb_group, NULL);
+ g_hash_table_remove(cur_groups, group_name);
+ }
+
+ return buddy;
+}
+
+
+GList *fb_get_buddies_friend_list (FacebookAccount *fba,
+ const gchar *uid, JsonArray *friend_list_ids)
+{
+ GSList *buddies;
+ GSList *cur;
+ GHashTable *cur_groups;
+ int i;
+ GList *final_buddies, *cur_buddy;
+
+ final_buddies = NULL;
+ buddies = purple_find_buddies(fba->account, uid);
+
+ // If we're already in the buddy list, stop. Ignore FB info because
+ // it will be incorrect.
+ if (atoll(uid) == fba->uid && buddies != NULL) {
+ purple_debug_info("facebook",
+ "already have buddies for self, not adding\n");
+ for (cur = buddies; cur != NULL; cur = cur->next)
+ {
+ final_buddies = g_list_append(
+ final_buddies, cur->data);
+ }
+ g_slist_free(buddies);
+ return final_buddies;
+ }
+
+ // Determine what buddies exist and what groups they are in.
+ cur_groups = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+ for (cur = buddies; cur != NULL; cur = cur->next)
+ {
+ const gchar *group_name;
+
+ group_name = purple_group_get_name(purple_buddy_get_group(
+ (PurpleBuddy *)cur->data));
+
+ g_hash_table_insert(cur_groups, g_strdup(group_name), cur->data);
+ }
+ g_slist_free(buddies);
+
+ // Create/insert necessary buddies
+ if (friend_list_ids) {
+ for (i = 0; i < json_array_get_length(friend_list_ids); i++)
+ {
+ const gchar *friend_list_id;
+ PurpleBuddy *buddy;
+
+ friend_list_id = json_node_get_string(
+ json_array_get_element(friend_list_ids, i));
+
+ buddy = add_buddy(fba, friend_list_id, uid, cur_groups);
+
+ final_buddies = g_list_append(final_buddies, buddy);
+ }
+ } else {
+ // No friend list data, so we use the default group.
+ final_buddies = g_list_append(final_buddies,
+ add_buddy(fba, "-1", uid, cur_groups));
+ }
+
+ // Figure out which groups/buddies are not represented.
+ for (cur_buddy = final_buddies; cur_buddy != NULL;
+ cur_buddy = cur_buddy->next)
+ {
+ g_hash_table_remove(cur_groups, purple_group_get_name(
+ purple_buddy_get_group(
+ (PurpleBuddy *)cur_buddy->data)));
+ }
+
+ // Delete remaining buddies to maintain sync state with server.
+ g_hash_table_foreach(cur_groups, destroy_buddy, fba);
+
+ // Cleanup!
+ g_hash_table_destroy(cur_groups);
+
+ return final_buddies;
+}
+
+void fb_friendlist_init(FacebookAccount *fba)
+{
+ /* data structure mapping friend list id to name. libpurple only
+ * recognizes name, does not have group aliases */
+ fba->friend_lists = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+ /* structure mapping names to list id for speed. */
+ fba->friend_lists_reverse = g_hash_table_new_full(g_str_hash,
+ g_str_equal, g_free, g_free);
+}
+
+void fb_friendlist_destroy(FacebookAccount *fba)
+{
+ if (fba->friend_lists) {
+ g_hash_table_destroy(fba->friend_lists);
+ }
+ if (fba->friend_lists_reverse) {
+ g_hash_table_destroy(fba->friend_lists_reverse);
+ }
+}
============================================================
--- libpurple/protocols/facebook/fb_friendlist.h 4245e211978d4e907a4e22578faaee53bed74f7c
+++ libpurple/protocols/facebook/fb_friendlist.h 4245e211978d4e907a4e22578faaee53bed74f7c
@@ -0,0 +1,48 @@
+/*
+ * libfacebook
+ *
+ * libfacebook is the property of its developers. See the COPYRIGHT file
+ * for more details.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FACEBOOK_FRIENDLIST_H
+#define FACEBOOK_FRIENDLIST_H
+
+#include "libfacebook.h"
+
+#include <json-glib/json-glib.h>
+
+#define DEFAULT_GROUP_NAME "Facebook"
+
+/* Friend list modification methods */
+void fb_group_buddy_move(PurpleConnection *pc, const char *who,
+ const char *old_group, const char *new_group);
+void fb_group_rename(PurpleConnection *pc, const char *old_name,
+ PurpleGroup *group, GList *moved_buddies);
+void fb_group_remove(PurpleConnection *pc, PurpleGroup *group);
+void fb_buddy_remove(PurpleConnection *pc, PurpleBuddy *buddy,
+ PurpleGroup *group);
+
+/* Friend list fetch methods */
+const gchar *fb_get_list_id(FacebookAccount *fba, const gchar *list_name);
+gboolean fb_process_friend_lists(FacebookAccount *fba, JsonObject *buddy_list);
+GList *fb_get_buddies_friend_list (FacebookAccount *fba,
+ const gchar *uid, JsonArray *friend_list_ids);
+
+void fb_friendlist_init(FacebookAccount *fba);
+void fb_friendlist_destroy(FacebookAccount *fba);
+
+#endif /* FACEBOOK_FRIENDLIST_H */
============================================================
--- libpurple/protocols/facebook/Makefile.am 8f244a845ebdbc8be60a3489aa8e2f9499c91549
+++ libpurple/protocols/facebook/Makefile.am d0ee40a9e8032bf4f2e5329a45bcf4151ad30d19
@@ -12,6 +12,8 @@ FACEBOOK_SOURCES = \
fb_connection.c \
fb_conversation.h \
fb_conversation.c \
+ fb_friendlist.h \
+ fb_friendlist.c \
fb_info.h \
fb_info.c \
fb_managefriends.h \
============================================================
--- libpurple/protocols/facebook/facebook.nsi 86d06564f9bcb28939ce31fea5cf6e899cb530a9
+++ libpurple/protocols/facebook/facebook.nsi ae7c331b9422552cef92e0d67f9f096857745d2e
@@ -6,7 +6,7 @@ SetCompress off
; todo: SetBrandingImage
; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "pidgin-facebookchat"
-!define PRODUCT_VERSION "1.53"
+!define PRODUCT_VERSION "1.54"
!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 a756fad89ceaabc66d0f1f4798a348b416396471
+++ libpurple/protocols/facebook/fb_blist.c 4bba8ded502f2a2210836c692c63af63ba0abcd0
@@ -21,16 +21,19 @@
#include "libfacebook.h"
#include "fb_connection.h"
#include "fb_blist.h"
+#include "fb_util.h"
+#include "fb_friendlist.h"
+#include "blist.h"
-#include <json-glib/json-glib.h>
-
-static void set_buddies_offline(PurpleBuddy *buddy, GHashTable *online_buddies_list)
+static void set_buddies_offline(PurpleBuddy *buddy,
+ GHashTable *online_buddies_list)
{
if (PURPLE_BUDDY_IS_ONLINE(buddy) &&
g_hash_table_lookup(online_buddies_list, buddy->name) == NULL)
{
purple_prpl_got_user_status(buddy->account, buddy->name,
- purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE),
+ purple_primitive_get_id_from_type(
+ PURPLE_STATUS_OFFLINE),
NULL);
}
}
@@ -51,39 +54,280 @@ static void buddy_icon_cb(FacebookAccoun
buddy = purple_find_buddy(fba->account, buddyname);
g_free(buddyname);
- if (buddy == NULL)
- return;
+ g_return_if_fail(buddy != NULL);
+
fbuddy = buddy->proto_data;
+ g_return_if_fail(fbuddy != NULL);
+
buddy_icon_data = g_memdup(data, data_len);
purple_buddy_icons_set_for_user(fba->account, buddy->name,
buddy_icon_data, data_len, fbuddy->thumb_url);
}
-static void got_buddy_list_cb(FacebookAccount *fba, gchar *data,
- gsize data_len, gpointer userdata)
+/**
+ * Find buddy names
+ */
+static GList *get_buddies(FacebookAccount *fba, const gchar *uid,
+ const gchar *name, JsonArray *friend_list_ids)
{
- GSList *buddies_list;
- GHashTable *online_buddies_list = g_hash_table_new(g_str_hash, g_str_equal);
- PurpleBuddy *buddy;
+ GList *buddies;
+ GList *cur;
+
+ buddies = fb_get_buddies_friend_list(fba, uid, friend_list_ids);
+
+ // Initialize proto data for each buddy.
+ for (cur = buddies; cur != NULL; cur = cur->next)
+ {
+ PurpleBuddy *buddy;
+
+ buddy = (PurpleBuddy *) cur->data;
+
+ /* Set the FacebookBuddy structure */
+ if (buddy->proto_data == NULL)
+ {
+ FacebookBuddy *fbuddy;
+ gchar *buddy_icon_url;
+
+ fbuddy = g_new0(FacebookBuddy, 1);
+ fbuddy->buddy = buddy;
+ fbuddy->fba = fba;
+ fbuddy->uid = atoll(uid);
+ fbuddy->name = g_strdup(name);
+
+ // load the old buddy icon url from the icon 'checksum'
+ buddy_icon_url = (char *)
+ purple_buddy_icons_get_checksum_for_user(buddy);
+ if (buddy_icon_url != NULL)
+ fbuddy->thumb_url = g_strdup(buddy_icon_url);
+
+ buddy->proto_data = fbuddy;
+ }
+ }
+
+ return buddies;
+}
+
+static gboolean process_buddy_status(FacebookAccount *fba, PurpleBuddy *buddy,
+ JsonObject *userInfo)
+{
FacebookBuddy *fbuddy;
- gchar *uid;
- gchar *name;
- gchar *status_text;
- gchar *status_time_text;
+ gboolean status_changed;
+
+ status_changed = FALSE;
+ fbuddy = buddy->proto_data;
+
+ if (json_object_has_member(userInfo, "status"))
+ {
+ gchar *status_text;
+ const gchar *status_time_text;
+
+ status_time_text = json_node_get_string(
+ json_object_get_member(userInfo, "statusTimeRel"));
+ status_text = fb_strdup_withhtml(json_node_get_string(
+ json_object_get_member(userInfo, "status")));
+
+ /* set our last known status so that we don't re-set it */
+ if (!fba->last_status_message &&
+ atoll(buddy->name) == fba->uid) {
+ fba->last_status_message = g_strdup(status_text);
+ }
+
+ if (strlen(status_time_text) == 0) {
+ status_time_text = NULL;
+ }
+
+ g_free(fbuddy->status_rel_time);
+ if (status_time_text != NULL) {
+ fbuddy->status_rel_time =
+ fb_strdup_withhtml(status_time_text);
+ } else {
+ fbuddy->status_rel_time = NULL;
+ }
+
+ /* if the buddy status has changed, update the contact list */
+ if (fbuddy->status == NULL ||
+ !g_str_equal(fbuddy->status, status_text))
+ {
+ g_free(fbuddy->status);
+ fbuddy->status = g_strdup(status_text);
+ status_changed = TRUE;
+ }
+
+ g_free(status_text);
+ } else {
+ if (fbuddy->status != NULL) {
+ g_free(fbuddy->status);
+ fbuddy->status = NULL;
+ status_changed = TRUE;
+ }
+ }
+
+ return status_changed;
+}
+
+static void process_buddy_icon(FacebookAccount *fba, PurpleBuddy *buddy,
+ JsonObject *userInfo)
+{
+ FacebookBuddy *fbuddy;
gchar *buddy_icon_url;
+
+ fbuddy = buddy->proto_data;
+
+ /* Set the buddy icon (if it hasn't changed) */
+ buddy_icon_url = json_node_dup_string(json_object_get_member(
+ userInfo, "thumbSrc"));
+ if (fbuddy->thumb_url == NULL ||
+ !g_str_equal(fbuddy->thumb_url, buddy_icon_url))
+ {
+ g_free(fbuddy->thumb_url);
+ if (g_str_equal(buddy_icon_url,
+ "http://static.ak.fbcdn.net/pics/q_silhouette.gif"))
+ {
+ fbuddy->thumb_url = NULL;
+ /* User has no icon */
+ purple_buddy_icons_set_for_user(fba->account,
+ purple_buddy_get_name(buddy), NULL, 0, NULL);
+ }
+ else
+ {
+ gchar *search_tmp;
+
+ fbuddy->thumb_url = g_strdup(buddy_icon_url);
+
+ /* small icon at http://profile.ak.facebook.com/profile6/1845/74/q800753867_2878.jpg */
+ /* bigger icon at http://profile.ak.facebook.com/profile6/1845/74/n800753867_2878.jpg */
+ search_tmp = strstr(buddy_icon_url, "/q");
+ if (search_tmp)
+ *(search_tmp + 1) = 'n';
+
+ /* Fetch their icon */
+ fb_post_or_get(fba, FB_METHOD_GET, "profile.ak.facebook.com",
+ buddy_icon_url, NULL,
+ buddy_icon_cb, g_strdup(purple_buddy_get_name(buddy)), FALSE);
+ }
+ }
+ g_free(buddy_icon_url);
+}
+
+static void process_buddies(FacebookAccount *fba, GHashTable *online_buddies_list,
+ JsonObject *nowAvailableList, gchar *uid, JsonObject *userInfo)
+{
+ const gchar *name;
gboolean idle;
- guint32 error_number;
+ GList *buddies, *cur;
+ gboolean current_buddy_online;
- gchar *search_tmp;
- gchar *tmp;
+ JsonArray *friend_list_ids;
- PurpleGroup *fb_group = NULL;
+ friend_list_ids = NULL;
+ name = json_node_get_string(json_object_get_member(userInfo, "name"));
- gboolean current_buddy_online = FALSE;
+ /* look for "uid":{"i":_____} */
+ if (json_object_has_member(nowAvailableList, uid))
+ {
+ JsonObject *userBlistInfo;
+ userBlistInfo = json_node_get_object(
+ json_object_get_member(nowAvailableList, uid));
+ idle = json_node_get_boolean(
+ json_object_get_member(userBlistInfo, "i"));
+ if (json_object_has_member(userBlistInfo, "fl")) {
+ friend_list_ids = json_node_get_array(
+ json_object_get_member(userBlistInfo, "fl"));
+ }
+ current_buddy_online = TRUE;
+ } else {
+ /* if we're here, the buddy's info has been sent,
+ * but they're not actually online */
+ current_buddy_online = FALSE;
+ idle = FALSE;
+ }
+
+ /* is this us? */
+ if (atoll(uid) == fba->uid)
+ {
+ purple_connection_set_display_name(fba->pc, name);
+
+ /* check that we don't want to show ourselves */
+ current_buddy_online = !purple_account_get_bool(
+ fba->account, "facebook_hide_self", TRUE);
+ }
+
+ buddies = get_buddies(fba, uid, name, friend_list_ids);
+ for (cur = buddies; cur != NULL; cur = cur->next)
+ {
+ PurpleBuddy *buddy;
+ gboolean status_changed;
+
+ buddy = (PurpleBuddy *)cur->data;
+
+ process_buddy_icon(fba, buddy, userInfo);
+ status_changed = process_buddy_status(fba, buddy, userInfo);
+
+ purple_presence_set_idle(purple_buddy_get_presence(buddy),
+ idle, 0);
+
+ if (current_buddy_online)
+ {
+ /* Add buddy to the list of online buddies */
+ g_hash_table_insert(online_buddies_list, buddy->name, buddy);
+
+ // Set buddy as online in buddy list. We check for several
+ // conditions before doing this, because if we set it always
+ // Pidgin has a bug where the logs go nuts with "x is online".
+ if (!PURPLE_BUDDY_IS_ONLINE(buddy) ||
+ status_changed ||
+ idle != purple_presence_is_idle(
+ purple_buddy_get_presence(buddy)))
+ {
+ purple_prpl_got_user_status(fba->account, buddy->name,
+ purple_primitive_get_id_from_type(
+ idle ? PURPLE_STATUS_AWAY :
+ PURPLE_STATUS_AVAILABLE), NULL);
+ }
+ }
+ }
+
+ /* update the blist if we have no previous alias */
+ fb_blist_set_alias(fba, uid, name);
+}
+
+static void process_notifications(FacebookAccount *fba,
+ JsonObject *notifications)
+{
+ if (notifications != NULL &&
+ purple_account_get_check_mail(fba->account))
+ {
+ JsonNode *inboxCount_node = json_object_get_member(
+ notifications, "inboxCount");
+ if (inboxCount_node) {
+ gint inbox_count = json_node_get_int(inboxCount_node);
+ if (inbox_count &&
+ inbox_count != fba->last_inbox_count) {
+ fba->last_inbox_count = inbox_count;
+ gchar *url = g_strdup("http://www.facebook.com/inbox/");
+ purple_notify_emails(
+ fba->pc, inbox_count,
+ FALSE, NULL, NULL,
+ (const char**) &(fba->account->username),
+ (const char**) &(url), NULL, NULL);
+ g_free(url);
+ }
+ }
+ }
+}
+
+static void got_buddy_list_cb(FacebookAccount *fba, gchar *data,
+ gsize data_len, gpointer userdata)
+{
+ GSList *buddies_list;
+ GHashTable *online_buddies_list = g_hash_table_new(
+ g_str_hash, g_str_equal);
+ gchar *uid;
+
purple_debug_info("facebook", "parsing buddy list\n");
if (fba == NULL)
@@ -96,60 +340,50 @@ static void got_buddy_list_cb(FacebookAc
_("Could not retrieve buddy list"));
return;
}
-
+
purple_debug_misc("facebook", "buddy list\n%s\n", data);
-
- JsonNode *root;
- root = json_parser_get_root(parser);
- JsonObject *objnode;
- objnode = json_node_get_object(root);
- /* Check if the facebook group already exists (fixes #13) */
- fb_group = purple_find_group("Facebook");
-
- /* if logged out, this comes up */
- /* for (;;);{"error":1357001,"errorSummary":"Not Logged In",
- "errorDescription":"You must be logged in to do that.",
- "payload":null,"bootload":[{"name":"js\/common.js.pkg.php",
- "type":"js","src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/pkg\/59\
- /98561\/js\/common.js.pkg.php"}]} */
- if (json_object_has_member(objnode, "error"))
- {
- error_number = json_node_get_int(json_object_get_member(objnode, "error"));
- if (error_number)
- {
- purple_connection_error_reason(fba->pc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- json_node_dup_string(json_object_get_member(objnode, "errorDescription")));
+ gchar *error = NULL;
+ JsonObject *objnode = fb_get_json_object(parser, &error);
+ if (error) {
+ purple_connection_error_reason(
+ fba->pc,
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+ error);
g_object_unref(parser);
return;
- }
}
-
+
/* look for "userInfos":{ ... }, */
if (!json_object_has_member(objnode, "payload"))
{
g_object_unref(parser);
return;
}
- objnode = json_node_get_object(json_object_get_member(objnode, "payload"));
+ objnode = json_node_get_object(json_object_get_member(
+ objnode, "payload"));
if (!json_object_has_member(objnode, "buddy_list"))
{
g_object_unref(parser);
return;
}
- JsonObject *buddy_list = json_node_get_object(json_object_get_member(objnode, "buddy_list"));
+ JsonObject *buddy_list = json_node_get_object(json_object_get_member(
+ objnode, "buddy_list"));
if (!json_object_has_member(buddy_list, "userInfos"))
{
g_object_unref(parser);
return;
}
- JsonObject *notifications = json_node_get_object(json_object_get_member(objnode, "notifications"));
-
+
+ fb_process_friend_lists(fba, buddy_list);
+
+ // Iterate through the list of buddy infos sent to us.
JsonObject *userInfos;
JsonObject *nowAvailableList;
- userInfos = json_node_get_object(json_object_get_member(buddy_list, "userInfos"));
- nowAvailableList = json_node_get_object(json_object_get_member(buddy_list, "nowAvailableList"));
+ userInfos = json_node_get_object(json_object_get_member(
+ buddy_list, "userInfos"));
+ nowAvailableList = json_node_get_object(json_object_get_member(
+ buddy_list, "nowAvailableList"));
GList *userIds;
userIds = json_object_get_members(userInfos);
GList *currentUserNode;
@@ -160,200 +394,34 @@ static void got_buddy_list_cb(FacebookAc
uid = currentUserNode->data;
JsonObject *userInfo;
- userInfo = json_node_get_object(json_object_get_member(userInfos, uid));
- name = json_node_dup_string(json_object_get_member(userInfo, "name"));
-
- /* update the blist if we have no previous alias */
- fb_blist_set_alias(fba, uid, name);
-
- /* look for "uid":{"i":_____} */
- if (json_object_has_member(nowAvailableList, uid))
- {
- JsonObject *userBlistInfo;
- userBlistInfo = json_node_get_object(json_object_get_member(nowAvailableList, uid));
- idle = json_node_get_boolean(json_object_get_member(userBlistInfo, "i"));
- current_buddy_online = TRUE;
- } else {
- /* if we're here, the buddy's info has been sent, but they're not actually online */
- current_buddy_online = FALSE;
- idle = FALSE;
- }
-
- /* Set the buddy status text and time */
- if (json_object_has_member(userInfo, "status"))
- {
- status_text = json_node_dup_string(json_object_get_member(userInfo, "status"));
- } else {
- status_text = NULL;
- }
-
- /* is this us? */
- if (atoll(uid) == fba->uid)
- {
- purple_connection_set_display_name(fba->pc, name);
-
- /* set our last known status so that we don't re-set it */
- if (status_text && !fba->last_status_message)
- fba->last_status_message = g_strdup(status_text);
-
- /* check that we don't want to show ourselves */
- if (purple_account_get_bool(fba->account, "facebook_hide_self", TRUE))
- {
- g_free(status_text);
- g_free(name);
- /* go on to the next buddy */
- continue;
- } else {
- current_buddy_online = TRUE;
- }
- }
-
- /* Is this a new buddy? */
- buddy = purple_find_buddy(fba->account, uid);
- if (buddy == NULL)
- {
- buddy = purple_buddy_new(fba->account, uid, NULL);
- if (fb_group == NULL)
- {
- fb_group = purple_group_new("Facebook");
- purple_blist_add_group(fb_group, NULL);
- }
- purple_blist_add_buddy(buddy, NULL, fb_group, NULL);
- }
- purple_presence_set_idle(purple_buddy_get_presence(buddy), idle, 0);
-
- /* Set the FacebookBuddy structure */
- if (buddy->proto_data == NULL)
- {
- fbuddy = g_new0(FacebookBuddy, 1);
- fbuddy->buddy = buddy;
- fbuddy->fba = fba;
- fbuddy->uid = atoll(uid);
- fbuddy->name = g_strdup(name);
-
- /* load the old buddy icon url from the icon 'checksum' */
- buddy_icon_url = (char *)purple_buddy_icons_get_checksum_for_user(buddy);
- if (buddy_icon_url != NULL)
- fbuddy->thumb_url = g_strdup(buddy_icon_url);
-
- buddy->proto_data = fbuddy;
- } else {
- fbuddy = buddy->proto_data;
- }
-
- g_free(name);
-
- if (status_text != NULL)
- {
- tmp = fb_strdup_withhtml(status_text);
- g_free(status_text);
- status_text = tmp;
-
- status_time_text = json_node_dup_string(json_object_get_member(userInfo, "statusTimeRel"));
- if (strlen(status_time_text) == 0)
- {
- g_free(status_time_text);
- status_time_text = NULL;
- }
- g_free(fbuddy->status_rel_time);
- if (status_time_text != NULL)
- {
- fbuddy->status_rel_time = fb_strdup_withhtml(status_time_text);
- g_free(status_time_text);
- } else {
- fbuddy->status_rel_time = NULL;
- }
-
- /* if the buddy status has changed, update the contact list */
- if (fbuddy->status == NULL || !g_str_equal(fbuddy->status, status_text))
- {
- tmp = fbuddy->status;
- fbuddy->status = status_text;
- g_free(tmp);
- if (current_buddy_online)
- purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
- } else {
- g_free(status_text);
- }
- } else {
- if (fbuddy->status != NULL)
- {
- g_free(fbuddy->status);
- fbuddy->status = NULL;
- if (current_buddy_online)
- {
- /* update the status in the contact list */
- purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
- }
- }
- }
-
- /* Set the buddy icon (if it hasn't changed) */
- buddy_icon_url = json_node_dup_string(json_object_get_member(userInfo, "thumbSrc"));
- if (fbuddy->thumb_url == NULL || !g_str_equal(fbuddy->thumb_url, buddy_icon_url))
- {
- g_free(fbuddy->thumb_url);
- if (g_str_equal(buddy_icon_url, "http://static.ak.fbcdn.net/pics/q_silhouette.gif"))
- {
- fbuddy->thumb_url = NULL;
- /* User has no icon */
- purple_buddy_icons_set_for_user(fba->account,
- purple_buddy_get_name(buddy), NULL, 0, NULL);
- }
- else
- {
- fbuddy->thumb_url = g_strdup(buddy_icon_url);
-
- /* small icon at http://profile.ak.facebook.com/profile6/1845/74/q800753867_2878.jpg */
- /* bigger icon at http://profile.ak.facebook.com/profile6/1845/74/n800753867_2878.jpg */
- search_tmp = strstr(buddy_icon_url, "/q");
- if (search_tmp)
- *(search_tmp + 1) = 'n';
-
- /* Fetch their icon */
- fb_post_or_get(fba, FB_METHOD_GET, "profile.ak.facebook.com",
- buddy_icon_url + strlen("http://profile.ak.facebook.com"), NULL,
- buddy_icon_cb, g_strdup(purple_buddy_get_name(buddy)), FALSE);
- }
- }
- g_free(buddy_icon_url);
-
- if (current_buddy_online)
- {
- /* Add buddy to the list of online buddies */
- g_hash_table_insert(online_buddies_list, buddy->name, buddy);
-
- /* Update the display of the buddy in the buddy list and make the user online */
- if (!PURPLE_BUDDY_IS_ONLINE(buddy))
- purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
- }
+ userInfo = json_node_get_object(json_object_get_member(
+ userInfos, uid));
+ // Process the user, which generally consists of updating
+ // state info such as name, idle item, status message,etc.
+ process_buddies(fba, online_buddies_list, nowAvailableList,
+ uid, userInfo);
}
g_list_free(userIds);
+ // Set users offline. We do this in a seperate function because FB
+ // only sends us a list of users who are online. We find the users
+ // that are not in the union of of buddy list users + online, and
+ // mark them as offline.
buddies_list = purple_find_buddies(fba->account, NULL);
if (buddies_list != NULL)
{
- g_slist_foreach(buddies_list, (GFunc)set_buddies_offline, online_buddies_list);
+ g_slist_foreach(
+ buddies_list,
+ (GFunc)set_buddies_offline, online_buddies_list);
g_slist_free(buddies_list);
}
g_hash_table_destroy(online_buddies_list);
- if (notifications != NULL && purple_account_get_check_mail(fba->account))
- {
- JsonNode *inboxCount_node = json_object_get_member(notifications, "inboxCount");
- if (inboxCount_node)
- {
- gint inbox_count = json_node_get_int(inboxCount_node);
- if (inbox_count && inbox_count != fba->last_inbox_count)
- {
- fba->last_inbox_count = inbox_count;
- gchar *url = g_strdup("http://www.facebook.com/inbox/");
- purple_notify_emails(fba->pc, inbox_count, FALSE, NULL, NULL, (const char**) &(fba->account->username), (const char**) &(url), NULL, NULL);
- g_free(url);
- }
- }
- }
-
+ // The buddy list also contains notifications data. Process and
+ // display is appropriate.
+ process_notifications(fba, json_node_get_object(
+ json_object_get_member(objnode, "notifications")));
+
g_object_unref(parser);
}
@@ -426,3 +494,24 @@ void fb_blist_set_alias(FacebookAccount
/* In case user removes an alias, we have the server as fallback */
serv_got_alias(fba->pc, id, name);
}
+
+void fb_blist_init(FacebookAccount *fba)
+{
+ fb_friendlist_init(fba);
+
+ fb_get_buddy_list(fba);
+
+ /* periodically check for updates to your buddy list */
+ fba->buddy_list_timer = purple_timeout_add_seconds(60,
+ fb_get_buddy_list, fba);
+
+}
+
+void fb_blist_destroy(FacebookAccount *fba)
+{
+ if (fba->buddy_list_timer) {
+ purple_timeout_remove(fba->buddy_list_timer);
+ }
+
+ fb_friendlist_destroy(fba);
+}
============================================================
--- libpurple/protocols/facebook/fb_blist.h 282d636d6e7f6011bec4f39d5cc9483b1be8b199
+++ libpurple/protocols/facebook/fb_blist.h e77ea2b71a92a022052a1083631d810b540385b4
@@ -29,4 +29,7 @@ void fb_blist_set_alias(FacebookAccount
void fb_blist_set_alias(FacebookAccount *fba, const char *id,
const char *name);
+void fb_blist_init(FacebookAccount *fba);
+void fb_blist_destroy(FacebookAccount *fba);
+
#endif /* FACEBOOK_BLIST_H */
============================================================
--- libpurple/protocols/facebook/fb_conversation.c 259358150129a9c835a26193282d46f2dd284d18
+++ libpurple/protocols/facebook/fb_conversation.c c7a209ce60af9d7660eeceecb1941275fe47bbe1
@@ -49,7 +49,7 @@ void fb_conversation_handle_message(Face
if (fba->uid != atoll(from) || fba->uid == atoll(to)) {
purple_debug_info("facebook",
"displaying received message %lld: %s\n",
- message_time, message_text);
+ (long long int) message_time, message_text);
// TODO/FIXME: cheat here by changing formatting colors.
// Or add an option to just disable history on conv open. TBD.
serv_got_im(fba->pc, from, message_text,
@@ -68,7 +68,7 @@ void fb_conversation_handle_message(Face
{
purple_debug_info("facebook",
"displaying sent message %lld: %s\n",
- message_time, message_text);
+ (long long int) message_time, message_text);
serv_got_im(fba->pc, to, message_text,
log?
@@ -96,7 +96,6 @@ static void fb_history_fetch_cb(Facebook
gsize data_len, gpointer userdata)
{
JsonParser *parser;
- JsonNode *root;
JsonObject *object, *payload;
JsonArray *history;
guint i;
@@ -114,10 +113,9 @@ static void fb_history_fetch_cb(Facebook
min_time = atoll((char *) userdata);
g_free(userdata);
purple_debug_info("facebook", "history fetch with min time of %lld\n",
- min_time);
+ (long long int) min_time);
- root = json_parser_get_root(parser);
- object = json_node_get_object(root);
+ object = fb_get_json_object(parser, NULL);
payload = json_node_get_object(
json_object_get_member(object, "payload"));
history = json_node_get_array(
@@ -159,7 +157,7 @@ static void fb_history_fetch_cb(Facebook
if (message_time > min_time) {
purple_debug_info("facebook",
"displaying history message %lld\n",
- message_time);
+ (long long int) message_time);
fb_conversation_handle_message(
fba, from, to, message_time, message,
min_time != 0);
@@ -188,7 +186,7 @@ void fb_history_fetch(FacebookAccount *f
gchar *url = g_strdup_printf("/ajax/chat/history.php?id=%s", who);
fb_post_or_get(
fba, FB_METHOD_GET, NULL, url, NULL, fb_history_fetch_cb,
- g_strdup_printf("%lld", min_time), FALSE);
+ g_strdup_printf("%lld", (long long int) min_time), FALSE);
g_free(url);
}
@@ -224,7 +222,10 @@ static void fb_conversation_created(Purp
purple_debug_info("facebook", "conversation created with %s\n",
conv->name);
- fb_history_fetch(account->gc->proto_data, conv->name, TRUE);
+ if (purple_account_get_bool(account, "facebook_show_history", TRUE))
+ {
+ fb_history_fetch(account->gc->proto_data, conv->name, TRUE);
+ }
}
gboolean fb_conversation_is_fb(PurpleConversation *conv)
============================================================
--- libpurple/protocols/facebook/fb_info.c 3eb9ceaf6170bc0b2ab8f2ef73d9adec28363839
+++ libpurple/protocols/facebook/fb_info.c b41f1bf46271eaa87317bdaa410b13abde797e7a
@@ -20,6 +20,7 @@
#include "fb_connection.h"
#include "fb_info.h"
+#include "fb_blist.h"
/*
* TODO: Do we really want to do this? Maybe we could just set a
@@ -130,7 +131,7 @@ static void fb_get_info_cb(FacebookAccou
value_tmp2 = g_strndup(value_tmp, strstr(value_tmp, "</title>")-value_tmp);
value_tmp = g_strchomp(purple_markup_strip_html(value_tmp2));
purple_notify_user_info_add_pair(user_info, _("Name"), value_tmp);
- serv_got_alias(fba->pc, uid, value_tmp);
+ fb_blist_set_alias(fba, uid, value_tmp);
g_free(value_tmp);
g_free(value_tmp2);
}
============================================================
--- libpurple/protocols/facebook/fb_managefriends.c 48d9104fae04b40e366b570f78e4b366e0d87a43
+++ libpurple/protocols/facebook/fb_managefriends.c 1d9f2f9e32feef9aa049321c952ab8cb205f1162
@@ -87,6 +87,9 @@ static void fb_check_friend_request_cb(F
FacebookBuddy *buddy;
gchar *search_start = data;
+ g_return_if_fail(data_len > 0);
+ g_return_if_fail(data != NULL);
+
/* loop through the data and look for confirm_friend_add_([0-9]*)" */
while ((search_start = strstr(search_start, uid_pre_text)))
{
@@ -169,10 +172,14 @@ void fb_add_buddy(PurpleConnection *pc,
if (!purple_account_get_bool(
fba->account, "facebook_manage_friends", FALSE)) {
+ /*
+ * We used to pop up dialogs here but if a user renamed a group,
+ * this would spawn message for each person in the buddy list. Bad!
purple_notify_info(fba->pc, _("Friend not added"),
_("Adding Facebook friends via Pidgin is disabled"),
_("Either add a friend via Facebook.com or edit your account preferences"));
- // TODO: Message here
+ */
+ purple_debug_warning("facebook", "attempted to add %s but was blocked\n", buddy->name);
return;
}
@@ -197,24 +204,3 @@ void fb_add_buddy(PurpleConnection *pc,
g_free(url);
}
-#if 0
-/* This code should never be reinstated in it's current form. Period. See
- * issue 185 for why */
-static void fb_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
-{
- gchar *postdata;
- FacebookAccount *fba = pc->proto_data;
-
- if (atoll(buddy->name) == fba->uid)
- {
- purple_account_set_bool(fba->account, "facebook_hide_self", TRUE);
- return;
- }
-
- postdata = g_strdup_printf("uid=%s&post_form_id=%s", buddy->name, fba->post_form_id);
-
- fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/removefriend.php", postdata, NULL, NULL, FALSE);
-
- g_free(postdata);
-}
-#endif
============================================================
--- libpurple/protocols/facebook/fb_messages.c 55cba18f6f06fcf967d93af64fce1cbb06224521
+++ libpurple/protocols/facebook/fb_messages.c 09b6b82775e77886d5aff74654063c9f70e7e7fb
@@ -22,9 +22,8 @@
#include "fb_connection.h"
#include "fb_conversation.h"
#include "fb_blist.h"
+#include "fb_util.h"
-#include <json-glib/json-glib.h>
-
#include "conversation.h"
typedef struct _FacebookOutgoingMessage FacebookOutgoingMessage;
@@ -207,18 +206,14 @@ static void got_new_messages(FacebookAcc
return;
}
- JsonNode *root;
- root = json_parser_get_root(parser);
+ JsonObject *objnode = fb_get_json_object(parser, NULL);
- JsonObject *objnode;
- objnode = json_node_get_object(root);
-
if (json_object_has_member(objnode, "t")) {
const gchar* command = json_node_get_string(json_object_get_member(objnode, "t"));
if (g_str_equal(command, "refresh")) {
- int seq = json_node_get_int(json_object_get_member(objnode, "seq"));
- if (seq) {
- fba->message_fetch_sequence = seq;
+ if (json_object_has_member(objnode, "seq")) {
+ fba->message_fetch_sequence = json_node_get_int(
+ json_object_get_member(objnode, "seq"));
}
/* grab history items for all open conversations */
@@ -297,7 +292,7 @@ static gboolean fb_get_new_messages(Face
fetch_server = g_strdup_printf("%d.channel%s.facebook.com", 0, channel_number);
/* use the current time in the url to get past any transparent proxy caches */
- fetch_url = g_strdup_printf("/x/%lu/%s/p_%" G_GINT64_FORMAT "=%d", time(NULL), (fba->is_idle?"false":"true"), fba->uid, fba->message_fetch_sequence);
+ fetch_url = g_strdup_printf("/x/%lu/%s/p_%" G_GINT64_FORMAT "=%d", (gulong)time(NULL), (fba->is_idle?"false":"true"), fba->uid, fba->message_fetch_sequence);
fb_post_or_get(fba, FB_METHOD_GET, fetch_server, fetch_url, NULL, got_new_messages, fba->pc, TRUE);
fba->last_messages_download_time = now;
@@ -311,29 +306,12 @@ static void fb_send_im_cb(FacebookAccoun
static void fb_send_im_cb(FacebookAccount *fba, gchar *data, gsize data_len, gpointer user_data)
{
FacebookOutgoingMessage *msg = user_data;
- gint error_number;
- const gchar *error_summary;
JsonParser *parser;
- JsonNode *root;
JsonObject *object;
PurpleConversation *conv;
+ gchar *error = NULL;
- /* NULL data crashes on Windows */
- if (data == NULL)
- {
- data = "(null)";
- }
-
purple_debug_misc("facebook", "sent im response: %s\n", data);
- /* for (;;);{"error":1356003,"errorSummary":"Send destination not online",
- "errorDescription":"This person is no longer online.","payload":null,
- "bootload":[{"name":"js\/common.js.pkg.php","type":"js",
- "src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/pkg\/59\/98936\
- /js\/common.js.pkg.php"}]} */
- /* for (;;);{"error":0,"errorSummary":"","errorDescription":"No error.",
- "payload":[],"bootload":[{"name":"js\/common.js.pkg.php","type":"js",
- "src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/pkg\/59\/98936\
- /js\/common.js.pkg.php"}]} */
parser = fb_get_parser(data, data_len);
if (!parser) {
@@ -341,15 +319,11 @@ static void fb_send_im_cb(FacebookAccoun
purple_debug_warning("facebook", "bad data while parsing sent IM\n");
return;
}
- root = json_parser_get_root(parser);
- object = json_node_get_object(root);
+ object = fb_get_json_object(parser, &error);
- error_number = json_node_get_int(json_object_get_member(object, "error"));
- error_summary = json_node_get_string(json_object_get_member(object, "errorSummary"));
-
- if (error_number)
+ if (error)
{
- purple_debug_error("facebook", "sent im error: %s\n", error_summary);
+ purple_debug_error("facebook", "sent im error: %s\n", error);
/* there was an error, either report it or retry */
if (msg->retry_count++ < FB_MAX_MSG_RETRY)
{
@@ -362,7 +336,7 @@ static void fb_send_im_cb(FacebookAccoun
{
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
fba->account, msg->who);
- purple_conversation_write(conv, NULL, error_summary,
+ purple_conversation_write(conv, NULL, error,
PURPLE_MESSAGE_ERROR, msg->time);
}
@@ -381,7 +355,7 @@ static gboolean fb_send_im_fom(FacebookO
encoded_message = g_strdup(purple_url_encode(msg->message));
postdata = g_strdup_printf("msg_text=%s&msg_id=%d&to=%s&client_time=%lu&post_form_id=%s",
encoded_message, msg->msg_id, msg->who,
- msg->time,
+ (gulong) msg->time,
msg->fba->post_form_id ? msg->fba->post_form_id : "0");
g_free(encoded_message);
@@ -432,7 +406,7 @@ void got_reconnect_json(FacebookAccount
gchar *new_channel_number;
JsonParser *parser;
- JsonNode *root;
+ JsonObject *objnode;
parser = fb_get_parser(data, data_len);
@@ -445,9 +419,7 @@ void got_reconnect_json(FacebookAccount
return;
}
- root = json_parser_get_root(parser);
- JsonObject *objnode;
- objnode = json_node_get_object(root);
+ objnode = fb_get_json_object(parser, NULL);
JsonObject *payload = json_node_get_object(json_object_get_member(objnode, "payload"));
============================================================
--- libpurple/protocols/facebook/fb_util.c 23606c4fef64d4b023b7dca41ac62a8b499a4924
+++ libpurple/protocols/facebook/fb_util.c 8d78175db675e416230954b25937b58700eb4b26
@@ -24,9 +24,179 @@
* UTILITY CODE *
*****************************************************************************/
+gchar *fb_convert_unicode(const gchar *input)
+{
+ /* \u00e9t\u00e9 should be ?t? */
+
+ gunichar unicode_char;
+ gchar unicode_char_str[6];
+ gint unicode_char_len;
+ gchar *next_pos;
+ gchar *input_string;
+ gchar *output_string;
+
+ if (input == NULL)
+ return NULL;
+
+ next_pos = input_string = g_strdup(input);
+
+ /* purple_debug_info("facebook", "unicode convert: in: %s\n", input); */
+ while ((next_pos = strstr(next_pos, "\\u")))
+ {
+ /* grab the unicode */
+ sscanf(next_pos, "\\u%4x", &unicode_char);
+ /* turn it to a char* */
+ unicode_char_len = g_unichar_to_utf8(unicode_char, unicode_char_str);
+ /* shove it back into the string */
+ g_memmove(next_pos, unicode_char_str, unicode_char_len);
+ /* move all the data after the \u0000 along */
+ g_stpcpy(next_pos + unicode_char_len, next_pos + 6);
+ }
+
+ /* purple_debug_info("facebook", "unicode convert: out: %s\n", input); */
+ output_string = g_strcompress(input_string);
+ g_free(input_string);
+
+ return output_string;
+}
+
+/* Like purple_strdup_withhtml, but escapes htmlentities too */
+gchar *fb_strdup_withhtml(const gchar *src)
+{
+ gulong destsize, i, j;
+ gchar *dest;
+
+ g_return_val_if_fail(src != NULL, NULL);
+
+ /* New length is (length of src) + (number of \n's * 3) + (number of &'s * 5) +
+ (number of <'s * 4) + (number of >'s *4) + (number of "'s * 6) -
+ (number of \r's) + 1 */
+ destsize = 1;
+ for (i = 0; src[i] != '\0'; i++)
+ {
+ if (src[i] == '\n' || src[i] == '<' || src[i] == '>')
+ destsize += 4;
+ else if (src[i] == '&')
+ destsize += 5;
+ else if (src[i] == '"')
+ destsize += 6;
+ else if (src[i] != '\r')
+ destsize++;
+ }
+
+ dest = g_malloc(destsize);
+
+ /* Copy stuff, ignoring \r's, because they are dumb */
+ for (i = 0, j = 0; src[i] != '\0'; i++) {
+ if (src[i] == '\n') {
+ strcpy(&dest[j], "<BR>");
+ j += 4;
+ } else if (src[i] == '<') {
+ strcpy(&dest[j], "<");
+ j += 4;
+ } else if (src[i] == '>') {
+ strcpy(&dest[j], ">");
+ j += 4;
+ } else if (src[i] == '&') {
+ strcpy(&dest[j], "&");
+ j += 5;
+ } else if (src[i] == '"') {
+ strcpy(&dest[j], """);
+ j += 6;
+ } else if (src[i] != '\r')
+ dest[j++] = src[i];
+ }
+
+ dest[destsize-1] = '\0';
+
+ return dest;
+}
+
+gint64 fb_time_kludge(gint initial_time)
+{
+ if (sizeof(gint) >= sizeof(gint64))
+ return initial_time;
+
+ gint64 now_millis = (gint64) time(NULL);
+ now_millis *= 1000;
+ now_millis &= 0xFFFFFFFF00000000LL;
+ gint64 final_time = now_millis | initial_time;
+
+ return final_time;
+}
+
+JsonParser *fb_get_parser(const gchar *data, gsize data_len)
+{
+ JsonParser *parser;
+
+ if (data == NULL) {
+ return NULL;
+ }
+
+ data = g_strstr_len(data, data_len, "for (;;);");
+ if (!data) {
+ return NULL;
+ } else {
+ data += strlen("for (;;);");
+ }
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_data(parser, data, -1, NULL)) {
+ g_object_unref(parser);
+ return NULL;
+ }
+
+ return parser;
+}
+
+JsonObject *fb_get_json_object(JsonParser *parser, char **error_message)
+{
+ JsonNode *root;
+ root = json_parser_get_root(parser);
+ JsonObject *objnode;
+ objnode = json_node_get_object(root);
+
+ /* Sample error messages */
+ /* for (;;);{"error":1357001,"errorSummary":"Not Logged In",
+ "errorDescription":"You must be logged in to do that.",
+ "payload":null,"bootload":[{"name":"js\/common.js.pkg.php",
+ "type":"js","src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/pkg\/59\
+ /98561\/js\/common.js.pkg.php"}]} */
+ if (json_object_has_member(objnode, "error"))
+ {
+ guint32 error_number;
+ const char *summary;
+ const char *description;
+
+ error_number = json_node_get_int(
+ json_object_get_member(objnode, "error"));
+ summary = json_node_get_string(
+ json_object_get_member(objnode, "errorSummary"));
+ description = json_node_get_string(
+ json_object_get_member(objnode, "errorDescription"));
+
+ if (error_number)
+ {
+ purple_debug_error("facebook",
+ "got error from facebook of %s (%s)",
+ summary, description);
+ // Pass error message to calling function if they asked for it.
+ if (error_message) {
+ *error_message = g_strdup(description);
+ }
+ }
+ }
+
+ return objnode;
+}
+
/* Converts *text* into <b>text</b> and _text_ into <i>text</i> */
gchar *fb_replace_styled_text(const gchar *text)
{
+#ifdef __ARM_EABI__
+ return g_strdup(text);
+#else /*__ARM_EABI__*/
+#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 14
if (glib_check_version(2, 14, 0))
{
return g_strdup(text);
@@ -52,13 +222,27 @@ gchar *fb_replace_styled_text(const gcha
dup_text = g_strdup(text);
midway_string = g_regex_replace(underline_regex, dup_text,
- -1, 0, "<u>\\1</u>", 0, NULL);
+ strlen(dup_text), 0, "<u>\\1</u>", 0, NULL);
+ if (midway_string == NULL)
+ {
+ purple_debug_warning("facebook", "regex failed for underline\n");
+ return dup_text;
+ }
g_free(dup_text);
output_string = g_regex_replace(bold_regex, midway_string,
- -1, 0, "\\1<b>\\2</b>", 0, NULL);
+ strlen(midway_string), 0, "\\1<b>\\2</b>", 0, NULL);
+ if (output_string == NULL)
+ {
+ purple_debug_warning("facebook", "regex failed for bold\n");
+ return midway_string;
+ }
g_free(midway_string);
return output_string;
}
+#else /* GLIB check */
+ return g_strdup(text);
+#endif /* GLIB check */
+#endif /*__ARM_EABI__*/
}
============================================================
--- libpurple/protocols/facebook/fb_util.h 33093b85583658b53d9519de66ab7da32ebd5076
+++ libpurple/protocols/facebook/fb_util.h 53baf5d5d5678ff04dc221e8d629b56d3f3a67f5
@@ -22,8 +22,15 @@
#define FACEBOOK_UTIL_H
#include "libfacebook.h"
+#include <json-glib/json-glib.h>
+JsonParser *fb_get_parser(const gchar *data, gsize data_len);
+JsonObject *fb_get_json_object(JsonParser *parser, char **error_message);
+
gchar *fb_replace_styled_text(const gchar *text);
+gchar *fb_strdup_withhtml(const gchar *src);
+gchar *fb_convert_unicode(const gchar *input);
+gint64 fb_time_kludge(int initial_time);
#endif /* FACEBOOK_UTIL_H */
============================================================
--- libpurple/protocols/facebook/libfacebook.c 4a5dcafa34bf51425459fa4d44852b720bbc3661
+++ libpurple/protocols/facebook/libfacebook.c bf869dde3e462fc590369c74f963d444c2d2cbe9
@@ -27,137 +27,9 @@
#include "fb_messages.h"
#include "fb_notifications.h"
#include "fb_search.h"
+#include "fb_friendlist.h"
/******************************************************************************/
-/* Utility functions */
-/******************************************************************************/
-
-gchar *fb_convert_unicode(const gchar *input)
-{
- /* \u00e9t\u00e9 should be ?t? */
-
- gunichar unicode_char;
- gchar unicode_char_str[6];
- gint unicode_char_len;
- gchar *next_pos;
- gchar *input_string;
- gchar *output_string;
-
- if (input == NULL)
- return NULL;
-
- next_pos = input_string = g_strdup(input);
-
- /* purple_debug_info("facebook", "unicode convert: in: %s\n", input); */
- while ((next_pos = strstr(next_pos, "\\u")))
- {
- /* grab the unicode */
- sscanf(next_pos, "\\u%4x", &unicode_char);
- /* turn it to a char* */
- unicode_char_len = g_unichar_to_utf8(unicode_char, unicode_char_str);
- /* shove it back into the string */
- g_memmove(next_pos, unicode_char_str, unicode_char_len);
- /* move all the data after the \u0000 along */
- g_stpcpy(next_pos + unicode_char_len, next_pos + 6);
- }
-
- /* purple_debug_info("facebook", "unicode convert: out: %s\n", input); */
- output_string = g_strcompress(input_string);
- g_free(input_string);
-
- return output_string;
-}
-
-/* Like purple_strdup_withhtml, but escapes htmlentities too */
-gchar *fb_strdup_withhtml(const gchar *src)
-{
- gulong destsize, i, j;
- gchar *dest;
-
- g_return_val_if_fail(src != NULL, NULL);
-
- /* New length is (length of src) + (number of \n's * 3) + (number of &'s * 5) +
- (number of <'s * 4) + (number of >'s *4) + (number of "'s * 6) -
- (number of \r's) + 1 */
- destsize = 1;
- for (i = 0; src[i] != '\0'; i++)
- {
- if (src[i] == '\n' || src[i] == '<' || src[i] == '>')
- destsize += 4;
- else if (src[i] == '&')
- destsize += 5;
- else if (src[i] == '"')
- destsize += 6;
- else if (src[i] != '\r')
- destsize++;
- }
-
- dest = g_malloc(destsize);
-
- /* Copy stuff, ignoring \r's, because they are dumb */
- for (i = 0, j = 0; src[i] != '\0'; i++) {
- if (src[i] == '\n') {
- strcpy(&dest[j], "<BR>");
- j += 4;
- } else if (src[i] == '<') {
- strcpy(&dest[j], "<");
- j += 4;
- } else if (src[i] == '>') {
- strcpy(&dest[j], ">");
- j += 4;
- } else if (src[i] == '&') {
- strcpy(&dest[j], "&");
- j += 5;
- } else if (src[i] == '"') {
- strcpy(&dest[j], """);
- j += 6;
- } else if (src[i] != '\r')
- dest[j++] = src[i];
- }
-
- dest[destsize-1] = '\0';
-
- return dest;
-}
-
-JsonParser *fb_get_parser(const gchar *data, gsize data_len)
-{
- JsonParser *parser;
-
- if (data == NULL) {
- return NULL;
- }
-
- data = g_strstr_len(data, data_len, "for (;;);");
- if (!data) {
- return NULL;
- } else {
- data += strlen("for (;;);");
- }
-
- parser = json_parser_new();
- if (!json_parser_load_from_data(parser, data, -1, NULL)) {
- g_object_unref(parser);
- return NULL;
- }
-
- return parser;
-}
-
-gint64 fb_time_kludge(gint initial_time)
-{
- if (sizeof(gint) >= sizeof(gint64))
- return initial_time;
-
- gint64 now_millis = (gint64) time(NULL);
- now_millis *= 1000;
- now_millis &= 0xFFFFFFFF00000000LL;
- gint64 final_time = now_millis | initial_time;
-
- return final_time;
-}
-
-/******************************************************************************/
/* PRPL functions */
/******************************************************************************/
@@ -269,17 +141,12 @@ static void fb_login_cb(FacebookAccount
/* This will kick off our long-poll message retrieval loop */
fb_get_post_form_id(fba);
- fb_get_buddy_list(fba);
fb_check_friend_requests(fba);
/* periodically check for people adding you to their facebook friend list */
fba->friend_request_timer = purple_timeout_add_seconds(60 * 5,
fb_check_friend_requests, fba);
- /* periodically check for updates to your buddy list */
- fba->buddy_list_timer = purple_timeout_add_seconds(60,
- fb_get_buddy_list, fba);
-
/* periodically check for new notifications */
fba->notifications_timer = purple_timeout_add_seconds(60,
(GSourceFunc)fb_get_notifications_feed, fba);
@@ -298,6 +165,9 @@ static void fb_login_cb(FacebookAccount
fba->perpetual_messages_timer = purple_timeout_add_seconds(15,
(GSourceFunc)fb_get_messages_failsafe, fba);
+ /* init blist subsystem */
+ fb_blist_init(fba);
+
/* init conversation subsystem */
fb_conversation_init(fba);
}
@@ -376,6 +246,9 @@ static void fb_close(PurpleConnection *p
purple_debug_info("facebook", "unloading plugin\n");
+ /* destroy blist subsystem */
+ fb_blist_destroy(fba);
+
/* destroy conversation subsystem */
fb_conversation_destroy(fba);
@@ -410,9 +283,6 @@ static void fb_close(PurpleConnection *p
postdata, NULL, NULL, FALSE);
g_free(postdata);
- if (fba->buddy_list_timer) {
- purple_timeout_remove(fba->buddy_list_timer);
- }
if (fba->friend_request_timer) {
purple_timeout_remove(fba->friend_request_timer);
}
@@ -518,7 +388,7 @@ static void fb_set_status_ok_cb(gpointer
postdata = g_strdup_printf("profile_id=%" G_GINT64_FORMAT "&clear=1&post_form_id=%s",
fba->uid, fba->post_form_id);
- fb_post_or_get(fba, FB_METHOD_POST, NULL, "/updatestatus.php",
+ fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/updatestatus.php",
postdata, NULL, NULL, FALSE);
g_free(postdata);
@@ -567,6 +437,7 @@ static void fb_buddy_free(PurpleBuddy *b
}
}
+#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5
static GHashTable *fb_get_account_text_table(PurpleAccount *account)
{
GHashTable *table;
@@ -577,6 +448,7 @@ static GHashTable *fb_get_account_text_t
return table;
}
+#endif
/******************************************************************************/
/* Plugin functions */
@@ -615,6 +487,17 @@ static void fb_display_plugin_info(Purpl
_("Version"), FACEBOOK_PLUGIN_VERSION);
}
+static void fb_refresh_blist(PurplePluginAction *action)
+{
+ PurpleConnection *pc;
+ FacebookAccount *fba;
+
+ pc = (PurpleConnection *) action->context;
+ fba = pc->proto_data;
+
+ fb_get_buddy_list(fba);
+}
+
static GList *fb_actions(PurplePlugin *plugin, gpointer context)
{
GList *m = NULL;
@@ -632,6 +515,11 @@ static GList *fb_actions(PurplePlugin *p
fb_search_users);
m = g_list_append(m, act);
+ // TODO: remove, this is for testing. REMOVE.
+ act = purple_plugin_action_new(_("Refresh buddy list..."),
+ fb_refresh_blist);
+ m = g_list_append(m, act);
+
return m;
}
@@ -646,8 +534,8 @@ static GList *fb_node_menu(PurpleBlistNo
buddy = (PurpleBuddy *)node;
act = purple_menu_action_new(_("_Poke"),
- PURPLE_CALLBACK(fb_blist_poke_buddy),
- NULL, NULL);
+ PURPLE_CALLBACK(fb_blist_poke_buddy),
+ NULL, NULL);
m = g_list_append(m, act);
}
return m;
@@ -674,17 +562,35 @@ static void plugin_init(PurplePlugin *pl
PurplePluginProtocolInfo *prpl_info = info->extra_info;
/* Add options to the advanced screen in the account settings */
- option = purple_account_option_bool_new(_("Hide myself in the Buddy List"), "facebook_hide_self", TRUE);
- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+ option = purple_account_option_bool_new(
+ _("Show history in new conversations"),
+ "facebook_show_history", TRUE);
+ prpl_info->protocol_options = g_list_append(
+ prpl_info->protocol_options, option);
- option = purple_account_option_bool_new(_("Set Facebook status through Pidgin status"), "facebook_set_status_through_pidgin", FALSE);
- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+ option = purple_account_option_bool_new(
+ _("Hide myself in the Buddy List"),
+ "facebook_hide_self", TRUE);
+ prpl_info->protocol_options = g_list_append(
+ prpl_info->protocol_options, option);
- option = purple_account_option_bool_new(_("Show Facebook notifications as e-mails in Pidgin"), "facebook_get_notifications", TRUE);
- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+ option = purple_account_option_bool_new(
+ _("Set Facebook status through Pidgin status"),
+ "facebook_set_status_through_pidgin", FALSE);
+ prpl_info->protocol_options = g_list_append(
+ prpl_info->protocol_options, option);
- option = purple_account_option_bool_new(_("Edit Facebook friends from Pidgin"), "facebook_manage_friends", FALSE);
- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+ option = purple_account_option_bool_new(
+ _("Show Facebook notifications as e-mails in Pidgin"),
+ "facebook_get_notifications", TRUE);
+ prpl_info->protocol_options = g_list_append(
+ prpl_info->protocol_options, option);
+
+ option = purple_account_option_bool_new(
+ _("Edit Facebook friends from Pidgin"),
+ "facebook_manage_friends", FALSE);
+ prpl_info->protocol_options = g_list_append(
+ prpl_info->protocol_options, option);
}
static PurplePluginProtocolInfo prpl_info = {
@@ -714,7 +620,7 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* change_passwd */
fb_add_buddy, /* add_buddy */
NULL, /* add_buddies */
- NULL, /* remove_buddy */
+ fb_buddy_remove, /* remove_buddy */
NULL, /* remove_buddies */
NULL, /* add_permit */
NULL, /* add_deny */
@@ -733,13 +639,13 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* get_cb_info */
NULL, /* get_cb_away */
NULL, /* alias_buddy */
- NULL, /* group_buddy */
- NULL, /* rename_group */
+ fb_group_buddy_move, /* group_buddy */
+ fb_group_rename, /* rename_group */
fb_buddy_free, /* buddy_free */
fb_conversation_closed, /* convo_closed */
purple_normalize_nocase,/* normalize */
NULL, /* set_buddy_icon */
- NULL, /* remove_group */
+ fb_group_remove, /* remove_group */
NULL, /* get_cb_real_name */
NULL, /* set_chat_topic */
NULL, /* find_blist_chat */
@@ -756,8 +662,12 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* unregister_user */
NULL, /* send_attention */
NULL, /* attention_types */
+#if PURPLE_MAJOR_VERSION >= 2 && PURPLE_MINOR_VERSION >= 5
sizeof(PurplePluginProtocolInfo), /* struct_size */
fb_get_account_text_table, /* get_account_text_table */
+#else
+ (gpointer) sizeof(PurplePluginProtocolInfo)
+#endif
};
static PurplePluginInfo info = {
============================================================
--- libpurple/protocols/facebook/libfacebook.h e5edab36948064137e8888d3aa9da077f34e2589
+++ libpurple/protocols/facebook/libfacebook.h 7d04fd4027fa7d06bc78b44177216e6d018567c7
@@ -21,7 +21,7 @@
#ifndef LIBFACEBOOK_H
#define LIBFACEBOOK_H
-#define FACEBOOK_PLUGIN_VERSION "1.53"
+#define FACEBOOK_PLUGIN_VERSION "1.54"
#define FACEBOOK_PLUGIN_ID "prpl-bigbrownchunx-facebookim"
#include <glib.h>
@@ -71,9 +71,11 @@
# include <zlib.h>
#endif
-#define FB_MAX_MSG_RETRY 2
+#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 12
+# define atoll(a) g_ascii_strtoll(a, NULL, 0)
+#endif
-#include <json-glib/json-glib.h>
+#define FB_MAX_MSG_RETRY 2
typedef struct _FacebookAccount FacebookAccount;
typedef struct _FacebookBuddy FacebookBuddy;
@@ -88,11 +90,13 @@ struct _FacebookAccount {
GHashTable *cookie_table;
gchar *post_form_id;
gint64 uid;
- guint buddy_list_timer;
+ guint buddy_list_timer; /* handled by fb_blist */
+ GHashTable *friend_lists; /* handled by fb_friendlist */
+ GHashTable *friend_lists_reverse; /* handled by fb_friendlist */
guint friend_request_timer;
gchar *channel_number;
guint message_fetch_sequence;
- gint64 last_message_time;
+ gint64 last_message_time; /* handled by fb_conversation */
GSList *resending_messages;
GHashTable *auth_buddies;
GHashTable *hostname_ip_cache;
@@ -116,10 +120,4 @@ struct _FacebookBuddy {
gchar *thumb_url;
};
-/* TODO: move util functions into a utils file */
-gchar *fb_strdup_withhtml(const gchar *src);
-gchar *fb_convert_unicode(const gchar *input);
-JsonParser *fb_get_parser(const gchar *data, gsize data_len);
-gint64 fb_time_kludge(int initial_time);
-
#endif /* LIBFACEBOOK_H */
============================================================
--- libpurple/protocols/facebook/pidgin-facebookchat.rc 1254a3c5068a1788a466179ff715a73c2a695c6b
+++ libpurple/protocols/facebook/pidgin-facebookchat.rc 6fa6c5397a3dfd95a4447ef1a17390ba0e8246e1
@@ -1,7 +1,7 @@ 1 VERSIONINFO
1 VERSIONINFO
-FILEVERSION 1,53,0,0
-PRODUCTVERSION 1,53,0,0
+FILEVERSION 1,54,0,0
+PRODUCTVERSION 1,54,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.53\0"
- VALUE "ProductVersion", "1.53\0"
+ VALUE "FileVersion", "1.54\0"
+ VALUE "ProductVersion", "1.54\0"
VALUE "InternalName", "pidgin-facebookchat\0"
VALUE "OriginalFilename", "libfacebook.dll\0"
VALUE "Comments", "http://pidgin-facebookchat.googlecode.com/\0"
More information about the Commits
mailing list