diff --git a/src/command/command.c b/src/command/command.c index e1833ede..8fe4f90e 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -99,7 +99,7 @@ static struct cmd_t command_defs[] = NULL } } }, { "/connect", - cmd_connect, parse_args, 1, 2, NULL, + cmd_connect, parse_args, 1, 5, NULL, { "/connect account [server]", "Login to a chat service.", { "/connect account [server]", "-------------------------", diff --git a/src/command/commands.c b/src/command/commands.c index b1bbfce8..8a6f6d7b 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -69,10 +69,72 @@ cmd_connect(gchar **args, struct cmd_help_t help) result = TRUE; } else { char *user = args[0]; - char *altdomain = args[1]; + char *opt1 = args[1]; + char *opt1val = args[2]; + char *opt2 = args[3]; + char *opt2val = args[4]; char *lower = g_utf8_strdown(user, -1); char *jid; + // parse options + char *altdomain = NULL; + int port = 0; + gboolean altdomain_set = FALSE; + gboolean port_set = FALSE; + if (opt1 != NULL) { + if (opt1val == NULL) { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + if (strcmp(opt1, "server") == 0) { + altdomain = opt1val; + altdomain_set = TRUE; + } else if (strcmp(opt1, "port") == 0) { + if (_strtoi(opt1val, &port, 1, 65536) != 0) { + port = 0; + cons_show("Port must be in the range 1 to 65535."); + } else { + port_set = TRUE; + } + } else { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + + if (opt2 != NULL) { + if (opt2val == NULL) { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + if (strcmp(opt2, "server") == 0) { + if (altdomain_set) { + cons_show("Usage: %s", help.usage); + return TRUE; + } + altdomain = opt2val; + altdomain_set = TRUE; + } else if (strcmp(opt2, "port") == 0) { + if (port_set) { + cons_show("Usage: %s", help.usage); + return TRUE; + } + if (_strtoi(opt2val, &port, 1, 65536) != 0) { + port = 0; + cons_show("Port must be in the range 1 to 65535."); + } else { + port_set = TRUE; + } + } else { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + } + } + ProfAccount *account = accounts_get_account(lower); if (account != NULL) { jid = accounts_create_full_jid(account); @@ -86,7 +148,7 @@ cmd_connect(gchar **args, struct cmd_help_t help) char *passwd = ui_ask_password(); jid = strdup(lower); cons_show("Connecting as %s", jid); - conn_status = jabber_connect_with_details(jid, passwd, altdomain); + conn_status = jabber_connect_with_details(jid, passwd, altdomain, port); free(passwd); } g_free(lower); @@ -140,7 +202,7 @@ cmd_account(gchar **args, struct cmd_help_t help) if (account_name == NULL) { cons_show("Usage: %s", help.usage); } else { - accounts_add(account_name, NULL); + accounts_add(account_name, NULL, 0); cons_show("Account created."); cons_show(""); } diff --git a/src/config/accounts.c b/src/config/accounts.c index 2270e874..178f726f 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -43,6 +43,7 @@ static Autocomplete enabled_ac; static gchar *string_keys[] = { "jid", "server", + "port", "resource", "password", "presence.last", @@ -118,7 +119,7 @@ _accounts_reset_enabled_search(void) } static void -_accounts_add(const char *account_name, const char *altdomain) +_accounts_add(const char *account_name, const char *altdomain, int port) { // set account name and resource const char *barejid = account_name; @@ -139,6 +140,9 @@ _accounts_add(const char *account_name, const char *altdomain) if (altdomain != NULL) { g_key_file_set_string(accounts, account_name, "server", altdomain); } + if (port != 0) { + g_key_file_set_integer(accounts, account_name, "port", port); + } Jid *jidp = jid_create(barejid); GString *muc_service = g_string_new("conference."); @@ -211,6 +215,9 @@ _accounts_get_account(const char * const name) account->server = NULL; } + int port = g_key_file_get_integer(accounts, name, "port", NULL); + account->port = port; + gchar *resource = g_key_file_get_string(accounts, name, "resource", NULL); if (resource != NULL) { account->resource = strdup(resource); @@ -435,6 +442,15 @@ _accounts_set_server(const char * const account_name, const char * const value) } } +static void +_accounts_set_port(const char * const account_name, const int value) +{ + if (value != 0) { + g_key_file_set_integer(accounts, account_name, "port", value); + _save_accounts(); + } +} + static void _accounts_set_resource(const char * const account_name, const char * const value) { @@ -736,6 +752,7 @@ accounts_init_module(void) accounts_account_exists = _accounts_account_exists; accounts_set_jid = _accounts_set_jid; accounts_set_server = _accounts_set_server; + accounts_set_port = _accounts_set_port; accounts_set_resource = _accounts_set_resource; accounts_set_password = _accounts_set_password; accounts_set_muc_service = _accounts_set_muc_service; diff --git a/src/config/accounts.h b/src/config/accounts.h index ccccefdf..8f7b5c37 100644 --- a/src/config/accounts.h +++ b/src/config/accounts.h @@ -33,6 +33,7 @@ typedef struct prof_account_t { gchar *password; gchar *resource; gchar *server; + int port; gchar *last_presence; gchar *login_presence; gint priority_online; @@ -55,7 +56,7 @@ char * (*accounts_find_all)(char *prefix); char * (*accounts_find_enabled)(char *prefix); void (*accounts_reset_all_search)(void); void (*accounts_reset_enabled_search)(void); -void (*accounts_add)(const char *jid, const char *altdomain); +void (*accounts_add)(const char *jid, const char *altdomain, int port); gchar** (*accounts_get_list)(void); ProfAccount* (*accounts_get_account)(const char * const name); void (*accounts_free_account)(ProfAccount *account); @@ -66,6 +67,7 @@ gboolean (*accounts_rename)(const char * const account_name, 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_port)(const char * const account_name, const int 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); diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index ad447767..dc015dd6 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -68,6 +68,7 @@ static struct { char *jid; char *passwd; char *altdomain; + int port; } saved_details; static GTimer *reconnect_timer; @@ -80,7 +81,7 @@ static void _xmpp_file_logger(void * const userdata, static xmpp_log_t * _xmpp_get_file_logger(); static jabber_conn_status_t _jabber_connect(const char * const fulljid, - const char * const passwd, const char * const altdomain); + const char * const passwd, const char * const altdomain, int port); static void _jabber_reconnect(void); static void _connection_handler(xmpp_conn_t * const conn, @@ -123,7 +124,7 @@ _jabber_connect_with_account(const ProfAccount * const account) // connect with fulljid Jid *jidp = jid_create_from_bare_and_resource(account->jid, account->resource); jabber_conn_status_t result = - _jabber_connect(jidp->fulljid, account->password, account->server); + _jabber_connect(jidp->fulljid, account->password, account->server, account->port); jid_destroy(jidp); return result; @@ -131,7 +132,7 @@ _jabber_connect_with_account(const ProfAccount * const account) static jabber_conn_status_t _jabber_connect_with_details(const char * const jid, - const char * const passwd, const char * const altdomain) + const char * const passwd, const char * const altdomain, int port) { assert(jid != NULL); assert(passwd != NULL); @@ -144,6 +145,11 @@ _jabber_connect_with_details(const char * const jid, } else { saved_details.altdomain = NULL; } + if (port != 0) { + saved_details.port = port; + } else { + saved_details.port = 0; + } // use 'profanity' when no resourcepart in provided jid Jid *jidp = jid_create(jid); @@ -158,7 +164,7 @@ _jabber_connect_with_details(const char * const jid, // connect with fulljid log_info("Connecting without account, JID: %s", saved_details.jid); - return _jabber_connect(saved_details.jid, passwd, saved_details.altdomain); + return _jabber_connect(saved_details.jid, passwd, saved_details.altdomain, saved_details.port); } static void @@ -377,7 +383,7 @@ connection_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, static jabber_conn_status_t _jabber_connect(const char * const fulljid, const char * const passwd, - const char * const altdomain) + const char * const altdomain, int port) { assert(fulljid != NULL); assert(passwd != NULL); @@ -421,7 +427,7 @@ _jabber_connect(const char * const fulljid, const char * const passwd, xmpp_conn_disable_tls(jabber_conn.conn); } - int connect_status = xmpp_connect_client(jabber_conn.conn, altdomain, 0, + int connect_status = xmpp_connect_client(jabber_conn.conn, altdomain, port, _connection_handler, jabber_conn.ctx); if (connect_status == 0) @@ -443,7 +449,7 @@ _jabber_reconnect(void) } else { char *fulljid = create_fulljid(account->jid, account->resource); log_debug("Attempting reconnect with account %s", account->name); - _jabber_connect(fulljid, saved_account.passwd, account->server); + _jabber_connect(fulljid, saved_account.passwd, account->server, account->port); free(fulljid); g_timer_start(reconnect_timer); } @@ -468,7 +474,7 @@ _connection_handler(xmpp_conn_t * const conn, // logged in without account, use details to create new account } else { log_debug("Connection handler: logged in with jid: %s", saved_details.name); - accounts_add(saved_details.name, saved_details.altdomain); + accounts_add(saved_details.name, saved_details.altdomain, saved_details.port); accounts_set_jid(saved_details.name, saved_details.jid); handle_login_account_success(saved_details.name); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 87cde006..86f585e4 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -85,7 +85,7 @@ void roster_init_module(void); // connection functions 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); + const char * const passwd, const char * const altdomain, int port); jabber_conn_status_t (*jabber_connect_with_account)(const ProfAccount * const account); void (*jabber_disconnect)(void); void (*jabber_shutdown)(void);