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