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