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