From 78a1556f1205d0d2ad2f9a5e7a29c4515defa128 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 6 Oct 2014 22:59:25 +0100 Subject: [PATCH] Added jid autocomplete for affiliation commands --- TODO_ROLES | 10 +++----- src/command/command.c | 21 +++++++++++++---- src/muc.c | 55 +++++++++++++++++++++++++++++++++++++++++++ src/muc.h | 4 ++++ src/server_events.c | 15 ++++++++++++ src/server_events.h | 3 +++ src/ui/core.c | 52 ++++++++++++++++++++++++++++++++++++++++ src/ui/ui.h | 3 +++ src/xmpp/presence.c | 22 +++++++++++++---- src/xmpp/stanza.c | 4 ++-- src/xmpp/stanza.h | 4 ++-- 11 files changed, 174 insertions(+), 19 deletions(-) diff --git a/TODO_ROLES b/TODO_ROLES index a8a1b85c..b83d149d 100644 --- a/TODO_ROLES +++ b/TODO_ROLES @@ -1,8 +1,4 @@ -Include self in role/affiliation lists -Handle status codes -Changing subject -Moderator use cases -Admin use cases -Owner use cases - +Include self in role/affiliation lists (roster) +Show role/affiliation on join +Show role/affiliation on update Check all commands from private conversations diff --git a/src/command/command.c b/src/command/command.c index daa86d76..9c4fd746 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1423,6 +1423,7 @@ cmd_reset_autocomplete() if (ui_current_win_type() == WIN_MUC) { char *recipient = ui_current_recipient(); muc_autocomplete_reset(recipient); + muc_jid_autocomplete_reset(recipient); } autocomplete_reset(who_room_ac); @@ -2281,14 +2282,13 @@ _room_autocomplete(char *input, int *size) char *recipient = ui_current_recipient(); Autocomplete nick_ac = muc_roster_ac(recipient); + Autocomplete jid_ac = muc_roster_jid_ac(recipient); input[*size] = '\0'; gchar **args = parse_args(input, 4, 4, &parse_result); - if ((strncmp(input, "/room", 5) == 0) && (parse_result == TRUE)) { - GString *beginning = g_string_new("/room "); - g_string_append(beginning, args[0]); - g_string_append(beginning, " "); + if ((strncmp(input, "/room role", 10) == 0) && (parse_result == TRUE)) { + GString *beginning = g_string_new("/room role "); g_string_append(beginning, args[1]); g_string_append(beginning, " "); g_string_append(beginning, args[2]); @@ -2300,6 +2300,19 @@ _room_autocomplete(char *input, int *size) } } + if ((strncmp(input, "/room affiliation", 17) == 0) && (parse_result == TRUE)) { + GString *beginning = g_string_new("/room affiliation "); + g_string_append(beginning, args[1]); + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + + result = autocomplete_param_with_ac(input, size, beginning->str, jid_ac, TRUE); + g_string_free(beginning, TRUE); + if (result != NULL) { + return result; + } + } + result = autocomplete_param_with_ac(input, size, "/room role set", room_role_ac, TRUE); if (result != NULL) { return result; diff --git a/src/muc.c b/src/muc.c index aa8148b1..2ee59ae5 100644 --- a/src/muc.c +++ b/src/muc.c @@ -58,6 +58,7 @@ typedef struct _muc_room_t { gboolean pending_nick_change; GHashTable *roster; Autocomplete nick_ac; + Autocomplete jid_ac; GHashTable *nick_changes; gboolean roster_received; } ChatRoom; @@ -170,6 +171,7 @@ muc_join(const char * const room, const char * const nick, new_room->pending_config = FALSE; new_room->roster = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_occupant_free); new_room->nick_ac = autocomplete_new(); + new_room->jid_ac = autocomplete_new(); new_room->nick_changes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); new_room->roster_received = FALSE; new_room->pending_nick_change = FALSE; @@ -410,6 +412,14 @@ muc_roster_add(const char * const room, const char * const nick, const char * co muc_affiliation_t affiliation_t = _affiliation_from_string(affiliation); Occupant *occupant = _muc_occupant_new(nick, jid, role_t, affiliation_t, presence, status); g_hash_table_replace(chat_room->roster, strdup(nick), occupant); + + if (jid) { + Jid *jidp = jid_create(jid); + if (jidp->barejid) { + autocomplete_add(chat_room->jid_ac, jidp->barejid); + } + jid_destroy(jidp); + } } return updated; @@ -479,6 +489,17 @@ muc_roster_ac(const char * const room) } } +Autocomplete +muc_roster_jid_ac(const char * const room) +{ + ChatRoom *chat_room = g_hash_table_lookup(rooms, room); + if (chat_room) { + return chat_room->jid_ac; + } else { + return NULL; + } +} + /* * Set to TRUE when the rooms roster has been fully received */ @@ -645,6 +666,39 @@ muc_autocomplete(char *input, int *size) } } +void +muc_jid_autocomplete_reset(const char * const room) +{ + ChatRoom *chat_room = g_hash_table_lookup(rooms, room); + if (chat_room) { + if (chat_room->jid_ac) { + autocomplete_reset(chat_room->jid_ac); + } + } +} + +void +muc_jid_autocomplete_add_all(const char * const room, GSList *jids) +{ + ChatRoom *chat_room = g_hash_table_lookup(rooms, room); + if (chat_room) { + if (chat_room->jid_ac) { + GSList *curr_jid = jids; + while (curr_jid) { + char *jid = curr_jid->data; + Jid *jidp = jid_create(jid); + if (jidp) { + if (jidp->barejid) { + autocomplete_add(chat_room->jid_ac, jidp->barejid); + } + } + jid_destroy(jidp); + curr_jid = g_slist_next(curr_jid); + } + } + } +} + void muc_autocomplete_reset(const char * const room) { @@ -714,6 +768,7 @@ _free_room(ChatRoom *room) g_hash_table_destroy(room->roster); } autocomplete_free(room->nick_ac); + autocomplete_free(room->jid_ac); if (room->nick_changes) { g_hash_table_destroy(room->nick_changes); } diff --git a/src/muc.h b/src/muc.h index 597a462e..96e8c1d0 100644 --- a/src/muc.h +++ b/src/muc.h @@ -93,6 +93,10 @@ void muc_roster_remove(const char * const room, const char * const nick); void muc_roster_set_complete(const char * const room); GList * muc_roster(const char * const room); Autocomplete muc_roster_ac(const char * const room); +Autocomplete muc_roster_jid_ac(const char * const room); +void muc_jid_autocomplete_reset(const char * const room); +void muc_jid_autocomplete_add_all(const char * const room, GSList *jids); + Occupant* muc_roster_item(const char * const room, const char * const nick); gboolean muc_occupant_available(Occupant *occupant); diff --git a/src/server_events.c b/src/server_events.c index 3c2620b1..cadb4d96 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -193,6 +193,7 @@ handle_room_affiliation_list_result_error(const char * const room, const char * void handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids) { + muc_jid_autocomplete_add_all(room, jids); ui_handle_room_affiliation_list(room, affiliation, jids); } @@ -557,6 +558,13 @@ handle_room_kicked(const char * const room, const char * const actor, const char ui_room_kicked(room, actor, reason); } +void +handle_room_banned(const char * const room, const char * const actor, const char * const reason) +{ + muc_leave(room); + ui_room_banned(room, actor, reason); +} + void handle_room_configure(const char * const room, DataForm *form) { @@ -664,6 +672,13 @@ handle_room_occupent_kicked(const char * const room, const char * const nick, co ui_room_member_kicked(room, nick, actor, reason); } +void +handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor, + const char * const reason) +{ + muc_roster_remove(room, nick); + ui_room_member_banned(room, nick, actor, reason); +} void handle_room_member_nick_change(const char * const room, diff --git a/src/server_events.h b/src/server_events.h index 56b01965..70c6b6bf 100644 --- a/src/server_events.h +++ b/src/server_events.h @@ -100,6 +100,9 @@ void handle_room_destroyed(const char * const room, const char * const new_jid, void handle_room_kicked(const char * const room, const char * const actor, const char * const reason); void handle_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor, const char * const reason); +void handle_room_banned(const char * const room, const char * const actor, const char * const reason); +void handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor, + const char * const reason); void handle_group_add(const char * const contact, const char * const group); void handle_group_remove(const char * const contact, diff --git a/src/ui/core.c b/src/ui/core.c index 5269e96b..cab56169 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -1517,6 +1517,29 @@ _ui_room_member_kicked(const char * const room, const char * const nick, const c } } +static void +_ui_room_member_banned(const char * const room, const char * const nick, const char * const actor, + const char * const reason) +{ + ProfWin *window = wins_get_by_recipient(room); + if (window == NULL) { + log_error("Received ban for room participant %s, but no window open for %s.", nick, room); + } else { + GString *message = g_string_new(nick); + g_string_append(message, " has been banned from the room"); + if (actor) { + g_string_append(message, " by "); + g_string_append(message, actor); + } + if (reason) { + g_string_append(message, ", reason: "); + g_string_append(message, reason); + } + + win_save_vprint(window, '!', NULL, 0, COLOUR_OFFLINE, "", "<- %s", message->str); + g_string_free(message, TRUE); + } +} static void _ui_room_member_online(const char * const room, const char * const nick, @@ -1793,6 +1816,33 @@ _ui_room_kicked(const char * const room, const char * const actor, const char * } } +static void +_ui_room_banned(const char * const room, const char * const actor, const char * const reason) +{ + ProfWin *window = wins_get_by_recipient(room); + if (window == NULL) { + log_error("Received ban, but no window open for %s.", room); + } else { + int num = wins_get_num(window); + ui_close_win(num); + + GString *message = g_string_new("Banned from "); + g_string_append(message, room); + if (actor) { + g_string_append(message, " by "); + g_string_append(message, actor); + } + if (reason) { + g_string_append(message, ", reason: "); + g_string_append(message, reason); + } + + ProfWin *console = wins_get_console(); + win_save_vprint(console, '!', NULL, 0, COLOUR_TYPING, "", "<- %s", message->str); + g_string_free(message, TRUE); + } +} + static void _ui_room_subject(const char * const room, const char * const nick, const char * const subject) { @@ -2925,8 +2975,10 @@ ui_init_module(void) ui_handle_room_kick_error = _ui_handle_room_kick_error; ui_room_destroyed = _ui_room_destroyed; ui_room_kicked = _ui_room_kicked; + ui_room_banned = _ui_room_banned; ui_leave_room = _ui_leave_room; ui_room_member_kicked = _ui_room_member_kicked; + ui_room_member_banned = _ui_room_member_banned; ui_handle_room_role_set_error = _ui_handle_room_role_set_error; ui_handle_room_role_set = _ui_handle_room_role_set; ui_handle_room_role_list_error = _ui_handle_room_role_list_error; diff --git a/src/ui/ui.h b/src/ui/ui.h index f987bdbb..b7bd7fbd 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -146,6 +146,9 @@ void (*ui_room_destroyed)(const char * const room, const char * const reason, co void (*ui_room_kicked)(const char * const room, const char * const actor, const char * const reason); void (*ui_room_member_kicked)(const char * const room, const char * const nick, const char * const actor, const char * const reason); +void (*ui_room_banned)(const char * const room, const char * const actor, const char * const reason); +void (*ui_room_member_banned)(const char * const room, const char * const nick, const char * const actor, + const char * const reason); void (*ui_leave_room)(const char * const room); void (*ui_room_broadcast)(const char * const room_jid, const char * const message); diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index adc6fc06..00506175 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -717,11 +717,18 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // kicked from room } else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) { - char *actor = stanza_get_kick_actor(stanza); - char *reason = stanza_get_kick_reason(stanza); + char *actor = stanza_get_kickban_actor(stanza); + char *reason = stanza_get_kickban_reason(stanza); handle_room_kicked(from_room, actor, reason); free(reason); + // banned from room + } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) { + char *actor = stanza_get_kickban_actor(stanza); + char *reason = stanza_get_kickban_reason(stanza); + handle_room_banned(from_room, actor, reason); + free(reason); + // normal exit } else { handle_leave_room(from_room); @@ -783,11 +790,18 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // kicked from room if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) { - char *actor = stanza_get_kick_actor(stanza); - char *reason = stanza_get_kick_reason(stanza); + char *actor = stanza_get_kickban_actor(stanza); + char *reason = stanza_get_kickban_reason(stanza); handle_room_occupent_kicked(from_room, from_nick, actor, reason); free(reason); + // banned from room + } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) { + char *actor = stanza_get_kickban_actor(stanza); + char *reason = stanza_get_kickban_reason(stanza); + handle_room_occupent_banned(from_room, from_nick, actor, reason); + free(reason); + // normal exit } else { handle_room_member_offline(from_room, from_nick, "offline", status_str); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 03b81bf3..58194124 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -1181,7 +1181,7 @@ stanza_get_muc_destroy_reason(xmpp_stanza_t *stanza) } char * -stanza_get_kick_actor(xmpp_stanza_t *stanza) +stanza_get_kickban_actor(xmpp_stanza_t *stanza) { char *stanza_name = xmpp_stanza_get_name(stanza); if (g_strcmp0(stanza_name, STANZA_NAME_PRESENCE) == 0) { @@ -1207,7 +1207,7 @@ stanza_get_kick_actor(xmpp_stanza_t *stanza) } char * -stanza_get_kick_reason(xmpp_stanza_t *stanza) +stanza_get_kickban_reason(xmpp_stanza_t *stanza) { char *stanza_name = xmpp_stanza_get_name(stanza); if (g_strcmp0(stanza_name, STANZA_NAME_PRESENCE) == 0) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 56aea01b..cbb6d23f 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -258,7 +258,7 @@ gboolean stanza_room_destroyed(xmpp_stanza_t *stanza); char* stanza_get_muc_destroy_alternative_room(xmpp_stanza_t *stanza); char* stanza_get_muc_destroy_alternative_password(xmpp_stanza_t *stanza); char* stanza_get_muc_destroy_reason(xmpp_stanza_t *stanza); -char* stanza_get_kick_actor(xmpp_stanza_t *stanza); -char* stanza_get_kick_reason(xmpp_stanza_t *stanza); +char* stanza_get_kickban_actor(xmpp_stanza_t *stanza); +char* stanza_get_kickban_reason(xmpp_stanza_t *stanza); #endif