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