diff --git a/src/command/command.c b/src/command/command.c index e8232405..f7737464 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -20,6 +20,7 @@ * */ +#include #include #include #include @@ -68,6 +69,7 @@ typedef struct cmd_t { typedef char*(*autocompleter)(char*, int*); +static char * _ask_password(void); static void _update_presence(const resource_presence_t presence, const char * const show, gchar **args); static gboolean _cmd_set_boolean_preference(gchar *arg, struct cmd_help_t help, @@ -92,6 +94,7 @@ static int _strtoi(char *str, int *saveptr, int min, int max); static gboolean _cmd_about(gchar **args, struct cmd_help_t help); static gboolean _cmd_account(gchar **args, struct cmd_help_t help); static gboolean _cmd_autoaway(gchar **args, struct cmd_help_t help); +static gboolean _cmd_autoconnect(gchar **args, struct cmd_help_t help); static gboolean _cmd_autoping(gchar **args, struct cmd_help_t help); static gboolean _cmd_away(gchar **args, struct cmd_help_t help); static gboolean _cmd_beep(gchar **args, struct cmd_help_t help); @@ -577,6 +580,16 @@ static struct cmd_t command_defs[] = "Switch on or off the ascii logo on start up and when the /about command is called.", NULL } } }, + { "/autoconnect", + _cmd_autoconnect, parse_args, 0, 1, cons_autoconnect_setting, + { "/autoconnect [account]", "Set account to autoconnect with.", + { "/autoconnect [account]", + "----------------------", + "Set the account to autoconnect with.", + "Will be overridden by any command line options specified.", + "Passing no account will clear the setting.", + NULL } } }, + { "/vercheck", _cmd_vercheck, parse_args, 0, 1, NULL, { "/vercheck [on|off]", "Check for a new release.", @@ -746,6 +759,7 @@ static struct cmd_t command_defs[] = "online|chat|away", "|xa|dnd : Priority for the specified presence.", "resource : The resource to be used.", + "password : Password for the account, note this is currently stored in plaintext if set.", "muc : The default MUC chat service to use.", "nick : The default nickname to use when joining chat rooms.", "", @@ -1300,6 +1314,13 @@ _cmd_complete_parameters(char *input, int *size) return; } + result = autocomplete_param_with_func(input, size, "/autoconnect", accounts_find_enabled); + if (result != NULL) { + inp_replace_input(input, result, size); + g_free(result); + return; + } + gchar *cmds[] = { "/help", "/prefs", "/log", "/disco", "/close", "/wins" }; Autocomplete completers[] = { help_ac, prefs_ac, log_ac, disco_ac, close_ac, wins_ac }; @@ -1347,13 +1368,6 @@ _cmd_connect(gchar **args, struct cmd_help_t help) char *lower = g_utf8_strdown(user, -1); char *jid; - status_bar_get_password(); - status_bar_refresh(); - char passwd[21]; - inp_block(); - inp_get_password(passwd); - inp_non_block(); - ProfAccount *account = accounts_get_account(lower); if (account != NULL) { if (account->resource != NULL) { @@ -1361,12 +1375,18 @@ _cmd_connect(gchar **args, struct cmd_help_t help) } else { jid = strdup(account->jid); } + + if (account->password == NULL) { + account->password = _ask_password(); + } cons_show("Connecting with account %s as %s", account->name, jid); - conn_status = jabber_connect_with_account(account, passwd); + conn_status = jabber_connect_with_account(account); } else { + char *passwd = _ask_password(); jid = strdup(lower); cons_show("Connecting as %s", jid); conn_status = jabber_connect_with_details(jid, passwd, altdomain); + free(passwd); } g_free(lower); @@ -1499,6 +1519,10 @@ _cmd_account(gchar **args, struct cmd_help_t help) accounts_set_resource(account_name, value); cons_show("Updated resource for account %s: %s", account_name, value); cons_show(""); + } else if (strcmp(property, "password") == 0) { + accounts_set_password(account_name, value); + cons_show("Updated password for account %s", account_name); + cons_show(""); } else if (strcmp(property, "muc") == 0) { accounts_set_muc_service(account_name, value); cons_show("Updated muc service for account %s: %s", account_name, value); @@ -1808,7 +1832,7 @@ _cmd_help(gchar **args, struct cmd_help_t help) _cmd_show_filtered_help("Service discovery commands", filter, ARRAY_SIZE(filter)); } else if (strcmp(args[0], "settings") == 0) { - gchar *filter[] = { "/account", "/autoaway", "/autoping", "/beep", + gchar *filter[] = { "/account", "/autoaway", "/autoping", "/autoconnect", "/beep", "/chlog", "/flash", "/gone", "/grlog", "/history", "/intype", "/log", "/mouse", "/notify", "/outtype", "/prefs", "/priority", "/reconnect", "/roster", "/splash", "/states", "/statuses", "/theme", @@ -3446,6 +3470,19 @@ _cmd_splash(gchar **args, struct cmd_help_t help) "Splash screen", PREF_SPLASH); } +static gboolean +_cmd_autoconnect(gchar **args, struct cmd_help_t help) +{ + if (args[0] == NULL) { + prefs_set_string(PREF_CONNECT_ACCOUNT, NULL); + cons_show("Autoconnect account disabled."); + } else { + prefs_set_string(PREF_CONNECT_ACCOUNT, args[0]); + cons_show("Autoconnect account set to: %s.", args[0]); + } + return true; +} + static gboolean _cmd_chlog(gchar **args, struct cmd_help_t help) { @@ -3525,6 +3562,20 @@ _cmd_xa(gchar **args, struct cmd_help_t help) return TRUE; } +// helper function that asks the user for a password and saves it in passwd + +static char * +_ask_password(void) { + char *passwd = malloc(sizeof(char) * (MAX_PASSWORD_SIZE + 1)); + status_bar_get_password(); + status_bar_refresh(); + inp_block(); + inp_get_password(passwd); + inp_non_block(); + + return passwd; +} + // helper function for status change commands static void diff --git a/src/config/accounts.c b/src/config/accounts.c index 4eb4b8e3..6bfc7bef 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -39,10 +39,12 @@ static GKeyFile *accounts; static Autocomplete all_ac; static Autocomplete enabled_ac; +// used to rename account (copies properties to new account) static gchar *string_keys[] = { "jid", "server", "resource", + "password", "presence.last", "presence.login", "muc.service", @@ -191,6 +193,14 @@ accounts_get_account(const char * const name) _save_accounts(); } + gchar *password = g_key_file_get_string(accounts, name, "password", NULL); + if (password != NULL) { + account->password = strdup(password); + g_free(password); + } else { + account->password = NULL; + } + account->enabled = g_key_file_get_boolean(accounts, name, "enabled", NULL); gchar *server = g_key_file_get_string(accounts, name, "server", NULL); @@ -288,6 +298,7 @@ accounts_free_account(ProfAccount *account) if (account != NULL) { free(account->name); free(account->jid); + free(account->password); free(account->resource); free(account->server); free(account->last_presence); @@ -339,16 +350,17 @@ accounts_rename(const char * const account_name, const char * const new_name) g_key_file_get_boolean(accounts, account_name, "enabled", NULL)); g_key_file_set_integer(accounts, new_name, "priority.online", - g_key_file_get_boolean(accounts, account_name, "priority.online", NULL)); + g_key_file_get_integer(accounts, account_name, "priority.online", NULL)); g_key_file_set_integer(accounts, new_name, "priority.chat", - g_key_file_get_boolean(accounts, account_name, "priority.chat", NULL)); + g_key_file_get_integer(accounts, account_name, "priority.chat", NULL)); g_key_file_set_integer(accounts, new_name, "priority.away", - g_key_file_get_boolean(accounts, account_name, "priority.away", NULL)); + g_key_file_get_integer(accounts, account_name, "priority.away", NULL)); g_key_file_set_integer(accounts, new_name, "priority.xa", - g_key_file_get_boolean(accounts, account_name, "priority.xa", NULL)); + g_key_file_get_integer(accounts, account_name, "priority.xa", NULL)); g_key_file_set_integer(accounts, new_name, "priority.dnd", - g_key_file_get_boolean(accounts, account_name, "priority.dnd", NULL)); + g_key_file_get_integer(accounts, account_name, "priority.dnd", NULL)); + // copy other string properties int i; for (i = 0; i < ARRAY_SIZE(string_keys); i++) { char *value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL); @@ -422,6 +434,15 @@ accounts_set_resource(const char * const account_name, const char * const value) } } +void +accounts_set_password(const char * const account_name, const char * const value) +{ + if (accounts_account_exists(account_name)) { + g_key_file_set_string(accounts, account_name, "password", value); + _save_accounts(); + } +} + void accounts_set_muc_service(const char * const account_name, const char * const value) { diff --git a/src/config/accounts.h b/src/config/accounts.h index 4c74a523..118b5c80 100644 --- a/src/config/accounts.h +++ b/src/config/accounts.h @@ -23,11 +23,14 @@ #ifndef ACCOUNTS_H #define ACCOUNTS_H +#define MAX_PASSWORD_SIZE 64 + #include "common.h" typedef struct prof_account_t { gchar *name; gchar *jid; + gchar *password; gchar *resource; gchar *server; gchar *last_presence; @@ -62,6 +65,7 @@ gboolean accounts_account_exists(const char * const account_name); void accounts_set_jid(const char * const account_name, const char * const value); void accounts_set_server(const char * const account_name, const char * const value); void accounts_set_resource(const char * const account_name, const char * const value); +void accounts_set_password(const char * const account_name, const char * const value); void accounts_set_muc_service(const char * const account_name, const char * const value); void accounts_set_muc_nick(const char * const account_name, const char * const value); void accounts_set_last_presence(const char * const account_name, const char * const value); diff --git a/src/config/preferences.c b/src/config/preferences.c index 1d417e41..18f10dee 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -309,6 +309,8 @@ _get_group(preference_t pref) case PREF_AUTOAWAY_MODE: case PREF_AUTOAWAY_MESSAGE: return "presence"; + case PREF_CONNECT_ACCOUNT: + return "connection"; default: return NULL; } @@ -361,6 +363,8 @@ _get_key(preference_t pref) return "autoaway.mode"; case PREF_AUTOAWAY_MESSAGE: return "autoaway.message"; + case PREF_CONNECT_ACCOUNT: + return "account"; default: return NULL; } diff --git a/src/config/preferences.h b/src/config/preferences.h index cb1f9204..5affe002 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -56,7 +56,8 @@ typedef enum { PREF_GRLOG, PREF_AUTOAWAY_CHECK, PREF_AUTOAWAY_MODE, - PREF_AUTOAWAY_MESSAGE + PREF_AUTOAWAY_MESSAGE, + PREF_CONNECT_ACCOUNT } preference_t; void prefs_load(void); diff --git a/src/contact.h b/src/contact.h index 998e5f8b..b096c8d9 100644 --- a/src/contact.h +++ b/src/contact.h @@ -35,7 +35,7 @@ gboolean p_contact_remove_resource(PContact contact, const char * const resource void p_contact_free(PContact contact); const char* p_contact_barejid(PContact contact); const char* p_contact_name(PContact contact); -const char * p_contact_name_or_jid(const PContact contact); +const char* p_contact_name_or_jid(const PContact contact); const char* p_contact_presence(PContact contact); const char* p_contact_status(PContact contact); const char* p_contact_subscription(const PContact contact); diff --git a/src/main.c b/src/main.c index 253c9237..c3065bd3 100644 --- a/src/main.c +++ b/src/main.c @@ -32,6 +32,7 @@ static gboolean disable_tls = FALSE; static gboolean version = FALSE; static char *log = "INFO"; +static char *account_name = NULL; int main(int argc, char **argv) @@ -40,6 +41,7 @@ main(int argc, char **argv) { { "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Show version information", NULL }, { "disable-tls", 'd', 0, G_OPTION_ARG_NONE, &disable_tls, "Disable TLS", NULL }, + { "account", 'a', 0, G_OPTION_ARG_STRING, &account_name, "Auto connect to an account on start-up" }, { "log",'l', 0, G_OPTION_ARG_STRING, &log, "Set logging levels, DEBUG, INFO (default), WARN, ERROR", "LEVEL" }, { NULL } }; @@ -77,7 +79,7 @@ main(int argc, char **argv) return 0; } - prof_run(disable_tls, log); + prof_run(disable_tls, log, account_name); return 0; } diff --git a/src/profanity.c b/src/profanity.c index 06067d93..6bd7e2f0 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -58,7 +58,7 @@ static void _create_directories(void); static gboolean idle = FALSE; void -prof_run(const int disable_tls, char *log_level) +prof_run(const int disable_tls, char *log_level, char *account_name) { _init(disable_tls, log_level); log_info("Starting main event loop"); @@ -70,6 +70,18 @@ prof_run(const int disable_tls, char *log_level) char inp[INP_WIN_MAX]; int size = 0; + ui_refresh(); + + if (account_name != NULL) { + char *cmd = "/connect"; + snprintf(inp, sizeof(inp), "%s %s", cmd, account_name); + _process_input(inp); + } else if (prefs_get_string(PREF_CONNECT_ACCOUNT) != NULL) { + char *cmd = "/connect"; + snprintf(inp, sizeof(inp), "%s %s", cmd, prefs_get_string(PREF_CONNECT_ACCOUNT)); + _process_input(inp); + } + while(cmd_result == TRUE) { wint_t ch = ERR; size = 0; diff --git a/src/profanity.h b/src/profanity.h index 0cd59fd0..3dac6c3e 100644 --- a/src/profanity.h +++ b/src/profanity.h @@ -26,7 +26,7 @@ #include "resource.h" #include "xmpp/xmpp.h" -void prof_run(const int disable_tls, char *log_level); +void prof_run(const int disable_tls, char *log_level, char *account_name); void prof_handle_login_success(const char *jid, const char *altdomain); void prof_handle_login_account_success(char *account_name); diff --git a/src/ui/console.c b/src/ui/console.c index 9fecf4e3..822da420 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -790,6 +790,9 @@ cons_show_account(ProfAccount *account) cons_show ("enabled : FALSE"); } cons_show ("jid : %s", account->jid); + if (account->password != NULL) { + cons_show ("password : [redacted]"); + } if (account->resource != NULL) { cons_show ("resource : %s", account->resource); } @@ -936,6 +939,15 @@ cons_splash_setting(void) cons_show("Splash screen (/splash) : OFF"); } +void +cons_autoconnect_setting(void) +{ + if (prefs_get_string(PREF_CONNECT_ACCOUNT) != NULL) + cons_show("Autoconnect (/autoconnect) : %s", prefs_get_string(PREF_CONNECT_ACCOUNT)); + else + cons_show("Autoconnect (/autoconnect) : OFF"); +} + void cons_vercheck_setting(void) { @@ -1212,6 +1224,7 @@ cons_show_connection_prefs(void) cons_show(""); cons_reconnect_setting(); cons_autoping_setting(); + cons_autoconnect_setting(); wins_refresh_console(); cons_alert(); diff --git a/src/ui/core.c b/src/ui/core.c index e436a4af..c5cfe284 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -847,8 +847,8 @@ ui_new_chat_win(const char * const to) if (contact != NULL) { if (strcmp(p_contact_presence(contact), "offline") == 0) { - const char const *show = p_contact_presence(contact); - const char const *status = p_contact_status(contact); + const char * const show = p_contact_presence(contact); + const char * const status = p_contact_status(contact); win_show_status_string(window, to, show, status, NULL, "--", "offline"); } } diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index dfcb533d..d5b882d7 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -35,6 +35,7 @@ #include "command/command.h" #include "common.h" +#include "config/accounts.h" #include "config/preferences.h" #include "config/theme.h" #include "log.h" @@ -207,7 +208,7 @@ inp_get_password(char *passwd) _clear_input(); _inp_win_refresh(); noecho(); - mvwgetnstr(inp_win, 0, 1, passwd, 20); + mvwgetnstr(inp_win, 0, 1, passwd, MAX_PASSWORD_SIZE); wmove(inp_win, 0, 0); echo(); status_bar_clear(); diff --git a/src/ui/ui.h b/src/ui/ui.h index 9c1cba52..13e96f27 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -216,6 +216,7 @@ void cons_autoaway_setting(void); void cons_reconnect_setting(void); void cons_autoping_setting(void); void cons_priority_setting(void); +void cons_autoconnect_setting(void); // status bar actions void status_bar_refresh(void); diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 40a1ea05..a1cb31c4 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -109,21 +109,20 @@ jabber_init(const int disable_tls) } jabber_conn_status_t -jabber_connect_with_account(const ProfAccount * const account, - const char * const passwd) +jabber_connect_with_account(const ProfAccount * const account) { assert(account != NULL); - assert(passwd != NULL); log_info("Connecting using account: %s", account->name); // save account name and password for reconnect saved_account.name = strdup(account->name); - saved_account.passwd = strdup(passwd); + saved_account.passwd = strdup(account->password); // connect with fulljid Jid *jidp = jid_create_from_bare_and_resource(account->jid, account->resource); - jabber_conn_status_t result = _jabber_connect(jidp->fulljid, passwd, account->server); + jabber_conn_status_t result = + _jabber_connect(jidp->fulljid, account->password, account->server); jid_destroy(jidp); return result; diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index c073464d..5fbb7be7 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -518,7 +518,7 @@ roster_barejid_from_name(const char * const name) } PContact -roster_get_contact(const char const *barejid) +roster_get_contact(const char * const barejid) { return g_hash_table_lookup(contacts, barejid); } diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 61f07e5e..f1b3ba6c 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -78,8 +78,7 @@ typedef struct disco_identity_t { void jabber_init(const int disable_tls); jabber_conn_status_t jabber_connect_with_details(const char * const jid, const char * const passwd, const char * const altdomain); -jabber_conn_status_t jabber_connect_with_account(const ProfAccount * const account, - const char * const passwd); +jabber_conn_status_t jabber_connect_with_account(const ProfAccount * const account); void jabber_disconnect(void); void jabber_shutdown(void); void jabber_process_events(void); @@ -128,7 +127,7 @@ void caps_close(void); void roster_clear(void); gboolean roster_update_presence(const char * const barejid, Resource *resource, GDateTime *last_activity); -PContact roster_get_contact(const char const *barejid); +PContact roster_get_contact(const char * const barejid); gboolean roster_contact_offline(const char * const barejid, const char * const resource, const char * const status); void roster_reset_search_attempts(void);