Mercurial > pidgin
changeset 26807:8d47c0d594dc
merge of '02982091b25d51cf15064b67811f0ff347e3ec48'
and 'acf47162ca3864daf33d64a93e65604bf88ec07e'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 03 May 2009 20:18:23 +0000 |
parents | 1dfa009f6db5 (diff) 9b7b8ee25af4 (current diff) |
children | 8cb3403430bb 55736bd691e2 |
files | |
diffstat | 17 files changed, 373 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sun May 03 17:59:12 2009 +0000 +++ b/ChangeLog Sun May 03 20:18:23 2009 +0000 @@ -31,6 +31,8 @@ * Support most recent version of User Avatar. (XEP-0084 v1.1) * Updated Entity Capabilities support. (Tobias Markmann) * Better support for receiving remote users' nicknames. + * /affiliate and /role will now list the room members with the specified + affiliation/role if possible. (Andrei Mozzhuhin) Yahoo: * P2P file transfers. (Sulabh Mahajan)
--- a/ChangeLog.API Sun May 03 17:59:12 2009 +0000 +++ b/ChangeLog.API Sun May 03 20:18:23 2009 +0000 @@ -13,6 +13,8 @@ * account-actions-changed * account-created * account-destroying + * blist-node-added and blist-node-removed signals (see + blist-signals.dox) * purple_buddy_destroy * purple_buddy_get_protocol_data * purple_buddy_set_protocol_data @@ -54,6 +56,7 @@ xmlnode_remove_with_namespace. Deprecated: + * buddy-added and buddy-removed blist signals * purple_buddy_get_local_alias * purple_notify_user_info_remove_entry * purple_status_type_set_primary_attr
--- a/doc/blist-signals.dox Sun May 03 17:59:12 2009 +0000 +++ b/doc/blist-signals.dox Sun May 03 20:18:23 2009 +0000 @@ -74,13 +74,30 @@ a GList of PurpleBlistNodeAction's allowing a plugin to add menu items @endsignaldef + @signaldef blist-node-added + @signalproto +void (*blist_node_added)(PurpleBlistNode *node) + @endsignalproto + @signaldesc + Emitted when a new blist node is added to the buddy list. + @endsignaldef + + @signaldef blist-node-removed + @signalproto +void (*blist_node_removed)(PurpleBlistNode *node) + @endsignalproto + @signaldesc + Emitted when a blist node is removed from the buddy list. + @endsignaldef + @signaldef buddy-added @signalproto void (*buddy_added)(PurpleBuddy *buddy) @endsignalproto @signaldesc Emitted when a new buddy is added to the buddy list. - @endsignaldef + @deprecated Use blist-node-added instead. + @endsignaldef @signaldef buddy-removed @signalproto @@ -88,7 +105,8 @@ @endsignalproto @signaldesc Emitted when a buddy is removed from the buddy list. - @endsignaldef + @deprecated Use blist-node-removed instead. + @endsignaldef @signaldef buddy-icon-changed @signalproto
--- a/libpurple/blist.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/blist.c Sun May 03 20:18:23 2009 +0000 @@ -1468,6 +1468,9 @@ if (ops && ops->update) ops->update(purplebuddylist, (PurpleBlistNode *)cnode); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + cnode); } void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node) @@ -1615,6 +1618,9 @@ /* Signal that the buddy has been added */ purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy); + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + PURPLE_BLIST_NODE(buddy)); } PurpleContact *purple_contact_new() @@ -1952,6 +1958,9 @@ for (node = gnode->child; node; node = node->next) ops->update(purplebuddylist, node); } + + purple_signal_emit(purple_blist_get_handle(), "blist-node-added", + gnode); } void purple_blist_remove_contact(PurpleContact *contact) @@ -1994,6 +2003,9 @@ if (ops && ops->remove) ops->remove(purplebuddylist, node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(contact)); + /* Delete the node */ purple_contact_destroy(contact); } @@ -2066,6 +2078,9 @@ /* Signal that the buddy has been removed before freeing the memory for it */ purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(buddy)); + purple_buddy_destroy(buddy); /* If the contact is empty then remove it */ @@ -2109,6 +2124,9 @@ if (ops && ops->remove) ops->remove(purplebuddylist, node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(chat)); + /* Delete the node */ purple_chat_destroy(chat); } @@ -2141,6 +2159,9 @@ if (ops && ops->remove) ops->remove(purplebuddylist, node); + purple_signal_emit(purple_blist_get_handle(), "blist-node-removed", + PURPLE_BLIST_NODE(group)); + /* Remove the group from all accounts that are online */ for (l = purple_connections_get_all(); l != NULL; l = l->next) { @@ -2973,6 +2994,16 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_BLIST_BUDDY)); + purple_signal_register(handle, "blist-node-added", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_BLIST_NODE)); + + purple_signal_register(handle, "blist-node-removed", + purple_marshal_VOID__POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_BLIST_NODE)); + purple_signal_register(handle, "buddy-added", purple_marshal_VOID__POINTER, NULL, 1, purple_value_new(PURPLE_TYPE_SUBTYPE,
--- a/libpurple/plugins/signals-test.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/plugins/signals-test.c Sun May 03 20:18:23 2009 +0000 @@ -145,16 +145,39 @@ } static void -buddy_added_cb(PurpleBuddy *buddy, void *data) +blist_node_added_cb(PurpleBlistNode *bnode, void *data) { - purple_debug_misc("signals test", "buddy_added_cb (%s)\n", - purple_buddy_get_name(buddy)); + const char *name; + if (PURPLE_BLIST_NODE_IS_GROUP(bnode)) + name = purple_group_get_name(PURPLE_GROUP(bnode)); + else if (PURPLE_BLIST_NODE_IS_CONTACT(bnode)) + /* Close enough */ + name = purple_contact_get_alias(PURPLE_CONTACT(bnode)); + else if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + name = purple_buddy_get_name(PURPLE_BUDDY(bnode)); + else + name = "(unknown)"; + + purple_debug_misc("signals test", "blist_node_added_cb (%s)\n", + name ? name : "(null)"); } static void -buddy_removed_cb(PurpleBuddy *buddy, void *data) +blist_node_removed_cb(PurpleBlistNode *bnode, void *data) { - purple_debug_misc("signals test", "buddy_removed_cb (%s)\n", purple_buddy_get_name(buddy)); + const char *name; + if (PURPLE_BLIST_NODE_IS_GROUP(bnode)) + name = purple_group_get_name(PURPLE_GROUP(bnode)); + else if (PURPLE_BLIST_NODE_IS_CONTACT(bnode)) + /* Close enough */ + name = purple_contact_get_alias(PURPLE_CONTACT(bnode)); + else if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + name = purple_buddy_get_name(PURPLE_BUDDY(bnode)); + else + name = "(unknown)"; + + purple_debug_misc("signals test", "blist_node_removed_cb (%s)\n", + name ? name : "(null)"); } static void @@ -643,10 +666,10 @@ plugin, PURPLE_CALLBACK(buddy_signed_on_cb), NULL); purple_signal_connect(blist_handle, "buddy-signed-off", plugin, PURPLE_CALLBACK(buddy_signed_off_cb), NULL); - purple_signal_connect(blist_handle, "buddy-added", - plugin, PURPLE_CALLBACK(buddy_added_cb), NULL); - purple_signal_connect(blist_handle, "buddy-removed", - plugin, PURPLE_CALLBACK(buddy_removed_cb), NULL); + purple_signal_connect(blist_handle, "blist-node-added", + plugin, PURPLE_CALLBACK(blist_node_added_cb), NULL); + purple_signal_connect(blist_handle, "blist-node-removed", + plugin, PURPLE_CALLBACK(blist_node_removed_cb), NULL); purple_signal_connect(blist_handle, "buddy-icon-changed", plugin, PURPLE_CALLBACK(buddy_icon_changed_cb), NULL); purple_signal_connect(blist_handle, "blist-node-aliased",
--- a/libpurple/protocols/jabber/caps.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/caps.c Sun May 03 20:18:23 2009 +0000 @@ -349,7 +349,7 @@ } g_hash_table_destroy(capstable); g_hash_table_destroy(nodetable); - capstable = NULL; + capstable = nodetable = NULL; } typedef struct _jabber_caps_cbplususerdata {
--- a/libpurple/protocols/jabber/chat.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Sun May 03 20:18:23 2009 +0000 @@ -916,6 +916,68 @@ return TRUE; } +static void +jabber_chat_affiliation_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberChat *chat; + xmlnode *query, *item; + int chat_id = GPOINTER_TO_INT(data); + GString *buf; + + if(!(chat = jabber_chat_find_by_id(js, chat_id))) + return; + + if (type == JABBER_IQ_ERROR) + return; + + if(!(query = xmlnode_get_child(packet, "query"))) + return; + + buf = g_string_new(_("Affiliations:")); + + item = xmlnode_get_child(query, "item"); + if (item) { + for( ; item; item = xmlnode_get_next_twin(item)) { + const char *jid = xmlnode_get_attrib(item, "jid"); + const char *affiliation = xmlnode_get_attrib(item, "affiliation"); + if (jid && affiliation) + g_string_append_printf(buf, "\n%s %s", jid, affiliation); + } + } else { + buf = g_string_append_c(buf, '\n'); + buf = g_string_append_len(buf, _("No users found"), -1); + } + + purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); + + g_string_free(buf, TRUE); +} + +gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation) +{ + JabberIq *iq; + char *room_jid; + xmlnode *query, *item; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, + "http://jabber.org/protocol/muc#admin"); + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", room_jid); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "affiliation", affiliation); + + jabber_iq_set_callback(iq, jabber_chat_affiliation_list_cb, GINT_TO_POINTER(chat->id)); + jabber_iq_send(iq); + + return TRUE; +} + gboolean jabber_chat_role_user(JabberChat *chat, const char *who, const char *role) { char *to; @@ -945,6 +1007,67 @@ return TRUE; } +static void jabber_chat_role_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberChat *chat; + xmlnode *query, *item; + int chat_id = GPOINTER_TO_INT(data); + GString *buf; + + if(!(chat = jabber_chat_find_by_id(js, chat_id))) + return; + + if (type == JABBER_IQ_ERROR) + return; + + if(!(query = xmlnode_get_child(packet, "query"))) + return; + + buf = g_string_new(_("Roles:")); + + item = xmlnode_get_child(query, "item"); + if (item) { + for( ; item; item = xmlnode_get_next_twin(item)) { + const char *jid = xmlnode_get_attrib(item, "jid"); + const char *role = xmlnode_get_attrib(item, "role"); + if (jid && role) + g_string_append_printf(buf, "\n%s %s", jid, role); + } + } else { + buf = g_string_append_c(buf, '\n'); + buf = g_string_append_len(buf, _("No users found"), -1); + } + + purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); + + g_string_free(buf, TRUE); +} + +gboolean jabber_chat_role_list(JabberChat *chat, const char *role) +{ + JabberIq *iq; + char *room_jid; + xmlnode *query, *item; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, + "http://jabber.org/protocol/muc#admin"); + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", room_jid); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "role", role); + + jabber_iq_set_callback(iq, jabber_chat_role_list_cb, GINT_TO_POINTER(chat->id)); + jabber_iq_send(iq); + + return TRUE; +} + gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why) { JabberIq *iq;
--- a/libpurple/protocols/jabber/chat.h Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Sun May 03 20:18:23 2009 +0000 @@ -81,8 +81,10 @@ const char *why); gboolean jabber_chat_affiliate_user(JabberChat *chat, const char *who, const char *affiliation); +gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation); gboolean jabber_chat_role_user(JabberChat *chat, const char *who, const char *role); +gboolean jabber_chat_role_list(JabberChat *chat, const char *role); gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why);
--- a/libpurple/protocols/jabber/ibb.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/ibb.c Sun May 03 20:18:23 2009 +0000 @@ -503,6 +503,8 @@ { jabber_ibb_sessions = g_hash_table_new(g_str_hash, g_str_equal); + jabber_add_feature(XEP_0047_NAMESPACE, NULL); + jabber_iq_register_handler("close", XEP_0047_NAMESPACE, jabber_ibb_parse); jabber_iq_register_handler("data", XEP_0047_NAMESPACE, jabber_ibb_parse); jabber_iq_register_handler("open", XEP_0047_NAMESPACE, jabber_ibb_parse);
--- a/libpurple/protocols/jabber/jabber.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun May 03 20:18:23 2009 +0000 @@ -70,6 +70,7 @@ static PurplePlugin *my_protocol = NULL; GList *jabber_features = NULL; GList *jabber_identities = NULL; +GSList *jabber_cmds = NULL; static void jabber_unregister_account_cb(JabberStream *js); static void try_srv_connect(JabberStream *js); @@ -2590,21 +2591,32 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if (!chat || !args || !args[0] || !args[1]) + if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; - if (strcmp(args[1], "owner") != 0 && - strcmp(args[1], "admin") != 0 && - strcmp(args[1], "member") != 0 && - strcmp(args[1], "outcast") != 0 && - strcmp(args[1], "none") != 0) { - *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[1]); + if (strcmp(args[0], "owner") != 0 && + strcmp(args[0], "admin") != 0 && + strcmp(args[0], "member") != 0 && + strcmp(args[0], "outcast") != 0 && + strcmp(args[0], "none") != 0) { + *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[0]); return PURPLE_CMD_RET_FAILED; } - if (!jabber_chat_affiliate_user(chat, args[0], args[1])) { - *error = g_strdup_printf(_("Unable to affiliate user %s as \"%s\""), args[0], args[1]); - return PURPLE_CMD_RET_FAILED; + if (args[1]) { + int i; + char **nicks = g_strsplit(args[1], " ", -1); + + for (i = 0; nicks[i]; ++i) + if (!jabber_chat_affiliate_user(chat, nicks[i], args[0])) { + *error = g_strdup_printf(_("Unable to affiliate user %s as \"%s\""), nicks[i], args[0]); + g_strfreev(nicks); + return PURPLE_CMD_RET_FAILED; + } + + g_strfreev(nicks); + } else { + jabber_chat_affiliation_list(chat, args[0]); } return PURPLE_CMD_RET_OK; @@ -2615,23 +2627,32 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if (!chat || !args || !args[0] || !args[1]) + if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; - if (strcmp(args[1], "moderator") != 0 && - strcmp(args[1], "participant") != 0 && - strcmp(args[1], "visitor") != 0 && - strcmp(args[1], "none") != 0) { - *error = g_strdup_printf(_("Unknown role: \"%s\""), args[1]); + if (strcmp(args[0], "moderator") != 0 && + strcmp(args[0], "participant") != 0 && + strcmp(args[0], "visitor") != 0 && + strcmp(args[0], "none") != 0) { + *error = g_strdup_printf(_("Unknown role: \"%s\""), args[0]); return PURPLE_CMD_RET_FAILED; } - if (!jabber_chat_role_user(chat, args[0], args[1])) { - *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"), - args[1], args[0]); - return PURPLE_CMD_RET_FAILED; + if (args[1]) { + int i; + char **nicks = g_strsplit(args[1], " ", -1); + + for (i = 0; nicks[i]; i++) + if (!jabber_chat_role_user(chat, nicks[i], args[0])) { + *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"), + args[0], nicks[i]); + return PURPLE_CMD_RET_FAILED; + } + + g_strfreev(nicks); + } else { + jabber_chat_role_list(chat, args[0]); } - return PURPLE_CMD_RET_OK; } @@ -3139,89 +3160,126 @@ void jabber_register_commands(void) { - purple_cmd_register("config", "", PURPLE_CMD_P_PRPL, + PurpleCmdId id; + id = purple_cmd_register("config", "", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_chat_config, _("config: Configure a chat room."), NULL); - purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_chat_config, _("configure: Configure a chat room."), NULL); - purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_chat_nick, _("nick <new nickname>: Change your nickname."), NULL); - purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_part, _("part [room]: Leave the room."), NULL); - purple_cmd_register("register", "", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("register", "", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_chat_register, _("register: Register with a chat room."), NULL); + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + /* XXX: there needs to be a core /topic cmd, methinks */ - purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, + id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_topic, _("topic [new topic]: View or change the topic."), NULL); - purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_ban, _("ban <user> [reason]: Ban a user from the room."), NULL); - purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_affiliate, - _("affiliate <user> <owner|admin|member|outcast|none>: Set a user's affiliation with the room."), + _("affiliate <owner|admin|member|outcast|none> [nick1] [nick2] ...: Get the users with an affiliation or set users' affiliation with the room."), NULL); - purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_role, - _("role <user> <moderator|participant|visitor|none>: Set a user's role in the room."), + _("role <moderator|participant|visitor|none> [nick1] [nick2] ...: Get the users with an role or set users' role with the room."), NULL); - purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_invite, _("invite <user> [message]: Invite a user to the room."), NULL); - purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_join, _("join: <room> [password]: Join a chat on this server."), NULL); - purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_kick, _("kick <user> [reason]: Kick a user from the room."), NULL); - purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_chat_msg, _("msg <user> <message>: Send a private message to another user."), NULL); - purple_cmd_register("ping", "w", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, "prpl-jabber", jabber_cmd_ping, _("ping <jid>: Ping a user/component/server."), NULL); - purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL, + jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id)); + + id = purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_buzz, _("buzz: Buzz a user to get their attention"), NULL); } +void jabber_unregister_commands(void) +{ + while (jabber_cmds != NULL) { + purple_cmd_unregister(GPOINTER_TO_UINT(jabber_cmds->data)); + jabber_cmds = g_slist_delete_link(jabber_cmds, jabber_cmds); + } +} + /* IPC functions */ /** @@ -3297,6 +3355,12 @@ jabber_add_feature("http://jabber.org/protocol/xhtml-im", 0); jabber_add_feature("urn:xmpp:ping", 0); + /* Buzz/Attention */ + jabber_add_feature(XEP_0224_NAMESPACE, jabber_buzz_isenabled); + + /* Bits Of Binary */ + jabber_add_feature(XEP_0231_NAMESPACE, jabber_custom_smileys_isenabled); + /* Jingle features! */ jabber_add_feature(JINGLE, 0); jabber_add_feature(JINGLE_TRANSPORT_RAWUDP, 0);
--- a/libpurple/protocols/jabber/jabber.h Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Sun May 03 20:18:23 2009 +0000 @@ -366,6 +366,7 @@ PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who); void jabber_register_commands(void); +void jabber_unregister_commands(void); void jabber_init_plugin(PurplePlugin *plugin); void jabber_uninit_plugin(void);
--- a/libpurple/protocols/jabber/libxmpp.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Sun May 03 20:18:23 2009 +0000 @@ -161,6 +161,8 @@ jabber_caps_uninit(); jabber_iq_uninit(); + jabber_unregister_commands(); + /* Stay on target...stay on target... Almost there... */ jabber_uninit_plugin(); @@ -298,10 +300,6 @@ jabber_ibb_init(); jabber_si_init(); - - jabber_add_feature(XEP_0224_NAMESPACE, jabber_buzz_isenabled); - jabber_add_feature(XEP_0231_NAMESPACE, jabber_custom_smileys_isenabled); - jabber_add_feature(XEP_0047_NAMESPACE, NULL); }
--- a/libpurple/protocols/jabber/pep.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/pep.c Sun May 03 20:18:23 2009 +0000 @@ -44,7 +44,10 @@ } void jabber_pep_uninit(void) { - /* any PEP handlers that need to clean things up go here */ + /* any PEP handlers that need to clean things up go here. The standard + * cleanup of removing the handler and feature are handled here and by + * jabber_features_destroy() in jabber.c + */ g_hash_table_destroy(pep_handlers); pep_handlers = NULL; }
--- a/libpurple/protocols/jabber/useravatar.c Sun May 03 17:59:12 2009 +0000 +++ b/libpurple/protocols/jabber/useravatar.c Sun May 03 20:18:23 2009 +0000 @@ -45,6 +45,9 @@ static void remove_avatar_0_12_nodes(JabberStream *js) { +#if 0 + See note below for why this is #if 0d + /* Publish an empty avatar according to the XEP-0084 v0.12 semantics */ xmlnode *publish, *item, *metadata; /* publish the metadata */ @@ -61,16 +64,26 @@ /* publish */ jabber_pep_publish(js, publish); +#endif /* - * This causes ejabberd 2.0.0 to RST our connection unceremoniously, - * so disable it for now (we publish a <stop/> to the metadata node - * instead. + * This causes ejabberd 2.0.0 to kill the connection unceremoniously. + * See https://support.process-one.net/browse/EJAB-623. When adiumx.com + * was upgraded, the issue went away. + * + * I think it makes a lot of sense to not have an avatar at the old + * node instead of having something interpreted as "no avatar". When + * a contact with an older client logs in, in the latter situation, + * there's a race between interpreting the <presence/> vcard-temp:x:update + * avatar (non-empty) and the XEP-0084 v0.12 avatar (empty, so show no + * avatar for the buddy) which leads to unhappy and confused users. + * + * A deluge of frustrating "Read error" bug reports may change my mind + * about this. + * --darkrain42 */ -#if 0 jabber_pep_delete_node(js, NS_AVATAR_0_12_METADATA); jabber_pep_delete_node(js, NS_AVATAR_0_12_DATA); -#endif } void jabber_avatar_set(JabberStream *js, PurpleStoredImage *img)
--- a/pidgin/gtkconv.c Sun May 03 17:59:12 2009 +0000 +++ b/pidgin/gtkconv.c Sun May 03 20:18:23 2009 +0000 @@ -4496,19 +4496,26 @@ } static void -buddy_added_cb(PurpleBuddy *buddy, PurpleConversation *conv) -{ - buddy_cb_common(buddy, conv, TRUE); -} - -static void -buddy_removed_cb(PurpleBuddy *buddy, PurpleConversation *conv) -{ +buddy_added_cb(PurpleBlistNode *node, PurpleConversation *conv) +{ + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + return; + + buddy_cb_common(PURPLE_BUDDY(node), conv, TRUE); +} + +static void +buddy_removed_cb(PurpleBlistNode *node, PurpleConversation *conv) +{ + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + return; + /* If there's another buddy for the same "dude" on the list, do nothing. */ - if (purple_find_buddy(buddy->account, buddy->name) != NULL) + if (purple_find_buddy(purple_buddy_get_account(PURPLE_BUDDY(node)), + purple_buddy_get_name(PURPLE_BUDDY(node))) != NULL) return; - buddy_cb_common(buddy, conv, FALSE); + buddy_cb_common(PURPLE_BUDDY(node), conv, FALSE); } static void send_menu_cb(GtkWidget *widget, PidginConversation *gtkconv) @@ -4747,9 +4754,9 @@ "weight", CHAT_USERS_WEIGHT_COLUMN, NULL); - purple_signal_connect(blist_handle, "buddy-added", + purple_signal_connect(blist_handle, "blist-node-added", gtkchat, PURPLE_CALLBACK(buddy_added_cb), conv); - purple_signal_connect(blist_handle, "buddy-removed", + purple_signal_connect(blist_handle, "blist-node-removed", gtkchat, PURPLE_CALLBACK(buddy_removed_cb), conv); purple_signal_connect(blist_handle, "blist-node-aliased", gtkchat, PURPLE_CALLBACK(blist_node_aliased_cb), conv); @@ -5121,7 +5128,8 @@ GList *list; g_return_if_fail(bnode); - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(bnode)); + if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + return; for (list = pidgin_conv_windows_get_list(); list; list = list->next) { @@ -8017,9 +8025,9 @@ handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); /* Callbacks to update a conversation */ - purple_signal_connect(blist_handle, "buddy-added", handle, + purple_signal_connect(blist_handle, "blist-node-added", handle, G_CALLBACK(buddy_update_cb), NULL); - purple_signal_connect(blist_handle, "buddy-removed", handle, + purple_signal_connect(blist_handle, "blist-node-removed", handle, G_CALLBACK(buddy_update_cb), NULL); purple_signal_connect(blist_handle, "buddy-signed-on", handle, PURPLE_CALLBACK(update_buddy_sign), "on");
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in Sun May 03 17:59:12 2009 +0000 +++ b/pidgin/pixmaps/emotes/default/24/default.theme.in Sun May 03 20:18:23 2009 +0000 @@ -399,13 +399,16 @@ smile-big.png :D :-D =D wink.png ;) ;-) ;^) shock.png :-o -tongue.png :P :-P +tongue.png :P :-P :-p glasses-cool.png B-) angry.png X-( -sad.png :( +sad.png :( :-( =( crying.png :'( neutral.png :-| thinking.png :-/ love.png <3 monkey.png :(|) victory.png \\m/ +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-)
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in Sun May 03 17:59:12 2009 +0000 +++ b/pidgin/pixmaps/emotes/small/16/small.theme.in Sun May 03 20:18:23 2009 +0000 @@ -161,10 +161,10 @@ smile-big.png :D :-D =D wink.png ;) ;-) ;^) shock.png :-o -tongue.png :P :-P +tongue.png :P :-P :-p glasses-cool.png B-) angry.png X-( -sad.png :( +sad.png :( :-( =( crying.png :'( neutral.png :-| thinking.png :-/