]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Mon Sep 3 18:48:26 PDT 2001
[libfaim.git] / utils / faimtest / faimtest.c
CommitLineData
9de3ca7e 1/*
d410cf58 2 * faimtest.
9de3ca7e 3 *
d410cf58 4 * The point of faimtest is twofold:
5 * - Test the functionality of libfaim.
6 * - Demonstrate the functionality of libfaim and how to use it.
9de3ca7e 7 *
d410cf58 8 * It does the latter rather badly, and the first as best it can without a
9 * more realistic UI. libfaim has a slightly different event model than
10 * many C programmers are used to, which is why I provide faimtest as
11 * documentation instead of attempting to explain how it works in English.
12 * If you're still in need of more guidance, see the source for the OSCAR
13 * "plugin" in gaim. It does it nicely, and in a realistic situation. (Did
14 * I mention faimtest is a bit idealized?)
9de3ca7e 15 *
d410cf58 16 * The faimtest code is very ugly. Probably always will be.
9de3ca7e 17 *
d410cf58 18 * Note that faimtest does not do a lot of error checking, except perhaps
19 * on some libfaim funtions. This is done for clarity, in hopes of
20 * making this crap ever so slighly more readable.
9de3ca7e 21 *
22 */
23
b562f484 24#include "faimtest.h"
83ae98f8 25#include <sys/stat.h>
397055b1 26
d410cf58 27char *dprintf_ctime(void)
37ee990e 28{
d410cf58 29 static char retbuf[64];
30 struct tm *lt;
31 struct timeval tv;
32 struct timezone tz;
37ee990e 33
d410cf58 34 gettimeofday(&tv, &tz);
35 lt = localtime((time_t *)&tv.tv_sec);
36 strftime(retbuf, 64, "%a %b %e %H:%M:%S %Z %Y", lt);
37
38 return retbuf;
37ee990e 39}
96f8b1ed 40
41static char *msgerrreasons[] = {
d410cf58 42 "Invalid error",
43 "Invalid SNAC",
44 "Rate to host",
45 "Rate to client",
46 "Not logged on",
47 "Service unavailable",
48 "Service not defined",
49 "Obsolete SNAC",
50 "Not supported by host",
51 "Not supported by client",
52 "Refused by client",
53 "Reply too big",
54 "Responses lost",
55 "Request denied",
56 "Busted SNAC payload",
57 "Insufficient rights",
58 "In local permit/deny",
59 "Too evil (sender)",
60 "Too evil (receiver)",
61 "User temporarily unavailable",
62 "No match",
63 "List overflow",
64 "Request ambiguous",
65 "Queue full",
66 "Not while on AOL",
67};
96f8b1ed 68static int msgerrreasonslen = 25;
7392c79f 69
d410cf58 70aim_session_t aimsess;
b562f484 71int keepgoing = 1;
72
d410cf58 73/*
74 * This is used to intercept debugging/diagnostic messages from libfaim.
75 *
76 * Note that you should have one of these even if you use a debuglevel of
77 * zero, as libfaim will send serious errors to stderr by default.
78 *
79 */
80static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
646c6b52 81{
82
355229fe 83 vfprintf(stderr, format, va);
646c6b52 84
355229fe 85 return;
646c6b52 86}
37ee990e 87
d410cf58 88int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
22517493 89{
90
d410cf58 91 /* XXX fix libfaim to support this */
92 dvprintf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
22517493 93
94#if 0
355229fe 95 /*
96 * This is an alternate location for starting the login process.
97 */
98 /* XXX should do more checking to make sure its really the right AUTH conn */
d410cf58 99 if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
355229fe 100 /* do NOT send a flapversion, request_login will send it if needed */
d410cf58 101 aim_request_login(sess, fr->conn, priv->screenname);
355229fe 102 dprintf("faimtest: login request sent\n");
103 }
22517493 104#endif
105
355229fe 106 return 1;
22517493 107}
108
109/*
110 * This is a frivilous callback. You don't need it. I only used it for
111 * debugging non-blocking connects.
112 *
113 * If packets are sent to a conn before its fully connected, they
114 * will be queued and then transmitted when the connection completes.
115 *
116 */
d410cf58 117int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
22517493 118{
355229fe 119 va_list ap;
d410cf58 120 aim_conn_t *conn;
22517493 121
d410cf58 122 va_start(ap, fr);
123 conn = va_arg(ap, aim_conn_t *);
355229fe 124 va_end(ap);
22517493 125
355229fe 126 if (conn)
127 dvprintf("faimtest: connection on %d completed\n", conn->fd);
128
129 return 1;
22517493 130}
131
999b6d5f 132#ifdef _WIN32
133/*
134 * This is really all thats needed to link against libfaim on win32.
135 *
136 * Note that this particular version of faimtest has never been tested
d410cf58 137 * on win32, but I'm fairly sure it should work.
999b6d5f 138 */
d410cf58 139static int initwsa(void)
999b6d5f 140{
355229fe 141 WORD wVersionRequested;
142 WSADATA wsaData;
999b6d5f 143
355229fe 144 wVersionRequested = MAKEWORD(2,2);
145 return WSAStartup(wVersionRequested, &wsaData);
999b6d5f 146}
147#endif /* _WIN32 */
148
d410cf58 149/*
150 * This is unrealistic. Most clients will not be able to do this.
151 */
b562f484 152int faimtest_init(void)
153{
d410cf58 154 aim_conn_t *stdinconn = NULL;
b562f484 155
355229fe 156 if (!(stdinconn = aim_newconn(&aimsess, 0, NULL))) {
157 dprintf("unable to create connection for stdin!\n");
158 return -1;
159 }
b562f484 160
355229fe 161 stdinconn->fd = STDIN_FILENO;
b562f484 162
355229fe 163 return 0;
b562f484 164}
165
37ee990e 166int main(int argc, char **argv)
9de3ca7e 167{
d410cf58 168 aim_conn_t *waitingconn = NULL;
355229fe 169 int i;
170 int selstat = 0;
171 static int faimtest_mode = 0;
172 struct timeval tv;
173 time_t lastnop = 0;
174 const char *buddyiconpath = NULL;
d410cf58 175 struct faimtest_priv priv = {
176 NULL, NULL, NULL, NULL,
177 NULL, NULL, NULL, NULL,
178 0,
179 NULL, NULL,
180 NULL, 0, 0, 0
181 };
355229fe 182
d410cf58 183 priv.screenname = getenv("SCREENNAME");
184 priv.password = getenv("PASSWORD");
185 priv.server = getenv("AUTHSERVER");
186 priv.proxy = getenv("SOCKSPROXY");
187 priv.proxyusername = getenv("SOCKSNAME");
188 priv.proxypass = getenv("SOCKSPASS");
355229fe 189
d410cf58 190 priv.listingpath = getenv("LISTINGPATH");
355229fe 191
192 while ((i = getopt(argc, argv, "u:p:a:U:P:A:l:c:hoOb:i:")) != EOF) {
193 switch (i) {
d410cf58 194 case 'u': priv.screenname = optarg; break;
195 case 'p': priv.password = optarg; break;
196 case 'a': priv.server = optarg; break;
197 case 'U': priv.proxyusername = optarg; break;
198 case 'P': priv.proxypass = optarg; break;
199 case 'A': priv.proxy = optarg; break;
200 case 'l': priv.listingpath = optarg; break;
201 case 'c': priv.ohcaptainmycaptain = optarg; break;
355229fe 202 case 'o': faimtest_mode = 1; break; /* half old interface */
203 case 'O': faimtest_mode = 2; break; /* full old interface */
d410cf58 204 case 'b': priv.aimbinarypath = optarg; break;
355229fe 205 case 'i': buddyiconpath = optarg; break;
206 case 'h':
207 default:
208 printf("faimtest\n");
209 printf(" Options: \n");
210 printf(" -u name Screen name ($SCREENNAME)\n");
211 printf(" -p passwd Password ($PASSWORD)\n");
212 printf(" -a host:port Authorizer ($AUTHSERVER)\n");
213 printf(" -U name Proxy user name ($SOCKSPROXY)\n");
214 printf(" -P passwd Proxy password ($SOCKSNAME)\n");
215 printf(" -A host:port Proxy host ($SOCKSPASS)\n");
216 printf(" -l path Path to listing file ($LISTINGPATH)\n");
217 printf(" -c name Screen name of owner\n");
218 printf(" -o Login at startup, then prompt\n");
219 printf(" -O Login, never give prompt\n");
220 printf(" -b path Path to AIM 3.5.1670 binaries\n");
221 printf(" -i file Buddy Icon to send\n");
222 exit(0);
223 }
224 }
37ee990e 225
999b6d5f 226#ifdef _WIN32
355229fe 227 if (initwsa() != 0) {
228 dprintf("faimtest: could not initialize windows sockets\n");
229 return -1;
230 }
999b6d5f 231#endif /* _WIN32 */
232
355229fe 233 /* Pass zero as flags if you want blocking connects */
234 aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 1);
235 aim_setdebuggingcb(&aimsess, faimtest_debugcb); /* still needed even if debuglevel = 0 ! */
d410cf58 236 aimsess.aux_data = &priv;
7b91722d 237
d410cf58 238 if (priv.listingpath) {
355229fe 239 char *listingname;
240
d410cf58 241 listingname = (char *)calloc(1, strlen(priv.listingpath)+strlen("/listing.txt"));
242 sprintf(listingname, "%s/listing.txt", priv.listingpath);
355229fe 243
d410cf58 244 if ((priv.listingfile = fopen(listingname, "r")) == NULL)
355229fe 245 dvprintf("Couldn't open %s... disabling that shit.\n", listingname);
7b91722d 246
355229fe 247 free(listingname);
248 }
50038c74 249
355229fe 250 if (buddyiconpath) {
251 struct stat st;
252 FILE *f;
7b91722d 253
355229fe 254 if ((stat(buddyiconpath, &st) != -1) && (st.st_size <= MAXICONLEN) && (f = fopen(buddyiconpath, "r"))) {
7b91722d 255
d410cf58 256 priv.buddyiconlen = st.st_size;
257 priv.buddyiconstamp = st.st_mtime;
258 priv.buddyicon = malloc(priv.buddyiconlen);
259 fread(priv.buddyicon, 1, st.st_size, f);
7b91722d 260
d410cf58 261 priv.buddyiconsum = aim_iconsum(priv.buddyicon, priv.buddyiconlen);
7b91722d 262
d410cf58 263 dvprintf("read %d bytes of %s for buddy icon (sum 0x%08x)\n", priv.buddyiconlen, buddyiconpath, priv.buddyiconsum);
bb0dc593 264
355229fe 265 fclose(f);
9bf14d44 266
355229fe 267 } else
268 dvprintf("could not open buddy icon %s\n", buddyiconpath);
9de3ca7e 269
355229fe 270 }
d32954e7 271
355229fe 272 faimtest_init();
d32954e7 273
355229fe 274 if (faimtest_mode < 2)
275 cmd_init();
d32954e7 276
355229fe 277 if (faimtest_mode >= 1) {
d410cf58 278 if (login(&aimsess, priv.screenname, priv.password) == -1) {
355229fe 279 if (faimtest_mode < 2)
280 cmd_uninit();
281 exit(-1);
282 }
283 }
b8d0da45 284
355229fe 285 while (keepgoing) {
286
d410cf58 287 /* XXX uh. */
355229fe 288 tv.tv_sec = 5;
289 tv.tv_usec = 0;
290
291 waitingconn = aim_select(&aimsess, &tv, &selstat);
292
d410cf58 293 if (priv.connected && ((time(NULL) - lastnop) > 30)) {
355229fe 294 lastnop = time(NULL);
295 aim_flap_nop(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS));
296 }
297
298 if (selstat == -1) { /* error */
299 keepgoing = 0; /* fall through */
300 } else if (selstat == 0) { /* no events pending */
301 ;
302 } else if (selstat == 1) { /* outgoing data pending */
303 aim_tx_flushqueue(&aimsess);
304 } else if (selstat == 2) { /* incoming data pending */
305 if ((faimtest_mode < 2) && (waitingconn->fd == STDIN_FILENO)) {
306 cmd_gotkey();
307 } else {
308 if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
d410cf58 309#if 0
355229fe 310 if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
311 dprintf("connection error (rend out)\n");
312 aim_conn_kill(&aimsess, &waitingconn);
313 }
d410cf58 314#endif
355229fe 315 } else {
316 if (aim_get_command(&aimsess, waitingconn) >= 0) {
317 aim_rxdispatch(&aimsess);
318 } else {
319 dvprintf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
320 /* we should have callbacks for all these, else the library will do the conn_kill for us. */
321 if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
322 dprintf("connection error: rendezvous connection. you forgot register a disconnect callback, right?\n");
323 aim_conn_kill(&aimsess, &waitingconn);
324 } else
325 aim_conn_kill(&aimsess, &waitingconn);
326 if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
327 dprintf("major connection error\n");
328 if (faimtest_mode == 2)
329 break;
330 }
331 }
332 }
333 }
334 }
7392c79f 335 }
9de3ca7e 336
355229fe 337 /* close up all connections, dead or no */
338 aim_session_kill(&aimsess);
9de3ca7e 339
355229fe 340 if (faimtest_mode < 2) {
341 printf("\n");
342 cmd_uninit();
343 }
b562f484 344
d410cf58 345 free(priv.buddyicon);
7b91722d 346
355229fe 347 /* Get out */
348 exit(0);
9de3ca7e 349}
350
d410cf58 351int faimtest_serverready(aim_session_t *sess, aim_frame_t *fr, ...)
c78446b5 352{
d410cf58 353 int famcount, i;
354 fu16_t *families;
355 va_list ap;
c78446b5 356
d410cf58 357 va_start(ap, fr);
358 famcount = va_arg(ap, int);
359 families = va_arg(ap, fu16_t *);
360 va_end(ap);
361
362 dvprintf("faimtest: SNAC families supported by this host (type %d): ", fr->conn->type);
363 for (i = 0; i < famcount; i++)
364 dvinlineprintf("0x%04x ", families[i]);
365 dinlineprintf("\n");
c78446b5 366
d410cf58 367 if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
c78446b5 368
d410cf58 369 aim_auth_setversions(sess, fr->conn);
370 aim_bos_reqrate(sess, fr->conn); /* request rate info */
c78446b5 371
d410cf58 372 dprintf("done with auth server ready\n");
355229fe 373
d410cf58 374 } else if (fr->conn->type == AIM_CONN_TYPE_BOS) {
355229fe 375
d410cf58 376 aim_setversions(sess, fr->conn);
377 aim_bos_reqrate(sess, fr->conn); /* request rate info */
355229fe 378
d410cf58 379 dprintf("done with BOS server ready\n");
355229fe 380 }
d410cf58 381
382 return 1;
383}
384
385int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
386{
387 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
388 va_list ap;
389 fu16_t code;
390 char *msg;
391
392 va_start(ap, fr);
393 code = va_arg(ap, int);
394 msg = va_arg(ap, char *);
395 va_end(ap);
396
397 dvprintf("connerr: Code 0x%04x: %s\n", code, msg);
398 aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
399
400 priv->connected = 0;
401
402 return 1;
403}
404
405#if 0
406static int faimtest_rateresp_auth(aim_session_t *sess, aim_frame_t *fr, ...)
407{
408
409 aim_bos_ackrateresp(sess, fr->conn);
410 aim_auth_clientready(sess, fr->conn);
411
412 dprintf("faimtest: connected to authorization/admin service\n");
413
414 return 1;
415}
416
417int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
418{
419 int status;
420 va_list ap;
421
422 va_start(ap, fr);
423 status = va_arg(ap, int); /* status code of confirmation request */
424 va_end(ap);
425
426 dvprintf("account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
427
428 return 1;
429}
430
431
432#endif
433
434#if 0
435/*
436 * This kind of function is really not legal in the new bstream way...
437 * In fact, clients should never access the aim_frame_t directly in handlers,
438 * since that may leave it in a bizare state for the lower layers. In fact,
439 * clients should probably not even get passed a pointer like this.
440 *
441 */
442int faimtest_parse_unknown(aim_session_t *sess, aim_frame_t *fr, ...)
443{
444 int i;
445
446 aim_bstream_rewind(&fr->data); /* boo! */
447
448 dprintf("\nReceived unknown packet:");
449 for (i = 0; aim_bstream_empty(&fr->data); i++) {
450 if ((i % 8) == 0)
451 dinlineprintf("\n\t");
452 dvinlineprintf("0x%2x ", aimbs_get8(&fr->data));
355229fe 453 }
d410cf58 454 dinlineprintf("\n\n");
355229fe 455
456 return 1;
c78446b5 457}
d410cf58 458#endif
c78446b5 459
d410cf58 460int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
461{
462 va_list ap;
463 int serviceid;
464 char *ip;
465 fu8_t *cookie;
466
467 va_start(ap, fr);
468 serviceid = va_arg(ap, int);
469 ip = va_arg(ap, char *);
470 cookie = va_arg(ap, fu8_t *);
471
472 if (serviceid == 0x0005) { /* Adverts */
473#if 0
474 aim_conn_t *tstconn;
475
476 tstconn = aim_newconn(sess, AIM_CONN_TYPE_ADS, ip);
477 if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
478 dprintf("faimtest: unable to reconnect with authorizer\n");
479 } else {
480 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
481 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
482 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
483 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
484 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
485 aim_auth_sendcookie(sess, tstconn, cookie);
486 dprintf("sent cookie to adverts host\n");
487 }
488#endif
489 } else if (serviceid == 0x0007) { /* Authorizer */
490#if 0
491 aim_conn_t *tstconn;
492
493 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
494 if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
495 dprintf("faimtest: unable to reconnect with authorizer\n");
496 } else {
497 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
498 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
499 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
500 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
501 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
502 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
503 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
504 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
505 /* Send the cookie to the Auth */
506 aim_auth_sendcookie(sess, tstconn, cookie);
507 dprintf("sent cookie to authorizer host\n");
508 }
509#endif
510 } else if (serviceid == 0x000d) { /* ChatNav */
511
512 chatnav_redirect(sess, ip, cookie);
513
514 } else if (serviceid == 0x000e) { /* Chat */
515 char *roomname = NULL;
516 int exchange;
517
518 roomname = va_arg(ap, char *);
519 exchange = va_arg(ap, int);
520
521 chat_redirect(sess, ip, cookie, roomname, exchange);
522
523 } else {
524 dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
525 }
526
527 va_end(ap);
528
529 return 1;
530}
531
532static int faimtest_rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...)
533{
534 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
535 char buddies[128]; /* this is the new buddy list */
536 char profile[256]; /* this is the new profile */
537 char awaymsg[] = {"blah blah blah Ole! blah blah blah"};
538
539 /* Caution: Buddy1 and Buddy2 are real people! (who I don't know) */
540 snprintf(buddies, sizeof(buddies), "Buddy1&Buddy2&%s&", priv->ohcaptainmycaptain ? priv->ohcaptainmycaptain : "blah");
541 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.", priv->ohcaptainmycaptain);
542
543 aim_bos_ackrateresp(sess, fr->conn); /* ack rate info response */
544 aim_bos_reqpersonalinfo(sess, fr->conn);
545 aim_bos_reqlocaterights(sess, fr->conn);
546 aim_bos_setprofile(sess, fr->conn, profile, awaymsg, AIM_CAPS_BUDDYICON | AIM_CAPS_CHAT | AIM_CAPS_GETFILE | AIM_CAPS_SENDFILE | AIM_CAPS_IMIMAGE /*| AIM_CAPS_GAMES | AIM_CAPS_SAVESTOCKS*/);
547 aim_bos_reqbuddyrights(sess, fr->conn);
548
549 /* send the buddy list and profile (required, even if empty) */
550 aim_bos_setbuddylist(sess, fr->conn, buddies);
551
552 aim_reqicbmparams(sess, fr->conn);
553
554 aim_bos_reqrights(sess, fr->conn);
555 /* set group permissions -- all user classes */
556 aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
557 aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE);
558
559 return 1;
560}
561
562static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
00ef5271 563{
355229fe 564 struct aim_icbmparameters *params;
565 va_list ap;
00ef5271 566
d410cf58 567 va_start(ap, fr);
355229fe 568 params = va_arg(ap, struct aim_icbmparameters *);
569 va_end(ap);
00ef5271 570
355229fe 571 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", params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval);
00ef5271 572
36a61e0d 573 /*
574 * Set these to your taste, or client medium. Setting minmsginterval
575 * higher is good for keeping yourself from getting flooded (esp
576 * if you're on a slow connection or something where that would be
577 * useful).
578 */
355229fe 579 params->maxmsglen = 8000;
36a61e0d 580 params->minmsginterval = 0; /* in milliseconds */
355229fe 581
d410cf58 582 aim_seticbmparam(sess, fr->conn, params);
355229fe 583
584 return 1;
00ef5271 585}
586
d410cf58 587static int faimtest_hostversions(aim_session_t *sess, aim_frame_t *fr, ...)
ee49b735 588{
355229fe 589 int vercount, i;
d410cf58 590 fu8_t *versions;
355229fe 591 va_list ap;
592
d410cf58 593 va_start(ap, fr);
355229fe 594 vercount = va_arg(ap, int); /* number of family/version pairs */
d410cf58 595 versions = va_arg(ap, fu8_t *);
355229fe 596 va_end(ap);
597
598 dprintf("faimtest: SNAC versions supported by this host: ");
599 for (i = 0; i < vercount*4; i += 4) {
600 dvinlineprintf("0x%04x:0x%04x ",
601 aimutil_get16(versions+i), /* SNAC family */
602 aimutil_get16(versions+i+2) /* Version number */);
603 }
604 dinlineprintf("\n");
ee49b735 605
355229fe 606 return 1;
ee49b735 607}
608
d410cf58 609static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
64c78745 610{
355229fe 611 va_list ap;
d410cf58 612 fu16_t maxbuddies, maxwatchers;
64c78745 613
d410cf58 614 va_start(ap, fr);
615 maxbuddies = va_arg(ap, int);
616 maxwatchers = va_arg(ap, int);
355229fe 617 va_end(ap);
64c78745 618
d410cf58 619 dvprintf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
64c78745 620
355229fe 621 return 1;
64c78745 622}
623
d410cf58 624static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 625{
d410cf58 626 va_list ap;
627 fu16_t maxpermits, maxdenies;
9de3ca7e 628
d410cf58 629 va_start(ap, fr);
630 maxpermits = va_arg(ap, int);
631 maxdenies = va_arg(ap, int);
632 va_end(ap);
633
634 dvprintf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
96f8b1ed 635
d410cf58 636 aim_bos_clientready(sess, fr->conn);
96f8b1ed 637
d410cf58 638 dprintf("officially connected to BOS.\n");
96f8b1ed 639
d410cf58 640 return 1;
96f8b1ed 641}
642
d410cf58 643static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
c78446b5 644{
d410cf58 645 va_list ap;
646 fu16_t maxsiglen;
96f8b1ed 647
d410cf58 648 va_start(ap, fr);
649 maxsiglen = va_arg(ap, int);
650 va_end(ap);
c78446b5 651
d410cf58 652 dvprintf("locate rights: max signature length = %d\n", maxsiglen);
37ee990e 653
d410cf58 654 return 1;
37ee990e 655}
656
d410cf58 657static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
b39e0a91 658{
d410cf58 659 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
660 va_list ap;
661 fu16_t interval;
b39e0a91 662
d410cf58 663 va_start(ap, fr);
664 interval = va_arg(ap, int);
665 va_end(ap);
b39e0a91 666
d410cf58 667 dvprintf("minimum report interval: %d (seconds?)\n", interval);
b39e0a91 668
d410cf58 669 if (!priv->connected)
670 priv->connected++;
b39e0a91 671
d410cf58 672#if 0
673 aim_bos_reqservice(sess, fr->conn, 0x0005); /* adverts */
674 aim_bos_reqservice(sess, fr->conn, 0x000f); /* user directory */
37ee990e 675
d410cf58 676 /* Don't know what this does... */
677 /* XXX sess->sn should be normalized by the 0001/000f handler */
678 aim_0002_000b(sess, fr->conn, sess->sn);
679#endif
37ee990e 680
d410cf58 681 aim_reqicbmparams(sess, fr->conn);
c78446b5 682
d410cf58 683 return 1;
c78446b5 684}
685
d410cf58 686static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 687{
d410cf58 688 static char *codes[] = {
689 "Unknown",
690 "Mandatory upgrade",
691 "Advisory upgrade",
692 "System bulletin",
693 "Top o' the world!"
694 };
695 static int codeslen = 5;
696 char *msg;
697 fu16_t id;
698 va_list ap;
699
700 va_start(ap, fr);
701 id = va_arg(ap, int);
702 msg = va_arg(ap, char *);
703 va_end(ap);
704
705 dvprintf("motd: %s (%d / %s)\n", msg, id, (id < codeslen)?codes[id]:"unknown");
706
707 return 1;
9de3ca7e 708}
709
83ae98f8 710/*
711 * This is a little more complicated than it looks. The module
712 * name (proto, boscore, etc) may or may not be given. If it is
713 * not given, then use aim.exe. If it is given, put ".ocm" on the
714 * end of it.
715 *
716 * Now, if the offset or length requested would cause a read past
717 * the end of the file, then the request is considered invalid. Invalid
718 * requests are processed specially. The value hashed is the
719 * the request, put into little-endian (eight bytes: offset followed
720 * by length).
721 *
722 * Additionally, if the request is valid, the length is mod 4096. It is
723 * important that the length is checked for validity first before doing
724 * the mod.
725 *
726 * Note to Bosco's Brigade: if you'd like to break this, put the
727 * module name on an invalid request.
728 *
729 */
d410cf58 730static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
b1eac25a 731{
d410cf58 732 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
733 FILE *f;
734 static const char defaultmod[] = "aim.exe";
735 char *filename = NULL;
736 struct stat st;
737 unsigned char *buf;
738 int invalid = 0;
739
740 if (!bufret || !buflenret)
741 return -1;
b1eac25a 742
d410cf58 743 if (modname) {
001c9b80 744
d410cf58 745 if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
746 dperror("memrequest: malloc");
747 return -1;
748 }
5ac961d5 749
d410cf58 750 sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
5ac961d5 751
d410cf58 752 } else {
328837f7 753
d410cf58 754 if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
755 dperror("memrequest: malloc");
756 return -1;
757 }
328837f7 758
d410cf58 759 sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
b1eac25a 760
d410cf58 761 }
83ae98f8 762
d410cf58 763 if (stat(filename, &st) == -1) {
764 if (!modname) {
765 dperror("memrequest: stat");
766 free(filename);
767 return -1;
768 }
769 invalid = 1;
770 }
83ae98f8 771
d410cf58 772 if (!invalid) {
773 if ((offset > st.st_size) || (len > st.st_size))
774 invalid = 1;
775 else if ((st.st_size - offset) < len)
776 len = st.st_size - offset;
777 else if ((st.st_size - len) < len)
778 len = st.st_size - len;
779 }
83ae98f8 780
d410cf58 781 if (!invalid && len)
782 len %= 4096;
83ae98f8 783
d410cf58 784 if (invalid) {
785 int i;
f6a4f6b7 786
d410cf58 787 free(filename); /* not needed */
f6a4f6b7 788
d410cf58 789 dvprintf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
83ae98f8 790
d410cf58 791 i = 8;
792 if (modname)
793 i += strlen(modname);
f6a4f6b7 794
d410cf58 795 if (!(buf = malloc(i)))
796 return -1;
83ae98f8 797
d410cf58 798 i = 0;
83ae98f8 799
d410cf58 800 if (modname) {
801 memcpy(buf, modname, strlen(modname));
802 i += strlen(modname);
803 }
83ae98f8 804
d410cf58 805 /* Damn endianness. This must be little (LSB first) endian. */
806 buf[i++] = offset & 0xff;
807 buf[i++] = (offset >> 8) & 0xff;
808 buf[i++] = (offset >> 16) & 0xff;
809 buf[i++] = (offset >> 24) & 0xff;
810 buf[i++] = len & 0xff;
811 buf[i++] = (len >> 8) & 0xff;
812 buf[i++] = (len >> 16) & 0xff;
813 buf[i++] = (len >> 24) & 0xff;
83ae98f8 814
d410cf58 815 *bufret = buf;
816 *buflenret = i;
83ae98f8 817
d410cf58 818 } else {
83ae98f8 819
d410cf58 820 if (!(buf = malloc(len))) {
821 free(filename);
822 return -1;
823 }
83ae98f8 824
d410cf58 825 dvprintf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename);
5ac961d5 826
d410cf58 827 if (!(f = fopen(filename, "r"))) {
828 dperror("memrequest: fopen");
829 free(filename);
830 free(buf);
831 return -1;
832 }
b1eac25a 833
d410cf58 834 free(filename);
b1eac25a 835
d410cf58 836 if (fseek(f, offset, SEEK_SET) == -1) {
837 dperror("memrequest: fseek");
838 fclose(f);
839 free(buf);
840 return -1;
841 }
83ae98f8 842
d410cf58 843 if (fread(buf, len, 1, f) != 1) {
844 dperror("memrequest: fread");
845 fclose(f);
846 free(buf);
847 return -1;
848 }
b1eac25a 849
d410cf58 850 fclose(f);
851
852 *bufret = buf;
853 *buflenret = len;
854
855 }
856
857 return 0; /* success! */
b1eac25a 858}
859
860/*
861 * This will get an offset and a length. The client should read this
862 * data out of whatever AIM.EXE binary the user has provided (hopefully
863 * it matches the client information thats sent at login) and pass a
864 * buffer back to libfaim so it can hash the data and send it to AOL for
865 * inspection by the client police.
866 */
d410cf58 867static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
b1eac25a 868{
d410cf58 869 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
870 va_list ap;
871 fu32_t offset, len;
872 char *modname;
873 unsigned char *buf;
874 int buflen;
875
876 va_start(ap, fr);
877 offset = va_arg(ap, fu32_t);
878 len = va_arg(ap, fu32_t);
879 modname = va_arg(ap, char *);
880 va_end(ap);
b1eac25a 881
d410cf58 882 if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
b1eac25a 883
d410cf58 884 aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 885
d410cf58 886 free(buf);
b1eac25a 887
d410cf58 888 } else {
b1eac25a 889
d410cf58 890 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
b1eac25a 891
d410cf58 892 aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 893
d410cf58 894 }
b1eac25a 895
d410cf58 896 return 1;
b1eac25a 897}
898
d410cf58 899static void printuserflags(fu16_t flags)
9de3ca7e 900{
d410cf58 901 if (flags & AIM_FLAG_UNCONFIRMED)
902 dinlineprintf("UNCONFIRMED ");
903 if (flags & AIM_FLAG_ADMINISTRATOR)
904 dinlineprintf("ADMINISTRATOR ");
905 if (flags & AIM_FLAG_AOL)
906 dinlineprintf("AOL ");
907 if (flags & AIM_FLAG_OSCAR_PAY)
908 dinlineprintf("OSCAR_PAY ");
909 if (flags & AIM_FLAG_FREE)
910 dinlineprintf("FREE ");
911 if (flags & AIM_FLAG_AWAY)
912 dinlineprintf("AWAY ");
913 if (flags & AIM_FLAG_UNKNOWN40)
914 dinlineprintf("ICQ? ");
915 if (flags & AIM_FLAG_UNKNOWN80)
916 dinlineprintf("UNKNOWN80 ");
917 return;
9de3ca7e 918}
919
d410cf58 920static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
a15d82b1 921{
d410cf58 922 struct aim_userinfo_s *userinfo;
923 char *prof_encoding = NULL;
924 char *prof = NULL;
925 fu16_t inforeq = 0;
a15d82b1 926
d410cf58 927 va_list ap;
928 va_start(ap, fr);
929 userinfo = va_arg(ap, struct aim_userinfo_s *);
930 prof_encoding = va_arg(ap, char *);
931 prof = va_arg(ap, char *);
932 inforeq = va_arg(ap, fu16_t);
933 va_end(ap);
934
935 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
936 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
937 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
938 printuserflags(userinfo->flags);
939 dinlineprintf("\n");
940
941 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
942 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
943 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
944
945 if (inforeq == AIM_GETINFO_GENERALINFO) {
946 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
947 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
948 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
949 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
950 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
951 } else
952 dprintf("faimtest: userinfo: unknown info request\n");
953
954 return 1;
9de3ca7e 955}
956
d410cf58 957static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, const char *tmpstr)
d2587300 958{
d410cf58 959 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
d2587300 960
d410cf58 961 if (!strncmp(tmpstr, "disconnect", 10)) {
d2587300 962
d410cf58 963 logout(sess);
d2587300 964
d410cf58 965 } else if (strstr(tmpstr, "goodday")) {
7b91722d 966
d410cf58 967 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
7b91722d 968
d410cf58 969 } else if (strstr(tmpstr, "haveicon") && priv->buddyicon) {
970 struct aim_sendimext_args args;
971 static const char iconmsg[] = {"I have an icon"};
7b91722d 972
d410cf58 973 args.destsn = userinfo->sn;
974 args.flags = AIM_IMFLAGS_HASICON;
975 args.msg = iconmsg;
976 args.msglen = strlen(iconmsg);
977 args.iconlen = priv->buddyiconlen;
978 args.iconstamp = priv->buddyiconstamp;
979 args.iconsum = priv->buddyiconsum;
7b91722d 980
d410cf58 981 aim_send_im_ext(sess, conn, &args);
7b91722d 982
d410cf58 983 } else if (strstr(tmpstr, "sendicon") && priv->buddyicon) {
d2587300 984
d410cf58 985 aim_send_icon(sess, conn, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum);
d2587300 986
d410cf58 987 } else if (strstr(tmpstr, "warnme")) {
d2587300 988
d410cf58 989 dprintf("faimtest: icbm: sending non-anon warning\n");
990 aim_send_warning(sess, conn, userinfo->sn, 0);
d2587300 991
d410cf58 992 } else if (strstr(tmpstr, "anonwarn")) {
d2587300 993
d410cf58 994 dprintf("faimtest: icbm: sending anon warning\n");
995 aim_send_warning(sess, conn, userinfo->sn, AIM_WARN_ANON);
d2587300 996
d410cf58 997 } else if (strstr(tmpstr, "setdirectoryinfo")) {
d2587300 998
d410cf58 999 dprintf("faimtest: icbm: sending backwards profile data\n");
1000 aim_setdirectoryinfo(sess, conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
d2587300 1001
d410cf58 1002 } else if (strstr(tmpstr, "setinterests")) {
d2587300 1003
d410cf58 1004 dprintf("faimtest: icbm: setting fun interests\n");
1005 aim_setuserinterests(sess, conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
d2587300 1006
d410cf58 1007 } else if (!strncmp(tmpstr, "getfile", 7)) {
d2587300 1008
d410cf58 1009 if (!priv->ohcaptainmycaptain) {
d2587300 1010
d410cf58 1011 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!");
d2587300 1012
d410cf58 1013 } else
1014 getfile_start(sess, conn, (strlen(tmpstr) < 8)?priv->ohcaptainmycaptain:tmpstr+8);
1015
1016 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
d2587300 1017
d410cf58 1018 aim_bos_reqservice(sess, conn, AIM_CONN_TYPE_CHATNAV);
d2587300 1019
d410cf58 1020 } else if (!strncmp(tmpstr, "create", 6)) {
d2587300 1021
d410cf58 1022 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
d2587300 1023
d410cf58 1024 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1025 aim_conn_t *chatnavconn;
d2587300 1026
d410cf58 1027 if ((chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)))
1028 aim_conn_kill(sess, &chatnavconn);
d2587300 1029
d410cf58 1030 } else if (!strncmp(tmpstr, "join", 4)) {
d2587300 1031
d410cf58 1032 aim_chat_join(sess, conn, 0x0004, "worlddomination", 0x0000);
d2587300 1033
d410cf58 1034 } else if (!strncmp(tmpstr, "leave", 5)) {
d2587300 1035
d410cf58 1036 aim_chat_leaveroom(sess, "worlddomination");
d2587300 1037
d410cf58 1038 } else if (!strncmp(tmpstr, "getinfo", 7)) {
d2587300 1039
d410cf58 1040 aim_getinfo(sess, conn, "75784102", AIM_GETINFO_GENERALINFO);
1041 aim_getinfo(sess, conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
1042 aim_getinfo(sess, conn, "midendian", AIM_GETINFO_GENERALINFO);
1043 aim_getinfo(sess, conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
d2587300 1044
d410cf58 1045 } else if (!strncmp(tmpstr, "open directim", 13)) {
d2587300 1046
d410cf58 1047 directim_start(sess, conn, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
d2587300 1048
d410cf58 1049 } else if(!(strncmp(tmpstr, "lookup", 6))) {
d2587300 1050
d410cf58 1051 aim_usersearch_address(sess, conn, tmpstr+7);
d2587300 1052
d410cf58 1053 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
d2587300 1054
d410cf58 1055 aim_send_im(sess, conn, priv->ohcaptainmycaptain, 0, "sendmsg 7900");
d2587300 1056
d410cf58 1057 } else if (!strncmp(tmpstr, "reqauth", 7)) {
d2587300 1058
d410cf58 1059 aim_bos_reqservice(sess, conn, AIM_CONN_TYPE_AUTH);
d2587300 1060
d410cf58 1061 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
d2587300 1062
d410cf58 1063 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
d2587300 1064
d410cf58 1065 } else if (!strncmp(tmpstr, "reqemail", 8)) {
d2587300 1066
d410cf58 1067 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
d2587300 1068
d410cf58 1069 } else if (!strncmp(tmpstr, "changepass", 8)) {
d2587300 1070
d410cf58 1071 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
d2587300 1072
d410cf58 1073 } else if (!strncmp(tmpstr, "setemail", 8)) {
d2587300 1074
d410cf58 1075 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
d2587300 1076
d410cf58 1077 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1078 int i;
d2587300 1079
d410cf58 1080 i = atoi(tmpstr+8);
1081 if (i < 10000) {
1082 char *newbuf;
1083 int z;
d2587300 1084
d410cf58 1085 newbuf = malloc(i+1);
1086 for (z = 0; z < i; z++)
1087 newbuf[z] = (z % 10)+0x30;
1088 newbuf[i] = '\0';
1089 aim_send_im(sess, conn, userinfo->sn, 0, newbuf);
1090 free(newbuf);
1091 }
d2587300 1092
d410cf58 1093 } else {
d2587300 1094
d410cf58 1095 dprintf("unknown command.\n");
1096 aim_add_buddy(sess, conn, userinfo->sn);
d2587300 1097
d410cf58 1098 }
d2587300 1099
d410cf58 1100 return 0;
d2587300 1101}
1102
9de3ca7e 1103/*
d410cf58 1104 * Channel 1: Standard Message
9de3ca7e 1105 */
d410cf58 1106static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, va_list ap)
9de3ca7e 1107{
d410cf58 1108 char *tmpstr;
1109 struct aim_incomingim_ch1_args *args;
1110 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
1111 char realmsg[8192+1] = {""};
7a449b5d 1112
d410cf58 1113 args = va_arg(ap, struct aim_incomingim_ch1_args *);
1114 va_end(ap);
7a449b5d 1115
d410cf58 1116 clienttype = aim_fingerprintclient(args->fingerprint, args->finlen);
9de3ca7e 1117
d410cf58 1118 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
1119 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
1120 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1121 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
1122 printuserflags(userinfo->flags);
1123 dinlineprintf("\n");
7392c79f 1124
d410cf58 1125 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1126 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1127 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1128 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
1129
1130 dprintf("faimtest: icbm: icbmflags = ");
1131 if (args->icbmflags & AIM_IMFLAGS_AWAY)
1132 dinlineprintf("away ");
1133 if (args->icbmflags & AIM_IMFLAGS_ACK)
1134 dinlineprintf("ackrequest ");
1135 if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)
1136 dinlineprintf("buddyreq ");
1137 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1138 dinlineprintf("hasicon ");
1139 dinlineprintf("\n");
7392c79f 1140
d410cf58 1141 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", args->flag1, args->flag2);
646c6b52 1142
d410cf58 1143 /*
1144 * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1145 * characters with their equivelent HTML entity.
1146 */
1147 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1148 int i;
7392c79f 1149
d410cf58 1150 for (i = 0; i < args->msglen; i += 2) {
1151 fu16_t uni;
7392c79f 1152
d410cf58 1153 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
7392c79f 1154
d410cf58 1155 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
7392c79f 1156
d410cf58 1157 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
7392c79f 1158
d410cf58 1159 } else { /* something else, do UNICODE entity */
7392c79f 1160
d410cf58 1161 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
7392c79f 1162
d410cf58 1163 }
871e2fd0 1164
d410cf58 1165 }
871e2fd0 1166
d410cf58 1167 } else {
1168
1169 /*
1170 * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1171 * no need to do anything special here. Most
1172 * terminals/whatever will be able to display such characters
1173 * unmodified.
1174 *
1175 * Beware that PC-ASCII 128 through 159 are _not_ actually
1176 * defined in ASCII or ISO 8859-1, and you should send them as
1177 * UNICODE. WinAIM will send these characters in a UNICODE
1178 * message, so you need to do so as well.
1179 *
1180 * You may not think it necessary to handle UNICODE messages.
1181 * You're probably wrong. For one thing, Microsoft "Smart
1182 * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1183 * but real UNICODE). If you don't parse UNICODE at all, your
1184 * users will get a blank message instead of the message
1185 * containing Smart Quotes.
1186 *
1187 */
1188 strncpy(realmsg, args->msg, sizeof(realmsg));
1189 }
3b101546 1190
d410cf58 1191 dvprintf("faimtest: icbm: message: %s\n", realmsg);
7392c79f 1192
d410cf58 1193 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1194 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon");
7392c79f 1195
d410cf58 1196 if (realmsg) {
1197 int i = 0;
9de3ca7e 1198
d410cf58 1199 while (realmsg[i] == '<') {
1200 if (realmsg[i] == '<') {
1201 while (realmsg[i] != '>')
1202 i++;
1203 i++;
1204 }
1205 }
1206 tmpstr = realmsg+i;
9de3ca7e 1207
d410cf58 1208 faimtest_handlecmd(sess, conn, userinfo, tmpstr);
64c78745 1209
d410cf58 1210 }
9de3ca7e 1211
d410cf58 1212 return 1;
9de3ca7e 1213}
1214
d410cf58 1215/*
1216 * Channel 2: Rendevous Request
1217 */
1218static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, va_list ap)
9de3ca7e 1219{
d410cf58 1220 struct aim_incomingim_ch2_args *args;
9de3ca7e 1221
d410cf58 1222 args = va_arg(ap, struct aim_incomingim_ch2_args *);
1223 va_end(ap);
9de3ca7e 1224
d410cf58 1225 if (args->reqclass == AIM_CAPS_VOICE) {
96f8b1ed 1226
d410cf58 1227 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1228 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1229 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
1230 printuserflags(userinfo->flags);
1231 dinlineprintf("\n");
ee49b735 1232
d410cf58 1233 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1234 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
e80a0fa9 1235
d410cf58 1236 } else if (args->reqclass == AIM_CAPS_GETFILE) {
1237
1238 getfile_requested(sess, conn, userinfo, args);
1239
1240 } else if (args->reqclass == AIM_CAPS_SENDFILE) {
96f8b1ed 1241
d410cf58 1242 dprintf("faimtest: send file!\n");
1449ad2b 1243
d410cf58 1244 } else if (args->reqclass == AIM_CAPS_CHAT) {
1449ad2b 1245
d410cf58 1246 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1247 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1248 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
1249 printuserflags(userinfo->flags);
1250 dinlineprintf("\n");
355229fe 1251
d410cf58 1252 /* we dont get membersince on chat invites! */
1253 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1254 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1449ad2b 1255
d410cf58 1256 dvprintf("faimtest: chat invitation: message = %s\n", args->info.chat.msg);
1257 dvprintf("faimtest: chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1258 dvprintf("faimtest: chat invitation: encoding = %s\n", args->info.chat.encoding);
1259 dvprintf("faimtest: chat invitation: language = %s\n", args->info.chat.lang);
1260 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1261 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1262 dvprintf("faimtest: chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name);
96f8b1ed 1263
d410cf58 1264 /* Automatically join room... */
1265 aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance);
96f8b1ed 1266
d410cf58 1267 } else if (args->reqclass == AIM_CAPS_IMIMAGE) {
355229fe 1268
d410cf58 1269 dprintf("faimtest: icbm: rendezvous imimage\n");
96f8b1ed 1270
d410cf58 1271 directim_requested(sess, conn, userinfo, args);
96f8b1ed 1272
d410cf58 1273 } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
01b59e1e 1274
d410cf58 1275 dvprintf("faimtest: Buddy Icon from %s, length = %u\n", userinfo->sn, args->info.icon.length);
1276
1277 } else {
1278
1279 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", args->reqclass);
1280 }
355229fe 1281
1282 return 1;
01b59e1e 1283}
9de3ca7e 1284
d410cf58 1285static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 1286{
d410cf58 1287 fu16_t channel;
355229fe 1288 struct aim_userinfo_s *userinfo;
d410cf58 1289 va_list ap;
1290 int ret = 0;
9de3ca7e 1291
d410cf58 1292 va_start(ap, fr);
1293 channel = va_arg(ap, fu16_t);
355229fe 1294 userinfo = va_arg(ap, struct aim_userinfo_s *);
355229fe 1295
d410cf58 1296 if (channel == 1)
1297 ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, ap);
1298 else if (channel == 2)
1299 ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, ap);
1300 else
1301 dvprintf("unsupported channel 0x%04x\n", channel);
1302
1303 dvprintf("faimtest: icbm: done with ICBM handling (ret = %d)\n", ret);
355229fe 1304
1305 return 1;
9de3ca7e 1306}
1307
d410cf58 1308#ifdef MID_REWROTE_ALL_THE_CRAP
1309static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
01b59e1e 1310{
d410cf58 1311 fu16_t change = 0, perms, type;
1312 int length, str;
1313 char *val;
355229fe 1314 va_list ap;
9de3ca7e 1315
d410cf58 1316 va_start(ap, fr);
1317 perms = va_arg(ap, fu16_t);
1318 type = va_arg(ap, fu16_t);
1319 length = va_arg(ap, int);
1320 val = va_arg(ap, char *);
1321 str = va_arg(ap, int);
355229fe 1322 va_end(ap);
1323
d410cf58 1324 if (aimutil_get16(command->data+2) == 0x0005)
1325 change = 1;
1326
1327 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
355229fe 1328
1329 return 1;
01b59e1e 1330}
d410cf58 1331#endif
0c20631f 1332
d410cf58 1333static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1334{
355229fe 1335 struct aim_userinfo_s *userinfo;
0c20631f 1336
d410cf58 1337 va_list ap;
1338 va_start(ap, fr);
355229fe 1339 userinfo = va_arg(ap, struct aim_userinfo_s *);
1340 va_end(ap);
0c20631f 1341
d410cf58 1342 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1343 time(NULL),
1344 userinfo->sn, userinfo->flags,
1345 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1346 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1347 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1348 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1349 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1350 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1351 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1352 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1353 userinfo->capabilities);
355229fe 1354 return 1;
0c20631f 1355}
1356
d410cf58 1357static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1358{
355229fe 1359 struct aim_userinfo_s *userinfo;
d410cf58 1360 va_list ap;
1361
1362 va_start(ap, fr);
355229fe 1363 userinfo = va_arg(ap, struct aim_userinfo_s *);
1364 va_end(ap);
37ee990e 1365
d410cf58 1366 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1367 time(NULL),
1368 userinfo->sn, userinfo->flags,
1369 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1370 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1371 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1372 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1373 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1374 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1375 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1376 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1377 userinfo->capabilities);
355229fe 1378
1379 return 1;
0c20631f 1380}
1381
d410cf58 1382static int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1383{
355229fe 1384 va_list ap;
d410cf58 1385 fu16_t reason;
355229fe 1386
d410cf58 1387 va_start(ap, fr);
1388 reason = va_arg(ap, fu16_t);
1389 va_end(ap);
355229fe 1390
d410cf58 1391 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
355229fe 1392
1393 return 1;
0c20631f 1394}
1395
d410cf58 1396static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1397{
355229fe 1398 va_list ap;
d410cf58 1399 char *destsn;
1400 fu16_t reason;
355229fe 1401
d410cf58 1402 va_start(ap, fr);
1403 reason = va_arg(ap, fu16_t);
1404 destsn = va_arg(ap, char *);
355229fe 1405 va_end(ap);
1406
d410cf58 1407 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
0c20631f 1408
355229fe 1409 return 1;
0c20631f 1410}
1411
d410cf58 1412static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
5e02cf44 1413{
355229fe 1414 va_list ap;
d410cf58 1415 char *destsn;
1416 fu16_t reason;
5e02cf44 1417
d410cf58 1418 va_start(ap, fr);
1419 reason = va_arg(ap, fu16_t);
1420 destsn = va_arg(ap, char *);
355229fe 1421 va_end(ap);
5e02cf44 1422
d410cf58 1423 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
d32954e7 1424
355229fe 1425 return 1;
5e02cf44 1426}
e5012450 1427
d410cf58 1428static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1429{
1430 static char *missedreasons[] = {
1431 "Invalid (0)",
1432 "Message too large",
1433 "Rate exceeded",
1434 "Evil Sender",
1435 "Evil Receiver"
1436 };
1437 static int missedreasonslen = 5;
e5012450 1438
d410cf58 1439 va_list ap;
1440 fu16_t chan, nummissed, reason;
1441 struct aim_userinfo_s *userinfo;
e5012450 1442
d410cf58 1443 va_start(ap, fr);
1444 chan = va_arg(ap, fu16_t);
1445 userinfo = va_arg(ap, struct aim_userinfo_s *);
1446 nummissed = va_arg(ap, fu16_t);
1447 reason = va_arg(ap, fu16_t);
1448 va_end(ap);
e5012450 1449
d410cf58 1450 dvprintf("faimtest: missed %d messages from %s on channel %d (reason %d: %s)\n", nummissed, userinfo->sn, chan, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
e5012450 1451
355229fe 1452 return 1;
e5012450 1453}
1a8c261b 1454
1455/*
646c6b52 1456 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 1457 */
d410cf58 1458static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1a8c261b 1459{
355229fe 1460 va_list ap;
d410cf58 1461 fu16_t type;
355229fe 1462 char *sn = NULL;
1a8c261b 1463
d410cf58 1464 va_start(ap, fr);
1465 type = va_arg(ap, fu16_t);
355229fe 1466 sn = va_arg(ap, char *);
1467 va_end(ap);
1a8c261b 1468
355229fe 1469 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 1470
355229fe 1471 return 1;
1a8c261b 1472}
1473
d410cf58 1474static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
871e2fd0 1475{
d410cf58 1476 static char *codes[5] = {
1477 "invalid",
1478 "change",
1479 "warning",
1480 "limit",
1481 "limit cleared"
1482 };
355229fe 1483 va_list ap;
d410cf58 1484 fu16_t code, rateclass;
1485 fu32_t windowsize, clear, alert, limit, disconnect;
1486 fu32_t currentavg, maxavg;
37ee990e 1487
d410cf58 1488 va_start(ap, fr);
37ee990e 1489
d410cf58 1490 /* See code explanations below */
1491 code = va_arg(ap, fu16_t);
37ee990e 1492
d410cf58 1493 /*
1494 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1495 */
1496 rateclass = va_arg(ap, fu16_t);
37ee990e 1497
d410cf58 1498 /*
1499 * Not sure what this is exactly. I think its the temporal
1500 * relation factor (ie, how to make the rest of the numbers
1501 * make sense in the real world).
1502 */
1503 windowsize = va_arg(ap, fu32_t);
646c6b52 1504
d410cf58 1505 /* Explained below */
1506 clear = va_arg(ap, fu32_t);
1507 alert = va_arg(ap, fu32_t);
1508 limit = va_arg(ap, fu32_t);
1509 disconnect = va_arg(ap, fu32_t);
1510 currentavg = va_arg(ap, fu32_t);
1511 maxavg = va_arg(ap, fu32_t);
646c6b52 1512
d410cf58 1513 va_end(ap);
646c6b52 1514
646c6b52 1515
d410cf58 1516 dvprintf("faimtest: rate %s (rate class 0x%04x): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
1517 (code < 5)?codes[code]:"invalid",
1518 rateclass,
1519 currentavg, maxavg,
1520 alert, clear,
1521 limit, disconnect,
1522 windowsize);
1523
1524 if (code == AIM_RATE_CODE_CHANGE) {
1525 /*
1526 * Not real sure when these get sent.
1527 */
1528 if (currentavg >= clear)
1529 aim_conn_setlatency(fr->conn, 0);
1530
1531 } else if (code == AIM_RATE_CODE_WARNING) {
1532 /*
1533 * We start getting WARNINGs the first time we go below the
1534 * 'alert' limit (currentavg < alert) and they stop when
1535 * either we pause long enough for currentavg to go above
1536 * 'clear', or until we flood it bad enough to go below
1537 * 'limit' (and start getting LIMITs instead) or even further
1538 * and go below 'disconnect' and get disconnected completely
1539 * (and won't be able to login right away either).
1540 */
1541 aim_conn_setlatency(fr->conn, windowsize/4); /* XXX this is bogus! */
1542
1543 } else if (code == AIM_RATE_CODE_LIMIT) {
1544 /*
1545 * When we hit LIMIT, messages will start getting dropped.
1546 */
1547 aim_conn_setlatency(fr->conn, windowsize/2); /* XXX this is bogus! */
1548
1549 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
1550 /*
1551 * The limit is cleared when curavg goes above 'clear'.
1552 */
1553 aim_conn_setlatency(fr->conn, 0);
1554 }
646c6b52 1555
d410cf58 1556 return 1;
78b3fb13 1557}
98c88242 1558
d410cf58 1559static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
98c88242 1560{
355229fe 1561 va_list ap;
d410cf58 1562 fu16_t newevil;
355229fe 1563 struct aim_userinfo_s *userinfo;
98c88242 1564
d410cf58 1565 va_start(ap, fr);
1566 newevil = va_arg(ap, fu16_t);
355229fe 1567 userinfo = va_arg(ap, struct aim_userinfo_s *);
1568 va_end(ap);
98c88242 1569
355229fe 1570 /*
1571 * Evil Notifications that are lacking userinfo->sn are anon-warns
1572 * if they are an evil increases, but are not warnings at all if its
1573 * a decrease (its the natural backoff happening).
1574 *
1575 * newevil is passed as an int representing the new evil value times
1576 * ten.
1577 */
1578 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
37ee990e 1579
355229fe 1580 return 1;
37ee990e 1581}
1582
d410cf58 1583static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1584{
355229fe 1585 va_list ap;
1586 char *address, *SNs;
1587 int i, num;
37ee990e 1588
d410cf58 1589 va_start(ap, fr);
355229fe 1590 address = va_arg(ap, char *);
1591 num = va_arg(ap, int);
1592 SNs = va_arg(ap, char *);
1593 va_end(ap);
37ee990e 1594
355229fe 1595 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
37ee990e 1596
355229fe 1597 for(i = 0; i < num; i++)
1598 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
1599 dinlineprintf("\n");
1600
1601 return 1;
37ee990e 1602}
1603
d410cf58 1604static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1605{
355229fe 1606 va_list ap;
1607 char *address;
37ee990e 1608
d410cf58 1609 va_start(ap, fr);
355229fe 1610 address = va_arg(ap, char *);
1611 va_end(ap);
98c88242 1612
355229fe 1613 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1614
1615 return 1;
78b3fb13 1616}
d410cf58 1617
1618void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
1619{
1620
1621 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1622
1623 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
1624 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp_bos, 0); /* rate info */
1625 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
1626 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
1627 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
1628 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
1629 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
1630 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
1631 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
1632 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1633 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
1634 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, faimtest_locrights, 0);
1635 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
1636 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
1637 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
1638 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1639 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
1640 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
1641 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
1642 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
1643 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
1644 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
1645 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
1646 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
1647 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
1648
1649 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
1650 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
1651 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
1652
1653#ifdef MID_REWROTE_ALL_THE_CRAP
1654 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
1655#endif
1656
1657 return;
1658}
1659
This page took 1.919947 seconds and 5 git commands to generate.