]> andersk Git - libfaim.git/blame_incremental - utils/faimtest/faimtest.c
- Thu Mar 29 14:45:22 CST 2001 (jbm)
[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, char *modname)
801{
802 FILE *f;
803
804 char *filename;
805 int len;
806
807 len = strlen(aimbinarypath)+1+strlen(modname)+1;
808
809 if(!(filename = malloc(len))) {
810 dperror("memrequest: malloc");
811 return -1;
812 }
813
814 memset(filename,0, len);
815 memcpy(filename, aimbinarypath, strlen(aimbinarypath));
816 filename[strlen(filename)] = '/';
817 strncat(filename, modname, len - strlen(filename));
818
819 if (!(f = fopen(filename, "r"))) {
820 dperror("memrequest: fopen");
821 return -1;
822 }
823
824 if (fseek(f, offset, SEEK_SET) == -1) {
825 dperror("memrequest: fseek");
826 fclose(f);
827 return -1;
828 }
829
830 if (fread(buf, buflen, 1, f) != 1) {
831 dperror("memrequest: fread");
832 fclose(f);
833 return -1;
834 }
835
836 fclose(f);
837
838 return buflen;
839}
840
841/*
842 * This will get an offset and a length. The client should read this
843 * data out of whatever AIM.EXE binary the user has provided (hopefully
844 * it matches the client information thats sent at login) and pass a
845 * buffer back to libfaim so it can hash the data and send it to AOL for
846 * inspection by the client police.
847 */
848static int faimtest_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...)
849{
850 va_list ap;
851 unsigned long offset, len;
852 unsigned char *buf;
853 char *modname;
854
855 va_start(ap, command);
856 offset = va_arg(ap, unsigned long);
857 len = va_arg(ap, unsigned long);
858 modname = va_arg(ap, char *);
859 va_end(ap);
860
861 if (!(buf = malloc(len))) {
862 dperror("memrequest: malloc");
863 return 0;
864 }
865
866 if (aimbinarypath && (getaimdata(buf, len, offset, modname) == len)) {
867
868 dvprintf("memrequest: sending %ld bytes from 0x%08lx in \"%s/%s\"...\n", len, offset, aimbinarypath, modname);
869
870 aim_sendmemblock(sess, command->conn, offset, len, buf);
871
872 } else {
873
874 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", aimbinarypath, modname);
875
876 aim_sendmemblock(sess, command->conn, offset, len, NULL);
877
878 }
879
880 free(buf);
881
882 return 1;
883}
884
885static int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
886{
887 va_list ap;
888 struct aim_conn_t *bosconn = NULL;
889 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
890 unsigned char *cookie = NULL;
891 int errorcode = 0, regstatus = 0;
892 int latestbuild = 0, latestbetabuild = 0;
893 char *latestrelease = NULL, *latestbeta = NULL;
894 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
895 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
896
897 va_start(ap, command);
898 sn = va_arg(ap, char *);
899 errorcode = va_arg(ap, int);
900 errurl = va_arg(ap, char *);
901 regstatus = va_arg(ap, int);
902 email = va_arg(ap, char *);
903 bosip = va_arg(ap, char *);
904 cookie = va_arg(ap, unsigned char *);
905
906 latestrelease = va_arg(ap, char *);
907 latestbuild = va_arg(ap, int);
908 latestreleaseurl = va_arg(ap, char *);
909 latestreleaseinfo = va_arg(ap, char *);
910
911 latestbeta = va_arg(ap, char *);
912 latestbetabuild = va_arg(ap, int);
913 latestbetaurl = va_arg(ap, char *);
914 latestbetainfo = va_arg(ap, char *);
915
916 va_end(ap);
917
918 dvprintf("Screen name: %s\n", sn);
919
920 /*
921 * Check for error.
922 */
923 if (errorcode || !bosip || !cookie) {
924 dvprintf("Login Error Code 0x%04x\n", errorcode);
925 dvprintf("Error URL: %s\n", errurl);
926 aim_conn_kill(sess, &command->conn);
927 return 1;
928 }
929
930 dvprintf("Reg status: %2d\n", regstatus);
931 dvprintf("Email: %s\n", email);
932 dvprintf("BOS IP: %s\n", bosip);
933
934 if (latestbeta)
935 dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
936
937 if (latestrelease)
938 dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
939
940 dprintf("Closing auth connection...\n");
941 aim_conn_kill(sess, &command->conn);
942 if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
943 dprintf("faimtest: could not connect to BOS: internal error\n");
944 return 1;
945 } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
946 dprintf("faimtest: could not connect to BOS\n");
947 aim_conn_kill(sess, &bosconn);
948 return 1;
949 }
950
951 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
952 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
953 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
954 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
955 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
956 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
957 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
958 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
959 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
960 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
961 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
962 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
963 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
964 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
965 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
966 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
967 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
968 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
969 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
970 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
971 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
972 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
973
974 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
975
976 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
977 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
978 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
979 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
980
981 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
982 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
983 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
984
985 aim_auth_sendcookie(sess, bosconn, cookie);
986
987 return 1;
988}
989
990static void printuserflags(unsigned short flags)
991{
992 if (flags & AIM_FLAG_UNCONFIRMED)
993 dinlineprintf("UNCONFIRMED ");
994 if (flags & AIM_FLAG_ADMINISTRATOR)
995 dinlineprintf("ADMINISTRATOR ");
996 if (flags & AIM_FLAG_AOL)
997 dinlineprintf("AOL ");
998 if (flags & AIM_FLAG_OSCAR_PAY)
999 dinlineprintf("OSCAR_PAY ");
1000 if (flags & AIM_FLAG_FREE)
1001 dinlineprintf("FREE ");
1002 if (flags & AIM_FLAG_AWAY)
1003 dinlineprintf("AWAY ");
1004 if (flags & AIM_FLAG_UNKNOWN40)
1005 dinlineprintf("ICQ? ");
1006 if (flags & AIM_FLAG_UNKNOWN80)
1007 dinlineprintf("UNKNOWN80 ");
1008 return;
1009}
1010
1011int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1012{
1013 struct aim_userinfo_s *userinfo;
1014 char *prof_encoding = NULL;
1015 char *prof = NULL;
1016 unsigned short inforeq = 0;
1017
1018 va_list ap;
1019 va_start(ap, command);
1020 userinfo = va_arg(ap, struct aim_userinfo_s *);
1021 prof_encoding = va_arg(ap, char *);
1022 prof = va_arg(ap, char *);
1023 inforeq = va_arg(ap, int);
1024 va_end(ap);
1025
1026 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
1027 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
1028 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
1029 printuserflags(userinfo->flags);
1030 dinlineprintf("\n");
1031
1032 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
1033 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1034 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
1035
1036 if (inforeq == AIM_GETINFO_GENERALINFO) {
1037 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1038 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
1039 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1040 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1041 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1042 } else
1043 dprintf("faimtest: userinfo: unknown info request\n");
1044
1045 return 1;
1046}
1047
1048static int faimtest_handlecmd(struct aim_session_t *sess, struct command_rx_struct *command, struct aim_userinfo_s *userinfo, char *tmpstr)
1049{
1050
1051 if (!strncmp(tmpstr, "disconnect", 10)) {
1052
1053 logout();
1054
1055 } else if (strstr(tmpstr, "goodday")) {
1056
1057 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.", strlen("Good day to you too."));
1058
1059 } else if (strstr(tmpstr, "warnme")) {
1060
1061 dprintf("faimtest: icbm: sending non-anon warning\n");
1062 aim_send_warning(sess, command->conn, userinfo->sn, 0);
1063
1064 } else if (strstr(tmpstr, "anonwarn")) {
1065
1066 dprintf("faimtest: icbm: sending anon warning\n");
1067 aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
1068
1069 } else if (strstr(tmpstr, "setdirectoryinfo")) {
1070
1071 dprintf("faimtest: icbm: sending backwards profile data\n");
1072 aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1073
1074 } else if (strstr(tmpstr, "setinterests")) {
1075
1076 dprintf("faimtest: icbm: setting fun interests\n");
1077 aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1078
1079 } else if (!strncmp(tmpstr, "getfile", 7)) {
1080
1081 if (!ohcaptainmycaptain) {
1082
1083 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!", strlen("I have no owner!"));
1084
1085 } else {
1086 struct aim_conn_t *newconn;
1087
1088 newconn = aim_getfile_initiate(sess, command->conn, (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1089 dvprintf("faimtest: getting file listing from %s\n", (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1090 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE, faimtest_getfile_initiate,0);
1091 }
1092
1093 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1094
1095 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
1096
1097 } else if (!strncmp(tmpstr, "create", 6)) {
1098
1099 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1100
1101 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1102 struct aim_conn_t *chatnavconn;
1103
1104 chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
1105 aim_conn_kill(sess, &chatnavconn);
1106
1107 } else if (!strncmp(tmpstr, "join", 4)) {
1108
1109 aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
1110
1111 } else if (!strncmp(tmpstr, "leave", 5)) {
1112
1113 aim_chat_leaveroom(sess, "worlddomination");
1114
1115 } else if (!strncmp(tmpstr, "getinfo", 7)) {
1116
1117 aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
1118 aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
1119 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
1120 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
1121
1122 } else if (!strncmp(tmpstr, "open directim", 13)) {
1123 struct aim_conn_t *newconn;
1124
1125 printf("faimtest: opening directim to %s\n", (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1126 newconn = aim_directim_initiate(sess, command->conn, NULL, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1127 if(!newconn || newconn->fd == -1)
1128 printf("connection failed!\n");
1129 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate,0);
1130
1131 } else if(!(strncmp(tmpstr, "lookup", 6))) {
1132
1133 aim_usersearch_address(sess, command->conn, tmpstr+7);
1134
1135 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1136
1137 aim_send_im(sess, command->conn, ohcaptainmycaptain, 0, "sendmsg 7900", strlen("sendmsg 7900"));
1138
1139 } else if (!strncmp(tmpstr, "reqauth", 7)) {
1140
1141 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
1142
1143 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1144
1145 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1146
1147 } else if (!strncmp(tmpstr, "reqemail", 8)) {
1148
1149 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1150
1151 } else if (!strncmp(tmpstr, "changepass", 8)) {
1152
1153 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1154
1155 } else if (!strncmp(tmpstr, "setemail", 8)) {
1156
1157 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1158
1159 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1160 int i;
1161 i = atoi(tmpstr+8);
1162 if (i < 10000) {
1163 char *newbuf;
1164 int z;
1165
1166 newbuf = malloc(i+1);
1167 for (z = 0; z < i; z++) {
1168 newbuf[z] = (z % 10)+0x30;
1169 }
1170 newbuf[i] = '\0';
1171 aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf, strlen(newbuf));
1172 free(newbuf);
1173 }
1174
1175 } else {
1176
1177 dprintf("unknown command.\n");
1178 aim_add_buddy(sess, command->conn, userinfo->sn);
1179
1180 }
1181
1182 return 0;
1183}
1184
1185/*
1186 * The user-level Incoming ICBM callback.
1187 *
1188 */
1189int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1190{
1191 int channel;
1192 va_list ap;
1193
1194 va_start(ap, command);
1195 channel = va_arg(ap, int);
1196
1197 /*
1198 * Channel 1: Standard Message
1199 */
1200 if (channel == 1) {
1201 struct aim_userinfo_s *userinfo;
1202 char *msg = NULL;
1203 u_int icbmflags = 0;
1204 char *tmpstr = NULL;
1205 unsigned short flag1, flag2;
1206 int finlen = 0;
1207 unsigned char *fingerprint = NULL;
1208 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
1209
1210 userinfo = va_arg(ap, struct aim_userinfo_s *);
1211 msg = va_arg(ap, char *);
1212 icbmflags = va_arg(ap, u_int);
1213 flag1 = va_arg(ap, int);
1214 flag2 = va_arg(ap, int);
1215 finlen = va_arg(ap, int);
1216 fingerprint = va_arg(ap, unsigned char *);
1217 va_end(ap);
1218
1219 clienttype = aim_fingerprintclient(fingerprint, finlen);
1220
1221 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
1222 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
1223 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1224 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
1225 printuserflags(userinfo->flags);
1226 dinlineprintf("\n");
1227
1228 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1229 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1230 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1231 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
1232
1233 dprintf("faimtest: icbm: icbmflags = ");
1234 if (icbmflags & AIM_IMFLAGS_AWAY)
1235 dinlineprintf("away ");
1236 if (icbmflags & AIM_IMFLAGS_ACK)
1237 dinlineprintf("ackrequest ");
1238 dinlineprintf("\n");
1239
1240 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
1241
1242 dvprintf("faimtest: icbm: message: %s\n", msg);
1243
1244 if (msg) {
1245 int i = 0;
1246
1247 while (msg[i] == '<') {
1248 if (msg[i] == '<') {
1249 while (msg[i] != '>')
1250 i++;
1251 i++;
1252 }
1253 }
1254 tmpstr = msg+i;
1255
1256 faimtest_handlecmd(sess, command, userinfo, tmpstr);
1257
1258 }
1259 }
1260 /*
1261 * Channel 2: Rendevous Request
1262 */
1263 else if (channel == 2) {
1264 struct aim_userinfo_s *userinfo;
1265 unsigned short reqclass;
1266
1267 reqclass = va_arg(ap, int);
1268 switch (reqclass) {
1269 case AIM_CAPS_VOICE: {
1270 userinfo = va_arg(ap, struct aim_userinfo_s *);
1271 va_end(ap);
1272
1273 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1274 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1275 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
1276 printuserflags(userinfo->flags);
1277 dinlineprintf("\n");
1278
1279 /* we dont get membersince on chat invites! */
1280 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1281 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1282
1283 break;
1284 }
1285 case AIM_CAPS_GETFILE: {
1286 char *ip, *cookie;
1287 struct aim_conn_t *newconn;
1288 struct aim_fileheader_t *fh;
1289
1290 userinfo = va_arg(ap, struct aim_userinfo_s *);
1291 ip = va_arg(ap, char *);
1292 cookie = va_arg(ap, char *);
1293 va_end(ap);
1294
1295 dvprintf("faimtest: get file request from %s (at %s) %x\n", userinfo->sn, ip, reqclass);
1296
1297 fh = aim_getlisting(sess, listingfile);
1298
1299 newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, fh->totfiles, fh->totsize, fh->size, fh->checksum, reqclass);
1300
1301 if( (!newconn) || (newconn->fd == -1) ) {
1302 dprintf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
1303 if(newconn)
1304 aim_conn_kill(sess, &newconn);
1305 break;
1306 }
1307
1308 free(fh);
1309
1310 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
1311 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1312 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1313 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
1314
1315 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1316
1317 dprintf("faimtest: getfile connect succeeded, handlers added.\n");
1318
1319 break;
1320 }
1321 case AIM_CAPS_SENDFILE: {
1322 dprintf("faimtest: send file!\n");
1323 break;
1324 }
1325 case AIM_CAPS_CHAT: {
1326 char *msg,*encoding,*lang;
1327 struct aim_chat_roominfo *roominfo;
1328
1329 userinfo = va_arg(ap, struct aim_userinfo_s *);
1330 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1331 msg = va_arg(ap, char *);
1332 encoding = va_arg(ap, char *);
1333 lang = va_arg(ap, char *);
1334 va_end(ap);
1335
1336 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1337 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1338 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
1339 printuserflags(userinfo->flags);
1340 dinlineprintf("\n");
1341
1342 /* we dont get membersince on chat invites! */
1343 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1344 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1345
1346 dvprintf("faimtest: chat invitation: message = %s\n", msg);
1347 dvprintf("faimtest: chat invitation: room name = %s\n", roominfo->name);
1348 dvprintf("faimtest: chat invitation: encoding = %s\n", encoding);
1349 dvprintf("faimtest: chat invitation: language = %s\n", lang);
1350 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
1351 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
1352 dvprintf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
1353 /*
1354 * Automatically join room...
1355 */
1356 aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
1357 break;
1358 }
1359 case AIM_CAPS_IMIMAGE: {
1360 struct aim_directim_priv *priv;
1361 struct aim_conn_t *newconn;
1362
1363 dprintf("faimtest: icbm: rendezvous imimage\n");
1364
1365 userinfo = va_arg(ap, struct aim_userinfo_s *);
1366 priv = va_arg(ap, struct aim_directim_priv *);
1367 va_end(ap);
1368
1369 dvprintf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
1370
1371 newconn = aim_directim_connect(sess, command->conn, priv);
1372
1373 if ( (!newconn) || (newconn->fd == -1) ) {
1374 dprintf("faimtest: icbm: imimage: could not connect\n");
1375
1376 if (newconn)
1377 aim_conn_kill(sess, &newconn);
1378
1379 break;
1380 }
1381
1382 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1383 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1384 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1385
1386 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
1387
1388 aim_send_im_direct(sess, newconn, "goodday");
1389
1390 break;
1391 }
1392 default:
1393 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
1394 } /* switch */
1395 } else
1396 dvprintf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1397 dprintf("faimtest: icbm: done with ICBM handling\n");
1398
1399 return 1;
1400}
1401
1402int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1403{
1404 va_list ap;
1405 struct aim_directim_priv *priv;
1406 struct aim_conn_t *newconn, *listenerconn;
1407
1408 va_start(ap, command);
1409 newconn = va_arg(ap, struct aim_conn_t *);
1410 listenerconn = va_arg(ap, struct aim_conn_t *);
1411 va_end(ap);
1412
1413 aim_conn_close(listenerconn);
1414 aim_conn_kill(sess, &listenerconn);
1415
1416 priv = (struct aim_directim_priv *)newconn->priv;
1417
1418 dvprintf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
1419
1420 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1421 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1422 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1423
1424 aim_send_im_direct(sess, newconn, "goodday");
1425
1426 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
1427
1428 return 1;
1429}
1430
1431int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1432{
1433 va_list ap;
1434 struct aim_directim_priv *priv;
1435
1436 va_start(ap, command);
1437 priv = va_arg(ap, struct aim_directim_priv *);
1438
1439 va_end(ap);
1440
1441 dprintf("faimtest: directim_connect\n");
1442
1443 return 1;
1444}
1445
1446int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1447{
1448 va_list ap;
1449 char *msg = NULL;
1450 struct aim_conn_t *conn;
1451 struct aim_directim_priv *priv;
1452
1453 va_start(ap, command);
1454 conn = va_arg(ap, struct aim_conn_t *);
1455 msg = va_arg(ap, char *);
1456 va_end(ap);
1457
1458 if(!(priv = conn->priv)) {
1459 dvprintf("faimtest: directim: no private struct on conn with fd %d\n", conn->fd);
1460 return -1;
1461 }
1462
1463 dvprintf("faimtest: Directim from %s: %s\n", priv->sn, msg);
1464 if (!strncmp(msg, "sendmsg", 7)) {
1465 int i;
1466 i = atoi(msg+8);
1467 if (i < 10000) {
1468 char *newbuf;
1469 int z;
1470
1471 newbuf = malloc(i+1);
1472 for (z = 0; z < i; z++) {
1473 newbuf[z] = (z % 10)+0x30;
1474 }
1475 newbuf[i] = '\0';
1476 aim_send_im_direct(sess, conn, newbuf);
1477 free(newbuf);
1478 }
1479 } else if (!strncmp(msg, "goodday", 7)) {
1480 aim_send_im_direct(sess, conn, "Good day to you, too");
1481 } else {
1482 char newmsg[1024];
1483 snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1484 aim_send_im_direct(sess, conn, newmsg);
1485 }
1486 return 1;
1487}
1488
1489int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1490{
1491 va_list ap;
1492 struct aim_conn_t *conn;
1493 char *sn;
1494
1495 va_start(ap, command);
1496 conn = va_arg(ap, struct aim_conn_t *);
1497 sn = va_arg(ap, char *);
1498 va_end(ap);
1499
1500 dvprintf("faimtest: directim: disconnected from %s\n", sn);
1501
1502 aim_conn_kill(sess, &conn);
1503 return 1;
1504}
1505
1506int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1507{
1508 va_list ap;
1509 struct aim_conn_t *conn;
1510 struct aim_directim_priv *priv;
1511
1512 va_start(ap, command);
1513 conn = va_arg(ap, struct aim_conn_t *);
1514 va_end(ap);
1515
1516 if(!(priv = (struct aim_directim_priv *)conn->priv)) {
1517 dvprintf("faimtest: no private struct on conn with fd %d!\n", conn->fd);
1518 return -1;
1519 }
1520
1521 dvprintf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
1522 return 1;
1523}
1524
1525int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1526{
1527 unsigned short change = 0;
1528 int perms, type, length, str;
1529 char *val;
1530 va_list ap;
1531
1532 va_start(ap, command);
1533 perms = va_arg(ap, int);
1534 type = va_arg(ap, int);
1535 length = va_arg(ap, int);
1536 val = va_arg(ap, char *);
1537 str = va_arg(ap, int);
1538 va_end(ap);
1539
1540 if (aimutil_get16(command->data+2) == 0x0005)
1541 change = 1;
1542
1543 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
1544
1545 return 1;
1546}
1547
1548int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1549{
1550 struct aim_userinfo_s *userinfo;
1551
1552 va_list ap;
1553 va_start(ap, command);
1554 userinfo = va_arg(ap, struct aim_userinfo_s *);
1555 va_end(ap);
1556
1557 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1558 time(NULL),
1559 userinfo->sn, userinfo->flags,
1560 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1561 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1562 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1563 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1564 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1565 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1566 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1567 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1568 userinfo->capabilities);
1569 return 1;
1570}
1571
1572int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1573{
1574 struct aim_userinfo_s *userinfo;
1575
1576 va_list ap;
1577 va_start(ap, command);
1578 userinfo = va_arg(ap, struct aim_userinfo_s *);
1579 va_end(ap);
1580
1581 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1582 time(NULL),
1583 userinfo->sn, userinfo->flags,
1584 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1585 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1586 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1587 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1588 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1589 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1590 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1591 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1592 userinfo->capabilities);
1593 return 1;
1594}
1595
1596int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1597{
1598 static char *codes[] = {
1599 "Unknown",
1600 "Mandatory upgrade",
1601 "Advisory upgrade",
1602 "System bulletin",
1603 "Top o' the world!"};
1604 static int codeslen = 5;
1605
1606 char *msg;
1607 unsigned short id;
1608 va_list ap;
1609
1610 va_start(ap, command);
1611 id = va_arg(ap, int);
1612 msg = va_arg(ap, char *);
1613 va_end(ap);
1614
1615 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1616 (id < codeslen)?codes[id]:"unknown");
1617
1618 if (!connected)
1619 connected++;
1620
1621#if 0
1622 aim_bos_reqservice(sess, command->conn, 0x0005); /* adverts */
1623 aim_bos_reqservice(sess, command->conn, 0x000f); /* user directory */
1624
1625 /* Don't know what this does... */
1626 /* XXX sess->sn should be normalized by the 0001/000f handler */
1627 aim_0002_000b(sess, command->conn, sess->sn);
1628#endif
1629
1630 return 1;
1631}
1632
1633int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1634{
1635 va_list ap;
1636 unsigned short reason;
1637
1638 va_start(ap, command);
1639 reason = va_arg(ap, int);
1640 va_end(ap);
1641
1642 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1643
1644 return 1;
1645}
1646
1647int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1648{
1649 va_list ap;
1650 char *destsn;
1651 unsigned short reason;
1652
1653 va_start(ap, command);
1654 reason = va_arg(ap, int);
1655 destsn = va_arg(ap, char *);
1656 va_end(ap);
1657
1658 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1659
1660 return 1;
1661}
1662
1663int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1664{
1665 va_list ap;
1666 char *destsn;
1667 unsigned short reason;
1668
1669 va_start(ap, command);
1670 reason = va_arg(ap, int);
1671 destsn = va_arg(ap, char *);
1672 va_end(ap);
1673
1674 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1675
1676 return 1;
1677}
1678
1679/*
1680 * Handles callbacks for AIM_CB_MISSED_CALL.
1681 */
1682int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1683{
1684 static char *missedreasons[] = {
1685 "Unknown",
1686 "Message too large"};
1687 static int missedreasonslen = 2;
1688
1689 va_list ap;
1690 unsigned short chan, nummissed, reason;
1691 struct aim_userinfo_s *userinfo;
1692
1693 va_start(ap, command);
1694 chan = va_arg(ap, int);
1695 userinfo = va_arg(ap, struct aim_userinfo_s *);
1696 nummissed = va_arg(ap, int);
1697 reason = va_arg(ap, int);
1698 va_end(ap);
1699
1700 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1701
1702 return 1;
1703}
1704
1705int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1706{
1707 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
1708 char *key;
1709 va_list ap;
1710
1711 va_start(ap, command);
1712 key = va_arg(ap, char *);
1713 va_end(ap);
1714
1715 aim_send_login(sess, command->conn, screenname, password, &info, key);
1716
1717 return 1;
1718}
1719
1720int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1721{
1722 va_list ap;
1723 struct aim_userinfo_s *userinfo;
1724 int count = 0, i = 0;
1725
1726 va_start(ap, command);
1727 count = va_arg(ap, int);
1728 userinfo = va_arg(ap, struct aim_userinfo_s *);
1729 va_end(ap);
1730
1731 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
1732 while (i < count)
1733 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1734
1735 return 1;
1736}
1737
1738int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1739{
1740 va_list ap;
1741 struct aim_userinfo_s *userinfo;
1742 int count = 0, i = 0;
1743
1744 va_start(ap, command);
1745 count = va_arg(ap, int);
1746 userinfo = va_arg(ap, struct aim_userinfo_s *);
1747 va_end(ap);
1748
1749 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1750
1751 for (i = 0; i < count; )
1752 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1753
1754 return 1;
1755}
1756
1757int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1758{
1759 va_list ap;
1760 struct aim_userinfo_s *userinfo;
1761 struct aim_chat_roominfo *roominfo;
1762 char *roomname;
1763 int usercount,i;
1764 char *roomdesc;
1765 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1766 unsigned long creationtime;
1767
1768 va_start(ap, command);
1769 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1770 roomname = va_arg(ap, char *);
1771 usercount= va_arg(ap, int);
1772 userinfo = va_arg(ap, struct aim_userinfo_s *);
1773 roomdesc = va_arg(ap, char *);
1774 unknown_c9 = va_arg(ap, int);
1775 creationtime = va_arg(ap, unsigned long);
1776 maxmsglen = va_arg(ap, int);
1777 unknown_d2 = va_arg(ap, int);
1778 unknown_d5 = va_arg(ap, int);
1779 va_end(ap);
1780
1781 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1782 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
1783 (char *)command->conn->priv,
1784 roominfo->exchange,
1785 roominfo->name,
1786 roominfo->instance);
1787 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1788 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1789 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1790
1791 for (i = 0; i < usercount; )
1792 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1793
1794 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1795 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1796 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1797 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1798 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1799
1800 return 1;
1801}
1802
1803int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1804{
1805 va_list ap;
1806 struct aim_userinfo_s *userinfo;
1807 char *msg;
1808 char tmpbuf[1152];
1809
1810 va_start(ap, command);
1811 userinfo = va_arg(ap, struct aim_userinfo_s *);
1812 msg = va_arg(ap, char *);
1813 va_end(ap);
1814
1815 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1816
1817 /*
1818 * Do an echo for testing purposes. But not for ourselves ("oops!")
1819 */
1820 if (strcmp(userinfo->sn, sess->sn) != 0)
1821 {
1822 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1823 aim_chat_send_im(sess, command->conn, 0, tmpbuf, strlen(tmpbuf));
1824 }
1825
1826 return 1;
1827}
1828
1829int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1830{
1831 unsigned short type;
1832 va_list ap;
1833
1834 va_start(ap, command);
1835 type = va_arg(ap, int);
1836
1837 switch(type) {
1838 case 0x0002: {
1839 int maxrooms;
1840 struct aim_chat_exchangeinfo *exchanges;
1841 int exchangecount,i = 0;
1842
1843 maxrooms = va_arg(ap, int);
1844 exchangecount = va_arg(ap, int);
1845 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1846 va_end(ap);
1847
1848 dprintf("faimtest: chat info: Chat Rights:\n");
1849 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1850
1851 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1852 for (i = 0; i < exchangecount; i++) {
1853 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1854 exchanges[i].number,
1855 exchanges[i].name,
1856 exchanges[i].charset1,
1857 exchanges[i].lang1);
1858 }
1859
1860 }
1861 break;
1862 case 0x0008: {
1863 char *fqcn, *name, *ck;
1864 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
1865 unsigned char createperms;
1866 unsigned long createtime;
1867
1868 fqcn = va_arg(ap, char *);
1869 instance = va_arg(ap, int);
1870 exchange = va_arg(ap, int);
1871 flags = va_arg(ap, int);
1872 createtime = va_arg(ap, unsigned long);
1873 maxmsglen = va_arg(ap, int);
1874 maxoccupancy = va_arg(ap, int);
1875 createperms = va_arg(ap, int);
1876 unknown = va_arg(ap, int);
1877 name = va_arg(ap, char *);
1878 ck = va_arg(ap, char *);
1879 va_end(ap);
1880
1881 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
1882 }
1883 break;
1884 default:
1885 va_end(ap);
1886 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
1887 }
1888 return 1;
1889}
1890
1891int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1892{
1893 va_list ap;
1894 unsigned short code;
1895 char *msg = NULL;
1896
1897 va_start(ap, command);
1898 code = va_arg(ap, int);
1899 msg = va_arg(ap, char *);
1900 va_end(ap);
1901
1902 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1903 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1904
1905 connected = 0;
1906
1907 return 1;
1908}
1909
1910int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1911{
1912 dprintf("faimtest: connecting to an aimdebugd!\n");
1913
1914 /* convert the authorizer connection to a BOS connection */
1915 command->conn->type = AIM_CONN_TYPE_BOS;
1916
1917 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1918
1919 /* tell the aimddebugd we're ready */
1920 aim_debugconn_sendconnect(sess, command->conn);
1921
1922 /* go right into main loop (don't open a BOS connection, etc) */
1923 return 1;
1924}
1925
1926/*
1927 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1928 */
1929int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1930{
1931 va_list ap;
1932 unsigned short type;
1933 char *sn = NULL;
1934
1935 va_start(ap, command);
1936 type = va_arg(ap, int);
1937 sn = va_arg(ap, char *);
1938 va_end(ap);
1939
1940 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1941
1942 return 1;
1943}
1944
1945int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1946{
1947 va_list ap;
1948 struct aim_conn_t *oftconn;
1949 struct aim_fileheader_t *fh;
1950 char *cookie;
1951
1952 va_start(ap, command);
1953 oftconn = va_arg(ap, struct aim_conn_t *);
1954 fh = va_arg(ap, struct aim_fileheader_t *);
1955 cookie = va_arg(ap, char *);
1956 va_end(ap);
1957
1958 dvprintf("faimtest: request for file %s.\n", fh->name);
1959
1960 return 1;
1961}
1962
1963
1964int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1965{
1966 va_list ap;
1967 struct aim_conn_t *oftconn;
1968 struct aim_fileheader_t *fh;
1969 char *path, *cookie;
1970 int pos, bufpos = 0, bufsize = 2048, i;
1971 char *buf;
1972
1973 FILE *file;
1974
1975 va_start(ap, command);
1976 oftconn = va_arg(ap, struct aim_conn_t *);
1977 fh = va_arg(ap, struct aim_fileheader_t *);
1978 cookie = va_arg(ap, char *);
1979 va_end(ap);
1980
1981 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
1982
1983 if(!(buf = malloc(2048)))
1984 return -1;
1985
1986 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
1987 dperror("calloc");
1988 dprintf("faimtest: error in calloc of path\n");
1989 return 0; /* XXX: no idea what winaim expects here =) */
1990 }
1991
1992 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
1993
1994
1995 if( (file = fopen(path, "r")) == NULL) {
1996 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
1997 return 0;
1998 }
1999
2000 /*
2001 * This is a mess. Remember that faimtest is demonstration code
2002 * only and for the sake of the gods, don't use this code in any
2003 * of your clients. --mid
2004 */
2005 for(pos = 0; pos < fh->size; pos++) {
2006 bufpos = pos % bufsize;
2007
2008 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2009 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2010 dperror("faim: getfile_send: write1");
2011 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2012 free(buf);
2013 return -1;
2014 }
2015 }
2016 if( (buf[bufpos] = fgetc(file)) == EOF) {
2017 if(pos != fh->size) {
2018 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2019 free(buf);
2020 return -1;
2021 }
2022 }
2023 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
2024 }
2025
2026 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2027 dperror("faim: getfile_send: write2");
2028 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2029 free(buf);
2030 return -1;
2031 }
2032
2033 free(buf);
2034 free(fh);
2035 return 1;
2036}
2037
2038int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2039{
2040 va_list ap;
2041 struct aim_conn_t *conn;
2042 struct aim_fileheader_t *fh;
2043
2044 va_start(ap, command);
2045 conn = va_arg(ap, struct aim_conn_t *);
2046 fh = va_arg(ap, struct aim_fileheader_t *);
2047 va_end(ap);
2048
2049 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
2050
2051 aim_conn_close(conn);
2052 aim_conn_kill(sess, &conn);
2053 return 1;
2054}
2055
2056int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2057{
2058 va_list ap;
2059 struct aim_conn_t *conn;
2060 char *sn;
2061
2062 va_start(ap, command);
2063 conn = va_arg(ap, struct aim_conn_t *);
2064 sn = va_arg(ap, char *);
2065 va_end(ap);
2066
2067 aim_conn_kill(sess, &conn);
2068
2069 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
2070 return 1;
2071}
2072int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2073{
2074 va_list ap;
2075 struct aim_conn_t *conn, *listenerconn;
2076 struct aim_filetransfer_priv *priv;
2077
2078 va_start(ap, command);
2079 conn = va_arg(ap, struct aim_conn_t *);
2080 listenerconn = va_arg(ap, struct aim_conn_t *);
2081 va_end(ap);
2082
2083 aim_conn_close(listenerconn);
2084 aim_conn_kill(sess, &listenerconn);
2085
2086 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
2087 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
2088 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
2089 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
2090 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
2091 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
2092 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
2093 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
2094
2095 priv = (struct aim_filetransfer_priv *)conn->priv;
2096
2097 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
2098 return 1;
2099}
2100
2101int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2102{
2103 va_list ap;
2104 struct aim_conn_t *conn;
2105 char *listing;
2106 struct aim_filetransfer_priv *ft;
2107 char *filename, *nameend, *sizec;
2108 int filesize, namelen;
2109
2110 va_start(ap, command);
2111 conn = va_arg(ap, struct aim_conn_t *);
2112 ft = va_arg(ap, struct aim_filetransfer_priv *);
2113 listing = va_arg(ap, char *);
2114 va_end(ap);
2115
2116 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2117
2118 nameend = strstr(listing+0x1a, "\r");
2119
2120 namelen = nameend - (listing + 0x1a);
2121
2122 filename = malloc(namelen + 1);
2123 strncpy(filename, listing+0x1a, namelen);
2124 filename[namelen] = 0x00;
2125
2126 sizec = malloc(8+1);
2127 memcpy(sizec, listing + 0x11, 8);
2128 sizec[8] = 0x00;
2129
2130 filesize = strtol(sizec, (char **)NULL, 10);
2131
2132 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2133
2134 aim_oft_getfile_request(sess, conn, filename, filesize);
2135
2136 free(filename);
2137 free(sizec);
2138
2139 return 0;
2140}
2141
2142int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2143{
2144 va_list ap;
2145 struct aim_conn_t *oftconn;
2146 struct aim_fileheader_t *fh;
2147 int pos, bufpos = 0, bufsize = 2048, i;
2148 char *buf;
2149
2150 va_start(ap, command);
2151 oftconn = va_arg(ap, struct aim_conn_t *);
2152 fh = va_arg(ap, struct aim_fileheader_t *);
2153 va_end(ap);
2154
2155 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2156
2157 if(!(buf = malloc(2048)))
2158 return -1;
2159
2160 for(pos = 0; pos < fh->size; pos++) {
2161 bufpos = pos % bufsize;
2162
2163 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2164 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2165 dperror("faim: getfile_send: write1");
2166 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2167 free(buf);
2168 return -1;
2169 }
2170 }
2171 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2172 if(pos != fh->size) {
2173 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2174 free(buf);
2175 return -1;
2176 }
2177 }
2178 }
2179
2180 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2181 dperror("faim: getfile_send: write2");
2182 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2183 free(buf);
2184 return -1;
2185 }
2186
2187 dprintf("faimtest: sent listing\n");
2188 free(buf);
2189 return 0;
2190}
2191
2192int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2193{
2194 va_list ap;
2195 struct aim_conn_t *conn;
2196 struct aim_filetransfer_priv *ft;
2197 unsigned char data;
2198 int pos;
2199
2200 va_start(ap, command);
2201 conn = va_arg(ap, struct aim_conn_t *);
2202 ft = va_arg(ap, struct aim_filetransfer_priv *);
2203 va_end(ap);
2204
2205 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2206
2207 for(pos = 0; pos < ft->fh.size; pos++) {
2208 read(conn->fd, &data, 1);
2209 printf("%c(%02x) ", data, data);
2210 }
2211
2212 printf("\n");
2213
2214 aim_oft_getfile_end(sess, conn);
2215
2216 return 0;
2217}
2218
2219int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2220{
2221 va_list ap;
2222 struct aim_conn_t *conn;
2223
2224 va_start(ap, command);
2225 conn = va_arg(ap, struct aim_conn_t *);
2226 va_end(ap);
2227
2228 aim_conn_close(conn);
2229 aim_conn_kill(sess, &conn);
2230 return 0;
2231}
2232
2233
2234int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2235{
2236 static char *codes[5] = {"invalid",
2237 "change",
2238 "warning",
2239 "limit",
2240 "limit cleared"};
2241 va_list ap;
2242 int code;
2243 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
2244 unsigned long currentavg, maxavg;
2245
2246 va_start(ap, command);
2247
2248 /* See code explanations below */
2249 code = va_arg(ap, int);
2250
2251 /*
2252 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
2253 */
2254 rateclass = va_arg(ap, unsigned long);
2255
2256 /*
2257 * Not sure what this is exactly. I think its the temporal
2258 * relation factor (ie, how to make the rest of the numbers
2259 * make sense in the real world).
2260 */
2261 windowsize = va_arg(ap, unsigned long);
2262
2263 /* Explained below */
2264 clear = va_arg(ap, unsigned long);
2265 alert = va_arg(ap, unsigned long);
2266 limit = va_arg(ap, unsigned long);
2267 disconnect = va_arg(ap, unsigned long);
2268 currentavg = va_arg(ap, unsigned long);
2269 maxavg = va_arg(ap, unsigned long);
2270
2271 va_end(ap);
2272
2273
2274 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",
2275 (code < 5)?codes[code]:"invalid",
2276 rateclass,
2277 currentavg, maxavg,
2278 alert, clear,
2279 limit, disconnect,
2280 windowsize);
2281
2282 if (code == AIM_RATE_CODE_CHANGE) {
2283 /*
2284 * Not real sure when these get sent.
2285 */
2286 if (currentavg >= clear)
2287 aim_conn_setlatency(command->conn, 0);
2288
2289 } else if (code == AIM_RATE_CODE_WARNING) {
2290 /*
2291 * We start getting WARNINGs the first time we go below the 'alert'
2292 * limit (currentavg < alert) and they stop when either we pause
2293 * long enough for currentavg to go above 'clear', or until we
2294 * flood it bad enough to go below 'limit' (and start getting
2295 * LIMITs instead) or even further and go below 'disconnect' and
2296 * get disconnected completely (and won't be able to login right
2297 * away either).
2298 */
2299 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2300
2301 } else if (code == AIM_RATE_CODE_LIMIT) {
2302 /*
2303 * When we hit LIMIT, messages will start getting dropped.
2304 */
2305 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2306
2307 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2308 /*
2309 * The limit is cleared when curavg goes above 'clear'.
2310 */
2311 aim_conn_setlatency(command->conn, 0);
2312 }
2313
2314 return 1;
2315}
2316
2317int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2318{
2319 va_list ap;
2320 int newevil;
2321 struct aim_userinfo_s *userinfo;
2322
2323 va_start(ap, command);
2324 newevil = va_arg(ap, int);
2325 userinfo = va_arg(ap, struct aim_userinfo_s *);
2326 va_end(ap);
2327
2328 /*
2329 * Evil Notifications that are lacking userinfo->sn are anon-warns
2330 * if they are an evil increases, but are not warnings at all if its
2331 * a decrease (its the natural backoff happening).
2332 *
2333 * newevil is passed as an int representing the new evil value times
2334 * ten.
2335 */
2336 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2337
2338 return 1;
2339}
2340
2341int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2342{
2343 va_list ap;
2344 char *address, *SNs;
2345 int i, num;
2346
2347 va_start(ap, command);
2348 address = va_arg(ap, char *);
2349 num = va_arg(ap, int);
2350 SNs = va_arg(ap, char *);
2351 va_end(ap);
2352
2353 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2354
2355 for(i = 0; i < num; i++)
2356 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2357 dinlineprintf("\n");
2358
2359 return 1;
2360}
2361
2362int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2363{
2364 va_list ap;
2365 char *address;
2366
2367 va_start(ap, command);
2368 address = va_arg(ap, char *);
2369 va_end(ap);
2370
2371 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
2372
2373 return 1;
2374}
This page took 0.063091 seconds and 5 git commands to generate.