1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-22 03:53:02 +01:00

No longer require quotes to enclose paths

This commit is contained in:
jfreegman 2018-10-08 00:47:51 -04:00
parent b6c746b5f5
commit 56e03a3f8b
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
12 changed files with 111 additions and 97 deletions

View File

@ -151,9 +151,9 @@ void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
if (argc != 1) {
if (argc < 1) {
error_str = "Path must be specified!";
error_str = "Path must be specified.";
} else {
error_str = "Only one argument allowed!";
error_str = "Only one argument allowed.";
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
@ -163,7 +163,7 @@ void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
fp = fopen(argv[1], "r");
if (fp == NULL) {
error_str = "Path does not exist!";
error_str = "Path does not exist.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
return;

View File

@ -38,5 +38,6 @@ int num_registered_handlers(void);
int help_max_width(void);
void draw_handler_help(WINDOW *win);
void invoke_autoruns(WINDOW *w, ToxWindow *self);
void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* API_H */

View File

@ -86,13 +86,15 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
}
/* looks for all instances in list that begin with the last entered word in line according to pos,
then fills line with the complete word. e.g. "Hello jo" would complete the line
with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
list is a pointer to the list of strings being compared, n_items is the number of items
in the list, and size is the size of each item in the list.
Returns the difference between the old len and new len of line on success, -1 if error */
* then fills line with the complete word. e.g. "Hello jo" would complete the line
* with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
*
* list is a pointer to the list of strings being compared, n_items is the number of items
* in the list, and size is the size of each item in the list.
*
* Returns the difference between the old len and new len of line on success.
* Returns -1 on error.
*/
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size)
{
ChatContext *ctx = self->chatwin;
@ -104,6 +106,7 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size
const char *L = (char *) list;
const char *endchrs = " ";
char ubuf[MAX_STR_SIZE];
memset(ubuf, 0, sizeof(ubuf));
/* work with multibyte string copy of buf for simplicity */
if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1) {
@ -123,7 +126,7 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size
snprintf(tmp, sizeof(tmp), "%s", ubuf);
tmp[ctx->pos] = '\0';
const char *s = dir_search ? strchr(tmp, '\"') : strrchr(tmp, ' ');
const char *s = strrchr(tmp, ' ');
char *sub = calloc(1, strlen(ubuf) + 1);
if (sub == NULL) {
@ -151,7 +154,7 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size
if (!sub[0]) {
free(sub);
return -1;
return 0;
}
int s_len = strlen(sub);
@ -188,7 +191,7 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size
if (dir_search) {
if (n_matches == 1) {
endchrs = char_rfind(match, '.', match_len) ? "\"" : "/";
endchrs = char_rfind(match, '.', match_len) ? "" : "/";
} else {
endchrs = "";
}
@ -231,8 +234,8 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size
return diff;
}
/* transforms a tab complete starting with the shorthand "~" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen)
/* Transforms a tab complete starting with the shorthand "~" into the full home directory. */
static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen)
{
ChatContext *ctx = self->chatwin;
@ -240,8 +243,8 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize, const cha
get_home_dir(homedir, sizeof(homedir));
char newline[MAX_STR_SIZE];
snprintf(newline, sizeof(newline), "%s \"%s%s", cmd, homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[cmdlen]);
snprintf(newline, sizeof(newline), "%s %s%s", cmd, homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[cmdlen-1]);
wchar_t wline[MAX_STR_SIZE];
@ -260,10 +263,13 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize, const cha
ctx->len = ctx->pos;
}
/* attempts to match /command "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */
/* Attempts to match /command <incomplete-dir> line to matching directories.
*
* If only one match, auto-complete line.
*
* Returns diff between old len and new len of ctx->line.
* Returns -1 if no matches or > 1 match.
*/
#define MAX_DIRS 512
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
@ -271,7 +277,7 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
char b_path[MAX_STR_SIZE];
char b_name[MAX_STR_SIZE];
char b_cmd[MAX_STR_SIZE];
const wchar_t *tmpline = &line[wcslen(cmd) + 2]; /* start after "/command \"" */
const wchar_t *tmpline = &line[wcslen(cmd) + 1]; /* start after "/command " */
if (wcs_to_mbs_buf(b_path, tmpline, sizeof(b_path)) == -1) {
return -1;
@ -282,7 +288,7 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
}
if (b_path[0] == '~') {
complt_home_dir(self, b_path, sizeof(b_path), b_cmd, strlen(b_cmd) + 2);
complete_home_dir(self, b_path, sizeof(b_path), b_cmd, strlen(b_cmd) + 2);
}
int si = char_rfind(b_path, '/', strlen(b_path));

View File

@ -1005,14 +1005,14 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
int diff = -1;
/* TODO: make this not suck */
if (wcsncmp(ctx->line, L"/sendfile \"", wcslen(L"/sendfile \"")) == 0) {
if (wcsncmp(ctx->line, L"/sendfile ", wcslen(L"/sendfile ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/sendfile");
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
} else if (wcsncmp(ctx->line, L"/avatar ", wcslen(L"/avatar ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
}
#ifdef PYTHON
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run \"")) == 0) {
else if (wcsncmp(ctx->line, L"/run ", wcslen(L"/run ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/run");
}

View File

@ -167,7 +167,7 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
}
if ((ft->file = fopen(ft->file_path, "a")) == NULL) {
const char *msg = "File transfer failed: Invalid file path.";
const char *msg = "File transfer failed: Invalid download path.";
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, notif_error);
return;
}
@ -225,16 +225,9 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return;
}
if (argv[1][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path must be enclosed in quotes.");
return;
}
/* remove opening and closing quotes */
char path[MAX_STR_SIZE];
snprintf(path, sizeof(path), "%s", &argv[1][1]);
int path_len = strlen(path) - 1;
path[path_len] = '\0';
snprintf(path, sizeof(path), "%s", argv[1]);
int path_len = strlen(path);
if (path_len >= MAX_STR_SIZE) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path exceeds character limit.");

View File

@ -107,23 +107,33 @@ static struct cmd_func group_commands[] = {
{ NULL, NULL },
};
#ifdef PYTHON
#define SPECIAL_COMMANDS 6
#else
#define SPECIAL_COMMANDS 5
#endif /* PYTHON */
/* Special commands are commands that only take one argument even if it contains spaces */
#define SPECIAL_COMMANDS 3
static const char special_commands[SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = {
"/avatar",
"/nick",
"/note",
#ifdef PYTHON
"/run",
#endif /* PYTHON */
"/title",
"/sendfile",
};
/* Returns true if input command is in the special_commands array. */
static bool is_special_command(const char *input)
{
int start = char_find(0, input, ' ');
int s = char_find(0, input, ' ');
int i;
for (i = 0; i < SPECIAL_COMMANDS; ++i) {
if (strncmp(input, special_commands[i], start) == 0) {
if (strncmp(input, special_commands[i], s) == 0) {
return true;
}
}
@ -134,19 +144,20 @@ static bool is_special_command(const char *input)
/* Parses commands in the special_commands array. Unlike parse_command, this function
* does not split the input string at spaces.
*
* Returns number of arguments on success, returns -1 on failure
* Returns the number of arguments.
*/
static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
{
int len = strlen(input);
int s = char_find(0, input, ' ');
if (s + 1 >= len) {
return -1;
memcpy(args[0], input, s);
args[0][s++] = '\0'; // increment to remove space after "/command "
if (s >= len) {
return 1; // No additional args
}
memcpy(args[0], input, s);
args[0][s++] = '\0'; /* increment to remove space after /command */
memcpy(args[1], input + s, len - s);
args[1][len - s] = '\0';
@ -154,7 +165,9 @@ static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input,
}
/* Parses input command and puts args into arg array.
Returns number of arguments on success, -1 on failure. */
*
* Returns the number of arguments.
*/
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
{
if (is_special_command(input)) {
@ -168,43 +181,32 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
}
int num_args = 0;
int i = 0; /* index of last char in an argument */
int i = 0; // index of last char in an argument
/* characters wrapped in double quotes count as one arg */
while (num_args < MAX_NUM_ARGS) {
int qt_ofst = 0; /* set to 1 to offset index for quote char at end of arg */
i = char_find(0, cmd, ' ');
memcpy(args[num_args], cmd, i);
args[num_args++][i] = '\0';
if (*cmd == '\"') {
qt_ofst = 1;
i = char_find(1, cmd, '\"');
if (cmd[i] == '\0') {
const char *errmsg = "Invalid argument. Did you forget a closing \"?";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
free(cmd);
return -1;
}
} else {
i = char_find(0, cmd, ' ');
}
memcpy(args[num_args], cmd, i + qt_ofst);
args[num_args++][i + qt_ofst] = '\0';
if (cmd[i] == '\0') { /* no more args */
if (cmd[i] == '\0') { // no more args
break;
}
char tmp[MAX_STR_SIZE];
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]);
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
strcpy(cmd, tmp); // tmp will always fit inside cmd
}
free(cmd);
return num_args;
}
/* Matches command to respective function. Returns 0 on match, 1 on no match */
/* Matches command to respective function.
*
* Returns 0 on match.
* Returns 1 on no match
*/
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
char (*args)[MAX_STR_SIZE])
{
@ -229,14 +231,15 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
char args[MAX_NUM_ARGS][MAX_STR_SIZE];
int num_args = parse_command(w, self, input, args);
if (num_args == -1) {
if (num_args <= 0) {
return;
}
/* Try to match input command to command functions. If non-global command mode is specified,
try specified mode's commands first, then upon failure try global commands.
Note: Global commands must come last in case of duplicate command names */
* try specified mode's commands first, then upon failure try global commands.
*
* Note: Global commands must come last in case of duplicate command names
*/
switch (mode) {
case CHAT_COMMAND_MODE:
if (do_command(w, self, m, num_args, chat_commands, args) == 0) {

View File

@ -201,21 +201,15 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (argc < 2 || strlen(argv[1]) < 3) {
if (argc != 1 || strlen(argv[1]) < 3) {
avatar_unset(m);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar is not set.");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar has been unset.");
return;
}
if (argv[1][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes.");
return;
}
/* remove opening and closing quotes */
char path[MAX_STR_SIZE];
snprintf(path, sizeof(path), "%s", &argv[1][1]);
int len = strlen(path) - 1;
snprintf(path, sizeof(path), "%s", argv[1]);
int len = strlen(path);
if (len <= 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid path.");
@ -502,16 +496,8 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
}
char nick[MAX_STR_SIZE];
size_t len = 0;
if (argv[1][0] == '\"') { /* remove opening and closing quotes */
snprintf(nick, sizeof(nick), "%s", &argv[1][1]);
len = strlen(nick) - 1;
nick[len] = '\0';
} else {
snprintf(nick, sizeof(nick), "%s", argv[1]);
len = strlen(nick);
}
snprintf(nick, sizeof(nick), "%s", argv[1]);
size_t len = strlen(nick);
if (!valid_nick(nick)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid name.");

View File

@ -507,12 +507,12 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) {
diff = complete_line(self, groupchats[self->num].name_list, groupchats[self->num].num_peers,
TOX_MAX_NAME_LENGTH);
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
} else if (wcsncmp(ctx->line, L"/avatar ", wcslen(L"/avatar ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
}
#ifdef PYTHON
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run \"")) == 0) {
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/run");
}

View File

@ -481,6 +481,25 @@ bool file_exists(const char *path)
return stat(path, &s) == 0;
}
/* Returns 0 if path points to a directory.
* Returns 1 if path points to a regular file.
* Returns -1 on any other result.
*/
int file_type(const char *path)
{
struct stat s;
stat(path, &s);
switch (s.st_mode & S_IFMT) {
case S_IFDIR:
return 0;
case S_IFREG:
return 1;
default:
return -1;
}
}
/* returns file size. If file doesn't exist returns 0. */
off_t file_size(const char *path)
{

View File

@ -146,6 +146,12 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes);
/* checks if a file exists. Returns true or false */
bool file_exists(const char *path);
/* Returns 0 if path points to a directory.
* Returns 1 if path points to a regular file.
* Returns -1 on any other result.
*/
int file_type(const char *path);
/* returns file size. If file doesn't exist returns 0. */
off_t file_size(const char *path);

View File

@ -247,12 +247,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ctx->len > 1 && ctx->line[0] == '/') {
int diff = -1;
if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
if (wcsncmp(ctx->line, L"/avatar ", wcslen(L"/avatar ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
}
#ifdef PYTHON
else if (wcsncmp(ctx->line, L"/run \"", wcslen(L"/run \"")) == 0) {
else if (wcsncmp(ctx->line, L"/run ", wcslen(L"/run ")) == 0) {
diff = dir_match(self, m, ctx->line, L"/run");
}

View File

@ -1355,7 +1355,7 @@ int main(int argc, char **argv)
/* set user avatar from config file. if no path is supplied tox_unset_avatar is called */
char avatarstr[PATH_MAX + 11];
snprintf(avatarstr, sizeof(avatarstr), "/avatar \"%s\"", user_settings->avatar_path);
snprintf(avatarstr, sizeof(avatarstr), "/avatar %s", user_settings->avatar_path);
execute(prompt->chatwin->history, prompt, m, avatarstr, GLOBAL_COMMAND_MODE);
time_t last_save = get_unix_time();