Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 64 additions & 3 deletions src/command/cmd_funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3540,6 +3540,51 @@ cmd_serversoftware(ProfWin* window, const char* const command, gchar** args)
return TRUE;
}

static gboolean
_xmpp_uri_parse_join(const gchar* uri, gchar** out_room, gchar** out_password)
{
if (g_ascii_strncasecmp(uri, "xmpp:", 5) != 0) {
return FALSE;
}

const gchar* body = uri + 5;
const gchar* query = strchr(body, '?');

if (query == NULL) {
*out_room = g_uri_unescape_string(body, NULL);
*out_password = NULL;
return TRUE;
}

gchar* room_escaped = g_strndup(body, query - body);
*out_room = g_uri_unescape_string(room_escaped, NULL);
g_free(room_escaped);

const gchar* query_str = query + 1;
auto_gcharv gchar** parts = g_strsplit(query_str, ";", -1);

if (parts[0] == NULL || g_strcmp0(parts[0], "join") != 0) {
g_free(*out_room);
*out_room = NULL;
return FALSE;
}

gchar* password = NULL;
for (int i = 1; parts[i] != NULL; i++) {
gchar* eq = strchr(parts[i], '=');
if (eq != NULL) {
gchar* key = g_strndup(parts[i], eq - parts[i]);
if (g_strcmp0(key, "password") == 0) {
password = g_uri_unescape_string(eq + 1, NULL);
}
g_free(key);
}
}

*out_password = password;
return TRUE;
}

gboolean
cmd_join(ProfWin* window, const char* const command, gchar** args)
{
Expand All @@ -3566,7 +3611,19 @@ cmd_join(ProfWin* window, const char* const command, gchar** args)
return TRUE;
}

auto_jid Jid* room_arg = jid_create(args[0]);
auto_gchar gchar* room_jid = NULL;
auto_gchar gchar* uri_password = NULL;

if (g_ascii_strncasecmp(args[0], "xmpp:", 5) == 0) {
if (!_xmpp_uri_parse_join(args[0], &room_jid, &uri_password)) {
cons_show_error("Unsupported or invalid XMPP URI query type. Only 'join' is supported.");
return TRUE;
}
} else {
room_jid = g_strdup(args[0]);
}

auto_jid Jid* room_arg = jid_create(room_jid);
if (room_arg == NULL) {
cons_show_error("Specified room has incorrect format.");
cons_show("");
Expand All @@ -3580,11 +3637,11 @@ cmd_join(ProfWin* window, const char* const command, gchar** args)

// full room jid supplied (room@server)
if (room_arg->localpart) {
room = g_strdup(args[0]);
room = g_strdup(room_jid);

// server not supplied (room), use account preference
} else if (account->muc_service) {
room = g_strdup_printf("%s@%s", args[0], account->muc_service);
room = g_strdup_printf("%s@%s", room_jid, account->muc_service);

// no account preference
} else {
Expand Down Expand Up @@ -3613,6 +3670,10 @@ cmd_join(ProfWin* window, const char* const command, gchar** args)
nick = account->muc_nick;
}

if (!passwd) {
passwd = uri_password;
}

// When no password, check for invite with password
if (!passwd) {
passwd = muc_invite_password(room);
Expand Down
65 changes: 65 additions & 0 deletions tests/unittests/command/test_cmd_join.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,68 @@ cmd_join__tests__uses_password_when_supplied(void** state)
gboolean result = cmd_join(NULL, CMD_JOIN, args);
assert_true(result);
}

void
cmd_join__tests__xmpp_uri_join(void** state)
{
gchar* account_name = g_strdup("an_account");
char* room_uri = "xmpp:room@conf.server.org?join";
char* expected_room = "room@conf.server.org";
gchar* account_nick = g_strdup("a_nick");
gchar* args[] = { room_uri, NULL };
ProfAccount* account = account_new(account_name, g_strdup("user@server.org"), NULL, NULL,
TRUE, NULL, 0, g_strdup("laptop"), NULL, NULL, 0, 0, 0, 0, 0, NULL, account_nick, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0);

will_return(connection_get_status, JABBER_CONNECTED);
will_return(session_get_account_name, account_name);

expect_string(accounts_get_account, name, account_name);
will_return(accounts_get_account, account);

expect_string(presence_join_room, room, expected_room);
expect_string(presence_join_room, nick, account_nick);
expect_value(presence_join_room, passwd, NULL);

gboolean result = cmd_join(NULL, CMD_JOIN, args);
assert_true(result);
}

void
cmd_join__tests__xmpp_uri_join_with_password(void** state)
{
gchar* account_name = g_strdup("an_account");
char* room_uri = "xmpp:room@conf.server.org?join;password=secret";
char* expected_room = "room@conf.server.org";
char* expected_password = "secret";
gchar* account_nick = g_strdup("a_nick");
gchar* args[] = { room_uri, NULL };
ProfAccount* account = account_new(account_name, g_strdup("user@server.org"), NULL, NULL,
TRUE, NULL, 0, g_strdup("laptop"), NULL, NULL, 0, 0, 0, 0, 0, NULL, account_nick, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0);

will_return(connection_get_status, JABBER_CONNECTED);
will_return(session_get_account_name, account_name);

expect_string(accounts_get_account, name, account_name);
will_return(accounts_get_account, account);

expect_string(presence_join_room, room, expected_room);
expect_string(presence_join_room, nick, account_nick);
expect_string(presence_join_room, passwd, expected_password);

gboolean result = cmd_join(NULL, CMD_JOIN, args);
assert_true(result);
}

void
cmd_join__tests__xmpp_uri_invalid_query_type(void** state)
{
char* room_uri = "xmpp:room@conf.server.org?message";
gchar* args[] = { room_uri, NULL };

will_return(connection_get_status, JABBER_CONNECTED);

expect_cons_show_error("Unsupported or invalid XMPP URI query type. Only 'join' is supported.");

gboolean result = cmd_join(NULL, CMD_JOIN, args);
assert_true(result);
}
3 changes: 3 additions & 0 deletions tests/unittests/command/test_cmd_join.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ void cmd_join__tests__uses_account_mucservice_when_no_service_specified(void** s
void cmd_join__tests__uses_supplied_nick(void** state);
void cmd_join__tests__uses_account_nick_when_not_supplied(void** state);
void cmd_join__tests__uses_password_when_supplied(void** state);
void cmd_join__tests__xmpp_uri_join(void** state);
void cmd_join__tests__xmpp_uri_join_with_password(void** state);
void cmd_join__tests__xmpp_uri_invalid_query_type(void** state);

#endif
3 changes: 3 additions & 0 deletions tests/unittests/unittests.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,9 @@ main(int argc, char* argv[])
muc_unit_test(cmd_join__tests__uses_supplied_nick),
muc_unit_test(cmd_join__tests__uses_account_nick_when_not_supplied),
muc_unit_test(cmd_join__tests__uses_password_when_supplied),
muc_unit_test(cmd_join__tests__xmpp_uri_join),
muc_unit_test(cmd_join__tests__xmpp_uri_join_with_password),
cmocka_unit_test(cmd_join__tests__xmpp_uri_invalid_query_type),

cmocka_unit_test(cmd_roster__shows__message_when_disconnecting),
cmocka_unit_test(cmd_roster__shows__message_when_connecting),
Expand Down
Loading