From eba3a7cb303af47624ea890e2c3164010684e60f Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 10 Sep 2014 23:05:35 +0100 Subject: [PATCH] Implemented /room config submit for saving room configuration --- src/command/commands.c | 17 ++++++++- src/server_events.c | 6 ++++ src/server_events.h | 1 + src/ui/core.c | 9 ++++- src/ui/ui.h | 1 + src/ui/window.c | 2 ++ src/ui/window.h | 2 ++ src/xmpp/form.c | 80 ++++++++++++++++++++++++++++++++++++++++++ src/xmpp/form.h | 1 + src/xmpp/iq.c | 34 ++++++++++++++++++ src/xmpp/stanza.c | 26 ++++++++++++++ src/xmpp/stanza.h | 2 ++ src/xmpp/xmpp.h | 1 + 13 files changed, 180 insertions(+), 2 deletions(-) diff --git a/src/command/commands.c b/src/command/commands.c index 17eb9157..8dc351aa 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1798,7 +1798,7 @@ cmd_room(gchar **args, struct cmd_help_t help) } win_type_t win_type = ui_current_win_type(); - if (win_type != WIN_MUC) { + if (win_type != WIN_MUC && win_type != WIN_MUC_CONFIG) { cons_show("Command /room only usable in chat rooms."); return TRUE; } @@ -1811,6 +1811,7 @@ cmd_room(gchar **args, struct cmd_help_t help) if ((g_strcmp0(args[1], "accept") != 0) && (g_strcmp0(args[1], "cancel") != 0) && (g_strcmp0(args[1], "destroy") != 0) && + (g_strcmp0(args[1], "submit") != 0) && (g_strcmp0(args[1], "edit") != 0)) { cons_show("Usage: %s", help.usage); return TRUE; @@ -1857,6 +1858,20 @@ cmd_room(gchar **args, struct cmd_help_t help) return TRUE; } + if (g_strcmp0(args[1], "submit") == 0) { + ProfWin *current = wins_get_current(); + if (current->type != WIN_MUC_CONFIG) { + cons_show("Room configuration can only be submitted when in the room configuration window."); + return TRUE; + } else { + gchar **split_recipient = g_strsplit(room, " ", 2); + room = split_recipient[0]; + iq_submit_room_config(room, current->form); + g_strfreev(split_recipient); + return TRUE; + } + } + if (g_strcmp0(args[1], "cancel") == 0) { iq_room_config_cancel(room); return TRUE; diff --git a/src/server_events.c b/src/server_events.c index f78c919b..4e48aecb 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -469,6 +469,12 @@ handle_room_configure(const char * const room, DataForm *form) ui_handle_room_configuration(room, form); } +void +handle_room_config_submit_result(void) +{ + ui_handle_room_config_submit_result(); +} + void handle_room_configuration_form_error(const char * const room, const char * const message) { diff --git a/src/server_events.h b/src/server_events.h index 1b23f108..06e851f0 100644 --- a/src/server_events.h +++ b/src/server_events.h @@ -98,5 +98,6 @@ void handle_ping_result(const char * const from, int millis); void handle_ping_error_result(const char * const from, const char * const error); void handle_room_configure(const char * const room, DataForm *form); void handle_room_configuration_form_error(const char * const from, const char * const message); +void handle_room_config_submit_result(void); #endif diff --git a/src/ui/core.c b/src/ui/core.c index fa18e6b4..07840760 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -1997,6 +1997,8 @@ _ui_handle_room_configuration(const char * const room, DataForm *form) ProfWin *window = wins_new(title->str, WIN_MUC_CONFIG); g_string_free(title, TRUE); + window->form = form; + int num = wins_get_num(window); ui_switch_win(num); @@ -2041,8 +2043,12 @@ TODO add command to get help for a field curr_field = g_slist_next(curr_field); } +} - form_destroy(form); +static void +_ui_handle_room_config_submit_result(void) +{ + cons_show("GOT ROOM CONFIG SUBMIT RESULT!!!!"); } static void @@ -2283,4 +2289,5 @@ ui_init_module(void) ui_room_requires_config = _ui_room_requires_config; ui_room_destroyed = _ui_room_destroyed; ui_handle_room_configuration = _ui_handle_room_configuration; + ui_handle_room_config_submit_result = _ui_handle_room_config_submit_result; } diff --git a/src/ui/ui.h b/src/ui/ui.h index cb1a92ee..bdfd79ae 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -161,6 +161,7 @@ void (*ui_handle_error)(const char * const err_msg); void (*ui_clear_win_title)(void); void (*ui_handle_room_join_error)(const char * const room, const char * const err); void (*ui_handle_room_configuration)(const char * const room, DataForm *form); +void (*ui_handle_room_config_submit_result)(void); // contact status functions void (*ui_status_room)(const char * const contact); diff --git a/src/ui/window.c b/src/ui/window.c index 6a1240e5..21591bae 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -68,6 +68,7 @@ win_create(const char * const title, int cols, win_type_t type) new_win->type = type; new_win->is_otr = FALSE; new_win->is_trusted = FALSE; + new_win->form = NULL; scrollok(new_win->win, TRUE); return new_win; @@ -79,6 +80,7 @@ win_free(ProfWin* window) buffer_free(window->buffer); delwin(window->win); free(window->from); + form_destroy(window->form); free(window); } diff --git a/src/ui/window.h b/src/ui/window.h index 5a72f18f..8150fac9 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -45,6 +45,7 @@ #include "contact.h" #include "ui/buffer.h" +#include "xmpp/xmpp.h" #define NO_ME 1 #define NO_DATE 2 @@ -75,6 +76,7 @@ typedef struct prof_win_t { int paged; int unread; int history_shown; + DataForm *form; } ProfWin; ProfWin* win_create(const char * const title, int cols, win_type_t type); diff --git a/src/xmpp/form.c b/src/xmpp/form.c index 4b79d8e6..b870aaa4 100644 --- a/src/xmpp/form.c +++ b/src/xmpp/form.c @@ -236,6 +236,86 @@ form_create(xmpp_stanza_t * const form_stanza) return form; } +xmpp_stanza_t * +form_create_submission(DataForm *form) +{ + xmpp_ctx_t *ctx = connection_get_ctx(); + + xmpp_stanza_t *x = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(x, STANZA_NAME_X); + xmpp_stanza_set_ns(x, STANZA_NS_DATA); + xmpp_stanza_set_type(x, "submit"); + + GSList *curr_field = form->fields; + while (curr_field != NULL) { + FormField *field = curr_field->data; + + xmpp_stanza_t *field_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field_stanza, "field"); + xmpp_stanza_set_attribute(field_stanza, "var", field->var); + + xmpp_stanza_t *value_stanza = NULL; + GSList *curr_value = NULL; + + switch (field->type_t) { + + case FIELD_HIDDEN: + case FIELD_TEXT_SINGLE: + case FIELD_TEXT_PRIVATE: + case FIELD_BOOLEAN: + case FIELD_LIST_SINGLE: + case FIELD_JID_SINGLE: + case FIELD_FIXED: + value_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(value_stanza, "value"); + if (field->values != NULL) { + if (field->values->data != NULL) { + xmpp_stanza_t *text_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text_stanza, field->values->data); + xmpp_stanza_add_child(value_stanza, text_stanza); + xmpp_stanza_release(text_stanza); + } + } + xmpp_stanza_add_child(field_stanza, value_stanza); + xmpp_stanza_release(value_stanza); + + break; + + case FIELD_TEXT_MULTI: + case FIELD_LIST_MUTLI: + case FIELD_JID_MULTI: + curr_value = field->values; + while (curr_value != NULL) { + char *value = curr_value->data; + + value_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(value_stanza, "value"); + if (value != NULL) { + xmpp_stanza_t *text_stanza = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text_stanza, value); + xmpp_stanza_add_child(value_stanza, text_stanza); + xmpp_stanza_release(text_stanza); + } + + xmpp_stanza_add_child(field_stanza, value_stanza); + xmpp_stanza_release(value_stanza); + + curr_value = g_slist_next(curr_value); + } + break; + default: + break; + } + + xmpp_stanza_add_child(x, field_stanza); + xmpp_stanza_release(field_stanza); + + curr_field = g_slist_next(curr_field); + } + + return x; +} + static void _free_option(FormOption *option) { diff --git a/src/xmpp/form.h b/src/xmpp/form.h index b0c32675..fb2bf80a 100644 --- a/src/xmpp/form.h +++ b/src/xmpp/form.h @@ -36,5 +36,6 @@ #define FROM_H DataForm* form_create(xmpp_stanza_t * const stanza); +xmpp_stanza_t* form_create_submission(DataForm *form); #endif diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index a3c9e7d9..39d8908b 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -78,6 +78,8 @@ static int _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); +static int _room_config_submit_handler(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata); static int _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _ping_timed_handler(xmpp_conn_t * const conn, @@ -203,6 +205,20 @@ _iq_request_room_config_form(const char * const room_jid) xmpp_stanza_release(iq); } +static void +_iq_submit_room_config(const char * const room, DataForm *form) +{ + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_room_config_submit_iq(ctx, room, form); + + char *id = xmpp_stanza_get_id(iq); + xmpp_id_handler_add(conn, _room_config_submit_handler, id, NULL); + + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + static void _iq_room_config_cancel(const char * const room_jid) { @@ -645,6 +661,23 @@ _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, return 0; } +static int +_room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, + void * const userdata) +{ + const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID); + + if (id != NULL) { + log_debug("IQ room config handler fired, id: %s.", id); + } else { + log_debug("IQ room config handler fired."); + } + + handle_room_config_submit_result(); + + return 0; +} + static void _identity_destroy(DiscoIdentity *identity) { @@ -897,4 +930,5 @@ iq_init_module(void) iq_send_ping = _iq_send_ping; iq_request_room_config_form = _iq_request_room_config_form; iq_room_config_cancel = _iq_room_config_cancel; + iq_submit_room_config = _iq_submit_room_config; } diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 519862f7..118bffb7 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -43,6 +43,7 @@ #include "xmpp/connection.h" #include "xmpp/stanza.h" #include "xmpp/capabilities.h" +#include "xmpp/form.h" #include "muc.h" @@ -616,6 +617,31 @@ stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char * const id, return iq; } +xmpp_stanza_t * +stanza_create_room_config_submit_iq(xmpp_ctx_t *ctx, const char * const room, DataForm *form) +{ + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, room); + char *id = create_unique_id("roomconf_submit"); + xmpp_stanza_set_id(iq, id); + free(id); + + xmpp_stanza_t *query = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, STANZA_NS_MUC_OWNER); + + xmpp_stanza_t *x = form_create_submission(form); + xmpp_stanza_add_child(query, x); + xmpp_stanza_release(x); + + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(query); + + return iq; +} + gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index b13c2960..155044f2 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -202,6 +202,8 @@ xmpp_stanza_t* stanza_create_room_config_request_iq(xmpp_ctx_t *ctx, const char * const room_jid); xmpp_stanza_t* stanza_create_room_config_cancel_iq(xmpp_ctx_t *ctx, const char * const room_jid); +xmpp_stanza_t* stanza_create_room_config_submit_iq(xmpp_ctx_t *ctx, + const char * const room, DataForm *form); 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 c5583517..7ffce4c4 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -180,6 +180,7 @@ void (*iq_set_autoping)(int seconds); void (*iq_confirm_instant_room)(const char * const room_jid); void (*iq_destroy_instant_room)(const char * const room_jid); void (*iq_request_room_config_form)(const char * const room_jid); +void (*iq_submit_room_config)(const char * const room, DataForm *form); void (*iq_room_config_cancel)(const char * const room_jid); void (*iq_send_ping)(const char * const target);