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