cpw.darkrain42.xmpp.roster: b4776a1c: A clunky attempt to track roster subscri...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Tue Jan 12 22:56:58 EST 2010
-----------------------------------------------------------------
Revision: b4776a1cbbcc566564678032d094cc560701f4f6
Ancestor: d5a2e2287440ac7134c201e66921754bd4187ba9
Author: darkrain42 at pidgin.im
Date: 2010-01-13T03:00:55
Branch: im.pidgin.cpw.darkrain42.xmpp.roster
URL: http://d.pidgin.im/viewmtn/revision/info/b4776a1cbbcc566564678032d094cc560701f4f6
Modified files:
libpurple/protocols/jabber/buddy.c
libpurple/protocols/jabber/buddy.h
libpurple/protocols/jabber/jabber.c
libpurple/protocols/jabber/jutil.c
libpurple/protocols/jabber/jutil.h
libpurple/protocols/jabber/presence.c
libpurple/protocols/jabber/roster.c
libpurple/protocols/jabber/si.c
ChangeLog:
A clunky attempt to track roster subscriptions with roster versioning enabled.
There are, I believe, two remaining issues here:
* All uses of jabber_buddy_find(js, ..., FALSE) need to be audited, as
users on the roster aren't pre-created.
* jabber_roster_add_buddy() needs to check all instances of the PurpleBuddy
for subscription state (and sync to this instance), as this could be
a new PB for a pre-existing contact.
This would be so much cleaner if the core had a concept of subscription state
(or a model of one PurpleBuddy per contact). Refs #10935.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/buddy.c 0c8b7646ec51795cd8296b341efde6504c1e7035
+++ libpurple/protocols/jabber/buddy.c 5b85dfcc3506b32d145244de8f8569139f9018ac
@@ -1814,6 +1814,7 @@ static GList *jabber_buddy_menu(PurpleBu
PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
JabberStream *js = purple_connection_get_protocol_data(gc);
const char *name = purple_buddy_get_name(buddy);
+ JabberSubscription subscription = jabber_subscription_from_buddy(buddy);
JabberBuddy *jb = jabber_buddy_find(js, name, TRUE);
GList *jbrs;
@@ -1836,14 +1837,14 @@ static GList *jabber_buddy_menu(PurpleBu
m = g_list_append(m, act);
}
- if(jb->subscription & JABBER_SUB_FROM && jb != js->user_jb) {
+ if (subscription & JABBER_SUB_FROM && jb != js->user_jb) {
act = purple_menu_action_new(_("Cancel Presence Notification"),
PURPLE_CALLBACK(jabber_buddy_cancel_presence_notification),
NULL, NULL);
m = g_list_append(m, act);
}
- if(!(jb->subscription & JABBER_SUB_TO)) {
+ if (!(subscription & JABBER_SUB_TO)) {
act = purple_menu_action_new(_("(Re-)Request authorization"),
PURPLE_CALLBACK(jabber_buddy_rerequest_auth),
NULL, NULL);
============================================================
--- libpurple/protocols/jabber/buddy.h 509699775bb00c543db2320f5098bc63aa66d78d
+++ libpurple/protocols/jabber/buddy.h 1d06efcbf7c1b1a795a8b5580b936289193bdf14
@@ -48,14 +48,6 @@ struct _JabberBuddy {
JABBER_INVISIBLE_SERVER = 1 << 1,
JABBER_INVIS_BUDDY = 1 << 2
} invisible;
- enum {
- JABBER_SUB_NONE = 0,
- JABBER_SUB_PENDING = 1 << 1,
- JABBER_SUB_TO = 1 << 2,
- JABBER_SUB_FROM = 1 << 3,
- JABBER_SUB_BOTH = (JABBER_SUB_TO | JABBER_SUB_FROM),
- JABBER_SUB_REMOVE = 1 << 4
- } subscription;
};
typedef struct _JabberAdHocCommands {
============================================================
--- libpurple/protocols/jabber/jabber.c 3f8dd3c03faffaf7c79505103730b4ed8b2a4621
+++ libpurple/protocols/jabber/jabber.c ead612d51ed5353a009fbf91569370601d74eeba
@@ -121,6 +121,23 @@ static void jabber_session_init(JabberSt
jabber_iq_send(iq);
}
+static void
+update_self_contact_subscriptions(JabberStream *js, const char *jid)
+{
+ PurpleAccount *account = purple_connection_get_account(js->gc);
+ GSList *buddies = purple_find_buddies(account, jid);
+
+ while (buddies) {
+ PurpleBlistNode *bnode = buddies->data;
+ if (!purple_strequal(purple_blist_node_get_string(bnode, "subscription"), "both"))
+ purple_blist_node_set_string(bnode, "subscription", "both");
+ if (purple_blist_node_get_bool(bnode, "subscription_pending"))
+ purple_blist_node_set_bool(bnode, "subscription_pending", FALSE);
+
+ buddies = g_slist_delete_link(buddies, buddies);
+ }
+}
+
static void jabber_bind_result_cb(JabberStream *js, const char *from,
JabberIqType type, const char *id,
xmlnode *packet, gpointer data)
@@ -144,7 +161,7 @@ static void jabber_bind_result_cb(Jabber
}
js->user_jb = jabber_buddy_find(js, full_jid, TRUE);
- js->user_jb->subscription |= JABBER_SUB_BOTH;
+ update_self_contact_subscriptions(js, full_jid);
purple_connection_set_display_name(js->gc, full_jid);
@@ -842,7 +859,7 @@ jabber_stream_new(PurpleAccount *account
g_return_val_if_reached(NULL);
}
- js->user_jb->subscription |= JABBER_SUB_BOTH;
+ update_self_contact_subscriptions(js, user);
js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
@@ -1907,9 +1924,12 @@ const char* jabber_list_emblem(PurpleBud
jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
if(!PURPLE_BUDDY_IS_ONLINE(b)) {
- if(jb && (jb->subscription & JABBER_SUB_PENDING ||
- !(jb->subscription & JABBER_SUB_TO)))
- return "not-authorized";
+ if (jb && jb != js->user_jb) {
+ JabberSubscription subscription = jabber_subscription_from_buddy(b);
+ if ((subscription & JABBER_SUB_PENDING) ||
+ !(subscription & JABBER_SUB_TO))
+ return "not-authorized";
+ }
}
if (jb) {
@@ -1939,18 +1959,27 @@ char *jabber_status_text(PurpleBuddy *b)
char *jabber_status_text(PurpleBuddy *b)
{
char *ret = NULL;
- JabberBuddy *jb = NULL;
PurpleAccount *account = purple_buddy_get_account(b);
PurpleConnection *gc = purple_account_get_connection(account);
+ JabberStream *js = NULL;
+ JabberBuddy *jb = NULL;
- if (gc && gc->proto_data)
- jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
+ if (gc)
+ js = purple_connection_get_protocol_data(gc);
- if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) {
- ret = g_strdup(_("Not Authorized"));
- } else if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && jb->error_msg) {
- ret = g_strdup(jb->error_msg);
- } else {
+ if (js)
+ jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
+
+ if (jb && jb != js->user_jb && !PURPLE_BUDDY_IS_ONLINE(b)) {
+ JabberSubscription subscription = jabber_subscription_from_buddy(b);
+ if ((subscription & JABBER_SUB_PENDING) || !(subscription & JABBER_SUB_TO)) {
+ ret = g_strdup(_("Not Authorized"));
+ } else if (jb->error_msg) {
+ ret = g_strdup(jb->error_msg);
+ }
+ }
+
+ if (!ret) {
PurplePresence *presence = purple_buddy_get_presence(b);
PurpleStatus *status = purple_presence_get_active_status(presence);
const char *message;
@@ -2019,6 +2048,7 @@ void jabber_tooltip_text(PurpleBuddy *b,
JabberBuddy *jb;
PurpleAccount *account;
PurpleConnection *gc;
+ JabberStream *js = NULL;
g_return_if_fail(b != NULL);
@@ -2027,9 +2057,10 @@ void jabber_tooltip_text(PurpleBuddy *b,
gc = purple_account_get_connection(account);
g_return_if_fail(gc != NULL);
- g_return_if_fail(gc->proto_data != NULL);
+ g_return_if_fail(purple_connection_get_protocol_data(gc) != NULL);
- jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE);
+ js = purple_connection_get_protocol_data(gc);
+ jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE);
if(jb) {
JabberBuddyResource *jbr = NULL;
@@ -2058,6 +2089,7 @@ void jabber_tooltip_text(PurpleBuddy *b,
if (full) {
PurpleStatus *status;
+ JabberSubscription subscription = jabber_subscription_from_buddy(b);
status = purple_presence_get_active_status(presence);
mood = purple_status_get_attr_string(status, "mood");
@@ -2084,17 +2116,17 @@ void jabber_tooltip_text(PurpleBuddy *b,
}
}
- if(jb->subscription & JABBER_SUB_FROM) {
- if(jb->subscription & JABBER_SUB_TO)
+ if (subscription & JABBER_SUB_FROM) {
+ if (subscription & JABBER_SUB_TO)
sub = _("Both");
- else if(jb->subscription & JABBER_SUB_PENDING)
+ else if (subscription & JABBER_SUB_PENDING)
sub = _("From (To pending)");
else
sub = _("From");
} else {
- if(jb->subscription & JABBER_SUB_TO)
+ if (subscription & JABBER_SUB_TO)
sub = _("To");
- else if(jb->subscription & JABBER_SUB_PENDING)
+ else if (subscription & JABBER_SUB_PENDING)
sub = _("None (To pending)");
else
sub = _("None");
@@ -3000,8 +3032,8 @@ jabber_initiate_media(PurpleAccount *acc
PurpleMediaSessionType type)
{
#ifdef USE_VV
- JabberStream *js = (JabberStream *)
- purple_account_get_connection(account)->proto_data;
+ JabberStream *js = purple_connection_get_protocol_data(
+ purple_account_get_connection(account));
JabberBuddy *jb;
JabberBuddyResource *jbr = NULL;
char *resource;
@@ -3036,11 +3068,16 @@ jabber_initiate_media(PurpleAccount *acc
/* no resources online, we're trying to initiate with someone
* whose presence we're not subscribed to, or
* someone who is offline. Let's inform the user */
+ PurpleBuddy *buddy = purple_find_buddy(account, who);
+ JabberSubscription subscription = JABBER_SUB_NONE;
char *msg;
+ if (buddy)
+ subscription = jabber_subscription_from_buddy(buddy);
+
if(!jb) {
msg = g_strdup_printf(_("Unable to initiate media with %s: invalid JID"), who);
- } else if(jb->subscription & JABBER_SUB_TO) {
+ } else if (subscription & JABBER_SUB_TO) {
msg = g_strdup_printf(_("Unable to initiate media with %s: user is not online"), who);
} else {
msg = g_strdup_printf(_("Unable to initiate media with %s: not subscribed to user presence"), who);
============================================================
--- libpurple/protocols/jabber/jutil.c 99af4534d0e0e24e6e0acd64e06d681311e59078
+++ libpurple/protocols/jabber/jutil.c a75d5ed68ff704d8c27cc1314405ee30356d9661
@@ -670,6 +670,59 @@ jabber_find_unnormalized_conv(const char
return NULL;
}
+const char *
+jabber_subscription_to_string(JabberSubscription sub)
+{
+ sub = sub & ~JABBER_SUB_PENDING;
+
+ if (sub == JABBER_SUB_BOTH)
+ return "both";
+ else if (sub == JABBER_SUB_FROM)
+ return "from";
+ else if (sub == JABBER_SUB_TO)
+ return "to";
+ else if (JABBER_SUB_NONE)
+ return "none";
+
+ purple_debug_warning("jabber", "Unknown JabberSubscription value %d\n", sub);
+ return "none";
+}
+
+JabberSubscription
+jabber_subscription_from_string(const char *str)
+{
+ JabberSubscription subscription = JABBER_SUB_NONE;
+
+ if (str) {
+ if (g_str_equal(str, "to"))
+ subscription = JABBER_SUB_TO;
+ else if (g_str_equal(str, "from"))
+ subscription = JABBER_SUB_FROM;
+ else if (g_str_equal(str, "both"))
+ subscription = JABBER_SUB_BOTH;
+ }
+
+ return subscription;
+}
+
+JabberSubscription
+jabber_subscription_from_buddy(PurpleBuddy *buddy)
+{
+ const char *sub;
+ gboolean pending;
+ JabberSubscription subscription = JABBER_SUB_NONE;
+
+ sub = purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "subscription");
+ pending = purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "subscription_pending");
+
+ if (sub)
+ subscription = jabber_subscription_from_string(sub);
+ if (pending)
+ subscription |= JABBER_SUB_PENDING;
+
+ return subscription;
+}
+
/* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */
char *
jabber_calculate_data_sha1sum(gconstpointer data, size_t len)
============================================================
--- libpurple/protocols/jabber/jutil.h 868ace1b7d30296ddba8ba5b105198a5c97ddc12
+++ libpurple/protocols/jabber/jutil.h 883402184c515f3ce1a27815c6a24b4d578a027e
@@ -30,6 +30,14 @@ typedef struct _JabberID {
char *resource;
} JabberID;
+typedef enum {
+ JABBER_SUB_NONE = 0,
+ JABBER_SUB_PENDING = 1 << 1,
+ JABBER_SUB_TO = 1 << 2,
+ JABBER_SUB_FROM = 1 << 3,
+ JABBER_SUB_BOTH = (JABBER_SUB_TO | JABBER_SUB_FROM)
+} JabberSubscription;
+
#include "jabber.h"
JabberID* jabber_id_new(const char *str);
@@ -65,5 +73,9 @@ PurpleConversation *jabber_find_unnormal
PurpleConversation *jabber_find_unnormalized_conv(const char *name, PurpleAccount *account);
+const gchar *jabber_subscription_to_string(JabberSubscription sub);
+JabberSubscription jabber_subscription_from_string(const char *str);
+JabberSubscription jabber_subscription_from_buddy(PurpleBuddy *buddy);
+
char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len);
#endif /* PURPLE_JABBER_JUTIL_H_ */
============================================================
--- libpurple/protocols/jabber/presence.c 2f5c934a28b8a0bcb26cdf7a249b7fc7832458ad
+++ libpurple/protocols/jabber/presence.c 2a3f0a1fa7054e58331d35a8acb9a4604f3c1717
@@ -561,7 +561,6 @@ void jabber_presence_parse(JabberStream
gboolean onlist = FALSE;
PurpleAccount *account;
PurpleBuddy *buddy;
- JabberBuddy *jb = NULL;
xmlnode *nick;
account = purple_connection_get_account(js->gc);
@@ -571,8 +570,8 @@ void jabber_presence_parse(JabberStream
nickname = xmlnode_get_data(nick);
if (buddy) {
- jb = jabber_buddy_find(js, from, TRUE);
- if ((jb->subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING)))
+ JabberSubscription subscription = jabber_subscription_from_buddy(buddy);
+ if (subscription & (JABBER_SUB_TO | JABBER_SUB_PENDING))
onlist = TRUE;
}
============================================================
--- libpurple/protocols/jabber/roster.c 71d568bb2d7e1cd166f30864723b0089da7d3dce
+++ libpurple/protocols/jabber/roster.c daed8902e128dab4bab51b0cce8f4e921cc94161
@@ -77,13 +77,16 @@ void jabber_roster_request(JabberStream
void jabber_roster_request(JabberStream *js)
{
PurpleAccount *account;
+ const char *ver;
JabberIq *iq;
xmlnode *query;
account = purple_connection_get_account(js->gc);
+ ver = purple_account_get_string(account, "roster_ver", "");
iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
query = xmlnode_get_child(iq->node, "query");
+ xmlnode_set_attrib(query, "ver", ver);
if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
@@ -107,12 +110,12 @@ static void add_purple_buddy_to_groups(J
}
static void add_purple_buddy_to_groups(JabberStream *js, const char *jid,
- const char *alias, GSList *groups)
+ const char *alias, JabberSubscription subscription, GSList *groups)
{
GSList *buddies, *l;
PurpleAccount *account = purple_connection_get_account(js->gc);
- buddies = purple_find_buddies(js->gc->account, jid);
+ buddies = purple_find_buddies(account, jid);
if(!groups) {
if(!buddies)
@@ -141,16 +144,22 @@ static void add_purple_buddy_to_groups(J
*/
if((l = g_slist_find_custom(groups, purple_group_get_name(g), (GCompareFunc)purple_utf8_strcasecmp))) {
/* The buddy is already on the local list. Update info. */
+ PurpleBlistNode *bnode = PURPLE_BLIST_NODE(b);
const char *servernick, *balias;
/* Previously stored serverside / buddy-supplied alias */
- if((servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick")))
+ if((servernick = purple_blist_node_get_string(bnode, "servernick")))
serv_got_alias(js->gc, jid, servernick);
/* Alias from our roster retrieval */
balias = purple_buddy_get_local_buddy_alias(b);
if(alias && !purple_strequal(alias, balias))
purple_serv_got_private_alias(js->gc, jid, alias);
+
+ /* Subscription status */
+ purple_blist_node_set_string(bnode, "subscription", jabber_subscription_to_string(subscription));
+ purple_blist_node_set_bool(bnode, "subscription_pending", (subscription & JABBER_SUB_PENDING));
+
g_free(l->data);
groups = g_slist_delete_link(groups, l);
} else {
@@ -209,6 +218,8 @@ void jabber_roster_parse(JabberStream *j
{
const char *jid, *name, *subscription, *ask;
JabberBuddy *jb;
+ gboolean remove = FALSE;
+ JabberSubscription sub = JABBER_SUB_NONE;
subscription = xmlnode_get_attrib(item, "subscription");
jid = xmlnode_get_attrib(item, "jid");
@@ -221,27 +232,19 @@ void jabber_roster_parse(JabberStream *j
if(!(jb = jabber_buddy_find(js, jid, TRUE)))
continue;
- if(subscription) {
+ if (subscription) {
if (g_str_equal(subscription, "remove"))
- jb->subscription = JABBER_SUB_REMOVE;
- else if (jb == js->user_jb)
- jb->subscription = JABBER_SUB_BOTH;
- else if (g_str_equal(subscription, "none"))
- jb->subscription = JABBER_SUB_NONE;
- else if (g_str_equal(subscription, "to"))
- jb->subscription = JABBER_SUB_TO;
- else if (g_str_equal(subscription, "from"))
- jb->subscription = JABBER_SUB_FROM;
- else if (g_str_equal(subscription, "both"))
- jb->subscription = JABBER_SUB_BOTH;
+ remove = TRUE;
+ else
+ sub = jabber_subscription_from_string(subscription);
}
if(purple_strequal(ask, "subscribe"))
- jb->subscription |= JABBER_SUB_PENDING;
+ sub |= JABBER_SUB_PENDING;
else
- jb->subscription &= ~JABBER_SUB_PENDING;
+ sub &= ~JABBER_SUB_PENDING;
- if(jb->subscription & JABBER_SUB_REMOVE) {
+ if (remove) {
remove_purple_buddies(js, jid);
} else {
GSList *groups = NULL;
@@ -262,7 +265,7 @@ void jabber_roster_parse(JabberStream *j
groups = g_slist_prepend(groups, group_name);
}
- add_purple_buddy_to_groups(js, jid, name, groups);
+ add_purple_buddy_to_groups(js, jid, name, sub, groups);
if (jb == js->user_jb)
jabber_presence_fake_to_self(js, NULL);
}
@@ -354,6 +357,7 @@ void jabber_roster_add_buddy(PurpleConne
JabberID *jid;
JabberBuddy *jb;
JabberBuddyResource *jbr;
+ JabberSubscription subscription;
const char *name;
/* If we haven't received the roster yet, ignore any adds */
@@ -397,9 +401,11 @@ void jabber_roster_add_buddy(PurpleConne
jabber_roster_update(js, who, NULL);
+ subscription = jabber_subscription_from_buddy(buddy);
+
if (jb == js->user_jb) {
jabber_presence_fake_to_self(js, NULL);
- } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
+ } else if (!jb || !(subscription & JABBER_SUB_TO)) {
jabber_presence_subscription_set(js, who, "subscribe");
} else if((jbr =jabber_buddy_find_resource(jb, NULL))) {
purple_prpl_got_user_status(gc->account, who,
============================================================
--- libpurple/protocols/jabber/si.c 04dcf15bf4537fe1f17570752ee39f81e49c6bb1
+++ libpurple/protocols/jabber/si.c a6a0daf121bd9b4f0fd307a1416b87807b5ccfe2
@@ -1504,11 +1504,17 @@ static void jabber_si_xfer_init(PurpleXf
/* no resources online, we're trying to send to someone
* whose presence we're not subscribed to, or
* someone who is offline. Let's inform the user */
+ PurpleBuddy *buddy;
+ JabberSubscription subscription = JABBER_SUB_NONE;
char *msg;
+ buddy = purple_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer));
+ if (buddy)
+ subscription = jabber_subscription_from_buddy(buddy);
+
if(!jb) {
msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who);
- } else if(jb->subscription & JABBER_SUB_TO) {
+ } else if(subscription & JABBER_SUB_TO) {
msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who);
} else {
msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who);
More information about the Commits
mailing list