]> andersk Git - libfaim.git/blob - utils/faimtest/faimtest.c
- Sat Dec 16 01:34:19 UTC 2000
[libfaim.git] / utils / faimtest / faimtest.c
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
47 #include <faim/aim.h> 
48
49 int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...);
50 int faimtest_parse_offgoing(struct aim_session_t *, struct command_rx_struct *, ...);
51 int faimtest_parse_login_phase3d_f(struct aim_session_t *, struct command_rx_struct *, ...);
52 int faimtest_parse_authresp(struct aim_session_t *, struct command_rx_struct *, ...);
53 int faimtest_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *command, ...);
54 int faimtest_parse_userinfo(struct aim_session_t *, struct command_rx_struct *command, ...);
55 int faimtest_handleredirect(struct aim_session_t *, struct command_rx_struct *command, ...);
56 int faimtest_authsvrready(struct aim_session_t *, struct command_rx_struct *command, ...);
57 int faimtest_pwdchngdone(struct aim_session_t *, struct command_rx_struct *command, ...);
58 int faimtest_serverready(struct aim_session_t *, struct command_rx_struct *command, ...);
59 int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...);
60 int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
61 int faimtest_parse_msgack(struct aim_session_t *, struct command_rx_struct *command, ...);
62 int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
63 int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
64 int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
65 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
66 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
67 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
68 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
69 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
70 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
71
72 int faimtest_directim_request(struct aim_session_t *sess, struct command_rx_struct *command, ...);
73 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
74 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
75 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...);
76 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
77 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
78 #define FILESUPPORT
79 #ifdef FILESUPPORT
80 int faimtest_getfile_filereq(struct aim_session_t *sess, struct command_rx_struct *command, ...);
81 int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...);
82 int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...);
83 int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
84 #endif
85
86 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
87 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...);
88 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
89 int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
90 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
91 int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
92
93 static char *msgerrreasons[] = {
94   "Invalid error",
95   "Invalid SNAC",
96   "Rate to host",
97   "Rate to client",
98   "Not logged on",
99   "Service unavailable",
100   "Service not defined",
101   "Obsolete SNAC",
102   "Not supported by host",
103   "Not supported by client",
104   "Refused by client",
105   "Reply too big",
106   "Responses lost",
107   "Request denied",
108   "Busted SNAC payload",
109   "Insufficient rights",
110   "In local permit/deny",
111   "Too evil (sender)",
112   "Too evil (receiver)",
113   "User temporarily unavailable",
114   "No match",
115   "List overflow",
116   "Request ambiguous",
117   "Queue full",
118   "Not while on AOL"};
119 static int msgerrreasonslen = 25;
120
121 static char *screenname,*password,*server=NULL;
122 static int connected = 0;
123
124 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
125 {
126   if (command->data) {
127     printf("aim: minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10));
128   } else
129     printf("aim: NULL minimum report interval!\n");
130   return 1;
131 }
132
133 int faimtest_flapversion(struct aim_session_t *sess, struct command_rx_struct *command, ...)
134 {
135
136   printf("faimtest: using FLAP version %u\n", aimutil_get32(command->data));
137
138 #if 0
139   /* 
140    * This is an alternate location for starting the login process.
141    */
142   /* XXX should do more checking to make sure its really the right AUTH conn */
143   if (command->conn->type == AIM_CONN_TYPE_AUTH) {
144     /* do NOT send a connack/flapversion, request_login will send it if needed */
145     aim_request_login(sess, command->conn, screenname);
146     printf("faimtest: login request sent\n");
147   }
148 #endif
149
150   return 1;
151 }
152
153 /*
154  * This is a frivilous callback. You don't need it. I only used it for
155  * debugging non-blocking connects.
156  *
157  * If packets are sent to a conn before its fully connected, they
158  * will be queued and then transmitted when the connection completes.
159  *
160  */
161 int faimtest_conncomplete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
162 {
163   va_list ap;
164   struct aim_conn_t *conn;
165
166   va_start(ap, command);
167   conn = va_arg(ap, struct aim_conn_t *);
168   va_end(ap);
169   
170   if (conn)
171     printf("faimtest: connection on %d completed\n", conn->fd);
172
173   return 1;
174 }
175
176 #ifdef _WIN32
177 /*
178  * This is really all thats needed to link against libfaim on win32.
179  *
180  * Note that this particular version of faimtest has never been tested
181  * on win32, but I'm fairly sure it should.
182  */
183 int initwsa(void)
184 {
185   WORD wVersionRequested;
186   WSADATA wsaData;
187
188   wVersionRequested = MAKEWORD(2,2);
189   return WSAStartup(wVersionRequested, &wsaData);
190 }
191 #endif /* _WIN32 */
192
193 int main(void)
194 {
195   struct aim_session_t aimsess;
196   struct aim_conn_t *authconn = NULL, *waitingconn = NULL;
197   int keepgoing = 1;
198   char *proxy, *proxyusername, *proxypass;
199
200   char *listingpath;
201
202   int selstat = 0;
203
204 #ifdef FILESUPPORT
205   FILE *listingfile;
206 #endif
207
208   if ( !(screenname = getenv("SCREENNAME")) ||
209        !(password = getenv("PASSWORD")))
210     {
211       printf("Must specify SCREENAME and PASSWORD in environment.\n");
212       return -1;
213     }
214
215   server = getenv("AUTHSERVER");
216
217   proxy = getenv("SOCKSPROXY");
218   proxyusername = getenv("SOCKSNAME");
219   proxypass = getenv("SOCKSPASS");
220
221 #ifdef FILESUPPORT
222   listingpath = getenv("LISTINGPATH");
223 #endif
224
225 #ifdef _WIN32
226   if (initwsa() != 0) {
227     printf("faimtest: could not initialize windows sockets\n");
228     return -1;
229   }
230 #endif /* _WIN32 */
231
232   /* Pass zero as flags if you want blocking connects */
233   aim_session_init(&aimsess, AIM_SESS_FLAGS_NONBLOCKCONNECT);
234
235 #ifdef FILESUPPORT
236   if(listingpath) {
237     char *listingname;
238     if(!(listingname = (char *)calloc(1, strlen(listingpath)+strlen("/listing.txt")))) {
239       perror("listingname calloc.");
240       exit(-1);
241     }
242     sprintf(listingname, "%s/listing.txt", listingpath);
243     if( (listingfile = fopen(listingname, "r")) == NULL) {
244       printf("Couldn't open %s... bombing.\n", listingname);
245       exit(-1);
246     }
247
248     aim_oft_registerlisting(&aimsess, listingfile, listingpath);
249
250     free(listingname);
251   }
252 #endif
253
254   if (proxy)
255     aim_setupproxy(&aimsess, proxy, proxyusername, proxypass);
256
257   authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER);
258
259   if (authconn == NULL) {
260     fprintf(stderr, "faimtest: internal connection error while in aim_login.  bailing out.\n");
261     return -1;
262   } else if (authconn->fd == -1) {
263     if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
264       fprintf(stderr, "faimtest: could not resolve authorizer name\n");
265     else if (authconn->status & AIM_CONN_STATUS_CONNERR)
266       fprintf(stderr, "faimtest: could not connect to authorizer\n");
267     aim_conn_kill(&aimsess, &authconn);
268     return -1;
269   }
270
271   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
272   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
273   aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
274   aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);    
275
276   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
277
278   /* If the connection is in progress, this will just be queued */
279   aim_request_login(&aimsess, authconn, screenname);
280   printf("faimtest: login request sent\n");
281
282   while (keepgoing) {
283     waitingconn = aim_select(&aimsess, NULL, &selstat);
284
285     switch(selstat) {
286     case -1: /* error */
287       keepgoing = 0; /* fall through and hit the aim_logoff() */
288       break;
289
290     case 0: /* no events pending */
291       break;
292
293     case 1: /* outgoing data pending */
294       aim_tx_flushqueue(&aimsess);
295       break;
296
297     case 2: /* incoming data pending */
298       if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
299         if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
300           printf("connection error (rend out)\n");
301         }
302       } else {
303         if (aim_get_command(&aimsess, waitingconn) >= 0) {
304           aim_rxdispatch(&aimsess);
305         } else {
306           printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
307           if(waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
308             /* we should have callbacks for all these, else the library will do the conn_kill for us. */
309             printf("connection error: rendezvous connection. you forgot register a disconnect callback, right?\n");
310           }
311           else
312             aim_conn_kill(&aimsess, &waitingconn);
313           if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
314             printf("major connection error\n");
315             keepgoing = 0;
316           }
317         }
318       }
319       break;
320       
321     default:
322       break; /* invalid */
323     }
324   }
325
326   /* Close up */
327   printf("AIM just decided we didn't need to be here anymore, closing up...\n");
328   
329   /* close up all connections, dead or no */
330   aim_logoff(&aimsess); 
331
332   /* Get out */
333   exit(0);
334 }
335
336 int faimtest_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
337 {
338
339   switch(command->conn->type) {
340   case AIM_CONN_TYPE_BOS: {
341     /* this is the new buddy list */
342     char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&midendian&ewarmenhoven&";
343     /* this is the new profile */
344     char profile[] = "Hello";  
345
346     aim_bos_ackrateresp(sess, command->conn);  /* ack rate info response */
347     aim_bos_reqpersonalinfo(sess, command->conn);
348     aim_bos_reqlocaterights(sess, command->conn);
349     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);
350     aim_bos_reqbuddyrights(sess, command->conn);
351
352     /* send the buddy list and profile (required, even if empty) */
353     aim_bos_setbuddylist(sess, command->conn, buddies);
354
355     /* dont really know what this does */
356     aim_addicbmparam(sess, command->conn);
357     aim_bos_reqicbmparaminfo(sess, command->conn);  
358   
359     aim_bos_reqrights(sess, command->conn);  
360     /* set group permissions -- all user classes */
361     aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS);
362     aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE|AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
363
364     break;  
365   }
366
367   default: 
368     printf("faimtest: got rate response for unhandled connection type %04x\n", command->conn->type);
369     break;
370   }
371
372   return 1;
373 }
374
375 int faimtest_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...)
376 {
377   int vercount, i;
378   unsigned char *versions;
379   va_list ap;
380
381   va_start(ap, command);
382   vercount = va_arg(ap, int); /* number of family/version pairs */
383   versions = va_arg(ap, unsigned char *);
384   va_end(ap);
385
386   printf("faimtest: SNAC versions supported by this host: ");
387   for (i = 0; i < vercount*4; i += 4)
388     printf("0x%04x:0x%04x ", 
389            aimutil_get16(versions+i),  /* SNAC family */
390            aimutil_get16(versions+i+2) /* Version number */);
391   printf("\n");
392
393   return 1;
394 }
395
396 int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
397 {
398   int famcount, i;
399   unsigned short *families;
400   va_list ap;
401
402   va_start(ap, command);
403   famcount = va_arg(ap, int);
404   families = va_arg(ap, unsigned short *);
405   va_end(ap);
406
407   printf("faimtest: SNAC families supported by this host (type %d): ", command->conn->type);
408   for (i = 0; i < famcount; i++)
409     printf("0x%04x ", families[i]);
410   printf("\n");
411
412   switch (command->conn->type) {
413   case AIM_CONN_TYPE_BOS:
414
415     aim_setversions(sess, command->conn);
416     aim_bos_reqrate(sess, command->conn); /* request rate info */
417
418     fprintf(stderr, "faimtest: done with BOS ServerReady\n");
419     break;
420
421   case AIM_CONN_TYPE_CHATNAV:
422     fprintf(stderr, "faimtest: chatnav: got server ready\n");
423     aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
424     aim_bos_reqrate(sess, command->conn);
425     aim_bos_ackrateresp(sess, command->conn);
426     aim_chatnav_clientready(sess, command->conn);
427     aim_chatnav_reqrights(sess, command->conn);
428
429     break;
430
431   case AIM_CONN_TYPE_CHAT:
432     aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
433     aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
434     aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
435     aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
436     aim_bos_reqrate(sess, command->conn);
437     aim_bos_ackrateresp(sess, command->conn);
438     aim_chat_clientready(sess, command->conn);
439     break;
440
441   case AIM_CONN_TYPE_RENDEZVOUS: /* empty */
442     break;
443
444   default:
445     fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
446   }
447
448   return 1;
449 }
450
451 int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
452 {
453   va_list ap;
454   unsigned short maxbuddies, maxwatchers;
455
456   va_start(ap, command);
457   maxbuddies = va_arg(ap, int);
458   maxwatchers = va_arg(ap, int);
459   va_end(ap);
460
461   printf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
462
463   return 1;
464 }
465
466 int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
467 {
468   unsigned short maxpermits, maxdenies;
469   va_list ap;
470
471   va_start(ap, command);
472   maxpermits = va_arg(ap, int);
473   maxdenies = va_arg(ap, int);
474   va_end(ap);
475
476   printf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
477
478   aim_bos_clientready(sess, command->conn);
479
480   printf("faimtest: officially connected to BOS.\n");
481
482   return 1;
483 }
484
485 /*
486   handleredirect()...
487
488   This, of course, handles Service Redirects from OSCAR.
489
490   Should get passed in the following:
491      struct command_rx_struct *command
492        the raw command data
493      int serviceid
494        the destination service ID
495      char *serverip
496        the IP address of the service's server
497      char *cookie
498        the raw auth cookie
499  */
500 int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
501 {
502   va_list ap;
503   int serviceid;
504   char *ip;
505   unsigned char *cookie;
506
507   va_start(ap, command);
508   serviceid = va_arg(ap, int);
509   ip = va_arg(ap, char *);
510   cookie = va_arg(ap, unsigned char *);
511  
512   switch(serviceid)
513     {
514     case 0x0007: /* Authorizer */
515       {
516         struct aim_conn_t *tstconn;
517         /* Open a connection to the Auth */
518         tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
519         if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR) )
520           fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
521         else {
522           aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
523           aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
524           /* Send the cookie to the Auth */
525           aim_auth_sendcookie(sess, tstconn, cookie);
526         }
527
528       }  
529       break;
530     case 0x000d: /* ChatNav */
531       {
532         struct aim_conn_t *tstconn = NULL;
533         tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
534         if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
535           fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
536           if (tstconn) aim_conn_kill(sess, &tstconn);
537           return 1;
538         }
539 #if 0
540         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
541         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
542 #endif
543         aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
544         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
545         aim_auth_sendcookie(sess, tstconn, cookie);
546         fprintf(stderr, "\achatnav: connected\n");
547       }
548       break;
549     case 0x000e: /* Chat */
550       {
551         char *roomname = NULL;
552         int exchange;
553         struct aim_conn_t *tstconn = NULL;
554
555         roomname = va_arg(ap, char *);
556         exchange = va_arg(ap, int);
557
558         tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
559         if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR))
560           {
561             fprintf(stderr, "faimtest: unable to connect to chat server\n");
562             if (tstconn) aim_conn_kill(sess, &tstconn);
563             return 1;
564           }             
565         printf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
566
567         /*
568          * We must do this to attach the stored name to the connection!
569          */
570         aim_chat_attachname(tstconn, roomname);
571
572         aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
573         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
574         aim_auth_sendcookie(sess, tstconn, cookie);
575       }
576       break;
577     default:
578       printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
579       /* dunno */
580     }
581
582   va_end(ap);
583
584   return 1;
585 }
586
587 int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
588 {
589   va_list ap;
590   struct aim_conn_t *bosconn = NULL;
591   char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
592   unsigned char *cookie = NULL;
593   int errorcode = 0, regstatus = 0;
594   int latestbuild = 0, latestbetabuild = 0;
595   char *latestrelease = NULL, *latestbeta = NULL;
596   char *latestreleaseurl = NULL, *latestbetaurl = NULL;
597   char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
598
599   va_start(ap, command);
600   sn = va_arg(ap, char *);
601   errorcode = va_arg(ap, int);
602   errurl = va_arg(ap, char *);
603   regstatus = va_arg(ap, int);
604   email = va_arg(ap, char *);
605   bosip = va_arg(ap, char *);
606   cookie = va_arg(ap, unsigned char *);
607
608   latestrelease = va_arg(ap, char *);
609   latestbuild = va_arg(ap, int);
610   latestreleaseurl = va_arg(ap, char *);
611   latestreleaseinfo = va_arg(ap, char *);
612
613   latestbeta = va_arg(ap, char *);
614   latestbetabuild = va_arg(ap, int);
615   latestbetaurl = va_arg(ap, char *);
616   latestbetainfo = va_arg(ap, char *);
617
618   va_end(ap);
619
620   printf("Screen name: %s\n", sn);
621
622   /*
623    * Check for error.
624    */
625   if (errorcode || !bosip || !cookie) {
626     printf("Login Error Code 0x%04x\n", errorcode);
627     printf("Error URL: %s\n", errurl);
628     aim_conn_kill(sess, &command->conn); 
629     return 1;
630   }
631
632   printf("Reg status: %2d\n", regstatus);
633   printf("Email: %s\n", email);
634   printf("BOS IP: %s\n", bosip);
635
636   if (latestbeta)
637     printf("Latest beta version: %s, build %d, at %s (more info at %s)\n", latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
638
639   if (latestrelease)
640     printf("Latest released version: %s, build %d, at %s (more info at %s)\n", latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
641
642   printf("Closing auth connection...\n");
643   aim_conn_kill(sess, &command->conn);
644   if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
645     fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
646     return 1;
647   } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
648     fprintf(stderr, "faimtest: could not connect to BOS\n");
649     aim_conn_kill(sess, &bosconn);
650     return 1;
651   }
652
653   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
654   aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
655   aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
656   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
657   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, faimtest_hostversions, 0);
658   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
659   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
660   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
661   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
662   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
663   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
664   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
665   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
666   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
667   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
668   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
669   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
670   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
671   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
672   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
673
674   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
675   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
676   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
677     
678   aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, faimtest_parse_genericerr, 0);
679   aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, faimtest_parse_genericerr, 0);
680   aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, faimtest_parse_genericerr, 0);
681
682   aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
683
684
685   aim_auth_sendcookie(sess, bosconn, cookie);
686
687   return 1;
688 }
689
690 static void printuserflags(unsigned short flags)
691 {
692   if (flags & AIM_FLAG_UNCONFIRMED)
693     printf("UNCONFIRMED ");
694   if (flags & AIM_FLAG_ADMINISTRATOR)
695     printf("ADMINISTRATOR ");
696   if (flags & AIM_FLAG_AOL)
697     printf("AOL ");
698   if (flags & AIM_FLAG_OSCAR_PAY)
699       printf("OSCAR_PAY ");
700   if (flags & AIM_FLAG_FREE)
701     printf("FREE ");
702   if (flags & AIM_FLAG_AWAY)
703     printf("AWAY ");
704   if (flags & AIM_FLAG_UNKNOWN40)
705     printf("ICQ? ");
706   if (flags & AIM_FLAG_UNKNOWN80)
707     printf("UNKNOWN80 ");
708   return;
709 }
710
711 int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
712 {
713   struct aim_userinfo_s *userinfo;
714   char *prof_encoding = NULL;
715   char *prof = NULL;
716   unsigned short inforeq = 0;
717
718   va_list ap;
719   va_start(ap, command);
720   userinfo = va_arg(ap, struct aim_userinfo_s *);
721   prof_encoding = va_arg(ap, char *);
722   prof = va_arg(ap, char *);
723   inforeq = va_arg(ap, int);
724   va_end(ap);
725   
726   printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
727   printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
728   printf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
729   printuserflags(userinfo->flags);
730   printf("\n");
731   
732   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
733   printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
734   printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
735   
736   if (inforeq == AIM_GETINFO_GENERALINFO) {
737     printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
738     printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
739   } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
740     printf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
741     printf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
742   } else 
743     printf("faimtest: userinfo: unknown info request\n");
744   
745   return 1;
746 }
747
748 /*
749  * The user-level Incoming ICBM callback.
750  *
751  * Arguments:
752  *  struct command_rx_struct *  command     if you feel like doing it yourself
753  *  char *                      srcsn       the source name
754  *  char *                      msg         message
755  *  int                         warnlevel   warning/evil level
756  *  int                         flags       flags
757  *  ulong                       membersince time_t of date of signup
758  *  ulong                       onsince     time_t of date of singon
759  *  int                         idletime    min (sec?) idle
760  *  u_int                       icbmflags   sets AIM_IMFLAGS_{AWAY,ACK}
761  *
762  */
763 int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
764 {
765   int channel;
766   va_list ap;
767
768   va_start(ap, command);
769   channel = va_arg(ap, int);
770
771   /*
772    * Channel 1: Standard Message
773    */
774   if (channel == 1) {
775     struct aim_userinfo_s *userinfo;
776     char *msg = NULL;
777     u_int icbmflags = 0;
778     char *tmpstr = NULL;
779     unsigned short flag1, flag2;
780     
781     userinfo = va_arg(ap, struct aim_userinfo_s *);
782     msg = va_arg(ap, char *);
783     icbmflags = va_arg(ap, u_int);
784     flag1 = va_arg(ap, int);
785     flag2 = va_arg(ap, int);
786     va_end(ap);
787     
788     printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
789     printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
790     printf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
791     printuserflags(userinfo->flags);
792     printf("\n");
793
794     printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
795     printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
796     printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
797     printf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
798     
799     printf("faimtest: icbm: icbmflags = ");
800     if (icbmflags & AIM_IMFLAGS_AWAY)
801       printf("away ");
802     if (icbmflags & AIM_IMFLAGS_ACK)
803       printf("ackrequest ");
804     printf("\n");
805     
806     printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
807     
808     printf("faimtest: icbm: message: %s\n", msg);
809     
810     if (msg) {
811       int i = 0;
812
813       while (msg[i] == '<') {
814         if (msg[i] == '<') {
815           while (msg[i] != '>')
816             i++;
817           i++;
818         }
819       }
820       tmpstr = msg+i;
821
822       printf("tmpstr = %s\n", tmpstr);
823       
824       if ( (strlen(tmpstr) >= 10) &&
825            (!strncmp(tmpstr, "disconnect", 10)) ) {
826           aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
827           aim_logoff(sess);
828       } else if (strstr(tmpstr, "goodday")) {
829         printf("faimtest: icbm: sending response\n");
830         aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
831       } else if (strstr(tmpstr, "warnme")) {
832         printf("faimtest: icbm: sending non-anon warning\n");
833         aim_send_warning(sess, command->conn, userinfo->sn, 0);
834       } else if (strstr(tmpstr, "anonwarn")) {
835         printf("faimtest: icbm: sending anon warning\n");
836         aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
837       } else if (strstr(tmpstr, "setdirectoryinfo")) {
838         printf("faimtest: icbm: sending backwards profile data\n");
839         aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
840       } else if (strstr(tmpstr, "setinterests")) {
841         printf("faimtest: icbm: setting fun interests\n");
842         aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
843       } else if (!strncmp(tmpstr, "open chatnav", 12)) {
844         aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
845         //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
846       } else if (!strncmp(tmpstr, "create", 6)) {
847         aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
848       } else if (!strncmp(tmpstr, "close chatnav", 13)) {
849         struct aim_conn_t *chatnavconn;
850         chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
851         aim_conn_kill(sess, &chatnavconn);
852       } else if (!strncmp(tmpstr, "join", 4)) {
853           aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
854       } else if (!strncmp(tmpstr, "leave", 5))
855             aim_chat_leaveroom(sess, "worlddomination");
856       else if (!strncmp(tmpstr, "getinfo", 7)) {
857         aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
858         aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
859       } else if (!strncmp(tmpstr, "open directim", 13)) {
860         struct aim_conn_t *newconn;
861         newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
862       } else if (!strncmp(tmpstr, "openauth", 8)) {
863         aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_AUTH);
864       } else if (!strncmp(tmpstr, "auth", 4)) {
865         aim_genericreq_n(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0007, 0x0002);
866       } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
867         aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7900");
868       } else if (!strncmp(tmpstr, "sendmsg", 7)) {
869         int i;
870         i = atoi(tmpstr+8);
871         if (i < 10000) {
872           char *newbuf;
873           int z;
874
875           newbuf = malloc(i+1);
876           for (z = 0; z < i; z++) {
877             newbuf[z] = (z % 10)+0x30;
878           }
879           newbuf[i] = '\0';
880           aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf);
881           free(newbuf);
882         }
883       } else {
884         printf("unknown command.\n");
885         aim_add_buddy(sess, command->conn, userinfo->sn);
886       }
887       
888     }
889   }
890   /*
891    * Channel 2: Rendevous Request
892    */
893   else if (channel == 2) {
894     struct aim_userinfo_s *userinfo;
895     unsigned short reqclass;
896     
897     reqclass = va_arg(ap, int);
898     switch (reqclass) {
899     case AIM_CAPS_VOICE: {
900       userinfo = va_arg(ap, struct aim_userinfo_s *);
901       va_end(ap);
902       
903       printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
904       printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
905       printf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
906       printuserflags(userinfo->flags);
907       printf("\n");
908
909       /* we dont get membersince on chat invites! */
910       printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
911       printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
912       
913       break;
914     }
915     case AIM_CAPS_GETFILE: {
916 #ifdef FILESUPPORT
917       char *ip, *cookie;
918       struct aim_conn_t *newconn;
919
920       userinfo = va_arg(ap, struct aim_userinfo_s *);
921       ip = va_arg(ap, char *);
922       cookie = va_arg(ap, char *);
923       va_end(ap);
924       
925       printf("faimtest: get file request from %s (at %s)\n", userinfo->sn, ip);
926
927       sleep(1);
928
929       if( (newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, sess->oft.listing, reqclass)) == NULL ) {
930         printf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
931         break;
932       }
933       
934       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ,  faimtest_getfile_filereq, 0);
935       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
936       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);      
937       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);      
938
939       printf("faimtest: getfile connect succeeded, handlers added.\n");
940
941       break;
942 #endif
943     }
944     case AIM_CAPS_SENDFILE: {
945       printf("faimtest: send file!\n");
946       break;
947     }
948     case AIM_CAPS_CHAT: {
949       char *msg,*encoding,*lang;
950       struct aim_chat_roominfo *roominfo;
951       
952       userinfo = va_arg(ap, struct aim_userinfo_s *);
953       roominfo = va_arg(ap, struct aim_chat_roominfo *);
954       msg = va_arg(ap, char *);
955       encoding = va_arg(ap, char *);
956       lang = va_arg(ap, char *);
957       va_end(ap);
958       
959       printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
960       printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
961       printf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
962       printuserflags(userinfo->flags);
963       printf("\n");
964
965       /* we dont get membersince on chat invites! */
966       printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
967       printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
968       
969       printf("faimtest: chat invitation: message = %s\n", msg);
970       printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
971       printf("faimtest: chat invitation: encoding = %s\n", encoding);
972       printf("faimtest: chat invitation: language = %s\n", lang);
973       printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
974       printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
975       printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
976       /*
977        * Automatically join room...
978        */ 
979       aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
980       break;
981     }   
982     case AIM_CAPS_IMIMAGE: {
983       struct aim_directim_priv *priv;
984       struct aim_conn_t *newconn;
985
986       printf("faimtest: icbm: rendezvous imimage\n");
987      
988       userinfo = va_arg(ap, struct aim_userinfo_s *);
989       priv = va_arg(ap, struct aim_directim_priv *);
990       va_end(ap);
991
992       printf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
993       
994       if (!(newconn = aim_directim_connect(sess, command->conn, priv))) {
995         printf("faimtest: icbm: imimage: could not connect\n");
996         break;
997       }
998       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
999       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1000       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1001
1002       printf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
1003
1004       aim_send_im_direct(sess, newconn, "goodday");
1005
1006       break;
1007     }
1008     default:
1009       printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
1010     } /* switch */
1011   } else
1012     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
1013   printf("faimtest: icbm: done with ICBM handling\n");
1014
1015   return 1;
1016 }
1017
1018 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1019 {
1020   va_list ap;
1021   struct aim_directim_priv *priv;
1022   struct aim_conn_t *newconn;
1023
1024   va_start(ap, command);
1025   newconn = va_arg(ap, struct aim_conn_t *);
1026   va_end(ap);
1027
1028   priv = (struct aim_directim_priv *)newconn->priv;
1029
1030   printf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
1031   
1032   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
1033   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
1034   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
1035
1036   aim_send_im_direct(sess, newconn, "goodday");
1037
1038   printf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
1039
1040   return 1;
1041 }
1042
1043 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1044 {
1045   va_list ap;
1046   struct aim_directim_priv *priv;
1047   
1048   va_start(ap, command);
1049   priv = va_arg(ap, struct aim_directim_priv *);
1050
1051   va_end(ap);
1052   
1053   printf("faimtest: directim_connect\n");
1054
1055   return 1;
1056 }
1057
1058 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1059 {
1060   va_list ap;
1061   char *sn = NULL, *msg = NULL;
1062   struct aim_conn_t *conn;
1063
1064   va_start(ap, command);
1065   conn = va_arg(ap, struct aim_conn_t *);
1066   sn = va_arg(ap, char *);
1067   msg = va_arg(ap, char *);
1068   va_end(ap);
1069
1070   printf("faimtest: Directim from %s: %s\n", sn, msg);
1071   if (!strncmp(msg, "sendmsg", 7)) {
1072     int i;
1073     i = atoi(msg+8);
1074     if (i < 10000) {
1075       char *newbuf;
1076       int z;
1077       
1078       newbuf = malloc(i+1);
1079       for (z = 0; z < i; z++) {
1080         newbuf[z] = (z % 10)+0x30;
1081       }
1082       newbuf[i] = '\0';
1083       aim_send_im_direct(sess, conn, newbuf);
1084       free(newbuf);
1085     }
1086   } else if (!strncmp(msg, "goodday", 7)) {
1087     aim_send_im_direct(sess, conn, "Good day to you, too");
1088   } else {
1089     char newmsg[1024];
1090     snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1091     aim_send_im_direct(sess, conn, newmsg);
1092   }
1093   return 1;
1094 }
1095
1096 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1097 {
1098   va_list ap;
1099   struct aim_conn_t *conn;
1100   char *sn;
1101
1102   va_start(ap, command);
1103   conn = va_arg(ap, struct aim_conn_t *);
1104   sn = va_arg(ap, char *);
1105   va_end(ap);
1106
1107   printf("faimtest: directim: disconnected from %s\n", sn);
1108
1109   aim_conn_kill(sess, &conn);
1110   return 1;
1111 }
1112
1113 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1114 {
1115   va_list ap;
1116   char *sn;
1117   
1118   va_start(ap, command);
1119   sn = va_arg(ap, char *);
1120   va_end(ap);
1121
1122   printf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
1123   return 1;
1124 }
1125
1126 int faimtest_authsvrready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1127 {
1128   printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
1129   sleep(10);
1130   /* should just be able to tell it we're ready too... */
1131   aim_auth_clientready(sess, command->conn);
1132
1133 #if 0
1134   /*
1135    * This is where you'd really begin changing your password.
1136    *   However, this callback may get called for reasons other
1137    *   than you wanting to change your password.  You should 
1138    *   probably check that before actually doing it.
1139    */
1140   aim_auth_changepasswd(sess, command->conn, "PWD1", "PWD2");
1141 #endif
1142
1143   return 1;
1144 }
1145
1146 int faimtest_pwdchngdone(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1147 {
1148   printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
1149   return 1;
1150 }
1151
1152 int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1153 {
1154   struct aim_userinfo_s *userinfo;
1155    
1156   va_list ap;
1157   va_start(ap, command);
1158   userinfo = va_arg(ap, struct aim_userinfo_s *);
1159   va_end(ap);
1160
1161   printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1162          time(NULL),
1163          userinfo->sn, userinfo->flags,
1164          (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1165          (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1166          (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1167          (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1168          (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1169          (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1170          (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1171          (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1172          userinfo->capabilities);
1173   return 1;
1174 }
1175
1176 int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1177 {
1178   char *sn;
1179   va_list ap;
1180   
1181   va_start(ap, command);
1182   sn = va_arg(ap, char *);
1183   va_end(ap);
1184
1185   printf("\n%s has left\n", sn);
1186
1187   return 1;
1188 }
1189
1190 int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1191 {
1192   static char *codes[] = {
1193     "Unknown",
1194     "Mandatory upgrade",
1195     "Advisory upgrade",
1196     "System bulletin",
1197     "Top o' the world!"};
1198   static int codeslen = 5;
1199
1200   char *msg;
1201   unsigned short id;
1202   va_list ap;
1203   
1204   va_start(ap, command);
1205   id = va_arg(ap, int);
1206   msg = va_arg(ap, char *);
1207   va_end(ap);
1208
1209   printf("faimtest: motd: %s (%d / %s)\n", msg, id, 
1210          (id < codeslen)?codes[id]:"unknown");
1211
1212   if (!connected)
1213     connected++;
1214
1215   return 1;
1216 }
1217
1218 int faimtest_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1219 {
1220   va_list ap;
1221   unsigned short reason;
1222
1223   va_start(ap, command);
1224   reason = va_arg(ap, int);
1225   va_end(ap);
1226
1227   printf("faimtest: snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1228   
1229   return 1;
1230 }
1231
1232 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1233 {
1234   va_list ap;
1235   char *destsn;
1236   unsigned short reason;
1237
1238   va_start(ap, command);
1239   destsn = va_arg(ap, char *);
1240   reason = va_arg(ap, int);
1241   va_end(ap);
1242
1243   printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1244   
1245   return 1;
1246 }
1247
1248 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1249 {
1250   va_list ap;
1251   char *destsn;
1252   unsigned short reason;
1253
1254   va_start(ap, command);
1255   destsn = va_arg(ap, char *);
1256   reason = va_arg(ap, int);
1257   va_end(ap);
1258
1259   printf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1260   
1261   return 1;
1262 }
1263
1264 /* 
1265  * Handles callbacks for AIM_CB_MISSED_CALL.
1266  */
1267 int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1268 {
1269   static char *missedreasons[] = {
1270     "Unknown",
1271     "Message too large"};
1272   static int missedreasonslen = 2;
1273
1274   va_list ap;
1275   unsigned short chan, nummissed, reason;
1276   struct aim_userinfo_s *userinfo;
1277   
1278   va_start(ap, command);
1279   chan = va_arg(ap, int);
1280   userinfo = va_arg(ap, struct aim_userinfo_s *);
1281   nummissed = va_arg(ap, int);
1282   reason = va_arg(ap, int);
1283   va_end(ap);
1284
1285   printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1286   
1287   return 1;
1288 }
1289
1290 int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1291 {
1292   struct client_info_s info = {"faimtest (with SNAC login)", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x0000004b}; /* 4.1.2010 */
1293   char *key;
1294   va_list ap;
1295   
1296   va_start(ap, command);
1297   key = va_arg(ap, char *);
1298   va_end(ap);
1299
1300   aim_send_login(sess, command->conn, screenname, password, &info, key);
1301  
1302   return 1;
1303 }
1304
1305 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1306 {
1307   va_list ap;
1308   struct aim_userinfo_s *userinfo;
1309   int count = 0, i = 0;
1310   
1311   va_start(ap, command);
1312   count = va_arg(ap, int);
1313   userinfo = va_arg(ap, struct aim_userinfo_s *);
1314   va_end(ap);
1315
1316   printf("faimtest: chat: %s:  New occupants have joined:\n", (char *)command->conn->priv);
1317   while (i < count)
1318     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1319
1320   return 1;
1321 }
1322
1323 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1324 {
1325   va_list ap;
1326   struct aim_userinfo_s *userinfo;
1327   int count = 0, i = 0;
1328   
1329   va_start(ap, command);
1330   count = va_arg(ap, int);
1331   userinfo = va_arg(ap, struct aim_userinfo_s *);
1332   va_end(ap);
1333
1334   printf("faimtest: chat: %s:  Some occupants have left:\n", (char *)command->conn->priv);
1335   while (i < count)
1336     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1337
1338   return 1;
1339 }
1340
1341 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1342 {
1343   va_list ap;
1344   struct aim_userinfo_s *userinfo;
1345   struct aim_chat_roominfo *roominfo;
1346   char *roomname;
1347   int usercount,i;
1348   char *roomdesc;
1349   unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1350   unsigned long creationtime;
1351
1352   va_start(ap, command);
1353   roominfo = va_arg(ap, struct aim_chat_roominfo *);
1354   roomname = va_arg(ap, char *);
1355   usercount= va_arg(ap, int);
1356   userinfo = va_arg(ap, struct aim_userinfo_s *);
1357   roomdesc = va_arg(ap, char *);
1358   unknown_c9 = va_arg(ap, int);
1359   creationtime = va_arg(ap, unsigned long);
1360   maxmsglen = va_arg(ap, int);
1361   unknown_d2 = va_arg(ap, int);
1362   unknown_d5 = va_arg(ap, int);
1363   va_end(ap);
1364
1365   printf("faimtest: chat: %s:  info update:\n", (char *)command->conn->priv);
1366   printf("faimtest: chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", 
1367          (char *)command->conn->priv,
1368          roominfo->exchange,
1369          roominfo->name,
1370          roominfo->instance);
1371   printf("faimtest: chat: %s:  \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1372   printf("faimtest: chat: %s:  \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1373   printf("faimtest: chat: %s:  \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1374   
1375   i = 0;
1376   while (i < usercount)
1377     printf("faimtest: chat: %s:  \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1378
1379   printf("faimtest: chat: %s:  \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1380   printf("faimtest: chat: %s:  \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1381   printf("faimtest: chat: %s:  \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1382   printf("faimtest: chat: %s:  \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1383   printf("faimtest: chat: %s:  \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1384
1385   return 1;
1386 }
1387
1388 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1389 {
1390   va_list ap;
1391   struct aim_userinfo_s *userinfo;
1392   char *msg;
1393   char tmpbuf[1152];
1394  
1395   va_start(ap, command);
1396   userinfo = va_arg(ap, struct aim_userinfo_s *);       
1397   msg = va_arg(ap, char *);
1398   va_end(ap);
1399
1400   printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1401
1402   /*
1403    * Do an echo for testing purposes.  But not for ourselves ("oops!")
1404    */
1405   if (strcmp(userinfo->sn, sess->sn) != 0)
1406     {
1407       sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1408       aim_chat_send_im(sess, command->conn, tmpbuf);
1409     }
1410
1411   return 1;
1412 }
1413
1414 int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1415 {
1416   unsigned short type;
1417   va_list ap;
1418
1419   va_start(ap, command);
1420   type = va_arg(ap, int);
1421
1422   switch(type) {
1423   case 0x0002: {
1424     int maxrooms;
1425     struct aim_chat_exchangeinfo *exchanges;
1426     int exchangecount,i = 0;
1427     
1428     maxrooms = va_arg(ap, int);
1429     exchangecount = va_arg(ap, int);
1430     exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1431     va_end(ap);
1432     
1433     printf("faimtest: chat info: Chat Rights:\n");
1434     printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1435     
1436     printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1437     while (i < exchangecount) {
1438       printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n", 
1439              exchanges[i].number,       
1440              exchanges[i].name,
1441              exchanges[i].charset1,
1442              exchanges[i].lang1);
1443       i++;
1444     }
1445     
1446   }
1447   break;
1448   case 0x0008: {
1449     char *fqcn, *name, *ck;
1450     unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
1451     unsigned char createperms;
1452     unsigned long createtime;
1453
1454     fqcn = va_arg(ap, char *);
1455     instance = va_arg(ap, int);
1456     exchange = va_arg(ap, int);
1457     flags = va_arg(ap, int);
1458     createtime = va_arg(ap, unsigned long);
1459     maxmsglen = va_arg(ap, int);
1460     maxoccupancy = va_arg(ap, int);
1461     createperms = va_arg(ap, int);
1462     unknown = va_arg(ap, int);
1463     name = va_arg(ap, char *);
1464     ck = va_arg(ap, char *);
1465     va_end(ap);
1466
1467     printf("faimtest: recieved room create reply for %s/0x%04x\n", fqcn, exchange);
1468   }
1469   break;
1470   default:
1471     va_end(ap);
1472     printf("faimtest: chatnav info: unknown type (%04x)\n", type);
1473   }
1474   return 1;
1475 }
1476
1477 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1478 {
1479   va_list ap;
1480   unsigned short code;
1481   char *msg = NULL;
1482
1483   va_start(ap, command);
1484   code = va_arg(ap, int);
1485   msg = va_arg(ap, char *);
1486   va_end(ap);
1487
1488   printf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1489   aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1490
1491   return 1;
1492 }
1493
1494 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1495 {       
1496   printf("faimtest: connecting to an aimdebugd!\n");
1497
1498   /* convert the authorizer connection to a BOS connection */
1499   command->conn->type = AIM_CONN_TYPE_BOS;
1500
1501   aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1502
1503   /* tell the aimddebugd we're ready */
1504   aim_debugconn_sendconnect(sess, command->conn); 
1505
1506   /* go right into main loop (don't open a BOS connection, etc) */
1507   return 1;
1508 }
1509
1510 /*
1511  * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
1512  */
1513 int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1514 {
1515   va_list ap;
1516   unsigned short type;
1517   char *sn = NULL;
1518
1519   va_start(ap, command);
1520   type = va_arg(ap, int);
1521   sn = va_arg(ap, char *);
1522   va_end(ap);
1523
1524   printf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1525
1526   return 1;
1527 }
1528
1529 #ifdef FILESUPPORT
1530 int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1531 {
1532   va_list ap;
1533   struct aim_conn_t *oftconn;
1534   struct aim_fileheader_t *fh;
1535   char *cookie;
1536
1537   va_start(ap, command);
1538   oftconn = va_arg(ap, struct aim_conn_t *);
1539   fh = va_arg(ap, struct aim_fileheader_t *);
1540   cookie = va_arg(ap, char *);
1541   va_end(ap);
1542
1543   printf("faimtest: request for file %s.\n", fh->name);
1544
1545   return 1;
1546 }
1547
1548
1549 int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1550 {
1551   va_list ap;
1552   struct aim_conn_t *oftconn;
1553   struct aim_fileheader_t *fh;
1554   char *path, *cookie;
1555
1556   FILE *file;
1557
1558   va_start(ap, command);
1559   oftconn = va_arg(ap, struct aim_conn_t *);
1560   fh = va_arg(ap, struct aim_fileheader_t *);
1561   cookie = va_arg(ap, char *);
1562   va_end(ap);
1563
1564   printf("faimtest: sending file %s.\n", fh->name);
1565
1566   if( (path = (char *)calloc(1, strlen(sess->oft.listingdir) +strlen(fh->name)+2)) == NULL) {
1567     perror("calloc:");
1568     printf("faimtest: error in calloc of path\n");
1569     return 0; /* XXX: no idea what winaim expects here =) */
1570   }
1571   
1572   snprintf(path, strlen(sess->oft.listingdir)+strlen(fh->name)+2, "%s/%s", sess->oft.listingdir, fh->name);
1573
1574
1575   if( (file = fopen(path, "r")) == NULL) {
1576     printf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
1577     return 0;
1578   }
1579
1580   if (aim_getfile_send(oftconn, file, fh) == -1) {
1581     printf("faimtest: getfile_send failed. damn.\n");
1582   } else {
1583     printf("faimtest: looks like getfile went clean\n");
1584   }
1585
1586   free(fh);  
1587   return 1;
1588 }
1589
1590 int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...) 
1591 {
1592   va_list ap;
1593   struct aim_conn_t *conn;
1594   struct aim_fileheader_t *fh;
1595
1596   va_start(ap, command);
1597   conn = va_arg(ap, struct aim_conn_t *);
1598   fh = va_arg(ap, struct aim_fileheader_t *);
1599   va_end(ap);
1600
1601   printf("faimtest: completed file transfer for %s.\n", fh->name);
1602
1603   /*  aim_conn_kill(sess, &conn); */ /* we'll let winaim close the conn */
1604   return 1;
1605 }
1606
1607 int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1608 {
1609   va_list ap;
1610   struct aim_conn_t *conn;
1611   char *sn;
1612
1613   va_start(ap, command);
1614   conn = va_arg(ap, struct aim_conn_t *);
1615   sn = va_arg(ap, char *);
1616   va_end(ap);
1617
1618   aim_conn_kill(sess, &conn);
1619
1620   printf("faimtest: getfile: disconnected from %s\n", sn);
1621   return 1;
1622 }
1623 #endif
1624
1625 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1626 {
1627   static char *codes[5] = {"invalid",
1628                            "change",
1629                            "warning",
1630                            "limit",
1631                            "limit cleared"};
1632   va_list ap;
1633   int code;
1634   unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
1635   unsigned long currentavg, maxavg;
1636
1637   va_start(ap, command); 
1638
1639   /* See code explanations below */
1640   code = va_arg(ap, int);
1641
1642   /*
1643    * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1644    */
1645   rateclass = va_arg(ap, unsigned long);
1646
1647   /*
1648    * Not sure what this is exactly.  I think its the temporal 
1649    * relation factor (ie, how to make the rest of the numbers
1650    * make sense in the real world). 
1651    */
1652   windowsize = va_arg(ap, unsigned long);
1653
1654   /* Explained below */
1655   clear = va_arg(ap, unsigned long);
1656   alert = va_arg(ap, unsigned long);
1657   limit = va_arg(ap, unsigned long);
1658   disconnect = va_arg(ap, unsigned long);
1659   currentavg = va_arg(ap, unsigned long);
1660   maxavg = va_arg(ap, unsigned long);
1661
1662   va_end(ap);
1663
1664
1665   printf("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",
1666          (code < 5)?codes[code]:"invalid",
1667          rateclass,
1668          currentavg, maxavg,
1669          alert, clear,
1670          limit, disconnect,
1671          windowsize);
1672
1673   if (code == AIM_RATE_CODE_CHANGE) {
1674     /*
1675      * Not real sure when these get sent.
1676      */
1677     if (currentavg >= clear)
1678       aim_conn_setlatency(command->conn, 0);
1679
1680   } else if (code == AIM_RATE_CODE_WARNING) {
1681     /*
1682      * We start getting WARNINGs the first time we go below the 'alert'
1683      * limit (currentavg < alert) and they stop when either we pause
1684      * long enough for currentavg to go above 'clear', or until we
1685      * flood it bad enough to go below 'limit' (and start getting
1686      * LIMITs instead) or even further and go below 'disconnect' and 
1687      * get disconnected completely (and won't be able to login right
1688      * away either).
1689      */
1690     aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */ 
1691
1692   } else if (code == AIM_RATE_CODE_LIMIT) {
1693     /*
1694      * When we hit LIMIT, messages will start getting dropped.
1695      */
1696     aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */ 
1697
1698   } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
1699     /*
1700      * The limit is cleared when curavg goes above 'clear'.
1701      */
1702     aim_conn_setlatency(command->conn, 0); 
1703   }
1704
1705   return 1;
1706 }
1707
1708 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1709 {
1710   va_list ap;
1711   int newevil;
1712   struct aim_userinfo_s *userinfo;
1713
1714   va_start(ap, command);
1715   newevil = va_arg(ap, int);
1716   userinfo = va_arg(ap, struct aim_userinfo_s *);
1717   va_end(ap);
1718
1719   /*
1720    * Evil Notifications that are lacking userinfo->sn are anon-warns
1721    * if they are an evil increases, but are not warnings at all if its
1722    * a decrease (its the natural backoff happening).
1723    *
1724    * newevil is passed as an int representing the new evil value times
1725    * ten.
1726    */
1727   printf("faimtest: evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
1728
1729   return 1;
1730 }
This page took 0.194009 seconds and 5 git commands to generate.