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