]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Mon Mar 26 16:08:45 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{
69e7980c 1475 struct aim_userinfo_s *userinfo;
1476
397055b1 1477 va_list ap;
397055b1 1478 va_start(ap, command);
69e7980c 1479 userinfo = va_arg(ap, struct aim_userinfo_s *);
397055b1 1480 va_end(ap);
9de3ca7e 1481
69e7980c 1482 dvprintf("%ld %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1483 time(NULL),
1484 userinfo->sn, userinfo->flags,
1485 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1486 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1487 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1488 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1489 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1490 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1491 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1492 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1493 userinfo->capabilities);
9de3ca7e 1494 return 1;
1495}
1496
01b59e1e 1497int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1498{
96f8b1ed 1499 static char *codes[] = {
1500 "Unknown",
1501 "Mandatory upgrade",
1502 "Advisory upgrade",
1503 "System bulletin",
1504 "Top o' the world!"};
1505 static int codeslen = 5;
1506
01b59e1e 1507 char *msg;
96f8b1ed 1508 unsigned short id;
01b59e1e 1509 va_list ap;
1510
1511 va_start(ap, command);
e7fb57f5 1512 id = va_arg(ap, int);
01b59e1e 1513 msg = va_arg(ap, char *);
1514 va_end(ap);
1515
37ee990e 1516 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1517 (id < codeslen)?codes[id]:"unknown");
96f8b1ed 1518
ee49b735 1519 if (!connected)
1520 connected++;
1521
e80a0fa9 1522#if 0
1523 aim_bos_reqservice(sess, command->conn, 0x0005); /* adverts */
1524 aim_bos_reqservice(sess, command->conn, 0x000f); /* user directory */
1525
1526 /* Don't know what this does... */
1527 /* XXX sess->sn should be normalized by the 0001/000f handler */
1528 aim_0002_000b(sess, command->conn, sess->sn);
1529#endif
1530
1531 /* As of 26 Mar 2001 you need to send this to keep from getting kicked off */
1532 aim_0001_0020(sess, command->conn);
1533
1534
96f8b1ed 1535 return 1;
1536}
1537
1449ad2b 1538int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1539{
1540 va_list ap;
1541 unsigned short reason;
1542
1543 va_start(ap, command);
1544 reason = va_arg(ap, int);
1545 va_end(ap);
1546
37ee990e 1547 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1449ad2b 1548
1549 return 1;
1550}
1551
96f8b1ed 1552int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1553{
1554 va_list ap;
1555 char *destsn;
1556 unsigned short reason;
1557
1558 va_start(ap, command);
e7fb57f5 1559 reason = va_arg(ap, int);
00ef5271 1560 destsn = va_arg(ap, char *);
96f8b1ed 1561 va_end(ap);
1562
37ee990e 1563 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1564
1565 return 1;
1566}
1567
1568int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1569{
1570 va_list ap;
1571 char *destsn;
1572 unsigned short reason;
1573
1574 va_start(ap, command);
e7fb57f5 1575 reason = va_arg(ap, int);
00ef5271 1576 destsn = va_arg(ap, char *);
96f8b1ed 1577 va_end(ap);
01b59e1e 1578
37ee990e 1579 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1580
01b59e1e 1581 return 1;
1582}
9de3ca7e 1583
1584/*
96f8b1ed 1585 * Handles callbacks for AIM_CB_MISSED_CALL.
9de3ca7e 1586 */
397055b1 1587int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1588{
96f8b1ed 1589 static char *missedreasons[] = {
1590 "Unknown",
1591 "Message too large"};
1592 static int missedreasonslen = 2;
9de3ca7e 1593
96f8b1ed 1594 va_list ap;
1595 unsigned short chan, nummissed, reason;
1596 struct aim_userinfo_s *userinfo;
9de3ca7e 1597
96f8b1ed 1598 va_start(ap, command);
e7fb57f5 1599 chan = va_arg(ap, int);
96f8b1ed 1600 userinfo = va_arg(ap, struct aim_userinfo_s *);
e7fb57f5 1601 nummissed = va_arg(ap, int);
1602 reason = va_arg(ap, int);
96f8b1ed 1603 va_end(ap);
9de3ca7e 1604
37ee990e 1605 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
96f8b1ed 1606
00f3b08b 1607 return 1;
9de3ca7e 1608}
1609
01b59e1e 1610int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1611{
154b4093 1612 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
78b3fb13 1613 char *key;
b5bc2a8c 1614 va_list ap;
01b59e1e 1615
b5bc2a8c 1616 va_start(ap, command);
1617 key = va_arg(ap, char *);
1618 va_end(ap);
9de3ca7e 1619
b5bc2a8c 1620 aim_send_login(sess, command->conn, screenname, password, &info, key);
01b59e1e 1621
1622 return 1;
1623}
0c20631f 1624
1625int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1626{
1627 va_list ap;
1628 struct aim_userinfo_s *userinfo;
1629 int count = 0, i = 0;
1630
1631 va_start(ap, command);
1632 count = va_arg(ap, int);
1633 userinfo = va_arg(ap, struct aim_userinfo_s *);
1634 va_end(ap);
1635
37ee990e 1636 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
0c20631f 1637 while (i < count)
37ee990e 1638 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1639
1640 return 1;
1641}
1642
1643int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1644{
1645 va_list ap;
1646 struct aim_userinfo_s *userinfo;
1647 int count = 0, i = 0;
1648
1649 va_start(ap, command);
1650 count = va_arg(ap, int);
1651 userinfo = va_arg(ap, struct aim_userinfo_s *);
1652 va_end(ap);
1653
37ee990e 1654 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1655
1656 for (i = 0; i < count; )
1657 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1658
1659 return 1;
1660}
1661
1662int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1663{
1664 va_list ap;
1665 struct aim_userinfo_s *userinfo;
1666 struct aim_chat_roominfo *roominfo;
1667 char *roomname;
1668 int usercount,i;
1669 char *roomdesc;
aa6efcfd 1670 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1671 unsigned long creationtime;
0c20631f 1672
1673 va_start(ap, command);
1674 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1675 roomname = va_arg(ap, char *);
1676 usercount= va_arg(ap, int);
1677 userinfo = va_arg(ap, struct aim_userinfo_s *);
1678 roomdesc = va_arg(ap, char *);
e7fb57f5 1679 unknown_c9 = va_arg(ap, int);
aa6efcfd 1680 creationtime = va_arg(ap, unsigned long);
e7fb57f5 1681 maxmsglen = va_arg(ap, int);
1682 unknown_d2 = va_arg(ap, int);
1683 unknown_d5 = va_arg(ap, int);
0c20631f 1684 va_end(ap);
1685
37ee990e 1686 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1687 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
0c20631f 1688 (char *)command->conn->priv,
1689 roominfo->exchange,
1690 roominfo->name,
1691 roominfo->instance);
37ee990e 1692 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1693 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1694 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
0c20631f 1695
37ee990e 1696 for (i = 0; i < usercount; )
1697 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1698
37ee990e 1699 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1700 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1701 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1702 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1703 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
aa6efcfd 1704
0c20631f 1705 return 1;
1706}
1707
1708int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1709{
1710 va_list ap;
1711 struct aim_userinfo_s *userinfo;
1712 char *msg;
1713 char tmpbuf[1152];
1714
1715 va_start(ap, command);
1716 userinfo = va_arg(ap, struct aim_userinfo_s *);
1717 msg = va_arg(ap, char *);
1718 va_end(ap);
1719
37ee990e 1720 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
0c20631f 1721
1722 /*
1723 * Do an echo for testing purposes. But not for ourselves ("oops!")
1724 */
355982c5 1725 if (strcmp(userinfo->sn, sess->sn) != 0)
0c20631f 1726 {
1727 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1728 aim_chat_send_im(sess, command->conn, tmpbuf);
1729 }
1730
1731 return 1;
1732}
1733
1734int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1735{
e7fb57f5 1736 unsigned short type;
0c20631f 1737 va_list ap;
1738
e7fb57f5 1739 va_start(ap, command);
1740 type = va_arg(ap, int);
0c20631f 1741
efe9513b 1742 switch(type) {
1743 case 0x0002: {
1744 int maxrooms;
1745 struct aim_chat_exchangeinfo *exchanges;
1746 int exchangecount,i = 0;
1747
e7fb57f5 1748 maxrooms = va_arg(ap, int);
efe9513b 1749 exchangecount = va_arg(ap, int);
1750 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1751 va_end(ap);
1752
37ee990e 1753 dprintf("faimtest: chat info: Chat Rights:\n");
1754 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
efe9513b 1755
37ee990e 1756 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1757 for (i = 0; i < exchangecount; i++) {
1758 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1759 exchanges[i].number,
1760 exchanges[i].name,
1761 exchanges[i].charset1,
1762 exchanges[i].lang1);
0c20631f 1763 }
efe9513b 1764
1765 }
1766 break;
1767 case 0x0008: {
1768 char *fqcn, *name, *ck;
9dbda50b 1769 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
efe9513b 1770 unsigned char createperms;
1771 unsigned long createtime;
1772
1773 fqcn = va_arg(ap, char *);
e7fb57f5 1774 instance = va_arg(ap, int);
9dbda50b 1775 exchange = va_arg(ap, int);
e7fb57f5 1776 flags = va_arg(ap, int);
efe9513b 1777 createtime = va_arg(ap, unsigned long);
e7fb57f5 1778 maxmsglen = va_arg(ap, int);
1779 maxoccupancy = va_arg(ap, int);
1780 createperms = va_arg(ap, int);
1781 unknown = va_arg(ap, int);
efe9513b 1782 name = va_arg(ap, char *);
1783 ck = va_arg(ap, char *);
1784 va_end(ap);
1785
646c6b52 1786 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
efe9513b 1787 }
1788 break;
1789 default:
1790 va_end(ap);
37ee990e 1791 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
efe9513b 1792 }
0c20631f 1793 return 1;
1794}
5e02cf44 1795
1796int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1797{
1798 va_list ap;
1799 unsigned short code;
1800 char *msg = NULL;
1801
e7fb57f5 1802 va_start(ap, command);
1803 code = va_arg(ap, int);
5e02cf44 1804 msg = va_arg(ap, char *);
1805 va_end(ap);
1806
37ee990e 1807 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
68ac63c2 1808 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
5e02cf44 1809
1810 return 1;
1811}
e5012450 1812
1813int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1814{
37ee990e 1815 dprintf("faimtest: connecting to an aimdebugd!\n");
e5012450 1816
1817 /* convert the authorizer connection to a BOS connection */
1818 command->conn->type = AIM_CONN_TYPE_BOS;
1819
1820 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1821
1822 /* tell the aimddebugd we're ready */
1823 aim_debugconn_sendconnect(sess, command->conn);
1824
1825 /* go right into main loop (don't open a BOS connection, etc) */
1826 return 1;
1827}
1a8c261b 1828
1829/*
646c6b52 1830 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 1831 */
1832int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1833{
1834 va_list ap;
1835 unsigned short type;
1836 char *sn = NULL;
1837
e7fb57f5 1838 va_start(ap, command);
1839 type = va_arg(ap, int);
1a8c261b 1840 sn = va_arg(ap, char *);
1841 va_end(ap);
1842
37ee990e 1843 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 1844
1845 return 1;
1846}
1847
871e2fd0 1848int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1849{
1850 va_list ap;
1851 struct aim_conn_t *oftconn;
1852 struct aim_fileheader_t *fh;
1853 char *cookie;
1854
e7fb57f5 1855 va_start(ap, command);
871e2fd0 1856 oftconn = va_arg(ap, struct aim_conn_t *);
1857 fh = va_arg(ap, struct aim_fileheader_t *);
1858 cookie = va_arg(ap, char *);
1859 va_end(ap);
1860
37ee990e 1861 dvprintf("faimtest: request for file %s.\n", fh->name);
871e2fd0 1862
1863 return 1;
1864}
1865
1866
1867int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1868{
1869 va_list ap;
1870 struct aim_conn_t *oftconn;
1871 struct aim_fileheader_t *fh;
1872 char *path, *cookie;
646c6b52 1873 int pos, bufpos = 0, bufsize = 2048, i;
1874 char *buf;
871e2fd0 1875
1876 FILE *file;
1877
e7fb57f5 1878 va_start(ap, command);
871e2fd0 1879 oftconn = va_arg(ap, struct aim_conn_t *);
1880 fh = va_arg(ap, struct aim_fileheader_t *);
1881 cookie = va_arg(ap, char *);
1882 va_end(ap);
1883
37ee990e 1884 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
871e2fd0 1885
646c6b52 1886 if(!(buf = malloc(2048)))
1887 return -1;
1888
37ee990e 1889 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
1890 dperror("calloc");
1891 dprintf("faimtest: error in calloc of path\n");
871e2fd0 1892 return 0; /* XXX: no idea what winaim expects here =) */
1893 }
1894
37ee990e 1895 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
871e2fd0 1896
1897
1898 if( (file = fopen(path, "r")) == NULL) {
37ee990e 1899 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
871e2fd0 1900 return 0;
1901 }
646c6b52 1902
1903 /*
1904 * This is a mess. Remember that faimtest is demonstration code
1905 * only and for the sake of the gods, don't use this code in any
1906 * of your clients. --mid
1907 */
37ee990e 1908 for(pos = 0; pos < fh->size; pos++) {
1909 bufpos = pos % bufsize;
1910
1911 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
1912 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
1913 dperror("faim: getfile_send: write1");
1914 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
1915 free(buf);
1916 return -1;
1917 }
1918 }
1919 if( (buf[bufpos] = fgetc(file)) == EOF) {
1920 if(pos != fh->size) {
1921 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
1922 free(buf);
1923 return -1;
1924 }
1925 }
1926 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
1927 }
871e2fd0 1928
37ee990e 1929 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
1930 dperror("faim: getfile_send: write2");
1931 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
1932 free(buf);
1933 return -1;
871e2fd0 1934 }
1935
646c6b52 1936 free(buf);
871e2fd0 1937 free(fh);
1938 return 1;
1939}
1940
1941int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1942{
1943 va_list ap;
1944 struct aim_conn_t *conn;
1945 struct aim_fileheader_t *fh;
1946
e7fb57f5 1947 va_start(ap, command);
871e2fd0 1948 conn = va_arg(ap, struct aim_conn_t *);
1949 fh = va_arg(ap, struct aim_fileheader_t *);
1950 va_end(ap);
1951
37ee990e 1952 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
871e2fd0 1953
37ee990e 1954 aim_conn_close(conn);
1955 aim_conn_kill(sess, &conn);
871e2fd0 1956 return 1;
1957}
1958
1959int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1960{
1961 va_list ap;
1962 struct aim_conn_t *conn;
1963 char *sn;
1964
e7fb57f5 1965 va_start(ap, command);
871e2fd0 1966 conn = va_arg(ap, struct aim_conn_t *);
1967 sn = va_arg(ap, char *);
1968 va_end(ap);
1969
1970 aim_conn_kill(sess, &conn);
1971
37ee990e 1972 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
1973 return 1;
1974}
1975int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1976{
1977 va_list ap;
646c6b52 1978 struct aim_conn_t *conn, *listenerconn;
37ee990e 1979 struct aim_filetransfer_priv *priv;
1980
1981 va_start(ap, command);
1982 conn = va_arg(ap, struct aim_conn_t *);
646c6b52 1983 listenerconn = va_arg(ap, struct aim_conn_t *);
37ee990e 1984 va_end(ap);
1985
646c6b52 1986 aim_conn_close(listenerconn);
1987 aim_conn_kill(sess, &listenerconn);
1988
37ee990e 1989 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1990 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1991 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
1992 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1993 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
1994 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
646c6b52 1995 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
1996 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
37ee990e 1997
1998 priv = (struct aim_filetransfer_priv *)conn->priv;
1999
646c6b52 2000 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
871e2fd0 2001 return 1;
2002}
871e2fd0 2003
37ee990e 2004int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2005{
2006 va_list ap;
2007 struct aim_conn_t *conn;
2008 char *listing;
2009 struct aim_filetransfer_priv *ft;
2010 char *filename, *nameend, *sizec;
2011 int filesize, namelen;
2012
2013 va_start(ap, command);
2014 conn = va_arg(ap, struct aim_conn_t *);
2015 ft = va_arg(ap, struct aim_filetransfer_priv *);
2016 listing = va_arg(ap, char *);
2017 va_end(ap);
2018
2019 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2020
2021 nameend = strstr(listing+0x1a, "\r");
2022
2023 namelen = nameend - (listing + 0x1a);
2024
2025 filename = malloc(namelen + 1);
2026 strncpy(filename, listing+0x1a, namelen);
2027 filename[namelen] = 0x00;
2028
2029 sizec = malloc(8+1);
2030 memcpy(sizec, listing + 0x11, 8);
2031 sizec[8] = 0x00;
2032
2033 filesize = strtol(sizec, (char **)NULL, 10);
2034
2035 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2036
2037 aim_oft_getfile_request(sess, conn, filename, filesize);
2038
2039 free(filename);
2040 free(sizec);
2041
2042 return 0;
2043}
2044
2045int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2046{
2047 va_list ap;
2048 struct aim_conn_t *oftconn;
2049 struct aim_fileheader_t *fh;
646c6b52 2050 int pos, bufpos = 0, bufsize = 2048, i;
2051 char *buf;
37ee990e 2052
2053 va_start(ap, command);
2054 oftconn = va_arg(ap, struct aim_conn_t *);
2055 fh = va_arg(ap, struct aim_fileheader_t *);
2056 va_end(ap);
2057
2058 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2059
646c6b52 2060 if(!(buf = malloc(2048)))
2061 return -1;
2062
37ee990e 2063 for(pos = 0; pos < fh->size; pos++) {
2064 bufpos = pos % bufsize;
2065
2066 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2067 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2068 dperror("faim: getfile_send: write1");
2069 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2070 free(buf);
2071 return -1;
2072 }
2073 }
2074 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2075 if(pos != fh->size) {
2076 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2077 free(buf);
2078 return -1;
2079 }
2080 }
2081 }
2082
2083 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2084 dperror("faim: getfile_send: write2");
2085 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2086 free(buf);
2087 return -1;
2088 }
2089
2090 dprintf("faimtest: sent listing\n");
646c6b52 2091 free(buf);
37ee990e 2092 return 0;
2093}
2094
646c6b52 2095int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
37ee990e 2096{
2097 va_list ap;
2098 struct aim_conn_t *conn;
2099 struct aim_filetransfer_priv *ft;
2100 unsigned char data;
2101 int pos;
2102
2103 va_start(ap, command);
2104 conn = va_arg(ap, struct aim_conn_t *);
2105 ft = va_arg(ap, struct aim_filetransfer_priv *);
2106 va_end(ap);
2107
2108 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2109
2110 for(pos = 0; pos < ft->fh.size; pos++) {
2111 read(conn->fd, &data, 1);
646c6b52 2112 printf("%c(%02x) ", data, data);
37ee990e 2113 }
2114
646c6b52 2115 printf("\n");
37ee990e 2116
37ee990e 2117 aim_oft_getfile_end(sess, conn);
2118
2119 return 0;
2120}
646c6b52 2121
2122int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2123{
2124 va_list ap;
2125 struct aim_conn_t *conn;
2126
2127 va_start(ap, command);
2128 conn = va_arg(ap, struct aim_conn_t *);
2129 va_end(ap);
2130
2131 aim_conn_close(conn);
2132 aim_conn_kill(sess, &conn);
2133 return 0;
2134}
2135
2136
1a8c261b 2137int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2138{
275a2ff8 2139 static char *codes[5] = {"invalid",
2140 "change",
2141 "warning",
2142 "limit",
2143 "limit cleared"};
1a8c261b 2144 va_list ap;
275a2ff8 2145 int code;
d6c9fcf0 2146 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 2147 unsigned long currentavg, maxavg;
2148
1a8c261b 2149 va_start(ap, command);
275a2ff8 2150
2151 /* See code explanations below */
2152 code = va_arg(ap, int);
2153
2154 /*
d6c9fcf0 2155 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
275a2ff8 2156 */
d6c9fcf0 2157 rateclass = va_arg(ap, unsigned long);
275a2ff8 2158
2159 /*
2160 * Not sure what this is exactly. I think its the temporal
2161 * relation factor (ie, how to make the rest of the numbers
2162 * make sense in the real world).
2163 */
2164 windowsize = va_arg(ap, unsigned long);
2165
2166 /* Explained below */
2167 clear = va_arg(ap, unsigned long);
2168 alert = va_arg(ap, unsigned long);
2169 limit = va_arg(ap, unsigned long);
2170 disconnect = va_arg(ap, unsigned long);
2171 currentavg = va_arg(ap, unsigned long);
2172 maxavg = va_arg(ap, unsigned long);
2173
1a8c261b 2174 va_end(ap);
2175
275a2ff8 2176
37ee990e 2177 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 2178 (code < 5)?codes[code]:"invalid",
d6c9fcf0 2179 rateclass,
275a2ff8 2180 currentavg, maxavg,
2181 alert, clear,
2182 limit, disconnect,
2183 windowsize);
2184
2185 if (code == AIM_RATE_CODE_CHANGE) {
2186 /*
2187 * Not real sure when these get sent.
2188 */
2189 if (currentavg >= clear)
2190 aim_conn_setlatency(command->conn, 0);
2191
2192 } else if (code == AIM_RATE_CODE_WARNING) {
2193 /*
2194 * We start getting WARNINGs the first time we go below the 'alert'
2195 * limit (currentavg < alert) and they stop when either we pause
2196 * long enough for currentavg to go above 'clear', or until we
2197 * flood it bad enough to go below 'limit' (and start getting
2198 * LIMITs instead) or even further and go below 'disconnect' and
2199 * get disconnected completely (and won't be able to login right
2200 * away either).
2201 */
2202 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2203
2204 } else if (code == AIM_RATE_CODE_LIMIT) {
2205 /*
2206 * When we hit LIMIT, messages will start getting dropped.
2207 */
2208 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2209
2210 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2211 /*
2212 * The limit is cleared when curavg goes above 'clear'.
2213 */
2214 aim_conn_setlatency(command->conn, 0);
2215 }
1a8c261b 2216
871e2fd0 2217 return 1;
78b3fb13 2218}
98c88242 2219
2220int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2221{
2222 va_list ap;
06bc8607 2223 int newevil;
2224 struct aim_userinfo_s *userinfo;
98c88242 2225
2226 va_start(ap, command);
06bc8607 2227 newevil = va_arg(ap, int);
2228 userinfo = va_arg(ap, struct aim_userinfo_s *);
98c88242 2229 va_end(ap);
2230
06bc8607 2231 /*
2232 * Evil Notifications that are lacking userinfo->sn are anon-warns
2233 * if they are an evil increases, but are not warnings at all if its
2234 * a decrease (its the natural backoff happening).
2235 *
2236 * newevil is passed as an int representing the new evil value times
2237 * ten.
2238 */
37ee990e 2239 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2240
2241 return 1;
2242}
2243
2244int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2245{
2246 va_list ap;
2247 char *address, *SNs;
2248 int i, num;
2249
2250 va_start(ap, command);
2251 address = va_arg(ap, char *);
2252 num = va_arg(ap, int);
2253 SNs = va_arg(ap, char *);
2254 va_end(ap);
2255
2256 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2257
2258 for(i = 0; i < num; i++)
2259 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2260 dinlineprintf("\n");
2261
2262 return 1;
2263}
2264
2265int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2266{
2267 va_list ap;
2268 char *address;
2269
2270 va_start(ap, command);
2271 address = va_arg(ap, char *);
2272 va_end(ap);
2273
2274 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
98c88242 2275
98c88242 2276 return 1;
78b3fb13 2277}
This page took 0.447396 seconds and 5 git commands to generate.