]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Sat Sep 8 19:05:05 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) {
309 if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
310 dprintf("connection error (rend out)\n");
311 aim_conn_kill(&aimsess, &waitingconn);
312 }
313 } else {
314 if (aim_get_command(&aimsess, waitingconn) >= 0) {
315 aim_rxdispatch(&aimsess);
316 } else {
317 dvprintf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
318 /* we should have callbacks for all these, else the library will do the conn_kill for us. */
319 if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
59e1da90 320 if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
321 dvprintf("disconnected from %s\n", aim_directim_getsn(waitingconn));
355229fe 322 aim_conn_kill(&aimsess, &waitingconn);
323 } else
324 aim_conn_kill(&aimsess, &waitingconn);
325 if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
326 dprintf("major connection error\n");
327 if (faimtest_mode == 2)
328 break;
329 }
330 }
331 }
332 }
333 }
7392c79f 334 }
9de3ca7e 335
355229fe 336 /* close up all connections, dead or no */
337 aim_session_kill(&aimsess);
9de3ca7e 338
355229fe 339 if (faimtest_mode < 2) {
340 printf("\n");
341 cmd_uninit();
342 }
b562f484 343
d410cf58 344 free(priv.buddyicon);
7b91722d 345
355229fe 346 /* Get out */
347 exit(0);
9de3ca7e 348}
349
d410cf58 350int faimtest_serverready(aim_session_t *sess, aim_frame_t *fr, ...)
c78446b5 351{
d410cf58 352 int famcount, i;
353 fu16_t *families;
354 va_list ap;
c78446b5 355
d410cf58 356 va_start(ap, fr);
357 famcount = va_arg(ap, int);
358 families = va_arg(ap, fu16_t *);
359 va_end(ap);
360
361 dvprintf("faimtest: SNAC families supported by this host (type %d): ", fr->conn->type);
362 for (i = 0; i < famcount; i++)
363 dvinlineprintf("0x%04x ", families[i]);
364 dinlineprintf("\n");
c78446b5 365
d410cf58 366 if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
c78446b5 367
d410cf58 368 aim_auth_setversions(sess, fr->conn);
369 aim_bos_reqrate(sess, fr->conn); /* request rate info */
c78446b5 370
d410cf58 371 dprintf("done with auth server ready\n");
355229fe 372
d410cf58 373 } else if (fr->conn->type == AIM_CONN_TYPE_BOS) {
355229fe 374
d410cf58 375 aim_setversions(sess, fr->conn);
376 aim_bos_reqrate(sess, fr->conn); /* request rate info */
355229fe 377
d410cf58 378 dprintf("done with BOS server ready\n");
355229fe 379 }
d410cf58 380
381 return 1;
382}
383
384int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
385{
386 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
387 va_list ap;
388 fu16_t code;
389 char *msg;
390
391 va_start(ap, fr);
392 code = va_arg(ap, int);
393 msg = va_arg(ap, char *);
394 va_end(ap);
395
396 dvprintf("connerr: Code 0x%04x: %s\n", code, msg);
397 aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
398
399 priv->connected = 0;
400
401 return 1;
402}
403
404#if 0
405static int faimtest_rateresp_auth(aim_session_t *sess, aim_frame_t *fr, ...)
406{
407
408 aim_bos_ackrateresp(sess, fr->conn);
409 aim_auth_clientready(sess, fr->conn);
410
411 dprintf("faimtest: connected to authorization/admin service\n");
412
413 return 1;
414}
415
416int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
417{
418 int status;
419 va_list ap;
420
421 va_start(ap, fr);
422 status = va_arg(ap, int); /* status code of confirmation request */
423 va_end(ap);
424
425 dvprintf("account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
426
427 return 1;
428}
429
430
431#endif
432
433#if 0
434/*
435 * This kind of function is really not legal in the new bstream way...
436 * In fact, clients should never access the aim_frame_t directly in handlers,
437 * since that may leave it in a bizare state for the lower layers. In fact,
438 * clients should probably not even get passed a pointer like this.
439 *
440 */
441int faimtest_parse_unknown(aim_session_t *sess, aim_frame_t *fr, ...)
442{
443 int i;
444
445 aim_bstream_rewind(&fr->data); /* boo! */
446
447 dprintf("\nReceived unknown packet:");
448 for (i = 0; aim_bstream_empty(&fr->data); i++) {
449 if ((i % 8) == 0)
450 dinlineprintf("\n\t");
451 dvinlineprintf("0x%2x ", aimbs_get8(&fr->data));
355229fe 452 }
d410cf58 453 dinlineprintf("\n\n");
355229fe 454
455 return 1;
c78446b5 456}
d410cf58 457#endif
c78446b5 458
d410cf58 459int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
460{
461 va_list ap;
462 int serviceid;
463 char *ip;
464 fu8_t *cookie;
465
466 va_start(ap, fr);
467 serviceid = va_arg(ap, int);
468 ip = va_arg(ap, char *);
469 cookie = va_arg(ap, fu8_t *);
470
471 if (serviceid == 0x0005) { /* Adverts */
472#if 0
473 aim_conn_t *tstconn;
474
475 tstconn = aim_newconn(sess, AIM_CONN_TYPE_ADS, ip);
476 if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
477 dprintf("faimtest: unable to reconnect with authorizer\n");
478 } else {
479 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
480 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
481 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
482 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
483 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
484 aim_auth_sendcookie(sess, tstconn, cookie);
485 dprintf("sent cookie to adverts host\n");
486 }
487#endif
488 } else if (serviceid == 0x0007) { /* Authorizer */
489#if 0
490 aim_conn_t *tstconn;
491
492 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
493 if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
494 dprintf("faimtest: unable to reconnect with authorizer\n");
495 } else {
496 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
497 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
498 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
499 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
500 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
501 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
502 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
503 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
504 /* Send the cookie to the Auth */
505 aim_auth_sendcookie(sess, tstconn, cookie);
506 dprintf("sent cookie to authorizer host\n");
507 }
508#endif
509 } else if (serviceid == 0x000d) { /* ChatNav */
510
511 chatnav_redirect(sess, ip, cookie);
512
513 } else if (serviceid == 0x000e) { /* Chat */
514 char *roomname = NULL;
515 int exchange;
516
517 roomname = va_arg(ap, char *);
518 exchange = va_arg(ap, int);
519
520 chat_redirect(sess, ip, cookie, roomname, exchange);
521
522 } else {
523 dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
524 }
525
526 va_end(ap);
527
528 return 1;
529}
530
531static int faimtest_rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...)
532{
533 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
534 char buddies[128]; /* this is the new buddy list */
535 char profile[256]; /* this is the new profile */
536 char awaymsg[] = {"blah blah blah Ole! blah blah blah"};
537
538 /* Caution: Buddy1 and Buddy2 are real people! (who I don't know) */
539 snprintf(buddies, sizeof(buddies), "Buddy1&Buddy2&%s&", priv->ohcaptainmycaptain ? priv->ohcaptainmycaptain : "blah");
540 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);
541
542 aim_bos_ackrateresp(sess, fr->conn); /* ack rate info response */
543 aim_bos_reqpersonalinfo(sess, fr->conn);
544 aim_bos_reqlocaterights(sess, fr->conn);
545 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*/);
546 aim_bos_reqbuddyrights(sess, fr->conn);
547
548 /* send the buddy list and profile (required, even if empty) */
549 aim_bos_setbuddylist(sess, fr->conn, buddies);
550
551 aim_reqicbmparams(sess, fr->conn);
552
553 aim_bos_reqrights(sess, fr->conn);
554 /* set group permissions -- all user classes */
555 aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
556 aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE);
557
558 return 1;
559}
560
561static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
00ef5271 562{
355229fe 563 struct aim_icbmparameters *params;
564 va_list ap;
00ef5271 565
d410cf58 566 va_start(ap, fr);
355229fe 567 params = va_arg(ap, struct aim_icbmparameters *);
568 va_end(ap);
00ef5271 569
355229fe 570 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 571
36a61e0d 572 /*
573 * Set these to your taste, or client medium. Setting minmsginterval
574 * higher is good for keeping yourself from getting flooded (esp
575 * if you're on a slow connection or something where that would be
576 * useful).
577 */
355229fe 578 params->maxmsglen = 8000;
36a61e0d 579 params->minmsginterval = 0; /* in milliseconds */
355229fe 580
d410cf58 581 aim_seticbmparam(sess, fr->conn, params);
355229fe 582
583 return 1;
00ef5271 584}
585
d410cf58 586static int faimtest_hostversions(aim_session_t *sess, aim_frame_t *fr, ...)
ee49b735 587{
355229fe 588 int vercount, i;
d410cf58 589 fu8_t *versions;
355229fe 590 va_list ap;
591
d410cf58 592 va_start(ap, fr);
355229fe 593 vercount = va_arg(ap, int); /* number of family/version pairs */
d410cf58 594 versions = va_arg(ap, fu8_t *);
355229fe 595 va_end(ap);
596
597 dprintf("faimtest: SNAC versions supported by this host: ");
598 for (i = 0; i < vercount*4; i += 4) {
599 dvinlineprintf("0x%04x:0x%04x ",
600 aimutil_get16(versions+i), /* SNAC family */
601 aimutil_get16(versions+i+2) /* Version number */);
602 }
603 dinlineprintf("\n");
ee49b735 604
355229fe 605 return 1;
ee49b735 606}
607
d410cf58 608static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
64c78745 609{
355229fe 610 va_list ap;
d410cf58 611 fu16_t maxbuddies, maxwatchers;
64c78745 612
d410cf58 613 va_start(ap, fr);
614 maxbuddies = va_arg(ap, int);
615 maxwatchers = va_arg(ap, int);
355229fe 616 va_end(ap);
64c78745 617
d410cf58 618 dvprintf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
64c78745 619
355229fe 620 return 1;
64c78745 621}
622
d410cf58 623static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 624{
d410cf58 625 va_list ap;
626 fu16_t maxpermits, maxdenies;
9de3ca7e 627
d410cf58 628 va_start(ap, fr);
629 maxpermits = va_arg(ap, int);
630 maxdenies = va_arg(ap, int);
631 va_end(ap);
632
633 dvprintf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
96f8b1ed 634
d410cf58 635 aim_bos_clientready(sess, fr->conn);
96f8b1ed 636
d410cf58 637 dprintf("officially connected to BOS.\n");
96f8b1ed 638
d410cf58 639 return 1;
96f8b1ed 640}
641
d410cf58 642static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
c78446b5 643{
d410cf58 644 va_list ap;
645 fu16_t maxsiglen;
96f8b1ed 646
d410cf58 647 va_start(ap, fr);
648 maxsiglen = va_arg(ap, int);
649 va_end(ap);
c78446b5 650
d410cf58 651 dvprintf("locate rights: max signature length = %d\n", maxsiglen);
37ee990e 652
d410cf58 653 return 1;
37ee990e 654}
655
d410cf58 656static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
b39e0a91 657{
d410cf58 658 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
659 va_list ap;
660 fu16_t interval;
b39e0a91 661
d410cf58 662 va_start(ap, fr);
663 interval = va_arg(ap, int);
664 va_end(ap);
b39e0a91 665
d410cf58 666 dvprintf("minimum report interval: %d (seconds?)\n", interval);
b39e0a91 667
d410cf58 668 if (!priv->connected)
669 priv->connected++;
b39e0a91 670
d410cf58 671#if 0
672 aim_bos_reqservice(sess, fr->conn, 0x0005); /* adverts */
673 aim_bos_reqservice(sess, fr->conn, 0x000f); /* user directory */
37ee990e 674
d410cf58 675 /* Don't know what this does... */
676 /* XXX sess->sn should be normalized by the 0001/000f handler */
677 aim_0002_000b(sess, fr->conn, sess->sn);
678#endif
37ee990e 679
d410cf58 680 aim_reqicbmparams(sess, fr->conn);
c78446b5 681
d410cf58 682 return 1;
c78446b5 683}
684
d410cf58 685static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 686{
d410cf58 687 static char *codes[] = {
688 "Unknown",
689 "Mandatory upgrade",
690 "Advisory upgrade",
691 "System bulletin",
692 "Top o' the world!"
693 };
694 static int codeslen = 5;
695 char *msg;
696 fu16_t id;
697 va_list ap;
698
699 va_start(ap, fr);
700 id = va_arg(ap, int);
701 msg = va_arg(ap, char *);
702 va_end(ap);
703
704 dvprintf("motd: %s (%d / %s)\n", msg, id, (id < codeslen)?codes[id]:"unknown");
705
706 return 1;
9de3ca7e 707}
708
83ae98f8 709/*
710 * This is a little more complicated than it looks. The module
711 * name (proto, boscore, etc) may or may not be given. If it is
712 * not given, then use aim.exe. If it is given, put ".ocm" on the
713 * end of it.
714 *
715 * Now, if the offset or length requested would cause a read past
716 * the end of the file, then the request is considered invalid. Invalid
717 * requests are processed specially. The value hashed is the
718 * the request, put into little-endian (eight bytes: offset followed
719 * by length).
720 *
721 * Additionally, if the request is valid, the length is mod 4096. It is
722 * important that the length is checked for validity first before doing
723 * the mod.
724 *
725 * Note to Bosco's Brigade: if you'd like to break this, put the
726 * module name on an invalid request.
727 *
728 */
d410cf58 729static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
b1eac25a 730{
d410cf58 731 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
732 FILE *f;
733 static const char defaultmod[] = "aim.exe";
734 char *filename = NULL;
735 struct stat st;
736 unsigned char *buf;
737 int invalid = 0;
738
739 if (!bufret || !buflenret)
740 return -1;
b1eac25a 741
d410cf58 742 if (modname) {
001c9b80 743
d410cf58 744 if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
745 dperror("memrequest: malloc");
746 return -1;
747 }
5ac961d5 748
d410cf58 749 sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
5ac961d5 750
d410cf58 751 } else {
328837f7 752
d410cf58 753 if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
754 dperror("memrequest: malloc");
755 return -1;
756 }
328837f7 757
d410cf58 758 sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
b1eac25a 759
d410cf58 760 }
83ae98f8 761
d410cf58 762 if (stat(filename, &st) == -1) {
763 if (!modname) {
764 dperror("memrequest: stat");
765 free(filename);
766 return -1;
767 }
768 invalid = 1;
769 }
83ae98f8 770
d410cf58 771 if (!invalid) {
772 if ((offset > st.st_size) || (len > st.st_size))
773 invalid = 1;
774 else if ((st.st_size - offset) < len)
775 len = st.st_size - offset;
776 else if ((st.st_size - len) < len)
777 len = st.st_size - len;
778 }
83ae98f8 779
d410cf58 780 if (!invalid && len)
781 len %= 4096;
83ae98f8 782
d410cf58 783 if (invalid) {
784 int i;
f6a4f6b7 785
d410cf58 786 free(filename); /* not needed */
f6a4f6b7 787
d410cf58 788 dvprintf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
83ae98f8 789
d410cf58 790 i = 8;
791 if (modname)
792 i += strlen(modname);
f6a4f6b7 793
d410cf58 794 if (!(buf = malloc(i)))
795 return -1;
83ae98f8 796
d410cf58 797 i = 0;
83ae98f8 798
d410cf58 799 if (modname) {
800 memcpy(buf, modname, strlen(modname));
801 i += strlen(modname);
802 }
83ae98f8 803
d410cf58 804 /* Damn endianness. This must be little (LSB first) endian. */
805 buf[i++] = offset & 0xff;
806 buf[i++] = (offset >> 8) & 0xff;
807 buf[i++] = (offset >> 16) & 0xff;
808 buf[i++] = (offset >> 24) & 0xff;
809 buf[i++] = len & 0xff;
810 buf[i++] = (len >> 8) & 0xff;
811 buf[i++] = (len >> 16) & 0xff;
812 buf[i++] = (len >> 24) & 0xff;
83ae98f8 813
d410cf58 814 *bufret = buf;
815 *buflenret = i;
83ae98f8 816
d410cf58 817 } else {
83ae98f8 818
d410cf58 819 if (!(buf = malloc(len))) {
820 free(filename);
821 return -1;
822 }
83ae98f8 823
d410cf58 824 dvprintf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename);
5ac961d5 825
d410cf58 826 if (!(f = fopen(filename, "r"))) {
827 dperror("memrequest: fopen");
828 free(filename);
829 free(buf);
830 return -1;
831 }
b1eac25a 832
d410cf58 833 free(filename);
b1eac25a 834
d410cf58 835 if (fseek(f, offset, SEEK_SET) == -1) {
836 dperror("memrequest: fseek");
837 fclose(f);
838 free(buf);
839 return -1;
840 }
83ae98f8 841
d410cf58 842 if (fread(buf, len, 1, f) != 1) {
843 dperror("memrequest: fread");
844 fclose(f);
845 free(buf);
846 return -1;
847 }
b1eac25a 848
d410cf58 849 fclose(f);
850
851 *bufret = buf;
852 *buflenret = len;
853
854 }
855
856 return 0; /* success! */
b1eac25a 857}
858
859/*
860 * This will get an offset and a length. The client should read this
861 * data out of whatever AIM.EXE binary the user has provided (hopefully
862 * it matches the client information thats sent at login) and pass a
863 * buffer back to libfaim so it can hash the data and send it to AOL for
864 * inspection by the client police.
865 */
d410cf58 866static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
b1eac25a 867{
d410cf58 868 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
869 va_list ap;
870 fu32_t offset, len;
871 char *modname;
872 unsigned char *buf;
873 int buflen;
874
875 va_start(ap, fr);
876 offset = va_arg(ap, fu32_t);
877 len = va_arg(ap, fu32_t);
878 modname = va_arg(ap, char *);
879 va_end(ap);
b1eac25a 880
d410cf58 881 if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
b1eac25a 882
d410cf58 883 aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 884
d410cf58 885 free(buf);
b1eac25a 886
d410cf58 887 } else {
b1eac25a 888
d410cf58 889 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
b1eac25a 890
d410cf58 891 aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 892
d410cf58 893 }
b1eac25a 894
d410cf58 895 return 1;
b1eac25a 896}
897
d410cf58 898static void printuserflags(fu16_t flags)
9de3ca7e 899{
d410cf58 900 if (flags & AIM_FLAG_UNCONFIRMED)
901 dinlineprintf("UNCONFIRMED ");
902 if (flags & AIM_FLAG_ADMINISTRATOR)
903 dinlineprintf("ADMINISTRATOR ");
904 if (flags & AIM_FLAG_AOL)
905 dinlineprintf("AOL ");
906 if (flags & AIM_FLAG_OSCAR_PAY)
907 dinlineprintf("OSCAR_PAY ");
908 if (flags & AIM_FLAG_FREE)
909 dinlineprintf("FREE ");
910 if (flags & AIM_FLAG_AWAY)
911 dinlineprintf("AWAY ");
912 if (flags & AIM_FLAG_UNKNOWN40)
913 dinlineprintf("ICQ? ");
914 if (flags & AIM_FLAG_UNKNOWN80)
915 dinlineprintf("UNKNOWN80 ");
916 return;
9de3ca7e 917}
918
d410cf58 919static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
a15d82b1 920{
d410cf58 921 struct aim_userinfo_s *userinfo;
922 char *prof_encoding = NULL;
923 char *prof = NULL;
924 fu16_t inforeq = 0;
a15d82b1 925
d410cf58 926 va_list ap;
927 va_start(ap, fr);
928 userinfo = va_arg(ap, struct aim_userinfo_s *);
929 prof_encoding = va_arg(ap, char *);
930 prof = va_arg(ap, char *);
931 inforeq = va_arg(ap, fu16_t);
932 va_end(ap);
933
934 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
935 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
936 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
937 printuserflags(userinfo->flags);
938 dinlineprintf("\n");
939
940 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
941 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
942 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
943
944 if (inforeq == AIM_GETINFO_GENERALINFO) {
945 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
946 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
947 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
948 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
949 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
950 } else
951 dprintf("faimtest: userinfo: unknown info request\n");
952
953 return 1;
9de3ca7e 954}
955
d410cf58 956static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, const char *tmpstr)
d2587300 957{
d410cf58 958 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
d2587300 959
d410cf58 960 if (!strncmp(tmpstr, "disconnect", 10)) {
d2587300 961
d410cf58 962 logout(sess);
d2587300 963
d410cf58 964 } else if (strstr(tmpstr, "goodday")) {
7b91722d 965
d410cf58 966 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
7b91722d 967
d410cf58 968 } else if (strstr(tmpstr, "haveicon") && priv->buddyicon) {
969 struct aim_sendimext_args args;
970 static const char iconmsg[] = {"I have an icon"};
7b91722d 971
d410cf58 972 args.destsn = userinfo->sn;
973 args.flags = AIM_IMFLAGS_HASICON;
974 args.msg = iconmsg;
975 args.msglen = strlen(iconmsg);
976 args.iconlen = priv->buddyiconlen;
977 args.iconstamp = priv->buddyiconstamp;
978 args.iconsum = priv->buddyiconsum;
7b91722d 979
d410cf58 980 aim_send_im_ext(sess, conn, &args);
7b91722d 981
84e0ca17 982 } else if (strstr(tmpstr, "havefeat")) {
983 struct aim_sendimext_args args;
984 static const char featmsg[] = {"I have nifty features."};
985 fu8_t features[] = {0x01, 0x01, 0x01, 0x02, 0x42, 0x43, 0x44, 0x45};
986
987 args.destsn = userinfo->sn;
988 args.flags = AIM_IMFLAGS_CUSTOMFEATURES;
989 args.msg = featmsg;
990 args.msglen = strlen(featmsg);
991 args.features = features;
992 args.featureslen = sizeof(features);
993
994 aim_send_im_ext(sess, conn, &args);
995
d410cf58 996 } else if (strstr(tmpstr, "sendicon") && priv->buddyicon) {
d2587300 997
d410cf58 998 aim_send_icon(sess, conn, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum);
d2587300 999
d410cf58 1000 } else if (strstr(tmpstr, "warnme")) {
d2587300 1001
d410cf58 1002 dprintf("faimtest: icbm: sending non-anon warning\n");
1003 aim_send_warning(sess, conn, userinfo->sn, 0);
d2587300 1004
d410cf58 1005 } else if (strstr(tmpstr, "anonwarn")) {
d2587300 1006
d410cf58 1007 dprintf("faimtest: icbm: sending anon warning\n");
1008 aim_send_warning(sess, conn, userinfo->sn, AIM_WARN_ANON);
d2587300 1009
d410cf58 1010 } else if (strstr(tmpstr, "setdirectoryinfo")) {
d2587300 1011
d410cf58 1012 dprintf("faimtest: icbm: sending backwards profile data\n");
1013 aim_setdirectoryinfo(sess, conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
d2587300 1014
d410cf58 1015 } else if (strstr(tmpstr, "setinterests")) {
d2587300 1016
d410cf58 1017 dprintf("faimtest: icbm: setting fun interests\n");
1018 aim_setuserinterests(sess, conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
d2587300 1019
d410cf58 1020 } else if (!strncmp(tmpstr, "getfile", 7)) {
d2587300 1021
d410cf58 1022 if (!priv->ohcaptainmycaptain) {
d2587300 1023
d410cf58 1024 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!");
d2587300 1025
d410cf58 1026 } else
1027 getfile_start(sess, conn, (strlen(tmpstr) < 8)?priv->ohcaptainmycaptain:tmpstr+8);
1028
1029 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
d2587300 1030
d410cf58 1031 aim_bos_reqservice(sess, conn, AIM_CONN_TYPE_CHATNAV);
d2587300 1032
d410cf58 1033 } else if (!strncmp(tmpstr, "create", 6)) {
d2587300 1034
d410cf58 1035 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
d2587300 1036
d410cf58 1037 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1038 aim_conn_t *chatnavconn;
d2587300 1039
d410cf58 1040 if ((chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)))
1041 aim_conn_kill(sess, &chatnavconn);
d2587300 1042
d410cf58 1043 } else if (!strncmp(tmpstr, "join", 4)) {
d2587300 1044
d410cf58 1045 aim_chat_join(sess, conn, 0x0004, "worlddomination", 0x0000);
d2587300 1046
d410cf58 1047 } else if (!strncmp(tmpstr, "leave", 5)) {
d2587300 1048
d410cf58 1049 aim_chat_leaveroom(sess, "worlddomination");
d2587300 1050
d410cf58 1051 } else if (!strncmp(tmpstr, "getinfo", 7)) {
d2587300 1052
d410cf58 1053 aim_getinfo(sess, conn, "75784102", AIM_GETINFO_GENERALINFO);
1054 aim_getinfo(sess, conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
1055 aim_getinfo(sess, conn, "midendian", AIM_GETINFO_GENERALINFO);
1056 aim_getinfo(sess, conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
d2587300 1057
c5f5b7f1 1058 } else if (strstr(tmpstr, "open directim")) {
d2587300 1059
c5f5b7f1 1060 directim_start(sess, conn, userinfo->sn);
d2587300 1061
3e9e6e14 1062 } else if(strstr(tmpstr, "lookup")) {
d2587300 1063
3e9e6e14 1064 aim_usersearch_address(sess, conn, "mid@auk.cx");
d2587300 1065
d410cf58 1066 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
d2587300 1067
d410cf58 1068 aim_send_im(sess, conn, priv->ohcaptainmycaptain, 0, "sendmsg 7900");
d2587300 1069
d410cf58 1070 } else if (!strncmp(tmpstr, "reqauth", 7)) {
d2587300 1071
d410cf58 1072 aim_bos_reqservice(sess, conn, AIM_CONN_TYPE_AUTH);
d2587300 1073
d410cf58 1074 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
d2587300 1075
d410cf58 1076 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
d2587300 1077
d410cf58 1078 } else if (!strncmp(tmpstr, "reqemail", 8)) {
d2587300 1079
d410cf58 1080 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
d2587300 1081
d410cf58 1082 } else if (!strncmp(tmpstr, "changepass", 8)) {
d2587300 1083
d410cf58 1084 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
d2587300 1085
d410cf58 1086 } else if (!strncmp(tmpstr, "setemail", 8)) {
d2587300 1087
d410cf58 1088 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
d2587300 1089
d410cf58 1090 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1091 int i;
d2587300 1092
d410cf58 1093 i = atoi(tmpstr+8);
1094 if (i < 10000) {
1095 char *newbuf;
1096 int z;
d2587300 1097
d410cf58 1098 newbuf = malloc(i+1);
1099 for (z = 0; z < i; z++)
1100 newbuf[z] = (z % 10)+0x30;
1101 newbuf[i] = '\0';
1102 aim_send_im(sess, conn, userinfo->sn, 0, newbuf);
1103 free(newbuf);
1104 }
d2587300 1105
d410cf58 1106 } else {
d2587300 1107
d410cf58 1108 dprintf("unknown command.\n");
1109 aim_add_buddy(sess, conn, userinfo->sn);
d2587300 1110
d410cf58 1111 }
d2587300 1112
d410cf58 1113 return 0;
d2587300 1114}
1115
9de3ca7e 1116/*
d410cf58 1117 * Channel 1: Standard Message
9de3ca7e 1118 */
d410cf58 1119static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, va_list ap)
9de3ca7e 1120{
e1b8c575 1121 struct faimtest_priv *priv = (struct faimtest_priv *)sess->aux_data;
d410cf58 1122 char *tmpstr;
1123 struct aim_incomingim_ch1_args *args;
1124 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
1125 char realmsg[8192+1] = {""};
7a449b5d 1126
d410cf58 1127 args = va_arg(ap, struct aim_incomingim_ch1_args *);
1128 va_end(ap);
7a449b5d 1129
84e0ca17 1130 clienttype = aim_fingerprintclient(args->features, args->featureslen);
9de3ca7e 1131
d410cf58 1132 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
1133 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
1134 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1135 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
1136 printuserflags(userinfo->flags);
1137 dinlineprintf("\n");
7392c79f 1138
d410cf58 1139 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1140 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1141 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1142 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
1143
1144 dprintf("faimtest: icbm: icbmflags = ");
1145 if (args->icbmflags & AIM_IMFLAGS_AWAY)
1146 dinlineprintf("away ");
1147 if (args->icbmflags & AIM_IMFLAGS_ACK)
1148 dinlineprintf("ackrequest ");
1149 if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)
1150 dinlineprintf("buddyreq ");
1151 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1152 dinlineprintf("hasicon ");
1153 dinlineprintf("\n");
7392c79f 1154
d410cf58 1155 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", args->flag1, args->flag2);
646c6b52 1156
d410cf58 1157 /*
1158 * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1159 * characters with their equivelent HTML entity.
1160 */
1161 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1162 int i;
7392c79f 1163
d410cf58 1164 for (i = 0; i < args->msglen; i += 2) {
1165 fu16_t uni;
7392c79f 1166
d410cf58 1167 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
7392c79f 1168
d410cf58 1169 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
7392c79f 1170
d410cf58 1171 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
7392c79f 1172
d410cf58 1173 } else { /* something else, do UNICODE entity */
7392c79f 1174
d410cf58 1175 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
7392c79f 1176
d410cf58 1177 }
871e2fd0 1178
d410cf58 1179 }
871e2fd0 1180
d410cf58 1181 } else {
1182
1183 /*
1184 * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1185 * no need to do anything special here. Most
1186 * terminals/whatever will be able to display such characters
1187 * unmodified.
1188 *
1189 * Beware that PC-ASCII 128 through 159 are _not_ actually
1190 * defined in ASCII or ISO 8859-1, and you should send them as
1191 * UNICODE. WinAIM will send these characters in a UNICODE
1192 * message, so you need to do so as well.
1193 *
1194 * You may not think it necessary to handle UNICODE messages.
1195 * You're probably wrong. For one thing, Microsoft "Smart
1196 * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1197 * but real UNICODE). If you don't parse UNICODE at all, your
1198 * users will get a blank message instead of the message
1199 * containing Smart Quotes.
1200 *
1201 */
1202 strncpy(realmsg, args->msg, sizeof(realmsg));
1203 }
3b101546 1204
d410cf58 1205 dvprintf("faimtest: icbm: message: %s\n", realmsg);
7392c79f 1206
d410cf58 1207 if (args->icbmflags & AIM_IMFLAGS_HASICON)
1208 aim_send_im(sess, conn, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon");
7392c79f 1209
d410cf58 1210 if (realmsg) {
1211 int i = 0;
9de3ca7e 1212
d410cf58 1213 while (realmsg[i] == '<') {
1214 if (realmsg[i] == '<') {
1215 while (realmsg[i] != '>')
1216 i++;
1217 i++;
1218 }
1219 }
1220 tmpstr = realmsg+i;
9de3ca7e 1221
d410cf58 1222 faimtest_handlecmd(sess, conn, userinfo, tmpstr);
64c78745 1223
d410cf58 1224 }
9de3ca7e 1225
e1b8c575 1226 if (priv->buddyicon && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ))
1227 aim_send_icon(sess, conn, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum);
1228
d410cf58 1229 return 1;
9de3ca7e 1230}
1231
d410cf58 1232/*
1233 * Channel 2: Rendevous Request
1234 */
1235static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, va_list ap)
9de3ca7e 1236{
d410cf58 1237 struct aim_incomingim_ch2_args *args;
9de3ca7e 1238
d410cf58 1239 args = va_arg(ap, struct aim_incomingim_ch2_args *);
1240 va_end(ap);
9de3ca7e 1241
d410cf58 1242 if (args->reqclass == AIM_CAPS_VOICE) {
96f8b1ed 1243
d410cf58 1244 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1245 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1246 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
1247 printuserflags(userinfo->flags);
1248 dinlineprintf("\n");
ee49b735 1249
d410cf58 1250 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1251 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
e80a0fa9 1252
d410cf58 1253 } else if (args->reqclass == AIM_CAPS_GETFILE) {
1254
1255 getfile_requested(sess, conn, userinfo, args);
1256
1257 } else if (args->reqclass == AIM_CAPS_SENDFILE) {
96f8b1ed 1258
d410cf58 1259 dprintf("faimtest: send file!\n");
1449ad2b 1260
d410cf58 1261 } else if (args->reqclass == AIM_CAPS_CHAT) {
1449ad2b 1262
d410cf58 1263 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1264 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1265 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
1266 printuserflags(userinfo->flags);
1267 dinlineprintf("\n");
355229fe 1268
d410cf58 1269 /* we dont get membersince on chat invites! */
1270 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1271 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
1449ad2b 1272
d410cf58 1273 dvprintf("faimtest: chat invitation: message = %s\n", args->info.chat.msg);
1274 dvprintf("faimtest: chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1275 dvprintf("faimtest: chat invitation: encoding = %s\n", args->info.chat.encoding);
1276 dvprintf("faimtest: chat invitation: language = %s\n", args->info.chat.lang);
1277 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1278 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1279 dvprintf("faimtest: chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name);
96f8b1ed 1280
d410cf58 1281 /* Automatically join room... */
1282 aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance);
96f8b1ed 1283
d410cf58 1284 } else if (args->reqclass == AIM_CAPS_IMIMAGE) {
355229fe 1285
d410cf58 1286 dprintf("faimtest: icbm: rendezvous imimage\n");
96f8b1ed 1287
d410cf58 1288 directim_requested(sess, conn, userinfo, args);
96f8b1ed 1289
d410cf58 1290 } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
01b59e1e 1291
e1b8c575 1292 dvprintf("faimtest: Buddy Icon from %s, length = %lu\n", userinfo->sn, args->info.icon.length);
d410cf58 1293
1294 } else {
1295
1296 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", args->reqclass);
1297 }
355229fe 1298
1299 return 1;
01b59e1e 1300}
9de3ca7e 1301
d410cf58 1302static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
9de3ca7e 1303{
d410cf58 1304 fu16_t channel;
355229fe 1305 struct aim_userinfo_s *userinfo;
d410cf58 1306 va_list ap;
1307 int ret = 0;
9de3ca7e 1308
d410cf58 1309 va_start(ap, fr);
1310 channel = va_arg(ap, fu16_t);
355229fe 1311 userinfo = va_arg(ap, struct aim_userinfo_s *);
355229fe 1312
d410cf58 1313 if (channel == 1)
1314 ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, ap);
1315 else if (channel == 2)
1316 ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, ap);
1317 else
1318 dvprintf("unsupported channel 0x%04x\n", channel);
1319
1320 dvprintf("faimtest: icbm: done with ICBM handling (ret = %d)\n", ret);
355229fe 1321
1322 return 1;
9de3ca7e 1323}
1324
d410cf58 1325#ifdef MID_REWROTE_ALL_THE_CRAP
1326static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
01b59e1e 1327{
d410cf58 1328 fu16_t change = 0, perms, type;
1329 int length, str;
1330 char *val;
355229fe 1331 va_list ap;
9de3ca7e 1332
d410cf58 1333 va_start(ap, fr);
1334 perms = va_arg(ap, fu16_t);
1335 type = va_arg(ap, fu16_t);
1336 length = va_arg(ap, int);
1337 val = va_arg(ap, char *);
1338 str = va_arg(ap, int);
355229fe 1339 va_end(ap);
1340
d410cf58 1341 if (aimutil_get16(command->data+2) == 0x0005)
1342 change = 1;
1343
1344 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
355229fe 1345
1346 return 1;
01b59e1e 1347}
d410cf58 1348#endif
0c20631f 1349
d410cf58 1350static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1351{
355229fe 1352 struct aim_userinfo_s *userinfo;
0c20631f 1353
d410cf58 1354 va_list ap;
1355 va_start(ap, fr);
355229fe 1356 userinfo = va_arg(ap, struct aim_userinfo_s *);
1357 va_end(ap);
0c20631f 1358
d410cf58 1359 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1360 time(NULL),
1361 userinfo->sn, userinfo->flags,
1362 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1363 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1364 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1365 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1366 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1367 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1368 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1369 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1370 userinfo->capabilities);
355229fe 1371 return 1;
0c20631f 1372}
1373
d410cf58 1374static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1375{
355229fe 1376 struct aim_userinfo_s *userinfo;
d410cf58 1377 va_list ap;
1378
1379 va_start(ap, fr);
355229fe 1380 userinfo = va_arg(ap, struct aim_userinfo_s *);
1381 va_end(ap);
37ee990e 1382
d410cf58 1383 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1384 time(NULL),
1385 userinfo->sn, userinfo->flags,
1386 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1387 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1388 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1389 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1390 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1391 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1392 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1393 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1394 userinfo->capabilities);
355229fe 1395
1396 return 1;
0c20631f 1397}
1398
d410cf58 1399static int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1400{
355229fe 1401 va_list ap;
d410cf58 1402 fu16_t reason;
355229fe 1403
d410cf58 1404 va_start(ap, fr);
1405 reason = va_arg(ap, fu16_t);
1406 va_end(ap);
355229fe 1407
d410cf58 1408 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
355229fe 1409
1410 return 1;
0c20631f 1411}
1412
d410cf58 1413static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
0c20631f 1414{
355229fe 1415 va_list ap;
d410cf58 1416 char *destsn;
1417 fu16_t reason;
355229fe 1418
d410cf58 1419 va_start(ap, fr);
1420 reason = va_arg(ap, fu16_t);
1421 destsn = va_arg(ap, char *);
355229fe 1422 va_end(ap);
1423
d410cf58 1424 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
0c20631f 1425
355229fe 1426 return 1;
0c20631f 1427}
1428
d410cf58 1429static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
5e02cf44 1430{
355229fe 1431 va_list ap;
d410cf58 1432 char *destsn;
1433 fu16_t reason;
5e02cf44 1434
d410cf58 1435 va_start(ap, fr);
1436 reason = va_arg(ap, fu16_t);
1437 destsn = va_arg(ap, char *);
355229fe 1438 va_end(ap);
5e02cf44 1439
d410cf58 1440 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
d32954e7 1441
355229fe 1442 return 1;
5e02cf44 1443}
e5012450 1444
d410cf58 1445static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1446{
1447 static char *missedreasons[] = {
1448 "Invalid (0)",
1449 "Message too large",
1450 "Rate exceeded",
1451 "Evil Sender",
1452 "Evil Receiver"
1453 };
1454 static int missedreasonslen = 5;
e5012450 1455
d410cf58 1456 va_list ap;
1457 fu16_t chan, nummissed, reason;
1458 struct aim_userinfo_s *userinfo;
e5012450 1459
d410cf58 1460 va_start(ap, fr);
1461 chan = va_arg(ap, fu16_t);
1462 userinfo = va_arg(ap, struct aim_userinfo_s *);
1463 nummissed = va_arg(ap, fu16_t);
1464 reason = va_arg(ap, fu16_t);
1465 va_end(ap);
e5012450 1466
d410cf58 1467 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 1468
355229fe 1469 return 1;
e5012450 1470}
1a8c261b 1471
1472/*
646c6b52 1473 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 1474 */
d410cf58 1475static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1a8c261b 1476{
355229fe 1477 va_list ap;
d410cf58 1478 fu16_t type;
355229fe 1479 char *sn = NULL;
1a8c261b 1480
d410cf58 1481 va_start(ap, fr);
1482 type = va_arg(ap, fu16_t);
355229fe 1483 sn = va_arg(ap, char *);
1484 va_end(ap);
1a8c261b 1485
355229fe 1486 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 1487
355229fe 1488 return 1;
1a8c261b 1489}
1490
d410cf58 1491static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
871e2fd0 1492{
d410cf58 1493 static char *codes[5] = {
1494 "invalid",
1495 "change",
1496 "warning",
1497 "limit",
1498 "limit cleared"
1499 };
355229fe 1500 va_list ap;
d410cf58 1501 fu16_t code, rateclass;
1502 fu32_t windowsize, clear, alert, limit, disconnect;
1503 fu32_t currentavg, maxavg;
37ee990e 1504
d410cf58 1505 va_start(ap, fr);
37ee990e 1506
d410cf58 1507 /* See code explanations below */
1508 code = va_arg(ap, fu16_t);
37ee990e 1509
d410cf58 1510 /*
1511 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1512 */
1513 rateclass = va_arg(ap, fu16_t);
37ee990e 1514
d410cf58 1515 /*
1516 * Not sure what this is exactly. I think its the temporal
1517 * relation factor (ie, how to make the rest of the numbers
1518 * make sense in the real world).
1519 */
1520 windowsize = va_arg(ap, fu32_t);
646c6b52 1521
d410cf58 1522 /* Explained below */
1523 clear = va_arg(ap, fu32_t);
1524 alert = va_arg(ap, fu32_t);
1525 limit = va_arg(ap, fu32_t);
1526 disconnect = va_arg(ap, fu32_t);
1527 currentavg = va_arg(ap, fu32_t);
1528 maxavg = va_arg(ap, fu32_t);
646c6b52 1529
d410cf58 1530 va_end(ap);
646c6b52 1531
646c6b52 1532
d410cf58 1533 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",
1534 (code < 5)?codes[code]:"invalid",
1535 rateclass,
1536 currentavg, maxavg,
1537 alert, clear,
1538 limit, disconnect,
1539 windowsize);
1540
1541 if (code == AIM_RATE_CODE_CHANGE) {
1542 /*
1543 * Not real sure when these get sent.
1544 */
1545 if (currentavg >= clear)
1546 aim_conn_setlatency(fr->conn, 0);
1547
1548 } else if (code == AIM_RATE_CODE_WARNING) {
1549 /*
1550 * We start getting WARNINGs the first time we go below the
1551 * 'alert' limit (currentavg < alert) and they stop when
1552 * either we pause long enough for currentavg to go above
1553 * 'clear', or until we flood it bad enough to go below
1554 * 'limit' (and start getting LIMITs instead) or even further
1555 * and go below 'disconnect' and get disconnected completely
1556 * (and won't be able to login right away either).
1557 */
1558 aim_conn_setlatency(fr->conn, windowsize/4); /* XXX this is bogus! */
1559
1560 } else if (code == AIM_RATE_CODE_LIMIT) {
1561 /*
1562 * When we hit LIMIT, messages will start getting dropped.
1563 */
1564 aim_conn_setlatency(fr->conn, windowsize/2); /* XXX this is bogus! */
1565
1566 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
1567 /*
1568 * The limit is cleared when curavg goes above 'clear'.
1569 */
1570 aim_conn_setlatency(fr->conn, 0);
1571 }
646c6b52 1572
d410cf58 1573 return 1;
78b3fb13 1574}
98c88242 1575
d410cf58 1576static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
98c88242 1577{
355229fe 1578 va_list ap;
d410cf58 1579 fu16_t newevil;
355229fe 1580 struct aim_userinfo_s *userinfo;
98c88242 1581
d410cf58 1582 va_start(ap, fr);
1583 newevil = va_arg(ap, fu16_t);
355229fe 1584 userinfo = va_arg(ap, struct aim_userinfo_s *);
1585 va_end(ap);
98c88242 1586
355229fe 1587 /*
1588 * Evil Notifications that are lacking userinfo->sn are anon-warns
1589 * if they are an evil increases, but are not warnings at all if its
1590 * a decrease (its the natural backoff happening).
1591 *
1592 * newevil is passed as an int representing the new evil value times
1593 * ten.
1594 */
1595 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
37ee990e 1596
355229fe 1597 return 1;
37ee990e 1598}
1599
d410cf58 1600static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1601{
355229fe 1602 va_list ap;
1603 char *address, *SNs;
1604 int i, num;
37ee990e 1605
d410cf58 1606 va_start(ap, fr);
355229fe 1607 address = va_arg(ap, char *);
1608 num = va_arg(ap, int);
1609 SNs = va_arg(ap, char *);
1610 va_end(ap);
37ee990e 1611
355229fe 1612 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
37ee990e 1613
355229fe 1614 for(i = 0; i < num; i++)
1615 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
1616 dinlineprintf("\n");
1617
1618 return 1;
37ee990e 1619}
1620
d410cf58 1621static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
37ee990e 1622{
355229fe 1623 va_list ap;
1624 char *address;
37ee990e 1625
d410cf58 1626 va_start(ap, fr);
355229fe 1627 address = va_arg(ap, char *);
1628 va_end(ap);
98c88242 1629
355229fe 1630 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1631
1632 return 1;
78b3fb13 1633}
d410cf58 1634
1635void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
1636{
1637
1638 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1639
1640 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
1641 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp_bos, 0); /* rate info */
1642 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
1643 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
1644 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
1645 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
1646 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
1647 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
1648 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
1649 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1650 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
1651 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, faimtest_locrights, 0);
1652 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
1653 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
1654 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
1655 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1656 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
1657 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
1658 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
1659 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
1660 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
1661 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
1662 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
1663 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
1664 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
1665
1666 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
1667 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
1668 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
1669
1670#ifdef MID_REWROTE_ALL_THE_CRAP
1671 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
1672#endif
1673
1674 return;
1675}
1676
This page took 2.709388 seconds and 5 git commands to generate.