1 /*
2  * gaim
3  *
4  * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21 
22 
23 /*
24  * Heavily modified by Nadeem Riaz (nads@bleh.org)
25  * for use in libtoc
26  */
27 
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <string.h>
34 #include <sys/socket.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <time.h>
39 #include "toc.h"
40 
41 /* descriptor for talking to TOC */
42 static int toc_fd;
43 static int seqno;
44 static unsigned int peer_ver=0;
45 int state;
46 /* static int inpa=-1; */
47 int permdeny = PERMIT_PERMITALL;
48 
toc_login(char * username,char * password)49 int toc_login(char *username, char *password)
50 {
51 	char *config;
52 	struct in_addr *sin;
53 	char buf[80];
54 	char buf2[2048];
55 
56 	toc_debug_printf("looking up host! %s", aim_host);
57 
58 	sin = (struct in_addr *)get_address(aim_host);
59 	if (!sin) {
60 		set_state(STATE_OFFLINE);
61 		toc_msg_printf(TOC_CONNECT_MSGS,"Unable to lookup %s", aim_host);
62 		return -1;
63 	}
64 
65 	snprintf(toc_addy, sizeof(toc_addy), "%s", inet_ntoa(*sin));
66 	snprintf(buf, sizeof(buf), "Connecting to %s", inet_ntoa(*sin));
67 
68 	toc_msg_printf(TOC_CONNECT_MSGS,"%s",buf);
69 
70 	toc_fd = connect_address(sin->s_addr, aim_port);
71 
72         if (toc_fd < 0) {
73                 set_state(STATE_OFFLINE);
74 		toc_msg_printf(TOC_CONNECT_MSGS,"Connect to %s failed", inet_ntoa(*sin));
75 		return -1;
76         }
77 
78         free(sin);
79 
80 	toc_msg_printf(TOC_CONNECT_MSGS,"Signon: %s",username);
81 
82 	if (toc_signon(username, password) < 0) {
83                 set_state(STATE_OFFLINE);
84 		toc_msg_printf(TOC_CONNECT_MSGS,"Disconnected.");
85 		return -1;
86 	}
87 
88 	toc_msg_printf(TOC_CONNECT_MSGS,"Waiting for reply...");
89 	if (toc_wait_signon() < 0) {
90                 set_state(STATE_OFFLINE);
91 		toc_msg_printf(TOC_CONNECT_MSGS,"Authentication Failed");
92 		return -1;
93 	}
94 
95 
96 	snprintf(aim_username, sizeof(aim_username), "%s", username);
97 	snprintf(aim_password, sizeof(aim_password), "%s", password);
98 
99 	save_prefs();
100 
101 	toc_msg_printf(TOC_CONNECT_MSGS,"Retrieving config...");
102         if ((config=toc_wait_config()) == NULL) {
103 		toc_msg_printf(TOC_CONNECT_MSGS,"No Configuration\n");
104 		set_state(STATE_OFFLINE);
105 		return -1;
106 
107 	}
108 
109 	init_lists();
110 /*        gtk_widget_hide(mainwindow);
111 	show_buddy_list();  */
112         parse_toc_buddy_list(config);
113 /*        refresh_buddy_window(); */
114 
115 	snprintf(buf2, sizeof(buf2), "toc_init_done");
116 	sflap_send(buf2, -1, TYPE_DATA);
117 
118         serv_finish_login();
119 	return 0;
120 }
121 
toc_close()122 void toc_close()
123 {
124         seqno = 0;
125         state = STATE_OFFLINE;
126 	toc_remove_input_stream(toc_fd);
127 	close(toc_fd);
128 	toc_fd=-1;
129 }
130 
toc_signon(char * username,char * password)131 int toc_signon(char *username, char *password)
132 {
133 	char buf[BUF_LONG];
134 	int res;
135 	struct signon so;
136 
137     	toc_debug_printf("State = %d\n", state);
138 
139 	strncpy(aim_username, username, sizeof(aim_username));
140 
141 	if ((res = write(toc_fd, FLAPON, strlen(FLAPON))) < 0)
142 		return res;
143 	/* Wait for signon packet */
144 
145 	state = STATE_FLAPON;
146 
147 	if ((res = wait_reply(buf, sizeof(buf)) < 0))
148 		return res;
149 
150 	if (state != STATE_SIGNON_REQUEST) {
151 			toc_debug_printf( "State should be %d, but is %d instead\n", STATE_SIGNON_REQUEST, state);
152 			return -1;
153 	}
154 
155 	/* Compose a response */
156 
157 	snprintf(so.username, sizeof(so.username), "%s", username);
158 	so.ver = ntohl(1);
159 	so.tag = ntohs(1);
160 	so.namelen = htons(strlen(so.username));
161 
162 	sflap_send((char *)&so, ntohs(so.namelen) + 8, TYPE_SIGNON);
163 
164 	snprintf(buf, sizeof(buf),
165 		"toc_signon %s %d %s %s %s \"%s\"",
166 		login_host, login_port, normalize(username), roast_password(password), LANGUAGE, REVISION);
167 
168         toc_debug_printf("Send: %s\n", buf);
169 
170 	return sflap_send(buf, -1, TYPE_DATA);
171 }
172 
toc_wait_signon()173 int toc_wait_signon()
174 {
175 	/* Wait for the SIGNON to be approved */
176 	char buf[BUF_LEN];
177 	int res;
178 	res = wait_reply(buf, sizeof(buf));
179 	if (res < 0)
180 		return res;
181 	if (state != STATE_SIGNON_ACK) {
182 			toc_debug_printf("State should be %d, but is %d instead\n",STATE_SIGNON_ACK, state);
183 		return -1;
184 	}
185 	return 0;
186 }
187 
188 
wait_reply(char * buffer,int buflen)189 int wait_reply(char *buffer, int buflen)
190 {
191         int res=6;
192 	struct sflap_hdr *hdr=(struct sflap_hdr *)buffer;
193         char *c;
194 
195         while((res = read(toc_fd, buffer, 1))) {
196 		if (res < 0)
197 			return res;
198 		if (buffer[0] == '*')
199                         break;
200 
201 	}
202 
203 	res = read(toc_fd, buffer+1, sizeof(struct sflap_hdr) - 1);
204 
205         if (res < 0)
206 		return res;
207 
208 	res += 1;
209 
210 
211 	toc_debug_printf( "Rcv: %s %s\n",print_header(buffer), "");
212 
213         while (res < (sizeof(struct sflap_hdr) + ntohs(hdr->len))) {
214 		res += read(toc_fd, buffer + res, (ntohs(hdr->len) + sizeof(struct sflap_hdr)) - res);
215 		/* while(gtk_events_pending())
216 			gtk_main_iteration(); */
217 	}
218 
219         if (res >= sizeof(struct sflap_hdr))
220 		buffer[res]='\0';
221 	else
222 		return res - sizeof(struct sflap_hdr);
223 
224 	switch(hdr->type) {
225 	case TYPE_SIGNON:
226 		memcpy(&peer_ver, buffer + sizeof(struct sflap_hdr), 4);
227 		peer_ver = ntohl(peer_ver);
228 		seqno = ntohs(hdr->seqno);
229 		state = STATE_SIGNON_REQUEST;
230 		break;
231 	case TYPE_DATA:
232 		if (!strncasecmp(buffer + sizeof(struct sflap_hdr), "SIGN_ON:", strlen("SIGN_ON:")))
233 			state = STATE_SIGNON_ACK;
234 		else if (!strncasecmp(buffer + sizeof(struct sflap_hdr), "CONFIG:", strlen("CONFIG:"))) {
235 			state = STATE_CONFIG;
236 		} else if (state != STATE_ONLINE && !strncasecmp(buffer + sizeof(struct sflap_hdr), "ERROR:", strlen("ERROR:"))) {
237 			c = strtok(buffer + sizeof(struct sflap_hdr) + strlen("ERROR:"), ":");
238 			translate_toc_error_code(c);
239 			toc_debug_printf("ERROR CODE: %s\n",c);
240 		}
241 
242 		toc_debug_printf("Data: %s\n",buffer + sizeof(struct sflap_hdr));
243 
244 		break;
245 	default:
246 			toc_debug_printf("Unknown/unimplemented packet type %d\n",hdr->type);
247 	}
248         return res;
249 }
250 
sflap_send(char * buf,int olen,int type)251 int sflap_send(char *buf, int olen, int type)
252 {
253 	int len;
254 	int slen=0;
255 	struct sflap_hdr hdr;
256 	char obuf[MSG_LEN];
257 
258         /* One _last_ 2048 check here!  This shouldn't ever
259          * get hit though, hopefully.  If it gets hit on an IM
260          * It'll lose the last " and the message won't go through,
261          * but this'll stop a segfault. */
262         if (strlen(buf) > (MSG_LEN - sizeof(hdr))) {
263                 buf[MSG_LEN - sizeof(hdr) - 3] = '"';
264                 buf[MSG_LEN - sizeof(hdr) - 2] = '\0';
265         }
266 
267         toc_debug_printf("%s [Len %d]\n", buf, strlen(buf));
268 
269 
270 	if (olen < 0)
271 		len = escape_message(buf);
272 	else
273 		len = olen;
274 	hdr.ast = '*';
275 	hdr.type = type;
276 	hdr.seqno = htons(seqno++ & 0xffff);
277         hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1));
278 
279 	toc_debug_printf("Escaped message is '%s'\n",buf);
280 
281 	memcpy(obuf, &hdr, sizeof(hdr));
282 	slen += sizeof(hdr);
283 	memcpy(&obuf[slen], buf, len);
284 	slen += len;
285 	if (type != TYPE_SIGNON) {
286 		obuf[slen]='\0';
287 		slen += 1;
288 	}
289 	/* print_buffer(obuf, slen); */
290 
291 	return write(toc_fd, obuf, slen);
292 }
293 
roast_password(char * pass)294 unsigned char *roast_password(char *pass)
295 {
296 	/* Trivial "encryption" */
297 	static char rp[256];
298 	static char *roast = ROAST;
299 	int pos=2;
300 	int x;
301 	strcpy(rp, "0x");
302 	for (x=0;(x<150) && pass[x]; x++)
303 		pos+=sprintf(&rp[pos],"%02x", pass[x] ^ roast[x % strlen(roast)]);
304 	rp[pos]='\0';
305         return rp;
306 }
307 
print_header(void * hdr_v)308 char *print_header(void *hdr_v)
309 {
310 	static char s[80];
311 	struct sflap_hdr *hdr = (struct sflap_hdr *)hdr_v;
312 	snprintf(s,sizeof(s), "[ ast: %c, type: %d, seqno: %d, len: %d ]",
313 		hdr->ast, hdr->type, ntohs(hdr->seqno), ntohs(hdr->len));
314 	return s;
315 }
316 
toc_callback(int fd)317 int toc_callback(int fd)
318 {
319         char *buf;
320 	char *c;
321 	char **args = NULL;
322 	char *dup,*raw;
323         char *l;
324 	int numargs =0;
325 
326         buf = malloc(BUF_LONG);
327 
328         if (wait_reply(buf, BUF_LONG) < 0) {
329                 toc_signoff();
330 		toc_debug_printf("need to do proper sign off on this\n");
331 		toc_msg_printf(TOC_CONNECT_MSGS,"Connection Closed");
332 		return -1;
333         }
334 
335         dup = strdup(buf+sizeof(struct sflap_hdr));
336 	raw = rindex(dup,':');
337 	c=strtok(buf+sizeof(struct sflap_hdr),":");	/* Ditch the first part */
338 	if (!strcasecmp(c,"UPDATE_BUDDY")) {
339 		char *uc, *t;
340 		int logged, evil, idle, type = 0;
341 		long signon;
342 		time_t time_idle;
343 
344 		numargs = 7;
345 		args = (char **) malloc(sizeof(char *)*numargs);
346 		use_handler(TOC_RAW_HANDLE,TOC_UPDATE_BUDDY,raw);
347 		c = strtok(NULL,":"); /* c is name */
348 		args[0] = strdup(c);
349 
350 		l = strtok(NULL,":"); /* l is T/F logged status */
351        		args[1] = strdup(l);
352 
353 		t = strtok(NULL, ":");
354 		args[2] = strdup(t);
355 		sscanf(t, "%d", &evil);
356 
357 		t = strtok(NULL, ":");
358 		args[3] = strdup(t);
359 		sscanf(t, "%ld", &signon);
360 
361 		t = strtok(NULL, ":");
362 		args[4] = strdup(t);
363 		sscanf(t, "%d", &idle);
364 
365                 uc = strtok(NULL, ":");
366 		args[5] = strdup(uc);
367 
368 		if (!strncasecmp(l,"T",1))
369 			logged = 1;
370 		else
371 			logged = 0;
372 
373 
374 		if (uc[0] == 'A')
375 			type |= UC_AOL;
376 
377 		switch(uc[1]) {
378 		case 'A':
379 			type |= UC_ADMIN;
380 			break;
381 		case 'U':
382 			type |= UC_UNCONFIRMED;
383 			break;
384 		case 'O':
385 			type |= UC_NORMAL;
386 			break;
387 		default:
388 			break;
389 		}
390 
391                 switch(uc[2]) {
392 		case 'U':
393 			type |= UC_UNAVAILABLE;
394 			break;
395 		default:
396 			break;
397 		}
398 
399                 if (idle) {
400                         time(&time_idle);
401                         time_idle -= idle*60;
402                 } else
403                         time_idle = 0;
404 
405 		serv_got_update(c, logged, evil, signon, time_idle, type);
406 		args[6] = NULL;
407 		use_handler(TOC_HANDLE,TOC_UPDATE_BUDDY,args);
408 	} else if (!strcasecmp(c, "ERROR")) {
409 		use_handler(TOC_RAW_HANDLE,TOC_ERROR,raw);
410 		c = strtok(NULL,":");
411 		translate_toc_error_code(c);
412 		args = (char **) malloc(sizeof(char *)*1 + 1);
413 		numargs = 1;
414 		args[0] = strdup(c);
415 		use_handler(TOC_HANDLE,TOC_ERROR,args);
416 		toc_debug_printf("ERROR: %s",c);
417 	} else if (!strcasecmp(c, "NICK")) {
418 		use_handler(TOC_RAW_HANDLE,TOC_NICK,raw);
419 		c = strtok(NULL,":");
420 		snprintf(aim_username, sizeof(aim_username), "%s", c);
421 		numargs = 2;
422 		args = (char **) malloc(sizeof(char *)*numargs);
423 		args[0] = strdup(c);
424 		args[1] = NULL;
425 		use_handler(TOC_HANDLE,TOC_NICK,args);
426 	} else if (!strcasecmp(c, "IM_IN")) {
427 		char *away, *message;
428                 int a = 0;
429 		use_handler(TOC_RAW_HANDLE,TOC_IM_IN,raw);
430 		c = strtok(NULL,":");
431 		away = strtok(NULL,":");
432 
433 		message = away;
434 
435                 while(*message && (*message != ':'))
436                         message++;
437 
438                 message++;
439 
440 		if (!strncasecmp(away, "T", 1))
441 			a = 1;
442 
443 		if ( serv_got_im(c, message,a) > 0 ) {
444 			numargs = 3;
445 			args = (char **) malloc(sizeof(char *)*numargs);
446 			args[0] = strdup(c);
447 			args[1] = strdup(message);
448 			args[2] = NULL;
449 			use_handler(TOC_HANDLE,TOC_IM_IN,args);
450 		}
451 	} else if (!strcasecmp(c, "GOTO_URL")) {
452 		char *name;
453 		char *url;
454 
455 		char tmp[256];
456 
457 		use_handler(TOC_RAW_HANDLE,TOC_GOTO_URL,raw);
458 		name = strtok(NULL, ":");
459 		url = strtok(NULL, ":");
460 
461 
462 		snprintf(tmp, sizeof(tmp), "http://%s:%d/%s", toc_addy, aim_port, url);
463 /*		fprintf(stdout, "Name: %s\n%s\n", name, url);
464 		printf("%s", grab_url(tmp));*/
465 
466 		numargs = 2;
467 		args = (char **) malloc(sizeof(char *)*numargs);
468 		args[0] = strdup(tmp);
469 		args[1] = NULL;
470 		use_handler(TOC_HANDLE,TOC_GOTO_URL,args);
471 		/* statusprintf("GOTO_URL: %s","tmp"); */
472         } else if (!strcasecmp(c, "EVILED")) {
473                 int lev;
474 		char *name = NULL;
475 		char *levc;
476 
477 		use_handler(TOC_RAW_HANDLE,TOC_EVILED,raw);
478 		levc = strtok(NULL, ":");
479                 sscanf(levc, "%d", &lev);
480                 name = strtok(NULL, ":");
481 
482                 toc_debug_printf("evil: %s | %d\n", name, lev);
483 
484 		numargs = 3;
485 		my_evil = lev;
486 		args = (char **) malloc(sizeof(char *)*numargs);
487 		if ( name != NULL )
488 			args[0] = strdup(name);
489 		else
490 			args[0] = NULL;
491 		args[1] = strdup(levc);
492 		args[2] = NULL;
493 		use_handler(TOC_HANDLE,TOC_EVILED,args);
494 
495         } else if (!strcasecmp(c, "CHAT_JOIN")) {
496                 char *name,*idc;
497                 int id;
498 
499                 use_handler(TOC_RAW_HANDLE,TOC_CHAT_JOIN,raw);
500 		idc = strtok(NULL, ":");
501 		sscanf(idc, "%d", &id);
502                 name = strtok(NULL, ":");
503                 serv_got_joined_chat(id, name);
504 		numargs = 3;
505 		args = (char **) malloc(sizeof(char *)*numargs);
506 		args[0] = strdup(idc);
507 		args[1] = strdup(name);
508 		args[2] = NULL;
509 		use_handler(TOC_HANDLE,TOC_CHAT_JOIN,args);
510 	} else if (!strcasecmp(c, "DIR_STATUS")) {
511 		char *status;
512 		use_handler(TOC_RAW_HANDLE,TOC_DIR_STATUS,raw);
513 		status = strtok(NULL,":");
514 		numargs = 2;
515 		args = (char **) malloc(sizeof(char *)*numargs);
516 		args[0] = strdup(status);
517 		args[1] = NULL;
518 		use_handler(TOC_HANDLE,TOC_DIR_STATUS,args);
519 	} else if (!strcasecmp(c, "CHAT_UPDATE_BUDDY")) {
520 		int id;
521 		char *in,*idc;
522 		char *buddy;
523                 LLE t;
524 		struct buddy_chat *b = NULL;
525 
526 		use_handler(TOC_RAW_HANDLE,TOC_CHAT_UPDATE_BUDDY,raw);
527 		idc = strtok(NULL, ":");
528 		sscanf(idc, "%d", &id);
529 
530 		in = strtok(NULL, ":");
531 
532 		for ( TLL(buddy_chats,t) ) {
533 			b = (struct buddy_chat *)t->data;
534 			if (id == b->id)
535 				break;
536                         b = NULL;
537 		}
538 
539 		if (!b)
540 			return -2;
541 
542 
543 		if (!strcasecmp(in, "T")) {
544 			while((buddy = strtok(NULL, ":")) != NULL) {
545 				/*
546 				 * Fuxin aim causes a problem here
547 				 */
548 				AddToLL(b->in_room, buddy,NULL);
549 				if ( b->init_chat ) {
550 					args = (char **) malloc(sizeof(char *)*3);
551 					args[0] = strdup(b->name);
552 					args[1] = strdup(buddy);
553 					args[2] = NULL;
554 					use_handler(TOC_HANDLE,TOC_BUDDY_JOIN_CHAT,args);
555 					free(args[0]); free(args[1]); free(args); args = NULL;
556 				}
557 			}
558 			/*
559 			 * init_chat is so that the user doenst get flooded
560 			 * with user joined chat when he first joins a chat
561 			 */
562 			b->init_chat = 1;
563 		} else {
564 			while((buddy = strtok(NULL, ":")) != NULL) {
565 				RemoveFromLLByKey(b->in_room, buddy);
566 				/*
567 				 * Since we might get multiple leave/joins at once
568 				 * we allocate & deallocate here
569 				 */
570 				args = (char **) malloc(sizeof(char *)*3);
571 				args[0] = strdup(b->name);
572 				args[1] = strdup(buddy);
573 				args[2] = NULL;
574 				use_handler(TOC_HANDLE,TOC_BUDDY_LEFT_CHAT,args);
575 				free(args[0]); free(args[1]); free(args); args = NULL;
576 			}
577 		}
578 	} else if (!strcasecmp(c, "CHAT_LEFT")) {
579 		char *idc;
580 		int id;
581 
582 		use_handler(TOC_RAW_HANDLE,TOC_CHAT_LEFT,raw);
583 		idc = strtok(NULL, ":");
584                 sscanf(idc, "%d", &id);
585 
586                 serv_got_chat_left(id);
587 
588 		numargs = 2;
589 		args = (char **) malloc(sizeof(char *)*numargs);
590 		args[0] = strdup(idc);
591 		args[1] = NULL;
592 		use_handler(TOC_HANDLE,TOC_CHAT_LEFT,args);
593 	} else if (!strcasecmp(c, "CHAT_IN")) {
594 
595 		int id, w;
596 		char *m,*idc;
597 		char *who, *whisper, *chan;
598 		struct buddy_chat *b;
599 
600 		use_handler(TOC_RAW_HANDLE,TOC_CHAT_IN,raw);
601 		idc = strtok(NULL, ":");
602 		sscanf(idc, "%d", &id);
603 		who = strtok(NULL, ":");
604 		whisper = strtok(NULL, ":");
605 		m = whisper;
606                 while(*m && (*m != ':')) m++;
607                 m++;
608 
609                 if (!strcasecmp(whisper, "T"))
610 			w = 1;
611 		else
612 			w = 0;
613 
614 		/* serv_got_chat_in(id, who, w, m); */
615 		b = buddy_chat_getbyid(id);
616 		if ( ! b ) {
617 			chan = (char *) malloc(50);
618 			strcpy(chan,"ERROR Couldn't lookup chan!");
619 		} else {
620 			chan = (char *) malloc(strlen(b->name)+1);
621 			strcpy(chan,b->name);
622 		}
623 		numargs = 6;
624 		args = (char **) malloc(sizeof(char *)*numargs);
625 		args[0] = strdup(idc);
626 		args[1] = strdup(who);
627 		args[2] = strdup(whisper);
628 		args[3] = strdup(m);
629 		/* Added arg to make things simple */
630 		args[4] = chan;
631 		args[5] = NULL;
632 		use_handler(TOC_HANDLE,TOC_CHAT_IN,args);
633 	} else if (!strcasecmp(c, "CHAT_INVITE")) {
634 		char *name;
635 		char *who;
636 		char *message,*idc;
637                 int id, *pid;
638 
639                 use_handler(TOC_RAW_HANDLE,TOC_CHAT_INVITE,raw);
640 		name = strtok(NULL, ":");
641 		idc = strtok(NULL, ":");
642 		sscanf(idc, "%d", &id);
643 		who = strtok(NULL, ":");
644                 message = strtok(NULL, ":");
645                /* serv_got_chat_invite(name, id, who, message); */
646 	        pid = (int *) malloc(sizeof(int));
647 		*pid = id;
648 	        AddToLL(invited_chats,name,pid);
649 		numargs = 5;
650 		args = (char **) malloc(sizeof(char *)*numargs);
651 		args[0] = strdup(name);
652 		args[1] = strdup(idc);
653 		args[2] = strdup(who);
654 		args[3] = strdup(message);
655 		args[4] = NULL;
656 		use_handler(TOC_HANDLE,TOC_CHAT_INVITE,args);
657 	} else {
658 		toc_debug_printf("don't know what to do with %s\n", c);
659 	}
660 	free(dup);
661         free(buf);
662 	if ( args != NULL ) {
663 		int x;
664 		/* toc_debug_printf("\nGOING TO FREE!: numargs = %d",numargs); */
665 		for (x=0;x< numargs; x++)
666 			if ( args[x] != NULL ) {
667 				/* toc_debug_printf("freeing %d",x); */
668 				free(args[x]);
669 			}
670 		/* toc_debug_printf(""); */
671 		free(args);
672 	}
673 	return 1;
674 }
675 
toc_wait_config()676 char *toc_wait_config()
677 {
678 	/* Waits for configuration packet, returning the contents of the packet */
679 	static char buf[BUF_LEN];
680 	int res;
681         res = wait_reply(buf, sizeof(buf));
682 	if (res < 0)
683 		return NULL;
684 	if (state != STATE_CONFIG) {
685      		toc_debug_printf("State should be %d, but is %d instead\n",STATE_CONFIG, state);
686 		return NULL;
687 	}
688 	/* At this point, it's time to setup automatic handling of incoming packets */
689         state = STATE_ONLINE;
690 
691         // inpa = gdk_input_add(toc_fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, toc_callback, NULL);
692 	toc_add_input_stream(toc_fd,&toc_callback);
693 
694 	return buf;
695 }
696 
parse_toc_buddy_list(char * config)697 void parse_toc_buddy_list(char *config)
698 {
699 	char *c;
700         char current[256];
701 	char *name;
702 	LL bud = CreateLL();
703 
704         /* skip "CONFIG:" (if it exists)*/
705 
706         c = strncmp(config + sizeof(struct sflap_hdr),"CONFIG:",strlen("CONFIG:"))?
707 			strtok(config, "\n"):
708 			strtok(config + sizeof(struct sflap_hdr)+strlen("CONFIG:"), "\n");
709 
710 	do {
711 		if (c == NULL)
712 			break;
713 		if (*c == 'g') {
714 			strncpy(current,c+2, sizeof(current));
715 			add_group(current);
716 		} else if (*c == 'b') {
717 			add_buddy(current, c+2);
718 			AddToLL(bud, c+2, NULL);
719         	} else if (*c == 'p') {
720            		name = malloc(strlen(c+2) + 2);
721 			snprintf(name, strlen(c+2) + 1, "%s", c+2);
722 			AddToLL(permit, name, NULL);
723 		} else if (*c == 'd') {
724 			name = malloc(strlen(c+2) + 2);
725 			snprintf(name, strlen(c+2) + 1, "%s", c+2);
726 			AddToLL(deny, name,NULL);
727 		} else if (*c == 'm') {
728  			sscanf(c + strlen(c) - 1, "%d", &permdeny);
729 			if (permdeny == 0)
730 				permdeny = PERMIT_PERMITALL;
731 		}
732 	} while ((c=strtok(NULL,"\n")));
733 
734 	serv_add_buddies(bud);
735 	FreeLL(bud);
736         serv_set_permit_deny();
737 }
738 
toc_signoff()739 int toc_signoff() {
740 	/* Leaking memory like a MOFO */
741 	FreeLL(groups);
742 	FreeLL(buddy_chats);
743 	FreeLL(invited_chats);
744 	FreeLL(permit);
745 	FreeLL(deny);
746 	deny = groups = permit = buddy_chats = invited_chats = NULL;
747 	toc_debug_printf("LEAKING MEMORY LIKE A BITCH in toc_signoff!");
748 
749 	serv_close();
750 	toc_msg_printf(TOC_CONNECT_MSGS,"%s signed off",aim_username);
751 	return 1;
752 }
753 
toc_build_config(char * s,int len)754 void toc_build_config(char *s, int len)
755 {
756 	struct group *g;
757 	struct buddy *b;
758 	LLE t,t1;
759 	LL mem;
760 
761 	int pos=0;
762 	toc_debug_printf("FIX this permdeny hack shit!");
763 
764 	if (!permdeny)
765 		    permdeny = PERMIT_PERMITALL;
766 	pos += snprintf(&s[pos], len - pos, "m %d\n", permdeny);
767 
768 	/* Create Buddy List */
769 	for ( TLL(groups,t) ) {
770 		g = (struct group *)t->data;
771 		pos += snprintf(&s[pos], len - pos, "g %s\n", g->name);
772 		mem = g->members;
773 		for ( TLL(mem,t1) ) {
774 			b = (struct buddy *)t1->data;
775 			pos += snprintf(&s[pos], len - pos, "b %s\n", b->name);
776 		}
777 	}
778 
779 	/* Create Permit and Deny Lists */;
780 	for ( TLL(permit,t) ) {
781 		toc_debug_printf("permit: added %s\n",(char *)t->key);
782     		pos += snprintf(&s[pos], len - pos, "p %s\n", (char *)t->key);
783 	}
784 	for ( TLL(deny,t) ) {
785 		toc_debug_printf("deny: added %s\n",(char *)t->key);
786     		pos += snprintf(&s[pos], len - pos, "d %s\n", (char *)t->key);
787 	}
788 }
789 
translate_toc_error_code(char * c)790 void translate_toc_error_code(char *c) {
791 
792 	int no = atoi(c);
793 	char *w = strtok(NULL, ":");
794 	char buf[256];
795 
796         switch ( no ) {
797         	case 901:
798                 	snprintf(buf, sizeof(buf), "%s not currently logged in.", w);
799 	                break;
800         	case 902:
801 	                snprintf(buf, sizeof(buf), "Warning of %s not allowed.", w);
802         	        break;
803 	        case 903:
804         	        snprintf(buf, sizeof(buf), "A message has been dropped, you are exceeding the server speed limit.");
805                 	break;
806 	        case 950:
807         	        snprintf(buf, sizeof(buf), "Chat in %s is not available.", w);
808                 	break;
809 	        case 960:
810         	        snprintf(buf, sizeof(buf), "You are sending messages too fast to %s.", w);
811                 	break;
812 	        case 961:
813         	        snprintf(buf, sizeof(buf), "You missed an IM from %s because it was too big.", w);
814                 	break;
815 	        case 962:
816 	                snprintf(buf, sizeof(buf), "You missed an IM from %s because it was sent too fast.", w);
817                 	break;
818 	        case 970:
819         	        snprintf(buf, sizeof(buf), "Failure.");
820                 	break;
821 	        case 971:
822         	        snprintf(buf, sizeof(buf), "Too many matches.");
823                 	break;
824 	        case 972:
825         	        snprintf(buf, sizeof(buf), "Need more qualifiers.");
826                 	break;
827         	case 973:
828 	                snprintf(buf, sizeof(buf), "Dir service temporarily unavailable.");
829         	        break;
830 	        case 974:
831 	                snprintf(buf, sizeof(buf), "Email lookup restricted.");
832         	        break;
833 	        case 975:
834                 	snprintf(buf, sizeof(buf), "Keyword ignored.");
835         	        break;
836 	        case 976:
837          	       snprintf(buf, sizeof(buf), "No keywords.");
838                 	break;
839 	        case 977:
840                 	snprintf(buf, sizeof(buf), "User has no directory information.");
841         	        /* snprintf(buf, sizeof(buf), "Language not supported."); */
842 	                break;
843         	case 978:
844                 	snprintf(buf, sizeof(buf), "Country not supported.");
845 	                break;
846         	case 979:
847                 	snprintf(buf, sizeof(buf), "Failure unknown: %s.", w);
848 	                break;
849         	case 980:
850                 	snprintf(buf, sizeof(buf), "Incorrect nickname or password.");
851 	                break;
852 	        case 981:
853         	        snprintf(buf, sizeof(buf), "The service is temporarily unavailable.");
854                 	break;
855 	        case 982:
856         	        snprintf(buf, sizeof(buf), "Your warning level is currently too high to log in.");
857                 	break;
858 	        case 983:
859         	        snprintf(buf, sizeof(buf), "You have been connecting and disconnecting too frequently.  Wait ten minutes and try again.  If you continue to try, you will need to wait even longer.");
860                 	break;
861 	        case 989:
862         	        snprintf(buf, sizeof(buf), "An unknown signon error has occurred: %s.", w);
863                 	break;
864 	        default:
865         	        snprintf(buf, sizeof(buf), "An unknown error, %d, has occured.  Info: %s", no, w);
866 	}
867 	toc_msg_printf(TOC_TRANSLATED_ERROR,buf);
868         return;
869 }
870