]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Fri Sep 7 19:59:43 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{
e1b8c575 1108 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
d410cf58 1109 char *tmpstr;
1110 struct aim_incomingim_ch1_args *args;
1111 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
1112 char realmsg[8192+1] = {""};
7a449b5d 1113
d410cf58 1114 args = va_arg(ap, struct aim_incomingim_ch1_args *);
1115 va_end(ap);
7a449b5d 1116
d410cf58 1117 clienttype = aim_fingerprintclient(args->fingerprint, args->finlen);
9de3ca7e 1118
d410cf58 1119 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
1120 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
1121 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1122 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
1123 printuserflags(userinfo->flags);
1124 dinlineprintf("\n");
7392c79f 1125
d410cf58 1126 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1127 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1128 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1129 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
1130
1131 dprintf("faimtest: icbm: icbmflags = ");
1132 if (args->icbmflags & AIM_IMFLAGS_AWAY)
1133 dinlineprintf("away ");
1134 if (args->icbmflags & AIM_IMFLAGS_ACK)
1135 dinlineprintf("ackrequest ");
1136 if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)
1137 dinlineprintf("buddyreq ");
1138 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1139 dinlineprintf("hasicon ");
1140 dinlineprintf("\n");
7392c79f 1141
d410cf58 1142 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", args->flag1, args->flag2);
646c6b52 1143
d410cf58 1144 /*
1145 * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1146 * characters with their equivelent HTML entity.
1147 */
1148 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1149 int i;
7392c79f 1150
d410cf58 1151 for (i = 0; i < args->msglen; i += 2) {
1152 fu16_t uni;
7392c79f 1153
d410cf58 1154 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
7392c79f 1155
d410cf58 1156 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
7392c79f 1157
d410cf58 1158 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
7392c79f 1159
d410cf58 1160 } else { /* something else, do UNICODE entity */
7392c79f 1161
d410cf58 1162 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
7392c79f 1163
d410cf58 1164 }
871e2fd0 1165
d410cf58 1166 }
871e2fd0 1167
d410cf58 1168 } else {
1169
1170 /*
1171 * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1172 * no need to do anything special here. Most
1173 * terminals/whatever will be able to display such characters
1174 * unmodified.
1175 *
1176 * Beware that PC-ASCII 128 through 159 are _not_ actually
1177 * defined in ASCII or ISO 8859-1, and you should send them as
1178 * UNICODE. WinAIM will send these characters in a UNICODE
1179 * message, so you need to do so as well.
1180 *
1181 * You may not think it necessary to handle UNICODE messages.
1182 * You're probably wrong. For one thing, Microsoft "Smart
1183 * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1184 * but real UNICODE). If you don't parse UNICODE at all, your
1185 * users will get a blank message instead of the message
1186 * containing Smart Quotes.
1187 *
1188 */
1189 strncpy(realmsg, args->msg, sizeof(realmsg));
1190 }
3b101546 1191
d410cf58 1192 dvprintf("faimtest: icbm: message: %s\n", realmsg);
7392c79f 1193
d410cf58 1194 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1195 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon");
7392c79f 1196
d410cf58 1197 if (realmsg) {
1198 int i = 0;
9de3ca7e 1199
d410cf58 1200 while (realmsg[i] == '<') {
1201 if (realmsg[i] == '<') {
1202 while (realmsg[i] != '>')
1203 i++;
1204 i++;
1205 }
1206 }
1207 tmpstr = realmsg+i;
9de3ca7e 1208
d410cf58 1209 faimtest_handlecmd(sess, conn, userinfo, tmpstr);
64c78745 1210
d410cf58 1211 }
9de3ca7e 1212
e1b8c575 1213 if (priv->buddyicon && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ))
1214 aim_send_icon(sess, conn, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum);
1215
d410cf58 1216 return 1;
9de3ca7e 1217}
1218
d410cf58 1219/*
1220 * Channel 2: Rendevous Request
1221 */
1222static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, va_list ap)
9de3ca7e 1223{
d410cf58 1224 struct aim_incomingim_ch2_args *args;
9de3ca7e 1225
d410cf58 1226 args = va_arg(ap, struct aim_incomingim_ch2_args *);
1227 va_end(ap);
9de3ca7e 1228
d410cf58 1229 if (args->reqclass == AIM_CAPS_VOICE) {
96f8b1ed 1230
d410cf58 1231 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1232 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1233 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
1234 printuserflags(userinfo->flags);
1235 dinlineprintf("\n");
ee49b735 1236
d410cf58 1237 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1238 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
e80a0fa9 1239
d410cf58 1240 } else if (args->reqclass == AIM_CAPS_GETFILE) {
1241
1242 getfile_requested(sess, conn, userinfo, args);
1243
1244 } else if (args->reqclass == AIM_CAPS_SENDFILE) {
96f8b1ed 1245
d410cf58 1246 dprintf("faimtest: send file!\n");
1449ad2b 1247
d410cf58 1248 } else if (args->reqclass == AIM_CAPS_CHAT) {
1449ad2b 1249
d410cf58 1250 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1251 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1252 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
1253 printuserflags(userinfo->flags);
1254 dinlineprintf("\n");
355229fe 1255
d410cf58 1256 /* we dont get membersince on chat invites! */
1257 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1258 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1449ad2b 1259
d410cf58 1260 dvprintf("faimtest: chat invitation: message = %s\n", args->info.chat.msg);
1261 dvprintf("faimtest: chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1262 dvprintf("faimtest: chat invitation: encoding = %s\n", args->info.chat.encoding);
1263 dvprintf("faimtest: chat invitation: language = %s\n", args->info.chat.lang);
1264 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1265 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1266 dvprintf("faimtest: chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name);
96f8b1ed 1267
d410cf58 1268 /* Automatically join room... */
1269 aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance);
96f8b1ed 1270
d410cf58 1271 } else if (args->reqclass == AIM_CAPS_IMIMAGE) {
355229fe 1272
d410cf58 1273 dprintf("faimtest: icbm: rendezvous imimage\n");
96f8b1ed 1274
d410cf58 1275 directim_requested(sess, conn, userinfo, args);
96f8b1ed 1276
d410cf58 1277 } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
01b59e1e 1278
e1b8c575 1279 dvprintf("faimtest: Buddy Icon from %s, length = %lu\n", userinfo->sn, args->info.icon.length);
d410cf58 1280
1281 } else {
1282
1283 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", args->reqclass);
1284 }
355229fe 1285
1286 return 1;
01b59e1e 1287}
9de3ca7e 1288
d410cf58 1289static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 1290{
d410cf58 1291 fu16_t channel;
355229fe 1292 struct aim_userinfo_s *userinfo;
d410cf58 1293 va_list ap;
1294 int ret = 0;
9de3ca7e 1295
d410cf58 1296 va_start(ap, fr);
1297 channel = va_arg(ap, fu16_t);
355229fe 1298 userinfo = va_arg(ap, struct aim_userinfo_s *);
355229fe 1299
d410cf58 1300 if (channel == 1)
1301 ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, ap);
1302 else if (channel == 2)
1303 ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, ap);
1304 else
1305 dvprintf("unsupported channel 0x%04x\n", channel);
1306
1307 dvprintf("faimtest: icbm: done with ICBM handling (ret = %d)\n", ret);
355229fe 1308
1309 return 1;
9de3ca7e 1310}
1311
d410cf58 1312#ifdef MID_REWROTE_ALL_THE_CRAP
1313static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
01b59e1e 1314{
d410cf58 1315 fu16_t change = 0, perms, type;
1316 int length, str;
1317 char *val;
355229fe 1318 va_list ap;
9de3ca7e 1319
d410cf58 1320 va_start(ap, fr);
1321 perms = va_arg(ap, fu16_t);
1322 type = va_arg(ap, fu16_t);
1323 length = va_arg(ap, int);
1324 val = va_arg(ap, char *);
1325 str = va_arg(ap, int);
355229fe 1326 va_end(ap);
1327
d410cf58 1328 if (aimutil_get16(command->data+2) == 0x0005)
1329 change = 1;
1330
1331 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
355229fe 1332
1333 return 1;
01b59e1e 1334}
d410cf58 1335#endif
0c20631f 1336
d410cf58 1337static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1338{
355229fe 1339 struct aim_userinfo_s *userinfo;
0c20631f 1340
d410cf58 1341 va_list ap;
1342 va_start(ap, fr);
355229fe 1343 userinfo = va_arg(ap, struct aim_userinfo_s *);
1344 va_end(ap);
0c20631f 1345
d410cf58 1346 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1347 time(NULL),
1348 userinfo->sn, userinfo->flags,
1349 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1350 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1351 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1352 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1353 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1354 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1355 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1356 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1357 userinfo->capabilities);
355229fe 1358 return 1;
0c20631f 1359}
1360
d410cf58 1361static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1362{
355229fe 1363 struct aim_userinfo_s *userinfo;
d410cf58 1364 va_list ap;
1365
1366 va_start(ap, fr);
355229fe 1367 userinfo = va_arg(ap, struct aim_userinfo_s *);
1368 va_end(ap);
37ee990e 1369
d410cf58 1370 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1371 time(NULL),
1372 userinfo->sn, userinfo->flags,
1373 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1374 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1375 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1376 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1377 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1378 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1379 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1380 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1381 userinfo->capabilities);
355229fe 1382
1383 return 1;
0c20631f 1384}
1385
d410cf58 1386static int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1387{
355229fe 1388 va_list ap;
d410cf58 1389 fu16_t reason;
355229fe 1390
d410cf58 1391 va_start(ap, fr);
1392 reason = va_arg(ap, fu16_t);
1393 va_end(ap);
355229fe 1394
d410cf58 1395 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
355229fe 1396
1397 return 1;
0c20631f 1398}
1399
d410cf58 1400static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1401{
355229fe 1402 va_list ap;
d410cf58 1403 char *destsn;
1404 fu16_t reason;
355229fe 1405
d410cf58 1406 va_start(ap, fr);
1407 reason = va_arg(ap, fu16_t);
1408 destsn = va_arg(ap, char *);
355229fe 1409 va_end(ap);
1410
d410cf58 1411 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
0c20631f 1412
355229fe 1413 return 1;
0c20631f 1414}
1415
d410cf58 1416static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
5e02cf44 1417{
355229fe 1418 va_list ap;
d410cf58 1419 char *destsn;
1420 fu16_t reason;
5e02cf44 1421
d410cf58 1422 va_start(ap, fr);
1423 reason = va_arg(ap, fu16_t);
1424 destsn = va_arg(ap, char *);
355229fe 1425 va_end(ap);
5e02cf44 1426
d410cf58 1427 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
d32954e7 1428
355229fe 1429 return 1;
5e02cf44 1430}
e5012450 1431
d410cf58 1432static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1433{
1434 static char *missedreasons[] = {
1435 "Invalid (0)",
1436 "Message too large",
1437 "Rate exceeded",
1438 "Evil Sender",
1439 "Evil Receiver"
1440 };
1441 static int missedreasonslen = 5;
e5012450 1442
d410cf58 1443 va_list ap;
1444 fu16_t chan, nummissed, reason;
1445 struct aim_userinfo_s *userinfo;
e5012450 1446
d410cf58 1447 va_start(ap, fr);
1448 chan = va_arg(ap, fu16_t);
1449 userinfo = va_arg(ap, struct aim_userinfo_s *);
1450 nummissed = va_arg(ap, fu16_t);
1451 reason = va_arg(ap, fu16_t);
1452 va_end(ap);
e5012450 1453
d410cf58 1454 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 1455
355229fe 1456 return 1;
e5012450 1457}
1a8c261b 1458
1459/*
646c6b52 1460 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 1461 */
d410cf58 1462static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1a8c261b 1463{
355229fe 1464 va_list ap;
d410cf58 1465 fu16_t type;
355229fe 1466 char *sn = NULL;
1a8c261b 1467
d410cf58 1468 va_start(ap, fr);
1469 type = va_arg(ap, fu16_t);
355229fe 1470 sn = va_arg(ap, char *);
1471 va_end(ap);
1a8c261b 1472
355229fe 1473 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 1474
355229fe 1475 return 1;
1a8c261b 1476}
1477
d410cf58 1478static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
871e2fd0 1479{
d410cf58 1480 static char *codes[5] = {
1481 "invalid",
1482 "change",
1483 "warning",
1484 "limit",
1485 "limit cleared"
1486 };
355229fe 1487 va_list ap;
d410cf58 1488 fu16_t code, rateclass;
1489 fu32_t windowsize, clear, alert, limit, disconnect;
1490 fu32_t currentavg, maxavg;
37ee990e 1491
d410cf58 1492 va_start(ap, fr);
37ee990e 1493
d410cf58 1494 /* See code explanations below */
1495 code = va_arg(ap, fu16_t);
37ee990e 1496
d410cf58 1497 /*
1498 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1499 */
1500 rateclass = va_arg(ap, fu16_t);
37ee990e 1501
d410cf58 1502 /*
1503 * Not sure what this is exactly. I think its the temporal
1504 * relation factor (ie, how to make the rest of the numbers
1505 * make sense in the real world).
1506 */
1507 windowsize = va_arg(ap, fu32_t);
646c6b52 1508
d410cf58 1509 /* Explained below */
1510 clear = va_arg(ap, fu32_t);
1511 alert = va_arg(ap, fu32_t);
1512 limit = va_arg(ap, fu32_t);
1513 disconnect = va_arg(ap, fu32_t);
1514 currentavg = va_arg(ap, fu32_t);
1515 maxavg = va_arg(ap, fu32_t);
646c6b52 1516
d410cf58 1517 va_end(ap);
646c6b52 1518
646c6b52 1519
d410cf58 1520 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",
1521 (code < 5)?codes[code]:"invalid",
1522 rateclass,
1523 currentavg, maxavg,
1524 alert, clear,
1525 limit, disconnect,
1526 windowsize);
1527
1528 if (code == AIM_RATE_CODE_CHANGE) {
1529 /*
1530 * Not real sure when these get sent.
1531 */
1532 if (currentavg >= clear)
1533 aim_conn_setlatency(fr->conn, 0);
1534
1535 } else if (code == AIM_RATE_CODE_WARNING) {
1536 /*
1537 * We start getting WARNINGs the first time we go below the
1538 * 'alert' limit (currentavg < alert) and they stop when
1539 * either we pause long enough for currentavg to go above
1540 * 'clear', or until we flood it bad enough to go below
1541 * 'limit' (and start getting LIMITs instead) or even further
1542 * and go below 'disconnect' and get disconnected completely
1543 * (and won't be able to login right away either).
1544 */
1545 aim_conn_setlatency(fr->conn, windowsize/4); /* XXX this is bogus! */
1546
1547 } else if (code == AIM_RATE_CODE_LIMIT) {
1548 /*
1549 * When we hit LIMIT, messages will start getting dropped.
1550 */
1551 aim_conn_setlatency(fr->conn, windowsize/2); /* XXX this is bogus! */
1552
1553 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
1554 /*
1555 * The limit is cleared when curavg goes above 'clear'.
1556 */
1557 aim_conn_setlatency(fr->conn, 0);
1558 }
646c6b52 1559
d410cf58 1560 return 1;
78b3fb13 1561}
98c88242 1562
d410cf58 1563static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
98c88242 1564{
355229fe 1565 va_list ap;
d410cf58 1566 fu16_t newevil;
355229fe 1567 struct aim_userinfo_s *userinfo;
98c88242 1568
d410cf58 1569 va_start(ap, fr);
1570 newevil = va_arg(ap, fu16_t);
355229fe 1571 userinfo = va_arg(ap, struct aim_userinfo_s *);
1572 va_end(ap);
98c88242 1573
355229fe 1574 /*
1575 * Evil Notifications that are lacking userinfo->sn are anon-warns
1576 * if they are an evil increases, but are not warnings at all if its
1577 * a decrease (its the natural backoff happening).
1578 *
1579 * newevil is passed as an int representing the new evil value times
1580 * ten.
1581 */
1582 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
37ee990e 1583
355229fe 1584 return 1;
37ee990e 1585}
1586
d410cf58 1587static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1588{
355229fe 1589 va_list ap;
1590 char *address, *SNs;
1591 int i, num;
37ee990e 1592
d410cf58 1593 va_start(ap, fr);
355229fe 1594 address = va_arg(ap, char *);
1595 num = va_arg(ap, int);
1596 SNs = va_arg(ap, char *);
1597 va_end(ap);
37ee990e 1598
355229fe 1599 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
37ee990e 1600
355229fe 1601 for(i = 0; i < num; i++)
1602 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
1603 dinlineprintf("\n");
1604
1605 return 1;
37ee990e 1606}
1607
d410cf58 1608static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1609{
355229fe 1610 va_list ap;
1611 char *address;
37ee990e 1612
d410cf58 1613 va_start(ap, fr);
355229fe 1614 address = va_arg(ap, char *);
1615 va_end(ap);
98c88242 1616
355229fe 1617 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1618
1619 return 1;
78b3fb13 1620}
d410cf58 1621
1622void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
1623{
1624
1625 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1626
1627 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
1628 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp_bos, 0); /* rate info */
1629 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
1630 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
1631 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
1632 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
1633 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
1634 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
1635 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
1636 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1637 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
1638 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, faimtest_locrights, 0);
1639 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
1640 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
1641 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
1642 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1643 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
1644 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
1645 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
1646 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
1647 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
1648 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
1649 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
1650 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
1651 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
1652
1653 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
1654 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
1655 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
1656
1657#ifdef MID_REWROTE_ALL_THE_CRAP
1658 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
1659#endif
1660
1661 return;
1662}
1663
This page took 2.315618 seconds and 5 git commands to generate.