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