diff --git a/src/command/command.c b/src/command/command.c index 8a0baf3f..1f8977b7 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -976,6 +976,7 @@ static Autocomplete room_ac; static Autocomplete room_affiliation_ac; static Autocomplete room_role_ac; static Autocomplete room_cmd_ac; +static Autocomplete room_subject_ac; static Autocomplete form_ac; /* @@ -1249,6 +1250,7 @@ cmd_init(void) autocomplete_add(room_ac, "destroy"); autocomplete_add(room_ac, "config"); autocomplete_add(room_ac, "info"); + autocomplete_add(room_ac, "subject"); autocomplete_add(room_ac, "role"); autocomplete_add(room_ac, "affiliation"); @@ -1268,6 +1270,10 @@ cmd_init(void) autocomplete_add(room_cmd_ac, "list"); autocomplete_add(room_cmd_ac, "set"); + room_subject_ac = autocomplete_new(); + autocomplete_add(room_subject_ac, "set"); + autocomplete_add(room_subject_ac, "clear"); + form_ac = autocomplete_new(); autocomplete_add(form_ac, "submit"); autocomplete_add(form_ac, "cancel"); @@ -1323,6 +1329,7 @@ cmd_uninit(void) autocomplete_free(room_affiliation_ac); autocomplete_free(room_role_ac); autocomplete_free(room_cmd_ac); + autocomplete_free(room_subject_ac); autocomplete_free(form_ac); } @@ -1452,6 +1459,7 @@ cmd_reset_autocomplete() autocomplete_reset(room_affiliation_ac); autocomplete_reset(room_role_ac); autocomplete_reset(room_cmd_ac); + autocomplete_reset(room_subject_ac); autocomplete_reset(form_ac); if (ui_current_win_type() == WIN_MUC_CONFIG) { @@ -2298,6 +2306,11 @@ _room_autocomplete(char *input, int *size) return result; } + result = autocomplete_param_with_ac(input, size, "/room subject", room_subject_ac, TRUE); + if (result != NULL) { + return result; + } + result = autocomplete_param_with_ac(input, size, "/room", room_ac, TRUE); if (result != NULL) { return result; diff --git a/src/command/commands.c b/src/command/commands.c index 8a6150c0..ad8e93ea 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -2126,6 +2126,7 @@ cmd_room(gchar **args, struct cmd_help_t help) if ((g_strcmp0(args[0], "accept") != 0) && (g_strcmp0(args[0], "destroy") != 0) && (g_strcmp0(args[0], "config") != 0) && + (g_strcmp0(args[0], "subject") != 0) && (g_strcmp0(args[0], "role") != 0) && (g_strcmp0(args[0], "affiliation") != 0) && (g_strcmp0(args[0], "info") != 0)) { @@ -2148,6 +2149,36 @@ cmd_room(gchar **args, struct cmd_help_t help) return TRUE; } + if (g_strcmp0(args[0], "subject") == 0) { + if (args[1] == NULL) { + char *subject = muc_subject(room); + if (subject) { + win_save_vprint(window, '!', NULL, NO_EOL, COLOUR_ROOMINFO, "", "Room subject: "); + win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject); + } else { + win_save_print(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Room has no subject"); + } + return TRUE; + } + + if (g_strcmp0(args[1], "set") == 0) { + if (args[2]) { + message_send_groupchat_subject(room, args[2]); + } else { + cons_show("Usage: %s", help.usage); + } + return TRUE; + } + + if (g_strcmp0(args[1], "clear") == 0) { + message_send_groupchat_subject(room, NULL); + return TRUE; + } + + cons_show("Usage: %s", help.usage); + return TRUE; + } + if (g_strcmp0(args[0], "affiliation") == 0) { char *cmd = args[1]; if (cmd == NULL) { diff --git a/src/muc.c b/src/muc.c index effb1227..aa8148b1 100644 --- a/src/muc.c +++ b/src/muc.c @@ -232,7 +232,11 @@ muc_set_subject(const char * const room, const char * const subject) ChatRoom *chat_room = g_hash_table_lookup(rooms, room); if (chat_room) { free(chat_room->subject); - chat_room->subject = strdup(subject); + if (subject) { + chat_room->subject = strdup(subject); + } else { + chat_room->subject = NULL; + } } } diff --git a/src/server_events.c b/src/server_events.c index 1636cc81..3ca41f0f 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -239,11 +239,11 @@ handle_room_broadcast(const char *const room_jid, } void -handle_room_subject(const char * const room_jid, const char * const subject) +handle_room_subject(const char * const room, const char * const nick, const char * const subject) { - muc_set_subject(room_jid, subject); - if (muc_roster_complete(room_jid)) { - ui_room_subject(room_jid, subject); + muc_set_subject(room, subject); + if (muc_roster_complete(room)) { + ui_room_subject(room, nick, subject); } } @@ -553,7 +553,7 @@ handle_room_roster_complete(const char * const room) char *subject = muc_subject(room); if (subject != NULL) { - ui_room_subject(room, subject); + ui_room_subject(room, NULL, subject); } GList *pending_broadcasts = muc_pending_broadcasts(room); diff --git a/src/server_events.h b/src/server_events.h index e16b81f3..3fcab421 100644 --- a/src/server_events.h +++ b/src/server_events.h @@ -51,7 +51,7 @@ void handle_room_invite(jabber_invite_t invite_type, const char * const reason); void handle_room_broadcast(const char *const room_jid, const char * const message); -void handle_room_subject(const char * const room_jid, const char * const subject); +void handle_room_subject(const char * const room, const char * const nick, const char * const subject); void handle_room_history(const char * const room_jid, const char * const nick, GTimeVal tv_stamp, const char * const message); void handle_room_message(const char * const room_jid, const char * const nick, diff --git a/src/ui/core.c b/src/ui/core.c index ae47d881..0aca17b6 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -1704,16 +1704,29 @@ _ui_room_destroyed(const char * const room_jid) } static void -_ui_room_subject(const char * const room_jid, const char * const subject) +_ui_room_subject(const char * const room, const char * const nick, const char * const subject) { - ProfWin *window = wins_get_by_recipient(room_jid); + ProfWin *window = wins_get_by_recipient(room); if (window == NULL) { - log_error("Received room subject, but no window open for %s.", room_jid); + log_error("Received room subject, but no window open for %s.", room); } else { int num = wins_get_num(window); - win_save_vprint(window, '!', NULL, NO_EOL, COLOUR_ROOMINFO, "", "Room subject: "); - win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject); + if (subject) { + if (nick) { + win_save_vprint(window, '!', NULL, NO_EOL, COLOUR_ROOMINFO, "", "*%s has set the room subject: ", nick); + win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject); + } else { + win_save_vprint(window, '!', NULL, NO_EOL, COLOUR_ROOMINFO, "", "Room subject: "); + win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject); + } + } else { + if (nick) { + win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "*%s has cleared the room subject: ", nick); + } else { + win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Room subject cleared"); + } + } // currently in groupchat window if (wins_is_current(window)) { diff --git a/src/ui/ui.h b/src/ui/ui.h index e49c7295..bd3d4181 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -133,8 +133,7 @@ void (*ui_room_history)(const char * const room_jid, const char * const nick, GTimeVal tv_stamp, const char * const message); void (*ui_room_message)(const char * const room_jid, const char * const nick, const char * const message); -void (*ui_room_subject)(const char * const room_jid, - const char * const subject); +void (*ui_room_subject)(const char * const room, const char * const nick, const char * const subject); void (*ui_room_requires_config)(const char * const room_jid); void (*ui_room_destroyed)(const char * const room_jid); void (*ui_show_room_info)(ProfWin *window, const char * const room); diff --git a/src/xmpp/message.c b/src/xmpp/message.c index f3940067..16a51829 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -124,6 +124,17 @@ _message_send_groupchat(const char * const msg, const char * const recipient) xmpp_stanza_release(message); } +static void +_message_send_groupchat_subject(const char * const room, const char * const subject) +{ + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *message = stanza_create_room_subject_message(ctx, room, subject); + + xmpp_send(conn, message); + xmpp_stanza_release(message); +} + static void _message_send_duck(const char * const query) { @@ -361,10 +372,8 @@ _groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT); if (subject != NULL) { message = xmpp_stanza_get_text(subject); - if (message != NULL) { - handle_room_subject(jid->barejid, message); - xmpp_free(ctx, message); - } + handle_room_subject(jid->barejid, jid->resourcepart, message); + xmpp_free(ctx, message); jid_destroy(jid); return 1; @@ -530,4 +539,5 @@ message_init_module(void) message_send_paused = _message_send_paused; message_send_inactive = _message_send_inactive; message_send_gone = _message_send_gone; + message_send_groupchat_subject = _message_send_groupchat_subject; } diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index e17ed86e..b1bb51d8 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -220,6 +220,29 @@ stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, return msg; } +xmpp_stanza_t * +stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char * const room, const char * const subject) +{ + xmpp_stanza_t *msg = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE); + xmpp_stanza_set_type(msg, STANZA_TYPE_GROUPCHAT); + xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, room); + + xmpp_stanza_t *subject_st = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(subject_st, STANZA_NAME_SUBJECT); + if (subject) { + xmpp_stanza_t *subject_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(subject_text, subject); + xmpp_stanza_add_child(subject_st, subject_text); + xmpp_stanza_release(subject_text); + } + + xmpp_stanza_add_child(msg, subject_st); + xmpp_stanza_release(subject_st); + + return msg; +} + xmpp_stanza_t * stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, const char * const type, const char * const message, diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index cf2dc482..d9f82929 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -209,6 +209,7 @@ xmpp_stanza_t* stanza_create_room_affiliation_list_iq(xmpp_ctx_t *ctx, const cha const char * const affiliation); xmpp_stanza_t* stanza_create_room_affiliation_set_iq(xmpp_ctx_t *ctx, const char * const room, const char * const jid, const char * const affiliation, const char * const reason); +xmpp_stanza_t* stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char * const room, const char * const subject); int stanza_get_idle_time(xmpp_stanza_t * const stanza); char * stanza_get_caps_str(xmpp_stanza_t * const stanza); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 0695d903..37c916f4 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -156,6 +156,8 @@ GList * (*jabber_get_available_resources)(void); // message functions void (*message_send)(const char * const msg, const char * const recipient); void (*message_send_groupchat)(const char * const msg, const char * const recipient); +void (*message_send_groupchat_subject)(const char * const room, const char * const subject); + void (*message_send_inactive)(const char * const recipient); void (*message_send_composing)(const char * const recipient); void (*message_send_paused)(const char * const recipient);