]> andersk Git - libfaim.git/blame_incremental - utils/faimtest/faimtest.c
- Tue Apr 24 17:36:03 PDT 2001
[libfaim.git] / utils / faimtest / faimtest.c
... / ...
CommitLineData
1/*
2 * -----------------------------------------------------------
3 * ProtoFAIM: v1.xx.xxplxx
4 * -----------------------------------------------------------
5 *
6 * This is ProtoFAIM v1.xx.xxplxx!!! Its nearly completely
7 * different than that ugly thing called v0. This app is
8 * compatible with the latest version of the libfaim library.
9 * Work is continuing.
10 *
11 * ProtoFAIM should only be used for two things...
12 * 1) Testing the libfaim backend.
13 * 2) For reference on the libfaim API when developing clients.
14 *
15 * Its very ugly. Probably always will be. Nothing is more
16 * ugly than the backend itself, however.
17 *
18 * -----------------------------------------------------------
19 *
20 * I'm releasing this code and all it's associated linkage
21 * under the GNU General Public License. For more information,
22 * please refer to http://www.fsf.org. For any questions,
23 * please contact me at the address below.
24 *
25 * Most everything:
26 * (c) 1998 Adam Fritzler, PST, mid@zigamoprh.net
27 *
28 * The password algorithms
29 * (c) 1998 Brock Wilcox, awwaiid@zigamorph.net
30 *
31 * THERE IS NO CODE FROM AOL'S AIM IN THIS CODE, NOR
32 * WAS THERE ANY DISASSEMBLAGE TO DEFINE PROTOCOL. All
33 * information was gained through painstakingly comparing
34 * TCP dumps while the AIM Java client was running. Nothing
35 * more than that, except for a lot of experimenting.
36 *
37 * -----------------------------------------------------------
38 *
39 */
40
41#include "faimtest.h"
42
43static char *dprintf_ctime(void)
44{
45 static char retbuf[64];
46 struct tm *lt;
47 struct timeval tv;
48 struct timezone tz;
49
50 gettimeofday(&tv, &tz);
51 lt = localtime((time_t *)&tv.tv_sec);
52 strftime(retbuf, 64, "%a %b %e %H:%M:%S %Z %Y", lt);
53 return retbuf;
54}
55
56#define DPRINTF_OUTSTREAM stdout
57#define dprintf(x) { \
58 fprintf(DPRINTF_OUTSTREAM, "%s %s: " x, dprintf_ctime(), "faimtest"); \
59 fflush(DPRINTF_OUTSTREAM); \
60}
61#define dvprintf(x, y...) { \
62 fprintf(DPRINTF_OUTSTREAM, "%s %s: " x, dprintf_ctime(), "faimtest", y); \
63 fflush(DPRINTF_OUTSTREAM); \
64}
65#define dinlineprintf(x) { \
66 fprintf(DPRINTF_OUTSTREAM, x); \
67 fflush(DPRINTF_OUTSTREAM); \
68}
69#define dvinlineprintf(x, y...) { \
70 fprintf(DPRINTF_OUTSTREAM, x, y); \
71 fflush(DPRINTF_OUTSTREAM); \
72}
73#define dperror(x) dvprintf("%s: %s\n", x, strerror(errno));
74
75int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...);
76int faimtest_parse_offgoing(struct aim_session_t *, struct command_rx_struct *, ...);
77int faimtest_parse_login_phase3d_f(struct aim_session_t *, struct command_rx_struct *, ...);
78static int faimtest_parse_authresp(struct aim_session_t *, struct command_rx_struct *, ...);
79int faimtest_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *command, ...);
80int faimtest_parse_userinfo(struct aim_session_t *, struct command_rx_struct *command, ...);
81int faimtest_handleredirect(struct aim_session_t *, struct command_rx_struct *command, ...);
82int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
83int faimtest_serverready(struct aim_session_t *, struct command_rx_struct *command, ...);
84int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...);
85int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
86int faimtest_parse_msgack(struct aim_session_t *, struct command_rx_struct *command, ...);
87int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
88int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
89int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
90int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
91int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
92int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
93int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
94int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
95int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
96
97int faimtest_directim_request(struct aim_session_t *sess, struct command_rx_struct *command, ...);
98int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
99int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
100int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...);
101int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
102int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
103
104int faimtest_getfile_filereq(struct aim_session_t *sess, struct command_rx_struct *command, ...);
105int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...);
106int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...);
107int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
108int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
109int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
110int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...);
111int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...);
112int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...);
113
114int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
115int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...);
116int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...);
117int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...);
118int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
119int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
120int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
121int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
122
123static char *msgerrreasons[] = {
124 "Invalid error",
125 "Invalid SNAC",
126 "Rate to host",
127 "Rate to client",
128 "Not logged on",
129 "Service unavailable",
130 "Service not defined",
131 "Obsolete SNAC",
132 "Not supported by host",
133 "Not supported by client",
134 "Refused by client",
135 "Reply too big",
136 "Responses lost",
137 "Request denied",
138 "Busted SNAC payload",
139 "Insufficient rights",
140 "In local permit/deny",
141 "Too evil (sender)",
142 "Too evil (receiver)",
143 "User temporarily unavailable",
144 "No match",
145 "List overflow",
146 "Request ambiguous",
147 "Queue full",
148 "Not while on AOL"};
149static int msgerrreasonslen = 25;
150
151static char *aimbinarypath = NULL;
152static char *screenname,*password,*server=NULL;
153static char *proxy = NULL, *proxyusername = NULL, *proxypass = NULL;
154static char *ohcaptainmycaptain = NULL;
155static int connected = 0;
156
157struct aim_session_t aimsess;
158int keepgoing = 1;
159
160static FILE *listingfile;
161static char *listingpath;
162
163static void faimtest_debugcb(struct aim_session_t *sess, int level, const char *format, va_list va)
164{
165
166 vfprintf(stderr, format, va);
167
168 return;
169}
170
171int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
172{
173 va_list ap;
174 unsigned short interval = 0;
175
176 va_start(ap, command);
177 interval = va_arg(ap, int);
178 va_end(ap);
179
180 dvprintf("aim: minimum report interval: %d (seconds?)\n", interval);
181
182 return 1;
183}
184
185int faimtest_flapversion(struct aim_session_t *sess, struct command_rx_struct *command, ...)
186{
187
188 dvprintf("faimtest: using FLAP version %u\n", aimutil_get32(command->data));
189
190#if 0
191 /*
192 * This is an alternate location for starting the login process.
193 */
194 /* XXX should do more checking to make sure its really the right AUTH conn */
195 if (command->conn->type == AIM_CONN_TYPE_AUTH) {
196 /* do NOT send a connack/flapversion, request_login will send it if needed */
197 aim_request_login(sess, command->conn, screenname);
198 dprintf("faimtest: login request sent\n");
199 }
200#endif
201
202 return 1;
203}
204
205/*
206 * This is a frivilous callback. You don't need it. I only used it for
207 * debugging non-blocking connects.
208 *
209 * If packets are sent to a conn before its fully connected, they
210 * will be queued and then transmitted when the connection completes.
211 *
212 */
213int faimtest_conncomplete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
214{
215 va_list ap;
216 struct aim_conn_t *conn;
217
218 va_start(ap, command);
219 conn = va_arg(ap, struct aim_conn_t *);
220 va_end(ap);
221
222 if (conn)
223 dvprintf("faimtest: connection on %d completed\n", conn->fd);
224
225 return 1;
226}
227
228#ifdef _WIN32
229/*
230 * This is really all thats needed to link against libfaim on win32.
231 *
232 * Note that this particular version of faimtest has never been tested
233 * on win32, but I'm fairly sure it should.
234 */
235int initwsa(void)
236{
237 WORD wVersionRequested;
238 WSADATA wsaData;
239
240 wVersionRequested = MAKEWORD(2,2);
241 return WSAStartup(wVersionRequested, &wsaData);
242}
243#endif /* _WIN32 */
244
245int faimtest_init(void)
246{
247 struct aim_conn_t *stdinconn = NULL;
248
249 if (!(stdinconn = aim_newconn(&aimsess, 0, NULL))) {
250 dprintf("unable to create connection for stdin!\n");
251 return -1;
252 }
253
254 stdinconn->fd = STDIN_FILENO;
255
256 return 0;
257}
258
259int logout(void)
260{
261
262 if (ohcaptainmycaptain)
263 aim_send_im(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS), ohcaptainmycaptain, 0, "ta ta...", strlen("ta ta..."));
264
265 aim_session_kill(&aimsess);
266
267 if (faimtest_init() == -1)
268 dprintf("faimtest_init failed\n");
269
270 return 0;
271}
272
273int login(const char *sn, const char *passwd)
274{
275 struct aim_conn_t *authconn;
276
277 if (sn)
278 screenname = strdup(sn);
279 if (passwd)
280 password = strdup(passwd);
281
282 if (proxy)
283 aim_setupproxy(&aimsess, proxy, proxyusername, proxypass);
284
285 if (!screenname || !password) {
286 dprintf("need SN and password\n");
287 return -1;
288 }
289
290 if (!(authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER))) {
291 dprintf("faimtest: internal connection error while in aim_login. bailing out.\n");
292 return -1;
293 } else if (authconn->fd == -1) {
294 if (authconn->status & AIM_CONN_STATUS_RESOLVERR) {
295 dprintf("faimtest: could not resolve authorizer name\n");
296 } else if (authconn->status & AIM_CONN_STATUS_CONNERR) {
297 dprintf("faimtest: could not connect to authorizer\n");
298 }
299 aim_conn_kill(&aimsess, &authconn);
300 return -1;
301 }
302
303 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
304 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
305 aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
306 aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
307
308 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
309
310 /* If the connection is in progress, this will just be queued */
311 aim_request_login(&aimsess, authconn, screenname);
312 dprintf("faimtest: login request sent\n");
313
314 return 0;
315}
316
317int main(int argc, char **argv)
318{
319 struct aim_conn_t *waitingconn = NULL;
320 int i;
321 int selstat = 0;
322 static int faimtest_mode = 0;
323 struct timeval tv;
324 time_t lastnop = 0;
325
326 screenname = getenv("SCREENNAME");
327 password = getenv("PASSWORD");
328 server = getenv("AUTHSERVER");
329 proxy = getenv("SOCKSPROXY");
330 proxyusername = getenv("SOCKSNAME");
331 proxypass = getenv("SOCKSPASS");
332
333 listingpath = getenv("LISTINGPATH");
334
335 while ((i = getopt(argc, argv, "u:p:a:U:P:A:l:c:hoOb:")) != EOF) {
336 switch (i) {
337 case 'u': screenname = optarg; break;
338 case 'p': password = optarg; break;
339 case 'a': server = optarg; break;
340 case 'U': proxyusername = optarg; break;
341 case 'P': proxypass = optarg; break;
342 case 'A': proxy = optarg; break;
343 case 'l': listingpath = optarg; break;
344 case 'c': ohcaptainmycaptain = optarg; break;
345 case 'o': faimtest_mode = 1; break; /* half old interface */
346 case 'O': faimtest_mode = 2; break; /* full old interface */
347 case 'b': aimbinarypath = optarg; break;
348 case 'h':
349 default:
350 printf("faimtest\n");
351 printf(" Options: \n");
352 printf(" -u name Screen name ($SCREENNAME)\n");
353 printf(" -p passwd Password ($PASSWORD)\n");
354 printf(" -a host:port Authorizer ($AUTHSERVER)\n");
355 printf(" -U name Proxy user name ($SOCKSPROXY)\n");
356 printf(" -P passwd Proxy password ($SOCKSNAME)\n");
357 printf(" -A host:port Proxy host ($SOCKSPASS)\n");
358 printf(" -l path Path to listing file ($LISTINGPATH)\n");
359 printf(" -c name Screen name of owner\n");
360 printf(" -o Login at startup, then prompt\n");
361 printf(" -O Login, never give prompt\n");
362 exit(0);
363 }
364 }
365
366#ifdef _WIN32
367 if (initwsa() != 0) {
368 dprintf("faimtest: could not initialize windows sockets\n");
369 return -1;
370 }
371#endif /* _WIN32 */
372
373 /* Pass zero as flags if you want blocking connects */
374 aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 1);
375 aim_setdebuggingcb(&aimsess, faimtest_debugcb); /* still needed even if debuglevel = 0 ! */
376
377 if(listingpath) {
378 char *listingname;
379 if(!(listingname = (char *)calloc(1, strlen(listingpath)+strlen("/listing.txt")))) {
380 dperror("listingname calloc");
381 exit(-1);
382 }
383 sprintf(listingname, "%s/listing.txt", listingpath);
384 if( (listingfile = fopen(listingname, "r")) == NULL) {
385 dvprintf("Couldn't open %s... disabling that shit.\n", listingname);
386 }
387
388 free(listingname);
389 }
390
391 faimtest_init();
392
393 if (faimtest_mode < 2)
394 cmd_init();
395
396 if (faimtest_mode >= 1) {
397 if (login(screenname, password) == -1) {
398 if (faimtest_mode < 2)
399 cmd_uninit();
400 exit(-1);
401 }
402 }
403
404 while (keepgoing) {
405
406 tv.tv_sec = 5;
407 tv.tv_usec = 0;
408
409 waitingconn = aim_select(&aimsess, &tv, &selstat);
410
411 if (connected && ((time(NULL) - lastnop) > 30)) {
412 lastnop = time(NULL);
413 aim_flap_nop(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS));
414 }
415
416 if (selstat == -1) { /* error */
417 keepgoing = 0; /* fall through */
418 } else if (selstat == 0) { /* no events pending */
419 ;
420 } else if (selstat == 1) { /* outgoing data pending */
421 aim_tx_flushqueue(&aimsess);
422 } else if (selstat == 2) { /* incoming data pending */
423 if ((faimtest_mode < 2) && (waitingconn->fd == STDIN_FILENO)) {
424 cmd_gotkey();
425 } else {
426 if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
427 if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
428 dprintf("connection error (rend out)\n");
429 aim_conn_kill(&aimsess, &waitingconn);
430 }
431 } else {
432 if (aim_get_command(&aimsess, waitingconn) >= 0) {
433 aim_rxdispatch(&aimsess);
434 } else {
435 dvprintf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
436 /* we should have callbacks for all these, else the library will do the conn_kill for us. */
437 if(waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
438 dprintf("connection error: rendezvous connection. you forgot register a disconnect callback, right?\n");
439 aim_conn_kill(&aimsess, &waitingconn);
440 } else
441 aim_conn_kill(&aimsess, &waitingconn);
442 if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
443 dprintf("major connection error\n");
444 if (faimtest_mode == 2)
445 break;
446 }
447 }
448 }
449 }
450 }
451 }
452
453 /* close up all connections, dead or no */
454 aim_session_kill(&aimsess);
455
456 if (faimtest_mode < 2) {
457 printf("\n");
458 cmd_uninit();
459 }
460
461 /* Get out */
462 exit(0);
463}
464
465int faimtest_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
466{
467
468 switch(command->conn->type) {
469 case AIM_CONN_TYPE_BOS: {
470 /* this is the new buddy list */
471 char buddies[128];
472 /* this is the new profile */
473 char profile[256];
474
475 /* Caution: Buddy1 and Buddy2 are real people! (who I don't know) */
476 snprintf(buddies, sizeof(buddies), "Buddy1&Buddy2&%s&", ohcaptainmycaptain?ohcaptainmycaptain:"blah");
477 snprintf(profile, sizeof(profile), "Hello.<br>My captain is %s. They were dumb enough to leave this message in their client, or they are using faimtest. Shame on them.", ohcaptainmycaptain);
478
479 aim_bos_ackrateresp(sess, command->conn); /* ack rate info response */
480 aim_bos_reqpersonalinfo(sess, command->conn);
481 aim_bos_reqlocaterights(sess, command->conn);
482 aim_bos_setprofile(sess, command->conn, profile, NULL, AIM_CAPS_BUDDYICON | AIM_CAPS_CHAT | AIM_CAPS_VOICE | AIM_CAPS_GETFILE | AIM_CAPS_SENDFILE | AIM_CAPS_IMIMAGE /*| AIM_CAPS_GAMES | AIM_CAPS_SAVESTOCKS*/);
483 aim_bos_reqbuddyrights(sess, command->conn);
484
485 /* send the buddy list and profile (required, even if empty) */
486 aim_bos_setbuddylist(sess, command->conn, buddies);
487
488 /* dont really know what this does */
489 aim_addicbmparam(sess, command->conn);
490 aim_bos_reqicbmparaminfo(sess, command->conn);
491
492 aim_bos_reqrights(sess, command->conn);
493 /* set group permissions -- all user classes */
494 aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS);
495 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE);
496
497 break;
498 }
499 case AIM_CONN_TYPE_AUTH:
500 aim_bos_ackrateresp(sess, command->conn);
501 aim_auth_clientready(sess, command->conn);
502 dprintf("faimtest: connected to authorization/admin service\n");
503 break;
504
505 default:
506 dvprintf("faimtest: got rate response for unhandled connection type %04x\n", command->conn->type);
507 break;
508 }
509
510 return 1;
511}
512
513static int faimtest_icbmparaminfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
514{
515 unsigned long defflags, minmsginterval;
516 unsigned short maxicbmlen, maxsenderwarn, maxrecverwarn, maxchannel;
517 va_list ap;
518
519 va_start(ap, command);
520 maxchannel = va_arg(ap, unsigned short);
521 defflags = va_arg(ap, unsigned long);
522 maxicbmlen = va_arg(ap, unsigned short);
523 maxsenderwarn = va_arg(ap, unsigned short);
524 maxrecverwarn = va_arg(ap, unsigned short);
525 minmsginterval = va_arg(ap, unsigned long);
526 va_end(ap);
527
528 dvprintf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %ld\n", maxchannel, defflags, maxicbmlen, ((float)maxsenderwarn)/10.0, ((float)maxrecverwarn)/10.0, minmsginterval);
529
530 return 1;
531}
532
533int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...)
534{
535 int vercount, i;
536 unsigned char *versions;
537 va_list ap;
538
539 va_start(ap, command);
540 vercount = va_arg(ap, int); /* number of family/version pairs */
541 versions = va_arg(ap, unsigned char *);
542 va_end(ap);
543
544 dprintf("faimtest: SNAC versions supported by this host: ");
545 for (i = 0; i < vercount*4; i += 4)
546 dvinlineprintf("0x%04x:0x%04x ",
547 aimutil_get16(versions+i), /* SNAC family */
548 aimutil_get16(versions+i+2) /* Version number */);
549 dinlineprintf("\n");
550
551 return 1;
552}
553
554int faimtest_accountconfirm(struct aim_session_t *sess, struct command_rx_struct *command, ...)
555{
556 int status;
557 va_list ap;
558
559 va_start(ap, command);
560 status = va_arg(ap, int); /* status code of confirmation request */
561 va_end(ap);
562
563 dvprintf("account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
564
565 return 1;
566}
567
568int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
569{
570 int famcount, i;
571 unsigned short *families;
572 va_list ap;
573
574 va_start(ap, command);
575 famcount = va_arg(ap, int);
576 families = va_arg(ap, unsigned short *);
577 va_end(ap);
578
579 dvprintf("faimtest: SNAC families supported by this host (type %d): ", command->conn->type);
580 for (i = 0; i < famcount; i++)
581 dvinlineprintf("0x%04x ", families[i]);
582 dinlineprintf("\n");
583
584 switch (command->conn->type) {
585 case AIM_CONN_TYPE_AUTH:
586 aim_auth_setversions(sess, command->conn);
587 aim_bos_reqrate(sess, command->conn); /* request rate info */
588
589 dprintf("faimtest: done with auth ServerReady\n");
590 break;
591
592 case AIM_CONN_TYPE_BOS:
593
594 aim_setversions(sess, command->conn);
595 aim_bos_reqrate(sess, command->conn); /* request rate info */
596
597 dprintf("faimtest: done with BOS ServerReady\n");
598 break;
599
600 case AIM_CONN_TYPE_CHATNAV:
601 dprintf("faimtest: chatnav: got server ready\n");
602 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
603 aim_bos_reqrate(sess, command->conn);
604 aim_bos_ackrateresp(sess, command->conn);
605 aim_chatnav_clientready(sess, command->conn);
606 aim_chatnav_reqrights(sess, command->conn);
607
608 break;
609
610 case AIM_CONN_TYPE_CHAT:
611 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
612 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
613 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
614 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
615 aim_bos_reqrate(sess, command->conn);
616 aim_bos_ackrateresp(sess, command->conn);
617 aim_chat_clientready(sess, command->conn);
618 break;
619
620 case AIM_CONN_TYPE_RENDEZVOUS: /* empty */
621 break;
622
623 default:
624 dvprintf("faimtest: unknown connection type on Host Online (0x%04x)\n", command->conn->type);
625 }
626
627 return 1;
628}
629
630int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
631{
632 va_list ap;
633 unsigned short maxbuddies, maxwatchers;
634
635 va_start(ap, command);
636 maxbuddies = va_arg(ap, int);
637 maxwatchers = va_arg(ap, int);
638 va_end(ap);
639
640 dvprintf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
641
642 return 1;
643}
644
645int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
646{
647 unsigned short maxpermits, maxdenies;
648 va_list ap;
649
650 va_start(ap, command);
651 maxpermits = va_arg(ap, int);
652 maxdenies = va_arg(ap, int);
653 va_end(ap);
654
655 dvprintf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
656
657 aim_bos_clientready(sess, command->conn);
658
659 dprintf("faimtest: officially connected to BOS.\n");
660
661 return 1;
662}
663
664int faimtest_parse_unknown(struct aim_session_t *sess, struct command_rx_struct *command, ...)
665{
666 int i = 0;
667
668 if (!sess || !command)
669 return 1;
670
671 dprintf("\nReceived unknown packet:");
672 for (i = 0; i < command->commandlen; i++) {
673 if ((i % 8) == 0)
674 dinlineprintf("\n\t");
675 dvinlineprintf("0x%2x ", command->data[i]);
676 }
677 dinlineprintf("\n\n");
678
679 return 1;
680}
681
682/*
683 handleredirect()...
684
685 This, of course, handles Service Redirects from OSCAR.
686
687 Should get passed in the following:
688 struct command_rx_struct *command
689 the raw command data
690 int serviceid
691 the destination service ID
692 char *serverip
693 the IP address of the service's server
694 char *cookie
695 the raw auth cookie
696 */
697int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
698{
699 va_list ap;
700 int serviceid;
701 char *ip;
702 unsigned char *cookie;
703
704 va_start(ap, command);
705 serviceid = va_arg(ap, int);
706 ip = va_arg(ap, char *);
707 cookie = va_arg(ap, unsigned char *);
708
709 switch(serviceid) {
710 case 0x0005: { /* Adverts */
711 struct aim_conn_t *tstconn;
712
713 tstconn = aim_newconn(sess, AIM_CONN_TYPE_ADS, ip);
714 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
715 dprintf("faimtest: unable to reconnect with authorizer\n");
716 } else {
717 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
718 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
719 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
720 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
721 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
722 aim_auth_sendcookie(sess, tstconn, cookie);
723 dprintf("sent cookie to adverts host\n");
724 }
725 break;
726 }
727 case 0x0007: { /* Authorizer */
728 struct aim_conn_t *tstconn;
729 /* Open a connection to the Auth */
730 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
731 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
732 dprintf("faimtest: unable to reconnect with authorizer\n");
733 } else {
734 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
735 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
736 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
737 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
738 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
739 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
740 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
741 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
742 /* Send the cookie to the Auth */
743 aim_auth_sendcookie(sess, tstconn, cookie);
744 dprintf("sent cookie to authorizer host\n");
745 }
746 break;
747 }
748 case 0x000d: { /* ChatNav */
749 struct aim_conn_t *tstconn = NULL;
750 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
751 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
752 dprintf("faimtest: unable to connect to chatnav server\n");
753 if (tstconn) aim_conn_kill(sess, &tstconn);
754 return 1;
755 }
756
757 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
758 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
759 aim_auth_sendcookie(sess, tstconn, cookie);
760 dprintf("\achatnav: connected\n");
761 break;
762 }
763 case 0x000e: { /* Chat */
764 char *roomname = NULL;
765 int exchange;
766 struct aim_conn_t *tstconn = NULL;
767
768 roomname = va_arg(ap, char *);
769 exchange = va_arg(ap, int);
770
771 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
772 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
773 dprintf("faimtest: unable to connect to chat server\n");
774 if (tstconn) aim_conn_kill(sess, &tstconn);
775 return 1;
776 }
777 dvprintf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
778
779 /*
780 * We must do this to attach the stored name to the connection!
781 */
782 aim_chat_attachname(tstconn, roomname);
783
784 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
785 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
786 aim_auth_sendcookie(sess, tstconn, cookie);
787
788 break;
789 }
790 default:
791 dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
792 /* dunno */
793 }
794
795 va_end(ap);
796
797 return 1;
798}
799
800static int getaimdata(unsigned char *buf, int buflen, unsigned long offset, const char *modname)
801{
802 FILE *f;
803 static const char defaultmod[] = "aim.exe";
804 char *filename = NULL;
805
806 memset(buf, 0, buflen);
807
808 if (modname) {
809
810 if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(modname)+4+1))) {
811 dperror("memrequest: malloc");
812 return -1;
813 }
814
815 sprintf(filename, "%s/%s.ocm", aimbinarypath, modname);
816
817 } else {
818
819 if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(defaultmod)+1))) {
820 dperror("memrequest: malloc");
821 return -1;
822 }
823
824 sprintf(filename, "%s/%s", aimbinarypath, defaultmod);
825
826 }
827
828 dvprintf("memrequest: loading %d bytes from 0x%08lx in \"%s\"...\n", buflen, offset, filename);
829
830 if (!(f = fopen(filename, "r"))) {
831 dperror("memrequest: fopen");
832 free(filename);
833 return -1;
834 }
835
836 free(filename);
837
838 if (buflen) {
839 if (fseek(f, offset, SEEK_SET) == -1) {
840 dperror("memrequest: fseek");
841 fclose(f);
842 return -1;
843 }
844
845 if (fread(buf, buflen, 1, f) != 1) {
846 dperror("memrequest: fread");
847 fclose(f);
848 return -1;
849 }
850 }
851
852 fclose(f);
853
854 return buflen;
855}
856
857/*
858 * This will get an offset and a length. The client should read this
859 * data out of whatever AIM.EXE binary the user has provided (hopefully
860 * it matches the client information thats sent at login) and pass a
861 * buffer back to libfaim so it can hash the data and send it to AOL for
862 * inspection by the client police.
863 */
864static int faimtest_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...)
865{
866 va_list ap;
867 unsigned long offset, len;
868 unsigned char *buf;
869 char *modname;
870
871 va_start(ap, command);
872 offset = va_arg(ap, unsigned long);
873 len = va_arg(ap, unsigned long);
874 modname = va_arg(ap, char *);
875 va_end(ap);
876
877 if (!(buf = malloc(len))) {
878 dperror("memrequest: malloc");
879 return 0;
880 }
881
882 if (aimbinarypath && (getaimdata(buf, len, offset, modname) == len)) {
883
884 aim_sendmemblock(sess, command->conn, offset, len, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
885
886 } else {
887
888 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", aimbinarypath, modname);
889
890 aim_sendmemblock(sess, command->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
891
892 }
893
894 free(buf);
895
896 return 1;
897}
898
899static int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
900{
901 va_list ap;
902 struct aim_conn_t *bosconn = NULL;
903 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
904 unsigned char *cookie = NULL;
905 int errorcode = 0, regstatus = 0;
906 int latestbuild = 0, latestbetabuild = 0;
907 char *latestrelease = NULL, *latestbeta = NULL;
908 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
909 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
910
911 va_start(ap, command);
912 sn = va_arg(ap, char *);
913 errorcode = va_arg(ap, int);
914 errurl = va_arg(ap, char *);
915 regstatus = va_arg(ap, int);
916 email = va_arg(ap, char *);
917 bosip = va_arg(ap, char *);
918 cookie = va_arg(ap, unsigned char *);
919
920 latestrelease = va_arg(ap, char *);
921 latestbuild = va_arg(ap, int);
922 latestreleaseurl = va_arg(ap, char *);
923 latestreleaseinfo = va_arg(ap, char *);
924
925 latestbeta = va_arg(ap, char *);
926 latestbetabuild = va_arg(ap, int);
927 latestbetaurl = va_arg(ap, char *);
928 latestbetainfo = va_arg(ap, char *);
929
930 va_end(ap);
931
932 dvprintf("Screen name: %s\n", sn);
933
934 /*
935 * Check for error.
936 */
937 if (errorcode || !bosip || !cookie) {
938 dvprintf("Login Error Code 0x%04x\n", errorcode);
939 dvprintf("Error URL: %s\n", errurl);
940 aim_conn_kill(sess, &command->conn);
941 return 1;
942 }
943
944 dvprintf("Reg status: %2d\n", regstatus);
945 dvprintf("Email: %s\n", email);
946 dvprintf("BOS IP: %s\n", bosip);
947
948 if (latestbeta)
949 dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
950
951 if (latestrelease)
952 dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
953
954 dprintf("Closing auth connection...\n");
955 aim_conn_kill(sess, &command->conn);
956 if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
957 dprintf("faimtest: could not connect to BOS: internal error\n");
958 return 1;
959 } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
960 dprintf("faimtest: could not connect to BOS\n");
961 aim_conn_kill(sess, &bosconn);
962 return 1;
963 }
964
965 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
966 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
967 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
968 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
969 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
970 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
971 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
972 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
973 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
974 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
975 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
976 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
977 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
978 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
979 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
980 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
981 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
982 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
983 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
984 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
985 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
986 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
987
988 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
989
990 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
991 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
992 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
993 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
994
995 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
996 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
997 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
998
999 aim_auth_sendcookie(sess, bosconn, cookie);
1000
1001 return 1;
1002}
1003
1004static void printuserflags(unsigned short flags)
1005{
1006 if (flags & AIM_FLAG_UNCONFIRMED)
1007 dinlineprintf("UNCONFIRMED ");
1008 if (flags & AIM_FLAG_ADMINISTRATOR)
1009 dinlineprintf("ADMINISTRATOR ");
1010 if (flags & AIM_FLAG_AOL)
1011 dinlineprintf("AOL ");
1012 if (flags & AIM_FLAG_OSCAR_PAY)
1013 dinlineprintf("OSCAR_PAY ");
1014 if (flags & AIM_FLAG_FREE)
1015 dinlineprintf("FREE ");
1016 if (flags & AIM_FLAG_AWAY)
1017 dinlineprintf("AWAY ");
1018 if (flags & AIM_FLAG_UNKNOWN40)
1019 dinlineprintf("ICQ? ");
1020 if (flags & AIM_FLAG_UNKNOWN80)
1021 dinlineprintf("UNKNOWN80 ");
1022 return;
1023}
1024
1025int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1026{
1027 struct aim_userinfo_s *userinfo;
1028 char *prof_encoding = NULL;
1029 char *prof = NULL;
1030 unsigned short inforeq = 0;
1031
1032 va_list ap;
1033 va_start(ap, command);
1034 userinfo = va_arg(ap, struct aim_userinfo_s *);
1035 prof_encoding = va_arg(ap, char *);
1036 prof = va_arg(ap, char *);
1037 inforeq = va_arg(ap, int);
1038 va_end(ap);
1039
1040 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
1041 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
1042 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
1043 printuserflags(userinfo->flags);
1044 dinlineprintf("\n");
1045
1046 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
1047 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1048 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
1049
1050 if (inforeq == AIM_GETINFO_GENERALINFO) {
1051 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1052 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
1053 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1054 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1055 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1056 } else
1057 dprintf("faimtest: userinfo: unknown info request\n");
1058
1059 return 1;
1060}
1061
1062static int faimtest_handlecmd(struct aim_session_t *sess, struct command_rx_struct *command, struct aim_userinfo_s *userinfo, char *tmpstr)
1063{
1064
1065 if (!strncmp(tmpstr, "disconnect", 10)) {
1066
1067 logout();
1068
1069 } else if (strstr(tmpstr, "goodday")) {
1070
1071 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.", strlen("Good day to you too."));
1072
1073 } else if (strstr(tmpstr, "warnme")) {
1074
1075 dprintf("faimtest: icbm: sending non-anon warning\n");
1076 aim_send_warning(sess, command->conn, userinfo->sn, 0);
1077
1078 } else if (strstr(tmpstr, "anonwarn")) {
1079
1080 dprintf("faimtest: icbm: sending anon warning\n");
1081 aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
1082
1083 } else if (strstr(tmpstr, "setdirectoryinfo")) {
1084
1085 dprintf("faimtest: icbm: sending backwards profile data\n");
1086 aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1087
1088 } else if (strstr(tmpstr, "setinterests")) {
1089
1090 dprintf("faimtest: icbm: setting fun interests\n");
1091 aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1092
1093 } else if (!strncmp(tmpstr, "getfile", 7)) {
1094
1095 if (!ohcaptainmycaptain) {
1096
1097 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!", strlen("I have no owner!"));
1098
1099 } else {
1100 struct aim_conn_t *newconn;
1101
1102 newconn = aim_getfile_initiate(sess, command->conn, (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1103 dvprintf("faimtest: getting file listing from %s\n", (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1104 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE, faimtest_getfile_initiate,0);
1105 }
1106
1107 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1108
1109 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
1110
1111 } else if (!strncmp(tmpstr, "create", 6)) {
1112
1113 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1114
1115 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1116 struct aim_conn_t *chatnavconn;
1117
1118 chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
1119 aim_conn_kill(sess, &chatnavconn);
1120
1121 } else if (!strncmp(tmpstr, "join", 4)) {
1122
1123 aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
1124
1125 } else if (!strncmp(tmpstr, "leave", 5)) {
1126
1127 aim_chat_leaveroom(sess, "worlddomination");
1128
1129 } else if (!strncmp(tmpstr, "getinfo", 7)) {
1130
1131 aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
1132 aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
1133 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
1134 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
1135
1136 } else if (!strncmp(tmpstr, "open directim", 13)) {
1137 struct aim_conn_t *newconn;
1138
1139 printf("faimtest: opening directim to %s\n", (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1140 newconn = aim_directim_initiate(sess, command->conn, NULL, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1141 if(!newconn || newconn->fd == -1)
1142 printf("connection failed!\n");
1143 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate,0);
1144
1145 } else if(!(strncmp(tmpstr, "lookup", 6))) {
1146
1147 aim_usersearch_address(sess, command->conn, tmpstr+7);
1148
1149 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1150
1151 aim_send_im(sess, command->conn, ohcaptainmycaptain, 0, "sendmsg 7900", strlen("sendmsg 7900"));
1152
1153 } else if (!strncmp(tmpstr, "reqauth", 7)) {
1154
1155 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
1156
1157 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1158
1159 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1160
1161 } else if (!strncmp(tmpstr, "reqemail", 8)) {
1162
1163 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1164
1165 } else if (!strncmp(tmpstr, "changepass", 8)) {
1166
1167 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1168
1169 } else if (!strncmp(tmpstr, "setemail", 8)) {
1170
1171 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1172
1173 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1174 int i;
1175 i = atoi(tmpstr+8);
1176 if (i < 10000) {
1177 char *newbuf;
1178 int z;
1179
1180 newbuf = malloc(i+1);
1181 for (z = 0; z < i; z++) {
1182 newbuf[z] = (z % 10)+0x30;
1183 }
1184 newbuf[i] = '\0';
1185 aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf, strlen(newbuf));
1186 free(newbuf);
1187 }
1188
1189 } else {
1190
1191 dprintf("unknown command.\n");
1192 aim_add_buddy(sess, command->conn, userinfo->sn);
1193
1194 }
1195
1196 return 0;
1197}
1198
1199/*
1200 * The user-level Incoming ICBM callback.
1201 *
1202 */
1203int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1204{
1205 int channel;
1206 va_list ap;
1207
1208 va_start(ap, command);
1209 channel = va_arg(ap, int);
1210
1211 /*
1212 * Channel 1: Standard Message
1213 */
1214 if (channel == 1) {
1215 struct aim_userinfo_s *userinfo;
1216 char *msg = NULL;
1217 u_int icbmflags = 0;
1218 char *tmpstr = NULL;
1219 unsigned short flag1, flag2;
1220 int finlen = 0;
1221 unsigned char *fingerprint = NULL;
1222 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
1223
1224 userinfo = va_arg(ap, struct aim_userinfo_s *);
1225 msg = va_arg(ap, char *);
1226 icbmflags = va_arg(ap, u_int);
1227 flag1 = va_arg(ap, int);
1228 flag2 = va_arg(ap, int);
1229 finlen = va_arg(ap, int);
1230 fingerprint = va_arg(ap, unsigned char *);
1231 va_end(ap);
1232
1233 clienttype = aim_fingerprintclient(fingerprint, finlen);
1234
1235 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
1236 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
1237 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1238 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
1239 printuserflags(userinfo->flags);
1240 dinlineprintf("\n");
1241
1242 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1243 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1244 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1245 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
1246
1247 dprintf("faimtest: icbm: icbmflags = ");
1248 if (icbmflags & AIM_IMFLAGS_AWAY)
1249 dinlineprintf("away ");
1250 if (icbmflags & AIM_IMFLAGS_ACK)
1251 dinlineprintf("ackrequest ");
1252 dinlineprintf("\n");
1253
1254 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
1255
1256 dvprintf("faimtest: icbm: message: %s\n", msg);
1257
1258 if (msg) {
1259 int i = 0;
1260
1261 while (msg[i] == '<') {
1262 if (msg[i] == '<') {
1263 while (msg[i] != '>')
1264 i++;
1265 i++;
1266 }
1267 }
1268 tmpstr = msg+i;
1269
1270 faimtest_handlecmd(sess, command, userinfo, tmpstr);
1271
1272 }
1273 }
1274 /*
1275 * Channel 2: Rendevous Request
1276 */
1277 else if (channel == 2) {
1278 struct aim_userinfo_s *userinfo;
1279 unsigned short reqclass;
1280
1281 reqclass = va_arg(ap, int);
1282 switch (reqclass) {
1283 case AIM_CAPS_VOICE: {
1284 userinfo = va_arg(ap, struct aim_userinfo_s *);
1285 va_end(ap);
1286
1287 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1288 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1289 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
1290 printuserflags(userinfo->flags);
1291 dinlineprintf("\n");
1292
1293 /* we dont get membersince on chat invites! */
1294 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1295 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1296
1297 break;
1298 }
1299 case AIM_CAPS_GETFILE: {
1300 char *ip, *cookie;
1301 struct aim_conn_t *newconn;
1302 struct aim_fileheader_t *fh;
1303
1304 userinfo = va_arg(ap, struct aim_userinfo_s *);
1305 ip = va_arg(ap, char *);
1306 cookie = va_arg(ap, char *);
1307 va_end(ap);
1308
1309 dvprintf("faimtest: get file request from %s (at %s) %x\n", userinfo->sn, ip, reqclass);
1310
1311 fh = aim_getlisting(sess, listingfile);
1312
1313 newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, fh->totfiles, fh->totsize, fh->size, fh->checksum, reqclass);
1314
1315 if( (!newconn) || (newconn->fd == -1) ) {
1316 dprintf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
1317 if(newconn)
1318 aim_conn_kill(sess, &newconn);
1319 break;
1320 }
1321
1322 free(fh);
1323
1324 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
1325 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1326 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1327 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
1328
1329 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1330
1331 dprintf("faimtest: getfile connect succeeded, handlers added.\n");
1332
1333 break;
1334 }
1335 case AIM_CAPS_SENDFILE: {
1336 dprintf("faimtest: send file!\n");
1337 break;
1338 }
1339 case AIM_CAPS_CHAT: {
1340 char *msg,*encoding,*lang;
1341 struct aim_chat_roominfo *roominfo;
1342
1343 userinfo = va_arg(ap, struct aim_userinfo_s *);
1344 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1345 msg = va_arg(ap, char *);
1346 encoding = va_arg(ap, char *);
1347 lang = va_arg(ap, char *);
1348 va_end(ap);
1349
1350 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1351 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1352 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
1353 printuserflags(userinfo->flags);
1354 dinlineprintf("\n");
1355
1356 /* we dont get membersince on chat invites! */
1357 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1358 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1359
1360 dvprintf("faimtest: chat invitation: message = %s\n", msg);
1361 dvprintf("faimtest: chat invitation: room name = %s\n", roominfo->name);
1362 dvprintf("faimtest: chat invitation: encoding = %s\n", encoding);
1363 dvprintf("faimtest: chat invitation: language = %s\n", lang);
1364 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
1365 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
1366 dvprintf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
1367 /*
1368 * Automatically join room...
1369 */
1370 aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
1371 break;
1372 }
1373 case AIM_CAPS_IMIMAGE: {
1374 struct aim_directim_priv *priv;
1375 struct aim_conn_t *newconn;
1376
1377 dprintf("faimtest: icbm: rendezvous imimage\n");
1378
1379 userinfo = va_arg(ap, struct aim_userinfo_s *);
1380 priv = va_arg(ap, struct aim_directim_priv *);
1381 va_end(ap);
1382
1383 dvprintf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
1384
1385 newconn = aim_directim_connect(sess, command->conn, priv);
1386
1387 if ( (!newconn) || (newconn->fd == -1) ) {
1388 dprintf("faimtest: icbm: imimage: could not connect\n");
1389
1390 if (newconn)
1391 aim_conn_kill(sess, &newconn);
1392
1393 break;
1394 }
1395
1396 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1397 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1398 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1399
1400 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
1401
1402 aim_send_im_direct(sess, newconn, "goodday");
1403
1404 break;
1405 }
1406 default:
1407 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
1408 } /* switch */
1409 } else
1410 dvprintf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1411 dprintf("faimtest: icbm: done with ICBM handling\n");
1412
1413 return 1;
1414}
1415
1416int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1417{
1418 va_list ap;
1419 struct aim_directim_priv *priv;
1420 struct aim_conn_t *newconn, *listenerconn;
1421
1422 va_start(ap, command);
1423 newconn = va_arg(ap, struct aim_conn_t *);
1424 listenerconn = va_arg(ap, struct aim_conn_t *);
1425 va_end(ap);
1426
1427 aim_conn_close(listenerconn);
1428 aim_conn_kill(sess, &listenerconn);
1429
1430 priv = (struct aim_directim_priv *)newconn->priv;
1431
1432 dvprintf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
1433
1434 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1435 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1436 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1437
1438 aim_send_im_direct(sess, newconn, "goodday");
1439
1440 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
1441
1442 return 1;
1443}
1444
1445int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1446{
1447 va_list ap;
1448 struct aim_directim_priv *priv;
1449
1450 va_start(ap, command);
1451 priv = va_arg(ap, struct aim_directim_priv *);
1452
1453 va_end(ap);
1454
1455 dprintf("faimtest: directim_connect\n");
1456
1457 return 1;
1458}
1459
1460int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1461{
1462 va_list ap;
1463 char *msg = NULL;
1464 struct aim_conn_t *conn;
1465 struct aim_directim_priv *priv;
1466
1467 va_start(ap, command);
1468 conn = va_arg(ap, struct aim_conn_t *);
1469 msg = va_arg(ap, char *);
1470 va_end(ap);
1471
1472 if(!(priv = conn->priv)) {
1473 dvprintf("faimtest: directim: no private struct on conn with fd %d\n", conn->fd);
1474 return -1;
1475 }
1476
1477 dvprintf("faimtest: Directim from %s: %s\n", priv->sn, msg);
1478 if (!strncmp(msg, "sendmsg", 7)) {
1479 int i;
1480 i = atoi(msg+8);
1481 if (i < 10000) {
1482 char *newbuf;
1483 int z;
1484
1485 newbuf = malloc(i+1);
1486 for (z = 0; z < i; z++) {
1487 newbuf[z] = (z % 10)+0x30;
1488 }
1489 newbuf[i] = '\0';
1490 aim_send_im_direct(sess, conn, newbuf);
1491 free(newbuf);
1492 }
1493 } else if (!strncmp(msg, "goodday", 7)) {
1494 aim_send_im_direct(sess, conn, "Good day to you, too");
1495 } else {
1496 char newmsg[1024];
1497 snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1498 aim_send_im_direct(sess, conn, newmsg);
1499 }
1500 return 1;
1501}
1502
1503int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1504{
1505 va_list ap;
1506 struct aim_conn_t *conn;
1507 char *sn;
1508
1509 va_start(ap, command);
1510 conn = va_arg(ap, struct aim_conn_t *);
1511 sn = va_arg(ap, char *);
1512 va_end(ap);
1513
1514 dvprintf("faimtest: directim: disconnected from %s\n", sn);
1515
1516 aim_conn_kill(sess, &conn);
1517 return 1;
1518}
1519
1520int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1521{
1522 va_list ap;
1523 struct aim_conn_t *conn;
1524 struct aim_directim_priv *priv;
1525
1526 va_start(ap, command);
1527 conn = va_arg(ap, struct aim_conn_t *);
1528 va_end(ap);
1529
1530 if(!(priv = (struct aim_directim_priv *)conn->priv)) {
1531 dvprintf("faimtest: no private struct on conn with fd %d!\n", conn->fd);
1532 return -1;
1533 }
1534
1535 dvprintf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
1536 return 1;
1537}
1538
1539int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1540{
1541 unsigned short change = 0;
1542 int perms, type, length, str;
1543 char *val;
1544 va_list ap;
1545
1546 va_start(ap, command);
1547 perms = va_arg(ap, int);
1548 type = va_arg(ap, int);
1549 length = va_arg(ap, int);
1550 val = va_arg(ap, char *);
1551 str = va_arg(ap, int);
1552 va_end(ap);
1553
1554 if (aimutil_get16(command->data+2) == 0x0005)
1555 change = 1;
1556
1557 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
1558
1559 return 1;
1560}
1561
1562int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1563{
1564 struct aim_userinfo_s *userinfo;
1565
1566 va_list ap;
1567 va_start(ap, command);
1568 userinfo = va_arg(ap, struct aim_userinfo_s *);
1569 va_end(ap);
1570
1571 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1572 time(NULL),
1573 userinfo->sn, userinfo->flags,
1574 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1575 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1576 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1577 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1578 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1579 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1580 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1581 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1582 userinfo->capabilities);
1583 return 1;
1584}
1585
1586int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1587{
1588 struct aim_userinfo_s *userinfo;
1589
1590 va_list ap;
1591 va_start(ap, command);
1592 userinfo = va_arg(ap, struct aim_userinfo_s *);
1593 va_end(ap);
1594
1595 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1596 time(NULL),
1597 userinfo->sn, userinfo->flags,
1598 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1599 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1600 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1601 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1602 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1603 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1604 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1605 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1606 userinfo->capabilities);
1607 return 1;
1608}
1609
1610int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1611{
1612 static char *codes[] = {
1613 "Unknown",
1614 "Mandatory upgrade",
1615 "Advisory upgrade",
1616 "System bulletin",
1617 "Top o' the world!"};
1618 static int codeslen = 5;
1619
1620 char *msg;
1621 unsigned short id;
1622 va_list ap;
1623
1624 va_start(ap, command);
1625 id = va_arg(ap, int);
1626 msg = va_arg(ap, char *);
1627 va_end(ap);
1628
1629 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1630 (id < codeslen)?codes[id]:"unknown");
1631
1632 if (!connected)
1633 connected++;
1634
1635#if 0
1636 aim_bos_reqservice(sess, command->conn, 0x0005); /* adverts */
1637 aim_bos_reqservice(sess, command->conn, 0x000f); /* user directory */
1638
1639 /* Don't know what this does... */
1640 /* XXX sess->sn should be normalized by the 0001/000f handler */
1641 aim_0002_000b(sess, command->conn, sess->sn);
1642#endif
1643
1644 return 1;
1645}
1646
1647int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1648{
1649 va_list ap;
1650 unsigned short reason;
1651
1652 va_start(ap, command);
1653 reason = va_arg(ap, int);
1654 va_end(ap);
1655
1656 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1657
1658 return 1;
1659}
1660
1661int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1662{
1663 va_list ap;
1664 char *destsn;
1665 unsigned short reason;
1666
1667 va_start(ap, command);
1668 reason = va_arg(ap, int);
1669 destsn = va_arg(ap, char *);
1670 va_end(ap);
1671
1672 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1673
1674 return 1;
1675}
1676
1677int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1678{
1679 va_list ap;
1680 char *destsn;
1681 unsigned short reason;
1682
1683 va_start(ap, command);
1684 reason = va_arg(ap, int);
1685 destsn = va_arg(ap, char *);
1686 va_end(ap);
1687
1688 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1689
1690 return 1;
1691}
1692
1693/*
1694 * Handles callbacks for AIM_CB_MISSED_CALL.
1695 */
1696int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1697{
1698 static char *missedreasons[] = {
1699 "Unknown",
1700 "Message too large"};
1701 static int missedreasonslen = 2;
1702
1703 va_list ap;
1704 unsigned short chan, nummissed, reason;
1705 struct aim_userinfo_s *userinfo;
1706
1707 va_start(ap, command);
1708 chan = va_arg(ap, int);
1709 userinfo = va_arg(ap, struct aim_userinfo_s *);
1710 nummissed = va_arg(ap, int);
1711 reason = va_arg(ap, int);
1712 va_end(ap);
1713
1714 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1715
1716 return 1;
1717}
1718
1719int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1720{
1721 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
1722 char *key;
1723 va_list ap;
1724
1725 va_start(ap, command);
1726 key = va_arg(ap, char *);
1727 va_end(ap);
1728
1729 aim_send_login(sess, command->conn, screenname, password, &info, key);
1730
1731 return 1;
1732}
1733
1734int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1735{
1736 va_list ap;
1737 struct aim_userinfo_s *userinfo;
1738 int count = 0, i = 0;
1739
1740 va_start(ap, command);
1741 count = va_arg(ap, int);
1742 userinfo = va_arg(ap, struct aim_userinfo_s *);
1743 va_end(ap);
1744
1745 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
1746 while (i < count)
1747 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1748
1749 return 1;
1750}
1751
1752int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1753{
1754 va_list ap;
1755 struct aim_userinfo_s *userinfo;
1756 int count = 0, i = 0;
1757
1758 va_start(ap, command);
1759 count = va_arg(ap, int);
1760 userinfo = va_arg(ap, struct aim_userinfo_s *);
1761 va_end(ap);
1762
1763 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1764
1765 for (i = 0; i < count; )
1766 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1767
1768 return 1;
1769}
1770
1771int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1772{
1773 va_list ap;
1774 struct aim_userinfo_s *userinfo;
1775 struct aim_chat_roominfo *roominfo;
1776 char *roomname;
1777 int usercount,i;
1778 char *roomdesc;
1779 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1780 unsigned long creationtime;
1781
1782 va_start(ap, command);
1783 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1784 roomname = va_arg(ap, char *);
1785 usercount= va_arg(ap, int);
1786 userinfo = va_arg(ap, struct aim_userinfo_s *);
1787 roomdesc = va_arg(ap, char *);
1788 unknown_c9 = va_arg(ap, int);
1789 creationtime = va_arg(ap, unsigned long);
1790 maxmsglen = va_arg(ap, int);
1791 unknown_d2 = va_arg(ap, int);
1792 unknown_d5 = va_arg(ap, int);
1793 va_end(ap);
1794
1795 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1796 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
1797 (char *)command->conn->priv,
1798 roominfo->exchange,
1799 roominfo->name,
1800 roominfo->instance);
1801 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1802 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1803 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1804
1805 for (i = 0; i < usercount; )
1806 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1807
1808 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1809 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1810 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1811 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1812 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1813
1814 return 1;
1815}
1816
1817int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1818{
1819 va_list ap;
1820 struct aim_userinfo_s *userinfo;
1821 char *msg;
1822 char tmpbuf[1152];
1823
1824 va_start(ap, command);
1825 userinfo = va_arg(ap, struct aim_userinfo_s *);
1826 msg = va_arg(ap, char *);
1827 va_end(ap);
1828
1829 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1830
1831 /*
1832 * Do an echo for testing purposes. But not for ourselves ("oops!")
1833 */
1834 if (strcmp(userinfo->sn, sess->sn) != 0)
1835 {
1836 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1837 aim_chat_send_im(sess, command->conn, 0, tmpbuf, strlen(tmpbuf));
1838 }
1839
1840 return 1;
1841}
1842
1843int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1844{
1845 unsigned short type;
1846 va_list ap;
1847
1848 va_start(ap, command);
1849 type = va_arg(ap, int);
1850
1851 switch(type) {
1852 case 0x0002: {
1853 int maxrooms;
1854 struct aim_chat_exchangeinfo *exchanges;
1855 int exchangecount,i = 0;
1856
1857 maxrooms = va_arg(ap, int);
1858 exchangecount = va_arg(ap, int);
1859 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1860 va_end(ap);
1861
1862 dprintf("faimtest: chat info: Chat Rights:\n");
1863 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1864
1865 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1866 for (i = 0; i < exchangecount; i++) {
1867 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1868 exchanges[i].number,
1869 exchanges[i].name,
1870 exchanges[i].charset1,
1871 exchanges[i].lang1);
1872 }
1873
1874 }
1875 break;
1876 case 0x0008: {
1877 char *fqcn, *name, *ck;
1878 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
1879 unsigned char createperms;
1880 unsigned long createtime;
1881
1882 fqcn = va_arg(ap, char *);
1883 instance = va_arg(ap, int);
1884 exchange = va_arg(ap, int);
1885 flags = va_arg(ap, int);
1886 createtime = va_arg(ap, unsigned long);
1887 maxmsglen = va_arg(ap, int);
1888 maxoccupancy = va_arg(ap, int);
1889 createperms = va_arg(ap, int);
1890 unknown = va_arg(ap, int);
1891 name = va_arg(ap, char *);
1892 ck = va_arg(ap, char *);
1893 va_end(ap);
1894
1895 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
1896 }
1897 break;
1898 default:
1899 va_end(ap);
1900 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
1901 }
1902 return 1;
1903}
1904
1905int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1906{
1907 va_list ap;
1908 unsigned short code;
1909 char *msg = NULL;
1910
1911 va_start(ap, command);
1912 code = va_arg(ap, int);
1913 msg = va_arg(ap, char *);
1914 va_end(ap);
1915
1916 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1917 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1918
1919 connected = 0;
1920
1921 return 1;
1922}
1923
1924int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1925{
1926 dprintf("faimtest: connecting to an aimdebugd!\n");
1927
1928 /* convert the authorizer connection to a BOS connection */
1929 command->conn->type = AIM_CONN_TYPE_BOS;
1930
1931 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1932
1933 /* tell the aimddebugd we're ready */
1934 aim_debugconn_sendconnect(sess, command->conn);
1935
1936 /* go right into main loop (don't open a BOS connection, etc) */
1937 return 1;
1938}
1939
1940/*
1941 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1942 */
1943int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1944{
1945 va_list ap;
1946 unsigned short type;
1947 char *sn = NULL;
1948
1949 va_start(ap, command);
1950 type = va_arg(ap, int);
1951 sn = va_arg(ap, char *);
1952 va_end(ap);
1953
1954 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1955
1956 return 1;
1957}
1958
1959int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1960{
1961 va_list ap;
1962 struct aim_conn_t *oftconn;
1963 struct aim_fileheader_t *fh;
1964 char *cookie;
1965
1966 va_start(ap, command);
1967 oftconn = va_arg(ap, struct aim_conn_t *);
1968 fh = va_arg(ap, struct aim_fileheader_t *);
1969 cookie = va_arg(ap, char *);
1970 va_end(ap);
1971
1972 dvprintf("faimtest: request for file %s.\n", fh->name);
1973
1974 return 1;
1975}
1976
1977
1978int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1979{
1980 va_list ap;
1981 struct aim_conn_t *oftconn;
1982 struct aim_fileheader_t *fh;
1983 char *path, *cookie;
1984 int pos, bufpos = 0, bufsize = 2048, i;
1985 char *buf;
1986
1987 FILE *file;
1988
1989 va_start(ap, command);
1990 oftconn = va_arg(ap, struct aim_conn_t *);
1991 fh = va_arg(ap, struct aim_fileheader_t *);
1992 cookie = va_arg(ap, char *);
1993 va_end(ap);
1994
1995 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
1996
1997 if(!(buf = malloc(2048)))
1998 return -1;
1999
2000 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
2001 dperror("calloc");
2002 dprintf("faimtest: error in calloc of path\n");
2003 return 0; /* XXX: no idea what winaim expects here =) */
2004 }
2005
2006 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
2007
2008
2009 if( (file = fopen(path, "r")) == NULL) {
2010 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
2011 return 0;
2012 }
2013
2014 /*
2015 * This is a mess. Remember that faimtest is demonstration code
2016 * only and for the sake of the gods, don't use this code in any
2017 * of your clients. --mid
2018 */
2019 for(pos = 0; pos < fh->size; pos++) {
2020 bufpos = pos % bufsize;
2021
2022 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2023 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2024 dperror("faim: getfile_send: write1");
2025 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2026 free(buf);
2027 return -1;
2028 }
2029 }
2030 if( (buf[bufpos] = fgetc(file)) == EOF) {
2031 if(pos != fh->size) {
2032 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2033 free(buf);
2034 return -1;
2035 }
2036 }
2037 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
2038 }
2039
2040 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2041 dperror("faim: getfile_send: write2");
2042 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2043 free(buf);
2044 return -1;
2045 }
2046
2047 free(buf);
2048 free(fh);
2049 return 1;
2050}
2051
2052int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2053{
2054 va_list ap;
2055 struct aim_conn_t *conn;
2056 struct aim_fileheader_t *fh;
2057
2058 va_start(ap, command);
2059 conn = va_arg(ap, struct aim_conn_t *);
2060 fh = va_arg(ap, struct aim_fileheader_t *);
2061 va_end(ap);
2062
2063 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
2064
2065 aim_conn_close(conn);
2066 aim_conn_kill(sess, &conn);
2067 return 1;
2068}
2069
2070int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2071{
2072 va_list ap;
2073 struct aim_conn_t *conn;
2074 char *sn;
2075
2076 va_start(ap, command);
2077 conn = va_arg(ap, struct aim_conn_t *);
2078 sn = va_arg(ap, char *);
2079 va_end(ap);
2080
2081 aim_conn_kill(sess, &conn);
2082
2083 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
2084 return 1;
2085}
2086int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2087{
2088 va_list ap;
2089 struct aim_conn_t *conn, *listenerconn;
2090 struct aim_filetransfer_priv *priv;
2091
2092 va_start(ap, command);
2093 conn = va_arg(ap, struct aim_conn_t *);
2094 listenerconn = va_arg(ap, struct aim_conn_t *);
2095 va_end(ap);
2096
2097 aim_conn_close(listenerconn);
2098 aim_conn_kill(sess, &listenerconn);
2099
2100 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
2101 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
2102 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
2103 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
2104 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
2105 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
2106 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
2107 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
2108
2109 priv = (struct aim_filetransfer_priv *)conn->priv;
2110
2111 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
2112 return 1;
2113}
2114
2115int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2116{
2117 va_list ap;
2118 struct aim_conn_t *conn;
2119 char *listing;
2120 struct aim_filetransfer_priv *ft;
2121 char *filename, *nameend, *sizec;
2122 int filesize, namelen;
2123
2124 va_start(ap, command);
2125 conn = va_arg(ap, struct aim_conn_t *);
2126 ft = va_arg(ap, struct aim_filetransfer_priv *);
2127 listing = va_arg(ap, char *);
2128 va_end(ap);
2129
2130 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2131
2132 nameend = strstr(listing+0x1a, "\r");
2133
2134 namelen = nameend - (listing + 0x1a);
2135
2136 filename = malloc(namelen + 1);
2137 strncpy(filename, listing+0x1a, namelen);
2138 filename[namelen] = 0x00;
2139
2140 sizec = malloc(8+1);
2141 memcpy(sizec, listing + 0x11, 8);
2142 sizec[8] = 0x00;
2143
2144 filesize = strtol(sizec, (char **)NULL, 10);
2145
2146 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2147
2148 aim_oft_getfile_request(sess, conn, filename, filesize);
2149
2150 free(filename);
2151 free(sizec);
2152
2153 return 0;
2154}
2155
2156int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2157{
2158 va_list ap;
2159 struct aim_conn_t *oftconn;
2160 struct aim_fileheader_t *fh;
2161 int pos, bufpos = 0, bufsize = 2048, i;
2162 char *buf;
2163
2164 va_start(ap, command);
2165 oftconn = va_arg(ap, struct aim_conn_t *);
2166 fh = va_arg(ap, struct aim_fileheader_t *);
2167 va_end(ap);
2168
2169 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2170
2171 if(!(buf = malloc(2048)))
2172 return -1;
2173
2174 for(pos = 0; pos < fh->size; pos++) {
2175 bufpos = pos % bufsize;
2176
2177 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2178 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2179 dperror("faim: getfile_send: write1");
2180 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2181 free(buf);
2182 return -1;
2183 }
2184 }
2185 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2186 if(pos != fh->size) {
2187 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2188 free(buf);
2189 return -1;
2190 }
2191 }
2192 }
2193
2194 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2195 dperror("faim: getfile_send: write2");
2196 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2197 free(buf);
2198 return -1;
2199 }
2200
2201 dprintf("faimtest: sent listing\n");
2202 free(buf);
2203 return 0;
2204}
2205
2206int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2207{
2208 va_list ap;
2209 struct aim_conn_t *conn;
2210 struct aim_filetransfer_priv *ft;
2211 unsigned char data;
2212 int pos;
2213
2214 va_start(ap, command);
2215 conn = va_arg(ap, struct aim_conn_t *);
2216 ft = va_arg(ap, struct aim_filetransfer_priv *);
2217 va_end(ap);
2218
2219 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2220
2221 for(pos = 0; pos < ft->fh.size; pos++) {
2222 read(conn->fd, &data, 1);
2223 printf("%c(%02x) ", data, data);
2224 }
2225
2226 printf("\n");
2227
2228 aim_oft_getfile_end(sess, conn);
2229
2230 return 0;
2231}
2232
2233int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2234{
2235 va_list ap;
2236 struct aim_conn_t *conn;
2237
2238 va_start(ap, command);
2239 conn = va_arg(ap, struct aim_conn_t *);
2240 va_end(ap);
2241
2242 aim_conn_close(conn);
2243 aim_conn_kill(sess, &conn);
2244 return 0;
2245}
2246
2247
2248int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2249{
2250 static char *codes[5] = {"invalid",
2251 "change",
2252 "warning",
2253 "limit",
2254 "limit cleared"};
2255 va_list ap;
2256 int code;
2257 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
2258 unsigned long currentavg, maxavg;
2259
2260 va_start(ap, command);
2261
2262 /* See code explanations below */
2263 code = va_arg(ap, int);
2264
2265 /*
2266 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
2267 */
2268 rateclass = va_arg(ap, unsigned long);
2269
2270 /*
2271 * Not sure what this is exactly. I think its the temporal
2272 * relation factor (ie, how to make the rest of the numbers
2273 * make sense in the real world).
2274 */
2275 windowsize = va_arg(ap, unsigned long);
2276
2277 /* Explained below */
2278 clear = va_arg(ap, unsigned long);
2279 alert = va_arg(ap, unsigned long);
2280 limit = va_arg(ap, unsigned long);
2281 disconnect = va_arg(ap, unsigned long);
2282 currentavg = va_arg(ap, unsigned long);
2283 maxavg = va_arg(ap, unsigned long);
2284
2285 va_end(ap);
2286
2287
2288 dvprintf("faimtest: rate %s (rate class 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
2289 (code < 5)?codes[code]:"invalid",
2290 rateclass,
2291 currentavg, maxavg,
2292 alert, clear,
2293 limit, disconnect,
2294 windowsize);
2295
2296 if (code == AIM_RATE_CODE_CHANGE) {
2297 /*
2298 * Not real sure when these get sent.
2299 */
2300 if (currentavg >= clear)
2301 aim_conn_setlatency(command->conn, 0);
2302
2303 } else if (code == AIM_RATE_CODE_WARNING) {
2304 /*
2305 * We start getting WARNINGs the first time we go below the 'alert'
2306 * limit (currentavg < alert) and they stop when either we pause
2307 * long enough for currentavg to go above 'clear', or until we
2308 * flood it bad enough to go below 'limit' (and start getting
2309 * LIMITs instead) or even further and go below 'disconnect' and
2310 * get disconnected completely (and won't be able to login right
2311 * away either).
2312 */
2313 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2314
2315 } else if (code == AIM_RATE_CODE_LIMIT) {
2316 /*
2317 * When we hit LIMIT, messages will start getting dropped.
2318 */
2319 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2320
2321 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2322 /*
2323 * The limit is cleared when curavg goes above 'clear'.
2324 */
2325 aim_conn_setlatency(command->conn, 0);
2326 }
2327
2328 return 1;
2329}
2330
2331int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2332{
2333 va_list ap;
2334 int newevil;
2335 struct aim_userinfo_s *userinfo;
2336
2337 va_start(ap, command);
2338 newevil = va_arg(ap, int);
2339 userinfo = va_arg(ap, struct aim_userinfo_s *);
2340 va_end(ap);
2341
2342 /*
2343 * Evil Notifications that are lacking userinfo->sn are anon-warns
2344 * if they are an evil increases, but are not warnings at all if its
2345 * a decrease (its the natural backoff happening).
2346 *
2347 * newevil is passed as an int representing the new evil value times
2348 * ten.
2349 */
2350 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2351
2352 return 1;
2353}
2354
2355int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2356{
2357 va_list ap;
2358 char *address, *SNs;
2359 int i, num;
2360
2361 va_start(ap, command);
2362 address = va_arg(ap, char *);
2363 num = va_arg(ap, int);
2364 SNs = va_arg(ap, char *);
2365 va_end(ap);
2366
2367 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2368
2369 for(i = 0; i < num; i++)
2370 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2371 dinlineprintf("\n");
2372
2373 return 1;
2374}
2375
2376int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2377{
2378 va_list ap;
2379 char *address;
2380
2381 va_start(ap, command);
2382 address = va_arg(ap, char *);
2383 va_end(ap);
2384
2385 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
2386
2387 return 1;
2388}
This page took 0.279654 seconds and 5 git commands to generate.