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