summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-08-09 09:29:56 -0700
committerirungentoo <irungentoo@gmail.com>2013-08-09 09:29:56 -0700
commit44902d15a720a0fb10550f03d00324db82b9531c (patch)
treef5c644e85fc1d16740ef3854d18b1c483b019486
parent79cbfb535e4b07ca76a6659b096623fab995f1c6 (diff)
parentb378a246a0b28f02e58c0a5d8c844c80b4dd50cd (diff)
Merge pull request #409 from lukechampine/betterprompt
make toxic handle input in a more sane manner
-rw-r--r--testing/toxic/prompt.c510
1 files changed, 265 insertions, 245 deletions
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index eaa8d7bc..e4eb259b 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -16,10 +16,44 @@ uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX
16uint8_t num_requests=0; // XXX 16uint8_t num_requests=0; // XXX
17 17
18extern void on_friendadded(int friendnumber); 18extern void on_friendadded(int friendnumber);
19static void print_usage(ToxWindow *self);
20static char prompt_buf[MAX_STR_SIZE] = {0}; 19static char prompt_buf[MAX_STR_SIZE] = {0};
21static int prompt_buf_pos = 0; 20static int prompt_buf_pos = 0;
22 21
22/* commands */
23void cmd_accept(ToxWindow *, char **);
24void cmd_add(ToxWindow *, char **);
25void cmd_clear(ToxWindow *, char **);
26void cmd_connect(ToxWindow *, char **);
27void cmd_help(ToxWindow *, char **);
28void cmd_msg(ToxWindow *, char **);
29void cmd_myid(ToxWindow *, char **);
30void cmd_nick(ToxWindow *, char **);
31void cmd_quit(ToxWindow *, char **);
32void cmd_status(ToxWindow *, char **);
33void cmd_statusmsg(ToxWindow *, char **);
34
35#define NUM_COMMANDS 13
36
37static struct {
38 char *name;
39 int numargs;
40 void (*func)(ToxWindow *, char **);
41} commands[] = {
42 { "accept", 1, cmd_accept },
43 { "add", 2, cmd_add },
44 { "clear", 0, cmd_clear },
45 { "connect", 3, cmd_connect },
46 { "exit", 0, cmd_quit },
47 { "help", 0, cmd_help },
48 { "msg", 2, cmd_msg },
49 { "myid", 0, cmd_myid },
50 { "nick", 1, cmd_nick },
51 { "q", 0, cmd_quit },
52 { "quit", 0, cmd_quit },
53 { "status", 2, cmd_status },
54 { "statusmsg", 1, cmd_statusmsg },
55};
56
23// XXX: 57// XXX:
24int add_req(uint8_t *public_key) 58int add_req(uint8_t *public_key)
25{ 59{
@@ -40,259 +74,268 @@ unsigned char *hex_string_to_bin(char hex_string[])
40 return val; 74 return val;
41} 75}
42 76
43static void execute(ToxWindow *self, char *u_cmd) 77void cmd_accept(ToxWindow *self, char **args)
44{ 78{
45 int newlines = 0; 79 int num = atoi(args[1]);
46 char cmd[MAX_STR_SIZE] = {0}; 80 if (num >= num_requests) {
47 int i; 81 wprintw(self->window, "Invalid syntax.\n");
48 for (i = 0; i < strlen(prompt_buf); ++i) { 82 return;
49 if (u_cmd[i] == '\n')
50 ++newlines;
51 else
52 cmd[i - newlines] = u_cmd[i];
53 } 83 }
54 84
55 int leading_spc = 0; 85 num = m_addfriend_norequest(pending_requests[num]);
56 for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i) 86 if (num == -1)
57 leading_spc++; 87 wprintw(self->window, "Failed to add friend.\n");
58 memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc); 88 else {
59 89 wprintw(self->window, "Friend accepted as: %d.\n", num);
60 int cmd_end = strlen(cmd); 90 on_friendadded(num);
61 while (cmd_end > 0 && cmd_end--)
62 if (!isspace(cmd[cmd_end]))
63 break;
64 cmd[cmd_end + 1] = '\0';
65
66/* What is this supposed to do?
67 if (cmd[0] == '/') {
68 wprintw(self->window,"Warning: Run your command without the /, this may not work\n");
69 int i;
70 for (i = 1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word
71 cmd[i - 1] = cmd[i]; //Still working on why
72 }
73 } 91 }
74*/ 92}
75 93
76 if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { 94void cmd_add(ToxWindow *self, char **args)
77 endwin(); 95{
78 exit(0); 96 uint8_t id_bin[KEY_SIZE_BYTES];
97 char xx[3];
98 uint32_t x;
99 char *id = args[1];
100 char *msg = args[2];
101
102 if (!id) {
103 wprintw(self->window, "Invalid command: add expected at least one argument.\n");
104 return;
79 } 105 }
106 if (!msg)
107 msg = "";
80 108
81 else if (!strncmp(cmd, "connect ", strlen("connect "))) { 109 if (strlen(id) != 2*KEY_SIZE_BYTES) {
82 IP_Port dht; 110 wprintw(self->window, "Invalid ID length.\n");
83 char *ip = strchr(cmd, ' '); 111 return;
84 if (ip == NULL) { 112 }
85 wprintw(self->window, "Invalid syntax.\n"); 113 int i;
86 return; 114 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
87 } 115 xx[0] = id[2*i];
88 ip++; 116 xx[1] = id[2*i+1];
89 117 xx[2] = '\0';
90 char *port = strchr(ip, ' '); 118 if (sscanf(xx, "%02x", &x) != 1) {
91 if (port == NULL) { 119 wprintw(self->window, "Invalid ID.\n");
92 wprintw(self->window, "Invalid syntax.\n");
93 return;
94 }
95 port[0] = 0;
96 port++;
97
98 char *key = strchr(port, ' ');
99 if (key == NULL) {
100 wprintw(self->window, "Invalid syntax.\n");
101 return;
102 }
103 key[0] = 0;
104 key++;
105
106 if (atoi(port) == 0) {
107 wprintw(self->window, "Invalid syntax.\n");
108 return; 120 return;
109 } 121 }
122 id_bin[i] = x;
123 }
124 int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
125 switch (num) {
126 case FAERR_TOOLONG:
127 wprintw(self->window, "Message is too long.\n");
128 break;
129 case FAERR_NOMESSAGE:
130 wprintw(self->window, "Please add a message to your request.\n");
131 break;
132 case FAERR_OWNKEY:
133 wprintw(self->window, "That appears to be your own ID.\n");
134 break;
135 case FAERR_ALREADYSENT:
136 wprintw(self->window, "Friend request already sent.\n");
137 break;
138 case FAERR_UNKNOWN:
139 wprintw(self->window, "Undefined error when adding friend.\n");
140 break;
141 default:
142 wprintw(self->window, "Friend added as %d.\n", num);
143 on_friendadded(num);
144 break;
145 }
146}
110 147
111 dht.port = htons(atoi(port)); 148void cmd_clear(ToxWindow *self, char **args)
112 uint32_t resolved_address = resolve_addr(ip); 149{
113 if (resolved_address == 0) { 150 wclear(self->window);
114 return; 151}
115 }
116 152
117 dht.ip.i = resolved_address; 153void cmd_connect(ToxWindow *self, char **args)
118 unsigned char *binary_string = hex_string_to_bin(key); 154{
119 DHT_bootstrap(dht, binary_string); 155 IP_Port dht;
120 free(binary_string); 156 char *ip = args[1];
157 char *port = args[2];
158 char *key = args[3];
159
160 if (atoi(port) == 0) {
161 wprintw(self->window, "Invalid syntax.\n");
162 return;
121 } 163 }
122 164
123 else if (!strncmp(cmd, "add ", strlen("add "))) { 165 dht.port = htons(atoi(port));
124 uint8_t id_bin[KEY_SIZE_BYTES]; 166 uint32_t resolved_address = resolve_addr(ip);
125 char xx[3]; 167 if (resolved_address == 0) {
126 uint32_t x; 168 return;
127 char *id = strchr(cmd, ' ');
128 if (id == NULL) {
129 wprintw(self->window, "Invalid syntax.\n");
130 return;
131 }
132 id++;
133 char *msg = strchr(id, ' ');
134 if (msg != NULL) {
135 msg[0] = 0;
136 msg++;
137 }
138 else msg = "";
139 if (strlen(id) != 2*KEY_SIZE_BYTES) {
140 wprintw(self->window, "Invalid ID length.\n");
141 return;
142 }
143 int i;
144 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
145 xx[0] = id[2*i];
146 xx[1] = id[2*i+1];
147 xx[2] = '\0';
148 if (sscanf(xx, "%02x", &x) != 1) {
149 wprintw(self->window, "Invalid ID.\n");
150 return;
151 }
152 id_bin[i] = x;
153 }
154 int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1);
155 switch (num) {
156 case -1:
157 wprintw(self->window, "Message is too long.\n");
158 break;
159 case -2:
160 wprintw(self->window, "Please add a message to your request.\n");
161 break;
162 case -3:
163 wprintw(self->window, "That appears to be your own ID.\n");
164 break;
165 case -4:
166 wprintw(self->window, "Friend request already sent.\n");
167 break;
168 case -5:
169 wprintw(self->window, "Undefined error when adding friend.\n");
170 break;
171 default:
172 wprintw(self->window, "Friend added as %d.\n", num);
173 on_friendadded(num);
174 break;
175 }
176 } 169 }
177 170
178 else if (!strcmp(cmd, "clear")) { 171 dht.ip.i = resolved_address;
179 wclear(self->window); 172 unsigned char *binary_string = hex_string_to_bin(key);
180 } 173 DHT_bootstrap(dht, binary_string);
174 free(binary_string);
175}
181 176
182 else if (!strcmp(cmd, "help")) { 177void cmd_quit(ToxWindow *self, char **args)
183 wclear(self->window); 178{
184 print_usage(self); 179 endwin();
185 } 180 exit(0);
181}
186 182
187 else if (!strncmp(cmd, "status ", strlen("status "))) { 183void cmd_help(ToxWindow *self, char **args)
188 char *status = strchr(cmd, ' '); 184{
189 char *msg; 185 wclear(self->window);
190 char *status_text; 186 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
191 if (status == NULL) { 187 wprintw(self->window, "Commands:\n");
192 wprintw(self->window, "Invalid syntax.\n"); 188 wattroff(self->window, A_BOLD);
193 return;
194 }
195 status++;
196 USERSTATUS status_kind;
197 if (!strncmp(status, "online", strlen("online"))) {
198 status_kind = USERSTATUS_NONE;
199 status_text = "ONLINE";
200 }
201 189
202 else if (!strncmp(status, "away", strlen("away"))) { 190 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
203 status_kind = USERSTATUS_AWAY; 191 wprintw(self->window, " add <id> <message> : Add friend\n");
204 status_text = "AWAY"; 192 wprintw(self->window, " status <type> <message> : Set your status\n");
205 } 193 wprintw(self->window, " statusmsg <message> : Set your status\n");
194 wprintw(self->window, " nick <nickname> : Set your nickname\n");
195 wprintw(self->window, " accept <number> : Accept friend request\n");
196 wprintw(self->window, " myid : Print your ID\n");
197 wprintw(self->window, " quit/exit : Exit program\n");
198 wprintw(self->window, " help : Print this message again\n");
199 wprintw(self->window, " clear : Clear this window\n");
200
201 wattron(self->window, A_BOLD);
202 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
203 wattroff(self->window, A_BOLD);
206 204
207 else if (!strncmp(status, "busy", strlen("busy"))) { 205 wattroff(self->window, COLOR_PAIR(2));
208 status_kind = USERSTATUS_BUSY; 206}
209 status_text = "BUSY";
210 }
211 207
212 else 208void cmd_msg(ToxWindow *self, char **args)
213 { 209{
214 wprintw(self->window, "Invalid status.\n"); 210 char *id = args[1];
215 return; 211 char *msg = args[2];
216 } 212 if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0)
213 wprintw(self->window, "Error occurred while sending message.\n");
214 else
215 wprintw(self->window, "Message successfully sent.\n");
216}
217 217
218 msg = strchr(status, ' '); 218void cmd_myid(ToxWindow *self, char **args)
219 if (msg == NULL) { 219{
220 m_set_userstatus(status_kind); 220 char id[KEY_SIZE_BYTES*2 + 1] = {0};
221 wprintw(self->window, "Status set to: %s\n", status_text); 221 size_t i;
222 } 222 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
223 else { 223 char xx[3];
224 msg++; 224 snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff);
225 m_set_userstatus(status_kind); 225 strcat(id, xx);
226 m_set_statusmessage((uint8_t*) msg, strlen(msg)+1);
227 wprintw(self->window, "Status set to: %s, %s\n", status_text, msg);
228 }
229 } 226 }
227 wprintw(self->window, "Your ID: %s\n", id);
228}
230 229
231 else if (!strncmp(cmd, "nick ", strlen("nick "))) { 230void cmd_nick(ToxWindow *self, char **args)
232 char *nick = strchr(cmd, ' '); 231{
233 if (nick == NULL) { 232 char *nick = args[1];
234 wprintw(self->window, "Invalid syntax.\n"); 233 setname((uint8_t*) nick, strlen(nick)+1);
235 return; 234 wprintw(self->window, "Nickname set to: %s\n", nick);
236 } 235}
237 nick++;
238 setname((uint8_t*) nick, strlen(nick)+1);
239 wprintw(self->window, "Nickname set to: %s\n", nick);
240 }
241 236
242 else if (!strcmp(cmd, "myid")) { 237void cmd_status(ToxWindow *self, char **args)
243 char id[KEY_SIZE_BYTES*2 + 1] = {0}; 238{
244 size_t i; 239 char *status = args[1];
245 for (i = 0; i < KEY_SIZE_BYTES; ++i) { 240 char *status_text;
246 char xx[3]; 241
247 snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); 242 USERSTATUS status_kind;
248 strcat(id, xx); 243 if (!strncmp(status, "online", strlen("online"))) {
249 } 244 status_kind = USERSTATUS_NONE;
250 wprintw(self->window, "Your ID: %s\n", id); 245 status_text = "ONLINE";
246 }
247 else if (!strncmp(status, "away", strlen("away"))) {
248 status_kind = USERSTATUS_AWAY;
249 status_text = "AWAY";
250 }
251 else if (!strncmp(status, "busy", strlen("busy"))) {
252 status_kind = USERSTATUS_BUSY;
253 status_text = "BUSY";
254 }
255 else
256 {
257 wprintw(self->window, "Invalid status.\n");
258 return;
251 } 259 }
252 260
253 else if (!strncmp(cmd, "accept ", strlen("accept "))) { 261 char *msg = args[2];
254 char *id = strchr(cmd, ' '); 262 if (msg == NULL) {
255 if (id == NULL) { 263 m_set_userstatus(status_kind);
256 wprintw(self->window, "Invalid syntax.\n"); 264 wprintw(self->window, "Status set to: %s\n", status_text);
257 return; 265 }
258 } 266 else {
259 id++; 267 m_set_userstatus(status_kind);
268 m_set_statusmessage((uint8_t*) msg, strlen(msg)+1);
269 wprintw(self->window, "Status set to: %s, %s\n", status_text, msg);
270 }
271}
260 272
261 int num = atoi(id); 273void cmd_statusmsg(ToxWindow *self, char **args)
262 if (num >= num_requests) { 274{
263 wprintw(self->window, "Invalid syntax.\n"); 275 char *msg = args[1];
264 return; 276 m_set_statusmessage((uint8_t*) msg, strlen(msg)+1);
265 } 277 wprintw(self->window, "Status set to: %s\n", msg);
278}
266 279
267 num = m_addfriend_norequest(pending_requests[num]); 280static void execute(ToxWindow *self, char *u_cmd)
268 if (num == -1) 281{
269 wprintw(self->window, "Failed to add friend.\n"); 282 int newlines = 0;
270 else { 283 char cmd[MAX_STR_SIZE] = {0};
271 wprintw(self->window, "Friend accepted as: %d.\n", num); 284 int i;
272 on_friendadded(num); 285 for (i = 0; i < strlen(prompt_buf); ++i) {
273 } 286 if (u_cmd[i] == '\n')
287 ++newlines;
288 else
289 cmd[i - newlines] = u_cmd[i];
274 } 290 }
275 291
276 else if (!strncmp(cmd, "msg ", strlen("msg "))) { 292 int leading_spc = 0;
277 char *id = strchr(cmd, ' '); 293 for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i)
278 if (id == NULL) { 294 leading_spc++;
279 wprintw(self->window, "Invalid syntax.\n"); 295 memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc);
280 return; 296
281 } 297 int cmd_end = strlen(cmd);
282 char *msg = strchr(++id, ' '); 298 while (cmd_end > 0 && cmd_end--)
283 if (msg == NULL) { 299 if (!isspace(cmd[cmd_end]))
284 wprintw(self->window, "Invalid syntax.\n"); 300 break;
301 cmd[cmd_end + 1] = '\0';
302
303 char *args[4];
304 args[0] = strtok(cmd, " ");
305
306 /* no input */
307 if (!args[0])
308 return;
309
310 /* match input to command list */
311 for (i = 0; i < NUM_COMMANDS; i++) {
312 if (!strcmp(args[0], commands[i].name)) {
313 /* read in arguments */
314 int j;
315 for (j = 1; j <= commands[i].numargs; j++) {
316 args[j] = strtok(NULL, " ");
317 /* check for missing arguments */
318 /* add is special because it can take either 1 or 2 arguments */
319 if (strcmp(args[0], "add") != 0 && args[j] == NULL) {
320 wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n",
321 commands[i].name, commands[i].numargs, j - 1);
322 return;
323 }
324 }
325 /* check for excess arguments */
326 /* add is special because the add message may contain spaces */
327 if (strcmp(args[0], "add") != 0 && strtok(NULL, " ") != NULL) {
328 wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name);
329 return;
330 }
331 /* pass arguments to command function */
332 (commands[i].func)(self, args);
285 return; 333 return;
286 } 334 }
287 msg[0] = 0;
288 msg++;
289 if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0)
290 wprintw(self->window, "Error occurred while sending message.\n");
291 else
292 wprintw(self->window, "Message successfully sent.\n");
293 } 335 }
294 else 336
295 wprintw(self->window, "Invalid command.\n"); 337 /* no match */
338 wprintw(self->window, "Invalid command.\n");
296} 339}
297 340
298static void prompt_onKey(ToxWindow *self, int key) 341static void prompt_onKey(ToxWindow *self, int key)
@@ -352,33 +395,10 @@ static void prompt_onDraw(ToxWindow *self)
352 wrefresh(self->window); 395 wrefresh(self->window);
353} 396}
354 397
355static void print_usage(ToxWindow *self)
356{
357 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
358 wprintw(self->window, "Commands:\n");
359 wattroff(self->window, A_BOLD);
360
361 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
362 wprintw(self->window, " add <id> <message> : Add friend\n");
363 wprintw(self->window, " status <type> <message> : Set your status\n");
364 wprintw(self->window, " nick <nickname> : Set your nickname\n");
365 wprintw(self->window, " accept <number> : Accept friend request\n");
366 wprintw(self->window, " myid : Print your ID\n");
367 wprintw(self->window, " quit/exit : Exit program\n");
368 wprintw(self->window, " help : Print this message again\n");
369 wprintw(self->window, " clear : Clear this window\n");
370
371 wattron(self->window, A_BOLD);
372 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
373 wattroff(self->window, A_BOLD);
374
375 wattroff(self->window, COLOR_PAIR(2));
376}
377
378static void prompt_onInit(ToxWindow *self) 398static void prompt_onInit(ToxWindow *self)
379{ 399{
380 scrollok(self->window, 1); 400 scrollok(self->window, 1);
381 print_usage(self); 401 cmd_help(self, NULL);
382 wclrtoeol(self->window); 402 wclrtoeol(self->window);
383} 403}
384 404