Mercurial > pidgin.yaz
changeset 27577:6d26258e9f1d
propagate from branch 'im.pidgin.pidgin' (head ac87c285c7056f86005dc157b9870745de471f74)
to branch 'im.pidgin.cpw.darkrain42.roster' (head 976d874853ac9745edb77d3cf107b92ebc037c10)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Mon, 06 Jul 2009 04:37:41 +0000 |
parents | b9da56683499 (diff) b41b69e8b341 (current diff) |
children | 3bb1085235d0 |
files | libpurple/blist.c libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jabber.h libpurple/protocols/jabber/presence.c |
diffstat | 7 files changed, 154 insertions(+), 167 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/blist.c Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/blist.c Mon Jul 06 04:37:41 2009 +0000 @@ -2352,16 +2352,14 @@ g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); hb.account = account; - hb.name = g_strdup(purple_normalize(account, name)); + hb.name = purple_normalize(account, name); for (group = purplebuddylist->root; group; group = group->next) { hb.group = group; if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb))) { - g_free(hb.name); return buddy; } } - g_free(hb.name); return NULL; }
--- a/libpurple/protocols/jabber/google.c Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Mon Jul 06 04:37:41 2009 +0000 @@ -1006,7 +1006,6 @@ gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item) { PurpleAccount *account = purple_connection_get_account(js->gc); - GSList *list = account->deny; const char *jid = xmlnode_get_attrib(item, "jid"); gboolean on_block_list = FALSE; @@ -1024,18 +1023,20 @@ jid_norm = g_strdup(jabber_normalize(account, jid)); - while (list) { - if (!strcmp(jid_norm, (char*)list->data)) { - on_block_list = TRUE; - break; - } - list = list->next; - } + on_block_list = NULL != g_slist_find_custom(account->deny, jid_norm, + (GCompareFunc)strcmp); if (grt && (*grt == 'H' || *grt == 'h')) { - PurpleBuddy *buddy = purple_find_buddy(account, jid_norm); - if (buddy) - purple_blist_remove_buddy(buddy); + /* Hidden; don't show this buddy. */ + GSList *buddies = purple_find_buddies(account, jid_norm); + if (buddies) + purple_debug_info("jabber", "Removing %s from local buddy list\n", + jid_norm); + + for ( ; buddies; buddies = g_slist_delete_link(buddies, buddies)) { + purple_blist_remove_buddy(buddies->data); + } + g_free(jid_norm); return FALSE; }
--- a/libpurple/protocols/jabber/jabber.c Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Jul 06 04:37:41 2009 +0000 @@ -1620,7 +1620,8 @@ break; case JABBER_STREAM_CONNECTED: - /* now we can alert the core that we're ready to send status */ + /* Send initial presence */ + jabber_presence_send(js, TRUE); purple_connection_set_state(js->gc, PURPLE_CONNECTED); break; }
--- a/libpurple/protocols/jabber/jabber.h Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Mon Jul 06 04:37:41 2009 +0000 @@ -116,7 +116,6 @@ char *expected_rspauth; GHashTable *buddies; - gboolean roster_parsed; /* * This boolean was added to eliminate a heinous bug where we would
--- a/libpurple/protocols/jabber/presence.c Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon Jul 06 04:37:41 2009 +0000 @@ -59,38 +59,44 @@ g_free(chat_full_jid); } -void jabber_presence_fake_to_self(JabberStream *js, const PurpleStatus *gstatus) { - char *my_base_jid; +void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status) +{ + PurpleAccount *account; + const char *username; - if(!js->user) - return; + g_return_if_fail(js->user != NULL); - my_base_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); - if(purple_find_buddy(js->gc->account, my_base_jid)) { - JabberBuddy *jb; + account = purple_connection_get_account(js->gc); + username = purple_account_get_username(account); + if (status == NULL) + status = purple_account_get_active_status(account); + + if (purple_find_buddy(account, username)) { + JabberBuddy *jb = jabber_buddy_find(js, username, TRUE); JabberBuddyResource *jbr; - if((jb = jabber_buddy_find(js, my_base_jid, TRUE))) { - JabberBuddyState state; - char *msg; - int priority; + JabberBuddyState state; + char *msg; + int priority; - purple_status_to_jabber(gstatus, &state, &msg, &priority); + g_return_if_fail(jb != NULL); + + purple_status_to_jabber(status, &state, &msg, &priority); - if (state == JABBER_BUDDY_STATE_UNAVAILABLE || state == JABBER_BUDDY_STATE_UNKNOWN) { - jabber_buddy_remove_resource(jb, js->user->resource); - } else { - jabber_buddy_track_resource(jb, js->user->resource, priority, state, msg); - } - if((jbr = jabber_buddy_find_resource(jb, NULL))) { - purple_prpl_got_user_status(js->gc->account, my_base_jid, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); - } else { - purple_prpl_got_user_status(js->gc->account, my_base_jid, "offline", msg ? "message" : NULL, msg, NULL); - } + if (state == JABBER_BUDDY_STATE_UNAVAILABLE || + state == JABBER_BUDDY_STATE_UNKNOWN) { + jabber_buddy_remove_resource(jb, js->user->resource); + } else { + jabber_buddy_track_resource(jb, js->user->resource, priority, + state, msg); + } - g_free(msg); + if ((jbr = jabber_buddy_find_resource(jb, NULL))) { + purple_prpl_got_user_status(js->gc->account, username, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); + } else { + purple_prpl_got_user_status(js->gc->account, username, "offline", msg ? "message" : NULL, msg, NULL); } + g_free(msg); } - g_free(my_base_jid); } void jabber_set_status(PurpleAccount *account, PurpleStatus *status) @@ -133,7 +139,7 @@ status = purple_presence_get_active_status(p); /* we don't want to send presence before we've gotten our roster */ - if(!js->roster_parsed) { + if (js->state != JABBER_STREAM_CONNECTED) { purple_debug_info("jabber", "attempt to send presence before roster retrieved\n"); return; }
--- a/libpurple/protocols/jabber/presence.h Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/presence.h Mon Jul 06 04:37:41 2009 +0000 @@ -42,7 +42,7 @@ void jabber_presence_parse(JabberStream *js, xmlnode *packet); void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type); -void jabber_presence_fake_to_self(JabberStream *js, const PurpleStatus *status); +void jabber_presence_fake_to_self(JabberStream *js, PurpleStatus *status); void purple_status_to_jabber(const PurpleStatus *status, JabberBuddyState *state, char **msg, int *priority); #endif /* PURPLE_JABBER_PRESENCE_H_ */
--- a/libpurple/protocols/jabber/roster.c Mon Jul 06 04:19:26 2009 +0000 +++ b/libpurple/protocols/jabber/roster.c Mon Jul 06 04:37:41 2009 +0000 @@ -31,6 +31,19 @@ #include <string.h> +/* Take a list of strings and join them with a ", " separator */ +static gchar *roster_groups_join(GSList *list) +{ + GString *out = g_string_new(NULL); + for ( ; list; list = list->next) { + out = g_string_append(out, (const char *)list->data); + if (list->next) + out = g_string_append(out, ", "); + } + + return g_string_free(out, FALSE); +} + void jabber_roster_request(JabberStream *js) { JabberIq *iq; @@ -52,35 +65,40 @@ g_slist_free(buddies); } -static void add_purple_buddies_to_groups(JabberStream *js, const char *jid, - const char *alias, GSList *groups) +static void add_purple_buddy_to_groups(JabberStream *js, const char *jid, + const char *alias, GSList *groups, const char *own_jid) { - GSList *buddies, *g2, *l; - gchar *my_bare_jid; - GList *pool = NULL; + GSList *buddies, *l; + GSList *pool = NULL; buddies = purple_find_buddies(js->gc->account, jid); - g2 = groups; - if(!groups) { if(!buddies) - g2 = g_slist_append(g2, g_strdup(_("Buddies"))); + groups = g_slist_append(groups, g_strdup(_("Buddies"))); else { + /* TODO: What should we do here? Removing the local buddies + * is wrong, but so is letting the group state get out of sync with + * the server. + */ g_slist_free(buddies); return; } } - my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); - while(buddies) { PurpleBuddy *b = buddies->data; PurpleGroup *g = purple_buddy_get_group(b); - buddies = g_slist_remove(buddies, b); + buddies = g_slist_delete_link(buddies, buddies); - if((l = g_slist_find_custom(g2, purple_group_get_name(g), (GCompareFunc)strcmp))) { + /* XMPP groups are case-sensitive, but libpurple groups are + * case-insensitive. We treat a buddy in both "Friends" and "friends" + * as only being in one group, so if we push changes about the buddy + * to the server, the buddy will be dropped from one of the groups. + */ + 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. */ const char *servernick, *balias; /* Previously stored serverside / buddy-supplied alias */ @@ -89,28 +107,46 @@ /* Alias from our roster retrieval */ balias = purple_buddy_get_local_buddy_alias(b); - if(alias && (!balias || strcmp(balias, alias))) + if(alias && !purple_strequal(alias, balias)) purple_serv_got_private_alias(js->gc, jid, alias); g_free(l->data); - g2 = g_slist_delete_link(g2, l); + groups = g_slist_delete_link(groups, l); } else { - pool = g_list_prepend(pool, b); + /* This buddy isn't in the group on the server anymore */ + pool = g_slist_prepend(pool, b); } } - while(g2) { - PurpleGroup *g = purple_find_group(g2->data); + if (pool) { + char *tmp = roster_groups_join(pool); + purple_debug_info("jabber", "jabber_roster_parse(): Removing %s from " + "groups: %s\n", jid, tmp); + g_free(tmp); + } + + if (groups) { + char *tmp = roster_groups_join(groups); + purple_debug_info("jabber", "jabber_roster_parse(): Adding %s to " + "groups: %s\n", jid, tmp); + g_free(tmp); + } + + while(groups) { + PurpleGroup *g = purple_find_group(groups->data); PurpleBuddy *b = NULL; + /* If there are buddies we would otherwise delete, move them to + * the new group (instead of deleting them below) + */ if (pool) { b = pool->data; - pool = g_list_delete_link(pool, pool); + pool = g_slist_delete_link(pool, pool); } else { b = purple_buddy_new(js->gc->account, jid, alias); } if(!g) { - g = purple_group_new(g2->data); + g = purple_group_new(groups->data); purple_blist_add_group(g, NULL); } @@ -120,28 +156,21 @@ /* If we just learned about ourself, then fake our status, * because we won't be receiving a normal presence message * about ourself. */ - if(!strcmp(purple_buddy_get_name(b), my_bare_jid)) { - PurplePresence *gpresence; - PurpleStatus *status; - PurpleAccount *account; + if(!strcmp(purple_buddy_get_name(b), own_jid)) + jabber_presence_fake_to_self(js, NULL); - account = purple_connection_get_account(js->gc); - gpresence = purple_account_get_presence(account); - status = purple_presence_get_active_status(gpresence); - jabber_presence_fake_to_self(js, status); - } - - g_free(g2->data); - g2 = g_slist_delete_link(g2, g2); + g_free(groups->data); + groups = g_slist_delete_link(groups, groups); } + /* Remove this person from all the groups they're no longer in on the + * server */ while (pool) { PurpleBuddy *b = pool->data; purple_blist_remove_buddy(b); - pool = g_list_delete_link(pool, pool); + pool = g_slist_delete_link(pool, pool); } - g_free(my_bare_jid); g_slist_free(buddies); } @@ -149,28 +178,18 @@ JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; - - if(from) { - char *from_norm; - gboolean invalid; - - from_norm = g_strdup(jabber_normalize(js->gc->account, from)); + gchar *own_jid; - if(!from_norm) - return; - - invalid = g_utf8_collate(from_norm, - jabber_normalize(js->gc->account, - purple_account_get_username(js->gc->account))); - - g_free(from_norm); - - if(invalid) - return; + if (!jabber_is_own_account(js, from)) { + purple_debug_warning("jabber", "Received bogon roster push from %s\n", + from); + return; } js->currently_parsing_roster_push = TRUE; + own_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); + for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; @@ -188,18 +207,11 @@ continue; if(subscription) { - gint me = -1; - char *jid_norm; - const char *username; + gboolean me = FALSE; - jid_norm = g_strdup(jabber_normalize(js->gc->account, jid)); - username = purple_account_get_username(js->gc->account); - me = g_utf8_collate(jid_norm, - jabber_normalize(js->gc->account, - username)); - g_free(jid_norm); + me = g_str_equal(own_jid, jabber_normalize(js->gc->account, jid)); - if(me == 0) + if(me) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "none")) jb->subscription = JABBER_SUB_NONE; @@ -211,20 +223,9 @@ jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "remove")) jb->subscription = JABBER_SUB_REMOVE; - /* XXX: if subscription is now "from" or "none" we need to - * fake a signoff, since we won't get any presence from them - * anymore */ - /* YYY: I was going to use this, but I'm not sure it's necessary - * anymore, but it's here in case it is. */ - /* - if ((jb->subscription & JABBER_SUB_FROM) || - (jb->subscription & JABBER_SUB_NONE)) { - purple_prpl_got_user_status(js->gc->account, jid, "offline", NULL); - } - */ } - if(ask && !strcmp(ask, "subscribe")) + if(purple_strequal(ask, "subscribe")) jb->subscription |= JABBER_SUB_PENDING; else jb->subscription &= ~JABBER_SUB_PENDING; @@ -233,44 +234,44 @@ remove_purple_buddies(js, jid); } else { GSList *groups = NULL; + gboolean seen_empty = FALSE; if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) if (!jabber_google_roster_incoming(js, item)) continue; for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { - char *group_name; - - if(!(group_name = xmlnode_get_data(group))) - group_name = g_strdup(""); + char *group_name = xmlnode_get_data(group); - if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp) == NULL) - groups = g_slist_append(groups, group_name); - else - g_free(group_name); + if (!group_name && !seen_empty) { + group_name = g_strdup(""); + seen_empty = TRUE; + } + + groups = g_slist_prepend(groups, group_name); } - add_purple_buddies_to_groups(js, jid, name, groups); + + add_purple_buddy_to_groups(js, jid, name, groups, own_jid); } } + g_free(own_jid); js->currently_parsing_roster_push = FALSE; /* if we're just now parsing the roster for the first time, - * then now would be the time to declare ourselves connected and - * send our initial presence */ - if(!js->roster_parsed) { - js->roster_parsed = TRUE; - jabber_presence_send(js, TRUE); + * then now would be the time to declare ourselves connected. + */ + if (js->state != JABBER_STREAM_CONNECTED) jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); - } } +/* jabber_roster_update frees the GSList* passed in */ static void jabber_roster_update(JabberStream *js, const char *name, - GSList *grps) + GSList *groups) { PurpleBuddy *b; PurpleGroup *g; - GSList *groups = NULL, *l; + GSList *l; JabberIq *iq; xmlnode *query, *item, *group; const char *balias; @@ -281,23 +282,15 @@ if(!(b = purple_find_buddy(js->gc->account, name))) return; - if(grps) { - GString *out = g_string_new(NULL); - groups = grps; + if (groups) { + char *tmp = roster_groups_join(groups); - for (l = groups; l; l = l->next) { - out = g_string_append(out, (const char *)l->data); - if (l->next) - out = g_string_append(out, ", "); - } - - purple_debug_info("jabber", "jabber_roster_update(%s): [Source: grps]: groups: %s\n", - name, out->str); - g_string_free(out, TRUE); - + purple_debug_info("jabber", "jabber_roster_update(%s): [Source: " + "groups]: groups: %s\n", name, tmp); + g_free(tmp); } else { GSList *buddies = purple_find_buddies(js->gc->account, name); - GString *out = g_string_new(NULL); + char *tmp; if(!buddies) return; @@ -307,15 +300,11 @@ groups = g_slist_append(groups, (char *)purple_group_get_name(g)); buddies = g_slist_remove(buddies, b); } - for (l = groups; l; l = l->next) { - out = g_string_append(out, (const char *)l->data); - if (l->next) - out = g_string_append(out, ", "); - } + tmp = roster_groups_join(groups); purple_debug_info("jabber", "jabber_roster_update(%s): [Source: local blist]: groups: %s\n", - name, out->str); - g_string_free(out, TRUE); + name, tmp); + g_free(tmp); } iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); @@ -333,8 +322,7 @@ xmlnode_insert_data(group, l->data, -1); } - if(!grps) - g_slist_free(groups); + g_slist_free(groups); if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) { jabber_google_roster_outgoing(js, query, item); @@ -351,10 +339,11 @@ char *who; JabberBuddy *jb; JabberBuddyResource *jbr; - char *my_bare_jid; + char *own_jid; const char *name; - if(!js->roster_parsed) + /* If we haven't received the roster yet, ignore any adds */ + if (js->state != JABBER_STREAM_CONNECTED) return; name = purple_buddy_get_name(buddy); @@ -368,14 +357,9 @@ jabber_roster_update(js, who, NULL); - my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); - if(!strcmp(who, my_bare_jid)) { - PurplePresence *gpresence; - PurpleStatus *status; - - gpresence = purple_account_get_presence(js->gc->account); - status = purple_presence_get_active_status(gpresence); - jabber_presence_fake_to_self(js, status); + own_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); + if (g_str_equal(who, own_jid)) { + jabber_presence_fake_to_self(js, NULL); } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { @@ -384,7 +368,7 @@ "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } - g_free(my_bare_jid); + g_free(own_jid); g_free(who); } @@ -429,7 +413,6 @@ name, old_group, new_group); jabber_roster_update(gc->proto_data, name, groups); - g_slist_free(groups); } void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name, @@ -465,7 +448,6 @@ purple_buddy_get_name(buddy), purple_group_get_name(group)); jabber_roster_update(gc->proto_data, name, groups); - g_slist_free(groups); } else { JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET, "jabber:iq:roster");