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