]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Wed May 16 12:48:13 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) {
f6a4f6b7 855 if (!modname) {
856 dperror("memrequest: stat");
857 free(filename);
858 return -1;
859 }
860 invalid = 1;
b1eac25a 861 }
862
f6a4f6b7 863 if (!invalid) {
864 if ((offset > st.st_size) || (len > st.st_size))
865 invalid = 1;
866 else if ((st.st_size - offset) < len)
867 len = st.st_size - offset;
868 else if ((st.st_size - len) < len)
869 len = st.st_size - len;
870 }
83ae98f8 871
872 if (!invalid && len)
873 len %= 4096;
874
875 if (invalid) {
f6a4f6b7 876 int i;
83ae98f8 877
878 free(filename); /* not needed */
879
f6a4f6b7 880 dvprintf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
881
882 i = 8;
883 if (modname)
884 i += strlen(modname);
885
886 if (!(buf = malloc(i)))
83ae98f8 887 return -1;
888
f6a4f6b7 889 i = 0;
890
891 if (modname) {
892 memcpy(buf, modname, strlen(modname));
893 i += strlen(modname);
894 }
83ae98f8 895
896 /* Damn endianness. This must be little (LSB first) endian. */
f6a4f6b7 897 buf[i++] = offset & 0xff;
898 buf[i++] = (offset >> 8) & 0xff;
899 buf[i++] = (offset >> 16) & 0xff;
900 buf[i++] = (offset >> 24) & 0xff;
901 buf[i++] = len & 0xff;
902 buf[i++] = (len >> 8) & 0xff;
903 buf[i++] = (len >> 16) & 0xff;
904 buf[i++] = (len >> 24) & 0xff;
83ae98f8 905
906 *bufret = buf;
f6a4f6b7 907 *buflenret = i;
83ae98f8 908
909 } else {
910
911 if (!(buf = malloc(len))) {
912 free(filename);
913 return -1;
914 }
915
916 dvprintf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename);
917
918 if (!(f = fopen(filename, "r"))) {
919 dperror("memrequest: fopen");
920 free(filename);
921 free(buf);
922 return -1;
923 }
924
925 free(filename);
5ac961d5 926
001c9b80 927 if (fseek(f, offset, SEEK_SET) == -1) {
928 dperror("memrequest: fseek");
929 fclose(f);
83ae98f8 930 free(buf);
001c9b80 931 return -1;
932 }
b1eac25a 933
83ae98f8 934 if (fread(buf, len, 1, f) != 1) {
001c9b80 935 dperror("memrequest: fread");
936 fclose(f);
83ae98f8 937 free(buf);
001c9b80 938 return -1;
939 }
b1eac25a 940
83ae98f8 941 fclose(f);
942
943 *bufret = buf;
944 *buflenret = len;
945
946 }
b1eac25a 947
83ae98f8 948 return 0; /* success! */
b1eac25a 949}
950
951/*
952 * This will get an offset and a length. The client should read this
953 * data out of whatever AIM.EXE binary the user has provided (hopefully
954 * it matches the client information thats sent at login) and pass a
955 * buffer back to libfaim so it can hash the data and send it to AOL for
956 * inspection by the client police.
957 */
958static int faimtest_memrequest(struct aim_session_t *sess, struct command_rx_struct *command, ...)
959{
960 va_list ap;
961 unsigned long offset, len;
328837f7 962 char *modname;
83ae98f8 963 unsigned char *buf;
964 int buflen;
b1eac25a 965
966 va_start(ap, command);
967 offset = va_arg(ap, unsigned long);
968 len = va_arg(ap, unsigned long);
328837f7 969 modname = va_arg(ap, char *);
b1eac25a 970 va_end(ap);
971
83ae98f8 972 if (aimbinarypath && (getaimdata(&buf, &buflen, offset, len, modname) == 0)) {
b1eac25a 973
83ae98f8 974 aim_sendmemblock(sess, command->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 975
83ae98f8 976 free(buf);
b1eac25a 977
978 } else {
979
328837f7 980 dvprintf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", aimbinarypath, modname);
b1eac25a 981
d2698e03 982 aim_sendmemblock(sess, command->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
b1eac25a 983
984 }
985
b1eac25a 986 return 1;
987}
988
989static int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 990{
355982c5 991 va_list ap;
9de3ca7e 992 struct aim_conn_t *bosconn = NULL;
355982c5 993 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
994 unsigned char *cookie = NULL;
995 int errorcode = 0, regstatus = 0;
89bce177 996 int latestbuild = 0, latestbetabuild = 0;
997 char *latestrelease = NULL, *latestbeta = NULL;
998 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
999 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
1000
355982c5 1001 va_start(ap, command);
1002 sn = va_arg(ap, char *);
1003 errorcode = va_arg(ap, int);
1004 errurl = va_arg(ap, char *);
1005 regstatus = va_arg(ap, int);
1006 email = va_arg(ap, char *);
1007 bosip = va_arg(ap, char *);
1008 cookie = va_arg(ap, unsigned char *);
89bce177 1009
1010 latestrelease = va_arg(ap, char *);
1011 latestbuild = va_arg(ap, int);
1012 latestreleaseurl = va_arg(ap, char *);
1013 latestreleaseinfo = va_arg(ap, char *);
1014
1015 latestbeta = va_arg(ap, char *);
1016 latestbetabuild = va_arg(ap, int);
1017 latestbetaurl = va_arg(ap, char *);
1018 latestbetainfo = va_arg(ap, char *);
1019
355982c5 1020 va_end(ap);
01b59e1e 1021
37ee990e 1022 dvprintf("Screen name: %s\n", sn);
01b59e1e 1023
1024 /*
1025 * Check for error.
1026 */
355982c5 1027 if (errorcode || !bosip || !cookie) {
37ee990e 1028 dvprintf("Login Error Code 0x%04x\n", errorcode);
1029 dvprintf("Error URL: %s\n", errurl);
9bf14d44 1030 aim_conn_kill(sess, &command->conn);
355982c5 1031 return 1;
1032 }
01b59e1e 1033
37ee990e 1034 dvprintf("Reg status: %2d\n", regstatus);
1035 dvprintf("Email: %s\n", email);
1036 dvprintf("BOS IP: %s\n", bosip);
9de3ca7e 1037
89bce177 1038 if (latestbeta)
37ee990e 1039 dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
89bce177 1040
1041 if (latestrelease)
37ee990e 1042 dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
89bce177 1043
37ee990e 1044 dprintf("Closing auth connection...\n");
040457cc 1045 aim_conn_kill(sess, &command->conn);
355982c5 1046 if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
37ee990e 1047 dprintf("faimtest: could not connect to BOS: internal error\n");
355982c5 1048 return 1;
22517493 1049 } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
37ee990e 1050 dprintf("faimtest: could not connect to BOS\n");
040457cc 1051 aim_conn_kill(sess, &bosconn);
355982c5 1052 return 1;
1053 }
1054
1055 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1056 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
1057 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
1058 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
ee49b735 1059 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
355982c5 1060 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
1061 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
1062 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
1063 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
1064 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
1065 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
1066 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
1067 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1068 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
1069 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
1070 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
1071 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
37ee990e 1072 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
1073 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
355982c5 1074 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
1075 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
1076 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
1077
355982c5 1078 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
00ef5271 1079
1080 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1449ad2b 1081 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
1082 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
1083 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
1084
355982c5 1085 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
b1eac25a 1086 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, faimtest_memrequest, 0);
d32954e7 1087 aim_conn_addhandler(sess, bosconn, 0xffff, 0xffff, faimtest_parse_unknown, 0);
1449ad2b 1088
355982c5 1089 aim_auth_sendcookie(sess, bosconn, cookie);
1090
9de3ca7e 1091 return 1;
1092}
1093
a15d82b1 1094static void printuserflags(unsigned short flags)
1095{
1096 if (flags & AIM_FLAG_UNCONFIRMED)
37ee990e 1097 dinlineprintf("UNCONFIRMED ");
a15d82b1 1098 if (flags & AIM_FLAG_ADMINISTRATOR)
37ee990e 1099 dinlineprintf("ADMINISTRATOR ");
a15d82b1 1100 if (flags & AIM_FLAG_AOL)
37ee990e 1101 dinlineprintf("AOL ");
a15d82b1 1102 if (flags & AIM_FLAG_OSCAR_PAY)
37ee990e 1103 dinlineprintf("OSCAR_PAY ");
a15d82b1 1104 if (flags & AIM_FLAG_FREE)
37ee990e 1105 dinlineprintf("FREE ");
a15d82b1 1106 if (flags & AIM_FLAG_AWAY)
37ee990e 1107 dinlineprintf("AWAY ");
a15d82b1 1108 if (flags & AIM_FLAG_UNKNOWN40)
37ee990e 1109 dinlineprintf("ICQ? ");
a15d82b1 1110 if (flags & AIM_FLAG_UNKNOWN80)
37ee990e 1111 dinlineprintf("UNKNOWN80 ");
a15d82b1 1112 return;
1113}
1114
397055b1 1115int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1116{
1117 struct aim_userinfo_s *userinfo;
1118 char *prof_encoding = NULL;
1119 char *prof = NULL;
5e02cf44 1120 unsigned short inforeq = 0;
9de3ca7e 1121
1122 va_list ap;
1123 va_start(ap, command);
1124 userinfo = va_arg(ap, struct aim_userinfo_s *);
1125 prof_encoding = va_arg(ap, char *);
1126 prof = va_arg(ap, char *);
e7fb57f5 1127 inforeq = va_arg(ap, int);
9de3ca7e 1128 va_end(ap);
1129
37ee990e 1130 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
1131 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
1132 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
a15d82b1 1133 printuserflags(userinfo->flags);
37ee990e 1134 dinlineprintf("\n");
9de3ca7e 1135
37ee990e 1136 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
1137 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1138 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
9de3ca7e 1139
5e02cf44 1140 if (inforeq == AIM_GETINFO_GENERALINFO) {
37ee990e 1141 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1142 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
5e02cf44 1143 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
37ee990e 1144 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1145 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
5e02cf44 1146 } else
37ee990e 1147 dprintf("faimtest: userinfo: unknown info request\n");
9de3ca7e 1148
1149 return 1;
1150}
1151
d2587300 1152static int faimtest_handlecmd(struct aim_session_t *sess, struct command_rx_struct *command, struct aim_userinfo_s *userinfo, char *tmpstr)
1153{
1154
1155 if (!strncmp(tmpstr, "disconnect", 10)) {
1156
1157 logout();
1158
1159 } else if (strstr(tmpstr, "goodday")) {
1160
a2244dd9 1161 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.", strlen("Good day to you too."));
d2587300 1162
1163 } else if (strstr(tmpstr, "warnme")) {
1164
1165 dprintf("faimtest: icbm: sending non-anon warning\n");
1166 aim_send_warning(sess, command->conn, userinfo->sn, 0);
1167
1168 } else if (strstr(tmpstr, "anonwarn")) {
1169
1170 dprintf("faimtest: icbm: sending anon warning\n");
1171 aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
1172
1173 } else if (strstr(tmpstr, "setdirectoryinfo")) {
1174
1175 dprintf("faimtest: icbm: sending backwards profile data\n");
1176 aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1177
1178 } else if (strstr(tmpstr, "setinterests")) {
1179
1180 dprintf("faimtest: icbm: setting fun interests\n");
1181 aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1182
1183 } else if (!strncmp(tmpstr, "getfile", 7)) {
1184
1185 if (!ohcaptainmycaptain) {
1186
a2244dd9 1187 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!", strlen("I have no owner!"));
d2587300 1188
1189 } else {
1190 struct aim_conn_t *newconn;
1191
1192 newconn = aim_getfile_initiate(sess, command->conn, (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1193 dvprintf("faimtest: getting file listing from %s\n", (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
1194 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE, faimtest_getfile_initiate,0);
1195 }
1196
1197 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1198
1199 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
1200
1201 } else if (!strncmp(tmpstr, "create", 6)) {
1202
1203 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1204
1205 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1206 struct aim_conn_t *chatnavconn;
1207
1208 chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
1209 aim_conn_kill(sess, &chatnavconn);
1210
1211 } else if (!strncmp(tmpstr, "join", 4)) {
1212
1213 aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
1214
1215 } else if (!strncmp(tmpstr, "leave", 5)) {
1216
1217 aim_chat_leaveroom(sess, "worlddomination");
1218
1219 } else if (!strncmp(tmpstr, "getinfo", 7)) {
1220
1221 aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
1222 aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
00ef5271 1223 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
1224 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
d2587300 1225
1226 } else if (!strncmp(tmpstr, "open directim", 13)) {
1227 struct aim_conn_t *newconn;
1228
1229 printf("faimtest: opening directim to %s\n", (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1230 newconn = aim_directim_initiate(sess, command->conn, NULL, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1231 if(!newconn || newconn->fd == -1)
1232 printf("connection failed!\n");
1233 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate,0);
1234
1235 } else if(!(strncmp(tmpstr, "lookup", 6))) {
1236
1237 aim_usersearch_address(sess, command->conn, tmpstr+7);
1238
1239 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1240
a2244dd9 1241 aim_send_im(sess, command->conn, ohcaptainmycaptain, 0, "sendmsg 7900", strlen("sendmsg 7900"));
d2587300 1242
1243 } else if (!strncmp(tmpstr, "reqauth", 7)) {
1244
1245 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
1246
1247 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1248
1249 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1250
1251 } else if (!strncmp(tmpstr, "reqemail", 8)) {
1252
1253 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1254
1255 } else if (!strncmp(tmpstr, "changepass", 8)) {
1256
1257 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1258
1259 } else if (!strncmp(tmpstr, "setemail", 8)) {
1260
1261 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1262
1263 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1264 int i;
1265 i = atoi(tmpstr+8);
1266 if (i < 10000) {
1267 char *newbuf;
1268 int z;
1269
1270 newbuf = malloc(i+1);
1271 for (z = 0; z < i; z++) {
1272 newbuf[z] = (z % 10)+0x30;
1273 }
1274 newbuf[i] = '\0';
a2244dd9 1275 aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf, strlen(newbuf));
d2587300 1276 free(newbuf);
1277 }
1278
1279 } else {
1280
1281 dprintf("unknown command.\n");
1282 aim_add_buddy(sess, command->conn, userinfo->sn);
1283
1284 }
1285
1286 return 0;
1287}
1288
9de3ca7e 1289/*
1290 * The user-level Incoming ICBM callback.
1291 *
9de3ca7e 1292 */
397055b1 1293int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1294{
26af6789 1295 int channel;
9de3ca7e 1296 va_list ap;
9de3ca7e 1297
1298 va_start(ap, command);
26af6789 1299 channel = va_arg(ap, int);
9de3ca7e 1300
26af6789 1301 /*
1302 * Channel 1: Standard Message
1303 */
040457cc 1304 if (channel == 1) {
1305 struct aim_userinfo_s *userinfo;
1306 char *msg = NULL;
1307 u_int icbmflags = 0;
1308 char *tmpstr = NULL;
e7fb57f5 1309 unsigned short flag1, flag2;
9d83220c 1310 int finlen = 0;
1311 unsigned char *fingerprint = NULL;
1312 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
040457cc 1313
1314 userinfo = va_arg(ap, struct aim_userinfo_s *);
1315 msg = va_arg(ap, char *);
1316 icbmflags = va_arg(ap, u_int);
e7fb57f5 1317 flag1 = va_arg(ap, int);
1318 flag2 = va_arg(ap, int);
9d83220c 1319 finlen = va_arg(ap, int);
1320 fingerprint = va_arg(ap, unsigned char *);
040457cc 1321 va_end(ap);
1322
9d83220c 1323 clienttype = aim_fingerprintclient(fingerprint, finlen);
1324
37ee990e 1325 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
9d83220c 1326 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
37ee990e 1327 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1328 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
a15d82b1 1329 printuserflags(userinfo->flags);
37ee990e 1330 dinlineprintf("\n");
a15d82b1 1331
37ee990e 1332 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1333 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1334 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1335 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
040457cc 1336
37ee990e 1337 dprintf("faimtest: icbm: icbmflags = ");
040457cc 1338 if (icbmflags & AIM_IMFLAGS_AWAY)
37ee990e 1339 dinlineprintf("away ");
040457cc 1340 if (icbmflags & AIM_IMFLAGS_ACK)
37ee990e 1341 dinlineprintf("ackrequest ");
1342 dinlineprintf("\n");
040457cc 1343
37ee990e 1344 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
040457cc 1345
37ee990e 1346 dvprintf("faimtest: icbm: message: %s\n", msg);
040457cc 1347
1348 if (msg) {
b69540e3 1349 int i = 0;
1350
1351 while (msg[i] == '<') {
1352 if (msg[i] == '<') {
1353 while (msg[i] != '>')
1354 i++;
1355 i++;
1356 }
1357 }
1358 tmpstr = msg+i;
1359
d2587300 1360 faimtest_handlecmd(sess, command, userinfo, tmpstr);
1361
040457cc 1362 }
1363 }
1364 /*
1365 * Channel 2: Rendevous Request
1366 */
1367 else if (channel == 2) {
1368 struct aim_userinfo_s *userinfo;
1369 unsigned short reqclass;
1370
e7fb57f5 1371 reqclass = va_arg(ap, int);
040457cc 1372 switch (reqclass) {
b69540e3 1373 case AIM_CAPS_VOICE: {
26af6789 1374 userinfo = va_arg(ap, struct aim_userinfo_s *);
26af6789 1375 va_end(ap);
9de3ca7e 1376
37ee990e 1377 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1378 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1379 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1380 printuserflags(userinfo->flags);
37ee990e 1381 dinlineprintf("\n");
a15d82b1 1382
040457cc 1383 /* we dont get membersince on chat invites! */
37ee990e 1384 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1385 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1386
040457cc 1387 break;
1388 }
b69540e3 1389 case AIM_CAPS_GETFILE: {
871e2fd0 1390 char *ip, *cookie;
1391 struct aim_conn_t *newconn;
37ee990e 1392 struct aim_fileheader_t *fh;
871e2fd0 1393
1394 userinfo = va_arg(ap, struct aim_userinfo_s *);
1395 ip = va_arg(ap, char *);
1396 cookie = va_arg(ap, char *);
1397 va_end(ap);
1398
646c6b52 1399 dvprintf("faimtest: get file request from %s (at %s) %x\n", userinfo->sn, ip, reqclass);
1400
1401 fh = aim_getlisting(sess, listingfile);
871e2fd0 1402
646c6b52 1403 newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, fh->totfiles, fh->totsize, fh->size, fh->checksum, reqclass);
871e2fd0 1404
646c6b52 1405 if( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1406 dprintf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
646c6b52 1407 if(newconn)
1408 aim_conn_kill(sess, &newconn);
871e2fd0 1409 break;
1410 }
37ee990e 1411
1412 free(fh);
1413
1414 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
871e2fd0 1415 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1416 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1417 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
37ee990e 1418
871e2fd0 1419 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1420
37ee990e 1421 dprintf("faimtest: getfile connect succeeded, handlers added.\n");
871e2fd0 1422
040457cc 1423 break;
1424 }
b69540e3 1425 case AIM_CAPS_SENDFILE: {
37ee990e 1426 dprintf("faimtest: send file!\n");
b69540e3 1427 break;
1428 }
1429 case AIM_CAPS_CHAT: {
040457cc 1430 char *msg,*encoding,*lang;
1431 struct aim_chat_roominfo *roominfo;
26af6789 1432
040457cc 1433 userinfo = va_arg(ap, struct aim_userinfo_s *);
1434 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1435 msg = va_arg(ap, char *);
1436 encoding = va_arg(ap, char *);
1437 lang = va_arg(ap, char *);
1438 va_end(ap);
26af6789 1439
37ee990e 1440 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1441 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1442 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1443 printuserflags(userinfo->flags);
37ee990e 1444 dinlineprintf("\n");
a15d82b1 1445
040457cc 1446 /* we dont get membersince on chat invites! */
37ee990e 1447 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1448 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1449
37ee990e 1450 dvprintf("faimtest: chat invitation: message = %s\n", msg);
1451 dvprintf("faimtest: chat invitation: room name = %s\n", roominfo->name);
1452 dvprintf("faimtest: chat invitation: encoding = %s\n", encoding);
1453 dvprintf("faimtest: chat invitation: language = %s\n", lang);
1454 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
1455 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
1456 dvprintf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
040457cc 1457 /*
1458 * Automatically join room...
1459 */
1460 aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
1461 break;
1462 }
7392c79f 1463 case AIM_CAPS_IMIMAGE: {
1464 struct aim_directim_priv *priv;
1465 struct aim_conn_t *newconn;
1466
37ee990e 1467 dprintf("faimtest: icbm: rendezvous imimage\n");
7392c79f 1468
1469 userinfo = va_arg(ap, struct aim_userinfo_s *);
1470 priv = va_arg(ap, struct aim_directim_priv *);
1471 va_end(ap);
1472
37ee990e 1473 dvprintf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
7392c79f 1474
646c6b52 1475 newconn = aim_directim_connect(sess, command->conn, priv);
1476
1477 if ( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1478 dprintf("faimtest: icbm: imimage: could not connect\n");
646c6b52 1479
1480 if (newconn)
1481 aim_conn_kill(sess, &newconn);
1482
7392c79f 1483 break;
1484 }
646c6b52 1485
7392c79f 1486 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1487 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1488 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1489
37ee990e 1490 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
7392c79f 1491
3b101546 1492 aim_send_im_direct(sess, newconn, "goodday");
1493
7392c79f 1494 break;
1495 }
040457cc 1496 default:
37ee990e 1497 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
040457cc 1498 } /* switch */
1499 } else
37ee990e 1500 dvprintf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1501 dprintf("faimtest: icbm: done with ICBM handling\n");
9de3ca7e 1502
1503 return 1;
1504}
1505
7392c79f 1506int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1507{
1508 va_list ap;
1509 struct aim_directim_priv *priv;
646c6b52 1510 struct aim_conn_t *newconn, *listenerconn;
7392c79f 1511
e7fb57f5 1512 va_start(ap, command);
7392c79f 1513 newconn = va_arg(ap, struct aim_conn_t *);
646c6b52 1514 listenerconn = va_arg(ap, struct aim_conn_t *);
7392c79f 1515 va_end(ap);
1516
646c6b52 1517 aim_conn_close(listenerconn);
1518 aim_conn_kill(sess, &listenerconn);
1519
7392c79f 1520 priv = (struct aim_directim_priv *)newconn->priv;
1521
37ee990e 1522 dvprintf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
7392c79f 1523
1524 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1525 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1526 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1527
1528 aim_send_im_direct(sess, newconn, "goodday");
1529
37ee990e 1530 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
7392c79f 1531
1532 return 1;
1533}
7392c79f 1534
1535int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1536{
1537 va_list ap;
1538 struct aim_directim_priv *priv;
1539
e7fb57f5 1540 va_start(ap, command);
7392c79f 1541 priv = va_arg(ap, struct aim_directim_priv *);
1542
1543 va_end(ap);
1544
37ee990e 1545 dprintf("faimtest: directim_connect\n");
7392c79f 1546
1547 return 1;
1548}
1549
1550int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1551{
1552 va_list ap;
9e8c4225 1553 char *msg = NULL;
7392c79f 1554 struct aim_conn_t *conn;
9e8c4225 1555 struct aim_directim_priv *priv;
7392c79f 1556
e7fb57f5 1557 va_start(ap, command);
7392c79f 1558 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1559 msg = va_arg(ap, char *);
1560 va_end(ap);
1561
9e8c4225 1562 if(!(priv = conn->priv)) {
1563 dvprintf("faimtest: directim: no private struct on conn with fd %d\n", conn->fd);
1564 return -1;
1565 }
1566
1567 dvprintf("faimtest: Directim from %s: %s\n", priv->sn, msg);
7392c79f 1568 if (!strncmp(msg, "sendmsg", 7)) {
1569 int i;
1570 i = atoi(msg+8);
1571 if (i < 10000) {
1572 char *newbuf;
1573 int z;
1574
1575 newbuf = malloc(i+1);
1576 for (z = 0; z < i; z++) {
1577 newbuf[z] = (z % 10)+0x30;
1578 }
1579 newbuf[i] = '\0';
1580 aim_send_im_direct(sess, conn, newbuf);
1581 free(newbuf);
1582 }
1583 } else if (!strncmp(msg, "goodday", 7)) {
1584 aim_send_im_direct(sess, conn, "Good day to you, too");
1585 } else {
1586 char newmsg[1024];
1587 snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1588 aim_send_im_direct(sess, conn, newmsg);
1589 }
1590 return 1;
1591}
1592
1593int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1594{
871e2fd0 1595 va_list ap;
1596 struct aim_conn_t *conn;
1597 char *sn;
1598
e7fb57f5 1599 va_start(ap, command);
871e2fd0 1600 conn = va_arg(ap, struct aim_conn_t *);
1601 sn = va_arg(ap, char *);
1602 va_end(ap);
1603
37ee990e 1604 dvprintf("faimtest: directim: disconnected from %s\n", sn);
3b101546 1605
1606 aim_conn_kill(sess, &conn);
7392c79f 1607 return 1;
1608}
1609
1610int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1611{
1612 va_list ap;
9e8c4225 1613 struct aim_conn_t *conn;
1614 struct aim_directim_priv *priv;
1615
e7fb57f5 1616 va_start(ap, command);
9e8c4225 1617 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1618 va_end(ap);
9e8c4225 1619
1620 if(!(priv = (struct aim_directim_priv *)conn->priv)) {
1621 dvprintf("faimtest: no private struct on conn with fd %d!\n", conn->fd);
1622 return -1;
1623 }
7392c79f 1624
9e8c4225 1625 dvprintf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
7392c79f 1626 return 1;
1627}
1628
64c78745 1629int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1630{
64c78745 1631 unsigned short change = 0;
1632 int perms, type, length, str;
1633 char *val;
1634 va_list ap;
9de3ca7e 1635
64c78745 1636 va_start(ap, command);
1637 perms = va_arg(ap, int);
1638 type = va_arg(ap, int);
1639 length = va_arg(ap, int);
1640 val = va_arg(ap, char *);
1641 str = va_arg(ap, int);
1642 va_end(ap);
9de3ca7e 1643
64c78745 1644 if (aimutil_get16(command->data+2) == 0x0005)
1645 change = 1;
1646
1647 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
9de3ca7e 1648
9de3ca7e 1649 return 1;
1650}
1651
397055b1 1652int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1653{
1654 struct aim_userinfo_s *userinfo;
1655
1656 va_list ap;
1657 va_start(ap, command);
1658 userinfo = va_arg(ap, struct aim_userinfo_s *);
1659 va_end(ap);
1660
37ee990e 1661 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
ee49b735 1662 time(NULL),
a15d82b1 1663 userinfo->sn, userinfo->flags,
1664 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1665 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1666 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1667 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1668 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1669 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1670 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1671 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
b69540e3 1672 userinfo->capabilities);
9de3ca7e 1673 return 1;
1674}
1675
397055b1 1676int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1677{
69e7980c 1678 struct aim_userinfo_s *userinfo;
1679
397055b1 1680 va_list ap;
397055b1 1681 va_start(ap, command);
69e7980c 1682 userinfo = va_arg(ap, struct aim_userinfo_s *);
397055b1 1683 va_end(ap);
9de3ca7e 1684
69e7980c 1685 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1686 time(NULL),
1687 userinfo->sn, userinfo->flags,
1688 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1689 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1690 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1691 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1692 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1693 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1694 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1695 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1696 userinfo->capabilities);
9de3ca7e 1697 return 1;
1698}
1699
01b59e1e 1700int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1701{
96f8b1ed 1702 static char *codes[] = {
1703 "Unknown",
1704 "Mandatory upgrade",
1705 "Advisory upgrade",
1706 "System bulletin",
1707 "Top o' the world!"};
1708 static int codeslen = 5;
1709
01b59e1e 1710 char *msg;
96f8b1ed 1711 unsigned short id;
01b59e1e 1712 va_list ap;
1713
1714 va_start(ap, command);
e7fb57f5 1715 id = va_arg(ap, int);
01b59e1e 1716 msg = va_arg(ap, char *);
1717 va_end(ap);
1718
37ee990e 1719 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1720 (id < codeslen)?codes[id]:"unknown");
96f8b1ed 1721
ee49b735 1722 if (!connected)
1723 connected++;
1724
e80a0fa9 1725#if 0
1726 aim_bos_reqservice(sess, command->conn, 0x0005); /* adverts */
1727 aim_bos_reqservice(sess, command->conn, 0x000f); /* user directory */
1728
1729 /* Don't know what this does... */
1730 /* XXX sess->sn should be normalized by the 0001/000f handler */
1731 aim_0002_000b(sess, command->conn, sess->sn);
1732#endif
1733
96f8b1ed 1734 return 1;
1735}
1736
1449ad2b 1737int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1738{
1739 va_list ap;
1740 unsigned short reason;
1741
1742 va_start(ap, command);
1743 reason = va_arg(ap, int);
1744 va_end(ap);
1745
37ee990e 1746 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1449ad2b 1747
1748 return 1;
1749}
1750
96f8b1ed 1751int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1752{
1753 va_list ap;
1754 char *destsn;
1755 unsigned short reason;
1756
1757 va_start(ap, command);
e7fb57f5 1758 reason = va_arg(ap, int);
00ef5271 1759 destsn = va_arg(ap, char *);
96f8b1ed 1760 va_end(ap);
1761
37ee990e 1762 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1763
1764 return 1;
1765}
1766
1767int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1768{
1769 va_list ap;
1770 char *destsn;
1771 unsigned short reason;
1772
1773 va_start(ap, command);
e7fb57f5 1774 reason = va_arg(ap, int);
00ef5271 1775 destsn = va_arg(ap, char *);
96f8b1ed 1776 va_end(ap);
01b59e1e 1777
37ee990e 1778 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1779
01b59e1e 1780 return 1;
1781}
9de3ca7e 1782
1783/*
96f8b1ed 1784 * Handles callbacks for AIM_CB_MISSED_CALL.
9de3ca7e 1785 */
397055b1 1786int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1787{
96f8b1ed 1788 static char *missedreasons[] = {
1789 "Unknown",
1790 "Message too large"};
1791 static int missedreasonslen = 2;
9de3ca7e 1792
96f8b1ed 1793 va_list ap;
1794 unsigned short chan, nummissed, reason;
1795 struct aim_userinfo_s *userinfo;
9de3ca7e 1796
96f8b1ed 1797 va_start(ap, command);
e7fb57f5 1798 chan = va_arg(ap, int);
96f8b1ed 1799 userinfo = va_arg(ap, struct aim_userinfo_s *);
e7fb57f5 1800 nummissed = va_arg(ap, int);
1801 reason = va_arg(ap, int);
96f8b1ed 1802 va_end(ap);
9de3ca7e 1803
37ee990e 1804 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
96f8b1ed 1805
00f3b08b 1806 return 1;
9de3ca7e 1807}
1808
01b59e1e 1809int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1810{
154b4093 1811 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
78b3fb13 1812 char *key;
b5bc2a8c 1813 va_list ap;
01b59e1e 1814
b5bc2a8c 1815 va_start(ap, command);
1816 key = va_arg(ap, char *);
1817 va_end(ap);
9de3ca7e 1818
b5bc2a8c 1819 aim_send_login(sess, command->conn, screenname, password, &info, key);
01b59e1e 1820
1821 return 1;
1822}
0c20631f 1823
1824int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1825{
1826 va_list ap;
1827 struct aim_userinfo_s *userinfo;
1828 int count = 0, i = 0;
1829
1830 va_start(ap, command);
1831 count = va_arg(ap, int);
1832 userinfo = va_arg(ap, struct aim_userinfo_s *);
1833 va_end(ap);
1834
37ee990e 1835 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
0c20631f 1836 while (i < count)
37ee990e 1837 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1838
1839 return 1;
1840}
1841
1842int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1843{
1844 va_list ap;
1845 struct aim_userinfo_s *userinfo;
1846 int count = 0, i = 0;
1847
1848 va_start(ap, command);
1849 count = va_arg(ap, int);
1850 userinfo = va_arg(ap, struct aim_userinfo_s *);
1851 va_end(ap);
1852
37ee990e 1853 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1854
1855 for (i = 0; i < count; )
1856 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1857
1858 return 1;
1859}
1860
1861int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1862{
1863 va_list ap;
1864 struct aim_userinfo_s *userinfo;
1865 struct aim_chat_roominfo *roominfo;
1866 char *roomname;
1867 int usercount,i;
1868 char *roomdesc;
aa6efcfd 1869 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1870 unsigned long creationtime;
0c20631f 1871
1872 va_start(ap, command);
1873 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1874 roomname = va_arg(ap, char *);
1875 usercount= va_arg(ap, int);
1876 userinfo = va_arg(ap, struct aim_userinfo_s *);
1877 roomdesc = va_arg(ap, char *);
e7fb57f5 1878 unknown_c9 = va_arg(ap, int);
aa6efcfd 1879 creationtime = va_arg(ap, unsigned long);
e7fb57f5 1880 maxmsglen = va_arg(ap, int);
1881 unknown_d2 = va_arg(ap, int);
1882 unknown_d5 = va_arg(ap, int);
0c20631f 1883 va_end(ap);
1884
37ee990e 1885 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1886 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
0c20631f 1887 (char *)command->conn->priv,
1888 roominfo->exchange,
1889 roominfo->name,
1890 roominfo->instance);
37ee990e 1891 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1892 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1893 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
0c20631f 1894
37ee990e 1895 for (i = 0; i < usercount; )
1896 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1897
37ee990e 1898 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1899 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1900 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1901 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1902 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
aa6efcfd 1903
0c20631f 1904 return 1;
1905}
1906
1907int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1908{
1909 va_list ap;
1910 struct aim_userinfo_s *userinfo;
1911 char *msg;
1912 char tmpbuf[1152];
1913
1914 va_start(ap, command);
1915 userinfo = va_arg(ap, struct aim_userinfo_s *);
1916 msg = va_arg(ap, char *);
1917 va_end(ap);
1918
37ee990e 1919 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
0c20631f 1920
1921 /*
1922 * Do an echo for testing purposes. But not for ourselves ("oops!")
1923 */
355982c5 1924 if (strcmp(userinfo->sn, sess->sn) != 0)
0c20631f 1925 {
1926 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
a2244dd9 1927 aim_chat_send_im(sess, command->conn, 0, tmpbuf, strlen(tmpbuf));
0c20631f 1928 }
1929
1930 return 1;
1931}
1932
1933int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1934{
e7fb57f5 1935 unsigned short type;
0c20631f 1936 va_list ap;
1937
e7fb57f5 1938 va_start(ap, command);
1939 type = va_arg(ap, int);
0c20631f 1940
efe9513b 1941 switch(type) {
1942 case 0x0002: {
1943 int maxrooms;
1944 struct aim_chat_exchangeinfo *exchanges;
1945 int exchangecount,i = 0;
1946
e7fb57f5 1947 maxrooms = va_arg(ap, int);
efe9513b 1948 exchangecount = va_arg(ap, int);
1949 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1950 va_end(ap);
1951
37ee990e 1952 dprintf("faimtest: chat info: Chat Rights:\n");
1953 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
efe9513b 1954
37ee990e 1955 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1956 for (i = 0; i < exchangecount; i++) {
1957 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1958 exchanges[i].number,
1959 exchanges[i].name,
1960 exchanges[i].charset1,
1961 exchanges[i].lang1);
0c20631f 1962 }
efe9513b 1963
1964 }
1965 break;
1966 case 0x0008: {
1967 char *fqcn, *name, *ck;
9dbda50b 1968 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
efe9513b 1969 unsigned char createperms;
1970 unsigned long createtime;
1971
1972 fqcn = va_arg(ap, char *);
e7fb57f5 1973 instance = va_arg(ap, int);
9dbda50b 1974 exchange = va_arg(ap, int);
e7fb57f5 1975 flags = va_arg(ap, int);
efe9513b 1976 createtime = va_arg(ap, unsigned long);
e7fb57f5 1977 maxmsglen = va_arg(ap, int);
1978 maxoccupancy = va_arg(ap, int);
1979 createperms = va_arg(ap, int);
1980 unknown = va_arg(ap, int);
efe9513b 1981 name = va_arg(ap, char *);
1982 ck = va_arg(ap, char *);
1983 va_end(ap);
1984
646c6b52 1985 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
efe9513b 1986 }
1987 break;
1988 default:
1989 va_end(ap);
37ee990e 1990 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
efe9513b 1991 }
0c20631f 1992 return 1;
1993}
5e02cf44 1994
1995int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1996{
1997 va_list ap;
1998 unsigned short code;
1999 char *msg = NULL;
2000
e7fb57f5 2001 va_start(ap, command);
2002 code = va_arg(ap, int);
5e02cf44 2003 msg = va_arg(ap, char *);
2004 va_end(ap);
2005
37ee990e 2006 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
68ac63c2 2007 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
5e02cf44 2008
d32954e7 2009 connected = 0;
2010
5e02cf44 2011 return 1;
2012}
e5012450 2013
2014int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2015{
37ee990e 2016 dprintf("faimtest: connecting to an aimdebugd!\n");
e5012450 2017
2018 /* convert the authorizer connection to a BOS connection */
2019 command->conn->type = AIM_CONN_TYPE_BOS;
2020
2021 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
2022
2023 /* tell the aimddebugd we're ready */
2024 aim_debugconn_sendconnect(sess, command->conn);
2025
2026 /* go right into main loop (don't open a BOS connection, etc) */
2027 return 1;
2028}
1a8c261b 2029
2030/*
646c6b52 2031 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 2032 */
2033int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2034{
2035 va_list ap;
2036 unsigned short type;
2037 char *sn = NULL;
2038
e7fb57f5 2039 va_start(ap, command);
2040 type = va_arg(ap, int);
1a8c261b 2041 sn = va_arg(ap, char *);
2042 va_end(ap);
2043
37ee990e 2044 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 2045
2046 return 1;
2047}
2048
871e2fd0 2049int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
2050{
2051 va_list ap;
2052 struct aim_conn_t *oftconn;
2053 struct aim_fileheader_t *fh;
2054 char *cookie;
2055
e7fb57f5 2056 va_start(ap, command);
871e2fd0 2057 oftconn = va_arg(ap, struct aim_conn_t *);
2058 fh = va_arg(ap, struct aim_fileheader_t *);
2059 cookie = va_arg(ap, char *);
2060 va_end(ap);
2061
37ee990e 2062 dvprintf("faimtest: request for file %s.\n", fh->name);
871e2fd0 2063
2064 return 1;
2065}
2066
2067
2068int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2069{
2070 va_list ap;
2071 struct aim_conn_t *oftconn;
2072 struct aim_fileheader_t *fh;
2073 char *path, *cookie;
646c6b52 2074 int pos, bufpos = 0, bufsize = 2048, i;
2075 char *buf;
871e2fd0 2076
2077 FILE *file;
2078
e7fb57f5 2079 va_start(ap, command);
871e2fd0 2080 oftconn = va_arg(ap, struct aim_conn_t *);
2081 fh = va_arg(ap, struct aim_fileheader_t *);
2082 cookie = va_arg(ap, char *);
2083 va_end(ap);
2084
37ee990e 2085 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
871e2fd0 2086
646c6b52 2087 if(!(buf = malloc(2048)))
2088 return -1;
2089
37ee990e 2090 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
2091 dperror("calloc");
2092 dprintf("faimtest: error in calloc of path\n");
871e2fd0 2093 return 0; /* XXX: no idea what winaim expects here =) */
2094 }
2095
37ee990e 2096 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
871e2fd0 2097
2098
2099 if( (file = fopen(path, "r")) == NULL) {
37ee990e 2100 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
871e2fd0 2101 return 0;
2102 }
646c6b52 2103
2104 /*
2105 * This is a mess. Remember that faimtest is demonstration code
2106 * only and for the sake of the gods, don't use this code in any
2107 * of your clients. --mid
2108 */
37ee990e 2109 for(pos = 0; pos < fh->size; pos++) {
2110 bufpos = pos % bufsize;
2111
2112 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2113 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2114 dperror("faim: getfile_send: write1");
2115 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2116 free(buf);
2117 return -1;
2118 }
2119 }
2120 if( (buf[bufpos] = fgetc(file)) == EOF) {
2121 if(pos != fh->size) {
2122 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2123 free(buf);
2124 return -1;
2125 }
2126 }
2127 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
2128 }
871e2fd0 2129
37ee990e 2130 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2131 dperror("faim: getfile_send: write2");
2132 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2133 free(buf);
2134 return -1;
871e2fd0 2135 }
2136
646c6b52 2137 free(buf);
871e2fd0 2138 free(fh);
2139 return 1;
2140}
2141
2142int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2143{
2144 va_list ap;
2145 struct aim_conn_t *conn;
2146 struct aim_fileheader_t *fh;
2147
e7fb57f5 2148 va_start(ap, command);
871e2fd0 2149 conn = va_arg(ap, struct aim_conn_t *);
2150 fh = va_arg(ap, struct aim_fileheader_t *);
2151 va_end(ap);
2152
37ee990e 2153 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
871e2fd0 2154
37ee990e 2155 aim_conn_close(conn);
2156 aim_conn_kill(sess, &conn);
871e2fd0 2157 return 1;
2158}
2159
2160int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2161{
2162 va_list ap;
2163 struct aim_conn_t *conn;
2164 char *sn;
2165
e7fb57f5 2166 va_start(ap, command);
871e2fd0 2167 conn = va_arg(ap, struct aim_conn_t *);
2168 sn = va_arg(ap, char *);
2169 va_end(ap);
2170
2171 aim_conn_kill(sess, &conn);
2172
37ee990e 2173 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
2174 return 1;
2175}
2176int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2177{
2178 va_list ap;
646c6b52 2179 struct aim_conn_t *conn, *listenerconn;
37ee990e 2180 struct aim_filetransfer_priv *priv;
2181
2182 va_start(ap, command);
2183 conn = va_arg(ap, struct aim_conn_t *);
646c6b52 2184 listenerconn = va_arg(ap, struct aim_conn_t *);
37ee990e 2185 va_end(ap);
2186
646c6b52 2187 aim_conn_close(listenerconn);
2188 aim_conn_kill(sess, &listenerconn);
2189
37ee990e 2190 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
2191 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
2192 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
2193 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
2194 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
2195 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
646c6b52 2196 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
2197 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
37ee990e 2198
2199 priv = (struct aim_filetransfer_priv *)conn->priv;
2200
646c6b52 2201 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
871e2fd0 2202 return 1;
2203}
871e2fd0 2204
37ee990e 2205int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2206{
2207 va_list ap;
2208 struct aim_conn_t *conn;
2209 char *listing;
2210 struct aim_filetransfer_priv *ft;
2211 char *filename, *nameend, *sizec;
2212 int filesize, namelen;
2213
2214 va_start(ap, command);
2215 conn = va_arg(ap, struct aim_conn_t *);
2216 ft = va_arg(ap, struct aim_filetransfer_priv *);
2217 listing = va_arg(ap, char *);
2218 va_end(ap);
2219
2220 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2221
2222 nameend = strstr(listing+0x1a, "\r");
2223
2224 namelen = nameend - (listing + 0x1a);
2225
2226 filename = malloc(namelen + 1);
2227 strncpy(filename, listing+0x1a, namelen);
2228 filename[namelen] = 0x00;
2229
2230 sizec = malloc(8+1);
2231 memcpy(sizec, listing + 0x11, 8);
2232 sizec[8] = 0x00;
2233
2234 filesize = strtol(sizec, (char **)NULL, 10);
2235
2236 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2237
2238 aim_oft_getfile_request(sess, conn, filename, filesize);
2239
2240 free(filename);
2241 free(sizec);
2242
2243 return 0;
2244}
2245
2246int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2247{
2248 va_list ap;
2249 struct aim_conn_t *oftconn;
2250 struct aim_fileheader_t *fh;
646c6b52 2251 int pos, bufpos = 0, bufsize = 2048, i;
2252 char *buf;
37ee990e 2253
2254 va_start(ap, command);
2255 oftconn = va_arg(ap, struct aim_conn_t *);
2256 fh = va_arg(ap, struct aim_fileheader_t *);
2257 va_end(ap);
2258
2259 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2260
646c6b52 2261 if(!(buf = malloc(2048)))
2262 return -1;
2263
37ee990e 2264 for(pos = 0; pos < fh->size; pos++) {
2265 bufpos = pos % bufsize;
2266
2267 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2268 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2269 dperror("faim: getfile_send: write1");
2270 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2271 free(buf);
2272 return -1;
2273 }
2274 }
2275 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2276 if(pos != fh->size) {
2277 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2278 free(buf);
2279 return -1;
2280 }
2281 }
2282 }
2283
2284 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2285 dperror("faim: getfile_send: write2");
2286 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2287 free(buf);
2288 return -1;
2289 }
2290
2291 dprintf("faimtest: sent listing\n");
646c6b52 2292 free(buf);
37ee990e 2293 return 0;
2294}
2295
646c6b52 2296int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
37ee990e 2297{
2298 va_list ap;
2299 struct aim_conn_t *conn;
2300 struct aim_filetransfer_priv *ft;
2301 unsigned char data;
2302 int pos;
2303
2304 va_start(ap, command);
2305 conn = va_arg(ap, struct aim_conn_t *);
2306 ft = va_arg(ap, struct aim_filetransfer_priv *);
2307 va_end(ap);
2308
2309 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2310
2311 for(pos = 0; pos < ft->fh.size; pos++) {
2312 read(conn->fd, &data, 1);
646c6b52 2313 printf("%c(%02x) ", data, data);
37ee990e 2314 }
2315
646c6b52 2316 printf("\n");
37ee990e 2317
37ee990e 2318 aim_oft_getfile_end(sess, conn);
2319
2320 return 0;
2321}
646c6b52 2322
2323int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2324{
2325 va_list ap;
2326 struct aim_conn_t *conn;
2327
2328 va_start(ap, command);
2329 conn = va_arg(ap, struct aim_conn_t *);
2330 va_end(ap);
2331
2332 aim_conn_close(conn);
2333 aim_conn_kill(sess, &conn);
2334 return 0;
2335}
2336
2337
1a8c261b 2338int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2339{
275a2ff8 2340 static char *codes[5] = {"invalid",
2341 "change",
2342 "warning",
2343 "limit",
2344 "limit cleared"};
1a8c261b 2345 va_list ap;
275a2ff8 2346 int code;
d6c9fcf0 2347 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 2348 unsigned long currentavg, maxavg;
2349
1a8c261b 2350 va_start(ap, command);
275a2ff8 2351
2352 /* See code explanations below */
2353 code = va_arg(ap, int);
2354
2355 /*
d6c9fcf0 2356 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
275a2ff8 2357 */
d6c9fcf0 2358 rateclass = va_arg(ap, unsigned long);
275a2ff8 2359
2360 /*
2361 * Not sure what this is exactly. I think its the temporal
2362 * relation factor (ie, how to make the rest of the numbers
2363 * make sense in the real world).
2364 */
2365 windowsize = va_arg(ap, unsigned long);
2366
2367 /* Explained below */
2368 clear = va_arg(ap, unsigned long);
2369 alert = va_arg(ap, unsigned long);
2370 limit = va_arg(ap, unsigned long);
2371 disconnect = va_arg(ap, unsigned long);
2372 currentavg = va_arg(ap, unsigned long);
2373 maxavg = va_arg(ap, unsigned long);
2374
1a8c261b 2375 va_end(ap);
2376
275a2ff8 2377
37ee990e 2378 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 2379 (code < 5)?codes[code]:"invalid",
d6c9fcf0 2380 rateclass,
275a2ff8 2381 currentavg, maxavg,
2382 alert, clear,
2383 limit, disconnect,
2384 windowsize);
2385
2386 if (code == AIM_RATE_CODE_CHANGE) {
2387 /*
2388 * Not real sure when these get sent.
2389 */
2390 if (currentavg >= clear)
2391 aim_conn_setlatency(command->conn, 0);
2392
2393 } else if (code == AIM_RATE_CODE_WARNING) {
2394 /*
2395 * We start getting WARNINGs the first time we go below the 'alert'
2396 * limit (currentavg < alert) and they stop when either we pause
2397 * long enough for currentavg to go above 'clear', or until we
2398 * flood it bad enough to go below 'limit' (and start getting
2399 * LIMITs instead) or even further and go below 'disconnect' and
2400 * get disconnected completely (and won't be able to login right
2401 * away either).
2402 */
2403 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2404
2405 } else if (code == AIM_RATE_CODE_LIMIT) {
2406 /*
2407 * When we hit LIMIT, messages will start getting dropped.
2408 */
2409 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2410
2411 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2412 /*
2413 * The limit is cleared when curavg goes above 'clear'.
2414 */
2415 aim_conn_setlatency(command->conn, 0);
2416 }
1a8c261b 2417
871e2fd0 2418 return 1;
78b3fb13 2419}
98c88242 2420
2421int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2422{
2423 va_list ap;
06bc8607 2424 int newevil;
2425 struct aim_userinfo_s *userinfo;
98c88242 2426
2427 va_start(ap, command);
06bc8607 2428 newevil = va_arg(ap, int);
2429 userinfo = va_arg(ap, struct aim_userinfo_s *);
98c88242 2430 va_end(ap);
2431
06bc8607 2432 /*
2433 * Evil Notifications that are lacking userinfo->sn are anon-warns
2434 * if they are an evil increases, but are not warnings at all if its
2435 * a decrease (its the natural backoff happening).
2436 *
2437 * newevil is passed as an int representing the new evil value times
2438 * ten.
2439 */
37ee990e 2440 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2441
2442 return 1;
2443}
2444
2445int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2446{
2447 va_list ap;
2448 char *address, *SNs;
2449 int i, num;
2450
2451 va_start(ap, command);
2452 address = va_arg(ap, char *);
2453 num = va_arg(ap, int);
2454 SNs = va_arg(ap, char *);
2455 va_end(ap);
2456
2457 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2458
2459 for(i = 0; i < num; i++)
2460 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2461 dinlineprintf("\n");
2462
2463 return 1;
2464}
2465
2466int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2467{
2468 va_list ap;
2469 char *address;
2470
2471 va_start(ap, command);
2472 address = va_arg(ap, char *);
2473 va_end(ap);
2474
2475 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
98c88242 2476
98c88242 2477 return 1;
78b3fb13 2478}
This page took 1.351321 seconds and 5 git commands to generate.