]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Thu May 10 17:37:23 PDT 2001
[libfaim.git] / utils / faimtest / faimtest.c
CommitLineData
9de3ca7e 1/*
2 * -----------------------------------------------------------
3 * ProtoFAIM: v1.xx.xxplxx
4 * -----------------------------------------------------------
5 *
6 * This is ProtoFAIM v1.xx.xxplxx!!! Its nearly completely
7 * different than that ugly thing called v0. This app is
8 * compatible with the latest version of the libfaim library.
9 * Work is continuing.
10 *
11 * ProtoFAIM should only be used for two things...
12 * 1) Testing the libfaim backend.
13 * 2) For reference on the libfaim API when developing clients.
14 *
15 * Its very ugly. Probably always will be. Nothing is more
16 * ugly than the backend itself, however.
17 *
18 * -----------------------------------------------------------
19 *
20 * I'm releasing this code and all it's associated linkage
21 * under the GNU General Public License. For more information,
22 * please refer to http://www.fsf.org. For any questions,
23 * please contact me at the address below.
24 *
25 * Most everything:
646c6b52 26 * (c) 1998 Adam Fritzler, PST, mid@zigamoprh.net
9de3ca7e 27 *
28 * The password algorithms
646c6b52 29 * (c) 1998 Brock Wilcox, awwaiid@zigamorph.net
9de3ca7e 30 *
31 * THERE IS NO CODE FROM AOL'S AIM IN THIS CODE, NOR
32 * WAS THERE ANY DISASSEMBLAGE TO DEFINE PROTOCOL. All
33 * information was gained through painstakingly comparing
34 * TCP dumps while the AIM Java client was running. Nothing
35 * more than that, except for a lot of experimenting.
36 *
37 * -----------------------------------------------------------
38 *
39 */
40
b562f484 41#include "faimtest.h"
83ae98f8 42#include <sys/stat.h>
397055b1 43
37ee990e 44static char *dprintf_ctime(void)
45{
46 static char retbuf[64];
47 struct tm *lt;
48 struct timeval tv;
49 struct timezone tz;
50
51 gettimeofday(&tv, &tz);
52 lt = localtime((time_t *)&tv.tv_sec);
53 strftime(retbuf, 64, "%a %b %e %H:%M:%S %Z %Y", lt);
54 return retbuf;
55}
56
646c6b52 57#define DPRINTF_OUTSTREAM stdout
37ee990e 58#define dprintf(x) { \
646c6b52 59 fprintf(DPRINTF_OUTSTREAM, "%s %s: " x, dprintf_ctime(), "faimtest"); \
60 fflush(DPRINTF_OUTSTREAM); \
37ee990e 61}
62#define dvprintf(x, y...) { \
646c6b52 63 fprintf(DPRINTF_OUTSTREAM, "%s %s: " x, dprintf_ctime(), "faimtest", y); \
64 fflush(DPRINTF_OUTSTREAM); \
37ee990e 65}
66#define dinlineprintf(x) { \
646c6b52 67 fprintf(DPRINTF_OUTSTREAM, x); \
68 fflush(DPRINTF_OUTSTREAM); \
37ee990e 69}
70#define dvinlineprintf(x, y...) { \
646c6b52 71 fprintf(DPRINTF_OUTSTREAM, x, y); \
72 fflush(DPRINTF_OUTSTREAM); \
37ee990e 73}
74#define dperror(x) dvprintf("%s: %s\n", x, strerror(errno));
75
397055b1 76int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...);
77int faimtest_parse_offgoing(struct aim_session_t *, struct command_rx_struct *, ...);
78int faimtest_parse_login_phase3d_f(struct aim_session_t *, struct command_rx_struct *, ...);
b1eac25a 79static int faimtest_parse_authresp(struct aim_session_t *, struct command_rx_struct *, ...);
397055b1 80int faimtest_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *command, ...);
81int faimtest_parse_userinfo(struct aim_session_t *, struct command_rx_struct *command, ...);
82int faimtest_handleredirect(struct aim_session_t *, struct command_rx_struct *command, ...);
64c78745 83int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
397055b1 84int faimtest_serverready(struct aim_session_t *, struct command_rx_struct *command, ...);
ee49b735 85int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...);
397055b1 86int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
1a8c261b 87int faimtest_parse_msgack(struct aim_session_t *, struct command_rx_struct *command, ...);
01b59e1e 88int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
89int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
0c20631f 90int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
91int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
92int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
93int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
94int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
5e02cf44 95int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
e5012450 96int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
49c8a2fa 97
7392c79f 98int faimtest_directim_request(struct aim_session_t *sess, struct command_rx_struct *command, ...);
99int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
100int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
101int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...);
102int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
103int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
646c6b52 104
871e2fd0 105int faimtest_getfile_filereq(struct aim_session_t *sess, struct command_rx_struct *command, ...);
106int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...);
107int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...);
108int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
37ee990e 109int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
110int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
111int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...);
646c6b52 112int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...);
113int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...);
871e2fd0 114
1a8c261b 115int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
98c88242 116int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...);
37ee990e 117int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...);
118int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...);
96f8b1ed 119int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
120int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
121int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
1449ad2b 122int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
96f8b1ed 123
124static char *msgerrreasons[] = {
125 "Invalid error",
126 "Invalid SNAC",
127 "Rate to host",
128 "Rate to client",
129 "Not logged on",
130 "Service unavailable",
131 "Service not defined",
132 "Obsolete SNAC",
133 "Not supported by host",
134 "Not supported by client",
135 "Refused by client",
136 "Reply too big",
137 "Responses lost",
138 "Request denied",
139 "Busted SNAC payload",
140 "Insufficient rights",
141 "In local permit/deny",
142 "Too evil (sender)",
143 "Too evil (receiver)",
144 "User temporarily unavailable",
145 "No match",
146 "List overflow",
147 "Request ambiguous",
148 "Queue full",
149 "Not while on AOL"};
150static int msgerrreasonslen = 25;
7392c79f 151
b1eac25a 152static char *aimbinarypath = NULL;
22517493 153static char *screenname,*password,*server=NULL;
b562f484 154static char *proxy = NULL, *proxyusername = NULL, *proxypass = NULL;
37ee990e 155static char *ohcaptainmycaptain = NULL;
ee49b735 156static int connected = 0;
22517493 157
b562f484 158struct aim_session_t aimsess;
159int keepgoing = 1;
160
161static FILE *listingfile;
162static char *listingpath;
646c6b52 163
164static void faimtest_debugcb(struct aim_session_t *sess, int level, const char *format, va_list va)
165{
166
167 vfprintf(stderr, format, va);
168
169 return;
170}
37ee990e 171
f0a7908e 172int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
173{
9f1a4013 174 va_list ap;
175 unsigned short interval = 0;
176
177 va_start(ap, command);
178 interval = va_arg(ap, int);
179 va_end(ap);
180
181 dvprintf("aim: minimum report interval: %d (seconds?)\n", interval);
182
f0a7908e 183 return 1;
184}
185
22517493 186int faimtest_flapversion(struct aim_session_t *sess, struct command_rx_struct *command, ...)
187{
188
37ee990e 189 dvprintf("faimtest: using FLAP version %u\n", aimutil_get32(command->data));
22517493 190
191#if 0
192 /*
193 * This is an alternate location for starting the login process.
194 */
195 /* XXX should do more checking to make sure its really the right AUTH conn */
196 if (command->conn->type == AIM_CONN_TYPE_AUTH) {
197 /* do NOT send a connack/flapversion, request_login will send it if needed */
198 aim_request_login(sess, command->conn, screenname);
37ee990e 199 dprintf("faimtest: login request sent\n");
22517493 200 }
201#endif
202
203 return 1;
204}
205
206/*
207 * This is a frivilous callback. You don't need it. I only used it for
208 * debugging non-blocking connects.
209 *
210 * If packets are sent to a conn before its fully connected, they
211 * will be queued and then transmitted when the connection completes.
212 *
213 */
214int faimtest_conncomplete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
215{
216 va_list ap;
217 struct aim_conn_t *conn;
218
219 va_start(ap, command);
220 conn = va_arg(ap, struct aim_conn_t *);
221 va_end(ap);
222
223 if (conn)
37ee990e 224 dvprintf("faimtest: connection on %d completed\n", conn->fd);
22517493 225
226 return 1;
227}
228
999b6d5f 229#ifdef _WIN32
230/*
231 * This is really all thats needed to link against libfaim on win32.
232 *
233 * Note that this particular version of faimtest has never been tested
234 * on win32, but I'm fairly sure it should.
235 */
236int initwsa(void)
237{
238 WORD wVersionRequested;
239 WSADATA wsaData;
240
241 wVersionRequested = MAKEWORD(2,2);
242 return WSAStartup(wVersionRequested, &wsaData);
243}
244#endif /* _WIN32 */
245
b562f484 246int faimtest_init(void)
247{
248 struct aim_conn_t *stdinconn = NULL;
249
250 if (!(stdinconn = aim_newconn(&aimsess, 0, NULL))) {
251 dprintf("unable to create connection for stdin!\n");
252 return -1;
253 }
254
255 stdinconn->fd = STDIN_FILENO;
256
257 return 0;
258}
259
260int logout(void)
261{
d2587300 262
263 if (ohcaptainmycaptain)
a2244dd9 264 aim_send_im(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS), ohcaptainmycaptain, 0, "ta ta...", strlen("ta ta..."));
d2587300 265
9f1a4013 266 aim_session_kill(&aimsess);
b562f484 267
268 if (faimtest_init() == -1)
269 dprintf("faimtest_init failed\n");
270
271 return 0;
272}
273
274int login(const char *sn, const char *passwd)
275{
276 struct aim_conn_t *authconn;
277
278 if (sn)
279 screenname = strdup(sn);
280 if (passwd)
281 password = strdup(passwd);
282
283 if (proxy)
284 aim_setupproxy(&aimsess, proxy, proxyusername, proxypass);
285
286 if (!screenname || !password) {
287 dprintf("need SN and password\n");
288 return -1;
289 }
290
291 if (!(authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER))) {
292 dprintf("faimtest: internal connection error while in aim_login. bailing out.\n");
293 return -1;
294 } else if (authconn->fd == -1) {
295 if (authconn->status & AIM_CONN_STATUS_RESOLVERR) {
296 dprintf("faimtest: could not resolve authorizer name\n");
297 } else if (authconn->status & AIM_CONN_STATUS_CONNERR) {
298 dprintf("faimtest: could not connect to authorizer\n");
299 }
300 aim_conn_kill(&aimsess, &authconn);
301 return -1;
302 }
303
304 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
305 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
306 aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
307 aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
308
309 aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
310
311 /* If the connection is in progress, this will just be queued */
312 aim_request_login(&aimsess, authconn, screenname);
313 dprintf("faimtest: login request sent\n");
314
315 return 0;
316}
317
37ee990e 318int main(int argc, char **argv)
9de3ca7e 319{
b562f484 320 struct aim_conn_t *waitingconn = NULL;
37ee990e 321 int i;
b8d0da45 322 int selstat = 0;
9bf14d44 323 static int faimtest_mode = 0;
d32954e7 324 struct timeval tv;
325 time_t lastnop = 0;
b8d0da45 326
37ee990e 327 screenname = getenv("SCREENNAME");
328 password = getenv("PASSWORD");
f1a5efe0 329 server = getenv("AUTHSERVER");
bb0dc593 330 proxy = getenv("SOCKSPROXY");
331 proxyusername = getenv("SOCKSNAME");
332 proxypass = getenv("SOCKSPASS");
333
871e2fd0 334 listingpath = getenv("LISTINGPATH");
871e2fd0 335
b1eac25a 336 while ((i = getopt(argc, argv, "u:p:a:U:P:A:l:c:hoOb:")) != EOF) {
37ee990e 337 switch (i) {
338 case 'u': screenname = optarg; break;
339 case 'p': password = optarg; break;
340 case 'a': server = optarg; break;
341 case 'U': proxyusername = optarg; break;
342 case 'P': proxypass = optarg; break;
343 case 'A': proxy = optarg; break;
344 case 'l': listingpath = optarg; break;
345 case 'c': ohcaptainmycaptain = optarg; break;
9bf14d44 346 case 'o': faimtest_mode = 1; break; /* half old interface */
347 case 'O': faimtest_mode = 2; break; /* full old interface */
b1eac25a 348 case 'b': aimbinarypath = optarg; break;
37ee990e 349 case 'h':
350 default:
37ee990e 351 printf("faimtest\n");
352 printf(" Options: \n");
353 printf(" -u name Screen name ($SCREENNAME)\n");
354 printf(" -p passwd Password ($PASSWORD)\n");
355 printf(" -a host:port Authorizer ($AUTHSERVER)\n");
356 printf(" -U name Proxy user name ($SOCKSPROXY)\n");
357 printf(" -P passwd Proxy password ($SOCKSNAME)\n");
358 printf(" -A host:port Proxy host ($SOCKSPASS)\n");
359 printf(" -l path Path to listing file ($LISTINGPATH)\n");
360 printf(" -c name Screen name of owner\n");
9bf14d44 361 printf(" -o Login at startup, then prompt\n");
362 printf(" -O Login, never give prompt\n");
83ae98f8 363 printf(" -b path Path to AIM 3.5.1670 binaries\n");
37ee990e 364 exit(0);
365 }
366 }
367
999b6d5f 368#ifdef _WIN32
369 if (initwsa() != 0) {
37ee990e 370 dprintf("faimtest: could not initialize windows sockets\n");
999b6d5f 371 return -1;
372 }
373#endif /* _WIN32 */
374
22517493 375 /* Pass zero as flags if you want blocking connects */
00ef5271 376 aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 1);
646c6b52 377 aim_setdebuggingcb(&aimsess, faimtest_debugcb); /* still needed even if debuglevel = 0 ! */
68ac63c2 378
871e2fd0 379 if(listingpath) {
380 char *listingname;
381 if(!(listingname = (char *)calloc(1, strlen(listingpath)+strlen("/listing.txt")))) {
37ee990e 382 dperror("listingname calloc");
871e2fd0 383 exit(-1);
384 }
385 sprintf(listingname, "%s/listing.txt", listingpath);
386 if( (listingfile = fopen(listingname, "r")) == NULL) {
9bf14d44 387 dvprintf("Couldn't open %s... disabling that shit.\n", listingname);
871e2fd0 388 }
389
871e2fd0 390 free(listingname);
391 }
871e2fd0 392
b562f484 393 faimtest_init();
bb0dc593 394
9bf14d44 395 if (faimtest_mode < 2)
396 cmd_init();
397
398 if (faimtest_mode >= 1) {
399 if (login(screenname, password) == -1) {
400 if (faimtest_mode < 2)
401 cmd_uninit();
402 exit(-1);
403 }
404 }
9de3ca7e 405
b8d0da45 406 while (keepgoing) {
d32954e7 407
408 tv.tv_sec = 5;
409 tv.tv_usec = 0;
410
411 waitingconn = aim_select(&aimsess, &tv, &selstat);
412
413 if (connected && ((time(NULL) - lastnop) > 30)) {
414 lastnop = time(NULL);
d32954e7 415 aim_flap_nop(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS));
416 }
b8d0da45 417
b562f484 418 if (selstat == -1) { /* error */
9f1a4013 419 keepgoing = 0; /* fall through */
b562f484 420 } else if (selstat == 0) { /* no events pending */
d32954e7 421 ;
b562f484 422 } else if (selstat == 1) { /* outgoing data pending */
b8d0da45 423 aim_tx_flushqueue(&aimsess);
b562f484 424 } else if (selstat == 2) { /* incoming data pending */
9bf14d44 425 if ((faimtest_mode < 2) && (waitingconn->fd == STDIN_FILENO)) {
b562f484 426 cmd_gotkey();
7392c79f 427 } else {
b562f484 428 if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
429 if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
430 dprintf("connection error (rend out)\n");
431 aim_conn_kill(&aimsess, &waitingconn);
432 }
433 } else {
434 if (aim_get_command(&aimsess, waitingconn) >= 0) {
435 aim_rxdispatch(&aimsess);
436 } else {
437 dvprintf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
438 /* we should have callbacks for all these, else the library will do the conn_kill for us. */
439 if(waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
440 dprintf("connection error: rendezvous connection. you forgot register a disconnect callback, right?\n");
441 aim_conn_kill(&aimsess, &waitingconn);
442 } else
443 aim_conn_kill(&aimsess, &waitingconn);
444 if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
445 dprintf("major connection error\n");
9bf14d44 446 if (faimtest_mode == 2)
447 break;
b562f484 448 }
449 }
7392c79f 450 }
451 }
9de3ca7e 452 }
b8d0da45 453 }
9de3ca7e 454
9de3ca7e 455 /* close up all connections, dead or no */
9f1a4013 456 aim_session_kill(&aimsess);
9de3ca7e 457
9bf14d44 458 if (faimtest_mode < 2) {
459 printf("\n");
460 cmd_uninit();
461 }
b562f484 462
9de3ca7e 463 /* Get out */
464 exit(0);
465}
466
c78446b5 467int faimtest_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
468{
469
470 switch(command->conn->type) {
471 case AIM_CONN_TYPE_BOS: {
472 /* this is the new buddy list */
37ee990e 473 char buddies[128];
c78446b5 474 /* this is the new profile */
37ee990e 475 char profile[256];
476
477 /* Caution: Buddy1 and Buddy2 are real people! (who I don't know) */
478 snprintf(buddies, sizeof(buddies), "Buddy1&Buddy2&%s&", ohcaptainmycaptain?ohcaptainmycaptain:"blah");
479 snprintf(profile, sizeof(profile), "Hello.<br>My captain is %s. They were dumb enough to leave this message in their client, or they are using faimtest. Shame on them.", ohcaptainmycaptain);
c78446b5 480
481 aim_bos_ackrateresp(sess, command->conn); /* ack rate info response */
482 aim_bos_reqpersonalinfo(sess, command->conn);
483 aim_bos_reqlocaterights(sess, command->conn);
e80a0fa9 484 aim_bos_setprofile(sess, command->conn, profile, NULL, AIM_CAPS_BUDDYICON | AIM_CAPS_CHAT | AIM_CAPS_VOICE | AIM_CAPS_GETFILE | AIM_CAPS_SENDFILE | AIM_CAPS_IMIMAGE /*| AIM_CAPS_GAMES | AIM_CAPS_SAVESTOCKS*/);
c78446b5 485 aim_bos_reqbuddyrights(sess, command->conn);
486
487 /* send the buddy list and profile (required, even if empty) */
488 aim_bos_setbuddylist(sess, command->conn, buddies);
489
490 /* dont really know what this does */
491 aim_addicbmparam(sess, command->conn);
492 aim_bos_reqicbmparaminfo(sess, command->conn);
493
494 aim_bos_reqrights(sess, command->conn);
495 /* set group permissions -- all user classes */
a15d82b1 496 aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS);
e80a0fa9 497 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE);
c78446b5 498
499 break;
500 }
64c78745 501 case AIM_CONN_TYPE_AUTH:
502 aim_bos_ackrateresp(sess, command->conn);
503 aim_auth_clientready(sess, command->conn);
504 dprintf("faimtest: connected to authorization/admin service\n");
505 break;
c78446b5 506
507 default:
37ee990e 508 dvprintf("faimtest: got rate response for unhandled connection type %04x\n", command->conn->type);
c78446b5 509 break;
510 }
511
512 return 1;
513}
514
00ef5271 515static int faimtest_icbmparaminfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
516{
517 unsigned long defflags, minmsginterval;
518 unsigned short maxicbmlen, maxsenderwarn, maxrecverwarn, maxchannel;
519 va_list ap;
520
521 va_start(ap, command);
522 maxchannel = va_arg(ap, unsigned short);
523 defflags = va_arg(ap, unsigned long);
524 maxicbmlen = va_arg(ap, unsigned short);
525 maxsenderwarn = va_arg(ap, unsigned short);
526 maxrecverwarn = va_arg(ap, unsigned short);
527 minmsginterval = va_arg(ap, unsigned long);
528 va_end(ap);
529
530 dvprintf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %ld\n", maxchannel, defflags, maxicbmlen, ((float)maxsenderwarn)/10.0, ((float)maxrecverwarn)/10.0, minmsginterval);
531
532 return 1;
533}
534
ee49b735 535int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...)
536{
537 int vercount, i;
538 unsigned char *versions;
539 va_list ap;
540
541 va_start(ap, command);
542 vercount = va_arg(ap, int); /* number of family/version pairs */
543 versions = va_arg(ap, unsigned char *);
544 va_end(ap);
545
37ee990e 546 dprintf("faimtest: SNAC versions supported by this host: ");
ee49b735 547 for (i = 0; i < vercount*4; i += 4)
37ee990e 548 dvinlineprintf("0x%04x:0x%04x ",
549 aimutil_get16(versions+i), /* SNAC family */
550 aimutil_get16(versions+i+2) /* Version number */);
551 dinlineprintf("\n");
ee49b735 552
553 return 1;
554}
555
64c78745 556int faimtest_accountconfirm(struct aim_session_t *sess, struct command_rx_struct *command, ...)
557{
558 int status;
559 va_list ap;
560
561 va_start(ap, command);
562 status = va_arg(ap, int); /* status code of confirmation request */
563 va_end(ap);
564
565 dvprintf("account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
566
567 return 1;
568}
569
397055b1 570int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 571{
ee49b735 572 int famcount, i;
573 unsigned short *families;
574 va_list ap;
26af6789 575
ee49b735 576 va_start(ap, command);
577 famcount = va_arg(ap, int);
578 families = va_arg(ap, unsigned short *);
579 va_end(ap);
9de3ca7e 580
37ee990e 581 dvprintf("faimtest: SNAC families supported by this host (type %d): ", command->conn->type);
ee49b735 582 for (i = 0; i < famcount; i++)
37ee990e 583 dvinlineprintf("0x%04x ", families[i]);
584 dinlineprintf("\n");
0c20631f 585
ee49b735 586 switch (command->conn->type) {
64c78745 587 case AIM_CONN_TYPE_AUTH:
588 aim_auth_setversions(sess, command->conn);
589 aim_bos_reqrate(sess, command->conn); /* request rate info */
590
591 dprintf("faimtest: done with auth ServerReady\n");
592 break;
593
ee49b735 594 case AIM_CONN_TYPE_BOS:
0c20631f 595
ee49b735 596 aim_setversions(sess, command->conn);
597 aim_bos_reqrate(sess, command->conn); /* request rate info */
7392c79f 598
37ee990e 599 dprintf("faimtest: done with BOS ServerReady\n");
ee49b735 600 break;
601
602 case AIM_CONN_TYPE_CHATNAV:
37ee990e 603 dprintf("faimtest: chatnav: got server ready\n");
ee49b735 604 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
605 aim_bos_reqrate(sess, command->conn);
606 aim_bos_ackrateresp(sess, command->conn);
607 aim_chatnav_clientready(sess, command->conn);
608 aim_chatnav_reqrights(sess, command->conn);
609
610 break;
611
612 case AIM_CONN_TYPE_CHAT:
613 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
614 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
615 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
616 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
617 aim_bos_reqrate(sess, command->conn);
618 aim_bos_ackrateresp(sess, command->conn);
619 aim_chat_clientready(sess, command->conn);
620 break;
621
622 case AIM_CONN_TYPE_RENDEZVOUS: /* empty */
623 break;
624
625 default:
64c78745 626 dvprintf("faimtest: unknown connection type on Host Online (0x%04x)\n", command->conn->type);
ee49b735 627 }
7392c79f 628
9de3ca7e 629 return 1;
630}
631
96f8b1ed 632int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
00f3b08b 633{
96f8b1ed 634 va_list ap;
635 unsigned short maxbuddies, maxwatchers;
636
637 va_start(ap, command);
e7fb57f5 638 maxbuddies = va_arg(ap, int);
639 maxwatchers = va_arg(ap, int);
96f8b1ed 640 va_end(ap);
641
37ee990e 642 dvprintf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
96f8b1ed 643
644 return 1;
645}
646
c78446b5 647int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
648{
96f8b1ed 649 unsigned short maxpermits, maxdenies;
650 va_list ap;
651
652 va_start(ap, command);
e7fb57f5 653 maxpermits = va_arg(ap, int);
654 maxdenies = va_arg(ap, int);
96f8b1ed 655 va_end(ap);
656
37ee990e 657 dvprintf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
96f8b1ed 658
c78446b5 659 aim_bos_clientready(sess, command->conn);
660
37ee990e 661 dprintf("faimtest: officially connected to BOS.\n");
662
663 return 1;
664}
665
666int faimtest_parse_unknown(struct aim_session_t *sess, struct command_rx_struct *command, ...)
667{
668 int i = 0;
669
670 if (!sess || !command)
671 return 1;
672
646c6b52 673 dprintf("\nReceived unknown packet:");
37ee990e 674 for (i = 0; i < command->commandlen; i++) {
675 if ((i % 8) == 0)
676 dinlineprintf("\n\t");
677 dvinlineprintf("0x%2x ", command->data[i]);
678 }
679 dinlineprintf("\n\n");
c78446b5 680
681 return 1;
682}
683
9de3ca7e 684/*
685 handleredirect()...
686
687 This, of course, handles Service Redirects from OSCAR.
688
689 Should get passed in the following:
690 struct command_rx_struct *command
691 the raw command data
692 int serviceid
693 the destination service ID
694 char *serverip
695 the IP address of the service's server
696 char *cookie
697 the raw auth cookie
698 */
397055b1 699int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 700{
701 va_list ap;
702 int serviceid;
703 char *ip;
78b3fb13 704 unsigned char *cookie;
9de3ca7e 705
9de3ca7e 706 va_start(ap, command);
707 serviceid = va_arg(ap, int);
708 ip = va_arg(ap, char *);
78b3fb13 709 cookie = va_arg(ap, unsigned char *);
0c20631f 710
e80a0fa9 711 switch(serviceid) {
712 case 0x0005: { /* Adverts */
713 struct aim_conn_t *tstconn;
64c78745 714
e80a0fa9 715 tstconn = aim_newconn(sess, AIM_CONN_TYPE_ADS, ip);
716 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
717 dprintf("faimtest: unable to reconnect with authorizer\n");
718 } else {
719 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
720 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
721 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
722 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
723 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
724 aim_auth_sendcookie(sess, tstconn, cookie);
725 dprintf("sent cookie to adverts host\n");
726 }
727 break;
728 }
729 case 0x0007: { /* Authorizer */
730 struct aim_conn_t *tstconn;
731 /* Open a connection to the Auth */
732 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
733 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
734 dprintf("faimtest: unable to reconnect with authorizer\n");
735 } else {
736 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
737 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
738 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
739 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
740 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
741 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
742 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
743 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
744 /* Send the cookie to the Auth */
745 aim_auth_sendcookie(sess, tstconn, cookie);
746 dprintf("sent cookie to authorizer host\n");
747 }
748 break;
749 }
750 case 0x000d: { /* ChatNav */
751 struct aim_conn_t *tstconn = NULL;
752 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
753 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
754 dprintf("faimtest: unable to connect to chatnav server\n");
755 if (tstconn) aim_conn_kill(sess, &tstconn);
756 return 1;
757 }
9de3ca7e 758
e80a0fa9 759 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
760 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
761 aim_auth_sendcookie(sess, tstconn, cookie);
762 dprintf("\achatnav: connected\n");
763 break;
764 }
765 case 0x000e: { /* Chat */
766 char *roomname = NULL;
767 int exchange;
768 struct aim_conn_t *tstconn = NULL;
769
770 roomname = va_arg(ap, char *);
771 exchange = va_arg(ap, int);
772
773 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
774 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
775 dprintf("faimtest: unable to connect to chat server\n");
776 if (tstconn) aim_conn_kill(sess, &tstconn);
777 return 1;
778 }
779 dvprintf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
780
781 /*
782 * We must do this to attach the stored name to the connection!
783 */
784 aim_chat_attachname(tstconn, roomname);
785
786 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
787 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
788 aim_auth_sendcookie(sess, tstconn, cookie);
00ef5271 789
e80a0fa9 790 break;
791 }
792 default:
793 dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
794 /* dunno */
795 }
9de3ca7e 796
9de3ca7e 797 va_end(ap);
798
0c20631f 799 return 1;
9de3ca7e 800}
801
83ae98f8 802/*
803 * This is a little more complicated than it looks. The module
804 * name (proto, boscore, etc) may or may not be given. If it is
805 * not given, then use aim.exe. If it is given, put ".ocm" on the
806 * end of it.
807 *
808 * Now, if the offset or length requested would cause a read past
809 * the end of the file, then the request is considered invalid. Invalid
810 * requests are processed specially. The value hashed is the
811 * the request, put into little-endian (eight bytes: offset followed
812 * by length).
813 *
814 * Additionally, if the request is valid, the length is mod 4096. It is
815 * important that the length is checked for validity first before doing
816 * the mod.
817 *
818 * Note to Bosco's Brigade: if you'd like to break this, put the
819 * module name on an invalid request.
820 *
821 */
822static int getaimdata(unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
b1eac25a 823{
824 FILE *f;
5ac961d5 825 static const char defaultmod[] = "aim.exe";
826 char *filename = NULL;
83ae98f8 827 struct stat st;
828 unsigned char *buf;
829 int invalid = 0;
b1eac25a 830
6c05e183 831 if (!bufret || !buflenret)
83ae98f8 832 return -1;
001c9b80 833
5ac961d5 834 if (modname) {
328837f7 835
5ac961d5 836 if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(modname)+4+1))) {
837 dperror("memrequest: malloc");
838 return -1;
839 }
840
841 sprintf(filename, "%s/%s.ocm", aimbinarypath, modname);
842
843 } else {
844
845 if (!(filename = malloc(strlen(aimbinarypath)+1+strlen(defaultmod)+1))) {
846 dperror("memrequest: malloc");
847 return -1;
848 }
849
850 sprintf(filename, "%s/%s", aimbinarypath, defaultmod);
328837f7 851
328837f7 852 }
853
83ae98f8 854 if (stat(filename, &st) == -1) {
855 dperror("memrequest: stat");
5ac961d5 856 free(filename);
b1eac25a 857 return -1;
858 }
859
6c05e183 860 if ((offset > st.st_size) || (len > st.st_size))
83ae98f8 861 invalid = 1;
862 else if ((st.st_size - offset) < len)
863 len = st.st_size - offset;
864 else if ((st.st_size - len) < len)
865 len = st.st_size - len;
866
867 if (!invalid && len)
868 len %= 4096;
869
870 if (invalid) {
871
872 free(filename); /* not needed */
873
874 if (!(buf = malloc(8)))
875 return -1;
876
877 dvprintf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx\n", len, offset);
878
879 /* Damn endianness. This must be little (LSB first) endian. */
880 buf[0] = offset & 0xff;
881 buf[1] = (offset >> 8) & 0xff;
882 buf[2] = (offset >> 16) & 0xff;
883 buf[3] = (offset >> 24) & 0xff;
884 buf[4] = len & 0xff;
885 buf[5] = (len >> 8) & 0xff;
886 buf[6] = (len >> 16) & 0xff;
887 buf[7] = (len >> 24) & 0xff;
888
889 *bufret = buf;
890 *buflenret = 8;
891
892 } else {
893
894 if (!(buf = malloc(len))) {
895 free(filename);
896 return -1;
897 }
898
899 dvprintf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename);
900
901 if (!(f = fopen(filename, "r"))) {
902 dperror("memrequest: fopen");
903 free(filename);
904 free(buf);
905 return -1;
906 }
907
908 free(filename);
5ac961d5 909
001c9b80 910 if (fseek(f, offset, SEEK_SET) == -1) {
911 dperror("memrequest: fseek");
912 fclose(f);
83ae98f8 913 free(buf);
001c9b80 914 return -1;
915 }
b1eac25a 916
83ae98f8 917 if (fread(buf, len, 1, f) != 1) {
001c9b80 918 dperror("memrequest: fread");
919 fclose(f);
83ae98f8 920 free(buf);
001c9b80 921 return -1;
922 }
b1eac25a 923
83ae98f8 924 fclose(f);
925
926 *bufret = buf;
927 *buflenret = len;
928
929 }
b1eac25a 930
83ae98f8 931 return 0; /* success! */
b1eac25a 932}
933
934/*
935 * This will get an offset and a length. The client should read this
936 * data out of whatever AIM.EXE binary the user has provided (hopefully
937 * it matches the client information thats sent at login) and pass a
938 * buffer back to libfaim so it can hash the data and send it to AOL for
939 * inspection by the client police.
940 */
941static int faimtest_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...)
942{
943 va_list ap;
944 unsigned long offset, len;
328837f7 945 char *modname;
83ae98f8 946 unsigned char *buf;
947 int buflen;
b1eac25a 948
949 va_start(ap, command);
950 offset = va_arg(ap, unsigned long);
951 len = va_arg(ap, unsigned long);
328837f7 952 modname = va_arg(ap, char *);
b1eac25a 953 va_end(ap);
954
83ae98f8 955 if (aimbinarypath && (getaimdata(&buf, &buflen, offset, len, modname) == 0)) {
b1eac25a 956
83ae98f8 957 aim_sendmemblock(sess, command->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 958
83ae98f8 959 free(buf);
b1eac25a 960
961 } else {
962
328837f7 963 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", aimbinarypath, modname);
b1eac25a 964
d2698e03 965 aim_sendmemblock(sess, command->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 966
967 }
968
b1eac25a 969 return 1;
970}
971
972static int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 973{
355982c5 974 va_list ap;
9de3ca7e 975 struct aim_conn_t *bosconn = NULL;
355982c5 976 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
977 unsigned char *cookie = NULL;
978 int errorcode = 0, regstatus = 0;
89bce177 979 int latestbuild = 0, latestbetabuild = 0;
980 char *latestrelease = NULL, *latestbeta = NULL;
981 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
982 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
983
355982c5 984 va_start(ap, command);
985 sn = va_arg(ap, char *);
986 errorcode = va_arg(ap, int);
987 errurl = va_arg(ap, char *);
988 regstatus = va_arg(ap, int);
989 email = va_arg(ap, char *);
990 bosip = va_arg(ap, char *);
991 cookie = va_arg(ap, unsigned char *);
89bce177 992
993 latestrelease = va_arg(ap, char *);
994 latestbuild = va_arg(ap, int);
995 latestreleaseurl = va_arg(ap, char *);
996 latestreleaseinfo = va_arg(ap, char *);
997
998 latestbeta = va_arg(ap, char *);
999 latestbetabuild = va_arg(ap, int);
1000 latestbetaurl = va_arg(ap, char *);
1001 latestbetainfo = va_arg(ap, char *);
1002
355982c5 1003 va_end(ap);
01b59e1e 1004
37ee990e 1005 dvprintf("Screen name: %s\n", sn);
01b59e1e 1006
1007 /*
1008 * Check for error.
1009 */
355982c5 1010 if (errorcode || !bosip || !cookie) {
37ee990e 1011 dvprintf("Login Error Code 0x%04x\n", errorcode);
1012 dvprintf("Error URL: %s\n", errurl);
9bf14d44 1013 aim_conn_kill(sess, &command->conn);
355982c5 1014 return 1;
1015 }
01b59e1e 1016
37ee990e 1017 dvprintf("Reg status: %2d\n", regstatus);
1018 dvprintf("Email: %s\n", email);
1019 dvprintf("BOS IP: %s\n", bosip);
9de3ca7e 1020
89bce177 1021 if (latestbeta)
37ee990e 1022 dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
89bce177 1023
1024 if (latestrelease)
37ee990e 1025 dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
89bce177 1026
37ee990e 1027 dprintf("Closing auth connection...\n");
040457cc 1028 aim_conn_kill(sess, &command->conn);
355982c5 1029 if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
37ee990e 1030 dprintf("faimtest: could not connect to BOS: internal error\n");
355982c5 1031 return 1;
22517493 1032 } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
37ee990e 1033 dprintf("faimtest: could not connect to BOS\n");
040457cc 1034 aim_conn_kill(sess, &bosconn);
355982c5 1035 return 1;
1036 }
1037
1038 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1039 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
1040 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
1041 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
ee49b735 1042 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
355982c5 1043 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
1044 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
1045 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
1046 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
1047 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
1048 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
1049 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
1050 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1051 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
1052 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
1053 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
1054 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
37ee990e 1055 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
1056 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
355982c5 1057 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
1058 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
1059 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
1060
355982c5 1061 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
00ef5271 1062
1063 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1449ad2b 1064 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
1065 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
1066 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
1067
355982c5 1068 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
b1eac25a 1069 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
d32954e7 1070 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
1449ad2b 1071
355982c5 1072 aim_auth_sendcookie(sess, bosconn, cookie);
1073
9de3ca7e 1074 return 1;
1075}
1076
a15d82b1 1077static void printuserflags(unsigned short flags)
1078{
1079 if (flags & AIM_FLAG_UNCONFIRMED)
37ee990e 1080 dinlineprintf("UNCONFIRMED ");
a15d82b1 1081 if (flags & AIM_FLAG_ADMINISTRATOR)
37ee990e 1082 dinlineprintf("ADMINISTRATOR ");
a15d82b1 1083 if (flags & AIM_FLAG_AOL)
37ee990e 1084 dinlineprintf("AOL ");
a15d82b1 1085 if (flags & AIM_FLAG_OSCAR_PAY)
37ee990e 1086 dinlineprintf("OSCAR_PAY ");
a15d82b1 1087 if (flags & AIM_FLAG_FREE)
37ee990e 1088 dinlineprintf("FREE ");
a15d82b1 1089 if (flags & AIM_FLAG_AWAY)
37ee990e 1090 dinlineprintf("AWAY ");
a15d82b1 1091 if (flags & AIM_FLAG_UNKNOWN40)
37ee990e 1092 dinlineprintf("ICQ? ");
a15d82b1 1093 if (flags & AIM_FLAG_UNKNOWN80)
37ee990e 1094 dinlineprintf("UNKNOWN80 ");
a15d82b1 1095 return;
1096}
1097
397055b1 1098int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1099{
1100 struct aim_userinfo_s *userinfo;
1101 char *prof_encoding = NULL;
1102 char *prof = NULL;
5e02cf44 1103 unsigned short inforeq = 0;
9de3ca7e 1104
1105 va_list ap;
1106 va_start(ap, command);
1107 userinfo = va_arg(ap, struct aim_userinfo_s *);
1108 prof_encoding = va_arg(ap, char *);
1109 prof = va_arg(ap, char *);
e7fb57f5 1110 inforeq = va_arg(ap, int);
9de3ca7e 1111 va_end(ap);
1112
37ee990e 1113 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
1114 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
1115 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
a15d82b1 1116 printuserflags(userinfo->flags);
37ee990e 1117 dinlineprintf("\n");
9de3ca7e 1118
37ee990e 1119 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
1120 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1121 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
9de3ca7e 1122
5e02cf44 1123 if (inforeq == AIM_GETINFO_GENERALINFO) {
37ee990e 1124 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1125 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
5e02cf44 1126 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
37ee990e 1127 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1128 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
5e02cf44 1129 } else
37ee990e 1130 dprintf("faimtest: userinfo: unknown info request\n");
9de3ca7e 1131
1132 return 1;
1133}
1134
d2587300 1135static int faimtest_handlecmd(struct aim_session_t *sess, struct command_rx_struct *command, struct aim_userinfo_s *userinfo, char *tmpstr)
1136{
1137
1138 if (!strncmp(tmpstr, "disconnect", 10)) {
1139
1140 logout();
1141
1142 } else if (strstr(tmpstr, "goodday")) {
1143
a2244dd9 1144 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.", strlen("Good day to you too."));
d2587300 1145
1146 } else if (strstr(tmpstr, "warnme")) {
1147
1148 dprintf("faimtest: icbm: sending non-anon warning\n");
1149 aim_send_warning(sess, command->conn, userinfo->sn, 0);
1150
1151 } else if (strstr(tmpstr, "anonwarn")) {
1152
1153 dprintf("faimtest: icbm: sending anon warning\n");
1154 aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
1155
1156 } else if (strstr(tmpstr, "setdirectoryinfo")) {
1157
1158 dprintf("faimtest: icbm: sending backwards profile data\n");
1159 aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1160
1161 } else if (strstr(tmpstr, "setinterests")) {
1162
1163 dprintf("faimtest: icbm: setting fun interests\n");
1164 aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1165
1166 } else if (!strncmp(tmpstr, "getfile", 7)) {
1167
1168 if (!ohcaptainmycaptain) {
1169
a2244dd9 1170 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!", strlen("I have no owner!"));
d2587300 1171
1172 } else {
1173 struct aim_conn_t *newconn;
1174
1175 newconn = aim_getfile_initiate(sess, command->conn, (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1176 dvprintf("faimtest: getting file listing from %s\n", (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1177 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE, faimtest_getfile_initiate,0);
1178 }
1179
1180 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1181
1182 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
1183
1184 } else if (!strncmp(tmpstr, "create", 6)) {
1185
1186 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1187
1188 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1189 struct aim_conn_t *chatnavconn;
1190
1191 chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
1192 aim_conn_kill(sess, &chatnavconn);
1193
1194 } else if (!strncmp(tmpstr, "join", 4)) {
1195
1196 aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
1197
1198 } else if (!strncmp(tmpstr, "leave", 5)) {
1199
1200 aim_chat_leaveroom(sess, "worlddomination");
1201
1202 } else if (!strncmp(tmpstr, "getinfo", 7)) {
1203
1204 aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
1205 aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
00ef5271 1206 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
1207 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
d2587300 1208
1209 } else if (!strncmp(tmpstr, "open directim", 13)) {
1210 struct aim_conn_t *newconn;
1211
1212 printf("faimtest: opening directim to %s\n", (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1213 newconn = aim_directim_initiate(sess, command->conn, NULL, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1214 if(!newconn || newconn->fd == -1)
1215 printf("connection failed!\n");
1216 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate,0);
1217
1218 } else if(!(strncmp(tmpstr, "lookup", 6))) {
1219
1220 aim_usersearch_address(sess, command->conn, tmpstr+7);
1221
1222 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1223
a2244dd9 1224 aim_send_im(sess, command->conn, ohcaptainmycaptain, 0, "sendmsg 7900", strlen("sendmsg 7900"));
d2587300 1225
1226 } else if (!strncmp(tmpstr, "reqauth", 7)) {
1227
1228 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
1229
1230 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1231
1232 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1233
1234 } else if (!strncmp(tmpstr, "reqemail", 8)) {
1235
1236 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1237
1238 } else if (!strncmp(tmpstr, "changepass", 8)) {
1239
1240 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1241
1242 } else if (!strncmp(tmpstr, "setemail", 8)) {
1243
1244 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1245
1246 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1247 int i;
1248 i = atoi(tmpstr+8);
1249 if (i < 10000) {
1250 char *newbuf;
1251 int z;
1252
1253 newbuf = malloc(i+1);
1254 for (z = 0; z < i; z++) {
1255 newbuf[z] = (z % 10)+0x30;
1256 }
1257 newbuf[i] = '\0';
a2244dd9 1258 aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf, strlen(newbuf));
d2587300 1259 free(newbuf);
1260 }
1261
1262 } else {
1263
1264 dprintf("unknown command.\n");
1265 aim_add_buddy(sess, command->conn, userinfo->sn);
1266
1267 }
1268
1269 return 0;
1270}
1271
9de3ca7e 1272/*
1273 * The user-level Incoming ICBM callback.
1274 *
9de3ca7e 1275 */
397055b1 1276int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1277{
26af6789 1278 int channel;
9de3ca7e 1279 va_list ap;
9de3ca7e 1280
1281 va_start(ap, command);
26af6789 1282 channel = va_arg(ap, int);
9de3ca7e 1283
26af6789 1284 /*
1285 * Channel 1: Standard Message
1286 */
040457cc 1287 if (channel == 1) {
1288 struct aim_userinfo_s *userinfo;
1289 char *msg = NULL;
1290 u_int icbmflags = 0;
1291 char *tmpstr = NULL;
e7fb57f5 1292 unsigned short flag1, flag2;
9d83220c 1293 int finlen = 0;
1294 unsigned char *fingerprint = NULL;
1295 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
040457cc 1296
1297 userinfo = va_arg(ap, struct aim_userinfo_s *);
1298 msg = va_arg(ap, char *);
1299 icbmflags = va_arg(ap, u_int);
e7fb57f5 1300 flag1 = va_arg(ap, int);
1301 flag2 = va_arg(ap, int);
9d83220c 1302 finlen = va_arg(ap, int);
1303 fingerprint = va_arg(ap, unsigned char *);
040457cc 1304 va_end(ap);
1305
9d83220c 1306 clienttype = aim_fingerprintclient(fingerprint, finlen);
1307
37ee990e 1308 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
9d83220c 1309 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
37ee990e 1310 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1311 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
a15d82b1 1312 printuserflags(userinfo->flags);
37ee990e 1313 dinlineprintf("\n");
a15d82b1 1314
37ee990e 1315 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1316 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1317 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1318 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
040457cc 1319
37ee990e 1320 dprintf("faimtest: icbm: icbmflags = ");
040457cc 1321 if (icbmflags & AIM_IMFLAGS_AWAY)
37ee990e 1322 dinlineprintf("away ");
040457cc 1323 if (icbmflags & AIM_IMFLAGS_ACK)
37ee990e 1324 dinlineprintf("ackrequest ");
1325 dinlineprintf("\n");
040457cc 1326
37ee990e 1327 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
040457cc 1328
37ee990e 1329 dvprintf("faimtest: icbm: message: %s\n", msg);
040457cc 1330
1331 if (msg) {
b69540e3 1332 int i = 0;
1333
1334 while (msg[i] == '<') {
1335 if (msg[i] == '<') {
1336 while (msg[i] != '>')
1337 i++;
1338 i++;
1339 }
1340 }
1341 tmpstr = msg+i;
1342
d2587300 1343 faimtest_handlecmd(sess, command, userinfo, tmpstr);
1344
040457cc 1345 }
1346 }
1347 /*
1348 * Channel 2: Rendevous Request
1349 */
1350 else if (channel == 2) {
1351 struct aim_userinfo_s *userinfo;
1352 unsigned short reqclass;
1353
e7fb57f5 1354 reqclass = va_arg(ap, int);
040457cc 1355 switch (reqclass) {
b69540e3 1356 case AIM_CAPS_VOICE: {
26af6789 1357 userinfo = va_arg(ap, struct aim_userinfo_s *);
26af6789 1358 va_end(ap);
9de3ca7e 1359
37ee990e 1360 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1361 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1362 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1363 printuserflags(userinfo->flags);
37ee990e 1364 dinlineprintf("\n");
a15d82b1 1365
040457cc 1366 /* we dont get membersince on chat invites! */
37ee990e 1367 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1368 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1369
040457cc 1370 break;
1371 }
b69540e3 1372 case AIM_CAPS_GETFILE: {
871e2fd0 1373 char *ip, *cookie;
1374 struct aim_conn_t *newconn;
37ee990e 1375 struct aim_fileheader_t *fh;
871e2fd0 1376
1377 userinfo = va_arg(ap, struct aim_userinfo_s *);
1378 ip = va_arg(ap, char *);
1379 cookie = va_arg(ap, char *);
1380 va_end(ap);
1381
646c6b52 1382 dvprintf("faimtest: get file request from %s (at %s) %x\n", userinfo->sn, ip, reqclass);
1383
1384 fh = aim_getlisting(sess, listingfile);
871e2fd0 1385
646c6b52 1386 newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, fh->totfiles, fh->totsize, fh->size, fh->checksum, reqclass);
871e2fd0 1387
646c6b52 1388 if( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1389 dprintf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
646c6b52 1390 if(newconn)
1391 aim_conn_kill(sess, &newconn);
871e2fd0 1392 break;
1393 }
37ee990e 1394
1395 free(fh);
1396
1397 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
871e2fd0 1398 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1399 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1400 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
37ee990e 1401
871e2fd0 1402 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1403
37ee990e 1404 dprintf("faimtest: getfile connect succeeded, handlers added.\n");
871e2fd0 1405
040457cc 1406 break;
1407 }
b69540e3 1408 case AIM_CAPS_SENDFILE: {
37ee990e 1409 dprintf("faimtest: send file!\n");
b69540e3 1410 break;
1411 }
1412 case AIM_CAPS_CHAT: {
040457cc 1413 char *msg,*encoding,*lang;
1414 struct aim_chat_roominfo *roominfo;
26af6789 1415
040457cc 1416 userinfo = va_arg(ap, struct aim_userinfo_s *);
1417 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1418 msg = va_arg(ap, char *);
1419 encoding = va_arg(ap, char *);
1420 lang = va_arg(ap, char *);
1421 va_end(ap);
26af6789 1422
37ee990e 1423 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1424 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1425 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1426 printuserflags(userinfo->flags);
37ee990e 1427 dinlineprintf("\n");
a15d82b1 1428
040457cc 1429 /* we dont get membersince on chat invites! */
37ee990e 1430 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1431 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1432
37ee990e 1433 dvprintf("faimtest: chat invitation: message = %s\n", msg);
1434 dvprintf("faimtest: chat invitation: room name = %s\n", roominfo->name);
1435 dvprintf("faimtest: chat invitation: encoding = %s\n", encoding);
1436 dvprintf("faimtest: chat invitation: language = %s\n", lang);
1437 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
1438 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
1439 dvprintf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
040457cc 1440 /*
1441 * Automatically join room...
1442 */
1443 aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
1444 break;
1445 }
7392c79f 1446 case AIM_CAPS_IMIMAGE: {
1447 struct aim_directim_priv *priv;
1448 struct aim_conn_t *newconn;
1449
37ee990e 1450 dprintf("faimtest: icbm: rendezvous imimage\n");
7392c79f 1451
1452 userinfo = va_arg(ap, struct aim_userinfo_s *);
1453 priv = va_arg(ap, struct aim_directim_priv *);
1454 va_end(ap);
1455
37ee990e 1456 dvprintf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
7392c79f 1457
646c6b52 1458 newconn = aim_directim_connect(sess, command->conn, priv);
1459
1460 if ( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1461 dprintf("faimtest: icbm: imimage: could not connect\n");
646c6b52 1462
1463 if (newconn)
1464 aim_conn_kill(sess, &newconn);
1465
7392c79f 1466 break;
1467 }
646c6b52 1468
7392c79f 1469 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1470 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1471 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1472
37ee990e 1473 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
7392c79f 1474
3b101546 1475 aim_send_im_direct(sess, newconn, "goodday");
1476
7392c79f 1477 break;
1478 }
040457cc 1479 default:
37ee990e 1480 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
040457cc 1481 } /* switch */
1482 } else
37ee990e 1483 dvprintf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1484 dprintf("faimtest: icbm: done with ICBM handling\n");
9de3ca7e 1485
1486 return 1;
1487}
1488
7392c79f 1489int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1490{
1491 va_list ap;
1492 struct aim_directim_priv *priv;
646c6b52 1493 struct aim_conn_t *newconn, *listenerconn;
7392c79f 1494
e7fb57f5 1495 va_start(ap, command);
7392c79f 1496 newconn = va_arg(ap, struct aim_conn_t *);
646c6b52 1497 listenerconn = va_arg(ap, struct aim_conn_t *);
7392c79f 1498 va_end(ap);
1499
646c6b52 1500 aim_conn_close(listenerconn);
1501 aim_conn_kill(sess, &listenerconn);
1502
7392c79f 1503 priv = (struct aim_directim_priv *)newconn->priv;
1504
37ee990e 1505 dvprintf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
7392c79f 1506
1507 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1508 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1509 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1510
1511 aim_send_im_direct(sess, newconn, "goodday");
1512
37ee990e 1513 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
7392c79f 1514
1515 return 1;
1516}
7392c79f 1517
1518int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1519{
1520 va_list ap;
1521 struct aim_directim_priv *priv;
1522
e7fb57f5 1523 va_start(ap, command);
7392c79f 1524 priv = va_arg(ap, struct aim_directim_priv *);
1525
1526 va_end(ap);
1527
37ee990e 1528 dprintf("faimtest: directim_connect\n");
7392c79f 1529
1530 return 1;
1531}
1532
1533int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1534{
1535 va_list ap;
9e8c4225 1536 char *msg = NULL;
7392c79f 1537 struct aim_conn_t *conn;
9e8c4225 1538 struct aim_directim_priv *priv;
7392c79f 1539
e7fb57f5 1540 va_start(ap, command);
7392c79f 1541 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1542 msg = va_arg(ap, char *);
1543 va_end(ap);
1544
9e8c4225 1545 if(!(priv = conn->priv)) {
1546 dvprintf("faimtest: directim: no private struct on conn with fd %d\n", conn->fd);
1547 return -1;
1548 }
1549
1550 dvprintf("faimtest: Directim from %s: %s\n", priv->sn, msg);
7392c79f 1551 if (!strncmp(msg, "sendmsg", 7)) {
1552 int i;
1553 i = atoi(msg+8);
1554 if (i < 10000) {
1555 char *newbuf;
1556 int z;
1557
1558 newbuf = malloc(i+1);
1559 for (z = 0; z < i; z++) {
1560 newbuf[z] = (z % 10)+0x30;
1561 }
1562 newbuf[i] = '\0';
1563 aim_send_im_direct(sess, conn, newbuf);
1564 free(newbuf);
1565 }
1566 } else if (!strncmp(msg, "goodday", 7)) {
1567 aim_send_im_direct(sess, conn, "Good day to you, too");
1568 } else {
1569 char newmsg[1024];
1570 snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1571 aim_send_im_direct(sess, conn, newmsg);
1572 }
1573 return 1;
1574}
1575
1576int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1577{
871e2fd0 1578 va_list ap;
1579 struct aim_conn_t *conn;
1580 char *sn;
1581
e7fb57f5 1582 va_start(ap, command);
871e2fd0 1583 conn = va_arg(ap, struct aim_conn_t *);
1584 sn = va_arg(ap, char *);
1585 va_end(ap);
1586
37ee990e 1587 dvprintf("faimtest: directim: disconnected from %s\n", sn);
3b101546 1588
1589 aim_conn_kill(sess, &conn);
7392c79f 1590 return 1;
1591}
1592
1593int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1594{
1595 va_list ap;
9e8c4225 1596 struct aim_conn_t *conn;
1597 struct aim_directim_priv *priv;
1598
e7fb57f5 1599 va_start(ap, command);
9e8c4225 1600 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1601 va_end(ap);
9e8c4225 1602
1603 if(!(priv = (struct aim_directim_priv *)conn->priv)) {
1604 dvprintf("faimtest: no private struct on conn with fd %d!\n", conn->fd);
1605 return -1;
1606 }
7392c79f 1607
9e8c4225 1608 dvprintf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
7392c79f 1609 return 1;
1610}
1611
64c78745 1612int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1613{
64c78745 1614 unsigned short change = 0;
1615 int perms, type, length, str;
1616 char *val;
1617 va_list ap;
9de3ca7e 1618
64c78745 1619 va_start(ap, command);
1620 perms = va_arg(ap, int);
1621 type = va_arg(ap, int);
1622 length = va_arg(ap, int);
1623 val = va_arg(ap, char *);
1624 str = va_arg(ap, int);
1625 va_end(ap);
9de3ca7e 1626
64c78745 1627 if (aimutil_get16(command->data+2) == 0x0005)
1628 change = 1;
1629
1630 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
9de3ca7e 1631
9de3ca7e 1632 return 1;
1633}
1634
397055b1 1635int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1636{
1637 struct aim_userinfo_s *userinfo;
1638
1639 va_list ap;
1640 va_start(ap, command);
1641 userinfo = va_arg(ap, struct aim_userinfo_s *);
1642 va_end(ap);
1643
37ee990e 1644 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
ee49b735 1645 time(NULL),
a15d82b1 1646 userinfo->sn, userinfo->flags,
1647 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1648 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1649 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1650 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1651 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1652 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1653 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1654 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
b69540e3 1655 userinfo->capabilities);
9de3ca7e 1656 return 1;
1657}
1658
397055b1 1659int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1660{
69e7980c 1661 struct aim_userinfo_s *userinfo;
1662
397055b1 1663 va_list ap;
397055b1 1664 va_start(ap, command);
69e7980c 1665 userinfo = va_arg(ap, struct aim_userinfo_s *);
397055b1 1666 va_end(ap);
9de3ca7e 1667
69e7980c 1668 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1669 time(NULL),
1670 userinfo->sn, userinfo->flags,
1671 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1672 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1673 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1674 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1675 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1676 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1677 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1678 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1679 userinfo->capabilities);
9de3ca7e 1680 return 1;
1681}
1682
01b59e1e 1683int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1684{
96f8b1ed 1685 static char *codes[] = {
1686 "Unknown",
1687 "Mandatory upgrade",
1688 "Advisory upgrade",
1689 "System bulletin",
1690 "Top o' the world!"};
1691 static int codeslen = 5;
1692
01b59e1e 1693 char *msg;
96f8b1ed 1694 unsigned short id;
01b59e1e 1695 va_list ap;
1696
1697 va_start(ap, command);
e7fb57f5 1698 id = va_arg(ap, int);
01b59e1e 1699 msg = va_arg(ap, char *);
1700 va_end(ap);
1701
37ee990e 1702 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1703 (id < codeslen)?codes[id]:"unknown");
96f8b1ed 1704
ee49b735 1705 if (!connected)
1706 connected++;
1707
e80a0fa9 1708#if 0
1709 aim_bos_reqservice(sess, command->conn, 0x0005); /* adverts */
1710 aim_bos_reqservice(sess, command->conn, 0x000f); /* user directory */
1711
1712 /* Don't know what this does... */
1713 /* XXX sess->sn should be normalized by the 0001/000f handler */
1714 aim_0002_000b(sess, command->conn, sess->sn);
1715#endif
1716
96f8b1ed 1717 return 1;
1718}
1719
1449ad2b 1720int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1721{
1722 va_list ap;
1723 unsigned short reason;
1724
1725 va_start(ap, command);
1726 reason = va_arg(ap, int);
1727 va_end(ap);
1728
37ee990e 1729 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1449ad2b 1730
1731 return 1;
1732}
1733
96f8b1ed 1734int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1735{
1736 va_list ap;
1737 char *destsn;
1738 unsigned short reason;
1739
1740 va_start(ap, command);
e7fb57f5 1741 reason = va_arg(ap, int);
00ef5271 1742 destsn = va_arg(ap, char *);
96f8b1ed 1743 va_end(ap);
1744
37ee990e 1745 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1746
1747 return 1;
1748}
1749
1750int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1751{
1752 va_list ap;
1753 char *destsn;
1754 unsigned short reason;
1755
1756 va_start(ap, command);
e7fb57f5 1757 reason = va_arg(ap, int);
00ef5271 1758 destsn = va_arg(ap, char *);
96f8b1ed 1759 va_end(ap);
01b59e1e 1760
37ee990e 1761 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1762
01b59e1e 1763 return 1;
1764}
9de3ca7e 1765
1766/*
96f8b1ed 1767 * Handles callbacks for AIM_CB_MISSED_CALL.
9de3ca7e 1768 */
397055b1 1769int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1770{
96f8b1ed 1771 static char *missedreasons[] = {
1772 "Unknown",
1773 "Message too large"};
1774 static int missedreasonslen = 2;
9de3ca7e 1775
96f8b1ed 1776 va_list ap;
1777 unsigned short chan, nummissed, reason;
1778 struct aim_userinfo_s *userinfo;
9de3ca7e 1779
96f8b1ed 1780 va_start(ap, command);
e7fb57f5 1781 chan = va_arg(ap, int);
96f8b1ed 1782 userinfo = va_arg(ap, struct aim_userinfo_s *);
e7fb57f5 1783 nummissed = va_arg(ap, int);
1784 reason = va_arg(ap, int);
96f8b1ed 1785 va_end(ap);
9de3ca7e 1786
37ee990e 1787 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
96f8b1ed 1788
00f3b08b 1789 return 1;
9de3ca7e 1790}
1791
01b59e1e 1792int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1793{
154b4093 1794 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
78b3fb13 1795 char *key;
b5bc2a8c 1796 va_list ap;
01b59e1e 1797
b5bc2a8c 1798 va_start(ap, command);
1799 key = va_arg(ap, char *);
1800 va_end(ap);
9de3ca7e 1801
b5bc2a8c 1802 aim_send_login(sess, command->conn, screenname, password, &info, key);
01b59e1e 1803
1804 return 1;
1805}
0c20631f 1806
1807int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1808{
1809 va_list ap;
1810 struct aim_userinfo_s *userinfo;
1811 int count = 0, i = 0;
1812
1813 va_start(ap, command);
1814 count = va_arg(ap, int);
1815 userinfo = va_arg(ap, struct aim_userinfo_s *);
1816 va_end(ap);
1817
37ee990e 1818 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
0c20631f 1819 while (i < count)
37ee990e 1820 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1821
1822 return 1;
1823}
1824
1825int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1826{
1827 va_list ap;
1828 struct aim_userinfo_s *userinfo;
1829 int count = 0, i = 0;
1830
1831 va_start(ap, command);
1832 count = va_arg(ap, int);
1833 userinfo = va_arg(ap, struct aim_userinfo_s *);
1834 va_end(ap);
1835
37ee990e 1836 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1837
1838 for (i = 0; i < count; )
1839 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1840
1841 return 1;
1842}
1843
1844int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1845{
1846 va_list ap;
1847 struct aim_userinfo_s *userinfo;
1848 struct aim_chat_roominfo *roominfo;
1849 char *roomname;
1850 int usercount,i;
1851 char *roomdesc;
aa6efcfd 1852 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1853 unsigned long creationtime;
0c20631f 1854
1855 va_start(ap, command);
1856 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1857 roomname = va_arg(ap, char *);
1858 usercount= va_arg(ap, int);
1859 userinfo = va_arg(ap, struct aim_userinfo_s *);
1860 roomdesc = va_arg(ap, char *);
e7fb57f5 1861 unknown_c9 = va_arg(ap, int);
aa6efcfd 1862 creationtime = va_arg(ap, unsigned long);
e7fb57f5 1863 maxmsglen = va_arg(ap, int);
1864 unknown_d2 = va_arg(ap, int);
1865 unknown_d5 = va_arg(ap, int);
0c20631f 1866 va_end(ap);
1867
37ee990e 1868 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1869 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
0c20631f 1870 (char *)command->conn->priv,
1871 roominfo->exchange,
1872 roominfo->name,
1873 roominfo->instance);
37ee990e 1874 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1875 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1876 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
0c20631f 1877
37ee990e 1878 for (i = 0; i < usercount; )
1879 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1880
37ee990e 1881 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1882 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1883 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1884 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1885 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
aa6efcfd 1886
0c20631f 1887 return 1;
1888}
1889
1890int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1891{
1892 va_list ap;
1893 struct aim_userinfo_s *userinfo;
1894 char *msg;
1895 char tmpbuf[1152];
1896
1897 va_start(ap, command);
1898 userinfo = va_arg(ap, struct aim_userinfo_s *);
1899 msg = va_arg(ap, char *);
1900 va_end(ap);
1901
37ee990e 1902 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
0c20631f 1903
1904 /*
1905 * Do an echo for testing purposes. But not for ourselves ("oops!")
1906 */
355982c5 1907 if (strcmp(userinfo->sn, sess->sn) != 0)
0c20631f 1908 {
1909 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
a2244dd9 1910 aim_chat_send_im(sess, command->conn, 0, tmpbuf, strlen(tmpbuf));
0c20631f 1911 }
1912
1913 return 1;
1914}
1915
1916int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1917{
e7fb57f5 1918 unsigned short type;
0c20631f 1919 va_list ap;
1920
e7fb57f5 1921 va_start(ap, command);
1922 type = va_arg(ap, int);
0c20631f 1923
efe9513b 1924 switch(type) {
1925 case 0x0002: {
1926 int maxrooms;
1927 struct aim_chat_exchangeinfo *exchanges;
1928 int exchangecount,i = 0;
1929
e7fb57f5 1930 maxrooms = va_arg(ap, int);
efe9513b 1931 exchangecount = va_arg(ap, int);
1932 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1933 va_end(ap);
1934
37ee990e 1935 dprintf("faimtest: chat info: Chat Rights:\n");
1936 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
efe9513b 1937
37ee990e 1938 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1939 for (i = 0; i < exchangecount; i++) {
1940 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1941 exchanges[i].number,
1942 exchanges[i].name,
1943 exchanges[i].charset1,
1944 exchanges[i].lang1);
0c20631f 1945 }
efe9513b 1946
1947 }
1948 break;
1949 case 0x0008: {
1950 char *fqcn, *name, *ck;
9dbda50b 1951 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
efe9513b 1952 unsigned char createperms;
1953 unsigned long createtime;
1954
1955 fqcn = va_arg(ap, char *);
e7fb57f5 1956 instance = va_arg(ap, int);
9dbda50b 1957 exchange = va_arg(ap, int);
e7fb57f5 1958 flags = va_arg(ap, int);
efe9513b 1959 createtime = va_arg(ap, unsigned long);
e7fb57f5 1960 maxmsglen = va_arg(ap, int);
1961 maxoccupancy = va_arg(ap, int);
1962 createperms = va_arg(ap, int);
1963 unknown = va_arg(ap, int);
efe9513b 1964 name = va_arg(ap, char *);
1965 ck = va_arg(ap, char *);
1966 va_end(ap);
1967
646c6b52 1968 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
efe9513b 1969 }
1970 break;
1971 default:
1972 va_end(ap);
37ee990e 1973 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
efe9513b 1974 }
0c20631f 1975 return 1;
1976}
5e02cf44 1977
1978int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1979{
1980 va_list ap;
1981 unsigned short code;
1982 char *msg = NULL;
1983
e7fb57f5 1984 va_start(ap, command);
1985 code = va_arg(ap, int);
5e02cf44 1986 msg = va_arg(ap, char *);
1987 va_end(ap);
1988
37ee990e 1989 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
68ac63c2 1990 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
5e02cf44 1991
d32954e7 1992 connected = 0;
1993
5e02cf44 1994 return 1;
1995}
e5012450 1996
1997int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1998{
37ee990e 1999 dprintf("faimtest: connecting to an aimdebugd!\n");
e5012450 2000
2001 /* convert the authorizer connection to a BOS connection */
2002 command->conn->type = AIM_CONN_TYPE_BOS;
2003
2004 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
2005
2006 /* tell the aimddebugd we're ready */
2007 aim_debugconn_sendconnect(sess, command->conn);
2008
2009 /* go right into main loop (don't open a BOS connection, etc) */
2010 return 1;
2011}
1a8c261b 2012
2013/*
646c6b52 2014 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 2015 */
2016int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2017{
2018 va_list ap;
2019 unsigned short type;
2020 char *sn = NULL;
2021
e7fb57f5 2022 va_start(ap, command);
2023 type = va_arg(ap, int);
1a8c261b 2024 sn = va_arg(ap, char *);
2025 va_end(ap);
2026
37ee990e 2027 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 2028
2029 return 1;
2030}
2031
871e2fd0 2032int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
2033{
2034 va_list ap;
2035 struct aim_conn_t *oftconn;
2036 struct aim_fileheader_t *fh;
2037 char *cookie;
2038
e7fb57f5 2039 va_start(ap, command);
871e2fd0 2040 oftconn = va_arg(ap, struct aim_conn_t *);
2041 fh = va_arg(ap, struct aim_fileheader_t *);
2042 cookie = va_arg(ap, char *);
2043 va_end(ap);
2044
37ee990e 2045 dvprintf("faimtest: request for file %s.\n", fh->name);
871e2fd0 2046
2047 return 1;
2048}
2049
2050
2051int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2052{
2053 va_list ap;
2054 struct aim_conn_t *oftconn;
2055 struct aim_fileheader_t *fh;
2056 char *path, *cookie;
646c6b52 2057 int pos, bufpos = 0, bufsize = 2048, i;
2058 char *buf;
871e2fd0 2059
2060 FILE *file;
2061
e7fb57f5 2062 va_start(ap, command);
871e2fd0 2063 oftconn = va_arg(ap, struct aim_conn_t *);
2064 fh = va_arg(ap, struct aim_fileheader_t *);
2065 cookie = va_arg(ap, char *);
2066 va_end(ap);
2067
37ee990e 2068 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
871e2fd0 2069
646c6b52 2070 if(!(buf = malloc(2048)))
2071 return -1;
2072
37ee990e 2073 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
2074 dperror("calloc");
2075 dprintf("faimtest: error in calloc of path\n");
871e2fd0 2076 return 0; /* XXX: no idea what winaim expects here =) */
2077 }
2078
37ee990e 2079 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
871e2fd0 2080
2081
2082 if( (file = fopen(path, "r")) == NULL) {
37ee990e 2083 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
871e2fd0 2084 return 0;
2085 }
646c6b52 2086
2087 /*
2088 * This is a mess. Remember that faimtest is demonstration code
2089 * only and for the sake of the gods, don't use this code in any
2090 * of your clients. --mid
2091 */
37ee990e 2092 for(pos = 0; pos < fh->size; pos++) {
2093 bufpos = pos % bufsize;
2094
2095 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2096 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2097 dperror("faim: getfile_send: write1");
2098 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2099 free(buf);
2100 return -1;
2101 }
2102 }
2103 if( (buf[bufpos] = fgetc(file)) == EOF) {
2104 if(pos != fh->size) {
2105 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2106 free(buf);
2107 return -1;
2108 }
2109 }
2110 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
2111 }
871e2fd0 2112
37ee990e 2113 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2114 dperror("faim: getfile_send: write2");
2115 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2116 free(buf);
2117 return -1;
871e2fd0 2118 }
2119
646c6b52 2120 free(buf);
871e2fd0 2121 free(fh);
2122 return 1;
2123}
2124
2125int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2126{
2127 va_list ap;
2128 struct aim_conn_t *conn;
2129 struct aim_fileheader_t *fh;
2130
e7fb57f5 2131 va_start(ap, command);
871e2fd0 2132 conn = va_arg(ap, struct aim_conn_t *);
2133 fh = va_arg(ap, struct aim_fileheader_t *);
2134 va_end(ap);
2135
37ee990e 2136 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
871e2fd0 2137
37ee990e 2138 aim_conn_close(conn);
2139 aim_conn_kill(sess, &conn);
871e2fd0 2140 return 1;
2141}
2142
2143int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2144{
2145 va_list ap;
2146 struct aim_conn_t *conn;
2147 char *sn;
2148
e7fb57f5 2149 va_start(ap, command);
871e2fd0 2150 conn = va_arg(ap, struct aim_conn_t *);
2151 sn = va_arg(ap, char *);
2152 va_end(ap);
2153
2154 aim_conn_kill(sess, &conn);
2155
37ee990e 2156 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
2157 return 1;
2158}
2159int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2160{
2161 va_list ap;
646c6b52 2162 struct aim_conn_t *conn, *listenerconn;
37ee990e 2163 struct aim_filetransfer_priv *priv;
2164
2165 va_start(ap, command);
2166 conn = va_arg(ap, struct aim_conn_t *);
646c6b52 2167 listenerconn = va_arg(ap, struct aim_conn_t *);
37ee990e 2168 va_end(ap);
2169
646c6b52 2170 aim_conn_close(listenerconn);
2171 aim_conn_kill(sess, &listenerconn);
2172
37ee990e 2173 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
2174 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
2175 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
2176 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
2177 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
2178 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
646c6b52 2179 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
2180 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
37ee990e 2181
2182 priv = (struct aim_filetransfer_priv *)conn->priv;
2183
646c6b52 2184 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
871e2fd0 2185 return 1;
2186}
871e2fd0 2187
37ee990e 2188int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2189{
2190 va_list ap;
2191 struct aim_conn_t *conn;
2192 char *listing;
2193 struct aim_filetransfer_priv *ft;
2194 char *filename, *nameend, *sizec;
2195 int filesize, namelen;
2196
2197 va_start(ap, command);
2198 conn = va_arg(ap, struct aim_conn_t *);
2199 ft = va_arg(ap, struct aim_filetransfer_priv *);
2200 listing = va_arg(ap, char *);
2201 va_end(ap);
2202
2203 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2204
2205 nameend = strstr(listing+0x1a, "\r");
2206
2207 namelen = nameend - (listing + 0x1a);
2208
2209 filename = malloc(namelen + 1);
2210 strncpy(filename, listing+0x1a, namelen);
2211 filename[namelen] = 0x00;
2212
2213 sizec = malloc(8+1);
2214 memcpy(sizec, listing + 0x11, 8);
2215 sizec[8] = 0x00;
2216
2217 filesize = strtol(sizec, (char **)NULL, 10);
2218
2219 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2220
2221 aim_oft_getfile_request(sess, conn, filename, filesize);
2222
2223 free(filename);
2224 free(sizec);
2225
2226 return 0;
2227}
2228
2229int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2230{
2231 va_list ap;
2232 struct aim_conn_t *oftconn;
2233 struct aim_fileheader_t *fh;
646c6b52 2234 int pos, bufpos = 0, bufsize = 2048, i;
2235 char *buf;
37ee990e 2236
2237 va_start(ap, command);
2238 oftconn = va_arg(ap, struct aim_conn_t *);
2239 fh = va_arg(ap, struct aim_fileheader_t *);
2240 va_end(ap);
2241
2242 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2243
646c6b52 2244 if(!(buf = malloc(2048)))
2245 return -1;
2246
37ee990e 2247 for(pos = 0; pos < fh->size; pos++) {
2248 bufpos = pos % bufsize;
2249
2250 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2251 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2252 dperror("faim: getfile_send: write1");
2253 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2254 free(buf);
2255 return -1;
2256 }
2257 }
2258 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2259 if(pos != fh->size) {
2260 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2261 free(buf);
2262 return -1;
2263 }
2264 }
2265 }
2266
2267 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2268 dperror("faim: getfile_send: write2");
2269 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2270 free(buf);
2271 return -1;
2272 }
2273
2274 dprintf("faimtest: sent listing\n");
646c6b52 2275 free(buf);
37ee990e 2276 return 0;
2277}
2278
646c6b52 2279int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
37ee990e 2280{
2281 va_list ap;
2282 struct aim_conn_t *conn;
2283 struct aim_filetransfer_priv *ft;
2284 unsigned char data;
2285 int pos;
2286
2287 va_start(ap, command);
2288 conn = va_arg(ap, struct aim_conn_t *);
2289 ft = va_arg(ap, struct aim_filetransfer_priv *);
2290 va_end(ap);
2291
2292 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2293
2294 for(pos = 0; pos < ft->fh.size; pos++) {
2295 read(conn->fd, &data, 1);
646c6b52 2296 printf("%c(%02x) ", data, data);
37ee990e 2297 }
2298
646c6b52 2299 printf("\n");
37ee990e 2300
37ee990e 2301 aim_oft_getfile_end(sess, conn);
2302
2303 return 0;
2304}
646c6b52 2305
2306int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2307{
2308 va_list ap;
2309 struct aim_conn_t *conn;
2310
2311 va_start(ap, command);
2312 conn = va_arg(ap, struct aim_conn_t *);
2313 va_end(ap);
2314
2315 aim_conn_close(conn);
2316 aim_conn_kill(sess, &conn);
2317 return 0;
2318}
2319
2320
1a8c261b 2321int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2322{
275a2ff8 2323 static char *codes[5] = {"invalid",
2324 "change",
2325 "warning",
2326 "limit",
2327 "limit cleared"};
1a8c261b 2328 va_list ap;
275a2ff8 2329 int code;
d6c9fcf0 2330 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 2331 unsigned long currentavg, maxavg;
2332
1a8c261b 2333 va_start(ap, command);
275a2ff8 2334
2335 /* See code explanations below */
2336 code = va_arg(ap, int);
2337
2338 /*
d6c9fcf0 2339 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
275a2ff8 2340 */
d6c9fcf0 2341 rateclass = va_arg(ap, unsigned long);
275a2ff8 2342
2343 /*
2344 * Not sure what this is exactly. I think its the temporal
2345 * relation factor (ie, how to make the rest of the numbers
2346 * make sense in the real world).
2347 */
2348 windowsize = va_arg(ap, unsigned long);
2349
2350 /* Explained below */
2351 clear = va_arg(ap, unsigned long);
2352 alert = va_arg(ap, unsigned long);
2353 limit = va_arg(ap, unsigned long);
2354 disconnect = va_arg(ap, unsigned long);
2355 currentavg = va_arg(ap, unsigned long);
2356 maxavg = va_arg(ap, unsigned long);
2357
1a8c261b 2358 va_end(ap);
2359
275a2ff8 2360
37ee990e 2361 dvprintf("faimtest: rate %s (rate class 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
275a2ff8 2362 (code < 5)?codes[code]:"invalid",
d6c9fcf0 2363 rateclass,
275a2ff8 2364 currentavg, maxavg,
2365 alert, clear,
2366 limit, disconnect,
2367 windowsize);
2368
2369 if (code == AIM_RATE_CODE_CHANGE) {
2370 /*
2371 * Not real sure when these get sent.
2372 */
2373 if (currentavg >= clear)
2374 aim_conn_setlatency(command->conn, 0);
2375
2376 } else if (code == AIM_RATE_CODE_WARNING) {
2377 /*
2378 * We start getting WARNINGs the first time we go below the 'alert'
2379 * limit (currentavg < alert) and they stop when either we pause
2380 * long enough for currentavg to go above 'clear', or until we
2381 * flood it bad enough to go below 'limit' (and start getting
2382 * LIMITs instead) or even further and go below 'disconnect' and
2383 * get disconnected completely (and won't be able to login right
2384 * away either).
2385 */
2386 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2387
2388 } else if (code == AIM_RATE_CODE_LIMIT) {
2389 /*
2390 * When we hit LIMIT, messages will start getting dropped.
2391 */
2392 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2393
2394 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2395 /*
2396 * The limit is cleared when curavg goes above 'clear'.
2397 */
2398 aim_conn_setlatency(command->conn, 0);
2399 }
1a8c261b 2400
871e2fd0 2401 return 1;
78b3fb13 2402}
98c88242 2403
2404int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2405{
2406 va_list ap;
06bc8607 2407 int newevil;
2408 struct aim_userinfo_s *userinfo;
98c88242 2409
2410 va_start(ap, command);
06bc8607 2411 newevil = va_arg(ap, int);
2412 userinfo = va_arg(ap, struct aim_userinfo_s *);
98c88242 2413 va_end(ap);
2414
06bc8607 2415 /*
2416 * Evil Notifications that are lacking userinfo->sn are anon-warns
2417 * if they are an evil increases, but are not warnings at all if its
2418 * a decrease (its the natural backoff happening).
2419 *
2420 * newevil is passed as an int representing the new evil value times
2421 * ten.
2422 */
37ee990e 2423 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2424
2425 return 1;
2426}
2427
2428int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2429{
2430 va_list ap;
2431 char *address, *SNs;
2432 int i, num;
2433
2434 va_start(ap, command);
2435 address = va_arg(ap, char *);
2436 num = va_arg(ap, int);
2437 SNs = va_arg(ap, char *);
2438 va_end(ap);
2439
2440 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2441
2442 for(i = 0; i < num; i++)
2443 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2444 dinlineprintf("\n");
2445
2446 return 1;
2447}
2448
2449int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2450{
2451 va_list ap;
2452 char *address;
2453
2454 va_start(ap, command);
2455 address = va_arg(ap, char *);
2456 va_end(ap);
2457
2458 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
98c88242 2459
98c88242 2460 return 1;
78b3fb13 2461}
This page took 1.501123 seconds and 5 git commands to generate.