]> andersk Git - libfaim.git/blob - utils/faimtest/faimtest.c
- Thu Sep 14 00:54:48 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_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_FLAG_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 static void printuserflags(unsigned short flags)
510 {
511   if (flags & AIM_FLAG_UNCONFIRMED)
512     printf("UNCONFIRMED ");
513   if (flags & AIM_FLAG_ADMINISTRATOR)
514     printf("ADMINISTRATOR ");
515   if (flags & AIM_FLAG_AOL)
516     printf("AOL ");
517   if (flags & AIM_FLAG_OSCAR_PAY)
518       printf("OSCAR_PAY ");
519   if (flags & AIM_FLAG_FREE)
520     printf("FREE ");
521   if (flags & AIM_FLAG_AWAY)
522     printf("AWAY ");
523   if (flags & AIM_FLAG_UNKNOWN40)
524     printf("ICQ? ");
525   if (flags & AIM_FLAG_UNKNOWN80)
526     printf("UNKNOWN80 ");
527   return;
528 }
529
530 int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
531 {
532   struct aim_userinfo_s *userinfo;
533   char *prof_encoding = NULL;
534   char *prof = NULL;
535   unsigned short inforeq = 0;
536
537   va_list ap;
538   va_start(ap, command);
539   userinfo = va_arg(ap, struct aim_userinfo_s *);
540   prof_encoding = va_arg(ap, char *);
541   prof = va_arg(ap, char *);
542   inforeq = va_arg(ap, unsigned short);
543   va_end(ap);
544   
545   printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
546   printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
547   printf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
548   printuserflags(userinfo->flags);
549   printf("\n");
550   
551   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
552   printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
553   printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
554   
555   if (inforeq == AIM_GETINFO_GENERALINFO) {
556     printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
557     printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
558   } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
559     printf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
560     printf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
561   } else 
562     printf("faimtest: userinfo: unknown info request\n");
563   
564   return 1;
565 }
566
567 /*
568  * The user-level Incoming ICBM callback.
569  *
570  * Arguments:
571  *  struct command_rx_struct *  command     if you feel like doing it yourself
572  *  char *                      srcsn       the source name
573  *  char *                      msg         message
574  *  int                         warnlevel   warning/evil level
575  *  int                         flags       flags
576  *  ulong                       membersince time_t of date of signup
577  *  ulong                       onsince     time_t of date of singon
578  *  int                         idletime    min (sec?) idle
579  *  u_int                       icbmflags   sets AIM_IMFLAGS_{AWAY,ACK}
580  *
581  */
582 int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
583 {
584   int channel;
585   va_list ap;
586
587   va_start(ap, command);
588   channel = va_arg(ap, int);
589
590   /*
591    * Channel 1: Standard Message
592    */
593   if (channel == 1) {
594     struct aim_userinfo_s *userinfo;
595     char *msg = NULL;
596     u_int icbmflags = 0;
597     char *tmpstr = NULL;
598     u_short flag1, flag2;
599     
600     userinfo = va_arg(ap, struct aim_userinfo_s *);
601     msg = va_arg(ap, char *);
602     icbmflags = va_arg(ap, u_int);
603     flag1 = va_arg(ap, u_short);
604     flag2 = va_arg(ap, u_short);
605     va_end(ap);
606     
607     printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
608     printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
609     printf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
610     printuserflags(userinfo->flags);
611     printf("\n");
612
613     printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
614     printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
615     printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
616     printf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
617     
618     printf("faimtest: icbm: icbmflags = ");
619     if (icbmflags & AIM_IMFLAGS_AWAY)
620       printf("away ");
621     if (icbmflags & AIM_IMFLAGS_ACK)
622       printf("ackrequest ");
623     printf("\n");
624     
625     printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
626     
627     printf("faimtest: icbm: message: %s\n", msg);
628     
629     if (msg) {
630       int i = 0;
631
632       while (msg[i] == '<') {
633         if (msg[i] == '<') {
634           while (msg[i] != '>')
635             i++;
636           i++;
637         }
638       }
639       tmpstr = msg+i;
640
641       printf("tmpstr = %s\n", tmpstr);
642       
643       if ( (strlen(tmpstr) >= 10) &&
644            (!strncmp(tmpstr, "disconnect", 10)) ) {
645           aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
646           aim_logoff(sess);
647       } else if (strstr(tmpstr, "goodday")) {
648         printf("faimtest: icbm: sending response\n");
649         aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
650       } else if (strstr(tmpstr, "warnme")) {
651         printf("faimtest: icbm: sending non-anon warning\n");
652         aim_send_warning(sess, command->conn, userinfo->sn, 0);
653       } else if (strstr(tmpstr, "anonwarn")) {
654         printf("faimtest: icbm: sending anon warning\n");
655         aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
656       } else if (!strncmp(tmpstr, "open chatnav", 12)) {
657         aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
658         //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
659       } else if (!strncmp(tmpstr, "create", 6)) {
660         aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
661       } else if (!strncmp(tmpstr, "close chatnav", 13)) {
662         struct aim_conn_t *chatnavconn;
663         chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
664         aim_conn_kill(sess, &chatnavconn);
665       } else if (!strncmp(tmpstr, "join", 4)) {
666           aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
667       } else if (!strncmp(tmpstr, "leave", 5))
668             aim_chat_leaveroom(sess, "worlddomination");
669       else if (!strncmp(tmpstr, "getinfo", 7)) {
670         aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
671         aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
672       } else if (!strncmp(tmpstr, "open directim", 13)) {
673         struct aim_conn_t *newconn;
674         newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
675         //aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, faimtest_directim_initiate, 0);
676       } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
677         aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7900");
678       } else if (!strncmp(tmpstr, "sendmsg", 7)) {
679         int i;
680         i = atoi(tmpstr+8);
681         if (i < 10000) {
682           char *newbuf;
683           int z;
684
685           newbuf = malloc(i+1);
686           for (z = 0; z < i; z++) {
687             newbuf[z] = (z % 10)+0x30;
688           }
689           newbuf[i] = '\0';
690           aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf);
691           free(newbuf);
692         }
693       } else {
694         printf("unknown command.\n");
695         aim_add_buddy(sess, command->conn, userinfo->sn);
696       }
697       
698     }
699   }
700   /*
701    * Channel 2: Rendevous Request
702    */
703   else if (channel == 2) {
704     struct aim_userinfo_s *userinfo;
705     unsigned short reqclass;
706     
707     reqclass = va_arg(ap, unsigned short);
708     switch (reqclass) {
709     case AIM_CAPS_VOICE: {
710       userinfo = va_arg(ap, struct aim_userinfo_s *);
711       va_end(ap);
712       
713       printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
714       printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
715       printf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
716       printuserflags(userinfo->flags);
717       printf("\n");
718
719       /* we dont get membersince on chat invites! */
720       printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
721       printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
722       
723       break;
724     }
725     case AIM_CAPS_GETFILE: {
726       printf("faimtset: get file!\n");
727       break;
728     }
729     case AIM_CAPS_SENDFILE: {
730       printf("faimtest: send file!\n");
731       break;
732     }
733     case AIM_CAPS_CHAT: {
734       char *msg,*encoding,*lang;
735       struct aim_chat_roominfo *roominfo;
736       
737       userinfo = va_arg(ap, struct aim_userinfo_s *);
738       roominfo = va_arg(ap, struct aim_chat_roominfo *);
739       msg = va_arg(ap, char *);
740       encoding = va_arg(ap, char *);
741       lang = va_arg(ap, char *);
742       va_end(ap);
743       
744       printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
745       printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
746       printf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
747       printuserflags(userinfo->flags);
748       printf("\n");
749
750       /* we dont get membersince on chat invites! */
751       printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
752       printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
753       
754       printf("faimtest: chat invitation: message = %s\n", msg);
755       printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
756       printf("faimtest: chat invitation: encoding = %s\n", encoding);
757       printf("faimtest: chat invitation: language = %s\n", lang);
758       printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
759       printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
760       printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
761       /*
762        * Automatically join room...
763        */ 
764       aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
765       break;
766     }   
767     case AIM_CAPS_IMIMAGE: {
768       struct aim_directim_priv *priv;
769       struct aim_conn_t *newconn;
770
771       printf("faimtest: icbm: rendezvous imimage\n");
772      
773       userinfo = va_arg(ap, struct aim_userinfo_s *);
774       priv = va_arg(ap, struct aim_directim_priv *);
775       va_end(ap);
776
777       printf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
778       
779       if (!(newconn = aim_directim_connect(sess, command->conn, priv))) {
780         printf("faimtest: icbm: imimage: could not connect\n");
781         break;
782       }
783       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
784       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
785       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
786
787       aim_send_im_direct(sess, newconn, "goodday");
788
789       printf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
790
791       break;
792     }
793     default:
794       printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
795     } /* switch */
796   } else
797     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
798   printf("faimtest: icbm: done with ICBM handling\n");
799
800   return 1;
801 }
802
803 #if 0
804 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
805 {
806   va_list ap;
807   struct aim_directim_priv *priv;
808   struct aim_conn_t *newconn;
809
810   ap = va_start(ap, command);
811   newconn = va_arg(ap, struct aim_conn_t *);
812   va_end(ap);
813
814   priv = (struct aim_directim_priv *)newconn->priv;
815
816   printf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
817   
818   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
819   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
820   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
821
822   aim_send_im_direct(sess, newconn, "goodday");
823
824   printf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
825
826   return 1;
827 }
828 #endif
829
830 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
831 {
832   va_list ap;
833   struct aim_directim_priv *priv;
834   
835   ap = va_start(ap, command);
836   priv = va_arg(ap, struct aim_directim_priv *);
837
838   va_end(ap);
839   
840   printf("faimtest: directim_connect\n");
841
842   return 1;
843 }
844
845 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
846 {
847   va_list ap;
848   char *sn = NULL, *msg = NULL;
849   struct aim_conn_t *conn;
850
851   ap = va_start(ap, command);
852   conn = va_arg(ap, struct aim_conn_t *);
853   sn = va_arg(ap, char *);
854   msg = va_arg(ap, char *);
855   va_end(ap);
856
857   printf("faimtest: Directim from %s: %s\n", sn, msg);
858   if (!strncmp(msg, "sendmsg", 7)) {
859     int i;
860     i = atoi(msg+8);
861     if (i < 10000) {
862       char *newbuf;
863       int z;
864       
865       newbuf = malloc(i+1);
866       for (z = 0; z < i; z++) {
867         newbuf[z] = (z % 10)+0x30;
868       }
869       newbuf[i] = '\0';
870       aim_send_im_direct(sess, conn, newbuf);
871       free(newbuf);
872     }
873   } else if (!strncmp(msg, "goodday", 7)) {
874     aim_send_im_direct(sess, conn, "Good day to you, too");
875   } else {
876     char newmsg[1024];
877     snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
878     aim_send_im_direct(sess, conn, newmsg);
879   }
880   return 1;
881 }
882
883 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
884 {
885   printf("faimtest: directim_disconnect\n");
886   return 1;
887 }
888
889 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
890 {
891   va_list ap;
892   char *sn;
893   
894   ap = va_start(ap, command);
895   sn = va_arg(ap, char *);
896   va_end(ap);
897
898   printf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
899   return 1;
900 }
901
902 int faimtest_authsvrready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
903 {
904   printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
905   sleep(10);
906   /* should just be able to tell it we're ready too... */
907   aim_auth_clientready(sess, command->conn);
908
909 #if 0
910   /*
911    * This is where you'd really begin changing your password.
912    *   However, this callback may get called for reasons other
913    *   than you wanting to change your password.  You should 
914    *   probably check that before actually doing it.
915    */
916   aim_auth_changepasswd(sess, command->conn, "PWD1", "PWD2");
917 #endif
918
919   return 1;
920 }
921
922 int faimtest_pwdchngdone(struct aim_session_t *sess, struct command_rx_struct *command, ...)
923 {
924   printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
925   return 1;
926 }
927
928 int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
929 {
930   struct aim_userinfo_s *userinfo;
931    
932   va_list ap;
933   va_start(ap, command);
934   userinfo = va_arg(ap, struct aim_userinfo_s *);
935   va_end(ap);
936
937   printf("\n%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
938          userinfo->sn, userinfo->flags,
939          (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
940          (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
941          (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
942          (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
943          (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
944          (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
945          (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
946          (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
947          userinfo->capabilities);
948   return 1;
949 }
950
951 int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
952 {
953   char *sn;
954   va_list ap;
955   
956   va_start(ap, command);
957   sn = va_arg(ap, char *);
958   va_end(ap);
959
960   printf("\n%s has left\n", sn);
961
962   return 1;
963 }
964
965 int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
966 {
967   static char *codes[] = {
968     "Unknown",
969     "Mandatory upgrade",
970     "Advisory upgrade",
971     "System bulletin",
972     "Top o' the world!"};
973   static int codeslen = 5;
974
975   char *msg;
976   unsigned short id;
977   va_list ap;
978   
979   va_start(ap, command);
980   id = va_arg(ap, unsigned short);
981   msg = va_arg(ap, char *);
982   va_end(ap);
983
984   printf("faimtest: motd: %s (%d / %s)\n", msg, id, 
985          (id < codeslen)?codes[id]:"unknown");
986
987   return 1;
988 }
989
990 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
991 {
992   va_list ap;
993   char *destsn;
994   unsigned short reason;
995
996   va_start(ap, command);
997   destsn = va_arg(ap, char *);
998   reason = va_arg(ap, unsigned short);
999   va_end(ap);
1000
1001   printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1002   
1003   return 1;
1004 }
1005
1006 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1007 {
1008   va_list ap;
1009   char *destsn;
1010   unsigned short reason;
1011
1012   va_start(ap, command);
1013   destsn = va_arg(ap, char *);
1014   reason = va_arg(ap, unsigned short);
1015   va_end(ap);
1016
1017   printf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1018   
1019   return 1;
1020 }
1021
1022 /* 
1023  * Handles callbacks for AIM_CB_MISSED_CALL.
1024  */
1025 int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1026 {
1027   static char *missedreasons[] = {
1028     "Unknown",
1029     "Message too large"};
1030   static int missedreasonslen = 2;
1031
1032   va_list ap;
1033   unsigned short chan, nummissed, reason;
1034   struct aim_userinfo_s *userinfo;
1035   
1036   va_start(ap, command);
1037   chan = va_arg(ap, unsigned short);
1038   userinfo = va_arg(ap, struct aim_userinfo_s *);
1039   nummissed = va_arg(ap, unsigned short);
1040   reason = va_arg(ap, unsigned short);
1041   va_end(ap);
1042
1043   printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1044   
1045   return 0;
1046 }
1047
1048 int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1049 {
1050   struct client_info_s info = {"faimtest (with SNAC login)", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x0000004b}; /* 4.1.2010 */
1051   char *key;
1052   va_list ap;
1053   
1054   va_start(ap, command);
1055   key = va_arg(ap, char *);
1056   va_end(ap);
1057
1058   aim_send_login(sess, command->conn, screenname, password, &info, key);
1059  
1060   return 1;
1061 }
1062
1063 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1064 {
1065   va_list ap;
1066   struct aim_userinfo_s *userinfo;
1067   int count = 0, i = 0;
1068   
1069   va_start(ap, command);
1070   count = va_arg(ap, int);
1071   userinfo = va_arg(ap, struct aim_userinfo_s *);
1072   va_end(ap);
1073
1074   printf("faimtest: chat: %s:  New occupants have joined:\n", (char *)command->conn->priv);
1075   while (i < count)
1076     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1077
1078   return 1;
1079 }
1080
1081 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1082 {
1083   va_list ap;
1084   struct aim_userinfo_s *userinfo;
1085   int count = 0, i = 0;
1086   
1087   va_start(ap, command);
1088   count = va_arg(ap, int);
1089   userinfo = va_arg(ap, struct aim_userinfo_s *);
1090   va_end(ap);
1091
1092   printf("faimtest: chat: %s:  Some occupants have left:\n", (char *)command->conn->priv);
1093   while (i < count)
1094     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1095
1096   return 1;
1097 }
1098
1099 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1100 {
1101   va_list ap;
1102   struct aim_userinfo_s *userinfo;
1103   struct aim_chat_roominfo *roominfo;
1104   char *roomname;
1105   int usercount,i;
1106   char *roomdesc;
1107   unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1108   unsigned long creationtime;
1109
1110   va_start(ap, command);
1111   roominfo = va_arg(ap, struct aim_chat_roominfo *);
1112   roomname = va_arg(ap, char *);
1113   usercount= va_arg(ap, int);
1114   userinfo = va_arg(ap, struct aim_userinfo_s *);
1115   roomdesc = va_arg(ap, char *);
1116   unknown_c9 = va_arg(ap, unsigned short);
1117   creationtime = va_arg(ap, unsigned long);
1118   maxmsglen = va_arg(ap, unsigned short);
1119   unknown_d2 = va_arg(ap, unsigned short);
1120   unknown_d5 = va_arg(ap, unsigned short);
1121   va_end(ap);
1122
1123   printf("faimtest: chat: %s:  info update:\n", (char *)command->conn->priv);
1124   printf("faimtest: chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", 
1125          (char *)command->conn->priv,
1126          roominfo->exchange,
1127          roominfo->name,
1128          roominfo->instance);
1129   printf("faimtest: chat: %s:  \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1130   printf("faimtest: chat: %s:  \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1131   printf("faimtest: chat: %s:  \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1132   
1133   i = 0;
1134   while (i < usercount)
1135     printf("faimtest: chat: %s:  \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1136
1137   printf("faimtest: chat: %s:  \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1138   printf("faimtest: chat: %s:  \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1139   printf("faimtest: chat: %s:  \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1140   printf("faimtest: chat: %s:  \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1141   printf("faimtest: chat: %s:  \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1142
1143   return 1;
1144 }
1145
1146 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1147 {
1148   va_list ap;
1149   struct aim_userinfo_s *userinfo;
1150   char *msg;
1151   char tmpbuf[1152];
1152  
1153   va_start(ap, command);
1154   userinfo = va_arg(ap, struct aim_userinfo_s *);       
1155   msg = va_arg(ap, char *);
1156   va_end(ap);
1157
1158   printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1159
1160   /*
1161    * Do an echo for testing purposes.  But not for ourselves ("oops!")
1162    */
1163   if (strcmp(userinfo->sn, sess->logininfo.screen_name) != 0)
1164     {
1165       sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1166       aim_chat_send_im(sess, command->conn, tmpbuf);
1167     }
1168
1169   return 1;
1170 }
1171
1172 int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1173 {
1174   u_short type;
1175   va_list ap;
1176
1177   ap = va_start(ap, command);
1178   type = va_arg(ap, u_short);
1179
1180   switch(type) {
1181   case 0x0002: {
1182     int maxrooms;
1183     struct aim_chat_exchangeinfo *exchanges;
1184     int exchangecount,i = 0;
1185     
1186     maxrooms = va_arg(ap, u_char);
1187     exchangecount = va_arg(ap, int);
1188     exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1189     va_end(ap);
1190     
1191     printf("faimtest: chat info: Chat Rights:\n");
1192     printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1193     
1194     printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1195     while (i < exchangecount) {
1196       printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n", 
1197              exchanges[i].number,       
1198              exchanges[i].name,
1199              exchanges[i].charset1,
1200              exchanges[i].lang1);
1201       i++;
1202     }
1203     
1204   }
1205   break;
1206   case 0x0008: {
1207     char *fqcn, *name, *ck;
1208     unsigned short instance, flags, maxmsglen, maxoccupancy, unknown;
1209     unsigned char createperms;
1210     unsigned long createtime;
1211
1212     fqcn = va_arg(ap, char *);
1213     instance = va_arg(ap, unsigned short);
1214     flags = va_arg(ap, unsigned short);
1215     createtime = va_arg(ap, unsigned long);
1216     maxmsglen = va_arg(ap, unsigned short);
1217     maxoccupancy = va_arg(ap, unsigned short);
1218     createperms = va_arg(ap, unsigned char);
1219     unknown = va_arg(ap, unsigned short);
1220     name = va_arg(ap, char *);
1221     ck = va_arg(ap, char *);
1222     va_end(ap);
1223
1224     printf("faimtest: recieved room create reply for %s\n", fqcn);
1225   }
1226   break;
1227   default:
1228     va_end(ap);
1229     printf("faimtest: chatnav info: unknown type (%04x)\n", type);
1230   }
1231   return 1;
1232 }
1233
1234 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1235 {
1236   va_list ap;
1237   unsigned short code;
1238   char *msg = NULL;
1239
1240   ap = va_start(ap, command);
1241   code = va_arg(ap, unsigned short);
1242   msg = va_arg(ap, char *);
1243   va_end(ap);
1244
1245   printf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1246   aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1247
1248   return 1;
1249 }
1250
1251 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1252 {       
1253   printf("faimtest: connecting to an aimdebugd!\n");
1254
1255   /* convert the authorizer connection to a BOS connection */
1256   command->conn->type = AIM_CONN_TYPE_BOS;
1257
1258   aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1259
1260   /* tell the aimddebugd we're ready */
1261   aim_debugconn_sendconnect(sess, command->conn); 
1262
1263   /* go right into main loop (don't open a BOS connection, etc) */
1264   return 1;
1265 }
1266
1267 /*
1268  * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
1269  */
1270 int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1271 {
1272   va_list ap;
1273   unsigned short type;
1274   char *sn = NULL;
1275
1276   ap = va_start(ap, command);
1277   type = va_arg(ap, unsigned short);
1278   sn = va_arg(ap, char *);
1279   va_end(ap);
1280
1281   printf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1282
1283   return 1;
1284 }
1285
1286 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1287 {
1288   va_list ap;
1289   unsigned long newrate;
1290   
1291   va_start(ap, command); 
1292   newrate = va_arg(ap, unsigned long);
1293   va_end(ap);
1294
1295   printf("faimtest: ratechange: %lu\n", newrate);
1296
1297   return (1);
1298 }
1299
1300 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1301 {
1302   va_list ap;
1303   char *sn;
1304
1305   va_start(ap, command);
1306   sn = va_arg(ap, char *);
1307   va_end(ap);
1308
1309   printf("faimtest: warning from: %s\n", sn);
1310
1311   return 1;
1312 }
This page took 0.134044 seconds and 5 git commands to generate.