From 0499f92ad7653e461e511bb2c419ecbfd8b11630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Pettersson?= Date: Sun, 5 Oct 2014 01:31:54 +0200 Subject: [PATCH] Fixed bugs with names containing spaces. --- src/twc-commands.c | 192 +++++++++++++++++++++++++++++++------------ src/twc-completion.c | 16 ++++ 2 files changed, 154 insertions(+), 54 deletions(-) diff --git a/src/twc-commands.c b/src/twc-commands.c index a52c737..132a66e 100644 --- a/src/twc-commands.c +++ b/src/twc-commands.c @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -34,59 +35,138 @@ #include "twc-commands.h" +enum TWC_FRIEND_MATCH +{ + TWC_FRIEND_MATCH_AMBIGUOUS = -1, + TWC_FRIEND_MATCH_NOMATCH = -2, +}; + /** * Make sure a command is executed on a Tox profile buffer. If not, warn user * and abort. */ -#define TWC_CHECK_PROFILE(profile) \ - if (!profile) \ - { \ - weechat_printf(NULL, \ - "%s%s: command \"%s\" must be executed on a Tox buffer", \ - weechat_prefix("error"), weechat_plugin->name, \ - argv[0]); \ - return WEECHAT_RC_OK; \ - } \ +#define TWC_CHECK_PROFILE(profile) \ + if (!profile) \ + { \ + weechat_printf(NULL, \ + "%s%s: command \"%s\" must be executed on a Tox " \ + "buffer", \ + weechat_prefix("error"), weechat_plugin->name, \ + argv[0]); \ + return WEECHAT_RC_OK; \ + } \ /** * Make sure a command is executed in a chat buffer. If not, warn user and * abort. */ -#define TWC_CHECK_CHAT(chat) \ - if (!chat) \ - { \ - weechat_printf(NULL, \ - "%s%s: command \"%s\" must be executed in a chat buffer", \ - weechat_prefix("error"), weechat_plugin->name, argv[0]); \ - return WEECHAT_RC_OK; \ +#define TWC_CHECK_CHAT(chat) \ + if (!chat) \ + { \ + weechat_printf(NULL, \ + "%s%s: command \"%s\" must be executed in a chat " \ + "buffer", \ + weechat_prefix("error"), \ + weechat_plugin->name, \ + argv[0]); \ + return WEECHAT_RC_OK; \ } /** * Make sure a profile with the given name exists. If not, warn user and * abort. */ -#define TWC_CHECK_PROFILE_EXISTS(profile) \ - if (!profile) \ - { \ - weechat_printf(NULL, \ - "%s%s: profile \"%s\" does not exist.", \ - weechat_prefix("error"), weechat_plugin->name, \ - name); \ - return WEECHAT_RC_OK; \ +#define TWC_CHECK_PROFILE_EXISTS(profile) \ + if (!profile) \ + { \ + weechat_printf(NULL, \ + "%s%s: profile \"%s\" does not exist.", \ + weechat_prefix("error"), weechat_plugin->name, \ + name); \ + return WEECHAT_RC_OK; \ } /** * Make sure a profile is loaded. */ -#define TWC_CHECK_PROFILE_LOADED(profile) \ - if (!(profile->tox)) \ - { \ - weechat_printf(profile->buffer, \ - "%sprofile must be loaded for command \"%s\"", \ - weechat_prefix("error"), argv[0]); \ - return WEECHAT_RC_OK; \ +#define TWC_CHECK_PROFILE_LOADED(profile) \ + if (!(profile->tox)) \ + { \ + weechat_printf(profile->buffer, \ + "%sprofile must be loaded for command \"%s\"", \ + weechat_prefix("error"), argv[0]); \ + return WEECHAT_RC_OK; \ } +/** + * Make sure friend exists. + */ +#define TWC_CHECK_FRIEND_NUMBER(number, string) \ + if (number == TWC_FRIEND_MATCH_NOMATCH) \ + { \ + weechat_printf(profile->buffer, \ + "%sno friend number, name or Tox ID found matching " \ + "\"%s\"", \ + weechat_prefix("error"), string); \ + return WEECHAT_RC_OK; \ + } \ + if (number == TWC_FRIEND_MATCH_AMBIGUOUS) \ + { \ + weechat_printf(profile->buffer, \ + "%smultiple friends with name \"%s\" found; please " \ + "use Tox ID instead", \ + weechat_prefix("error"), string); \ + return WEECHAT_RC_OK; \ + } + + +/** + * Get number of friend matching string. Tries to match number, name and + * Tox ID. + */ +enum TWC_FRIEND_MATCH +twc_match_friend(struct t_twc_profile *profile, const char *search_string) +{ + uint32_t friend_count = tox_count_friendlist(profile->tox); + int32_t *friend_numbers = malloc(sizeof(int32_t) * friend_count); + tox_get_friendlist(profile->tox, friend_numbers, friend_count); + + int32_t match = TWC_FRIEND_MATCH_NOMATCH; + + char *endptr; + unsigned long friend_number = strtoul(search_string, &endptr, 10); + if (endptr == search_string + strlen(search_string) + && tox_friend_exists(profile->tox, friend_number)) + return friend_number; + + size_t search_size = strlen(search_string); + for (uint32_t i = 0; i < friend_count; ++i) + { + if (search_size == TOX_CLIENT_ID_SIZE * 2) + { + uint8_t tox_id[TOX_CLIENT_ID_SIZE]; + char hex_id[TOX_CLIENT_ID_SIZE * 2 + 1]; + + tox_get_client_id(profile->tox, friend_numbers[i], tox_id); + twc_bin2hex(tox_id, TOX_CLIENT_ID_SIZE, hex_id); + + if (weechat_strcasecmp(hex_id, search_string) == 0) + return friend_number; + } + + char *name = twc_get_name_nt(profile->tox, friend_numbers[i]); + if (weechat_strcasecmp(name, search_string) == 0) + { + if (match == TWC_FRIEND_MATCH_NOMATCH) + match = friend_numbers[i]; + else + return TWC_FRIEND_MATCH_AMBIGUOUS; + } + } + + return match; +} + /** * Command /bootstrap callback. */ @@ -238,19 +318,11 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer, return WEECHAT_RC_OK; } - // /friend remove - else if (argc == 3 && (weechat_strcasecmp(argv[1], "remove") == 0)) + // /friend remove + else if (argc >= 3 && (weechat_strcasecmp(argv[1], "remove") == 0)) { - char *endptr; - unsigned long friend_number = strtoul(argv[2], &endptr, 10); - - if (endptr == argv[2] || !tox_friend_exists(profile->tox, friend_number)) - { - weechat_printf(profile->buffer, - "%sInvalid friend number.", - weechat_prefix("error")); - return WEECHAT_RC_OK; - } + int32_t friend_number = twc_match_friend(profile, argv[2]); + TWC_CHECK_FRIEND_NUMBER(friend_number, argv[2]); char *name = twc_get_name_nt(profile->tox, friend_number); if (tox_del_friend(profile->tox, friend_number) == 0) @@ -483,23 +555,35 @@ twc_cmd_msg(void *data, struct t_gui_buffer *buffer, TWC_CHECK_PROFILE(profile); TWC_CHECK_PROFILE_LOADED(profile); - char *endptr; - unsigned long friend_number = strtoul(argv[1], &endptr, 10); + // do a shell split in case a friend has spaces in his name and we need + // quotes + int shell_argc; + char **shell_argv = weechat_string_split_shell(argv_eol[0], &shell_argc); - if (endptr == argv[1] || !tox_friend_exists(profile->tox, friend_number)) + char recipient[TOX_MAX_NAME_LENGTH + 1]; + snprintf(recipient, TOX_MAX_NAME_LENGTH, "%s", shell_argv[1]); + weechat_string_free_split(shell_argv); + + char *message = NULL; + if (shell_argc >= 3) { - weechat_printf(profile->buffer, - "%sInvalid friend number.", - weechat_prefix("error")); - return WEECHAT_RC_OK; + // extract message, add two if quotes are used + message = argv_eol[1] + strlen(recipient); + if (*argv[1] == '"' || *argv[1] == '\'') + message += 2; } + int32_t friend_number = twc_match_friend(profile, recipient); + TWC_CHECK_FRIEND_NUMBER(friend_number, recipient); + // create chat buffer if it does not exist struct t_twc_chat *chat = twc_chat_search_friend(profile, friend_number, true); // send a message if provided - if (argc >= 3) - twc_chat_send_message(chat, argv_eol[2], TWC_MESSAGE_TYPE_MESSAGE); + if (message) + twc_chat_send_message(chat, + weechat_string_strip(message, 1, 1, " "), + TWC_MESSAGE_TYPE_MESSAGE); return WEECHAT_RC_OK; } @@ -851,8 +935,8 @@ twc_commands_init() " || add" " || remove %(tox_friend_name)|%(tox_friend_tox_id)" " || requests" - " || accept %(tox_friend_name)|%(tox_friend_tox_id)" - " || decline %(tox_friend_name)|%(tox_friend_tox_id)", + " || accept" + " || decline", twc_cmd_friend, NULL); weechat_hook_command("group", diff --git a/src/twc-completion.c b/src/twc-completion.c index 686b8f2..9ee6cd5 100644 --- a/src/twc-completion.c +++ b/src/twc-completion.c @@ -17,6 +17,9 @@ * along with Tox-WeeChat. If not, see . */ +#include +#include + #include #include "twc.h" @@ -78,10 +81,23 @@ twc_completion_friend(void *data, { char *name = twc_get_name_nt(profile->tox, friend_numbers[i]); + // add quotes if needed + if (strchr(name, ' ')) + { + size_t length = strlen(name) + 3; + char *quoted_name = malloc(length); + snprintf(quoted_name, length, "\"%s\"", name); + + free(name); + name = quoted_name; + } + weechat_hook_completion_list_add(completion, name, 0, WEECHAT_LIST_POS_SORT); + + free(name); } }