diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 765ef448..48d712e4 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -277,6 +277,7 @@ static Autocomplete correction_ac; static Autocomplete avatar_ac; static Autocomplete url_ac; static Autocomplete executable_ac; +static Autocomplete executable_param_ac; static Autocomplete intype_ac; static Autocomplete mood_ac; static Autocomplete mood_type_ac; @@ -1115,6 +1116,11 @@ cmd_ac_init(void) autocomplete_add(executable_ac, "urlopen"); autocomplete_add(executable_ac, "urlsave"); autocomplete_add(executable_ac, "editor"); + autocomplete_add(executable_ac, "vcard_photo"); + + executable_param_ac = autocomplete_new(); + autocomplete_add(executable_param_ac, "set"); + autocomplete_add(executable_param_ac, "default"); intype_ac = autocomplete_new(); autocomplete_add(intype_ac, "console"); @@ -1701,6 +1707,7 @@ cmd_ac_reset(ProfWin* window) autocomplete_reset(avatar_ac); autocomplete_reset(url_ac); autocomplete_reset(executable_ac); + autocomplete_reset(executable_param_ac); autocomplete_reset(intype_ac); autocomplete_reset(mood_ac); autocomplete_reset(mood_type_ac); @@ -1888,6 +1895,7 @@ cmd_ac_uninit(void) autocomplete_free(avatar_ac); autocomplete_free(url_ac); autocomplete_free(executable_ac); + autocomplete_free(executable_param_ac); autocomplete_free(intype_ac); autocomplete_free(adhoc_cmd_ac); autocomplete_free(lastactivity_ac); @@ -4379,6 +4387,31 @@ _executable_autocomplete(ProfWin* window, const char* const input, gboolean prev { char* result = NULL; + result = autocomplete_param_with_ac(input, "/executable avatar", executable_param_ac, TRUE, previous); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/executable urlopen", executable_param_ac, TRUE, previous); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/executable urlsave", executable_param_ac, TRUE, previous); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/executable vcard_photo", executable_param_ac, TRUE, previous); + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/executable editor", executable_param_ac, TRUE, previous); + if (result) { + return result; + } + result = autocomplete_param_with_ac(input, "/executable", executable_ac, TRUE, previous); return result; diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index c6e886a5..9828ab1a 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2437,7 +2437,7 @@ static const struct cmd_t command_defs[] = { { "set ", "Set avatar to the image at ." }, { "disable", "Disable avatar publishing; your avatar will not display to others." }, { "get ", "Download the avatar. barejid is the JID to download avatar from." }, - { "open ", "Download avatar and open it with command." }) + { "open ", "Download avatar and open it with command. See /executable." }) CMD_EXAMPLES( "/avatar set ~/images/avatar.png", "/avatar disable", @@ -2534,23 +2534,27 @@ static const struct cmd_t command_defs[] = { CMD_TAGS( CMD_TAG_DISCOVERY) CMD_SYN( - "/executable avatar ", + "/executable avatar set ", + "/executable avatar default", "/executable urlopen set ", "/executable urlopen default", "/executable urlsave set ", "/executable urlsave default", "/executable editor set ", + "/executable editor default", "/executable vcard_photo set ", "/executable vcard_photo default") CMD_DESC( "Configure executable that should be called upon a certain command.") CMD_ARGS( - { "avatar", "Set executable that is run by /avatar open. Use your favorite image viewer." }, + { "avatar set", "Set executable that is run by /avatar open. Use your favorite image viewer." }, + { "avatar default", "Restore to default settings." }, { "urlopen set", "Set executable that is run by /url open. Takes a command template that replaces %u and %p with the URL and path respectively." }, { "urlopen default", "Restore to default settings." }, { "urlsave set", "Set executable that is run by /url save. Takes a command template that replaces %u and %p with the URL and path respectively." }, { "urlsave default", "Use the built-in download method for saving." }, { "editor set", "Set editor to be used with /editor. Needs a terminal editor or a script to run a graphical editor." }, + { "editor default", "Restore to default settings." }, { "vcard_photo set", "Set executable that is run by /vcard photo open. Takes a command template that replaces %p with the path" }, { "vcard_photo default", "Restore to default settings." }) CMD_EXAMPLES( diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 83c594f5..bb6cc49d 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -6575,7 +6575,8 @@ cmd_reconnect(ProfWin* window, const char* const command, gchar** args) int intval = 0; char* err_msg = NULL; if (g_strcmp0(value, "now") == 0) { - session_reconnect_now(); + cons_show("Reconnecting now."); + cl_ev_reconnect(); } else if (strtoi_range(value, &intval, 0, INT_MAX, &err_msg)) { prefs_set_reconnect(intval); if (intval == 0) { @@ -9309,9 +9310,6 @@ cmd_avatar(ProfWin* window, const char* const command, gchar** args) avatar_get_by_nick(args[1], false); } else if (g_strcmp0(args[0], "open") == 0) { avatar_get_by_nick(args[1], true); - } else if (g_strcmp0(args[0], "cmd") == 0) { - prefs_set_string(PREF_AVATAR_CMD, args[1]); - cons_show("Avatar cmd set to: %s", args[1]); } else { cons_bad_cmd_usage(command); } @@ -9620,15 +9618,7 @@ out: } gboolean -cmd_executable_avatar(ProfWin* window, const char* const command, gchar** args) -{ - prefs_set_string(PREF_AVATAR_CMD, args[1]); - cons_show("`avatar` command set to invoke '%s'", args[1]); - return TRUE; -} - -gboolean -cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args) +_cmd_executable_template(const preference_t setting, const char* command, gchar** args) { guint num_args = g_strv_length(args); if (num_args < 2) { @@ -9638,14 +9628,17 @@ cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args) if (g_strcmp0(args[1], "set") == 0 && num_args >= 3) { gchar* str = g_strjoinv(" ", &args[2]); - prefs_set_string(PREF_URL_OPEN_CMD, str); - cons_show("`url open` command set to invoke '%s'", str); + prefs_set_string(setting, str); + cons_show("`%s` command set to invoke '%s'", command, str); g_free(str); } else if (g_strcmp0(args[1], "default") == 0) { - prefs_set_string(PREF_URL_OPEN_CMD, NULL); - gchar* def = prefs_get_string(PREF_URL_OPEN_CMD); - cons_show("`url open` command set to invoke %s (default)", def); + prefs_set_string(setting, NULL); + gchar* def = prefs_get_string(setting); + if (def == NULL) { + def = g_strdup("built-in method"); + } + cons_show("`%s` command set to invoke %s (default)", command, def); g_free(def); } else { cons_bad_cmd_usage(command); @@ -9654,63 +9647,36 @@ cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args) return TRUE; } +gboolean +cmd_executable_avatar(ProfWin* window, const char* const command, gchar** args) +{ + return _cmd_executable_template(PREF_AVATAR_CMD, args[0], args); +} + +gboolean +cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args) +{ + return _cmd_executable_template(PREF_URL_OPEN_CMD, args[0], args); +} + gboolean cmd_executable_urlsave(ProfWin* window, const char* const command, gchar** args) { - - guint num_args = g_strv_length(args); - if (num_args < 2) { - cons_bad_cmd_usage(command); - return TRUE; - } - - if (g_strcmp0(args[1], "set") == 0 && num_args >= 3) { - gchar* str = g_strjoinv(" ", &args[2]); - prefs_set_string(PREF_URL_SAVE_CMD, str); - cons_show("`url save` command set to invoke '%s'", str); - g_free(str); - - } else if (g_strcmp0(args[1], "default") == 0) { - prefs_set_string(PREF_URL_SAVE_CMD, NULL); - cons_show("`url save` will use built-in download method (default)"); - } else { - cons_bad_cmd_usage(command); - } - - return TRUE; + return _cmd_executable_template(PREF_URL_SAVE_CMD, args[0], args); } gboolean cmd_executable_editor(ProfWin* window, const char* const command, gchar** args) { - guint num_args = g_strv_length(args); - - if (g_strcmp0(args[1], "set") == 0 && num_args >= 3) { - prefs_set_string(PREF_COMPOSE_EDITOR, args[2]); - cons_show("`editor` command set to invoke '%s'", args[2]); - } else { - cons_bad_cmd_usage(command); - } - - return TRUE; + return _cmd_executable_template(PREF_COMPOSE_EDITOR, args[0], args); } gboolean cmd_executable_vcard_photo(ProfWin* window, const char* const command, gchar** args) { - if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) { - prefs_set_string(PREF_VCARD_PHOTO_CMD, args[2]); - cons_show("`vcard photo open` command set to invoke '%s'", args[2]); - } else if (g_strcmp0(args[1], "default") == 0) { - prefs_set_string(PREF_VCARD_PHOTO_CMD, NULL); - auto_gchar gchar* cmd = prefs_get_string(PREF_VCARD_PHOTO_CMD); - cons_show("`vcard photo open` command set to invoke '%s' (default)", cmd); - } else { - cons_bad_cmd_usage(command); - } - - return TRUE; + return _cmd_executable_template(PREF_VCARD_PHOTO_CMD, args[0], args); } + gboolean cmd_mam(ProfWin* window, const char* const command, gchar** args) { diff --git a/src/config/preferences.c b/src/config/preferences.c index 23709747..c10f4d83 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -2297,7 +2297,7 @@ _get_default_string(preference_t pref) case PREF_COLOR_NICK: return "false"; case PREF_AVATAR_CMD: - return "xdg-open"; + return "xdg-open %p"; case PREF_URL_OPEN_CMD: return "xdg-open %u"; case PREF_VCARD_PHOTO_CMD: diff --git a/src/event/client_events.c b/src/event/client_events.c index 67ffec20..c393ccd4 100644 --- a/src/event/client_events.c +++ b/src/event/client_events.c @@ -47,6 +47,7 @@ #include "plugins/plugins.h" #include "ui/window_list.h" #include "xmpp/chat_session.h" +#include "xmpp/session.h" #include "xmpp/xmpp.h" #ifdef HAVE_LIBOTR @@ -85,9 +86,8 @@ cl_ev_connect_account(ProfAccount* account) void cl_ev_disconnect(void) { - char* mybarejid = connection_get_barejid(); + auto_char char* mybarejid = connection_get_barejid(); cons_show("%s logged out successfully.", mybarejid); - free(mybarejid); ui_close_all_wins(); ev_disconnect_cleanup(); @@ -95,6 +95,18 @@ cl_ev_disconnect(void) ev_reset_connection_counter(); } +void +cl_ev_reconnect(void) +{ + if (connection_get_status() != JABBER_DISCONNECTED) { + connection_disconnect(); + ev_disconnect_cleanup(); + // on intentional disconnect reset the counter + ev_reset_connection_counter(); + } + session_reconnect_now(); +} + void cl_ev_presence_send(const resource_presence_t presence_type, const int idle_secs) { diff --git a/src/event/client_events.h b/src/event/client_events.h index fed2bb37..a35e97b5 100644 --- a/src/event/client_events.h +++ b/src/event/client_events.h @@ -42,6 +42,7 @@ jabber_conn_status_t cl_ev_connect_jid(const char* const jid, const char* const jabber_conn_status_t cl_ev_connect_account(ProfAccount* account); void cl_ev_disconnect(void); +void cl_ev_reconnect(void); void cl_ev_presence_send(const resource_presence_t presence_type, const int idle_secs); diff --git a/src/event/server_events.c b/src/event/server_events.c index 01002a1e..c10f69c3 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -1332,8 +1332,8 @@ sv_ev_bookmark_autojoin(Bookmark* bookmark) log_debug("Autojoin %s with nick=%s", bookmark->barejid, nick); if (!muc_active(bookmark->barejid)) { - presence_join_room(bookmark->barejid, nick, bookmark->password); muc_join(bookmark->barejid, nick, bookmark->password, TRUE); + presence_join_room(bookmark->barejid, nick, bookmark->password); iq_room_affiliation_list(bookmark->barejid, "member", false); iq_room_affiliation_list(bookmark->barejid, "admin", false); iq_room_affiliation_list(bookmark->barejid, "owner", false); diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index eef395f1..2a022cc4 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -964,6 +964,7 @@ _connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status conn.domain = strdup(my_jid->domainpart); jid_destroy(my_jid); + connection_clear_data(); conn.features_by_jid = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_hash_table_destroy); g_hash_table_insert(conn.features_by_jid, strdup(conn.domain), g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL)); @@ -990,6 +991,7 @@ _connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status conn.domain = strdup(my_raw_jid->domainpart); jid_destroy(my_raw_jid); + connection_clear_data(); conn.features_by_jid = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_hash_table_destroy); g_hash_table_insert(conn.features_by_jid, strdup(conn.domain), g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL)); diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index 79bee1d4..d4ade03a 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -48,7 +48,6 @@ jabber_conn_status_t connection_connect(const char* const fulljid, const char* c const char* const tls_policy, const char* const auth_policy); jabber_conn_status_t connection_register(const char* const altdomain, int port, const char* const tls_policy, const char* const username, const char* const password); -void connection_disconnect(void); void connection_set_disconnected(void); void connection_set_priority(const int priority); diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index f09deead..4f6eea40 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -265,6 +265,7 @@ iq_handlers_init(void) xmpp_timed_handler_add(conn, _autoping_timed_send, millis, ctx); } + iq_rooms_cache_clear(); iq_handlers_clear(); id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_iq_id_handler_free); @@ -2651,6 +2652,18 @@ iq_mam_request_older(ProfChatWin* win) return; } +static void +_mam_userdata_free(MamRsmUserdata* data) +{ + free(data->end_datestr); + data->end_datestr = NULL; + free(data->start_datestr); + data->start_datestr = NULL; + free(data->barejid); + data->barejid = NULL; + free(data); +} + void _iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate) { @@ -2694,7 +2707,7 @@ _iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate) data->fetch_next = fetch_next; data->win = win; - iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data); + iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, (ProfIqFreeCallback)_mam_userdata_free, data); } iq_send_stanza(iq); @@ -2742,13 +2755,13 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) buffer_remove_entry(window->layout->buffer, 0); - char* start_str = NULL; + auto_char char* start_str = NULL; if (data->start_datestr) { start_str = strdup(data->start_datestr); // Convert to iso8601 start_str[strlen(start_str) - 3] = '\0'; } - char* end_str = NULL; + auto_char char* end_str = NULL; if (data->end_datestr) { end_str = strdup(data->end_datestr); // Convert to iso8601 @@ -2757,24 +2770,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) if (is_complete || !data->fetch_next) { chatwin_db_history(data->win, is_complete ? NULL : start_str, end_str, TRUE); - // TODO free memory - if (start_str) { - free(start_str); - free(data->start_datestr); - } - - if (end_str) { - free(data->end_datestr); - } - - free(data->barejid); - free(data); return 0; } chatwin_db_history(data->win, start_str, end_str, TRUE); - if (start_str) - free(start_str); xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); if (set) { @@ -2787,14 +2786,14 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) // 4.3.2. send same stanza with set,max stanza xmpp_ctx_t* const ctx = connection_get_ctx(); - if (end_str) { + if (data->end_datestr) { free(data->end_datestr); + data->end_datestr = NULL; } - data->end_datestr = NULL; - xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, firstid, NULL); + xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, NULL, firstid, NULL); free(firstid); - iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data); + iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, (ProfIqFreeCallback)_mam_userdata_free, data); iq_send_stanza(iq); xmpp_stanza_release(iq); diff --git a/src/xmpp/session.h b/src/xmpp/session.h index e6facb93..d8565fa4 100644 --- a/src/xmpp/session.h +++ b/src/xmpp/session.h @@ -47,6 +47,5 @@ void session_init_activity(void); void session_check_autoaway(void); void session_reconnect(gchar* altdomain, unsigned short altport); -void session_reconnect_now(void); #endif diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 539126cd..2babe536 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -186,7 +186,9 @@ void session_disconnect(void); void session_shutdown(void); void session_process_events(void); char* session_get_account_name(void); +void session_reconnect_now(void); +void connection_disconnect(void); jabber_conn_status_t connection_get_status(void); char* connection_get_presence_msg(void); void connection_set_presence_msg(const char* const message); diff --git a/tests/unittests/xmpp/stub_xmpp.c b/tests/unittests/xmpp/stub_xmpp.c index a7dc9ebf..ffa7565d 100644 --- a/tests/unittests/xmpp/stub_xmpp.c +++ b/tests/unittests/xmpp/stub_xmpp.c @@ -54,6 +54,10 @@ void session_process_events(void) { } +void +connection_disconnect(void) +{ +} const char* connection_get_fulljid(void) {