Fixed bugs with names containing spaces.

This commit is contained in:
Håvard Pettersson 2014-10-05 01:31:54 +02:00
parent 9a97a3fe0c
commit 0499f92ad7
2 changed files with 154 additions and 54 deletions

View File

@ -18,6 +18,7 @@
*/ */
#include <string.h> #include <string.h>
#include <stdio.h>
#include <weechat/weechat-plugin.h> #include <weechat/weechat-plugin.h>
#include <tox/tox.h> #include <tox/tox.h>
@ -34,59 +35,138 @@
#include "twc-commands.h" #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 * Make sure a command is executed on a Tox profile buffer. If not, warn user
* and abort. * and abort.
*/ */
#define TWC_CHECK_PROFILE(profile) \ #define TWC_CHECK_PROFILE(profile) \
if (!profile) \ if (!profile) \
{ \ { \
weechat_printf(NULL, \ weechat_printf(NULL, \
"%s%s: command \"%s\" must be executed on a Tox buffer", \ "%s%s: command \"%s\" must be executed on a Tox " \
weechat_prefix("error"), weechat_plugin->name, \ "buffer", \
argv[0]); \ weechat_prefix("error"), weechat_plugin->name, \
return WEECHAT_RC_OK; \ argv[0]); \
} \ return WEECHAT_RC_OK; \
} \
/** /**
* Make sure a command is executed in a chat buffer. If not, warn user and * Make sure a command is executed in a chat buffer. If not, warn user and
* abort. * abort.
*/ */
#define TWC_CHECK_CHAT(chat) \ #define TWC_CHECK_CHAT(chat) \
if (!chat) \ if (!chat) \
{ \ { \
weechat_printf(NULL, \ weechat_printf(NULL, \
"%s%s: command \"%s\" must be executed in a chat buffer", \ "%s%s: command \"%s\" must be executed in a chat " \
weechat_prefix("error"), weechat_plugin->name, argv[0]); \ "buffer", \
return WEECHAT_RC_OK; \ 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 * Make sure a profile with the given name exists. If not, warn user and
* abort. * abort.
*/ */
#define TWC_CHECK_PROFILE_EXISTS(profile) \ #define TWC_CHECK_PROFILE_EXISTS(profile) \
if (!profile) \ if (!profile) \
{ \ { \
weechat_printf(NULL, \ weechat_printf(NULL, \
"%s%s: profile \"%s\" does not exist.", \ "%s%s: profile \"%s\" does not exist.", \
weechat_prefix("error"), weechat_plugin->name, \ weechat_prefix("error"), weechat_plugin->name, \
name); \ name); \
return WEECHAT_RC_OK; \ return WEECHAT_RC_OK; \
} }
/** /**
* Make sure a profile is loaded. * Make sure a profile is loaded.
*/ */
#define TWC_CHECK_PROFILE_LOADED(profile) \ #define TWC_CHECK_PROFILE_LOADED(profile) \
if (!(profile->tox)) \ if (!(profile->tox)) \
{ \ { \
weechat_printf(profile->buffer, \ weechat_printf(profile->buffer, \
"%sprofile must be loaded for command \"%s\"", \ "%sprofile must be loaded for command \"%s\"", \
weechat_prefix("error"), argv[0]); \ weechat_prefix("error"), argv[0]); \
return WEECHAT_RC_OK; \ 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. * Command /bootstrap callback.
*/ */
@ -238,19 +318,11 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer,
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
// /friend remove <number> // /friend remove
else if (argc == 3 && (weechat_strcasecmp(argv[1], "remove") == 0)) else if (argc >= 3 && (weechat_strcasecmp(argv[1], "remove") == 0))
{ {
char *endptr; int32_t friend_number = twc_match_friend(profile, argv[2]);
unsigned long friend_number = strtoul(argv[2], &endptr, 10); TWC_CHECK_FRIEND_NUMBER(friend_number, argv[2]);
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;
}
char *name = twc_get_name_nt(profile->tox, friend_number); char *name = twc_get_name_nt(profile->tox, friend_number);
if (tox_del_friend(profile->tox, friend_number) == 0) 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(profile);
TWC_CHECK_PROFILE_LOADED(profile); TWC_CHECK_PROFILE_LOADED(profile);
char *endptr; // do a shell split in case a friend has spaces in his name and we need
unsigned long friend_number = strtoul(argv[1], &endptr, 10); // 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, // extract message, add two if quotes are used
"%sInvalid friend number.", message = argv_eol[1] + strlen(recipient);
weechat_prefix("error")); if (*argv[1] == '"' || *argv[1] == '\'')
return WEECHAT_RC_OK; 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 // create chat buffer if it does not exist
struct t_twc_chat *chat = twc_chat_search_friend(profile, friend_number, true); struct t_twc_chat *chat = twc_chat_search_friend(profile, friend_number, true);
// send a message if provided // send a message if provided
if (argc >= 3) if (message)
twc_chat_send_message(chat, argv_eol[2], TWC_MESSAGE_TYPE_MESSAGE); twc_chat_send_message(chat,
weechat_string_strip(message, 1, 1, " "),
TWC_MESSAGE_TYPE_MESSAGE);
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
@ -851,8 +935,8 @@ twc_commands_init()
" || add" " || add"
" || remove %(tox_friend_name)|%(tox_friend_tox_id)" " || remove %(tox_friend_name)|%(tox_friend_tox_id)"
" || requests" " || requests"
" || accept %(tox_friend_name)|%(tox_friend_tox_id)" " || accept"
" || decline %(tox_friend_name)|%(tox_friend_tox_id)", " || decline",
twc_cmd_friend, NULL); twc_cmd_friend, NULL);
weechat_hook_command("group", weechat_hook_command("group",

View File

@ -17,6 +17,9 @@
* along with Tox-WeeChat. If not, see <http://www.gnu.org/licenses/>. * along with Tox-WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdio.h>
#include <weechat/weechat-plugin.h> #include <weechat/weechat-plugin.h>
#include "twc.h" #include "twc.h"
@ -78,10 +81,23 @@ twc_completion_friend(void *data,
{ {
char *name = twc_get_name_nt(profile->tox, friend_numbers[i]); 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, weechat_hook_completion_list_add(completion,
name, name,
0, 0,
WEECHAT_LIST_POS_SORT); WEECHAT_LIST_POS_SORT);
free(name);
} }
} }