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