From a5b44dffd25cb794962902f70e56dd80eb487825 Mon Sep 17 00:00:00 2001 From: jfreegman Date: Fri, 12 Nov 2021 12:28:54 -0500 Subject: [PATCH] Add the ability to make peer-specific commands using public keys This allows us to use commands on peers who may be using nicks with strange or unsupported unicode characters --- src/groupchat_commands.c | 60 +++++++++++++++++++++++++--------------- src/groupchat_commands.h | 1 + src/groupchats.c | 51 ++++++++++++++++++++++++++++++---- src/groupchats.h | 15 +++++++++- 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/groupchat_commands.c b/src/groupchat_commands.c index 6a76811..430b0c3 100644 --- a/src/groupchat_commands.c +++ b/src/groupchat_commands.c @@ -81,7 +81,7 @@ void cmd_disconnect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -89,8 +89,10 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ uint32_t peer_id; if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_TOGGLE_IGNORE err; @@ -118,7 +120,7 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -127,8 +129,10 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA uint32_t target_peer_id; if (group_get_nick_peer_id(self->num, nick, &target_peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &target_peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_MOD_KICK_PEER err; @@ -193,7 +197,7 @@ void cmd_list(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -201,8 +205,10 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX uint32_t target_peer_id; if (group_get_nick_peer_id(self->num, nick, &target_peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &target_peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_SELF_QUERY s_err; @@ -247,7 +253,7 @@ void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -255,8 +261,10 @@ void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M uint32_t target_peer_id; if (group_get_nick_peer_id(self->num, nick, &target_peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &target_peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_SELF_QUERY s_err; @@ -439,7 +447,7 @@ void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -447,8 +455,10 @@ void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) uint32_t target_peer_id; if (group_get_nick_peer_id(self->num, nick, &target_peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &target_peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_SELF_QUERY s_err; @@ -493,7 +503,7 @@ void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Peer name or public key must be specified."); return; } @@ -501,8 +511,10 @@ void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg uint32_t target_peer_id; if (group_get_nick_peer_id(self->num, nick, &target_peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &target_peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } if (tox_group_peer_get_role(m, self->num, target_peer_id, NULL) != TOX_GROUP_ROLE_OBSERVER) { @@ -639,8 +651,10 @@ void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv uint32_t peer_id; if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } TOX_ERR_GROUP_TOGGLE_IGNORE err; @@ -683,8 +697,10 @@ void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M uint32_t peer_id; if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick); - return; + if (group_get_public_key_peer_id(self->num, nick, &peer_id) == -1) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name or public key."); + return; + } } int peer_index = get_peer_index(self->num, peer_id); diff --git a/src/groupchat_commands.h b/src/groupchat_commands.h index 4199838..8a35875 100644 --- a/src/groupchat_commands.h +++ b/src/groupchat_commands.h @@ -45,3 +45,4 @@ void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUPCHAT_COMMANDS_H */ + diff --git a/src/groupchats.c b/src/groupchats.c index e03ba0e..a646cfd 100644 --- a/src/groupchats.c +++ b/src/groupchats.c @@ -465,6 +465,8 @@ static void sort_peerlist(uint32_t groupnumber) } /* Gets the peer_id associated with nick. + * + * Returns 0 on success. * Returns -1 on failure or if nick is not assigned to anyone in the group. */ int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32_t *peer_id) @@ -476,11 +478,50 @@ int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32_t *pee } for (size_t i = 0; i < chat->max_idx; ++i) { - if (chat->peer_list[i].active) { - if (strcmp(nick, chat->peer_list[i].name) == 0) { - *peer_id = chat->peer_list[i].peer_id; - return 0; - } + GroupPeer *peer = &chat->peer_list[i]; + + if (!peer->active) { + continue; + } + + if (strcmp(nick, peer->name) == 0) { + *peer_id = peer->peer_id; + return 0; + } + } + + return -1; +} + +/* Gets the peer_id associated with `public_key`. + * + * Returns 0 on success. + * Returns -1 on failure or if `public_key` is invalid. + */ +int group_get_public_key_peer_id(uint32_t groupnumber, const char *public_key, uint32_t *peer_id) +{ + GroupChat *chat = get_groupchat(groupnumber); + + if (!chat) { + return -1; + } + + char key_bin[TOX_GROUP_PEER_PUBLIC_KEY_SIZE]; + + if (hex_string_to_bin(public_key, strlen(public_key), key_bin, sizeof(key_bin)) == -1) { + return -1; + } + + for (size_t i = 0; i < chat->max_idx; ++i) { + GroupPeer *peer = &chat->peer_list[i]; + + if (!peer->active) { + continue; + } + + if (memcmp(key_bin, peer->public_key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0) { + *peer_id = peer->peer_id; + return 0; } } diff --git a/src/groupchats.h b/src/groupchats.h index 488849c..663237a 100644 --- a/src/groupchats.h +++ b/src/groupchats.h @@ -69,7 +69,6 @@ void exit_groupchat(ToxWindow *self, Tox *m, uint32_t groupnumber, const char *p int init_groupchat_win(Tox *m, uint32_t groupnumber, const char *groupname, size_t length, Group_Join_Type join_type); void set_nick_all_groups(Tox *m, const char *new_nick, size_t length); void set_status_all_groups(Tox *m, uint8_t status); -int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32_t *peer_id); int get_peer_index(uint32_t groupnumber, uint32_t peer_id); void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type, @@ -79,6 +78,20 @@ void groupchat_onGroupModeration(ToxWindow *self, Tox *m, uint32_t groupnumber, void groupchat_rejoin(ToxWindow *self, Tox *m); +/* Gets the peer_id associated with nick. + * + * Returns 0 on success. + * Returns -1 on failure or if nick is not assigned to anyone in the group. + */ +int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32_t *peer_id); + +/* Gets the peer_id associated with `public_key`. + * + * Returns 0 on success. + * Returns -1 on failure or if `public_key` is invalid. + */ +int group_get_public_key_peer_id(uint32_t groupnumber, const char *public_key, uint32_t *peer_id); + /* destroys and re-creates groupchat window */ void redraw_groupchat_win(ToxWindow *self);