changeset 9152:f65be7c97812

[gaim-migrate @ 9936] committing before I screw this up more committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Mon, 31 May 2004 07:23:50 +0000
parents e672ee8a12ec
children 5ad89e84b3d3
files src/protocols/jabber/chat.c src/protocols/jabber/chat.h src/protocols/jabber/jabber.c src/protocols/jabber/presence.c
diffstat 4 files changed, 246 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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;
+}
+
+
+
--- 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);
--- 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 *
--- 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);