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