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