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