# HG changeset patch # User Nathan Walp # Date 1085988230 0 # Node ID f65be7c97812522dacdf02f61bb6906d113ffd3a # Parent e672ee8a12ec652da5dbeccef88a2d1f5b70bf32 [gaim-migrate @ 9936] committing before I screw this up more committer: Tailor Script diff -r e672ee8a12ec -r f65be7c97812 src/protocols/jabber/chat.c --- a/src/protocols/jabber/chat.c Mon May 31 07:01:13 2004 +0000 +++ b/src/protocols/jabber/chat.c Mon May 31 07:23:50 2004 +0000 @@ -151,6 +151,8 @@ g_free(room_jid); } +void jabber_chat_member_free(JabberChatMember *jcm); + void jabber_chat_join(GaimConnection *gc, GHashTable *data) { JabberChat *chat; @@ -202,6 +204,9 @@ chat->server = g_strdup(server); chat->handle = g_strdup(handle); + chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)jabber_chat_member_free); + g_hash_table_insert(js->chats, room_jid, chat); presence = jabber_presence_create(gc->away_state, gc->away); @@ -231,6 +236,8 @@ return; jabber_chat_part(chat, NULL); + + chat->conv = NULL; } void jabber_chat_destroy(JabberChat *chat) @@ -721,5 +728,93 @@ } } +void jabber_chat_member_free(JabberChatMember *jcm) +{ + g_free(jcm->handle); + g_free(jcm->jid); + g_free(jcm); +} + +void jabber_chat_track_handle(JabberChat *chat, const char *handle, + const char *jid, const char *affiliation, const char *role) +{ + JabberChatMember *jcm = g_new0(JabberChatMember, 1); + + jcm->handle = g_strdup(handle); + jcm->jid = g_strdup(jid); + + g_hash_table_replace(chat->members, jcm->handle, jcm); + + /* XXX: keep track of role and affiliation */ +} + +void jabber_chat_remove_handle(JabberChat *chat, const char *handle) +{ + g_hash_table_remove(chat->members, handle); +} + +gboolean jabber_chat_ban_user(JabberChat *chat, const char *who, const char *why) +{ + JabberIq *iq; + JabberChatMember *jcm = g_hash_table_lookup(chat->members, who); + char *to; + xmlnode *query, *item, *reason; + + if(!jcm || !jcm->jid) + return FALSE; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, + "http://jabber.org/protocol/muc#admin"); + + to = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", to); + g_free(to); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "jid", jcm->jid); + xmlnode_set_attrib(item, "affiliation", "outcast"); + if(why) { + reason = xmlnode_new_child(item, "reason"); + xmlnode_insert_data(reason, why, -1); + } + + jabber_iq_send(iq); + + return TRUE; +} +gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why) +{ + JabberIq *iq; + JabberChatMember *jcm = g_hash_table_lookup(chat->members, who); + char *to; + xmlnode *query, *item, *reason; + + if(!jcm || !jcm->jid) + return FALSE; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_SET, + "http://jabber.org/protocol/muc#admin"); + + to = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", to); + g_free(to); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "jid", jcm->jid); + xmlnode_set_attrib(item, "role", "none"); + if(why) { + reason = xmlnode_new_child(item, "reason"); + xmlnode_insert_data(reason, why, -1); + } + + jabber_iq_send(iq); + + return TRUE; +} + + + diff -r e672ee8a12ec -r f65be7c97812 src/protocols/jabber/chat.h --- a/src/protocols/jabber/chat.h Mon May 31 07:01:13 2004 +0000 +++ b/src/protocols/jabber/chat.h Mon May 31 07:23:50 2004 +0000 @@ -30,6 +30,11 @@ #include "jabber.h" +typedef struct _JabberChatMember { + char *handle; + char *jid; +} JabberChatMember; + typedef struct _JabberChat { JabberStream *js; @@ -42,6 +47,7 @@ gboolean xhtml; GaimRequestType config_dialog_type; void *config_dialog_handle; + GHashTable *members; } JabberChat; GList *jabber_chat_info(GaimConnection *gc); @@ -64,6 +70,13 @@ void jabber_chat_set_topic(GaimConnection *gc, int id, const char *topic); void jabber_chat_change_nick(JabberChat *chat, const char *nick); void jabber_chat_part(JabberChat *chat, const char *msg); +void jabber_chat_track_handle(JabberChat *chat, const char *handle, + const char *jid, const char *affiliation, const char *role); +void jabber_chat_remove_handle(JabberChat *chat, const char *handle); +gboolean jabber_chat_ban_user(JabberChat *chat, const char *who, + const char *why); +gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, + const char *why); GaimRoomlist *jabber_roomlist_get_list(GaimConnection *gc); void jabber_roomlist_cancel(GaimRoomlist *list); diff -r e672ee8a12ec -r f65be7c97812 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Mon May 31 07:01:13 2004 +0000 +++ b/src/protocols/jabber/jabber.c Mon May 31 07:23:50 2004 +0000 @@ -1310,6 +1310,88 @@ return GAIM_CMD_RET_OK; } +static GaimCmdRet jabber_cmd_chat_ban(GaimConversation *conv, + const char *cmd, char **args, char **error) +{ + JabberChat *chat = jabber_chat_find_by_conv(conv); + + if(!args || !args[0]) + return GAIM_CMD_RET_FAILED; + + if(!jabber_chat_ban_user(chat, args[0], args[1])) { + *error = g_strdup_printf(_("Unable to ban user %s"), args[0]); + return GAIM_CMD_RET_FAILED; + } + + return GAIM_CMD_RET_OK; +} + +static GaimCmdRet jabber_cmd_chat_invite(GaimConversation *conv, + const char *cmd, char **args, char **error) +{ + if(!args || !args[0]) + return GAIM_CMD_RET_FAILED; + + jabber_chat_invite(gaim_conversation_get_gc(conv), + gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv)), args[1] ? args[1] : "", + args[0]); + + return GAIM_CMD_RET_OK; +} + +static GaimCmdRet jabber_cmd_chat_join(GaimConversation *conv, + const char *cmd, char **args, char **error) +{ + JabberChat *chat = jabber_chat_find_by_conv(conv); + GHashTable *components; + + if(!args || !args[0]) + return GAIM_CMD_RET_FAILED; + + components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + + g_hash_table_replace(components, "room", args[0]); + g_hash_table_replace(components, "server", chat->server); + g_hash_table_replace(components, "handle", chat->handle); + if(args[1]) + g_hash_table_replace(components, "password", args[1]); + + jabber_chat_join(gaim_conversation_get_gc(conv), components); + + g_hash_table_destroy(components); + return GAIM_CMD_RET_OK; +} + +static GaimCmdRet jabber_cmd_chat_kick(GaimConversation *conv, + const char *cmd, char **args, char **error) +{ + JabberChat *chat = jabber_chat_find_by_conv(conv); + + if(!args || !args[0]) + return GAIM_CMD_RET_FAILED; + + if(!jabber_chat_kick_user(chat, args[0], args[1])) { + *error = g_strdup_printf(_("Unable to kick user %s"), args[0]); + return GAIM_CMD_RET_FAILED; + } + + return GAIM_CMD_RET_OK; +} + +static GaimCmdRet jabber_cmd_chat_msg(GaimConversation *conv, + const char *cmd, char **args, char **error) +{ + JabberChat *chat = jabber_chat_find_by_conv(conv); + char *who; + + who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]); + + jabber_message_send_im(gaim_conversation_get_gc(conv), who, args[1], 0); + + g_free(who); + return GAIM_CMD_RET_OK; +} + static void jabber_register_commands(void) { gaim_cmd_register("config", "", GAIM_CMD_P_PRPL, @@ -1333,6 +1415,26 @@ GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_topic, _("View or change the topic")); + gaim_cmd_register("ban", "ws", GAIM_CMD_P_PRPL, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY | + GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", + jabber_cmd_chat_ban, _("Ban a user from the room")); + gaim_cmd_register("invite", "ws", GAIM_CMD_P_PRPL, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY | + GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", + jabber_cmd_chat_invite, _("Invite a user to the room")); + gaim_cmd_register("join", "ws", GAIM_CMD_P_PRPL, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY | + GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", + jabber_cmd_chat_join, _("Join a chat on this server")); + gaim_cmd_register("kick", "ws", GAIM_CMD_P_PRPL, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY | + GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", + jabber_cmd_chat_kick, _("Kick a user from the room")); + gaim_cmd_register("msg", "ws", GAIM_CMD_P_PRPL, + GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY, + "prpl-jabber", + jabber_cmd_chat_msg, _("Send a private message to another user")); } static GaimPluginPrefFrame * diff -r e672ee8a12ec -r f65be7c97812 src/protocols/jabber/presence.c --- a/src/protocols/jabber/presence.c Mon May 31 07:01:13 2004 +0000 +++ b/src/protocols/jabber/presence.c Mon May 31 07:23:50 2004 +0000 @@ -190,6 +190,8 @@ const char *from = xmlnode_get_attrib(packet, "from"); const char *type = xmlnode_get_attrib(packet, "type"); const char *real_jid = NULL; + const char *affiliation = NULL; + const char *role = NULL; char *status = NULL; int priority = 0; JabberID *jid; @@ -286,6 +288,8 @@ } if((z = xmlnode_get_child(y, "item"))) { real_jid = xmlnode_get_attrib(z, "jid"); + affiliation = xmlnode_get_attrib(z, "affiliation"); + role = xmlnode_get_attrib(z, "role"); } } } @@ -320,8 +324,11 @@ if(type && !strcmp(type, "unavailable")) { gboolean nick_change = FALSE; - /* If we haven't joined the chat yet, we don't care that someone left */ + /* If we haven't joined the chat yet, we don't care that someone + * left, or it was us leaving after we closed the chat */ if(!chat->conv) { + if(!strcmp(jid->resource, chat->handle)) + jabber_chat_destroy(chat); jabber_id_free(jid); g_free(status); g_free(room_jid); @@ -339,28 +346,42 @@ continue; if(!(stat = xmlnode_get_child(x, "status"))) continue; - if(!(code = xmlnode_get_attrib(stat, "code")) || strcmp(code, "303")) - continue; - if(!(item = xmlnode_get_child(x, "item"))) - continue; - if(!(nick = xmlnode_get_attrib(item, "nick"))) + if(!(code = xmlnode_get_attrib(stat, "code"))) continue; - nick_change = TRUE; - if(!strcmp(jid->resource, chat->handle)) { - g_free(chat->handle); - chat->handle = g_strdup(nick); + if(!strcmp(code, "301")) { + /* XXX: we got banned */ + } else if(!strcmp(code, "303")) { + if(!(item = xmlnode_get_child(x, "item"))) + continue; + if(!(nick = xmlnode_get_attrib(item, "nick"))) + continue; + nick_change = TRUE; + if(!strcmp(jid->resource, chat->handle)) { + g_free(chat->handle); + chat->handle = g_strdup(nick); + } + gaim_conv_chat_rename_user(GAIM_CONV_CHAT(chat->conv), jid->resource, nick); + jabber_chat_remove_handle(chat, jid->resource); + break; + } else if(!strcmp(code, "307")) { + /* XXX: we got kicked */ + } else if(!strcmp(code, "321")) { + /* XXX: removed due to an affiliation change */ + } else if(!strcmp(code, "322")) { + /* XXX: removed because room is now members-only */ + } else if(!strcmp(code, "332")) { + /* XXX: removed due to system shutdown */ } - gaim_conv_chat_rename_user(GAIM_CONV_CHAT(chat->conv), jid->resource, nick); - break; } } if(!nick_change) { - if(!g_utf8_collate(jid->resource, gaim_conv_chat_get_nick(GAIM_CONV_CHAT(chat->conv)))) { + if(!g_utf8_collate(jid->resource, chat->handle)) { serv_got_chat_left(js->gc, chat->id); jabber_chat_destroy(chat); } else { gaim_conv_chat_remove_user(GAIM_CONV_CHAT(chat->conv), jid->resource, status); + jabber_chat_remove_handle(chat, jid->resource); } } } else { @@ -376,6 +397,8 @@ jabber_buddy_track_resource(jb, jid->resource, priority, state, status); + jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); + if(!jabber_chat_find_buddy(chat->conv, jid->resource)) gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat->conv), jid->resource, real_jid);