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