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