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