diff --git a/src/command/command.c b/src/command/command.c index d8f55205..90e7cc2c 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -69,6 +69,7 @@ static char * _otr_autocomplete(char *input, int *size); static char * _connect_autocomplete(char *input, int *size); static char * _statuses_autocomplete(char *input, int *size); static char * _alias_autocomplete(char *input, int *size); +static char * _join_autocomplete(char *input, int *size); GHashTable *commands = NULL; @@ -235,9 +236,9 @@ static struct cmd_t command_defs[] = NULL } } }, { "/join", - cmd_join, parse_args_with_freetext, 1, 2, NULL, - { "/join room[@server] [nick]", "Join a chat room.", - { "/join room[@server] [nick]", + cmd_join, parse_args, 1, 5, NULL, + { "/join room[@server] [nick value] [passwd value]", "Join a chat room.", + { "/join room[@server] [nick value] [passwd value]", "--------------------------", "Join a chat room at the conference server.", "If nick is specified you will join with this nickname.", @@ -246,7 +247,8 @@ static struct cmd_t command_defs[] = "If the room doesn't exist, and the server allows it, a new one will be created.", "", "Example : /join jdev@conference.jabber.org", - "Example : /join jdev@conference.jabber.org mynick", + "Example : /join jdev@conference.jabber.org nick mynick", + "Example : /join private@conference.jabber.org nick mynick passwd mypassword", "Example : /join jdev (as user@jabber.org will join jdev@conference.jabber.org)", NULL } } }, @@ -880,6 +882,7 @@ static Autocomplete statuses_ac; static Autocomplete statuses_cons_chat_ac; static Autocomplete alias_ac; static Autocomplete aliases_ac; +static Autocomplete join_property_ac; /* * Initialise command autocompleter and history @@ -1068,6 +1071,10 @@ cmd_init(void) autocomplete_add(connect_property_ac, "server"); autocomplete_add(connect_property_ac, "port"); + join_property_ac = autocomplete_new(); + autocomplete_add(join_property_ac, "nick"); + autocomplete_add(join_property_ac, "passwd"); + statuses_ac = autocomplete_new(); autocomplete_add(statuses_ac, "console"); autocomplete_add(statuses_ac, "chat"); @@ -1120,6 +1127,7 @@ cmd_uninit(void) autocomplete_free(statuses_cons_chat_ac); autocomplete_free(alias_ac); autocomplete_free(aliases_ac); + autocomplete_free(join_property_ac); } gboolean @@ -1242,6 +1250,7 @@ cmd_reset_autocomplete() autocomplete_reset(statuses_cons_chat_ac); autocomplete_reset(alias_ac); autocomplete_reset(aliases_ac); + autocomplete_reset(join_property_ac); bookmark_autocomplete_reset(); } @@ -1482,13 +1491,6 @@ _cmd_complete_parameters(char *input, int *size) } } - result = autocomplete_param_with_func(input, size, "/join", bookmark_find); - 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 }; @@ -1505,7 +1507,8 @@ _cmd_complete_parameters(char *input, int *size) _autoaway_autocomplete, _titlebar_autocomplete, _theme_autocomplete, _account_autocomplete, _roster_autocomplete, _group_autocomplete, _bookmark_autocomplete, _autoconnect_autocomplete, _otr_autocomplete, - _connect_autocomplete, _statuses_autocomplete, _alias_autocomplete }; + _connect_autocomplete, _statuses_autocomplete, _alias_autocomplete, + _join_autocomplete }; for (i = 0; i < ARRAY_SIZE(acs); i++) { result = acs[i](input, size); @@ -1860,6 +1863,33 @@ _connect_autocomplete(char *input, int *size) return NULL; } +static char * +_join_autocomplete(char *input, int *size) +{ + char *result = NULL; + + input[*size] = '\0'; + gchar **args = parse_args(input, 2, 4); + + if ((strncmp(input, "/join", 5) == 0) && (args != NULL)) { + GString *beginning = g_string_new("/join "); + g_string_append(beginning, args[0]); + if (args[1] != NULL && args[2] != NULL) { + g_string_append(beginning, " "); + g_string_append(beginning, args[1]); + g_string_append(beginning, " "); + g_string_append(beginning, args[2]); + } + result = autocomplete_param_with_ac(input, size, beginning->str, join_property_ac); + g_string_free(beginning, TRUE); + if (result != NULL) { + return result; + } + } + + return NULL; +} + static char * _account_autocomplete(char *input, int *size) { diff --git a/src/command/commands.c b/src/command/commands.c index da360da8..9f4882fa 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1594,6 +1594,7 @@ cmd_join(gchar **args, struct cmd_help_t help) int num_args = g_strv_length(args); char *room = NULL; char *nick = NULL; + char *passwd = NULL; GString *room_str = g_string_new(""); Jid *my_jid = jid_create(jabber_get_fulljid()); @@ -1609,19 +1610,50 @@ cmd_join(gchar **args, struct cmd_help_t help) room = room_str->str; } - // nick supplied - if (num_args == 2) { - nick = args[1]; + // Additional args supplied + if (num_args > 1) { + char *opt1 = args[1]; + char *opt1val = args[2]; + char *opt2 = args[3]; + char *opt2val = args[4]; + if (opt1 != NULL) { + if (opt1val == NULL) { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + if (strcmp(opt1, "nick") == 0) { + nick = opt1val; + } else if (strcmp(opt1, "passwd") == 0) { + passwd = opt1val; + } else { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + if (opt2 != NULL) { + if (strcmp(opt2, "nick") == 0) { + nick = opt2val; + } else if (strcmp(opt2, "passwd") == 0) { + passwd = opt2val; + } else { + cons_show("Usage: %s", help.usage); + cons_show(""); + return TRUE; + } + } + } + } - // otherwise use account preference - } else { + // In the case that a nick wasn't provided by the optional args... + if (nick == NULL) { nick = account->muc_nick; } Jid *room_jid = jid_create_from_bare_and_resource(room, nick); if (!muc_room_is_active(room_jid)) { - presence_join_room(room_jid); + presence_join_room(room_jid, passwd); } ui_room_join(room_jid); muc_remove_invite(room); diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index 1bc102a3..27a768be 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -301,7 +301,7 @@ _bookmark_handle_result(xmpp_conn_t * const conn, log_debug("Autojoin %s with nick=%s", jid, name); room_jid = jid_create_from_bare_and_resource(jid, name); if (!muc_room_is_active(room_jid)) { - presence_join_room(room_jid); + presence_join_room(room_jid, NULL); /* TODO: this should be removed after fixing #195 */ ui_room_join(room_jid); } diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index ae392ad9..3098e6e4 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -260,7 +260,7 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence) } static void -_presence_join_room(Jid *jid) +_presence_join_room(Jid *jid, char * passwd) { assert(jid != NULL); assert(jid->fulljid != NULL); @@ -275,7 +275,7 @@ _presence_join_room(Jid *jid) int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), presence_type); - xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid); + xmpp_stanza_t *presence = stanza_create_room_join_presence(ctx, jid->fulljid, passwd); stanza_attach_show(ctx, presence, show); stanza_attach_status(ctx, presence, status); stanza_attach_priority(ctx, presence, pri); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index c37ab124..965b1671 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -249,7 +249,7 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room, xmpp_stanza_t * stanza_create_room_join_presence(xmpp_ctx_t * const ctx, - const char * const full_room_jid) + const char * const full_room_jid, const char * const passwd) { xmpp_stanza_t *presence = xmpp_stanza_new(ctx); xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE); @@ -260,6 +260,19 @@ stanza_create_room_join_presence(xmpp_ctx_t * const ctx, xmpp_stanza_t *x = xmpp_stanza_new(ctx); xmpp_stanza_set_name(x, STANZA_NAME_X); xmpp_stanza_set_ns(x, STANZA_NS_MUC); + + // if a password was given + if (passwd != NULL) { + xmpp_stanza_t *pass = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pass, "password"); + xmpp_stanza_t *text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(text, strdup(passwd)); + xmpp_stanza_add_child(pass, text); + xmpp_stanza_add_child(x, pass); + xmpp_stanza_release(text); + xmpp_stanza_release(pass); + } + xmpp_stanza_add_child(presence, x); xmpp_stanza_release(x); diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 471a9f76..28f12a32 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -158,7 +158,7 @@ xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, const char * const message, const char * const state); xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx, - const char * const full_room_jid); + const char * const full_room_jid, const char * const passwd); xmpp_stanza_t* stanza_create_room_newnick_presence(xmpp_ctx_t *ctx, const char * const full_room_jid); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index fdbcb500..3ef9c93c 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -114,7 +114,7 @@ GSList* (*presence_get_subscription_requests)(void); gint (*presence_sub_request_count)(void); void (*presence_reset_sub_request_search)(void); char * (*presence_sub_request_find)(char * search_str); -void (*presence_join_room)(Jid *jid); +void (*presence_join_room)(Jid *jid, char * passwd); void (*presence_change_room_nick)(const char * const room, const char * const nick); void (*presence_leave_chat_room)(const char * const room_jid); void (*presence_update)(resource_presence_t status, const char * const msg,