diff options
Diffstat (limited to 'src/xmpp')
37 files changed, 462 insertions, 117 deletions
diff --git a/src/xmpp/blocking.c b/src/xmpp/blocking.c index 5d1c52b2..d3c84f0d 100644 --- a/src/xmpp/blocking.c +++ b/src/xmpp/blocking.c @@ -1,7 +1,7 @@ /* * blocking.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -73,7 +73,7 @@ blocking_request(void) } blocked_ac = autocomplete_new(); - char *id = create_unique_id("blocked_list_request"); + char *id = connection_create_stanza_id("blocked_list_request"); iq_id_handler_add(id, _blocklist_result_handler, NULL, NULL); xmpp_ctx_t *ctx = connection_get_ctx(); @@ -115,7 +115,7 @@ blocked_add(char *jid) xmpp_ctx_t *ctx = connection_get_ctx(); - char *id = create_unique_id("block"); + char *id = connection_create_stanza_id("block"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); xmpp_stanza_t *block = xmpp_stanza_new(ctx); @@ -151,7 +151,7 @@ blocked_remove(char *jid) xmpp_ctx_t *ctx = connection_get_ctx(); - char *id = create_unique_id("unblock"); + char *id = connection_create_stanza_id("unblock"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); xmpp_stanza_t *block = xmpp_stanza_new(ctx); diff --git a/src/xmpp/blocking.h b/src/xmpp/blocking.h index 61acb631..7b3863f1 100644 --- a/src/xmpp/blocking.h +++ b/src/xmpp/blocking.h @@ -1,7 +1,7 @@ /* * blocking.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index 65009224..99c17c1e 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -1,7 +1,7 @@ /* * bookmark.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -333,7 +333,7 @@ _send_bookmarks(void) { xmpp_ctx_t *ctx = connection_get_ctx(); - char *id = create_unique_id("bookmarks_update"); + char *id = connection_create_stanza_id("bookmarks_update"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h index f6c72c27..0823aee1 100644 --- a/src/xmpp/bookmark.h +++ b/src/xmpp/bookmark.h @@ -1,7 +1,7 @@ /* * bookmark.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index 2152f869..8d66b25a 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -1,7 +1,7 @@ /* * capabilities.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/capabilities.h b/src/xmpp/capabilities.h index 21ffe0b4..a4e25128 100644 --- a/src/xmpp/capabilities.h +++ b/src/xmpp/capabilities.h @@ -1,7 +1,7 @@ /* * capabilities.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/chat_session.c b/src/xmpp/chat_session.c index 799a9c47..1b57068f 100644 --- a/src/xmpp/chat_session.c +++ b/src/xmpp/chat_session.c @@ -1,7 +1,7 @@ /* * chat_session.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/chat_session.h b/src/xmpp/chat_session.h index d8de0330..564ee2b0 100644 --- a/src/xmpp/chat_session.h +++ b/src/xmpp/chat_session.h @@ -1,7 +1,7 @@ /* * chat_session.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/chat_state.c b/src/xmpp/chat_state.c index 9659eb8b..da5c1342 100644 --- a/src/xmpp/chat_state.c +++ b/src/xmpp/chat_state.c @@ -1,7 +1,7 @@ /* * chat_state.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/chat_state.h b/src/xmpp/chat_state.h index 51698cd1..f3d3adb0 100644 --- a/src/xmpp/chat_state.h +++ b/src/xmpp/chat_state.h @@ -1,7 +1,7 @@ /* * chat_state.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 6c5e7323..2adda46e 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -1,7 +1,7 @@ /* * connection.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -150,6 +150,9 @@ connection_connect(const char *const jid, const char *const passwd, const char * if (!tls_policy || (g_strcmp0(tls_policy, "force") == 0)) { xmpp_conn_set_flags(conn.xmpp_conn, XMPP_CONN_FLAG_MANDATORY_TLS); + } else if (g_strcmp0(tls_policy, "trust") == 0) { + xmpp_conn_set_flags(conn.xmpp_conn, XMPP_CONN_FLAG_MANDATORY_TLS); + xmpp_conn_set_flags(conn.xmpp_conn, XMPP_CONN_FLAG_TRUST_TLS); } else if (g_strcmp0(tls_policy, "disable") == 0) { xmpp_conn_set_flags(conn.xmpp_conn, XMPP_CONN_FLAG_DISABLE_TLS); } else if (g_strcmp0(tls_policy, "legacy") == 0) { @@ -393,6 +396,27 @@ connection_free_uuid(char *uuid) } char* +connection_create_stanza_id(char *prefix) +{ + char *result = NULL; + GString *result_str = g_string_new(""); + char *uuid = connection_create_uuid(); + + if (prefix) { + g_string_printf(result_str, "prof_%s_%s", prefix, uuid); + } else { + g_string_printf(result_str, "prof_%s", uuid); + } + + connection_free_uuid(uuid); + + result = result_str->str; + g_string_free(result_str, FALSE); + + return result; +} + +char* connection_get_domain(void) { return conn.domain; diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index b0ff7cec..170bc2bf 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -1,7 +1,7 @@ /* * connection.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -60,4 +60,6 @@ void connection_clear_data(void); void connection_add_available_resource(Resource *resource); void connection_remove_available_resource(const char *const resource); +char* connection_create_stanza_id(char *prefix); + #endif diff --git a/src/xmpp/contact.c b/src/xmpp/contact.c index a43372f3..49d0786c 100644 --- a/src/xmpp/contact.c +++ b/src/xmpp/contact.c @@ -1,7 +1,7 @@ /* * contact.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/contact.h b/src/xmpp/contact.h index 170df2ca..d3b2dee3 100644 --- a/src/xmpp/contact.h +++ b/src/xmpp/contact.h @@ -1,7 +1,7 @@ /* * contact.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/form.c b/src/xmpp/form.c index 6e26411a..d30eb0fc 100644 --- a/src/xmpp/form.c +++ b/src/xmpp/form.c @@ -1,7 +1,7 @@ /* * form.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/form.h b/src/xmpp/form.h index 21314ce2..04af8f6b 100644 --- a/src/xmpp/form.h +++ b/src/xmpp/form.h @@ -1,7 +1,7 @@ /* * form.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 9bceb859..a77ef59b 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -1,7 +1,7 @@ /* * iq.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -88,6 +88,11 @@ typedef struct privilege_set_t { char *privilege; } ProfPrivilegeSet; +typedef struct command_config_data_t { + char *sessionid; + char *command; +} CommandConfigData; + static int _iq_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); static void _error_handler(xmpp_stanza_t *const stanza); @@ -120,6 +125,8 @@ static int _caps_response_for_jid_id_handler(xmpp_stanza_t *const stanza, void * static int _caps_response_legacy_id_handler(xmpp_stanza_t *const stanza, void *const userdata); static int _auto_pong_id_handler(xmpp_stanza_t *const stanza, void *const userdata); static int _room_list_id_handler(xmpp_stanza_t *const stanza, void *const userdata); +static int _command_list_result_handler(xmpp_stanza_t *const stanza, void *const userdata); +static int _command_exec_response_handler(xmpp_stanza_t *const stanza, void *const userdata); static void _iq_free_room_data(ProfRoomInfoData *roominfo); static void _iq_free_affiliation_set(ProfPrivilegeSet *affiliation_set); @@ -318,8 +325,8 @@ iq_room_list_request(gchar *conferencejid, gchar *filter) log_debug("Rooms request not cached for: %s", conferencejid); xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("confreq"); - xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, id, conferencejid); + char *id = connection_create_stanza_id("confreq"); + xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, id, conferencejid, NULL); iq_id_handler_add(id, _room_list_id_handler, NULL, filter); @@ -363,7 +370,7 @@ iq_http_upload_request(HTTPUpload *upload) } xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("http_upload_request"); + char *id = connection_create_stanza_id("http_upload_request"); xmpp_stanza_t *iq = stanza_create_http_upload_request(ctx, id, jid, upload); // TODO add free func iq_id_handler_add(id, _http_upload_response_id_handler, NULL, upload); @@ -379,7 +386,7 @@ void iq_disco_info_request(gchar *jid) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("disco_info"); + char *id = connection_create_stanza_id("disco_info"); xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, jid, NULL); iq_id_handler_add(id, _disco_info_response_id_handler, NULL, NULL); @@ -394,7 +401,7 @@ void iq_disco_info_request_onconnect(gchar *jid) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("disco_info_onconnect"); + char *id = connection_create_stanza_id("disco_info_onconnect"); xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, jid, NULL); iq_id_handler_add(id, _disco_info_response_id_handler_onconnect, NULL, NULL); @@ -409,7 +416,7 @@ void iq_last_activity_request(gchar *jid) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("lastactivity"); + char *id = connection_create_stanza_id("lastactivity"); xmpp_stanza_t *iq = stanza_create_last_activity_iq(ctx, id, jid); iq_id_handler_add(id, _last_activity_response_id_handler, NULL, NULL); @@ -424,7 +431,7 @@ void iq_room_info_request(const char *const room, gboolean display_result) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("room_disco_info"); + char *id = connection_create_stanza_id("room_disco_info"); xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, room, NULL); ProfRoomInfoData *cb_data = malloc(sizeof(ProfRoomInfoData)); @@ -521,7 +528,7 @@ void iq_disco_items_request(gchar *jid) { xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "discoitemsreq", jid); + xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "discoitemsreq", jid, NULL); iq_send_stanza(iq); xmpp_stanza_release(iq); } @@ -530,7 +537,7 @@ void iq_disco_items_request_onconnect(gchar *jid) { xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "discoitemsreq_onconnect", jid); + xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, "discoitemsreq_onconnect", jid, NULL); iq_send_stanza(iq); xmpp_stanza_release(iq); } @@ -584,10 +591,10 @@ iq_request_room_config_form(const char *const room_jid) } void -iq_submit_room_config(const char *const room, DataForm *form) +iq_submit_room_config(ProfConfWin *confwin) { xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_room_config_submit_iq(ctx, room, form); + xmpp_stanza_t *iq = stanza_create_room_config_submit_iq(ctx, confwin->roomjid, confwin->form); const char *id = xmpp_stanza_get_id(iq); iq_id_handler_add(id, _room_config_submit_id_handler, NULL, NULL); @@ -597,10 +604,10 @@ iq_submit_room_config(const char *const room, DataForm *form) } void -iq_room_config_cancel(const char *const room_jid) +iq_room_config_cancel(ProfConfWin *confwin) { xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_room_config_cancel_iq(ctx, room_jid); + xmpp_stanza_t *iq = stanza_create_room_config_cancel_iq(ctx, confwin->roomjid); iq_send_stanza(iq); xmpp_stanza_release(iq); } @@ -696,6 +703,62 @@ iq_send_ping(const char *const target) xmpp_stanza_release(iq); } +void +iq_command_list(const char *const target) +{ + xmpp_ctx_t * const ctx = connection_get_ctx(); + const char *id = connection_create_stanza_id("cmdlist"); + xmpp_stanza_t *iq = stanza_create_disco_items_iq(ctx, id, target, STANZA_NS_COMMAND); + + iq_id_handler_add(id, _command_list_result_handler, NULL, NULL); + + iq_send_stanza(iq); + xmpp_stanza_release(iq); +} + +void +iq_command_exec(const char *const target, const char *const command) +{ + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_command_exec_iq(ctx, target, command); + const char *id = xmpp_stanza_get_id(iq); + + iq_id_handler_add(id, _command_exec_response_handler, free, strdup(command)); + + iq_send_stanza(iq); + xmpp_stanza_release(iq); +} + +void +iq_submit_command_config(ProfConfWin *confwin) +{ + xmpp_ctx_t * const ctx = connection_get_ctx(); + CommandConfigData *data = (CommandConfigData *)confwin->userdata; + xmpp_stanza_t *iq = stanza_create_command_config_submit_iq(ctx, confwin->roomjid, data->command, data->sessionid, confwin->form); + + const char *id = xmpp_stanza_get_id(iq); + iq_id_handler_add(id, _command_exec_response_handler, free, strdup(data->command)); + + iq_send_stanza(iq); + xmpp_stanza_release(iq); + free(data->sessionid); + free(data->command); + free(data); +} + +void +iq_cancel_command_config(ProfConfWin *confwin) +{ + xmpp_ctx_t * const ctx = connection_get_ctx(); + CommandConfigData *data = (CommandConfigData *)confwin->userdata; + xmpp_stanza_t *iq = stanza_create_room_config_cancel_iq(ctx, confwin->roomjid); + iq_send_stanza(iq); + xmpp_stanza_release(iq); + free(data->sessionid); + free(data->command); + free(data); +} + static void _error_handler(xmpp_stanza_t *const stanza) { @@ -1012,6 +1075,186 @@ _room_list_id_handler(xmpp_stanza_t *const stanza, void *const userdata) } static int +_command_list_result_handler(xmpp_stanza_t *const stanza, void *const userdata) +{ + const char *id = xmpp_stanza_get_id(stanza); + const char *type = xmpp_stanza_get_type(stanza); + char *from = strdup(xmpp_stanza_get_from(stanza)); + + if (id) { + log_debug("IQ command list result handler fired, id: %s.", id); + } else { + log_debug("IQ command list result handler fired."); + } + + // handle error responses + if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { + char *error_message = stanza_get_error_message(stanza); + log_debug("Error retrieving command list for %s: %s", from, error_message); + ProfWin *win = wins_get_by_string(from); + if (win) { + win_command_list_error(win, error_message); + } + free(error_message); + free(from); + return 0; + } + + GSList *cmds = NULL; + + xmpp_stanza_t *query = xmpp_stanza_get_child_by_ns(stanza, XMPP_NS_DISCO_ITEMS); + if (query) { + xmpp_stanza_t *child = xmpp_stanza_get_children(query); + while (child) { + const char *name = xmpp_stanza_get_name(child); + if (g_strcmp0(name, "item") == 0) { + const char *node = xmpp_stanza_get_attribute(child, STANZA_ATTR_NODE); + if (node) { + cmds = g_slist_insert_sorted(cmds, (gpointer)node, (GCompareFunc)g_strcmp0); + } + } + child = xmpp_stanza_get_next(child); + } + } + + ProfWin *win = wins_get_by_string(from); + if (win == NULL) { + win = wins_get_console(); + } + + win_handle_command_list(win, cmds); + g_slist_free(cmds); + free(from); + + return 0; +} + +static int +_command_exec_response_handler(xmpp_stanza_t *const stanza, void *const userdata) +{ + const char *id = xmpp_stanza_get_id(stanza); + const char *type = xmpp_stanza_get_type(stanza); + const char *from = xmpp_stanza_get_from(stanza); + char *command = userdata; + + if (id) { + log_debug("IQ command exec response handler fired, id: %s.", id); + } else { + log_debug("IQ command exec response handler fired."); + } + + ProfWin *win = wins_get_by_string(from); + if (win == NULL) { + /* No more window associated with this command. + * Fallback to console. */ + win = wins_get_console(); + } + + // handle error responses + if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { + char *error_message = stanza_get_error_message(stanza); + log_debug("Error executing command %s for %s: %s", command, from, error_message); + win_command_exec_error(win, command, error_message); + free(error_message); + return 0; + } + + xmpp_stanza_t *cmd = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_COMMAND); + if (!cmd) { + log_error("No command element for command response"); + win_command_exec_error(win, command, "Malformed command response"); + return 0; + } + + + const char *status = xmpp_stanza_get_attribute(cmd, STANZA_ATTR_STATUS); + if (g_strcmp0(status, "completed") == 0) { + win_handle_command_exec_status(win, command, "completed"); + xmpp_stanza_t *note = xmpp_stanza_get_child_by_name(cmd, "note"); + if (note) { + const char *type = xmpp_stanza_get_attribute(note, "type"); + const char *value = xmpp_stanza_get_text(note); + win_handle_command_exec_result_note(win, type, value); + } + xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(cmd, STANZA_NS_DATA); + if (x) { + xmpp_stanza_t *roster = xmpp_stanza_get_child_by_ns(x, XMPP_NS_ROSTER); + if (roster) { + /* Special handling of xep-0133 roster in response */ + GSList *list = NULL; + xmpp_stanza_t *child = xmpp_stanza_get_children(roster); + while (child) { + const char *barejid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID); + gchar *barejid_lower = g_utf8_strdown(barejid, -1); + const char *name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME); + const char *sub = xmpp_stanza_get_attribute(child, STANZA_ATTR_SUBSCRIPTION); + const char *ask = xmpp_stanza_get_attribute(child, STANZA_ATTR_ASK); + + GSList *groups = NULL; + groups = roster_get_groups_from_item(child); + + gboolean pending_out = FALSE; + if (ask && (strcmp(ask, "subscribe") == 0)) { + pending_out = TRUE; + } + + PContact contact = p_contact_new(barejid_lower, name, groups, sub, NULL, pending_out); + list = g_slist_insert_sorted(list, contact, (GCompareFunc)roster_compare_name); + child = xmpp_stanza_get_next(child); + } + + cons_show_roster(list); + g_slist_free(list); + } else { + DataForm *form = form_create(x); + ProfConfWin *confwin = (ProfConfWin*)wins_new_config(from, form, NULL, NULL, NULL); + confwin_handle_configuration(confwin, form); + } + } + } else if (g_strcmp0(status, "executing") == 0) { + win_handle_command_exec_status(win, command, "executing"); + + /* Looking for a jabber:x:data type form */ + xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(cmd, STANZA_NS_DATA); + if (x == NULL) { + return 0; + } + + const char *form_type = xmpp_stanza_get_type(x); + if (g_strcmp0(form_type, "form") != 0) { + log_error("Unsupported payload in command response"); + win_command_exec_error(win, command, "Unsupported command response"); + return 0; + } + const char *sessionid = xmpp_stanza_get_attribute(cmd, "sessionid"); + + DataForm *form = form_create(x); + CommandConfigData *data = malloc(sizeof(CommandConfigData)); + if (sessionid == NULL) { + data->sessionid = NULL; + } else { + data->sessionid = strdup(sessionid); + } + data->command = command; + ProfConfWin *confwin = (ProfConfWin*)wins_new_config(from, form, iq_submit_command_config, iq_cancel_command_config, data); + confwin_handle_configuration(confwin, form); + } else if (g_strcmp0(status, "canceled") == 0) { + win_handle_command_exec_status(win, command, "canceled"); + xmpp_stanza_t *note = xmpp_stanza_get_child_by_name(cmd, "note"); + if (note) { + const char *type = xmpp_stanza_get_attribute(note, "type"); + const char *value = xmpp_stanza_get_text(note); + win_handle_command_exec_result_note(win, type, value); + } + } else { + log_error("Unsupported command status %s", status); + win_command_exec_error(win, command, "Malformed command response"); + } + + return 0; +} + +static int _enable_carbons_id_handler(xmpp_stanza_t *const stanza, void *const userdata) { const char *type = xmpp_stanza_get_type(stanza); @@ -1088,8 +1331,8 @@ _autoping_timed_send(xmpp_conn_t *const conn, void *const userdata) return 1; } - if (connection_supports(STANZA_NS_PING) == FALSE) { - log_warning("Server doesn't advertise %s feature, disabling autoping.", STANZA_NS_PING); + if (connection_supports(XMPP_FEATURE_PING) == FALSE) { + log_warning("Server doesn't advertise %s feature, disabling autoping.", XMPP_FEATURE_PING); prefs_set_autoping(0); cons_show_error("Server ping not supported, autoping disabled."); xmpp_conn_t *conn = connection_get_conn(); @@ -1540,8 +1783,8 @@ _room_config_id_handler(xmpp_stanza_t *const stanza, void *const userdata) } DataForm *form = form_create(x); - ProfMucConfWin *confwin = (ProfMucConfWin*)wins_new_muc_config(from, form); - mucconfwin_handle_configuration(confwin, form); + ProfConfWin *confwin = (ProfConfWin*)wins_new_config(from, form, iq_submit_room_config, iq_room_config_cancel, NULL); + confwin_handle_configuration(confwin, form); return 0; } diff --git a/src/xmpp/iq.h b/src/xmpp/iq.h index b06568b6..025d5e9f 100644 --- a/src/xmpp/iq.h +++ b/src/xmpp/iq.h @@ -1,7 +1,7 @@ /* * iq.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/jid.c b/src/xmpp/jid.c index 0af54c72..51e1fa3c 100644 --- a/src/xmpp/jid.c +++ b/src/xmpp/jid.c @@ -1,7 +1,7 @@ /* * jid.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/jid.h b/src/xmpp/jid.h index e4e4d272..fc0e388f 100644 --- a/src/xmpp/jid.h +++ b/src/xmpp/jid.h @@ -1,7 +1,7 @@ /* * jid.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 9f665892..6a2197f3 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -1,7 +1,7 @@ /* * message.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -139,7 +139,7 @@ message_send_chat(const char *const barejid, const char *const msg, const char * char *state = chat_session_get_state(barejid); char *jid = chat_session_get_jid(barejid); - char *id = create_unique_id("msg"); + char *id = connection_create_stanza_id("msg"); xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id); xmpp_message_set_body(message, msg); @@ -170,7 +170,7 @@ message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean char *state = chat_session_get_state(barejid); char *jid = chat_session_get_jid(barejid); - char *id = create_unique_id("msg"); + char *id = connection_create_stanza_id("msg"); xmpp_stanza_t *message = NULL; #ifdef HAVE_LIBGPGME @@ -229,7 +229,7 @@ message_send_chat_otr(const char *const barejid, const char *const msg, gboolean char *state = chat_session_get_state(barejid); char *jid = chat_session_get_jid(barejid); - char *id = create_unique_id("msg"); + char *id = connection_create_stanza_id("msg"); xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, barejid, id); xmpp_message_set_body(message, msg); @@ -258,7 +258,7 @@ void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("prv"); + char *id = connection_create_stanza_id("prv"); xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, fulljid, id); xmpp_message_set_body(message, msg); @@ -277,7 +277,7 @@ void message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("muc"); + char *id = connection_create_stanza_id("muc"); xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, roomjid, id); xmpp_message_set_body(message, msg); @@ -584,7 +584,7 @@ _message_send_receipt(const char *const fulljid, const char *const message_id) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("receipt"); + char *id = connection_create_stanza_id("receipt"); xmpp_stanza_t *message = xmpp_message_new(ctx, NULL, fulljid, id); free(id); diff --git a/src/xmpp/message.h b/src/xmpp/message.h index 47bb17ed..dee9be2d 100644 --- a/src/xmpp/message.h +++ b/src/xmpp/message.h @@ -1,7 +1,7 @@ /* * message.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/muc.c b/src/xmpp/muc.c index 9f2f9f61..62a589d7 100644 --- a/src/xmpp/muc.c +++ b/src/xmpp/muc.c @@ -1,7 +1,7 @@ /* * muc.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/muc.h b/src/xmpp/muc.h index e50e2a87..e0b035f2 100644 --- a/src/xmpp/muc.h +++ b/src/xmpp/muc.h @@ -1,7 +1,7 @@ /* * muc.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index 8efb60e0..6d615de4 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -1,7 +1,7 @@ /* * presence.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -128,7 +128,7 @@ presence_subscription(const char *const jid, const jabber_subscr_t action) xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_stanza_t *presence = xmpp_presence_new(ctx); - char *id = create_unique_id("sub"); + char *id = connection_create_stanza_id("sub"); xmpp_stanza_set_id(presence, id); free(id); @@ -211,7 +211,7 @@ presence_send(const resource_presence_t presence_type, const int idle, char *sig xmpp_ctx_t * const ctx = connection_get_ctx(); xmpp_stanza_t *presence = xmpp_presence_new(ctx); - char *id = create_unique_id("presence"); + char *id = connection_create_stanza_id("presence"); xmpp_stanza_set_id(presence, id); free(id); @@ -579,7 +579,7 @@ _handle_caps(const char *const jid, XMPPCaps *caps) caps_map_jid_to_ver(jid, caps->ver); } else { log_info("Capabilities cache miss: %s, for %s, sending service discovery request", caps->ver, jid); - char *id = create_unique_id("caps"); + char *id = connection_create_stanza_id("caps"); iq_send_caps_request(jid, id, caps->node, caps->ver); free(id); } @@ -588,14 +588,14 @@ _handle_caps(const char *const jid, XMPPCaps *caps) // unsupported hash, xep-0115, associate with JID, no cache } else if (caps->hash) { log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid); - char *id = create_unique_id("caps"); + char *id = connection_create_stanza_id("caps"); iq_send_caps_request_for_jid(jid, id, caps->node, caps->ver); free(id); // no hash, legacy caps, cache against node#ver } else if (caps->node && caps->ver) { log_info("No hash specified: %s, legacy request made for %s#%s", jid, caps->node, caps->ver); - char *id = create_unique_id("caps"); + char *id = connection_create_stanza_id("caps"); iq_send_caps_request_legacy(jid, id, caps->node, caps->ver); free(id); } else { diff --git a/src/xmpp/presence.h b/src/xmpp/presence.h index 6045f72c..cbdfd20b 100644 --- a/src/xmpp/presence.h +++ b/src/xmpp/presence.h @@ -1,7 +1,7 @@ /* * presence.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/resource.c b/src/xmpp/resource.c index 734de3a0..fc6b503e 100644 --- a/src/xmpp/resource.c +++ b/src/xmpp/resource.c @@ -1,7 +1,7 @@ /* * resource.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/resource.h b/src/xmpp/resource.h index 9376a51c..ef934c2b 100644 --- a/src/xmpp/resource.h +++ b/src/xmpp/resource.h @@ -1,7 +1,7 @@ /* * resource.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index e7d9cfb2..9be154e7 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -1,7 +1,7 @@ /* * roster.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -75,9 +75,6 @@ static int _group_add_id_handler(xmpp_stanza_t *const stanza, void *const userda static int _group_remove_id_handler(xmpp_stanza_t *const stanza, void *const userdata); static void _free_group_data(GroupData *data); -// helper functions -GSList* _get_groups_from_item(xmpp_stanza_t *item); - void roster_request(void) { @@ -91,7 +88,7 @@ void roster_send_add_new(const char *const barejid, const char *const name) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("roster"); + char *id = connection_create_stanza_id("roster"); xmpp_stanza_t *iq = stanza_create_roster_set(ctx, id, barejid, name, NULL); free(id); iq_send_stanza(iq); @@ -111,7 +108,7 @@ void roster_send_name_change(const char *const barejid, const char *const new_name, GSList *groups) { xmpp_ctx_t * const ctx = connection_get_ctx(); - char *id = create_unique_id("roster"); + char *id = connection_create_stanza_id("roster"); xmpp_stanza_t *iq = stanza_create_roster_set(ctx, id, barejid, new_name, groups); free(id); iq_send_stanza(iq); @@ -130,7 +127,7 @@ roster_send_add_to_group(const char *const group, PContact contact) new_groups = g_slist_append(new_groups, strdup(group)); // add an id handler to handle the response - char *unique_id = create_unique_id(NULL); + char *unique_id = connection_create_stanza_id(NULL); GroupData *data = malloc(sizeof(GroupData)); data->group = strdup(group); if (p_contact_name(contact)) { @@ -174,7 +171,7 @@ roster_send_remove_from_group(const char *const group, PContact contact) xmpp_ctx_t * const ctx = connection_get_ctx(); // add an id handler to handle the response - char *unique_id = create_unique_id(NULL); + char *unique_id = connection_create_stanza_id(NULL); GroupData *data = malloc(sizeof(GroupData)); data->group = strdup(group); if (p_contact_name(contact)) { @@ -254,7 +251,7 @@ roster_set_handler(xmpp_stanza_t *const stanza) pending_out = TRUE; } - GSList *groups = _get_groups_from_item(item); + GSList *groups = roster_get_groups_from_item(item); // update the local roster PContact contact = roster_get_contact(barejid_lower); @@ -301,7 +298,7 @@ roster_result_handler(xmpp_stanza_t *const stanza) pending_out = TRUE; } - GSList *groups = _get_groups_from_item(item); + GSList *groups = roster_get_groups_from_item(item); gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out); if (!added) { @@ -318,7 +315,7 @@ roster_result_handler(xmpp_stanza_t *const stanza) } GSList* -_get_groups_from_item(xmpp_stanza_t *item) +roster_get_groups_from_item(xmpp_stanza_t *item) { GSList *groups = NULL; xmpp_stanza_t *group_element = xmpp_stanza_get_children(item); diff --git a/src/xmpp/roster.h b/src/xmpp/roster.h index 15614377..969044a4 100644 --- a/src/xmpp/roster.h +++ b/src/xmpp/roster.h @@ -1,7 +1,7 @@ /* * roster.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -38,5 +38,6 @@ void roster_request(void); void roster_set_handler(xmpp_stanza_t *const stanza); void roster_result_handler(xmpp_stanza_t *const stanza); +GSList* roster_get_groups_from_item(xmpp_stanza_t *const item); #endif diff --git a/src/xmpp/roster_list.c b/src/xmpp/roster_list.c index a2c5653d..5ebdc08f 100644 --- a/src/xmpp/roster_list.c +++ b/src/xmpp/roster_list.c @@ -1,7 +1,7 @@ /* * roster_list.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -73,8 +73,6 @@ static gboolean _key_equals(void *key1, void *key2); static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2); static void _replace_name(const char *const current_name, const char *const new_name, const char *const barejid); static void _add_name_and_barejid(const char *const name, const char *const barejid); -static gint _compare_name(PContact a, PContact b); -static gint _compare_presence(PContact a, PContact b); void roster_create(void) @@ -397,7 +395,7 @@ roster_get_contacts_by_presence(const char *const presence) while (g_hash_table_iter_next(&iter, &key, &value)) { PContact contact = (PContact)value; if (g_strcmp0(p_contact_presence(contact), presence) == 0) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); + result = g_slist_insert_sorted(result, value, (GCompareFunc)roster_compare_name); } } @@ -417,9 +415,9 @@ roster_get_contacts(roster_ord_t order) GCompareFunc cmp_func; if (order == ROSTER_ORD_PRESENCE) { - cmp_func = (GCompareFunc) _compare_presence; + cmp_func = (GCompareFunc) roster_compare_presence; } else { - cmp_func = (GCompareFunc) _compare_name; + cmp_func = (GCompareFunc) roster_compare_name; } g_hash_table_iter_init(&iter, roster->contacts); @@ -444,7 +442,7 @@ roster_get_contacts_online(void) g_hash_table_iter_init(&iter, roster->contacts); while (g_hash_table_iter_next(&iter, &key, &value)) { if(strcmp(p_contact_presence(value), "offline")) - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); + result = g_slist_insert_sorted(result, value, (GCompareFunc)roster_compare_name); } // return all contact structs @@ -499,9 +497,9 @@ roster_get_group(const char *const group, roster_ord_t order) GCompareFunc cmp_func; if (order == ROSTER_ORD_PRESENCE) { - cmp_func = (GCompareFunc) _compare_presence; + cmp_func = (GCompareFunc) roster_compare_presence; } else { - cmp_func = (GCompareFunc) _compare_name; + cmp_func = (GCompareFunc) roster_compare_name; } g_hash_table_iter_init(&iter, roster->contacts); @@ -605,8 +603,8 @@ _add_name_and_barejid(const char *const name, const char *const barejid) } } -static gint -_compare_name(PContact a, PContact b) +gint +roster_compare_name(PContact a, PContact b) { const char * utf8_str_a = NULL; const char * utf8_str_b = NULL; @@ -645,8 +643,8 @@ _get_presence_weight(const char *presence) } } -static gint -_compare_presence(PContact a, PContact b) +gint +roster_compare_presence(PContact a, PContact b) { const char *presence_a = p_contact_presence(a); const char *presence_b = p_contact_presence(b); @@ -663,6 +661,6 @@ _compare_presence(PContact a, PContact b) // otherwise order by name } else { - return _compare_name(a, b); + return roster_compare_name(a, b); } } diff --git a/src/xmpp/roster_list.h b/src/xmpp/roster_list.h index a0b01625..5120043c 100644 --- a/src/xmpp/roster_list.h +++ b/src/xmpp/roster_list.h @@ -1,7 +1,7 @@ /* * roster_list.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -70,5 +70,7 @@ char* roster_group_autocomplete(const char *const search_str, gboolean previous) char* roster_barejid_autocomplete(const char *const search_str, gboolean previous); GSList* roster_get_contacts_by_presence(const char *const presence); char* roster_get_msg_display_name(const char *const barejid, const char *const resource); +gint roster_compare_name(PContact a, PContact b); +gint roster_compare_presence(PContact a, PContact b); #endif diff --git a/src/xmpp/session.c b/src/xmpp/session.c index e06b03f1..de7fb7ac 100644 --- a/src/xmpp/session.c +++ b/src/xmpp/session.c @@ -1,7 +1,7 @@ /* * session.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/session.h b/src/xmpp/session.h index a3413e9e..53200939 100644 --- a/src/xmpp/session.h +++ b/src/xmpp/session.h @@ -1,7 +1,7 @@ /* * session.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 2f690828..534ee06b 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -1,7 +1,7 @@ /* * stanza.c * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -45,6 +45,7 @@ #include <stdio.h> #include <libgen.h> #include <inttypes.h> +#include <assert.h> #include <glib.h> @@ -66,6 +67,7 @@ #include "xmpp/muc.h" static void _stanza_add_unique_id(xmpp_stanza_t *stanza, char *prefix); +static char* _stanza_create_sha1_hash(char *str); #if 0 xmpp_stanza_t* @@ -132,7 +134,7 @@ xmpp_stanza_t* stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char *const jid, const gboolean autojoin, const char *const nick) { - char *id = create_unique_id("bookmark_add"); + char *id = connection_create_stanza_id("bookmark_add"); xmpp_stanza_t *stanza = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); @@ -278,7 +280,7 @@ stanza_create_http_upload_request(xmpp_ctx_t *ctx, const char *const id, xmpp_stanza_t* stanza_enable_carbons(xmpp_ctx_t *ctx) { - char *id = create_unique_id("carbons"); + char *id = connection_create_stanza_id("carbons"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); @@ -295,7 +297,7 @@ stanza_enable_carbons(xmpp_ctx_t *ctx) xmpp_stanza_t* stanza_disable_carbons(xmpp_ctx_t *ctx) { - char *id = create_unique_id("carbons"); + char *id = connection_create_stanza_id("carbons"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); @@ -312,7 +314,7 @@ stanza_disable_carbons(xmpp_ctx_t *ctx) xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx, const char *const fulljid, const char *const state) { - char *id = create_unique_id(NULL); + char *id = connection_create_stanza_id(NULL); xmpp_stanza_t *msg = xmpp_message_new(ctx, STANZA_TYPE_CHAT, fulljid, id); free(id); @@ -432,7 +434,7 @@ stanza_attach_x_oob_url(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char *cons xmpp_stanza_t* stanza_create_roster_remove_set(xmpp_ctx_t *ctx, const char *const barejid) { - char *id = create_unique_id("roster"); + char *id = connection_create_stanza_id("roster"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); @@ -498,7 +500,7 @@ xmpp_stanza_t* stanza_create_invite(xmpp_ctx_t *ctx, const char *const room, const char *const contact, const char *const reason, const char *const password) { - char *id = create_unique_id(NULL); + char *id = connection_create_stanza_id(NULL); xmpp_stanza_t *message = xmpp_message_new(ctx, NULL, contact, id); free(id); @@ -524,7 +526,7 @@ xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char *const room, const char *const contact, const char *const reason) { - char *id = create_unique_id(NULL); + char *id = connection_create_stanza_id(NULL); xmpp_stanza_t *message = xmpp_message_new(ctx, NULL, room, id); free(id); @@ -616,7 +618,7 @@ stanza_create_room_leave_presence(xmpp_ctx_t *ctx, const char *const room, xmpp_stanza_t* stanza_create_instant_room_request_iq(xmpp_ctx_t *ctx, const char *const room_jid) { - char *id = create_unique_id("room"); + char *id = connection_create_stanza_id("room"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room_jid); @@ -642,7 +644,7 @@ stanza_create_instant_room_request_iq(xmpp_ctx_t *ctx, const char *const room_ji xmpp_stanza_t* stanza_create_instant_room_destroy_iq(xmpp_ctx_t *ctx, const char *const room_jid) { - char *id = create_unique_id("room"); + char *id = connection_create_stanza_id("room"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room_jid); @@ -666,7 +668,7 @@ stanza_create_instant_room_destroy_iq(xmpp_ctx_t *ctx, const char *const room_ji xmpp_stanza_t* stanza_create_room_config_request_iq(xmpp_ctx_t *ctx, const char *const room_jid) { - char *id = create_unique_id("room"); + char *id = connection_create_stanza_id("room"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); free(id); xmpp_stanza_set_to(iq, room_jid); @@ -684,7 +686,7 @@ 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) { - char *id = create_unique_id("room"); + char *id = connection_create_stanza_id("room"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room_jid); @@ -710,7 +712,7 @@ stanza_create_room_config_cancel_iq(xmpp_ctx_t *ctx, const char *const room_jid) xmpp_stanza_t* stanza_create_room_affiliation_list_iq(xmpp_ctx_t *ctx, const char *const room, const char *const affiliation) { - char *id = create_unique_id("affiliation_get"); + char *id = connection_create_stanza_id("affiliation_get"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -734,7 +736,7 @@ stanza_create_room_affiliation_list_iq(xmpp_ctx_t *ctx, const char *const room, xmpp_stanza_t* stanza_create_room_role_list_iq(xmpp_ctx_t *ctx, const char *const room, const char *const role) { - char *id = create_unique_id("role_get"); + char *id = connection_create_stanza_id("role_get"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -759,7 +761,7 @@ 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) { - char *id = create_unique_id("affiliation_set"); + char *id = connection_create_stanza_id("affiliation_set"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -797,7 +799,7 @@ xmpp_stanza_t* stanza_create_room_role_set_iq(xmpp_ctx_t *const ctx, const char *const room, const char *const nick, const char *const role, const char *const reason) { - char *id = create_unique_id("role_set"); + char *id = connection_create_stanza_id("role_set"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -835,7 +837,7 @@ xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t *const ctx, const char *const room, const char *const nick, const char *const reason) { - char *id = create_unique_id("room_kick"); + char *id = connection_create_stanza_id("room_kick"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -872,7 +874,7 @@ stanza_create_room_kick_iq(xmpp_ctx_t *const ctx, const char *const room, const xmpp_stanza_t* stanza_create_software_version_iq(xmpp_ctx_t *ctx, const char *const fulljid) { - char *id = create_unique_id("sv"); + char *id = connection_create_stanza_id("sv"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); free(id); xmpp_stanza_set_to(iq, fulljid); @@ -924,7 +926,7 @@ stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char *const id, const char *c xmpp_stanza_t* stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char *const id, - const char *const jid) + const char *const jid, const char *const node) { xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); xmpp_stanza_set_to(iq, jid); @@ -932,6 +934,9 @@ stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char *const id, xmpp_stanza_t *query = xmpp_stanza_new(ctx); xmpp_stanza_set_name(query, STANZA_NAME_QUERY); xmpp_stanza_set_ns(query, XMPP_NS_DISCO_ITEMS); + if (node) { + xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node); + } xmpp_stanza_add_child(iq, query); xmpp_stanza_release(query); @@ -958,7 +963,7 @@ stanza_create_last_activity_iq(xmpp_ctx_t *ctx, const char *const id, const char xmpp_stanza_t* stanza_create_room_config_submit_iq(xmpp_ctx_t *ctx, const char *const room, DataForm *form) { - char *id = create_unique_id("roomconf_submit"); + char *id = connection_create_stanza_id("roomconf_submit"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); free(id); xmpp_stanza_set_to(iq, room); @@ -1035,7 +1040,7 @@ stanza_contains_chat_state(xmpp_stanza_t *stanza) xmpp_stanza_t* stanza_create_ping_iq(xmpp_ctx_t *ctx, const char *const target) { - char *id = create_unique_id("ping"); + char *id = connection_create_stanza_id("ping"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); free(id); if (target) { @@ -1143,7 +1148,7 @@ stanza_create_caps_sha1_from_query(xmpp_stanza_t *const query) curr = g_slist_next(curr); } - char *result = p_sha1_hash(s->str); + char *result = _stanza_create_sha1_hash(s->str); g_string_free(s, TRUE); g_slist_free_full(identities, g_free); @@ -2038,10 +2043,74 @@ stanza_parse_presence(xmpp_stanza_t *stanza, int *err) return result; } +xmpp_stanza_t* +stanza_create_command_exec_iq(xmpp_ctx_t *ctx, const char *const target, + const char *const node) +{ + char *id = connection_create_stanza_id("cmdexec"); + xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + free(id); + xmpp_stanza_set_to(iq, target); + + xmpp_stanza_t *command = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(command, STANZA_NAME_COMMAND); + + xmpp_stanza_set_ns(command, STANZA_NS_COMMAND); + xmpp_stanza_set_attribute(command, "node", node); + xmpp_stanza_set_attribute(command, "action", "execute"); + + xmpp_stanza_add_child(iq, command); + xmpp_stanza_release(command); + + return iq; +} + +xmpp_stanza_t* +stanza_create_command_config_submit_iq(xmpp_ctx_t *ctx, const char *const room, + const char *const node, const char *const sessionid, DataForm *form) +{ + char *id = connection_create_stanza_id("commandconf_submit"); + xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + free(id); + xmpp_stanza_set_to(iq, room); + + xmpp_stanza_t *command = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(command, STANZA_NAME_COMMAND); + xmpp_stanza_set_ns(command, STANZA_NS_COMMAND); + xmpp_stanza_set_attribute(command, "node", node); + if (sessionid != NULL) { + xmpp_stanza_set_attribute(command, "sessionid", sessionid); + } + + xmpp_stanza_t *x = form_create_submission(form); + xmpp_stanza_add_child(command, x); + xmpp_stanza_release(x); + + xmpp_stanza_add_child(iq, command); + xmpp_stanza_release(command); + + return iq; +} + static void _stanza_add_unique_id(xmpp_stanza_t *stanza, char *prefix) { - char *id = create_unique_id(prefix); + char *id = connection_create_stanza_id(prefix); xmpp_stanza_set_id(stanza, id); free(id); } + +static char* +_stanza_create_sha1_hash(char *str) +{ + unsigned char *digest = (unsigned char*)malloc(XMPP_SHA1_DIGEST_SIZE); + assert(digest != NULL); + + xmpp_sha1_digest((unsigned char*)str, strlen(str), digest); + + char *b64 = g_base64_encode(digest, XMPP_SHA1_DIGEST_SIZE); + assert(b64 != NULL); + free(digest); + + return b64; +} diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index bd161616..d3c3c9dc 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -1,7 +1,7 @@ /* * stanza.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -99,6 +99,7 @@ #define STANZA_NAME_PUT "put" #define STANZA_NAME_GET "get" #define STANZA_NAME_URL "url" +#define STANZA_NAME_COMMAND "command" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -156,6 +157,7 @@ #define STANZA_ATTR_REASON "reason" #define STANZA_ATTR_AUTOJOIN "autojoin" #define STANZA_ATTR_PASSWORD "password" +#define STANZA_ATTR_STATUS "status" #define STANZA_TEXT_AWAY "away" #define STANZA_TEXT_DND "dnd" @@ -186,6 +188,7 @@ #define STANZA_NS_HTTP_UPLOAD "urn:xmpp:http:upload" #define STANZA_NS_X_OOB "jabber:x:oob" #define STANZA_NS_BLOCKING "urn:xmpp:blocking" +#define STANZA_NS_COMMAND "http://jabber.org/protocol/commands" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -278,6 +281,9 @@ xmpp_stanza_t* stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char *c xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t *const ctx, const char *const room, const char *const nick, const char *const reason); +xmpp_stanza_t* stanza_create_command_exec_iq(xmpp_ctx_t *ctx, const char *const target, const char *const node); +xmpp_stanza_t* stanza_create_command_config_submit_iq(xmpp_ctx_t *ctx, const char *const room, const char *const node, const char *const sessionid, DataForm *form); + int stanza_get_idle_time(xmpp_stanza_t *const stanza); void stanza_attach_priority(xmpp_ctx_t *const ctx, xmpp_stanza_t *const presence, const int pri); @@ -292,7 +298,7 @@ EntityCapabilities* stanza_create_caps_from_query_element(xmpp_stanza_t *query); const char* stanza_get_presence_string_from_type(resource_presence_t presence_type); xmpp_stanza_t* stanza_create_software_version_iq(xmpp_ctx_t *ctx, const char *const fulljid); -xmpp_stanza_t* stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char *const id, const char *const jid); +xmpp_stanza_t* stanza_create_disco_items_iq(xmpp_ctx_t *ctx, const char *const id, const char *const jid, const char *const node); char* stanza_get_status(xmpp_stanza_t *stanza, char *def); char* stanza_get_show(xmpp_stanza_t *stanza, char *def); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index d4a29196..c9403090 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -1,7 +1,7 @@ /* * xmpp.h * - * Copyright (C) 2012 - 2018 James Booth <boothj5@gmail.com> + * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com> * * This file is part of Profanity. * @@ -60,6 +60,7 @@ #define XMPP_FEATURE_RECEIPTS "urn:xmpp:receipts" #define XMPP_FEATURE_LASTACTIVITY "jabber:iq:last" #define XMPP_FEATURE_MUC "http://jabber.org/protocol/muc" +#define XMPP_FEATURE_COMMANDS "http://jabber.org/protocol/commands" typedef enum { JABBER_CONNECTING, @@ -170,8 +171,8 @@ void iq_set_autoping(int seconds); void iq_confirm_instant_room(const char *const room_jid); void iq_destroy_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_submit_room_config(ProfConfWin *confwin); +void iq_room_config_cancel(ProfConfWin *confwin); void iq_send_ping(const char *const target); void iq_room_info_request(const char *const room, gboolean display_result); void iq_room_affiliation_list(const char *const room, char *affiliation); @@ -182,6 +183,8 @@ void iq_room_role_set(const char *const room, const char *const nick, char *role void iq_room_role_list(const char * const room, char *role); void iq_autoping_check(void); void iq_http_upload_request(HTTPUpload *upload); +void iq_command_list(const char *const target); +void iq_command_exec(const char *const target, const char *const command); EntityCapabilities* caps_lookup(const char *const jid); void caps_close(void); |