]> andersk Git - libfaim.git/blob - utils/faimtest/faimtest.c
d38e7275fe8fcbf6312eb6e9a9f6c64d33b725b2
[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_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
60 int faimtest_parse_msgack(struct aim_session_t *, struct command_rx_struct *command, ...);
61 int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
62 int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
63 int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
64 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
65 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
66 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
67 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
68 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
69 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
70
71 int faimtest_directim_request(struct aim_session_t *sess, struct command_rx_struct *command, ...);
72 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
73 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
74 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...);
75 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
76 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...);
77 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...);
78 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...);
79 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
80 int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
81 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
82
83 static char *msgerrreasons[] = {
84   "Invalid error",
85   "Invalid SNAC",
86   "Rate to host",
87   "Rate to client",
88   "Not logged on",
89   "Service unavailable",
90   "Service not defined",
91   "Obsolete SNAC",
92   "Not supported by host",
93   "Not supported by client",
94   "Refused by client",
95   "Reply too big",
96   "Responses lost",
97   "Request denied",
98   "Busted SNAC payload",
99   "Insufficient rights",
100   "In local permit/deny",
101   "Too evil (sender)",
102   "Too evil (receiver)",
103   "User temporarily unavailable",
104   "No match",
105   "List overflow",
106   "Request ambiguous",
107   "Queue full",
108   "Not while on AOL"};
109 static int msgerrreasonslen = 25;
110
111 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
112 {
113   if (command->data) {
114     printf("aim: minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10));
115   } else
116     printf("aim: NULL minimum report interval!\n");
117   return 1;
118 }
119
120 #ifdef _WIN32
121 /*
122  * This is really all thats needed to link against libfaim on win32.
123  *
124  * Note that this particular version of faimtest has never been tested
125  * on win32, but I'm fairly sure it should.
126  */
127 int initwsa(void)
128 {
129   WORD wVersionRequested;
130   WSADATA wsaData;
131
132   wVersionRequested = MAKEWORD(2,2);
133   return WSAStartup(wVersionRequested, &wsaData);
134 }
135 #endif /* _WIN32 */
136
137 static char *screenname,*password,*server=NULL;
138
139 int main(void)
140 {
141   struct aim_session_t aimsess;
142   struct aim_conn_t *authconn = NULL, *waitingconn = NULL;
143   int keepgoing = 1;
144
145   int selstat = 0;
146
147   if ( !(screenname = getenv("SCREENNAME")) ||
148        !(password = getenv("PASSWORD")))
149     {
150       printf("Must specify SCREENAME and PASSWORD in environment.\n");
151       return -1;
152     }
153
154   server = getenv("AUTHSERVER");
155
156 #ifdef _WIN32
157   if (initwsa() != 0) {
158     printf("faimtest: could not initialize windows sockets\n");
159     return -1;
160   }
161 #endif /* _WIN32 */
162
163   aim_session_init(&aimsess);
164
165   authconn = aim_newconn(&aimsess, AIM_CONN_TYPE_AUTH, server?server:FAIM_LOGIN_SERVER);
166
167   if (authconn == NULL) {
168     fprintf(stderr, "faimtest: internal connection error while in aim_login.  bailing out.\n");
169     return -1;
170   } else if (authconn->fd == -1) {
171     if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
172       fprintf(stderr, "faimtest: could not resolve authorizer name\n");
173     else if (authconn->status & AIM_CONN_STATUS_CONNERR)
174       fprintf(stderr, "faimtest: could not connect to authorizer\n");
175     aim_conn_kill(&aimsess, &authconn);
176     return -1;
177   }
178
179   aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
180   aim_conn_addhandler(&aimsess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
181     
182   aim_sendconnack(&aimsess, authconn);
183   aim_request_login(&aimsess, authconn, screenname);
184
185   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
186
187   printf("faimtest: login request sent\n");
188
189   while (keepgoing) {
190     waitingconn = aim_select(&aimsess, NULL, &selstat);
191
192     switch(selstat) {
193     case -1: /* error */
194       keepgoing = 0; /* fall through and hit the aim_logoff() */
195       break;
196
197     case 0: /* no events pending */
198       break;
199
200     case 1: /* outgoing data pending */
201       aim_tx_flushqueue(&aimsess);
202       break;
203
204     case 2: /* incoming data pending */
205       if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
206         if (aim_handlerendconnect(&aimsess, waitingconn) < 0) {
207           printf("connection error (rend)\n");
208         }
209       } else {
210         if (aim_get_command(&aimsess, waitingconn) >= 0) {
211           aim_rxdispatch(&aimsess);
212         } else {
213           printf("connection error\n");
214           aim_conn_kill(&aimsess, &waitingconn);
215           if (!aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS)) {
216             printf("major connetion error\n");
217             keepgoing = 0;
218           }
219         }
220       }
221       break;
222       
223     default:
224       break; /* invalid */
225     }
226   }
227
228   /* Close up */
229   printf("AIM just decided we didn't need to be here anymore, closing up...\n");
230   
231   /* close up all connections, dead or no */
232   aim_logoff(&aimsess); 
233
234   /* Get out */
235   exit(0);
236 }
237
238 int faimtest_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
239 {
240
241   switch(command->conn->type) {
242   case AIM_CONN_TYPE_BOS: {
243     /* this is the new buddy list */
244     char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&";
245     /* this is the new profile */
246     char profile[] = "Hello";  
247
248     aim_bos_ackrateresp(sess, command->conn);  /* ack rate info response */
249     aim_bos_reqpersonalinfo(sess, command->conn);
250     aim_bos_reqlocaterights(sess, command->conn);
251     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);
252     aim_bos_reqbuddyrights(sess, command->conn);
253
254     /* send the buddy list and profile (required, even if empty) */
255     aim_bos_setbuddylist(sess, command->conn, buddies);
256
257     /* dont really know what this does */
258     aim_addicbmparam(sess, command->conn);
259     aim_bos_reqicbmparaminfo(sess, command->conn);  
260   
261     aim_bos_reqrights(sess, command->conn);  
262     /* set group permissions -- all user classes */
263     aim_bos_setgroupperm(sess, command->conn, AIM_CLASS_ALLUSERS);
264     aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE|AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
265
266     break;  
267   }
268
269   default: 
270     printf("faimtest: got rate response for unhandled connection type %04x\n", command->conn->type);
271     break;
272   }
273
274   return 1;
275 }
276
277 int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
278 {
279   switch (command->conn->type)
280     {
281     case AIM_CONN_TYPE_BOS:
282
283       aim_setversions(sess, command->conn);
284       aim_bos_reqrate(sess, command->conn); /* request rate info */
285
286       fprintf(stderr, "faimtest: done with BOS ServerReady\n");
287       break;
288
289     case AIM_CONN_TYPE_CHATNAV:
290       fprintf(stderr, "faimtest: chatnav: got server ready\n");
291       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
292       aim_bos_reqrate(sess, command->conn);
293       aim_bos_ackrateresp(sess, command->conn);
294       aim_chatnav_clientready(sess, command->conn);
295       aim_chatnav_reqrights(sess, command->conn);
296
297       break;
298     case AIM_CONN_TYPE_CHAT:
299       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
300       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
301       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
302       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
303       aim_bos_reqrate(sess, command->conn);
304       aim_bos_ackrateresp(sess, command->conn);
305       aim_chat_clientready(sess, command->conn);
306       break;
307
308     case AIM_CONN_TYPE_RENDEZVOUS: /* this is an overloaded function?? - mid */
309       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
310       aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
311       break;
312
313     default:
314       fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
315     }
316   return 1;
317 }
318
319 int faimtest_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
320 {       
321   va_list ap;
322   unsigned short maxbuddies, maxwatchers;
323
324   va_start(ap, command);
325   maxbuddies = va_arg(ap, unsigned short);
326   maxwatchers = va_arg(ap, unsigned short);
327   va_end(ap);
328
329   printf("faimtest: buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
330
331   return 1;
332 }
333
334 int faimtest_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...)
335 {
336   unsigned short maxpermits, maxdenies;
337   va_list ap;
338
339   va_start(ap, command);
340   maxpermits = va_arg(ap, unsigned short);
341   maxdenies = va_arg(ap, unsigned short);
342   va_end(ap);
343
344   printf("faimtest: BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
345
346   aim_bos_clientready(sess, command->conn);
347
348   printf("faimtest: officially connected to BOS.\n");
349
350   return 1;
351 }
352
353 /*
354   handleredirect()...
355
356   This, of course, handles Service Redirects from OSCAR.
357
358   Should get passed in the following:
359      struct command_rx_struct *command
360        the raw command data
361      int serviceid
362        the destination service ID
363      char *serverip
364        the IP address of the service's server
365      char *cookie
366        the raw auth cookie
367  */
368 int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
369 {
370   va_list ap;
371   int serviceid;
372   char *ip;
373   unsigned char *cookie;
374
375   va_start(ap, command);
376   serviceid = va_arg(ap, int);
377   ip = va_arg(ap, char *);
378   cookie = va_arg(ap, unsigned char *);
379  
380   switch(serviceid)
381     {
382     case 0x0007: /* Authorizer */
383       {
384         struct aim_conn_t *tstconn;
385         /* Open a connection to the Auth */
386         tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip);
387         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) )
388           fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
389         else
390           /* Send the cookie to the Auth */
391           aim_auth_sendcookie(sess, tstconn, cookie);
392
393       }  
394       break;
395     case 0x000d: /* ChatNav */
396       {
397         struct aim_conn_t *tstconn = NULL;
398         tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip);
399         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR)) {
400           fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
401           if (tstconn) aim_conn_kill(sess, &tstconn);
402           return 1;
403         }
404 #if 0
405         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
406         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
407 #endif
408         aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
409         aim_auth_sendcookie(sess, tstconn, cookie);
410         fprintf(stderr, "\achatnav: connected\n");
411       }
412       break;
413     case 0x000e: /* Chat */
414       {
415         char *roomname = NULL;
416         struct aim_conn_t *tstconn = NULL;
417
418         roomname = va_arg(ap, char *);
419
420         tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
421         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
422           {
423             fprintf(stderr, "faimtest: unable to connect to chat server\n");
424             if (tstconn) aim_conn_kill(sess, &tstconn);
425             return 1;
426           }             
427         printf("faimtest: chat: connected\n");
428
429         /*
430          * We must do this to attach the stored name to the connection!
431          */
432         aim_chat_attachname(tstconn, roomname);
433
434         aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
435         aim_auth_sendcookie(sess, tstconn, cookie);
436       }
437       break;
438     default:
439       printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
440       /* dunno */
441     }
442
443   va_end(ap);
444
445   return 1;
446 }
447
448 int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
449 {
450   struct aim_conn_t *bosconn = NULL;
451   
452
453   printf("Screen name: %s\n", sess->logininfo.screen_name);
454
455   /*
456    * Check for error.
457    */
458   if (sess->logininfo.errorcode)
459     {
460       printf("Login Error Code 0x%04x\n", sess->logininfo.errorcode);
461       printf("Error URL: %s\n", sess->logininfo.errorurl);
462       aim_conn_kill(sess, &command->conn);
463       exit(0); /* XXX: should return in order to let the above things get free()'d. */
464     }
465
466   printf("Reg status: %2d\n", sess->logininfo.regstatus);
467   printf("Email: %s\n", sess->logininfo.email);
468   printf("BOS IP: %s\n", sess->logininfo.BOSIP);
469
470   printf("Closing auth connection...\n");
471   aim_conn_kill(sess, &command->conn);
472   bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP);
473   if (bosconn == NULL) {
474     fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
475   } else if (bosconn->status != 0) {    
476     fprintf(stderr, "faimtest: could not connect to BOS\n");
477     aim_conn_kill(sess, &bosconn);
478   } else {
479     aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
480     aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
481     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
482     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
483     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
484     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
485     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
486     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
487     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
488     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
489     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
490     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
491     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
492     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
493     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
494     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
495     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
496     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
497
498     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
499     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
500     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
501     
502     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
503     
504     aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
505   }
506   return 1;
507 }
508
509 int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
510 {
511   struct aim_userinfo_s *userinfo;
512   char *prof_encoding = NULL;
513   char *prof = NULL;
514   unsigned short inforeq = 0;
515
516   va_list ap;
517   va_start(ap, command);
518   userinfo = va_arg(ap, struct aim_userinfo_s *);
519   prof_encoding = va_arg(ap, char *);
520   prof = va_arg(ap, char *);
521   inforeq = va_arg(ap, unsigned short);
522   va_end(ap);
523   
524   printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
525   printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
526   printf("faimtest: userinfo: class: 0x%04x = ", userinfo->class);
527
528   /*
529    *  00000000  (binary)
530    *         1  Trial  
531    *        2   Unknown
532    *       3    AOL
533    *      4     Unknown
534    *     5      Free
535    * 
536    * ORed together.
537    *
538    */
539
540   if (userinfo->class & 0x0001)
541     printf("TRIAL ");
542   if (userinfo->class & 0x0002)
543     printf("ADMINISTRATOR ");
544   if (userinfo->class & 0x0004)
545     printf("AOL ");
546   if (userinfo->class & 0x0008)
547     printf("OSCAR_PAY ");
548   if (userinfo->class & 0x0010)
549     printf("FREE ");
550   if (userinfo->class & 0x0040)
551     printf("ICQ? ");
552   printf("\n");
553   
554   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
555   printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
556   printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
557   
558   if (inforeq == AIM_GETINFO_GENERALINFO) {
559     printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
560     printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
561   } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
562     printf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
563     printf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
564   } else 
565     printf("faimtest: userinfo: unknown info request\n");
566   
567   return 1;
568 }
569
570 /*
571  * The user-level Incoming ICBM callback.
572  *
573  * Arguments:
574  *  struct command_rx_struct *  command     if you feel like doing it yourself
575  *  char *                      srcsn       the source name
576  *  char *                      msg         message
577  *  int                         warnlevel   warning/evil level
578  *  int                         class       user class
579  *  ulong                       membersince time_t of date of signup
580  *  ulong                       onsince     time_t of date of singon
581  *  int                         idletime    min (sec?) idle
582  *  u_int                       icbmflags   sets AIM_IMFLAGS_{AWAY,ACK}
583  *
584  */
585 int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
586 {
587   int channel;
588   va_list ap;
589
590   va_start(ap, command);
591   channel = va_arg(ap, int);
592
593   /*
594    * Channel 1: Standard Message
595    */
596   if (channel == 1) {
597     struct aim_userinfo_s *userinfo;
598     char *msg = NULL;
599     u_int icbmflags = 0;
600     char *tmpstr = NULL;
601     u_short flag1, flag2;
602     
603     userinfo = va_arg(ap, struct aim_userinfo_s *);
604     msg = va_arg(ap, char *);
605     icbmflags = va_arg(ap, u_int);
606     flag1 = va_arg(ap, u_short);
607     flag2 = va_arg(ap, u_short);
608     va_end(ap);
609     
610     printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
611     printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
612     printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
613     if (userinfo->class & 0x0010)
614       printf("(FREE) ");
615     if (userinfo->class & 0x0001)
616       printf("(TRIAL) ");
617     if (userinfo->class & 0x0004)
618       printf("(AOL) ");
619     printf("\n");
620     printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
621     printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
622     printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
623     printf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
624     
625     printf("faimtest: icbm: icbmflags = ");
626     if (icbmflags & AIM_IMFLAGS_AWAY)
627       printf("away ");
628     if (icbmflags & AIM_IMFLAGS_ACK)
629       printf("ackrequest ");
630     printf("\n");
631     
632     printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
633     
634     printf("faimtest: icbm: message: %s\n", msg);
635     
636     if (msg) {
637       int i = 0;
638
639       while (msg[i] == '<') {
640         if (msg[i] == '<') {
641           while (msg[i] != '>')
642             i++;
643           i++;
644         }
645       }
646       tmpstr = msg+i;
647
648       printf("tmpstr = %s\n", tmpstr);
649       
650       if ( (strlen(tmpstr) >= 10) &&
651            (!strncmp(tmpstr, "disconnect", 10)) ) {
652           aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
653           aim_logoff(sess);
654       } else if (strstr(tmpstr, "goodday")) {
655         printf("faimtest: icbm: sending response\n");
656         aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
657       } else if (strstr(tmpstr, "warnme")) {
658         printf("faimtest: icbm: sending non-anon warning\n");
659         aim_send_warning(sess, command->conn, userinfo->sn, 0);
660       } else if (strstr(tmpstr, "anonwarn")) {
661         printf("faimtest: icbm: sending anon warning\n");
662         aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
663       } else if (!strncmp(tmpstr, "open chatnav", 12)) {
664         aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
665         //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
666       } else if (!strncmp(tmpstr, "create", 6)) {
667         aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
668       } else if (!strncmp(tmpstr, "close chatnav", 13)) {
669         struct aim_conn_t *chatnavconn;
670         chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
671         aim_conn_kill(sess, &chatnavconn);
672       } else if (!strncmp(tmpstr, "join", 4)) {
673           aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
674       } else if (!strncmp(tmpstr, "leave", 5))
675             aim_chat_leaveroom(sess, "worlddomination");
676       else if (!strncmp(tmpstr, "getinfo", 7)) {
677         aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
678         aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
679       } else if (!strncmp(tmpstr, "open directim", 13)) {
680         struct aim_conn_t *newconn;
681         newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
682         //aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate, 0);
683       } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
684         aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7900");
685       } else if (!strncmp(tmpstr, "sendmsg", 7)) {
686         int i;
687         i = atoi(tmpstr+8);
688         if (i < 10000) {
689           char *newbuf;
690           int z;
691
692           newbuf = malloc(i+1);
693           for (z = 0; z < i; z++) {
694             newbuf[z] = (z % 10)+0x30;
695           }
696           newbuf[i] = '\0';
697           aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf);
698           free(newbuf);
699         }
700       } else {
701         printf("unknown command.\n");
702         aim_add_buddy(sess, command->conn, userinfo->sn);
703       }
704       
705     }
706   }
707   /*
708    * Channel 2: Rendevous Request
709    */
710   else if (channel == 2) {
711     struct aim_userinfo_s *userinfo;
712     unsigned short reqclass;
713     
714     reqclass = va_arg(ap, unsigned short);
715     switch (reqclass) {
716     case AIM_CAPS_VOICE: {
717       userinfo = va_arg(ap, struct aim_userinfo_s *);
718       va_end(ap);
719       
720       printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
721       printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
722       printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class);
723       if (userinfo->class & 0x0010)
724         printf("(FREE) ");
725       if (userinfo->class & 0x0001)
726         printf("(TRIAL) ");
727       if (userinfo->class & 0x0004)
728         printf("(AOL) ");
729       printf("\n");
730       /* we dont get membersince on chat invites! */
731       printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
732       printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
733       
734       break;
735     }
736     case AIM_CAPS_GETFILE: {
737       printf("faimtset: get file!\n");
738       break;
739     }
740     case AIM_CAPS_SENDFILE: {
741       printf("faimtest: send file!\n");
742       break;
743     }
744     case AIM_CAPS_CHAT: {
745       char *msg,*encoding,*lang;
746       struct aim_chat_roominfo *roominfo;
747       
748       userinfo = va_arg(ap, struct aim_userinfo_s *);
749       roominfo = va_arg(ap, struct aim_chat_roominfo *);
750       msg = va_arg(ap, char *);
751       encoding = va_arg(ap, char *);
752       lang = va_arg(ap, char *);
753       va_end(ap);
754       
755       printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
756       printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
757       printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
758       if (userinfo->class & 0x0010)
759         printf("(FREE) ");
760       if (userinfo->class & 0x0001)
761         printf("(TRIAL) ");
762       if (userinfo->class & 0x0004)
763         printf("(AOL) ");
764       printf("\n");
765       /* we dont get membersince on chat invites! */
766       printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
767       printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
768       
769       printf("faimtest: chat invitation: message = %s\n", msg);
770       printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
771       printf("faimtest: chat invitation: encoding = %s\n", encoding);
772       printf("faimtest: chat invitation: language = %s\n", lang);
773       printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
774       printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
775       printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
776       /*
777        * Automatically join room...
778        */ 
779       aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
780       break;
781     }   
782     case AIM_CAPS_IMIMAGE: {
783       struct aim_directim_priv *priv;
784       struct aim_conn_t *newconn;
785
786       printf("faimtest: icbm: rendezvous imimage\n");
787      
788       userinfo = va_arg(ap, struct aim_userinfo_s *);
789       priv = va_arg(ap, struct aim_directim_priv *);
790       va_end(ap);
791
792       printf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
793       
794       if (!(newconn = aim_directim_connect(sess, command->conn, priv))) {
795         printf("faimtest: icbm: imimage: could not connect\n");
796         break;
797       }
798       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
799       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
800       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
801
802       aim_send_im_direct(sess, newconn, "goodday");
803
804       printf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
805
806       break;
807     }
808     default:
809       printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
810     } /* switch */
811   } else
812     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
813   printf("faimtest: icbm: done with ICBM handling\n");
814
815   return 1;
816 }
817
818 #if 0
819 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
820 {
821   va_list ap;
822   struct aim_directim_priv *priv;
823   struct aim_conn_t *newconn;
824
825   ap = va_start(ap, command);
826   newconn = va_arg(ap, struct aim_conn_t *);
827   va_end(ap);
828
829   priv = (struct aim_directim_priv *)newconn->priv;
830
831   printf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
832   
833   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
834   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
835   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
836
837   aim_send_im_direct(sess, newconn, "goodday");
838
839   printf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
840
841   return 1;
842 }
843 #endif
844
845 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
846 {
847   va_list ap;
848   struct aim_directim_priv *priv;
849   
850   ap = va_start(ap, command);
851   priv = va_arg(ap, struct aim_directim_priv *);
852
853   va_end(ap);
854   
855   printf("faimtest: directim_connect\n");
856
857   return 1;
858 }
859
860 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
861 {
862   va_list ap;
863   char *sn = NULL, *msg = NULL;
864   struct aim_conn_t *conn;
865
866   ap = va_start(ap, command);
867   conn = va_arg(ap, struct aim_conn_t *);
868   sn = va_arg(ap, char *);
869   msg = va_arg(ap, char *);
870   va_end(ap);
871
872   printf("faimtest: Directim from %s: %s\n", sn, msg);
873   if (!strncmp(msg, "sendmsg", 7)) {
874     int i;
875     i = atoi(msg+8);
876     if (i < 10000) {
877       char *newbuf;
878       int z;
879       
880       newbuf = malloc(i+1);
881       for (z = 0; z < i; z++) {
882         newbuf[z] = (z % 10)+0x30;
883       }
884       newbuf[i] = '\0';
885       aim_send_im_direct(sess, conn, newbuf);
886       free(newbuf);
887     }
888   } else if (!strncmp(msg, "goodday", 7)) {
889     aim_send_im_direct(sess, conn, "Good day to you, too");
890   } else {
891     char newmsg[1024];
892     snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
893     aim_send_im_direct(sess, conn, newmsg);
894   }
895   return 1;
896 }
897
898 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
899 {
900   printf("faimtest: directim_disconnect\n");
901   return 1;
902 }
903
904 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
905 {
906   va_list ap;
907   char *sn;
908   
909   ap = va_start(ap, command);
910   sn = va_arg(ap, char *);
911   va_end(ap);
912
913   printf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
914   return 1;
915 }
916
917 int faimtest_authsvrready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
918 {
919   printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
920   sleep(10);
921   /* should just be able to tell it we're ready too... */
922   aim_auth_clientready(sess, command->conn);
923
924 #if 0
925   /*
926    * This is where you'd really begin changing your password.
927    *   However, this callback may get called for reasons other
928    *   than you wanting to change your password.  You should 
929    *   probably check that before actually doing it.
930    */
931   aim_auth_changepasswd(sess, command->conn, "PWD1", "PWD2");
932 #endif
933
934   return 1;
935 }
936
937 int faimtest_pwdchngdone(struct aim_session_t *sess, struct command_rx_struct *command, ...)
938 {
939   printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
940   return 1;
941 }
942
943 int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
944 {
945   struct aim_userinfo_s *userinfo;
946    
947   va_list ap;
948   va_start(ap, command);
949   userinfo = va_arg(ap, struct aim_userinfo_s *);
950   va_end(ap);
951
952   printf("\n%s is now online (class: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
953          userinfo->sn, userinfo->class,
954          (userinfo->class&AIM_CLASS_TRIAL)?" TRIAL":"",
955          (userinfo->class&AIM_CLASS_ADMINISTRATOR)?" ADMINISTRATOR":"",
956          (userinfo->class&AIM_CLASS_AOL)?" AOL":"",
957          (userinfo->class&AIM_CLASS_OSCAR_PAY)?" OSCAR_PAY":"",
958          (userinfo->class&AIM_CLASS_FREE)?" FREE":"",
959          (userinfo->class&AIM_CLASS_AWAY)?" AWAY":"",
960          (userinfo->class&AIM_CLASS_UNKNOWN40)?" UNKNOWN40":"",
961          (userinfo->class&AIM_CLASS_UNKNOWN80)?" UNKNOWN80":"",
962          userinfo->capabilities);
963   return 1;
964 }
965
966 int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
967 {
968   char *sn;
969   va_list ap;
970   
971   va_start(ap, command);
972   sn = va_arg(ap, char *);
973   va_end(ap);
974
975   printf("\n%s has left\n", sn);
976
977   return 1;
978 }
979
980 int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
981 {
982   static char *codes[] = {
983     "Unknown",
984     "Mandatory upgrade",
985     "Advisory upgrade",
986     "System bulletin",
987     "Top o' the world!"};
988   static int codeslen = 5;
989
990   char *msg;
991   unsigned short id;
992   va_list ap;
993   
994   va_start(ap, command);
995   id = va_arg(ap, unsigned short);
996   msg = va_arg(ap, char *);
997   va_end(ap);
998
999   printf("faimtest: motd: %s (%d / %s)\n", msg, id, 
1000          (id < codeslen)?codes[id]:"unknown");
1001
1002   return 1;
1003 }
1004
1005 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1006 {
1007   va_list ap;
1008   char *destsn;
1009   unsigned short reason;
1010
1011   va_start(ap, command);
1012   destsn = va_arg(ap, char *);
1013   reason = va_arg(ap, unsigned short);
1014   va_end(ap);
1015
1016   printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1017   
1018   return 1;
1019 }
1020
1021 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1022 {
1023   va_list ap;
1024   char *destsn;
1025   unsigned short reason;
1026
1027   va_start(ap, command);
1028   destsn = va_arg(ap, char *);
1029   reason = va_arg(ap, unsigned short);
1030   va_end(ap);
1031
1032   printf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1033   
1034   return 1;
1035 }
1036
1037 /* 
1038  * Handles callbacks for AIM_CB_MISSED_CALL.
1039  */
1040 int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1041 {
1042   static char *missedreasons[] = {
1043     "Unknown",
1044     "Message too large"};
1045   static int missedreasonslen = 2;
1046
1047   va_list ap;
1048   unsigned short chan, nummissed, reason;
1049   struct aim_userinfo_s *userinfo;
1050   
1051   va_start(ap, command);
1052   chan = va_arg(ap, unsigned short);
1053   userinfo = va_arg(ap, struct aim_userinfo_s *);
1054   nummissed = va_arg(ap, unsigned short);
1055   reason = va_arg(ap, unsigned short);
1056   va_end(ap);
1057
1058   printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1059   
1060   return 0;
1061 }
1062
1063 int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1064 {
1065   struct client_info_s info = {"faimtest (with SNAC login)", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x0000004b}; /* 4.1.2010 */
1066   char *key;
1067   va_list ap;
1068   
1069   va_start(ap, command);
1070   key = va_arg(ap, char *);
1071   va_end(ap);
1072
1073   aim_send_login(sess, command->conn, screenname, password, &info, key);
1074  
1075   return 1;
1076 }
1077
1078 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1079 {
1080   va_list ap;
1081   struct aim_userinfo_s *userinfo;
1082   int count = 0, i = 0;
1083   
1084   va_start(ap, command);
1085   count = va_arg(ap, int);
1086   userinfo = va_arg(ap, struct aim_userinfo_s *);
1087   va_end(ap);
1088
1089   printf("faimtest: chat: %s:  New occupants have joined:\n", (char *)command->conn->priv);
1090   while (i < count)
1091     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1092
1093   return 1;
1094 }
1095
1096 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1097 {
1098   va_list ap;
1099   struct aim_userinfo_s *userinfo;
1100   int count = 0, i = 0;
1101   
1102   va_start(ap, command);
1103   count = va_arg(ap, int);
1104   userinfo = va_arg(ap, struct aim_userinfo_s *);
1105   va_end(ap);
1106
1107   printf("faimtest: chat: %s:  Some occupants have left:\n", (char *)command->conn->priv);
1108   while (i < count)
1109     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1110
1111   return 1;
1112 }
1113
1114 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1115 {
1116   va_list ap;
1117   struct aim_userinfo_s *userinfo;
1118   struct aim_chat_roominfo *roominfo;
1119   char *roomname;
1120   int usercount,i;
1121   char *roomdesc;
1122   unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1123   unsigned long creationtime;
1124
1125   va_start(ap, command);
1126   roominfo = va_arg(ap, struct aim_chat_roominfo *);
1127   roomname = va_arg(ap, char *);
1128   usercount= va_arg(ap, int);
1129   userinfo = va_arg(ap, struct aim_userinfo_s *);
1130   roomdesc = va_arg(ap, char *);
1131   unknown_c9 = va_arg(ap, unsigned short);
1132   creationtime = va_arg(ap, unsigned long);
1133   maxmsglen = va_arg(ap, unsigned short);
1134   unknown_d2 = va_arg(ap, unsigned short);
1135   unknown_d5 = va_arg(ap, unsigned short);
1136   va_end(ap);
1137
1138   printf("faimtest: chat: %s:  info update:\n", (char *)command->conn->priv);
1139   printf("faimtest: chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", 
1140          (char *)command->conn->priv,
1141          roominfo->exchange,
1142          roominfo->name,
1143          roominfo->instance);
1144   printf("faimtest: chat: %s:  \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1145   printf("faimtest: chat: %s:  \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1146   printf("faimtest: chat: %s:  \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1147   
1148   i = 0;
1149   while (i < usercount)
1150     printf("faimtest: chat: %s:  \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1151
1152   printf("faimtest: chat: %s:  \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1153   printf("faimtest: chat: %s:  \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1154   printf("faimtest: chat: %s:  \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1155   printf("faimtest: chat: %s:  \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1156   printf("faimtest: chat: %s:  \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1157
1158   return 1;
1159 }
1160
1161 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1162 {
1163   va_list ap;
1164   struct aim_userinfo_s *userinfo;
1165   char *msg;
1166   char tmpbuf[1152];
1167  
1168   va_start(ap, command);
1169   userinfo = va_arg(ap, struct aim_userinfo_s *);       
1170   msg = va_arg(ap, char *);
1171   va_end(ap);
1172
1173   printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1174
1175   /*
1176    * Do an echo for testing purposes.  But not for ourselves ("oops!")
1177    */
1178   if (strcmp(userinfo->sn, sess->logininfo.screen_name) != 0)
1179     {
1180       sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1181       aim_chat_send_im(sess, command->conn, tmpbuf);
1182     }
1183
1184   return 1;
1185 }
1186
1187 int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1188 {
1189   u_short type;
1190   va_list ap;
1191
1192   ap = va_start(ap, command);
1193   type = va_arg(ap, u_short);
1194
1195   switch(type)
1196     {
1197     case 0x0002:
1198       {
1199         int maxrooms;
1200         struct aim_chat_exchangeinfo *exchanges;
1201         int exchangecount,i = 0;
1202         
1203         maxrooms = va_arg(ap, u_char);
1204         exchangecount = va_arg(ap, int);
1205         exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1206         va_end(ap);
1207
1208         printf("faimtest: chat info: Chat Rights:\n");
1209         printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1210         
1211         printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1212         while (i < exchangecount)
1213           {
1214             printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n", 
1215                    exchanges[i].number, 
1216                    exchanges[i].name,
1217                    exchanges[i].charset1,
1218                    exchanges[i].lang1);
1219             i++;
1220           }
1221         
1222       }
1223       break;
1224     default:
1225       va_end(ap);
1226       printf("faimtest: chatnav info: unknown type (%04x)\n", type);
1227     }
1228   return 1;
1229 }
1230
1231 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1232 {
1233   va_list ap;
1234   unsigned short code;
1235   char *msg = NULL;
1236
1237   ap = va_start(ap, command);
1238   code = va_arg(ap, unsigned short);
1239   msg = va_arg(ap, char *);
1240   va_end(ap);
1241
1242   printf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1243   aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1244
1245   return 1;
1246 }
1247
1248 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1249 {       
1250   printf("faimtest: connecting to an aimdebugd!\n");
1251
1252   /* convert the authorizer connection to a BOS connection */
1253   command->conn->type = AIM_CONN_TYPE_BOS;
1254
1255   aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1256
1257   /* tell the aimddebugd we're ready */
1258   aim_debugconn_sendconnect(sess, command->conn); 
1259
1260   /* go right into main loop (don't open a BOS connection, etc) */
1261   return 1;
1262 }
1263
1264 /*
1265  * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
1266  */
1267 int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1268 {
1269   va_list ap;
1270   unsigned short type;
1271   char *sn = NULL;
1272
1273   ap = va_start(ap, command);
1274   type = va_arg(ap, unsigned short);
1275   sn = va_arg(ap, char *);
1276   va_end(ap);
1277
1278   printf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1279
1280   return 1;
1281 }
1282
1283 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1284 {
1285   va_list ap;
1286   unsigned long newrate;
1287   
1288   va_start(ap, command); 
1289   newrate = va_arg(ap, unsigned long);
1290   va_end(ap);
1291
1292   printf("faimtest: ratechange: %lu\n", newrate);
1293
1294   return (1);
1295 }
1296
1297 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1298 {
1299   va_list ap;
1300   char *sn;
1301
1302   va_start(ap, command);
1303   sn = va_arg(ap, char *);
1304   va_end(ap);
1305
1306   printf("faimtest: warning from: %s\n", sn);
1307
1308   return 1;
1309 }
This page took 0.14864 seconds and 3 git commands to generate.