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