]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
- Sat Mar 24 03:16:32 UTC 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);
0589dc54 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);
c78446b5 482 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE|AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
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
9de3ca7e 696 switch(serviceid)
697 {
64c78745 698 case 0x0005: /* Adverts */
699 {
700 struct aim_conn_t *tstconn;
701
702 tstconn = aim_newconn(sess, AIM_CONN_TYPE_ADS, ip);
703 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
704 dprintf("faimtest: unable to reconnect with authorizer\n");
705 } else {
706 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
707 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
708 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
709 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
710 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
711 aim_auth_sendcookie(sess, tstconn, cookie);
712 dprintf("sent cookie to adverts host\n");
713 }
714
715 }
716 break;
9de3ca7e 717 case 0x0007: /* Authorizer */
718 {
719 struct aim_conn_t *tstconn;
720 /* Open a connection to the Auth */
397055b1 721 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
37ee990e 722 if ((tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
723 dprintf("faimtest: unable to reconnect with authorizer\n");
724 } else {
ee49b735 725 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
22517493 726 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
64c78745 727 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
728 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
729 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
730 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
731 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
732 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
9de3ca7e 733 /* Send the cookie to the Auth */
397055b1 734 aim_auth_sendcookie(sess, tstconn, cookie);
64c78745 735 dprintf("sent cookie to authorizer host\n");
22517493 736 }
9de3ca7e 737
738 }
739 break;
740 case 0x000d: /* ChatNav */
741 {
742 struct aim_conn_t *tstconn = NULL;
397055b1 743 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
22517493 744 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
37ee990e 745 dprintf("faimtest: unable to connect to chatnav server\n");
040457cc 746 if (tstconn) aim_conn_kill(sess, &tstconn);
747 return 1;
748 }
00ef5271 749
0c20631f 750 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
22517493 751 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
397055b1 752 aim_auth_sendcookie(sess, tstconn, cookie);
37ee990e 753 dprintf("\achatnav: connected\n");
9de3ca7e 754 }
755 break;
756 case 0x000e: /* Chat */
757 {
0c20631f 758 char *roomname = NULL;
9f20a4e3 759 int exchange;
9de3ca7e 760 struct aim_conn_t *tstconn = NULL;
0c20631f 761
762 roomname = va_arg(ap, char *);
9f20a4e3 763 exchange = va_arg(ap, int);
0c20631f 764
397055b1 765 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
22517493 766 if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR))
9de3ca7e 767 {
37ee990e 768 dprintf("faimtest: unable to connect to chat server\n");
040457cc 769 if (tstconn) aim_conn_kill(sess, &tstconn);
9de3ca7e 770 return 1;
0c20631f 771 }
37ee990e 772 dvprintf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
0c20631f 773
774 /*
775 * We must do this to attach the stored name to the connection!
776 */
777 aim_chat_attachname(tstconn, roomname);
778
779 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
22517493 780 aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
0c20631f 781 aim_auth_sendcookie(sess, tstconn, cookie);
9de3ca7e 782 }
783 break;
784 default:
37ee990e 785 dvprintf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
9de3ca7e 786 /* dunno */
787 }
788
9de3ca7e 789 va_end(ap);
790
0c20631f 791 return 1;
9de3ca7e 792}
793
01b59e1e 794int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 795{
355982c5 796 va_list ap;
9de3ca7e 797 struct aim_conn_t *bosconn = NULL;
355982c5 798 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
799 unsigned char *cookie = NULL;
800 int errorcode = 0, regstatus = 0;
89bce177 801 int latestbuild = 0, latestbetabuild = 0;
802 char *latestrelease = NULL, *latestbeta = NULL;
803 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
804 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
805
355982c5 806 va_start(ap, command);
807 sn = va_arg(ap, char *);
808 errorcode = va_arg(ap, int);
809 errurl = va_arg(ap, char *);
810 regstatus = va_arg(ap, int);
811 email = va_arg(ap, char *);
812 bosip = va_arg(ap, char *);
813 cookie = va_arg(ap, unsigned char *);
89bce177 814
815 latestrelease = va_arg(ap, char *);
816 latestbuild = va_arg(ap, int);
817 latestreleaseurl = va_arg(ap, char *);
818 latestreleaseinfo = va_arg(ap, char *);
819
820 latestbeta = va_arg(ap, char *);
821 latestbetabuild = va_arg(ap, int);
822 latestbetaurl = va_arg(ap, char *);
823 latestbetainfo = va_arg(ap, char *);
824
355982c5 825 va_end(ap);
01b59e1e 826
37ee990e 827 dvprintf("Screen name: %s\n", sn);
01b59e1e 828
829 /*
830 * Check for error.
831 */
355982c5 832 if (errorcode || !bosip || !cookie) {
37ee990e 833 dvprintf("Login Error Code 0x%04x\n", errorcode);
834 dvprintf("Error URL: %s\n", errurl);
9bf14d44 835 aim_conn_kill(sess, &command->conn);
355982c5 836 return 1;
837 }
01b59e1e 838
37ee990e 839 dvprintf("Reg status: %2d\n", regstatus);
840 dvprintf("Email: %s\n", email);
841 dvprintf("BOS IP: %s\n", bosip);
9de3ca7e 842
89bce177 843 if (latestbeta)
37ee990e 844 dvprintf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
89bce177 845
846 if (latestrelease)
37ee990e 847 dvprintf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
89bce177 848
37ee990e 849 dprintf("Closing auth connection...\n");
040457cc 850 aim_conn_kill(sess, &command->conn);
355982c5 851 if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
37ee990e 852 dprintf("faimtest: could not connect to BOS: internal error\n");
355982c5 853 return 1;
22517493 854 } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
37ee990e 855 dprintf("faimtest: could not connect to BOS\n");
040457cc 856 aim_conn_kill(sess, &bosconn);
355982c5 857 return 1;
858 }
859
860 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
861 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
862 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
863 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
ee49b735 864 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
355982c5 865 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
866 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
867 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
868 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
869 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
870 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
871 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
872 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
873 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
874 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
875 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
876 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
37ee990e 877 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0001, faimtest_parse_searcherror, 0);
878 aim_conn_addhandler(sess, bosconn, 0x000a, 0x0003, faimtest_parse_searchreply, 0);
355982c5 879 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
880 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
881 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
882
355982c5 883 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
00ef5271 884
885 aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, faimtest_icbmparaminfo, 0);
1449ad2b 886 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
887 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
888 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
889
355982c5 890 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
1449ad2b 891
892
355982c5 893 aim_auth_sendcookie(sess, bosconn, cookie);
894
9de3ca7e 895 return 1;
896}
897
a15d82b1 898static void printuserflags(unsigned short flags)
899{
900 if (flags & AIM_FLAG_UNCONFIRMED)
37ee990e 901 dinlineprintf("UNCONFIRMED ");
a15d82b1 902 if (flags & AIM_FLAG_ADMINISTRATOR)
37ee990e 903 dinlineprintf("ADMINISTRATOR ");
a15d82b1 904 if (flags & AIM_FLAG_AOL)
37ee990e 905 dinlineprintf("AOL ");
a15d82b1 906 if (flags & AIM_FLAG_OSCAR_PAY)
37ee990e 907 dinlineprintf("OSCAR_PAY ");
a15d82b1 908 if (flags & AIM_FLAG_FREE)
37ee990e 909 dinlineprintf("FREE ");
a15d82b1 910 if (flags & AIM_FLAG_AWAY)
37ee990e 911 dinlineprintf("AWAY ");
a15d82b1 912 if (flags & AIM_FLAG_UNKNOWN40)
37ee990e 913 dinlineprintf("ICQ? ");
a15d82b1 914 if (flags & AIM_FLAG_UNKNOWN80)
37ee990e 915 dinlineprintf("UNKNOWN80 ");
a15d82b1 916 return;
917}
918
397055b1 919int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 920{
921 struct aim_userinfo_s *userinfo;
922 char *prof_encoding = NULL;
923 char *prof = NULL;
5e02cf44 924 unsigned short inforeq = 0;
9de3ca7e 925
926 va_list ap;
927 va_start(ap, command);
928 userinfo = va_arg(ap, struct aim_userinfo_s *);
929 prof_encoding = va_arg(ap, char *);
930 prof = va_arg(ap, char *);
e7fb57f5 931 inforeq = va_arg(ap, int);
9de3ca7e 932 va_end(ap);
933
37ee990e 934 dvprintf("faimtest: userinfo: sn: %s\n", userinfo->sn);
935 dvprintf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
936 dvprintf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
a15d82b1 937 printuserflags(userinfo->flags);
37ee990e 938 dinlineprintf("\n");
9de3ca7e 939
37ee990e 940 dvprintf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
941 dvprintf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
942 dvprintf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
9de3ca7e 943
5e02cf44 944 if (inforeq == AIM_GETINFO_GENERALINFO) {
37ee990e 945 dvprintf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
946 dvprintf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
5e02cf44 947 } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
37ee990e 948 dvprintf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
949 dvprintf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
5e02cf44 950 } else
37ee990e 951 dprintf("faimtest: userinfo: unknown info request\n");
9de3ca7e 952
953 return 1;
954}
955
d2587300 956static int faimtest_handlecmd(struct aim_session_t *sess, struct command_rx_struct *command, struct aim_userinfo_s *userinfo, char *tmpstr)
957{
958
959 if (!strncmp(tmpstr, "disconnect", 10)) {
960
961 logout();
962
963 } else if (strstr(tmpstr, "goodday")) {
964
965 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
966
967 } else if (strstr(tmpstr, "warnme")) {
968
969 dprintf("faimtest: icbm: sending non-anon warning\n");
970 aim_send_warning(sess, command->conn, userinfo->sn, 0);
971
972 } else if (strstr(tmpstr, "anonwarn")) {
973
974 dprintf("faimtest: icbm: sending anon warning\n");
975 aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
976
977 } else if (strstr(tmpstr, "setdirectoryinfo")) {
978
979 dprintf("faimtest: icbm: sending backwards profile data\n");
980 aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
981
982 } else if (strstr(tmpstr, "setinterests")) {
983
984 dprintf("faimtest: icbm: setting fun interests\n");
985 aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
986
987 } else if (!strncmp(tmpstr, "getfile", 7)) {
988
989 if (!ohcaptainmycaptain) {
990
991 aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "I have no owner!");
992
993 } else {
994 struct aim_conn_t *newconn;
995
996 newconn = aim_getfile_initiate(sess, command->conn, (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
997 dvprintf("faimtest: getting file listing from %s\n", (strlen(tmpstr) < 8)?ohcaptainmycaptain:tmpstr+8);
998 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE, faimtest_getfile_initiate,0);
999 }
1000
1001 } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1002
1003 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
1004
1005 } else if (!strncmp(tmpstr, "create", 6)) {
1006
1007 aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1008
1009 } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1010 struct aim_conn_t *chatnavconn;
1011
1012 chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
1013 aim_conn_kill(sess, &chatnavconn);
1014
1015 } else if (!strncmp(tmpstr, "join", 4)) {
1016
1017 aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
1018
1019 } else if (!strncmp(tmpstr, "leave", 5)) {
1020
1021 aim_chat_leaveroom(sess, "worlddomination");
1022
1023 } else if (!strncmp(tmpstr, "getinfo", 7)) {
1024
1025 aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
1026 aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
00ef5271 1027 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_GENERALINFO);
1028 aim_getinfo(sess, command->conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
d2587300 1029
1030 } else if (!strncmp(tmpstr, "open directim", 13)) {
1031 struct aim_conn_t *newconn;
1032
1033 printf("faimtest: opening directim to %s\n", (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1034 newconn = aim_directim_initiate(sess, command->conn, NULL, (strlen(tmpstr) < 14)?userinfo->sn:tmpstr+14);
1035 if(!newconn || newconn->fd == -1)
1036 printf("connection failed!\n");
1037 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate,0);
1038
1039 } else if(!(strncmp(tmpstr, "lookup", 6))) {
1040
1041 aim_usersearch_address(sess, command->conn, tmpstr+7);
1042
1043 } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1044
1045 aim_send_im(sess, command->conn, ohcaptainmycaptain, 0, "sendmsg 7900");
1046
1047 } else if (!strncmp(tmpstr, "reqauth", 7)) {
1048
1049 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
1050
1051 } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1052
1053 aim_auth_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1054
1055 } else if (!strncmp(tmpstr, "reqemail", 8)) {
1056
1057 aim_auth_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1058
1059 } else if (!strncmp(tmpstr, "changepass", 8)) {
1060
1061 aim_auth_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1062
1063 } else if (!strncmp(tmpstr, "setemail", 8)) {
1064
1065 aim_auth_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1066
1067 } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1068 int i;
1069 i = atoi(tmpstr+8);
1070 if (i < 10000) {
1071 char *newbuf;
1072 int z;
1073
1074 newbuf = malloc(i+1);
1075 for (z = 0; z < i; z++) {
1076 newbuf[z] = (z % 10)+0x30;
1077 }
1078 newbuf[i] = '\0';
1079 aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf);
1080 free(newbuf);
1081 }
1082
1083 } else {
1084
1085 dprintf("unknown command.\n");
1086 aim_add_buddy(sess, command->conn, userinfo->sn);
1087
1088 }
1089
1090 return 0;
1091}
1092
9de3ca7e 1093/*
1094 * The user-level Incoming ICBM callback.
1095 *
9de3ca7e 1096 */
397055b1 1097int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1098{
26af6789 1099 int channel;
9de3ca7e 1100 va_list ap;
9de3ca7e 1101
1102 va_start(ap, command);
26af6789 1103 channel = va_arg(ap, int);
9de3ca7e 1104
26af6789 1105 /*
1106 * Channel 1: Standard Message
1107 */
040457cc 1108 if (channel == 1) {
1109 struct aim_userinfo_s *userinfo;
1110 char *msg = NULL;
1111 u_int icbmflags = 0;
1112 char *tmpstr = NULL;
e7fb57f5 1113 unsigned short flag1, flag2;
9d83220c 1114 int finlen = 0;
1115 unsigned char *fingerprint = NULL;
1116 int clienttype = AIM_CLIENTTYPE_UNKNOWN;
040457cc 1117
1118 userinfo = va_arg(ap, struct aim_userinfo_s *);
1119 msg = va_arg(ap, char *);
1120 icbmflags = va_arg(ap, u_int);
e7fb57f5 1121 flag1 = va_arg(ap, int);
1122 flag2 = va_arg(ap, int);
9d83220c 1123 finlen = va_arg(ap, int);
1124 fingerprint = va_arg(ap, unsigned char *);
040457cc 1125 va_end(ap);
1126
9d83220c 1127 clienttype = aim_fingerprintclient(fingerprint, finlen);
1128
37ee990e 1129 dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
9d83220c 1130 dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
37ee990e 1131 dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
1132 dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
a15d82b1 1133 printuserflags(userinfo->flags);
37ee990e 1134 dinlineprintf("\n");
a15d82b1 1135
37ee990e 1136 dvprintf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
1137 dvprintf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
1138 dvprintf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
1139 dvprintf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
040457cc 1140
37ee990e 1141 dprintf("faimtest: icbm: icbmflags = ");
040457cc 1142 if (icbmflags & AIM_IMFLAGS_AWAY)
37ee990e 1143 dinlineprintf("away ");
040457cc 1144 if (icbmflags & AIM_IMFLAGS_ACK)
37ee990e 1145 dinlineprintf("ackrequest ");
1146 dinlineprintf("\n");
040457cc 1147
37ee990e 1148 dvprintf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
040457cc 1149
37ee990e 1150 dvprintf("faimtest: icbm: message: %s\n", msg);
040457cc 1151
1152 if (msg) {
b69540e3 1153 int i = 0;
1154
1155 while (msg[i] == '<') {
1156 if (msg[i] == '<') {
1157 while (msg[i] != '>')
1158 i++;
1159 i++;
1160 }
1161 }
1162 tmpstr = msg+i;
1163
d2587300 1164 faimtest_handlecmd(sess, command, userinfo, tmpstr);
1165
040457cc 1166 }
1167 }
1168 /*
1169 * Channel 2: Rendevous Request
1170 */
1171 else if (channel == 2) {
1172 struct aim_userinfo_s *userinfo;
1173 unsigned short reqclass;
1174
e7fb57f5 1175 reqclass = va_arg(ap, int);
040457cc 1176 switch (reqclass) {
b69540e3 1177 case AIM_CAPS_VOICE: {
26af6789 1178 userinfo = va_arg(ap, struct aim_userinfo_s *);
26af6789 1179 va_end(ap);
9de3ca7e 1180
37ee990e 1181 dvprintf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
1182 dvprintf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1183 dvprintf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1184 printuserflags(userinfo->flags);
37ee990e 1185 dinlineprintf("\n");
a15d82b1 1186
040457cc 1187 /* we dont get membersince on chat invites! */
37ee990e 1188 dvprintf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1189 dvprintf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1190
040457cc 1191 break;
1192 }
b69540e3 1193 case AIM_CAPS_GETFILE: {
871e2fd0 1194 char *ip, *cookie;
1195 struct aim_conn_t *newconn;
37ee990e 1196 struct aim_fileheader_t *fh;
871e2fd0 1197
1198 userinfo = va_arg(ap, struct aim_userinfo_s *);
1199 ip = va_arg(ap, char *);
1200 cookie = va_arg(ap, char *);
1201 va_end(ap);
1202
646c6b52 1203 dvprintf("faimtest: get file request from %s (at %s) %x\n", userinfo->sn, ip, reqclass);
1204
1205 fh = aim_getlisting(sess, listingfile);
871e2fd0 1206
646c6b52 1207 newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, fh->totfiles, fh->totsize, fh->size, fh->checksum, reqclass);
871e2fd0 1208
646c6b52 1209 if( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1210 dprintf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
646c6b52 1211 if(newconn)
1212 aim_conn_kill(sess, &newconn);
871e2fd0 1213 break;
1214 }
37ee990e 1215
1216 free(fh);
1217
1218 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
871e2fd0 1219 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1220 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1221 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
37ee990e 1222
871e2fd0 1223 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1224
37ee990e 1225 dprintf("faimtest: getfile connect succeeded, handlers added.\n");
871e2fd0 1226
040457cc 1227 break;
1228 }
b69540e3 1229 case AIM_CAPS_SENDFILE: {
37ee990e 1230 dprintf("faimtest: send file!\n");
b69540e3 1231 break;
1232 }
1233 case AIM_CAPS_CHAT: {
040457cc 1234 char *msg,*encoding,*lang;
1235 struct aim_chat_roominfo *roominfo;
26af6789 1236
040457cc 1237 userinfo = va_arg(ap, struct aim_userinfo_s *);
1238 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1239 msg = va_arg(ap, char *);
1240 encoding = va_arg(ap, char *);
1241 lang = va_arg(ap, char *);
1242 va_end(ap);
26af6789 1243
37ee990e 1244 dvprintf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
1245 dvprintf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
1246 dvprintf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
a15d82b1 1247 printuserflags(userinfo->flags);
37ee990e 1248 dinlineprintf("\n");
a15d82b1 1249
040457cc 1250 /* we dont get membersince on chat invites! */
37ee990e 1251 dvprintf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
1252 dvprintf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
26af6789 1253
37ee990e 1254 dvprintf("faimtest: chat invitation: message = %s\n", msg);
1255 dvprintf("faimtest: chat invitation: room name = %s\n", roominfo->name);
1256 dvprintf("faimtest: chat invitation: encoding = %s\n", encoding);
1257 dvprintf("faimtest: chat invitation: language = %s\n", lang);
1258 dvprintf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
1259 dvprintf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
1260 dvprintf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
040457cc 1261 /*
1262 * Automatically join room...
1263 */
1264 aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
1265 break;
1266 }
7392c79f 1267 case AIM_CAPS_IMIMAGE: {
1268 struct aim_directim_priv *priv;
1269 struct aim_conn_t *newconn;
1270
37ee990e 1271 dprintf("faimtest: icbm: rendezvous imimage\n");
7392c79f 1272
1273 userinfo = va_arg(ap, struct aim_userinfo_s *);
1274 priv = va_arg(ap, struct aim_directim_priv *);
1275 va_end(ap);
1276
37ee990e 1277 dvprintf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
7392c79f 1278
646c6b52 1279 newconn = aim_directim_connect(sess, command->conn, priv);
1280
1281 if ( (!newconn) || (newconn->fd == -1) ) {
37ee990e 1282 dprintf("faimtest: icbm: imimage: could not connect\n");
646c6b52 1283
1284 if (newconn)
1285 aim_conn_kill(sess, &newconn);
1286
7392c79f 1287 break;
1288 }
646c6b52 1289
7392c79f 1290 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1291 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1292 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1293
37ee990e 1294 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
7392c79f 1295
3b101546 1296 aim_send_im_direct(sess, newconn, "goodday");
1297
7392c79f 1298 break;
1299 }
040457cc 1300 default:
37ee990e 1301 dvprintf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
040457cc 1302 } /* switch */
1303 } else
37ee990e 1304 dvprintf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1305 dprintf("faimtest: icbm: done with ICBM handling\n");
9de3ca7e 1306
1307 return 1;
1308}
1309
7392c79f 1310int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1311{
1312 va_list ap;
1313 struct aim_directim_priv *priv;
646c6b52 1314 struct aim_conn_t *newconn, *listenerconn;
7392c79f 1315
e7fb57f5 1316 va_start(ap, command);
7392c79f 1317 newconn = va_arg(ap, struct aim_conn_t *);
646c6b52 1318 listenerconn = va_arg(ap, struct aim_conn_t *);
7392c79f 1319 va_end(ap);
1320
646c6b52 1321 aim_conn_close(listenerconn);
1322 aim_conn_kill(sess, &listenerconn);
1323
7392c79f 1324 priv = (struct aim_directim_priv *)newconn->priv;
1325
37ee990e 1326 dvprintf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
7392c79f 1327
1328 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1329 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1330 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1331
1332 aim_send_im_direct(sess, newconn, "goodday");
1333
37ee990e 1334 dvprintf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
7392c79f 1335
1336 return 1;
1337}
7392c79f 1338
1339int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1340{
1341 va_list ap;
1342 struct aim_directim_priv *priv;
1343
e7fb57f5 1344 va_start(ap, command);
7392c79f 1345 priv = va_arg(ap, struct aim_directim_priv *);
1346
1347 va_end(ap);
1348
37ee990e 1349 dprintf("faimtest: directim_connect\n");
7392c79f 1350
1351 return 1;
1352}
1353
1354int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1355{
1356 va_list ap;
9e8c4225 1357 char *msg = NULL;
7392c79f 1358 struct aim_conn_t *conn;
9e8c4225 1359 struct aim_directim_priv *priv;
7392c79f 1360
e7fb57f5 1361 va_start(ap, command);
7392c79f 1362 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1363 msg = va_arg(ap, char *);
1364 va_end(ap);
1365
9e8c4225 1366 if(!(priv = conn->priv)) {
1367 dvprintf("faimtest: directim: no private struct on conn with fd %d\n", conn->fd);
1368 return -1;
1369 }
1370
1371 dvprintf("faimtest: Directim from %s: %s\n", priv->sn, msg);
7392c79f 1372 if (!strncmp(msg, "sendmsg", 7)) {
1373 int i;
1374 i = atoi(msg+8);
1375 if (i < 10000) {
1376 char *newbuf;
1377 int z;
1378
1379 newbuf = malloc(i+1);
1380 for (z = 0; z < i; z++) {
1381 newbuf[z] = (z % 10)+0x30;
1382 }
1383 newbuf[i] = '\0';
1384 aim_send_im_direct(sess, conn, newbuf);
1385 free(newbuf);
1386 }
1387 } else if (!strncmp(msg, "goodday", 7)) {
1388 aim_send_im_direct(sess, conn, "Good day to you, too");
1389 } else {
1390 char newmsg[1024];
1391 snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1392 aim_send_im_direct(sess, conn, newmsg);
1393 }
1394 return 1;
1395}
1396
1397int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1398{
871e2fd0 1399 va_list ap;
1400 struct aim_conn_t *conn;
1401 char *sn;
1402
e7fb57f5 1403 va_start(ap, command);
871e2fd0 1404 conn = va_arg(ap, struct aim_conn_t *);
1405 sn = va_arg(ap, char *);
1406 va_end(ap);
1407
37ee990e 1408 dvprintf("faimtest: directim: disconnected from %s\n", sn);
3b101546 1409
1410 aim_conn_kill(sess, &conn);
7392c79f 1411 return 1;
1412}
1413
1414int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1415{
1416 va_list ap;
9e8c4225 1417 struct aim_conn_t *conn;
1418 struct aim_directim_priv *priv;
1419
e7fb57f5 1420 va_start(ap, command);
9e8c4225 1421 conn = va_arg(ap, struct aim_conn_t *);
7392c79f 1422 va_end(ap);
9e8c4225 1423
1424 if(!(priv = (struct aim_directim_priv *)conn->priv)) {
1425 dvprintf("faimtest: no private struct on conn with fd %d!\n", conn->fd);
1426 return -1;
1427 }
7392c79f 1428
9e8c4225 1429 dvprintf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
7392c79f 1430 return 1;
1431}
1432
64c78745 1433int faimtest_infochange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1434{
64c78745 1435 unsigned short change = 0;
1436 int perms, type, length, str;
1437 char *val;
1438 va_list ap;
9de3ca7e 1439
64c78745 1440 va_start(ap, command);
1441 perms = va_arg(ap, int);
1442 type = va_arg(ap, int);
1443 length = va_arg(ap, int);
1444 val = va_arg(ap, char *);
1445 str = va_arg(ap, int);
1446 va_end(ap);
9de3ca7e 1447
64c78745 1448 if (aimutil_get16(command->data+2) == 0x0005)
1449 change = 1;
1450
1451 dvprintf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)");
9de3ca7e 1452
9de3ca7e 1453 return 1;
1454}
1455
397055b1 1456int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1457{
1458 struct aim_userinfo_s *userinfo;
1459
1460 va_list ap;
1461 va_start(ap, command);
1462 userinfo = va_arg(ap, struct aim_userinfo_s *);
1463 va_end(ap);
1464
37ee990e 1465 dvprintf("%ld %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
ee49b735 1466 time(NULL),
a15d82b1 1467 userinfo->sn, userinfo->flags,
1468 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1469 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1470 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1471 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1472 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1473 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1474 (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1475 (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
b69540e3 1476 userinfo->capabilities);
9de3ca7e 1477 return 1;
1478}
1479
397055b1 1480int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1481{
397055b1 1482 char *sn;
1483 va_list ap;
1484
1485 va_start(ap, command);
1486 sn = va_arg(ap, char *);
1487 va_end(ap);
9de3ca7e 1488
37ee990e 1489 dvprintf("\n%s has left\n", sn);
9de3ca7e 1490
1491 return 1;
1492}
1493
01b59e1e 1494int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1495{
96f8b1ed 1496 static char *codes[] = {
1497 "Unknown",
1498 "Mandatory upgrade",
1499 "Advisory upgrade",
1500 "System bulletin",
1501 "Top o' the world!"};
1502 static int codeslen = 5;
1503
01b59e1e 1504 char *msg;
96f8b1ed 1505 unsigned short id;
01b59e1e 1506 va_list ap;
1507
1508 va_start(ap, command);
e7fb57f5 1509 id = va_arg(ap, int);
01b59e1e 1510 msg = va_arg(ap, char *);
1511 va_end(ap);
1512
37ee990e 1513 dvprintf("faimtest: motd: %s (%d / %s)\n", msg, id,
1514 (id < codeslen)?codes[id]:"unknown");
96f8b1ed 1515
ee49b735 1516 if (!connected)
1517 connected++;
1518
96f8b1ed 1519 return 1;
1520}
1521
1449ad2b 1522int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1523{
1524 va_list ap;
1525 unsigned short reason;
1526
1527 va_start(ap, command);
1528 reason = va_arg(ap, int);
1529 va_end(ap);
1530
37ee990e 1531 dvprintf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1449ad2b 1532
1533 return 1;
1534}
1535
96f8b1ed 1536int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1537{
1538 va_list ap;
1539 char *destsn;
1540 unsigned short reason;
1541
1542 va_start(ap, command);
e7fb57f5 1543 reason = va_arg(ap, int);
00ef5271 1544 destsn = va_arg(ap, char *);
96f8b1ed 1545 va_end(ap);
1546
37ee990e 1547 dvprintf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1548
1549 return 1;
1550}
1551
1552int faimtest_parse_locerr(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);
01b59e1e 1562
37ee990e 1563 dvprintf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
96f8b1ed 1564
01b59e1e 1565 return 1;
1566}
9de3ca7e 1567
1568/*
96f8b1ed 1569 * Handles callbacks for AIM_CB_MISSED_CALL.
9de3ca7e 1570 */
397055b1 1571int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
9de3ca7e 1572{
96f8b1ed 1573 static char *missedreasons[] = {
1574 "Unknown",
1575 "Message too large"};
1576 static int missedreasonslen = 2;
9de3ca7e 1577
96f8b1ed 1578 va_list ap;
1579 unsigned short chan, nummissed, reason;
1580 struct aim_userinfo_s *userinfo;
9de3ca7e 1581
96f8b1ed 1582 va_start(ap, command);
e7fb57f5 1583 chan = va_arg(ap, int);
96f8b1ed 1584 userinfo = va_arg(ap, struct aim_userinfo_s *);
e7fb57f5 1585 nummissed = va_arg(ap, int);
1586 reason = va_arg(ap, int);
96f8b1ed 1587 va_end(ap);
9de3ca7e 1588
37ee990e 1589 dvprintf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
96f8b1ed 1590
00f3b08b 1591 return 1;
9de3ca7e 1592}
1593
01b59e1e 1594int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1595{
154b4093 1596 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
78b3fb13 1597 char *key;
b5bc2a8c 1598 va_list ap;
01b59e1e 1599
b5bc2a8c 1600 va_start(ap, command);
1601 key = va_arg(ap, char *);
1602 va_end(ap);
9de3ca7e 1603
b5bc2a8c 1604 aim_send_login(sess, command->conn, screenname, password, &info, key);
01b59e1e 1605
1606 return 1;
1607}
0c20631f 1608
1609int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1610{
1611 va_list ap;
1612 struct aim_userinfo_s *userinfo;
1613 int count = 0, i = 0;
1614
1615 va_start(ap, command);
1616 count = va_arg(ap, int);
1617 userinfo = va_arg(ap, struct aim_userinfo_s *);
1618 va_end(ap);
1619
37ee990e 1620 dvprintf("faimtest: chat: %s: New occupants have joined:\n", (char *)command->conn->priv);
0c20631f 1621 while (i < count)
37ee990e 1622 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1623
1624 return 1;
1625}
1626
1627int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1628{
1629 va_list ap;
1630 struct aim_userinfo_s *userinfo;
1631 int count = 0, i = 0;
1632
1633 va_start(ap, command);
1634 count = va_arg(ap, int);
1635 userinfo = va_arg(ap, struct aim_userinfo_s *);
1636 va_end(ap);
1637
37ee990e 1638 dvprintf("faimtest: chat: %s: Some occupants have left:\n", (char *)command->conn->priv);
1639
1640 for (i = 0; i < count; )
1641 dvprintf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1642
1643 return 1;
1644}
1645
1646int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1647{
1648 va_list ap;
1649 struct aim_userinfo_s *userinfo;
1650 struct aim_chat_roominfo *roominfo;
1651 char *roomname;
1652 int usercount,i;
1653 char *roomdesc;
aa6efcfd 1654 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1655 unsigned long creationtime;
0c20631f 1656
1657 va_start(ap, command);
1658 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1659 roomname = va_arg(ap, char *);
1660 usercount= va_arg(ap, int);
1661 userinfo = va_arg(ap, struct aim_userinfo_s *);
1662 roomdesc = va_arg(ap, char *);
e7fb57f5 1663 unknown_c9 = va_arg(ap, int);
aa6efcfd 1664 creationtime = va_arg(ap, unsigned long);
e7fb57f5 1665 maxmsglen = va_arg(ap, int);
1666 unknown_d2 = va_arg(ap, int);
1667 unknown_d5 = va_arg(ap, int);
0c20631f 1668 va_end(ap);
1669
37ee990e 1670 dvprintf("faimtest: chat: %s: info update:\n", (char *)command->conn->priv);
1671 dvprintf("faimtest: chat: %s: \tRoominfo: {%04x, %s, %04x}\n",
0c20631f 1672 (char *)command->conn->priv,
1673 roominfo->exchange,
1674 roominfo->name,
1675 roominfo->instance);
37ee990e 1676 dvprintf("faimtest: chat: %s: \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1677 dvprintf("faimtest: chat: %s: \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1678 dvprintf("faimtest: chat: %s: \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
0c20631f 1679
37ee990e 1680 for (i = 0; i < usercount; )
1681 dvprintf("faimtest: chat: %s: \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
0c20631f 1682
37ee990e 1683 dvprintf("faimtest: chat: %s: \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1684 dvprintf("faimtest: chat: %s: \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1685 dvprintf("faimtest: chat: %s: \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1686 dvprintf("faimtest: chat: %s: \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1687 dvprintf("faimtest: chat: %s: \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
aa6efcfd 1688
0c20631f 1689 return 1;
1690}
1691
1692int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1693{
1694 va_list ap;
1695 struct aim_userinfo_s *userinfo;
1696 char *msg;
1697 char tmpbuf[1152];
1698
1699 va_start(ap, command);
1700 userinfo = va_arg(ap, struct aim_userinfo_s *);
1701 msg = va_arg(ap, char *);
1702 va_end(ap);
1703
37ee990e 1704 dvprintf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
0c20631f 1705
1706 /*
1707 * Do an echo for testing purposes. But not for ourselves ("oops!")
1708 */
355982c5 1709 if (strcmp(userinfo->sn, sess->sn) != 0)
0c20631f 1710 {
1711 sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1712 aim_chat_send_im(sess, command->conn, tmpbuf);
1713 }
1714
1715 return 1;
1716}
1717
1718int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1719{
e7fb57f5 1720 unsigned short type;
0c20631f 1721 va_list ap;
1722
e7fb57f5 1723 va_start(ap, command);
1724 type = va_arg(ap, int);
0c20631f 1725
efe9513b 1726 switch(type) {
1727 case 0x0002: {
1728 int maxrooms;
1729 struct aim_chat_exchangeinfo *exchanges;
1730 int exchangecount,i = 0;
1731
e7fb57f5 1732 maxrooms = va_arg(ap, int);
efe9513b 1733 exchangecount = va_arg(ap, int);
1734 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1735 va_end(ap);
1736
37ee990e 1737 dprintf("faimtest: chat info: Chat Rights:\n");
1738 dvprintf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
efe9513b 1739
37ee990e 1740 dvprintf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1741 for (i = 0; i < exchangecount; i++) {
1742 dvprintf("faimtest: chat info: \t\t%x: %s (%s/%s)\n",
1743 exchanges[i].number,
1744 exchanges[i].name,
1745 exchanges[i].charset1,
1746 exchanges[i].lang1);
0c20631f 1747 }
efe9513b 1748
1749 }
1750 break;
1751 case 0x0008: {
1752 char *fqcn, *name, *ck;
9dbda50b 1753 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
efe9513b 1754 unsigned char createperms;
1755 unsigned long createtime;
1756
1757 fqcn = va_arg(ap, char *);
e7fb57f5 1758 instance = va_arg(ap, int);
9dbda50b 1759 exchange = va_arg(ap, int);
e7fb57f5 1760 flags = va_arg(ap, int);
efe9513b 1761 createtime = va_arg(ap, unsigned long);
e7fb57f5 1762 maxmsglen = va_arg(ap, int);
1763 maxoccupancy = va_arg(ap, int);
1764 createperms = va_arg(ap, int);
1765 unknown = va_arg(ap, int);
efe9513b 1766 name = va_arg(ap, char *);
1767 ck = va_arg(ap, char *);
1768 va_end(ap);
1769
646c6b52 1770 dvprintf("faimtest: received room create reply for %s/0x%04x\n", fqcn, exchange);
efe9513b 1771 }
1772 break;
1773 default:
1774 va_end(ap);
37ee990e 1775 dvprintf("faimtest: chatnav info: unknown type (%04x)\n", type);
efe9513b 1776 }
0c20631f 1777 return 1;
1778}
5e02cf44 1779
1780int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1781{
1782 va_list ap;
1783 unsigned short code;
1784 char *msg = NULL;
1785
e7fb57f5 1786 va_start(ap, command);
1787 code = va_arg(ap, int);
5e02cf44 1788 msg = va_arg(ap, char *);
1789 va_end(ap);
1790
37ee990e 1791 dvprintf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
68ac63c2 1792 aim_conn_kill(sess, &command->conn); /* this will break the main loop */
5e02cf44 1793
1794 return 1;
1795}
e5012450 1796
1797int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1798{
37ee990e 1799 dprintf("faimtest: connecting to an aimdebugd!\n");
e5012450 1800
1801 /* convert the authorizer connection to a BOS connection */
1802 command->conn->type = AIM_CONN_TYPE_BOS;
1803
1804 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1805
1806 /* tell the aimddebugd we're ready */
1807 aim_debugconn_sendconnect(sess, command->conn);
1808
1809 /* go right into main loop (don't open a BOS connection, etc) */
1810 return 1;
1811}
1a8c261b 1812
1813/*
646c6b52 1814 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1a8c261b 1815 */
1816int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1817{
1818 va_list ap;
1819 unsigned short type;
1820 char *sn = NULL;
1821
e7fb57f5 1822 va_start(ap, command);
1823 type = va_arg(ap, int);
1a8c261b 1824 sn = va_arg(ap, char *);
1825 va_end(ap);
1826
37ee990e 1827 dvprintf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1a8c261b 1828
1829 return 1;
1830}
1831
871e2fd0 1832int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1833{
1834 va_list ap;
1835 struct aim_conn_t *oftconn;
1836 struct aim_fileheader_t *fh;
1837 char *cookie;
1838
e7fb57f5 1839 va_start(ap, command);
871e2fd0 1840 oftconn = va_arg(ap, struct aim_conn_t *);
1841 fh = va_arg(ap, struct aim_fileheader_t *);
1842 cookie = va_arg(ap, char *);
1843 va_end(ap);
1844
37ee990e 1845 dvprintf("faimtest: request for file %s.\n", fh->name);
871e2fd0 1846
1847 return 1;
1848}
1849
1850
1851int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1852{
1853 va_list ap;
1854 struct aim_conn_t *oftconn;
1855 struct aim_fileheader_t *fh;
1856 char *path, *cookie;
646c6b52 1857 int pos, bufpos = 0, bufsize = 2048, i;
1858 char *buf;
871e2fd0 1859
1860 FILE *file;
1861
e7fb57f5 1862 va_start(ap, command);
871e2fd0 1863 oftconn = va_arg(ap, struct aim_conn_t *);
1864 fh = va_arg(ap, struct aim_fileheader_t *);
1865 cookie = va_arg(ap, char *);
1866 va_end(ap);
1867
37ee990e 1868 dvprintf("faimtest: sending file %s(%ld).\n", fh->name, fh->size);
871e2fd0 1869
646c6b52 1870 if(!(buf = malloc(2048)))
1871 return -1;
1872
37ee990e 1873 if( (path = (char *)calloc(1, strlen(listingpath) +strlen(fh->name)+2)) == NULL) {
1874 dperror("calloc");
1875 dprintf("faimtest: error in calloc of path\n");
871e2fd0 1876 return 0; /* XXX: no idea what winaim expects here =) */
1877 }
1878
37ee990e 1879 snprintf(path, strlen(listingpath)+strlen(fh->name)+2, "%s/%s", listingpath, fh->name);
871e2fd0 1880
1881
1882 if( (file = fopen(path, "r")) == NULL) {
37ee990e 1883 dvprintf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
871e2fd0 1884 return 0;
1885 }
646c6b52 1886
1887 /*
1888 * This is a mess. Remember that faimtest is demonstration code
1889 * only and for the sake of the gods, don't use this code in any
1890 * of your clients. --mid
1891 */
37ee990e 1892 for(pos = 0; pos < fh->size; pos++) {
1893 bufpos = pos % bufsize;
1894
1895 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
1896 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
1897 dperror("faim: getfile_send: write1");
1898 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
1899 free(buf);
1900 return -1;
1901 }
1902 }
1903 if( (buf[bufpos] = fgetc(file)) == EOF) {
1904 if(pos != fh->size) {
1905 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
1906 free(buf);
1907 return -1;
1908 }
1909 }
1910 dvprintf("%c(0x%02x) ", buf[pos], buf[pos]);
1911 }
871e2fd0 1912
37ee990e 1913 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
1914 dperror("faim: getfile_send: write2");
1915 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
1916 free(buf);
1917 return -1;
871e2fd0 1918 }
1919
646c6b52 1920 free(buf);
871e2fd0 1921 free(fh);
1922 return 1;
1923}
1924
1925int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1926{
1927 va_list ap;
1928 struct aim_conn_t *conn;
1929 struct aim_fileheader_t *fh;
1930
e7fb57f5 1931 va_start(ap, command);
871e2fd0 1932 conn = va_arg(ap, struct aim_conn_t *);
1933 fh = va_arg(ap, struct aim_fileheader_t *);
1934 va_end(ap);
1935
37ee990e 1936 dvprintf("faimtest: completed file transfer for %s.\n", fh->name);
871e2fd0 1937
37ee990e 1938 aim_conn_close(conn);
1939 aim_conn_kill(sess, &conn);
871e2fd0 1940 return 1;
1941}
1942
1943int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1944{
1945 va_list ap;
1946 struct aim_conn_t *conn;
1947 char *sn;
1948
e7fb57f5 1949 va_start(ap, command);
871e2fd0 1950 conn = va_arg(ap, struct aim_conn_t *);
1951 sn = va_arg(ap, char *);
1952 va_end(ap);
1953
1954 aim_conn_kill(sess, &conn);
1955
37ee990e 1956 dvprintf("faimtest: getfile: disconnected from %s\n", sn);
1957 return 1;
1958}
1959int faimtest_getfile_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1960{
1961 va_list ap;
646c6b52 1962 struct aim_conn_t *conn, *listenerconn;
37ee990e 1963 struct aim_filetransfer_priv *priv;
1964
1965 va_start(ap, command);
1966 conn = va_arg(ap, struct aim_conn_t *);
646c6b52 1967 listenerconn = va_arg(ap, struct aim_conn_t *);
37ee990e 1968 va_end(ap);
1969
646c6b52 1970 aim_conn_close(listenerconn);
1971 aim_conn_kill(sess, &listenerconn);
1972
37ee990e 1973 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, faimtest_getfile_filereq, 0);
1974 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
1975 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);
1976 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);
1977 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTING, faimtest_getfile_listing, 0);
1978 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ, faimtest_getfile_listingreq, 0);
646c6b52 1979 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE, faimtest_getfile_receive, 0);
1980 aim_conn_addhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4, faimtest_getfile_state4, 0);
37ee990e 1981
1982 priv = (struct aim_filetransfer_priv *)conn->priv;
1983
646c6b52 1984 dvprintf("faimtest: getfile: %s (%s) connected to us on %d\n", priv->sn, priv->ip, conn->fd);
871e2fd0 1985 return 1;
1986}
871e2fd0 1987
37ee990e 1988int faimtest_getfile_listing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1989{
1990 va_list ap;
1991 struct aim_conn_t *conn;
1992 char *listing;
1993 struct aim_filetransfer_priv *ft;
1994 char *filename, *nameend, *sizec;
1995 int filesize, namelen;
1996
1997 va_start(ap, command);
1998 conn = va_arg(ap, struct aim_conn_t *);
1999 ft = va_arg(ap, struct aim_filetransfer_priv *);
2000 listing = va_arg(ap, char *);
2001 va_end(ap);
2002
2003 dvprintf("listing on %d==================\n%s\n===========\n", conn->fd, listing);
2004
2005 nameend = strstr(listing+0x1a, "\r");
2006
2007 namelen = nameend - (listing + 0x1a);
2008
2009 filename = malloc(namelen + 1);
2010 strncpy(filename, listing+0x1a, namelen);
2011 filename[namelen] = 0x00;
2012
2013 sizec = malloc(8+1);
2014 memcpy(sizec, listing + 0x11, 8);
2015 sizec[8] = 0x00;
2016
2017 filesize = strtol(sizec, (char **)NULL, 10);
2018
2019 dvprintf("faimtest: requesting %d %s(%d long)\n", namelen, filename, filesize);
2020
2021 aim_oft_getfile_request(sess, conn, filename, filesize);
2022
2023 free(filename);
2024 free(sizec);
2025
2026 return 0;
2027}
2028
2029int faimtest_getfile_listingreq(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2030{
2031 va_list ap;
2032 struct aim_conn_t *oftconn;
2033 struct aim_fileheader_t *fh;
646c6b52 2034 int pos, bufpos = 0, bufsize = 2048, i;
2035 char *buf;
37ee990e 2036
2037 va_start(ap, command);
2038 oftconn = va_arg(ap, struct aim_conn_t *);
2039 fh = va_arg(ap, struct aim_fileheader_t *);
2040 va_end(ap);
2041
2042 dvprintf("faimtest: sending listing of size %ld\n", fh->size);
2043
646c6b52 2044 if(!(buf = malloc(2048)))
2045 return -1;
2046
37ee990e 2047 for(pos = 0; pos < fh->size; pos++) {
2048 bufpos = pos % bufsize;
2049
2050 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
2051 if ( (i = send(oftconn->fd, buf, bufsize, 0)) != bufsize ) {
2052 dperror("faim: getfile_send: write1");
2053 dprintf("faim: getfile_send: whoopsy, didn't write it all...\n");
2054 free(buf);
2055 return -1;
2056 }
2057 }
2058 if( (buf[bufpos] = fgetc(listingfile)) == EOF) {
2059 if(pos != fh->size) {
2060 dvprintf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
2061 free(buf);
2062 return -1;
2063 }
2064 }
2065 }
2066
2067 if( (i = send(oftconn->fd, buf, bufpos+1, 0)) != (bufpos+1)) {
2068 dperror("faim: getfile_send: write2");
2069 dprintf("faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
2070 free(buf);
2071 return -1;
2072 }
2073
2074 dprintf("faimtest: sent listing\n");
646c6b52 2075 free(buf);
37ee990e 2076 return 0;
2077}
2078
646c6b52 2079int faimtest_getfile_receive(struct aim_session_t *sess, struct command_rx_struct *command, ...)
37ee990e 2080{
2081 va_list ap;
2082 struct aim_conn_t *conn;
2083 struct aim_filetransfer_priv *ft;
2084 unsigned char data;
2085 int pos;
2086
2087 va_start(ap, command);
2088 conn = va_arg(ap, struct aim_conn_t *);
2089 ft = va_arg(ap, struct aim_filetransfer_priv *);
2090 va_end(ap);
2091
2092 dvprintf("faimtest: receiving %ld bytes of file data for %s:\n\t", ft->fh.size, ft->fh.name);
2093
2094 for(pos = 0; pos < ft->fh.size; pos++) {
2095 read(conn->fd, &data, 1);
646c6b52 2096 printf("%c(%02x) ", data, data);
37ee990e 2097 }
2098
646c6b52 2099 printf("\n");
37ee990e 2100
37ee990e 2101 aim_oft_getfile_end(sess, conn);
2102
2103 return 0;
2104}
646c6b52 2105
2106int faimtest_getfile_state4(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2107{
2108 va_list ap;
2109 struct aim_conn_t *conn;
2110
2111 va_start(ap, command);
2112 conn = va_arg(ap, struct aim_conn_t *);
2113 va_end(ap);
2114
2115 aim_conn_close(conn);
2116 aim_conn_kill(sess, &conn);
2117 return 0;
2118}
2119
2120
1a8c261b 2121int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2122{
275a2ff8 2123 static char *codes[5] = {"invalid",
2124 "change",
2125 "warning",
2126 "limit",
2127 "limit cleared"};
1a8c261b 2128 va_list ap;
275a2ff8 2129 int code;
d6c9fcf0 2130 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
275a2ff8 2131 unsigned long currentavg, maxavg;
2132
1a8c261b 2133 va_start(ap, command);
275a2ff8 2134
2135 /* See code explanations below */
2136 code = va_arg(ap, int);
2137
2138 /*
d6c9fcf0 2139 * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
275a2ff8 2140 */
d6c9fcf0 2141 rateclass = va_arg(ap, unsigned long);
275a2ff8 2142
2143 /*
2144 * Not sure what this is exactly. I think its the temporal
2145 * relation factor (ie, how to make the rest of the numbers
2146 * make sense in the real world).
2147 */
2148 windowsize = va_arg(ap, unsigned long);
2149
2150 /* Explained below */
2151 clear = va_arg(ap, unsigned long);
2152 alert = va_arg(ap, unsigned long);
2153 limit = va_arg(ap, unsigned long);
2154 disconnect = va_arg(ap, unsigned long);
2155 currentavg = va_arg(ap, unsigned long);
2156 maxavg = va_arg(ap, unsigned long);
2157
1a8c261b 2158 va_end(ap);
2159
275a2ff8 2160
37ee990e 2161 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 2162 (code < 5)?codes[code]:"invalid",
d6c9fcf0 2163 rateclass,
275a2ff8 2164 currentavg, maxavg,
2165 alert, clear,
2166 limit, disconnect,
2167 windowsize);
2168
2169 if (code == AIM_RATE_CODE_CHANGE) {
2170 /*
2171 * Not real sure when these get sent.
2172 */
2173 if (currentavg >= clear)
2174 aim_conn_setlatency(command->conn, 0);
2175
2176 } else if (code == AIM_RATE_CODE_WARNING) {
2177 /*
2178 * We start getting WARNINGs the first time we go below the 'alert'
2179 * limit (currentavg < alert) and they stop when either we pause
2180 * long enough for currentavg to go above 'clear', or until we
2181 * flood it bad enough to go below 'limit' (and start getting
2182 * LIMITs instead) or even further and go below 'disconnect' and
2183 * get disconnected completely (and won't be able to login right
2184 * away either).
2185 */
2186 aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
2187
2188 } else if (code == AIM_RATE_CODE_LIMIT) {
2189 /*
2190 * When we hit LIMIT, messages will start getting dropped.
2191 */
2192 aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
2193
2194 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
2195 /*
2196 * The limit is cleared when curavg goes above 'clear'.
2197 */
2198 aim_conn_setlatency(command->conn, 0);
2199 }
1a8c261b 2200
871e2fd0 2201 return 1;
78b3fb13 2202}
98c88242 2203
2204int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2205{
2206 va_list ap;
06bc8607 2207 int newevil;
2208 struct aim_userinfo_s *userinfo;
98c88242 2209
2210 va_start(ap, command);
06bc8607 2211 newevil = va_arg(ap, int);
2212 userinfo = va_arg(ap, struct aim_userinfo_s *);
98c88242 2213 va_end(ap);
2214
06bc8607 2215 /*
2216 * Evil Notifications that are lacking userinfo->sn are anon-warns
2217 * if they are an evil increases, but are not warnings at all if its
2218 * a decrease (its the natural backoff happening).
2219 *
2220 * newevil is passed as an int representing the new evil value times
2221 * ten.
2222 */
37ee990e 2223 dvprintf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
2224
2225 return 1;
2226}
2227
2228int faimtest_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2229{
2230 va_list ap;
2231 char *address, *SNs;
2232 int i, num;
2233
2234 va_start(ap, command);
2235 address = va_arg(ap, char *);
2236 num = va_arg(ap, int);
2237 SNs = va_arg(ap, char *);
2238 va_end(ap);
2239
2240 dvprintf("faimtest: E-Mail Search Results for %s: ", address);
2241
2242 for(i = 0; i < num; i++)
2243 dvinlineprintf("%s, ", &SNs[i*(MAXSNLEN+1)]);
2244 dinlineprintf("\n");
2245
2246 return 1;
2247}
2248
2249int faimtest_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...)
2250{
2251 va_list ap;
2252 char *address;
2253
2254 va_start(ap, command);
2255 address = va_arg(ap, char *);
2256 va_end(ap);
2257
2258 dvprintf("faimtest: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
98c88242 2259
98c88242 2260 return 1;
78b3fb13 2261}
This page took 6.740328 seconds and 5 git commands to generate.