1 #include "commands.h"
2 
3 #include "command_funcs.h"
4 #include "debug.h"
5 #include "flist.h"
6 #include "tox.h"
7 
8 #include "layout/friend.h" // TODO, we should try to remove this dependency
9 #include "ui/edit.h"
10 
11 #include <string.h>
12 
13 struct Command commands[MAX_NUM_CMDS] = {
14     { "alias",    5, slash_alias     },
15     { "invite",   6, slash_invite    },
16     { "d",        1, slash_device    },
17     { "sendfile", 8, slash_send_file },
18     { "topic",    5, slash_topic     },
19     { NULL,       0, NULL            },
20 };
21 
utox_run_command(char * string,uint16_t string_length,char ** cmd,char ** argument,int trusted)22 uint16_t utox_run_command(char *string, uint16_t string_length, char **cmd, char **argument, int trusted) {
23     if (trusted == 0) {
24         return 0; /* We don't currently support commands from non-trusted sources, before you run commands from friends
25                    * or elsewhere, you MUST implement error checking better than what exists */
26     }
27 
28     uint16_t cmd_length = 0, argument_length = 0;
29 
30     if (string[0] == '/') { /* Cool it's a command we support! */
31         // LOG_TRACE("Commands", "command found!" );
32         uint16_t i;
33         for (i = 0; i < string_length; ++i) {
34             if (string[i] == ' ') {
35                 cmd_length = i;
36                 break;
37             }
38         }
39 
40         ++i;
41         for (; i < string_length; ++i) {
42             if (string[i] != ' ') {
43                 argument_length = string_length - i;
44                 *argument       = string + i;
45                 break;
46             }
47         }
48 
49         if (cmd_length) {
50             --cmd_length;
51             *cmd = string + 1;
52         }
53     } else {
54         // LOG_TRACE("Commands", "No command found" ); /* Sad, we don't support this command. */
55         *argument = string;
56         cmd       = NULL;
57         return 0;
58     }
59 
60     int i = 0;
61     while(commands[i].cmd){
62         if (commands[i].cmd_length == cmd_length && memcmp(commands[i].cmd, *cmd, cmd_length) == 0) {
63             void* object = flist_get_friend() ? (void*)flist_get_friend() : (void*)flist_get_groupchat();
64             bool ret = commands[i].func(object, *argument, argument_length);
65             if (ret) {
66                 cmd_length = -1;
67             }
68             break;
69         }
70         i++;
71     }
72 
73     return cmd_length;
74 }
75 
76 bool g_select_add_friend_later = 0;
77 
do_tox_url(uint8_t * url_string,int len)78 void do_tox_url(uint8_t *url_string, int len) {
79     LOG_TRACE("Commands", "Command: %.*s" , len, url_string);
80 
81     //! lacks max length checks, writes to inputs even on failure, no notice of failure
82     // doesn't reset unset inputs
83 
84     // slashes are removed later
85     if (len > 4 && memcmp(url_string, "tox:", 4) == 0) {
86         url_string += 4;
87         len -= 4;
88     } else {
89         return;
90     }
91 
92     // wtf??
93     uint8_t  *b = (uint8_t *)edit_add_new_friend_id.data, *a = url_string, *end = url_string + len;
94     uint16_t *l = &edit_add_new_friend_id.length;
95     *l          = 0;
96     while (a != end) {
97         switch (*a) {
98             case 'a' ... 'z':
99             case 'A' ... 'Z':
100             case '0' ... '9':
101             case '@':
102             case '.':
103             case ' ': {
104                 *b++ = *a;
105                 *l   = *l + 1;
106                 break;
107             }
108 
109             case '+': {
110                 *b++ = ' ';
111                 *l   = *l + 1;
112                 break;
113             }
114 
115             case '?':
116             case '&': {
117                 a++;
118                 if (end - a >= 8 && memcmp(a, "message=", 8) == 0) {
119                     b  = (uint8_t *)edit_add_new_friend_msg.data;
120                     l  = &edit_add_new_friend_msg.length;
121                     *l = 0;
122                     a += 7;
123                 } else {
124                     // skip everythng up to the next &
125                     while (*a != '&' && a != end) {
126                         a++;
127                     }
128                     // set the track back to the & so we can proceed normally
129                     a--;
130                 }
131                 break;
132             }
133 
134             case '/': {
135                 break;
136             }
137 
138             default: {
139                 return;
140             }
141         }
142         a++;
143     }
144 
145     if (tox_thread_init != UTOX_TOX_THREAD_INIT_SUCCESS) {
146         // if we receive a URL event before the profile is loaded, save it for later.
147         // this usually happens when we are launched as the result of a URL click.
148         g_select_add_friend_later = 1;
149     } else {
150         flist_selectaddfriend();
151     }
152 }
153