adium: 7e1a5251: pidgin-facebookchat at r564.
zacw at adiumx.com
zacw at adiumx.com
Mon Jun 29 19:05:34 EDT 2009
-----------------------------------------------------------------
Revision: 7e1a5251180b65c5f9c3242f700497baf7062721
Ancestor: 83638905971b97ae72bc7318a7f152adf5e8b6f1
Author: zacw at adiumx.com
Date: 2009-06-29T23:01:38
Branch: im.pidgin.adium
URL: http://d.pidgin.im/viewmtn/revision/info/7e1a5251180b65c5f9c3242f700497baf7062721
Added files:
libpurple/protocols/facebook/fb_conversation.c
libpurple/protocols/facebook/fb_conversation.h
libpurple/protocols/facebook/fb_util.c
libpurple/protocols/facebook/fb_util.h
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_connection.h
libpurple/protocols/facebook/fb_info.c
libpurple/protocols/facebook/fb_managefriends.c
libpurple/protocols/facebook/fb_messages.c
libpurple/protocols/facebook/fb_notifications.c
libpurple/protocols/facebook/libfacebook.c
libpurple/protocols/facebook/libfacebook.h
libpurple/protocols/facebook/pidgin-facebookchat.rc
libpurple/protocols/facebook/rss.xml
Modified attrs:
libpurple/protocols/facebook/fb_util.c
libpurple/protocols/facebook/fb_util.h
ChangeLog:
pidgin-facebookchat at r564.
-------------- next part --------------
============================================================
--- libpurple/protocols/facebook/fb_conversation.c 259358150129a9c835a26193282d46f2dd284d18
+++ libpurple/protocols/facebook/fb_conversation.c 259358150129a9c835a26193282d46f2dd284d18
@@ -0,0 +1,258 @@
+/*
+ * 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_conversation.h"
+#include "fb_connection.h"
+#include "fb_util.h"
+
+#include <json-glib/json-glib.h>
+
+#include "conversation.h"
+#include "signals.h"
+
+/*****************************************************************************
+ * MESSAGE PROCESSING *
+ *****************************************************************************/
+void fb_conversation_handle_message(FacebookAccount *fba, const char *from,
+ const char *to, gint64 message_time, const gchar *message_orig,
+ gboolean log)
+{
+ gchar *tmp, *message_text;
+
+ if (!log) {
+ purple_debug_info("facebook", "message with no logging\n");
+ }
+
+ // Process message.
+ message_text = fb_strdup_withhtml(message_orig);
+ tmp = message_text;
+ message_text = fb_replace_styled_text(message_text);
+ g_free(tmp);
+
+ if (fba->uid != atoll(from) || fba->uid == atoll(to)) {
+ purple_debug_info("facebook",
+ "displaying received message %lld: %s\n",
+ 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,
+ log?
+ PURPLE_MESSAGE_RECV :
+ PURPLE_MESSAGE_RECV,
+ message_time / 1000);
+ if (message_time > fba->last_message_time) {
+ fba->last_message_time = message_time;
+ } else {
+ purple_debug_warning("facebook",
+ "displaying message out of sync\n");
+ }
+ } else if (!g_hash_table_remove(
+ fba->sent_messages_hash, message_orig))
+ {
+ purple_debug_info("facebook",
+ "displaying sent message %lld: %s\n",
+ message_time, message_text);
+
+ serv_got_im(fba->pc, to, message_text,
+ log?
+ PURPLE_MESSAGE_SEND :
+ PURPLE_MESSAGE_SEND,
+ message_time / 1000);
+ if (message_time > fba->last_message_time) {
+ fba->last_message_time = message_time;
+ } else {
+ purple_debug_warning("facebook",
+ "displaying message out of sync\n");
+ }
+ }
+
+ // Cleanup.
+ g_free(message_text);
+}
+
+
+/*****************************************************************************
+ * HISTORY CODE *
+ *****************************************************************************/
+
+static void fb_history_fetch_cb(FacebookAccount *fba, gchar *data,
+ gsize data_len, gpointer userdata)
+{
+ JsonParser *parser;
+ JsonNode *root;
+ JsonObject *object, *payload;
+ JsonArray *history;
+ guint i;
+ gint64 min_time;
+
+ parser = fb_get_parser(data, data_len);
+
+ if (!parser) {
+ // We didn't get data, but this isn't necessarily fatal.
+ purple_debug_warning("facebook",
+ "bad data while fetching history\n");
+ return;
+ }
+
+ min_time = atoll((char *) userdata);
+ g_free(userdata);
+ purple_debug_info("facebook", "history fetch with min time of %lld\n",
+ min_time);
+
+ root = json_parser_get_root(parser);
+ object = json_node_get_object(root);
+ payload = json_node_get_object(
+ json_object_get_member(object, "payload"));
+ history = json_node_get_array(
+ json_object_get_member(payload, "history"));
+
+ purple_debug_info("facebook",
+ "found %d history items to possibly render\n",
+ json_array_get_length(history));
+
+ for (i = 0; i < json_array_get_length(history); i++) {
+ const gchar *type;
+ JsonObject *message_obj;
+
+ message_obj = json_node_get_object(
+ json_array_get_element(history, i));
+ type = json_node_get_string(json_object_get_member(
+ message_obj, "type"));
+
+ if (g_str_equal(type, "msg")) {
+ gint64 message_time;
+ const gchar *message;
+ gchar *from;
+ gchar *to;
+ JsonObject *text_obj;
+
+ from = g_strdup_printf("%d", json_node_get_int(
+ json_object_get_member(message_obj, "from")));
+ to = g_strdup_printf("%d", json_node_get_int(
+ json_object_get_member(message_obj, "to")));
+
+ text_obj = json_node_get_object(
+ json_object_get_member(message_obj, "msg"));
+ message = json_node_get_string(
+ json_object_get_member(text_obj, "text"));
+
+ message_time = fb_time_kludge(json_node_get_int(
+ json_object_get_member(message_obj, "time")));
+
+ if (message_time > min_time) {
+ purple_debug_info("facebook",
+ "displaying history message %lld\n",
+ message_time);
+ fb_conversation_handle_message(
+ fba, from, to, message_time, message,
+ min_time != 0);
+ }
+
+ g_free(from);
+ g_free(to);
+ }
+ }
+
+ g_object_unref(parser);
+}
+
+void fb_history_fetch(FacebookAccount *fba, const char *who,
+ gboolean display_all)
+{
+ g_return_if_fail(fba != NULL);
+
+ purple_debug_info("facebook", "fetching history with %s\n", who);
+
+ gint64 min_time = fba->last_message_time;
+ if (display_all) {
+ min_time = 0;
+ }
+
+ 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_free(url);
+}
+
+/*****************************************************************************
+ * GENERAL EVENTS CODE *
+ *****************************************************************************/
+
+void fb_conversation_closed(PurpleConnection *gc, const char *who)
+{
+ FacebookAccount *fba = gc->proto_data;
+ gchar *postdata;
+
+ g_return_if_fail(fba->post_form_id != NULL);
+
+ /* notify server that we closed the chat window */
+ /* close_chat=589039771&window_id=3168919846&
+ * post_form_id=c258fe42460c7e8b61e242a37ef05afc */
+ postdata = g_strdup_printf("close_chat=%s&post_form_id=%s", who,
+ fba->post_form_id);
+ fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/chat/settings.php",
+ postdata, NULL, NULL, FALSE);
+ g_free(postdata);
+}
+
+static void fb_conversation_created(PurpleConversation *conv)
+{
+ PurpleAccount *account = purple_conversation_get_account(conv);
+
+ if (!fb_conversation_is_fb(conv)) {
+ return;
+ }
+
+ purple_debug_info("facebook", "conversation created with %s\n",
+ conv->name);
+
+ fb_history_fetch(account->gc->proto_data, conv->name, TRUE);
+}
+
+gboolean fb_conversation_is_fb(PurpleConversation *conv)
+{
+ PurpleAccount *account = purple_conversation_get_account(conv);
+ const gchar *prpl = purple_account_get_protocol_id(account);
+ return g_str_equal(prpl, FACEBOOK_PLUGIN_ID);
+}
+
+void fb_conversation_init(FacebookAccount *fba)
+{
+ fba->last_message_time = 0;
+
+ purple_signal_connect(
+ purple_conversations_get_handle(),
+ "conversation-created",
+ fba,
+ PURPLE_CALLBACK(fb_conversation_created),
+ NULL);
+}
+
+void fb_conversation_destroy(FacebookAccount *fba)
+{
+ purple_signal_disconnect(
+ purple_conversations_get_handle(),
+ "conversation-created",
+ fba,
+ PURPLE_CALLBACK(fb_conversation_created));
+}
+
+
============================================================
--- libpurple/protocols/facebook/fb_conversation.h 828d73df9a7ffcd3680ee051f49606328a742185
+++ libpurple/protocols/facebook/fb_conversation.h 828d73df9a7ffcd3680ee051f49606328a742185
@@ -0,0 +1,38 @@
+/*
+ * 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_CONVERSATION_H
+#define FACEBOOK_CONVERSATION_H
+
+#include "libfacebook.h"
+
+void fb_conversation_init(FacebookAccount *fba);
+void fb_conversation_destroy(FacebookAccount *fba);
+
+void fb_conversation_closed(PurpleConnection *gc, const char *who);
+gboolean fb_conversation_is_fb(PurpleConversation *conv);
+
+void fb_history_fetch(FacebookAccount *fba, const char *who,
+ gboolean display_all);
+void fb_conversation_handle_message(FacebookAccount *fba, const char *from,
+ const char *to, gint64 message_time, const gchar *message_orig,
+ gboolean log);
+
+#endif /* FACEBOOK_CONVERSATION_H */
============================================================
--- libpurple/protocols/facebook/fb_util.c 23606c4fef64d4b023b7dca41ac62a8b499a4924
+++ libpurple/protocols/facebook/fb_util.c 23606c4fef64d4b023b7dca41ac62a8b499a4924
@@ -0,0 +1,64 @@
+/*
+ * 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_util.h"
+
+/*****************************************************************************
+ * UTILITY CODE *
+ *****************************************************************************/
+
+/* Converts *text* into <b>text</b> and _text_ into <i>text</i> */
+gchar *fb_replace_styled_text(const gchar *text)
+{
+ if (glib_check_version(2, 14, 0))
+ {
+ return g_strdup(text);
+ } else {
+ static GRegex *underline_regex = NULL;
+ static GRegex *bold_regex = NULL;
+ gchar *dup_text;
+ gchar *midway_string;
+ gchar *output_string;
+
+ if (underline_regex == NULL)
+ {
+ underline_regex = g_regex_new(
+ "\\b_([^_\\*]+)_\\b", G_REGEX_OPTIMIZE,
+ 0, NULL);
+ }
+ if (bold_regex == NULL)
+ {
+ bold_regex = g_regex_new(
+ "(\\s|^)\\*([^_\\*]+)\\*(?=$|\\s)",
+ G_REGEX_OPTIMIZE, 0, NULL);
+ }
+
+ dup_text = g_strdup(text);
+ midway_string = g_regex_replace(underline_regex, dup_text,
+ -1, 0, "<u>\\1</u>", 0, NULL);
+ g_free(dup_text);
+ output_string = g_regex_replace(bold_regex, midway_string,
+ -1, 0, "\\1<b>\\2</b>", 0, NULL);
+ g_free(midway_string);
+
+ return output_string;
+ }
+}
+
============================================================
--- libpurple/protocols/facebook/fb_util.h 33093b85583658b53d9519de66ab7da32ebd5076
+++ libpurple/protocols/facebook/fb_util.h 33093b85583658b53d9519de66ab7da32ebd5076
@@ -0,0 +1,29 @@
+/*
+ * 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_UTIL_H
+#define FACEBOOK_UTIL_H
+
+#include "libfacebook.h"
+
+gchar *fb_replace_styled_text(const gchar *text);
+
+#endif /* FACEBOOK_UTIL_H */
+
============================================================
--- libpurple/protocols/facebook/facebook.nsi 67598b3e9ead8be15c1e600b6dd3de05c0dd682e
+++ libpurple/protocols/facebook/facebook.nsi 86d06564f9bcb28939ce31fea5cf6e899cb530a9
@@ -6,7 +6,7 @@ SetCompress off
; todo: SetBrandingImage
; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "pidgin-facebookchat"
-!define PRODUCT_VERSION "1.51"
+!define PRODUCT_VERSION "1.53"
!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 5074f94eb56fc5bfe2337b0e991d3ef9d0f20361
+++ libpurple/protocols/facebook/fb_blist.c a756fad89ceaabc66d0f1f4798a348b416396471
@@ -40,6 +40,7 @@ static void buddy_icon_cb(FacebookAccoun
{
gchar *buddyname;
PurpleBuddy *buddy;
+ FacebookBuddy *fbuddy;
gpointer buddy_icon_data;
buddyname = user_data;
@@ -53,10 +54,12 @@ static void buddy_icon_cb(FacebookAccoun
if (buddy == NULL)
return;
+ fbuddy = buddy->proto_data;
+
buddy_icon_data = g_memdup(data, data_len);
purple_buddy_icons_set_for_user(fba->account, buddy->name,
- buddy_icon_data, data_len, NULL);
+ buddy_icon_data, data_len, fbuddy->thumb_url);
}
static void got_buddy_list_cb(FacebookAccount *fba, gchar *data,
@@ -86,7 +89,8 @@ static void got_buddy_list_cb(FacebookAc
if (fba == NULL)
return;
- if (data == NULL) {
+ JsonParser *parser = fb_get_parser(data, data_len);
+ if (parser == NULL) {
purple_connection_error_reason(fba->pc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("Could not retrieve buddy list"));
@@ -95,23 +99,7 @@ static void got_buddy_list_cb(FacebookAc
purple_debug_misc("facebook", "buddy list\n%s\n", data);
- tmp = g_strstr_len(data, data_len, "for (;;);");
- if (tmp)
- {
- tmp += strlen("for (;;);");
- }
-
- JsonParser *parser;
JsonNode *root;
-
- parser = json_parser_new();
- if(!json_parser_load_from_data(parser, tmp, -1, NULL))
- {
- purple_connection_error_reason(fba->pc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Could not retrieve buddy list"));
- return;
- }
root = json_parser_get_root(parser);
JsonObject *objnode;
objnode = json_node_get_object(root);
@@ -170,15 +158,13 @@ static void got_buddy_list_cb(FacebookAc
currentUserNode = g_list_next(currentUserNode))
{
uid = currentUserNode->data;
- purple_debug_misc("facebook", "uid: %s\n", uid);
JsonObject *userInfo;
userInfo = json_node_get_object(json_object_get_member(userInfos, uid));
name = json_node_dup_string(json_object_get_member(userInfo, "name"));
- purple_debug_misc("facebook", "name: %s\n", name);
- /* try updating the alias, just in case it was removed locally */
- serv_got_alias(fba->pc, uid, 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))
@@ -186,7 +172,6 @@ static void got_buddy_list_cb(FacebookAc
JsonObject *userBlistInfo;
userBlistInfo = json_node_get_object(json_object_get_member(nowAvailableList, uid));
idle = json_node_get_boolean(json_object_get_member(userBlistInfo, "i"));
- purple_debug_misc("facebook", "buddy idle: %s\n", (idle?"true":"false"));
current_buddy_online = TRUE;
} else {
/* if we're here, the buddy's info has been sent, but they're not actually online */
@@ -203,7 +188,7 @@ static void got_buddy_list_cb(FacebookAc
}
/* is this us? */
- if (atoi(uid) == fba->uid)
+ if (atoll(uid) == fba->uid)
{
purple_connection_set_display_name(fba->pc, name);
@@ -235,7 +220,6 @@ static void got_buddy_list_cb(FacebookAc
}
purple_blist_add_buddy(buddy, NULL, fb_group, NULL);
}
- serv_got_alias(fba->pc, uid, name);
purple_presence_set_idle(purple_buddy_get_presence(buddy), idle, 0);
/* Set the FacebookBuddy structure */
@@ -244,13 +228,13 @@ static void got_buddy_list_cb(FacebookAc
fbuddy = g_new0(FacebookBuddy, 1);
fbuddy->buddy = buddy;
fbuddy->fba = fba;
- fbuddy->uid = atoi(uid);
+ fbuddy->uid = atoll(uid);
fbuddy->name = g_strdup(name);
- /* load the old buddy icon from the account settings */
- tmp = g_strdup_printf("buddy_icon_%d_cache", fbuddy->uid);
- fbuddy->thumb_url = g_strdup(purple_account_get_string(fba->account, tmp, ""));
- g_free(tmp);
+ /* 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 {
@@ -264,7 +248,6 @@ static void got_buddy_list_cb(FacebookAc
tmp = fb_strdup_withhtml(status_text);
g_free(status_text);
status_text = tmp;
- purple_debug_misc("facebook", "status: %s\n", status_text);
status_time_text = json_node_dup_string(json_object_get_member(userInfo, "statusTimeRel"));
if (strlen(status_time_text) == 0)
@@ -276,7 +259,7 @@ static void got_buddy_list_cb(FacebookAc
if (status_time_text != NULL)
{
fbuddy->status_rel_time = fb_strdup_withhtml(status_time_text);
- purple_debug_misc("facebook", "status time: %s\n", fbuddy->status_rel_time);
+ g_free(status_time_text);
} else {
fbuddy->status_rel_time = NULL;
}
@@ -310,37 +293,28 @@ static void got_buddy_list_cb(FacebookAc
if (fbuddy->thumb_url == NULL || !g_str_equal(fbuddy->thumb_url, buddy_icon_url))
{
g_free(fbuddy->thumb_url);
- fbuddy->thumb_url = g_strdup(buddy_icon_url);
-
- /* Save the buddy icon so that they don't all need to be reloaded at startup */
- tmp = g_strdup_printf("buddy_icon_%d_cache", fbuddy->uid);
- purple_account_set_string(fba->account, tmp, buddy_icon_url);
- g_free(tmp);
-
- /* Turn the \/ into / */
- tmp = g_strcompress(buddy_icon_url);
-
- if (g_str_equal(tmp, "http://static.ak.fbcdn.net/pics/q_silhouette.gif"))
+ 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(tmp, "/q");
+ 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",
- tmp + strlen("http://profile.ak.facebook.com"), NULL,
- buddy_icon_cb, g_strdup(purple_buddy_get_name(buddy)),
- FALSE);
+ buddy_icon_url + strlen("http://profile.ak.facebook.com"), NULL,
+ buddy_icon_cb, g_strdup(purple_buddy_get_name(buddy)), FALSE);
}
- g_free(tmp);
}
g_free(buddy_icon_url);
@@ -364,7 +338,7 @@ static void got_buddy_list_cb(FacebookAc
}
g_hash_table_destroy(online_buddies_list);
- if (notifications != NULL)
+ if (notifications != NULL && purple_account_get_check_mail(fba->account))
{
JsonNode *inboxCount_node = json_object_get_member(notifications, "inboxCount");
if (inboxCount_node)
@@ -391,7 +365,7 @@ gboolean fb_get_buddy_list(gpointer data
fba = data;
postdata = g_strdup_printf(
- "user=%d&popped_out=true&force_render=true&buddy_list=1¬ifications=1",
+ "user=%" G_GINT64_FORMAT "&popped_out=true&force_render=true&buddy_list=1¬ifications=1",
fba->uid);
fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/presence/update.php",
postdata, got_buddy_list_cb, NULL, FALSE);
@@ -419,7 +393,7 @@ void fb_blist_poke_buddy(PurpleBlistNode
if (!fba)
return;
- postdata = g_strdup_printf("uid=%d&pokeback=0&post_form_id=%s", fbuddy->uid, fba->post_form_id);
+ postdata = g_strdup_printf("uid=%" G_GINT64_FORMAT "&pokeback=0&post_form_id=%s", fbuddy->uid, fba->post_form_id);
fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/poke.php",
postdata, NULL, NULL, FALSE);
@@ -427,3 +401,28 @@ void fb_blist_poke_buddy(PurpleBlistNode
g_free(postdata);
}
+void fb_blist_set_alias(FacebookAccount *fba, const gchar *id,
+ const gchar *name)
+{
+ const char *current_alias;
+ PurpleBuddy *buddy;
+
+ buddy = purple_find_buddy(fba->account, id);
+ if (!buddy) {
+ return;
+ }
+
+ /* Set an alias if no user-defined alias is set yet. This provides
+ * a basic name alias for each user which is more useful than a
+ * number. A small corner case bug here- aliases will not change
+ * in accordance with people changing their names on Facebook.
+ */
+ current_alias = purple_buddy_get_alias_only(buddy);
+ if (!current_alias) {
+ purple_debug_info("facebook", "aliasing %s to %s\n", id, name);
+ purple_blist_alias_buddy(buddy, name);
+ }
+
+ /* In case user removes an alias, we have the server as fallback */
+ serv_got_alias(fba->pc, id, name);
+}
============================================================
--- libpurple/protocols/facebook/fb_blist.h 25ed459fca57c9f2b6e324cbba392d29081ce75c
+++ libpurple/protocols/facebook/fb_blist.h 282d636d6e7f6011bec4f39d5cc9483b1be8b199
@@ -26,4 +26,7 @@ void fb_blist_poke_buddy(PurpleBlistNode
gboolean fb_get_buddy_list(gpointer data);
void fb_blist_poke_buddy(PurpleBlistNode *node, gpointer data);
+void fb_blist_set_alias(FacebookAccount *fba, const char *id,
+ const char *name);
+
#endif /* FACEBOOK_BLIST_H */
============================================================
--- libpurple/protocols/facebook/fb_connection.c 8668d97080d9afe72ca0519bb5f0ab641daa34c5
+++ libpurple/protocols/facebook/fb_connection.c 557b8518d7576ae548b710f016cbca9d3f76f606
@@ -123,6 +123,7 @@ void fb_connection_destroy(FacebookConne
if (fbconn->input_watcher > 0)
purple_input_remove(fbconn->input_watcher);
+ g_free(fbconn->url);
g_free(fbconn->hostname);
g_free(fbconn);
}
@@ -153,9 +154,6 @@ static void fb_update_cookies(FacebookAc
cookie_value= g_strndup(cookie_start, cookie_end-cookie_start);
cookie_start = cookie_end;
- purple_debug_info("facebook", "got cookie %s=%s\n",
- cookie_name, cookie_value);
-
g_hash_table_replace(fba->cookie_table, cookie_name,
cookie_value);
}
@@ -184,8 +182,6 @@ static void fb_connection_process_data(F
tmp = g_memdup(tmp, len + 1);
tmp[len] = '\0';
fbconn->rx_buf[fbconn->rx_len - len] = '\0';
- purple_debug_misc("facebook", "response headers\n%s\n",
- fbconn->rx_buf);
fb_update_cookies(fbconn->fba, fbconn->rx_buf);
#ifdef HAVE_ZLIB
@@ -203,8 +199,10 @@ static void fb_connection_process_data(F
g_free(fbconn->rx_buf);
fbconn->rx_buf = NULL;
- if (fbconn->callback != NULL)
+ if (fbconn->callback != NULL) {
+ purple_debug_info("facebook", "executing callback for %s\n", fbconn->url);
fbconn->callback(fbconn->fba, tmp, len, fbconn->user_data);
+ }
g_free(tmp);
}
@@ -312,13 +310,13 @@ static void fb_post_or_get_connect_cb(gp
if (error_message)
{
+ purple_debug_error("facebook", "post_or_get_connect failure to %s\n", fbconn->url);
purple_debug_error("facebook", "post_or_get_connect_cb %s\n",
error_message);
fb_fatal_connection_cb(fbconn);
return;
}
- purple_debug_info("facebook", "post_or_get_connect_cb\n");
fbconn->fd = source;
/* TODO: Check the return value of write() */
@@ -356,8 +354,6 @@ static void fb_host_lookup_cb(GSList *ho
FacebookAccount *fba;
PurpleDnsQueryData *query;
- purple_debug_info("facebook", "updating cache of dns addresses\n");
-
/* Extract variables */
host_lookup_list = data;
@@ -412,9 +408,6 @@ static void fb_host_lookup_cb(GSList *ho
hosts = g_slist_delete_link(hosts, hosts);
}
- purple_debug_info("facebook", "Host %s has IP %s\n",
- hostname, ip_address);
-
g_hash_table_insert(fba->hostname_ip_cache, hostname, ip_address);
}
@@ -538,8 +531,7 @@ void fb_post_or_get(FacebookAccount *fba
g_string_append_printf(request, "Accept-Language: %s\r\n", language_names);
g_free(language_names);
- purple_debug_misc("facebook", "sending request headers:\n%s\n",
- request->str);
+ purple_debug_info("facebook", "getting url %s\n", url);
g_string_append_printf(request, "\r\n");
if (method & FB_METHOD_POST)
@@ -549,11 +541,11 @@ void fb_post_or_get(FacebookAccount *fba
* it in the debug log. Without this condition a user's password is
* printed in the debug log */
if (method == FB_METHOD_POST)
- purple_debug_misc("facebook", "sending request data:\n%s\n",
+ purple_debug_info("facebook", "sending request data:\n%s\n",
postdata);
g_free(cookies);
- g_free(real_url);
+
/*
* Do a separate DNS lookup for the given host name and cache it
* for next time.
@@ -574,9 +566,6 @@ void fb_post_or_get(FacebookAccount *fba
host_ip = g_hash_table_lookup(fba->hostname_ip_cache, host);
if (host_ip != NULL) {
- purple_debug_info("facebook",
- "swapping original host %s with cached value of %s\n",
- host, host_ip);
host = host_ip;
} else if (fba->account && !fba->account->disconnecting) {
GSList *host_lookup_list = NULL;
@@ -596,6 +585,7 @@ void fb_post_or_get(FacebookAccount *fba
fbconn = g_new0(FacebookConnection, 1);
fbconn->fba = fba;
+ fbconn->url = real_url;
fbconn->method = method;
fbconn->hostname = g_strdup(host);
fbconn->request = request;
============================================================
--- libpurple/protocols/facebook/fb_connection.h 89a1161f53d976e628a64a9f9d7a189db6e25f47
+++ libpurple/protocols/facebook/fb_connection.h e3c87874ac44ae6437066264c6a9996be5333a0e
@@ -38,6 +38,7 @@ struct _FacebookConnection {
FacebookAccount *fba;
FacebookMethod method;
gchar *hostname;
+ gchar *url;
GString *request;
FacebookProxyCallbackFunc callback;
gpointer user_data;
============================================================
--- libpurple/protocols/facebook/fb_info.c e106afd4c3c6b0a50eabe2befdffa860563a6f33
+++ libpurple/protocols/facebook/fb_info.c 3eb9ceaf6170bc0b2ab8f2ef73d9adec28363839
@@ -65,6 +65,7 @@ static void fb_get_info_cb(FacebookAccou
FacebookBuddy *fbuddy = NULL;
purple_debug_info("facebook", "get_info_cb\n");
+ purple_debug_info("facebook", "%s\n", data);
buddy = purple_find_buddy(fba->account, uid);
if (buddy)
@@ -86,6 +87,33 @@ static void fb_get_info_cb(FacebookAccou
search_start = g_strstr_len(data, data_len, "<div id=\"info_tab\" class=\"info_tab\">");
if (search_start == NULL)
{
+ search_start = g_strstr_len(data, data_len, "http:\\/\\/");
+ if (search_start)
+ {
+ search_end = strstr(search_start, "\"");
+ value_tmp = g_strndup(search_start, search_end - search_start);
+ value_tmp2 = value_tmp;
+ if (value_tmp) {
+ char * buf = g_new(char, strlen(value_tmp) + 1);
+ char * url = buf;
+ while(*value_tmp) {
+ if (*value_tmp=='\\') {
+ // skip escape char
+ *buf++ = value_tmp[1];
+ value_tmp += 2;
+ } else {
+ *buf++ = *value_tmp++;
+ }
+ }
+ *buf = 0;
+ purple_debug_info("facebook", "info url: %s\n", url);
+ fb_post_or_get(fba->pc->proto_data, FB_METHOD_GET, NULL, url, NULL, fb_get_info_cb, g_strdup(uid), FALSE);
+ g_free(uid);
+ g_free(url);
+ g_free(value_tmp2);
+ return;
+ }
+ }
purple_debug_warning("facebook",
"could not find user info, showing default");
purple_notify_userinfo(fba->pc, uid, user_info, NULL, NULL);
@@ -177,12 +205,16 @@ static void fb_get_info_cb(FacebookAccou
}
/* turn html to plaintext */
- value_tmp2 = g_strchomp(purple_markup_strip_html(value_tmp));
- g_free(value_tmp);
+ if (strcmp(label_tmp, "AIM")) {
+ value_tmp2 = g_strchomp(purple_markup_strip_html(value_tmp));
+ g_free(value_tmp);
+ value_tmp = value_tmp2;
- /* remove the silly links */
- value_tmp = fb_remove_useless_stripped_links(value_tmp2);
- g_free(value_tmp2);
+ /* remove the silly links */
+ value_tmp2 = fb_remove_useless_stripped_links(value_tmp);
+ g_free(value_tmp);
+ value_tmp = value_tmp2;
+ }
purple_debug_info("facebook", "label: %s\n", label_tmp);
purple_debug_info("facebook", "value: %s\n", value_tmp);
============================================================
--- libpurple/protocols/facebook/fb_managefriends.c 13711a39b329088119005f6dd7c6ec6617de8f26
+++ libpurple/protocols/facebook/fb_managefriends.c 48d9104fae04b40e366b570f78e4b366e0d87a43
@@ -25,46 +25,52 @@ static void fb_auth_accept_cb(gpointer d
{
FacebookBuddy *fbuddy = data;
FacebookAccount *fba = fbuddy->fba;
+ gchar *buddy_uid;
gchar *postdata;
g_return_if_fail(fba != NULL);
g_return_if_fail(fba->post_form_id != NULL);
g_return_if_fail(fbuddy->uid != 0);
+ buddy_uid = g_strdup_printf("%" G_GINT64_FORMAT, fbuddy->uid);
+
postdata = g_strdup_printf(
- "type=friend_add&id=%d&action=accept&post_form_id=%s",
- fbuddy->uid, fba->post_form_id);
+ "type=friend_add&id=%s&action=accept&post_form_id=%s",
+ buddy_uid, fba->post_form_id);
fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/reqs.php",
postdata, NULL, NULL, FALSE);
- g_free(postdata);
- fba->auth_buddies = g_slist_remove(fba->auth_buddies,
- GINT_TO_POINTER(fbuddy->uid));
-
+ g_hash_table_remove(fba->auth_buddies, buddy_uid);
+
+ g_free(postdata);
g_free(fbuddy);
+ g_free(buddy_uid);
}
static void fb_auth_reject_cb(gpointer data)
{
FacebookBuddy *fbuddy = data;
FacebookAccount *fba = fbuddy->fba;
+ gchar *buddy_uid;
gchar *postdata;
g_return_if_fail(fba != NULL);
g_return_if_fail(fba->post_form_id != NULL);
g_return_if_fail(fbuddy->uid != 0);
+ buddy_uid = g_strdup_printf("%" G_GINT64_FORMAT, fbuddy->uid);
+
postdata = g_strdup_printf(
- "type=friend_add&id=%d&action=reject&post_form_id=%s",
- fbuddy->uid, fba->post_form_id);
+ "type=friend_add&id=%s&action=reject&post_form_id=%s",
+ buddy_uid, fba->post_form_id);
fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/reqs.php",
postdata, NULL, NULL, FALSE);
- g_free(postdata);
- fba->auth_buddies = g_slist_remove(fba->auth_buddies,
- GINT_TO_POINTER(fbuddy->uid));
-
+ g_hash_table_remove(fba->auth_buddies, buddy_uid);
+
+ g_free(postdata);
g_free(fbuddy);
+ g_free(buddy_uid);
}
static void fb_check_friend_request_cb(FacebookAccount *fba, gchar *data,
@@ -89,10 +95,10 @@ static void fb_check_friend_request_cb(F
strchr(search_start, '"') - search_start);
purple_debug_info("facebook", "uid: %s\n", uid);
- uid_int = atoi(uid);
+ uid_int = atoll(uid);
- if (g_slist_find(fba->auth_buddies,
- GINT_TO_POINTER(uid_int)) != NULL)
+ if (g_hash_table_lookup_extended(fba->auth_buddies,
+ uid, NULL, NULL))
{
/* we've already notified the user of this friend request */
g_free(uid);
@@ -130,13 +136,12 @@ static void fb_check_friend_request_cb(F
name, msg_plain, TRUE,
fb_auth_accept_cb, fb_auth_reject_cb, buddy);
+ /* Don't display an auth request for this buddy again */
+ g_hash_table_insert(fba->auth_buddies, uid, NULL);
+
g_free(name);
g_free(uid);
- g_free(msg_plain);
-
- /* Don't display an auth request for this buddy again */
- fba->auth_buddies = g_slist_prepend(
- fba->auth_buddies, GINT_TO_POINTER(uid_int));
+ g_free(msg_plain);
}
}
@@ -171,7 +176,7 @@ void fb_add_buddy(PurpleConnection *pc,
return;
}
- if (atoi(buddy->name) == fba->uid)
+ if (atoll(buddy->name) == fba->uid)
{
purple_account_set_bool(fba->account,
"facebook_hide_self", FALSE);
@@ -200,7 +205,7 @@ static void fb_remove_buddy(PurpleConnec
gchar *postdata;
FacebookAccount *fba = pc->proto_data;
- if (atoi(buddy->name) == fba->uid)
+ if (atoll(buddy->name) == fba->uid)
{
purple_account_set_bool(fba->account, "facebook_hide_self", TRUE);
return;
============================================================
--- libpurple/protocols/facebook/fb_messages.c f5bc0e080df2dcc102667479e7940791008251bd
+++ libpurple/protocols/facebook/fb_messages.c 55cba18f6f06fcf967d93af64fce1cbb06224521
@@ -20,9 +20,13 @@
#include "fb_messages.h"
#include "fb_connection.h"
+#include "fb_conversation.h"
+#include "fb_blist.h"
#include <json-glib/json-glib.h>
+#include "conversation.h"
+
typedef struct _FacebookOutgoingMessage FacebookOutgoingMessage;
struct _FacebookOutgoingMessage {
@@ -38,7 +42,6 @@ static gboolean fb_get_new_messages(Face
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 gchar *fb_replace_styled_text(const gchar *text);
static FacebookOutgoingMessage *fb_msg_create(FacebookAccount *fba)
{
@@ -68,33 +71,94 @@ void fb_cancel_resending_messages(Facebo
fb_msg_destroy(msg);
}
}
-
-static void got_new_messages(FacebookAccount *fba, gchar *data,
- gsize data_len, gpointer userdata)
+
+static void parse_message(PurpleConnection *pc, FacebookAccount *fba,
+ JsonObject *messageObj, const char* from, const char* to)
{
- gchar *message;
- gchar *message_text;
- gchar *message_time;
- gchar *from;
- gchar *to;
- gchar *tmp;
- gchar *type;
- gchar *start;
- gchar *end;
- gint64 msgID;
+ gint64 message_time;
+ const gchar *message;
+
+ purple_debug_info("facebook", "message from %s to %s\n", from, to);
+
+ message = json_node_get_string(
+ json_object_get_member(messageObj, "text"));
+
+ message_time = fb_time_kludge(json_node_get_int(
+ json_object_get_member(messageObj, "time")));
+
+ fb_conversation_handle_message(fba, from, to, message_time, message, TRUE);
+}
+
+static void parse_new_messages(PurpleConnection *pc, FacebookAccount *fba, JsonArray *messages)
+{
int i;
- PurpleConnection *pc = userdata;
PurpleBuddy *buddy;
- /* NULL data will crash on Windows */
- if (data == NULL)
- data = "(null)";
+ purple_debug_info("facebook", "parsing new messages\n");
- purple_debug_misc("facebook", "got new messages: %s\n", data);
+ for (i = 0; i < json_array_get_length(messages); i++) {
+ const gchar *type;
+ gchar *from, *to;
- /* purple_debug_info("facebook", "fba: %d\n", fba); */
- /* purple_debug_info("facebook", "account: %d\n", fba->account); */
+ JsonObject *object = json_node_get_object(json_array_get_element(messages, i));
+ type = json_node_get_string(json_object_get_member(object, "type"));
+ from = g_strdup_printf("%d", json_node_get_int(json_object_get_member(object, "from")));
+ to = g_strdup_printf("%d", json_node_get_int(json_object_get_member(object, "to")));
+
+ /* Use the in-line buddy name if the buddy list hasn't been downloaded yet */
+ buddy = purple_find_buddy(pc->account, from);
+ if (buddy == NULL || buddy->server_alias == NULL || buddy->alias == NULL)
+ {
+ if (json_object_has_member(object, "from_name"))
+ {
+ const gchar *from_name = json_node_get_string(json_object_get_member(
+ object, "from_name"));
+ fb_blist_set_alias(fba, from, from_name);
+ }
+ }
+
+ if (from && to && g_str_equal(type, "msg")) {
+ JsonObject *messageObj = json_node_get_object(json_object_get_member(object, "msg"));
+ parse_message(pc, fba, messageObj, from, to);
+ } else if (from && g_str_equal(type, "typ")) {
+ purple_debug_info("facebook", "handling typing notification\n");
+
+ gint typing = json_node_get_int(json_object_get_member(object, "st"));
+ if (typing == 0) {
+ serv_got_typing(pc, from, 10, PURPLE_NOT_TYPING);
+ } else {
+ serv_got_typing(pc, from, 10, PURPLE_TYPING);
+ }
+ }
+
+ /*
+ * we've received something from a buddy, assume they're online
+ * only if it's not from ourselves
+ */
+ if (from && fba->uid != atoll(from)) {
+ purple_prpl_got_user_status(
+ fba->account, from,
+ purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
+
+ }
+
+ g_free(from);
+ g_free(to);
+
+ fba->message_fetch_sequence++;
+ }
+}
+
+static void got_new_messages(FacebookAccount *fba, gchar *data,
+ gsize data_len, gpointer userdata)
+{
+ JsonParser *parser;
+
+ PurpleConnection *pc = userdata;
+
+ purple_debug_misc("facebook", "got new messages:\n%s\n", data);
+
/* for (;;);{"t":"msg","c":"p_800753867","ms":[{"type":"msg",
"msg":{"text":"yes","time":1211176515861,"clientTime":1211176514750,
"msgID":"367146364"},"from":596176850,"to":800753867,
@@ -124,12 +188,10 @@ static void got_new_messages(FacebookAcc
"msgID":"3382240259"},"from":596176850,"to":800753867,
"from_name":"Jeremy Lawson","to_name":"Eion Robb",
"from_first_name":"Jeremy","to_first_name":"Eion"}]} */
-
/* for (;;);{"t":"refresh", "seq":1} */
- /* look for the start of the JSON, and ignore any proxy headers */
- data = g_strstr_len(data, data_len, "for (;;);");
- if (!data)
+ parser = fb_get_parser(data, data_len);
+ if (!parser)
{
/* Sometimes proxies will return incorrect data, so we just shrug
* it off.
@@ -145,198 +207,49 @@ static void got_new_messages(FacebookAcc
return;
}
- /* refresh means that the channel is invalid */
- if (g_str_equal(data, "for (;;);{\"t\":\"refresh\"}"))
- {
- fb_reconnect(fba);
- return;
- }
+ JsonNode *root;
+ root = json_parser_get_root(parser);
- /* continue means that the server wants us to remake the connection */
- if (g_str_equal(data, "for (;;);{\"t\":\"continue\"}"))
- {
- /* Continue looping, waiting for more messages */
- fb_get_new_messages(fba);
- return;
- }
+ JsonObject *objnode;
+ objnode = json_node_get_object(root);
- tmp = strstr(data, "\"seq\":");
- if (tmp != NULL)
- {
- tmp = tmp + 6;
- tmp = g_strndup(tmp, strchr(tmp, '}') - tmp);
- purple_debug_info("facebook", "new seq number: %s\n", tmp);
- fba->message_fetch_sequence = atoi(tmp);
- g_free(tmp);
- } else {
- fba->message_fetch_sequence++;
- }
-
- if (strncmp(data, "for (;;);{\"t\":\"msg\"", 19) == 0)
- {
- start = g_strstr_len(data, data_len, "\"ms\":[");
- if (!start)
- {
- /* Continue looping, waiting for more messages */
- fb_get_new_messages(fba);
- return;
- }
- start += 6;
- while (*start != ']')
- {
- tmp = strstr(start, "\"type\":\"");
- if (tmp)
- {
- tmp += 8;
- type = g_strndup(tmp, strchr(tmp, '"') - tmp);
- purple_debug_info("facebook", "type: %s\n", type);
- } else {
- type = g_strdup("unknown");
+ 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;
}
- tmp = strstr(start, "\"from\":");
- if (tmp)
- {
- tmp += 7;
- from = g_strndup(tmp, strchr(tmp, ',') - tmp);
- if (from[0] == '"')
- snprintf(from, strlen(from), "%d", atoi(from + 1));
- purple_debug_info("facebook", "from: %s\n", from);
- } else {
- from = NULL;
- }
- tmp = strstr(start, "\"to\":");
- if (tmp)
- {
- tmp += 5;
- end = strchr(tmp, ',');
- if (end == NULL || strchr(tmp, '}') < end)
- end = strchr(tmp, '}');
- to = g_strndup(tmp, end - tmp);
- if (to[0] == '"')
- snprintf(to, strlen(to), "%d", atoi(to + 1));
- purple_debug_info("facebook", "to: %s\n", to);
- } else {
- to = NULL;
- }
-
- if (from && to && g_str_equal(type, "msg"))
- {
- /* IM message */
- tmp = strstr(start, "\"msgID\":");
- tmp += 9;
- tmp = g_strndup(tmp, strchr(tmp, '"') - tmp);
- msgID = atoll(tmp);
- purple_debug_info("facebook", "message id: %s %" G_GINT64_FORMAT " %lld\n", tmp, msgID, atoll(tmp));
- g_free(tmp);
- /* loop through all the previous messages that we have stored */
- /* to make sure that we havn't already received this message */
- for(i = 0; i < FB_LAST_MESSAGE_MAX; i++)
- {
- purple_debug_info("facebook", "last_messages[%d] = %" G_GINT64_FORMAT "\n", i, fba->last_messages[i]);
- if (fba->last_messages[i] == msgID)
- break;
- }
- purple_debug_info("facebook", "i: %d\n", i);
- if (i == FB_LAST_MESSAGE_MAX)
- {
- /* if we're here, it must be a new message */
- fba->last_messages[fba->next_message_pointer++] = msgID;
- if (fba->next_message_pointer >= FB_LAST_MESSAGE_MAX)
- fba->next_message_pointer = 0;
-
- tmp = strstr(start, "\"text\":\"");
- tmp += 8;
- tmp = g_strndup(tmp, strstr(tmp, "\",\"time\":") - tmp);
- message = fb_convert_unicode(tmp);
- g_free(tmp);
- message_text = fb_strdup_withhtml(message);
- tmp = fb_replace_styled_text(message_text);
- g_free(message_text);
- message_text = tmp;
- purple_debug_info("facebook", "text: %s\n", message_text);
-
- tmp = strstr(start, "\"time\":");
- tmp += 7;
- message_time = g_strndup(tmp, strchr(tmp, ',') - tmp - 3);
- purple_debug_info("facebook", "time: %s\n", message_time);
-
- /* Use the in-line buddy name if the buddy list hasn't been downloaded yet */
- buddy = purple_find_buddy(pc->account, from);
- if (buddy == NULL || buddy->server_alias == NULL)
- {
- tmp = strstr(start, "\"from_name\":\"");
- if (tmp)
- {
- tmp += 13;
- tmp = g_strndup(tmp, strstr(tmp, "\",") - tmp);
- serv_got_alias(pc, from, tmp);
- g_free(tmp);
- }
- }
-
- if (fba->uid != atoi(from) || fba->uid == atoi(to))
- serv_got_im(pc, from, message_text, PURPLE_MESSAGE_RECV, atoi(message_time));
- else if (!g_hash_table_remove(fba->sent_messages_hash, message))
- serv_got_im(pc, to, message_text, PURPLE_MESSAGE_SEND, atoi(message_time));
- g_free(message);
-
- /*
- * Acknowledge receipt of the message by simulating
- * focusing the window. Not sure what the window_id
- * is here, but it doesn't seem to matter. Maybe
- * something internal to the Facebook javascript that
- * is used for maintaining UI state across page loads?
- */
- if (!fba->is_idle && fba->uid != atoi(from))
- {
- gchar *postdata;
-
- postdata = g_strdup_printf(
- "focus_chat=%s&window_id=12345&post_form_id=%s",
- from, fba->post_form_id);
- fb_post_or_get(fba, FB_METHOD_POST, NULL,
- "/ajax/chat/settings.php?_ecdc=false",
- postdata, NULL, NULL, FALSE);
- g_free(postdata);
- }
-
- g_free(message_text);
- g_free(message_time);
- }
-
- start = strchr(start, '}')+1;
- } else if (from && g_str_equal(type, "typ"))
- {
- /* typing notification */
- tmp = strstr(start, "\"st\":");
- if (tmp != NULL)
- {
- tmp += 5;
- if (*tmp == '0')
- serv_got_typing(pc, from, 10, PURPLE_TYPED);
- else
- serv_got_typing(pc, from, 10, PURPLE_TYPING);
+ /* grab history items for all open conversations */
+ GList *conversations = purple_get_conversations();
+ while (conversations != NULL) {
+ PurpleConversation *conv =
+ (PurpleConversation *)conversations->data;
+ if (fb_conversation_is_fb(conv)) {
+ purple_debug_info("facebook",
+ "checking for dropped messages with %s\n",
+ conv->name);
+ fb_history_fetch(fba, conv->name, FALSE);
}
+ conversations = conversations->next;
}
- /*
- * we've received something from a buddy, assume they're online
- * only if it's not from ourselves
- */
- if (from && fba->uid != atoi(from))
- purple_prpl_got_user_status(fba->account, from, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
-
- g_free(from);
- g_free(to);
- g_free(type);
-
- start = strchr(start, '}')+1;
- while (*start == ',')
- start++;
+ /* refresh means that the channel is invalid */
+ fb_reconnect(fba);
+ g_object_unref(parser);
+ return;
+ } else if (g_str_equal(command, "continue")) {
+ /* continue means that the server wants us to remake the connection.
+ * continue the loop and wait for messages. noop. */
+ } else if (g_str_equal(command, "msg")) {
+ parse_new_messages(pc, fba,
+ json_node_get_array(json_object_get_member(objnode, "ms")));
}
}
+ g_object_unref(parser);
+
/* Continue looping, waiting for more messages */
fb_get_new_messages(fba);
}
@@ -351,9 +264,6 @@ static gboolean fb_get_new_messages(Face
*/
static gboolean fb_get_new_messages(FacebookAccount *fba)
{
- /* MARKCONFLICT (r283,r286): Mark uses the fba->chanel_number variable here,
- * where this patch/fix eschews that in favor of some hacks.
- */
time_t now;
gchar *fetch_url;
gchar *fetch_server;
@@ -387,7 +297,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_%d=%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", 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;
@@ -401,14 +311,16 @@ 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;
- gchar *error_summary = NULL;
- gchar *tmp;
- gboolean was_an_error = FALSE;
+ gint error_number;
+ const gchar *error_summary;
+ JsonParser *parser;
+ JsonNode *root;
+ JsonObject *object;
+ PurpleConversation *conv;
/* NULL data crashes on Windows */
if (data == NULL)
{
- was_an_error = TRUE;
data = "(null)";
}
@@ -422,48 +334,42 @@ static void fb_send_im_cb(FacebookAccoun
"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"}]} */
-
- tmp = g_strstr_len(data, data_len, "\"error\":");
- if (tmp != NULL)
+
+ parser = fb_get_parser(data, data_len);
+ if (!parser) {
+ // We didn't get data, but this isn't necessarily fatal.
+ purple_debug_warning("facebook", "bad data while parsing sent IM\n");
+ return;
+ }
+ root = json_parser_get_root(parser);
+ object = json_node_get_object(root);
+
+ 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)
{
- tmp += 8;
- tmp = g_strndup(tmp, strchr(tmp, ',') - tmp);
- if (strlen(tmp) > 1 || tmp[0] != '0')
+ purple_debug_error("facebook", "sent im error: %s\n", error_summary);
+ /* there was an error, either report it or retry */
+ if (msg->retry_count++ < FB_MAX_MSG_RETRY)
{
- g_free(tmp);
- tmp = g_strstr_len(data, data_len, "\"errorSummary\":\"");
- tmp += 16;
- error_summary = g_strndup(tmp, strchr(tmp, '"') - tmp);
- purple_debug_error("facebook", "sent im error: %s\n", error_summary);
- if (*error_summary)
- {
- /* there was an error, either report it or retry */
- if (msg->retry_count++ < FB_MAX_MSG_RETRY)
- {
- msg->resend_timer = purple_timeout_add_seconds(1, (GSourceFunc)fb_resend_im_fom, msg);
- fba->resending_messages = g_slist_prepend(fba->resending_messages, msg);
- g_free(error_summary);
- return;
- }
- else
- {
- PurpleConversation *conv;
- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
- fba->account, msg->who);
- purple_conversation_write(conv, NULL, error_summary,
- PURPLE_MESSAGE_ERROR, msg->time);
- was_an_error = TRUE;
- }
- }
+ msg->resend_timer = purple_timeout_add_seconds(1, (GSourceFunc)fb_resend_im_fom, msg);
+ fba->resending_messages = g_slist_prepend(fba->resending_messages, msg);
+ g_object_unref(parser);
+ return;
}
- }
-
- if (was_an_error)
- {
+ else
+ {
+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
+ fba->account, msg->who);
+ purple_conversation_write(conv, NULL, error_summary,
+ PURPLE_MESSAGE_ERROR, msg->time);
+ }
+
g_hash_table_remove(fba->sent_messages_hash, msg->message);
}
- g_free(error_summary);
+ g_object_unref(parser);
fb_msg_destroy(msg);
}
@@ -517,11 +423,7 @@ int fb_send_im(PurpleConnection *pc, con
fb_send_im_fom(msg);
- /* gchar *styled_message = fb_replace_styled_text(msg->message);
- serv_got_im(pc, msg->who, styled_message, PURPLE_MESSAGE_SEND, msg->time);
- g_free(styled_message);
-
- return 0; */
+ /* Return 1 so UI will display message */
return 1;
}
@@ -532,26 +434,17 @@ void got_reconnect_json(FacebookAccount
JsonParser *parser;
JsonNode *root;
- if (data == NULL)
- data = "(null)";
+ parser = fb_get_parser(data, data_len);
- gchar *tmp = g_strstr_len(data, data_len, "for (;;);");
- if (tmp)
- {
- tmp += strlen("for (;;);");
- }
-
- parser = json_parser_new();
- if(!json_parser_load_from_data(parser, tmp, -1, NULL))
- {
+ if (!parser) {
purple_debug_error("facebook", "couldn't parse reconnect data\n");
purple_debug_info("facebook", "page content: %s\n", data);
purple_connection_error_reason(fba->pc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("Chat service currently unavailable"));
- g_object_unref(parser);
return;
}
+
root = json_parser_get_root(parser);
JsonObject *objnode;
objnode = json_node_get_object(root);
@@ -567,7 +460,7 @@ void got_reconnect_json(FacebookAccount
purple_debug_info("facebook", "page content: %s\n", data);
purple_connection_error_reason(fba->pc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Chat service currently unavailable"));
+ _("Error fetching channel; did you log in elsewhere?"));
g_object_unref(parser);
return;
}
@@ -589,7 +482,7 @@ gboolean fb_reconnect(FacebookAccount *f
gboolean fb_reconnect(FacebookAccount *fba)
{
- gchar *url = g_strdup_printf("/ajax/presence/reconnect.php?post_form_id=%s", fba->post_form_id);
+ gchar *url = g_strdup_printf("/ajax/presence/reconnect.php?reason=3&post_form_id=%s", fba->post_form_id);
fb_post_or_get(fba, FB_METHOD_GET, NULL, url, NULL, got_reconnect_json, NULL, FALSE);
g_free(url);
@@ -637,33 +530,3 @@ gboolean fb_get_post_form_id(FacebookAcc
fb_post_or_get(fba, FB_METHOD_GET, NULL, "/presence/popout.php", NULL, got_form_id_page, NULL, FALSE);
return FALSE;
}
-
-/* Converts *text* into <b>text</b> and _text_ into <i>text</i> */
-static gchar *fb_replace_styled_text(const gchar *text)
-{
- if (glib_check_version(2, 14, 0))
- {
- return g_strdup(text);
- } else {
- static GRegex *underline_regex = NULL;
- static GRegex *bold_regex = NULL;
- gchar *midway_string;
- gchar *output_string;
-
- if (underline_regex == NULL)
- {
- underline_regex = g_regex_new("\\b_([^_\\*]+)_\\b", G_REGEX_OPTIMIZE, 0, NULL);
- }
- if (bold_regex == NULL)
- {
- bold_regex = g_regex_new("(\\s|^)\\*([^_\\*]+)\\*(?=$|\\s)", G_REGEX_OPTIMIZE, 0, NULL);
- }
-
- midway_string = g_regex_replace(underline_regex, text, -1, 0, "<u>\\1</u>", 0, NULL);
- output_string = g_regex_replace(bold_regex, midway_string, -1, 0, "\\1<b>\\2</b>", 0, NULL);
- g_free(midway_string);
-
- return output_string;
- }
-}
-
============================================================
--- libpurple/protocols/facebook/fb_notifications.c 1066c720340c2b996497a69a99de13e422bf285b
+++ libpurple/protocols/facebook/fb_notifications.c ca23fe8908d98aa815fb521ef82a9c2937652dae
@@ -30,8 +30,7 @@ static void fb_got_notifications_cb(Face
gchar month_string[4], weekday[4];
guint year, month, day, hour, minute, second;
long timezone;
- gchar *subject, *url, *stripped_subject;
- gchar *search_start = (gchar *)url_text;
+ gchar *subject, *url;
month_string[3] = weekday[3] = '\0';
year = month = day = hour = minute = second = 0;
@@ -42,21 +41,25 @@ static void fb_got_notifications_cb(Face
last_fetch_time = purple_account_get_int(fba->account, "facebook_notifications_last_fetch", 0);
/* purple_debug_info("facebook", "last fetch time: %zu\n", last_fetch_time); */
- while (search_start && (search_start = strstr(search_start, "<item>")))
+ xmlnode *rss_root = xmlnode_from_str(url_text, len);
+ if (rss_root == NULL)
{
- search_start = search_start + 6;
-
- tmp = strstr(search_start, "<pubDate>");
- if (!tmp)
- {
- purple_debug_error("facebook", "couldn't find date in rss feed\n");
- return;
- }
- tmp += 9;
- tmp = g_strndup(tmp, strchr(tmp, '<')-tmp);
-
+ return;
+ }
+ xmlnode *channel = xmlnode_get_child(rss_root, "channel");
+ if (channel == NULL)
+ {
+ xmlnode_free(rss_root);
+ return;
+ }
+ xmlnode *item = xmlnode_get_child(channel, "item");
+ for (; item != NULL; item = xmlnode_get_next_twin(item))
+ {
+ xmlnode *pubDate = xmlnode_get_child(item, "pubDate");
+ if (!pubDate)
+ continue;
+ tmp = xmlnode_get_data_unescaped(pubDate);
/* rss times are in Thu, 19 Jun 2008 15:51:25 -1100 format */
- /* purple_debug_info("facebook", "pre time: %s\n", tmp); */
sscanf(tmp, "%3s, %2u %3s %4u %2u:%2u:%2u %5ld", (char*)&weekday, &day, (char*)&month_string, &year, &hour, &minute, &second, &timezone);
if (g_str_equal(month_string, "Jan")) month = 0;
else if (g_str_equal(month_string, "Feb")) month = 1;
@@ -79,14 +82,11 @@ static void fb_got_notifications_cb(Face
if (time_of_message <= 0)
{
- /* there's no cross-platform, portable way of converting string to time */
- /* that doesn't need a new version of glib, so just cheat */
+ /* there's no cross-platform, portable way of converting string to time
+ which doesn't need a new version of glib, so just cheat */
time_of_message = second + 60*minute + 3600*hour + 86400*day + 2592000*month + 31536000*(year-1970);
}
- /* purple_debug_info("facebook", "time of message: %zu\n", time_of_message); */
- /* purple_debug_info("facebook", "time of message: %s\n", ctime(&time_of_message)); */
-
if (time_of_message > newest_message)
{
/* we'll keep the newest message to save */
@@ -99,40 +99,28 @@ static void fb_got_notifications_cb(Face
/* so if this message is older than the last one, ignore rest */
break;
}
-
- tmp = strstr(search_start, "<link>");
- if (!tmp)
+
+ xmlnode *link = xmlnode_get_child(item, "link");
+ if (link)
{
- url = g_strdup("");
+ url = xmlnode_get_data_unescaped(link);
} else {
- tmp += 6;
- url = g_strndup(tmp, strchr(tmp, '<')-tmp);
- /* convert & to & */
- tmp = purple_unescape_html(url);
- g_free(url);
- url = tmp;
+ url = g_strdup("");
}
-
- tmp = strstr(search_start, "<title>");
- if (!tmp)
+
+ xmlnode *title = xmlnode_get_child(item, "title");
+ if (title)
{
- subject = g_strdup("");
+ subject = xmlnode_get_data_unescaped(title);
} else {
- tmp += 7;
- subject = g_strndup(tmp, strchr(tmp, '<')-tmp);
+ subject = g_strdup("");
}
- stripped_subject = purple_unescape_html(subject);
- g_free(subject);
- subject = stripped_subject;
- purple_debug_info("facebook", "subject: %s\n", subject);
-
purple_notify_email(fba->pc, subject, NULL, fba->account->username, url, NULL, NULL);
g_free(subject);
g_free(url);
-
- search_start = strstr(search_start, "</item>");
}
+ xmlnode_free(rss_root);
if (newest_message > last_fetch_time)
{
============================================================
--- libpurple/protocols/facebook/libfacebook.c 343796cc30236c62ce8522c5fe370f43924f7194
+++ libpurple/protocols/facebook/libfacebook.c 4a5dcafa34bf51425459fa4d44852b720bbc3661
@@ -21,6 +21,7 @@
#include "libfacebook.h"
#include "fb_blist.h"
#include "fb_connection.h"
+#include "fb_conversation.h"
#include "fb_info.h"
#include "fb_managefriends.h"
#include "fb_messages.h"
@@ -119,6 +120,43 @@ gchar *fb_strdup_withhtml(const gchar *s
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 */
/******************************************************************************/
@@ -177,7 +215,11 @@ static GList *fb_statuses(PurpleAccount
types = g_list_append(types, status);
/* Cave into feature requests and allow people to set themselves to be idle */
- status = purple_status_type_new_full(PURPLE_STATUS_AWAY, NULL, _("Idle"), FALSE, TRUE, FALSE);
+ status = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
+ NULL, _("Idle"), FALSE, TRUE, FALSE, "message",
+ _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+ "message_date", _("Message changed"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
types = g_list_append(types, status);
/* Offline people dont have messages */
@@ -219,8 +261,8 @@ static void fb_login_cb(FacebookAccount
_("Incorrect username or password."));
return;
}
- fba->uid = atoi(user_cookie);
- purple_debug_info("facebook", "uid %d\n", fba->uid);
+ fba->uid = atoll(user_cookie);
+ purple_debug_info("facebook", "uid %" G_GINT64_FORMAT "\n", fba->uid);
/* ok, we're logged in now! */
purple_connection_set_state(fba->pc, PURPLE_CONNECTED);
@@ -255,12 +297,14 @@ static void fb_login_cb(FacebookAccount
*/
fba->perpetual_messages_timer = purple_timeout_add_seconds(15,
(GSourceFunc)fb_get_messages_failsafe, fba);
+
+ /* init conversation subsystem */
+ fb_conversation_init(fba);
}
static void fb_login(PurpleAccount *account)
{
FacebookAccount *fba;
- guint16 i;
gchar *postdata, *encoded_username, *encoded_password, *encoded_charset_test;
const gchar* const *languages;
const gchar *locale;
@@ -277,13 +321,12 @@ static void fb_login(PurpleAccount *acco
g_free, g_free);
fba->sent_messages_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, NULL);
+ 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"));
- for (i = 0; i < FB_LAST_MESSAGE_MAX; i++)
- fba->last_messages[i] = 0;
-
account->gc->proto_data = fba;
/* Error localized in libpurple jabber.c */
@@ -331,6 +374,11 @@ static void fb_close(PurpleConnection *p
fba = pc->proto_data;
+ purple_debug_info("facebook", "unloading plugin\n");
+
+ /* destroy conversation subsystem */
+ fb_conversation_destroy(fba);
+
/* Tell Facebook that we've logged out. */
/*
* TODO
@@ -398,9 +446,9 @@ static void fb_close(PurpleConnection *p
g_hash_table_destroy(fba->cookie_table);
g_hash_table_destroy(fba->hostname_ip_cache);
+ g_hash_table_destroy(fba->auth_buddies);
g_free(fba->post_form_id);
g_free(fba->channel_number);
- g_slist_free(fba->auth_buddies);
g_free(fba->last_status_message);
g_free(fba);
}
@@ -419,7 +467,7 @@ static unsigned int fb_send_typing(Purpl
typing_state = (state == PURPLE_TYPING) ? 1 : 0;
/* Don't send typing notifications to self */
- if (atoi(name) != fba->uid)
+ if (atoll(name) != fba->uid)
{
encoded_name = g_strdup(purple_url_encode(name));
postdata = g_strdup_printf("typ=%d&to=%s&post_form_id=%s",
@@ -462,12 +510,12 @@ static void fb_set_status_ok_cb(gpointer
if (*status_text_new != '\0')
{
status_tmp = g_strdup(purple_url_encode(status_text_new));
- postdata = g_strdup_printf("profile_id=%d&status=%s&post_form_id=%s",
+ postdata = g_strdup_printf("profile_id=%" G_GINT64_FORMAT "&status=%s&post_form_id=%s",
fba->uid, status_tmp, fba->post_form_id);
g_free(status_tmp);
}
else
- postdata = g_strdup_printf("profile_id=%d&clear=1&post_form_id=%s",
+ 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",
@@ -519,23 +567,6 @@ static void fb_buddy_free(PurpleBuddy *b
}
}
-static void fb_convo_closed(PurpleConnection *gc, const char *who)
-{
- FacebookAccount *fba = gc->proto_data;
- gchar *postdata;
-
- g_return_if_fail(fba->post_form_id != NULL);
-
- /* notify server that we closed the chat window */
- /* close_chat=589039771&window_id=3168919846&
- * post_form_id=c258fe42460c7e8b61e242a37ef05afc */
- postdata = g_strdup_printf("close_chat=%s&post_form_id=%s", who,
- fba->post_form_id);
- fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/chat/settings.php",
- postdata, NULL, NULL, FALSE);
- g_free(postdata);
-}
-
static GHashTable *fb_get_account_text_table(PurpleAccount *account)
{
GHashTable *table;
@@ -567,7 +598,7 @@ static void fb_set_status_cb(PurplePlugi
FacebookAccount *fba = pc->proto_data;
gchar *uid_str;
- uid_str = g_strdup_printf("%d", fba->uid);
+ uid_str = g_strdup_printf("%" G_GINT64_FORMAT, fba->uid);
purple_request_input(pc, NULL, _("Set your Facebook status"),
purple_account_get_alias(pc->account), "is ",
@@ -658,7 +689,7 @@ static PurplePluginProtocolInfo prpl_inf
static PurplePluginProtocolInfo prpl_info = {
/* options */
- OPT_PROTO_UNIQUE_CHATNAME,
+ OPT_PROTO_MAIL_CHECK,
NULL, /* user_splits */
NULL, /* protocol_options */
@@ -705,7 +736,7 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* group_buddy */
NULL, /* rename_group */
fb_buddy_free, /* buddy_free */
- fb_convo_closed, /* convo_closed */
+ fb_conversation_closed, /* convo_closed */
purple_normalize_nocase,/* normalize */
NULL, /* set_buddy_icon */
NULL, /* remove_group */
@@ -731,29 +762,29 @@ static PurplePluginInfo info = {
static PurplePluginInfo info = {
PURPLE_PLUGIN_MAGIC,
- 2, /* major_version */
- 3, /* minor version */
- PURPLE_PLUGIN_PROTOCOL, /* type */
- NULL, /* ui_requirement */
- 0, /* flags */
- NULL, /* dependencies */
- PURPLE_PRIORITY_DEFAULT, /* priority */
- "prpl-bigbrownchunx-facebookim", /* id */
- "Facebook", /* name */
- FACEBOOK_PLUGIN_VERSION, /* version */
- N_("Facebook Protocol Plugin"), /* summary */
- N_("Facebook Protocol Plugin"), /* description */
- "Eion Robb <eionrobb at gmail.com>", /* author */
- "http://pidgin-facebookchat.googlecode.com/", /* homepage */
- plugin_load, /* load */
- plugin_unload, /* unload */
- NULL, /* destroy */
- NULL, /* ui_info */
- &prpl_info, /* extra_info */
- NULL, /* prefs_info */
- fb_actions, /* actions */
+ 2, /* major_version */
+ 3, /* minor version */
+ PURPLE_PLUGIN_PROTOCOL, /* type */
+ NULL, /* ui_requirement */
+ 0, /* flags */
+ NULL, /* dependencies */
+ PURPLE_PRIORITY_DEFAULT, /* priority */
+ FACEBOOK_PLUGIN_ID, /* id */
+ "Facebook", /* name */
+ FACEBOOK_PLUGIN_VERSION, /* version */
+ N_("Facebook Protocol Plugin"), /* summary */
+ N_("Facebook Protocol Plugin"), /* description */
+ "Eion Robb <eionrobb at gmail.com>", /* author */
+ "http://pidgin-facebookchat.googlecode.com/", /* homepage */
+ plugin_load, /* load */
+ plugin_unload, /* unload */
+ NULL, /* destroy */
+ NULL, /* ui_info */
+ &prpl_info, /* extra_info */
+ NULL, /* prefs_info */
+ fb_actions, /* actions */
- /* padding */
+ /* padding */
NULL,
NULL,
NULL,
============================================================
--- libpurple/protocols/facebook/libfacebook.h 30723f2d8d98def05c0e4811c6f95f4f5242364d
+++ libpurple/protocols/facebook/libfacebook.h e5edab36948064137e8888d3aa9da077f34e2589
@@ -21,7 +21,8 @@
#ifndef LIBFACEBOOK_H
#define LIBFACEBOOK_H
-#define FACEBOOK_PLUGIN_VERSION "1.51"
+#define FACEBOOK_PLUGIN_VERSION "1.53"
+#define FACEBOOK_PLUGIN_ID "prpl-bigbrownchunx-facebookim"
#include <glib.h>
@@ -70,9 +71,10 @@
# include <zlib.h>
#endif
-#define FB_LAST_MESSAGE_MAX 10
#define FB_MAX_MSG_RETRY 2
+#include <json-glib/json-glib.h>
+
typedef struct _FacebookAccount FacebookAccount;
typedef struct _FacebookBuddy FacebookBuddy;
@@ -85,16 +87,14 @@ struct _FacebookAccount {
GSList *dns_queries;
GHashTable *cookie_table;
gchar *post_form_id;
- guint post_form_id_refresh_timer;
- gint32 uid;
+ gint64 uid;
guint buddy_list_timer;
guint friend_request_timer;
gchar *channel_number;
guint message_fetch_sequence;
- gint64 last_messages[FB_LAST_MESSAGE_MAX];
- guint16 next_message_pointer;
+ gint64 last_message_time;
GSList *resending_messages;
- GSList *auth_buddies;
+ GHashTable *auth_buddies;
GHashTable *hostname_ip_cache;
guint notifications_timer;
time_t last_messages_download_time;
@@ -109,14 +109,17 @@ struct _FacebookBuddy {
struct _FacebookBuddy {
FacebookAccount *fba;
PurpleBuddy *buddy;
- gint32 uid;
+ gint64 uid;
gchar *name;
gchar *status;
gchar *status_rel_time;
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 c5f4af2b3b3bf3614532c11fbff8e7d901d8b8ca
+++ libpurple/protocols/facebook/pidgin-facebookchat.rc 1254a3c5068a1788a466179ff715a73c2a695c6b
@@ -1,7 +1,7 @@ 1 VERSIONINFO
1 VERSIONINFO
-FILEVERSION 1,51,0,0
-PRODUCTVERSION 1,51,0,0
+FILEVERSION 1,53,0,0
+PRODUCTVERSION 1,53,0,0
FILEOS 0x40004 // VOS_NT_WINDOWS32
FILETYPE 0x2 // VFT_DLL
{
@@ -12,10 +12,10 @@ BLOCK "StringFileInfo"
VALUE "CompanyName", "Eion Robb\0"
VALUE "FileDescription", "Facebook Chat plugin for Pidgin\0"
VALUE "ProductName", "pidgin-facebookchat\0"
- VALUE "FileVersion", "1.51\0"
- VALUE "ProductVersion", "1.51\0"
+ VALUE "FileVersion", "1.53\0"
+ VALUE "ProductVersion", "1.53\0"
VALUE "InternalName", "pidgin-facebookchat\0"
- VALUE "OriginalFilename", "pidgin-facebookchat.dll\0"
+ VALUE "OriginalFilename", "libfacebook.dll\0"
VALUE "Comments", "http://pidgin-facebookchat.googlecode.com/\0"
}
}
============================================================
--- libpurple/protocols/facebook/rss.xml 63a62d482440ae47b29631cfb4f7bb866184134c
+++ libpurple/protocols/facebook/rss.xml 29d247d04bd14b07d08d4df36a5456c2d89400bf
@@ -13,6 +13,32 @@
<width>48</width><height>48</height>
</image>
<item>
+ <title>Version 1.53</title>
+ <link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c46</link>
+ <description><![CDATA[<a href="http://www.pidgin.im">Pidgin 2.5.8</a> is available and so is 1.53 of pidgin-facebookchat.
+ <br/><br/>
+ We've fixed some important things such as no more missing messages, and buddy names working. You can see all the neat things we've done at:<br/>
+ <a href="http://code.google.com/p/pidgin-facebookchat/wiki/Changelog">http://code.google.com/p/pidgin-facebookchat/wiki/Changelog</a>
+ <br/><br/>
+ Thank you all for using the plugin! If you feel like helping me pay for my fianc?es $300/month medication bills I'd really appreciate a donation. Even one or two dollars can go a long way. You can donate at:<br/>
+ <a href="http://code.google.com/p/pidgin-facebookchat/wiki/Donate">http://code.google.com/p/pidgin-facebookchat/wiki/Donate</a>
+ <br/><br/>
+ Otherwise, go grab the update from the usual place:<br/>
+ <a href="http://code.google.com/p/pidgin-facebookchat/downloads/list">http://code.google.com/p/pidgin-facebookchat/downloads/list</a>]]></description>
+ <pubDate>Mon, 29 June 2009 20:56:20 +1200</pubDate>
+ <guid isPermaLink="true">http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c46</guid>
+ </item>
+ <item>
+ <title>Version 1.52</title>
+ <link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c45</link>
+ <description><![CDATA[Just uploaded version 1.52 which fixes an annoying crash sometimes. Don't forget to download 2.5.7 of Pidgin while you're at it
+ <br/><br/>
+ Download pidgin-facebookchat from:<br/>
+ http://code.google.com/p/pidgin-facebookchat/downloads/list]]></description>
+ <pubDate>Mon, 22 June 2009 19:04:56 +1200</pubDate>
+ <guid isPermaLink="true">http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c45</guid>
+ </item>
+ <item>
<title>Version 1.51</title>
<link>http://code.google.com/p/pidgin-facebookchat/issues/detail?id=24#c44</link>
<description><![CDATA[Version 1.51 of the pidgin-facebookchat plugin is available for download.<br/>
More information about the Commits
mailing list