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