]> andersk Git - libfaim.git/blob - utils/faimtest/faimtest.c
- Mon Dec 4 23:46:35 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         int exchange;
513         struct aim_conn_t *tstconn = NULL;
514
515         roomname = va_arg(ap, char *);
516         exchange = va_arg(ap, int);
517
518         tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
519         if ( (tstconn==NULL) || (tstconn->status & AIM_CONN_STATUS_RESOLVERR))
520           {
521             fprintf(stderr, "faimtest: unable to connect to chat server\n");
522             if (tstconn) aim_conn_kill(sess, &tstconn);
523             return 1;
524           }             
525         printf("faimtest: chat: connected to %s on exchange %d\n", roomname, exchange);
526
527         /*
528          * We must do this to attach the stored name to the connection!
529          */
530         aim_chat_attachname(tstconn, roomname);
531
532         aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
533         aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
534         aim_auth_sendcookie(sess, tstconn, cookie);
535       }
536       break;
537     default:
538       printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
539       /* dunno */
540     }
541
542   va_end(ap);
543
544   return 1;
545 }
546
547 int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
548 {
549   struct aim_conn_t *bosconn = NULL;
550   
551
552   printf("Screen name: %s\n", sess->logininfo.screen_name);
553
554   /*
555    * Check for error.
556    */
557   if (sess->logininfo.errorcode)
558     {
559       printf("Login Error Code 0x%04x\n", sess->logininfo.errorcode);
560       printf("Error URL: %s\n", sess->logininfo.errorurl);
561       aim_conn_kill(sess, &command->conn);
562       exit(0); /* XXX: should return in order to let the above things get free()'d. */
563     }
564
565   printf("Reg status: %2d\n", sess->logininfo.regstatus);
566   printf("Email: %s\n", sess->logininfo.email);
567   printf("BOS IP: %s\n", sess->logininfo.BOSIP);
568
569   printf("Closing auth connection...\n");
570   aim_conn_kill(sess, &command->conn);
571   bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP);
572   if (bosconn == NULL) {
573     fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
574   } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
575     fprintf(stderr, "faimtest: could not connect to BOS\n");
576     aim_conn_kill(sess, &bosconn);
577   } else {
578     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
579     aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, faimtest_bosrights, 0);
580     aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, faimtest_rateresp, 0); /* rate info */
581     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
582     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
583     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
584     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
585     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, faimtest_reportinterval, 0);
586     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, faimtest_parse_buddyrights, 0);
587     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
588     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
589     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
590     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_locerr, 0);
591     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
592     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_ratechange, 0);
593     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, faimtest_parse_evilnotify, 0);
594     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_msgerr, 0);
595     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
596     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, faimtest_parse_msgack, 0);
597
598     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
599     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
600     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, faimtest_parse_motd, 0);
601     
602     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, faimtest_parse_connerr, 0);
603     
604     aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie);
605   }
606   return 1;
607 }
608
609 static void printuserflags(unsigned short flags)
610 {
611   if (flags & AIM_FLAG_UNCONFIRMED)
612     printf("UNCONFIRMED ");
613   if (flags & AIM_FLAG_ADMINISTRATOR)
614     printf("ADMINISTRATOR ");
615   if (flags & AIM_FLAG_AOL)
616     printf("AOL ");
617   if (flags & AIM_FLAG_OSCAR_PAY)
618       printf("OSCAR_PAY ");
619   if (flags & AIM_FLAG_FREE)
620     printf("FREE ");
621   if (flags & AIM_FLAG_AWAY)
622     printf("AWAY ");
623   if (flags & AIM_FLAG_UNKNOWN40)
624     printf("ICQ? ");
625   if (flags & AIM_FLAG_UNKNOWN80)
626     printf("UNKNOWN80 ");
627   return;
628 }
629
630 int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct *command, ...)
631 {
632   struct aim_userinfo_s *userinfo;
633   char *prof_encoding = NULL;
634   char *prof = NULL;
635   unsigned short inforeq = 0;
636
637   va_list ap;
638   va_start(ap, command);
639   userinfo = va_arg(ap, struct aim_userinfo_s *);
640   prof_encoding = va_arg(ap, char *);
641   prof = va_arg(ap, char *);
642   inforeq = va_arg(ap, int);
643   va_end(ap);
644   
645   printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
646   printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
647   printf("faimtest: userinfo: flags: 0x%04x = ", userinfo->flags);
648   printuserflags(userinfo->flags);
649   printf("\n");
650   
651   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
652   printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
653   printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
654   
655   if (inforeq == AIM_GETINFO_GENERALINFO) {
656     printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
657     printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
658   } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
659     printf("faimtest: userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
660     printf("faimtest: userinfo: awaymsg: %s\n", prof ? prof : "[none]");
661   } else 
662     printf("faimtest: userinfo: unknown info request\n");
663   
664   return 1;
665 }
666
667 /*
668  * The user-level Incoming ICBM callback.
669  *
670  * Arguments:
671  *  struct command_rx_struct *  command     if you feel like doing it yourself
672  *  char *                      srcsn       the source name
673  *  char *                      msg         message
674  *  int                         warnlevel   warning/evil level
675  *  int                         flags       flags
676  *  ulong                       membersince time_t of date of signup
677  *  ulong                       onsince     time_t of date of singon
678  *  int                         idletime    min (sec?) idle
679  *  u_int                       icbmflags   sets AIM_IMFLAGS_{AWAY,ACK}
680  *
681  */
682 int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...)
683 {
684   int channel;
685   va_list ap;
686
687   va_start(ap, command);
688   channel = va_arg(ap, int);
689
690   /*
691    * Channel 1: Standard Message
692    */
693   if (channel == 1) {
694     struct aim_userinfo_s *userinfo;
695     char *msg = NULL;
696     u_int icbmflags = 0;
697     char *tmpstr = NULL;
698     unsigned short flag1, flag2;
699     
700     userinfo = va_arg(ap, struct aim_userinfo_s *);
701     msg = va_arg(ap, char *);
702     icbmflags = va_arg(ap, u_int);
703     flag1 = va_arg(ap, int);
704     flag2 = va_arg(ap, int);
705     va_end(ap);
706     
707     printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
708     printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
709     printf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
710     printuserflags(userinfo->flags);
711     printf("\n");
712
713     printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
714     printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
715     printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
716     printf("faimtest: icbm: capabilities = 0x%04x\n", userinfo->capabilities);
717     
718     printf("faimtest: icbm: icbmflags = ");
719     if (icbmflags & AIM_IMFLAGS_AWAY)
720       printf("away ");
721     if (icbmflags & AIM_IMFLAGS_ACK)
722       printf("ackrequest ");
723     printf("\n");
724     
725     printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
726     
727     printf("faimtest: icbm: message: %s\n", msg);
728     
729     if (msg) {
730       int i = 0;
731
732       while (msg[i] == '<') {
733         if (msg[i] == '<') {
734           while (msg[i] != '>')
735             i++;
736           i++;
737         }
738       }
739       tmpstr = msg+i;
740
741       printf("tmpstr = %s\n", tmpstr);
742       
743       if ( (strlen(tmpstr) >= 10) &&
744            (!strncmp(tmpstr, "disconnect", 10)) ) {
745           aim_send_im(sess, command->conn, "midendian", 0, "ta ta...");
746           aim_logoff(sess);
747       } else if (strstr(tmpstr, "goodday")) {
748         printf("faimtest: icbm: sending response\n");
749         aim_send_im(sess, command->conn, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too.");
750       } else if (strstr(tmpstr, "warnme")) {
751         printf("faimtest: icbm: sending non-anon warning\n");
752         aim_send_warning(sess, command->conn, userinfo->sn, 0);
753       } else if (strstr(tmpstr, "anonwarn")) {
754         printf("faimtest: icbm: sending anon warning\n");
755         aim_send_warning(sess, command->conn, userinfo->sn, AIM_WARN_ANON);
756       } else if (strstr(tmpstr, "setdirectoryinfo")) {
757         printf("faimtest: icbm: sending backwards profile data\n");
758         aim_setdirectoryinfo(sess, command->conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
759       } else if (strstr(tmpstr, "setinterests")) {
760         printf("faimtest: icbm: setting fun interests\n");
761         aim_setuserinterests(sess, command->conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
762       } else if (!strncmp(tmpstr, "open chatnav", 12)) {
763         aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
764         //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
765       } else if (!strncmp(tmpstr, "create", 6)) {
766         aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
767       } else if (!strncmp(tmpstr, "close chatnav", 13)) {
768         struct aim_conn_t *chatnavconn;
769         chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
770         aim_conn_kill(sess, &chatnavconn);
771       } else if (!strncmp(tmpstr, "join", 4)) {
772           aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
773       } else if (!strncmp(tmpstr, "leave", 5))
774             aim_chat_leaveroom(sess, "worlddomination");
775       else if (!strncmp(tmpstr, "getinfo", 7)) {
776         aim_getinfo(sess, command->conn, "75784102", AIM_GETINFO_GENERALINFO);
777         aim_getinfo(sess, command->conn, "15853637", AIM_GETINFO_AWAYMESSAGE);
778       } else if (!strncmp(tmpstr, "open directim", 13)) {
779         struct aim_conn_t *newconn;
780         newconn = aim_directim_initiate(sess, command->conn, NULL, userinfo->sn);
781       } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
782         aim_send_im(sess, command->conn, "vaxherder", 0, "sendmsg 7900");
783       } else if (!strncmp(tmpstr, "sendmsg", 7)) {
784         int i;
785         i = atoi(tmpstr+8);
786         if (i < 10000) {
787           char *newbuf;
788           int z;
789
790           newbuf = malloc(i+1);
791           for (z = 0; z < i; z++) {
792             newbuf[z] = (z % 10)+0x30;
793           }
794           newbuf[i] = '\0';
795           aim_send_im(sess, command->conn, userinfo->sn, 0, newbuf);
796           free(newbuf);
797         }
798       } else {
799         printf("unknown command.\n");
800         aim_add_buddy(sess, command->conn, userinfo->sn);
801       }
802       
803     }
804   }
805   /*
806    * Channel 2: Rendevous Request
807    */
808   else if (channel == 2) {
809     struct aim_userinfo_s *userinfo;
810     unsigned short reqclass;
811     
812     reqclass = va_arg(ap, int);
813     switch (reqclass) {
814     case AIM_CAPS_VOICE: {
815       userinfo = va_arg(ap, struct aim_userinfo_s *);
816       va_end(ap);
817       
818       printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
819       printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
820       printf("faimtest: voice invitation: \tclass = 0x%04x = ", userinfo->flags);
821       printuserflags(userinfo->flags);
822       printf("\n");
823
824       /* we dont get membersince on chat invites! */
825       printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
826       printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
827       
828       break;
829     }
830     case AIM_CAPS_GETFILE: {
831 #ifdef FILESUPPORT
832       char *ip, *cookie;
833       struct aim_conn_t *newconn;
834
835       userinfo = va_arg(ap, struct aim_userinfo_s *);
836       ip = va_arg(ap, char *);
837       cookie = va_arg(ap, char *);
838       va_end(ap);
839       
840       printf("faimtest: get file request from %s (at %s)\n", userinfo->sn, ip);
841
842       sleep(1);
843
844       if( (newconn = aim_accepttransfer(sess, command->conn, userinfo->sn, cookie, ip, sess->oft.listing, reqclass)) == NULL ) {
845         printf("faimtest: getfile: requestconn: apparent error in accepttransfer\n");
846         break;
847       }
848       
849       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ,  faimtest_getfile_filereq, 0);
850       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, faimtest_getfile_filesend, 0);
851       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, faimtest_getfile_complete, 0);      
852       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, faimtest_getfile_disconnect, 0);      
853
854       printf("faimtest: getfile connect succeeded, handlers added.\n");
855
856       break;
857 #endif
858     }
859     case AIM_CAPS_SENDFILE: {
860       printf("faimtest: send file!\n");
861       break;
862     }
863     case AIM_CAPS_CHAT: {
864       char *msg,*encoding,*lang;
865       struct aim_chat_roominfo *roominfo;
866       
867       userinfo = va_arg(ap, struct aim_userinfo_s *);
868       roominfo = va_arg(ap, struct aim_chat_roominfo *);
869       msg = va_arg(ap, char *);
870       encoding = va_arg(ap, char *);
871       lang = va_arg(ap, char *);
872       va_end(ap);
873       
874       printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
875       printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
876       printf("faimtest: chat invitation: \tclass = 0x%04x = ", userinfo->flags);
877       printuserflags(userinfo->flags);
878       printf("\n");
879
880       /* we dont get membersince on chat invites! */
881       printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
882       printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
883       
884       printf("faimtest: chat invitation: message = %s\n", msg);
885       printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
886       printf("faimtest: chat invitation: encoding = %s\n", encoding);
887       printf("faimtest: chat invitation: language = %s\n", lang);
888       printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
889       printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
890       printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
891       /*
892        * Automatically join room...
893        */ 
894       aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
895       break;
896     }   
897     case AIM_CAPS_IMIMAGE: {
898       struct aim_directim_priv *priv;
899       struct aim_conn_t *newconn;
900
901       printf("faimtest: icbm: rendezvous imimage\n");
902      
903       userinfo = va_arg(ap, struct aim_userinfo_s *);
904       priv = va_arg(ap, struct aim_directim_priv *);
905       va_end(ap);
906
907       printf("faimtest: OFT: DirectIM: request from %s (%s)\n", userinfo->sn, priv->ip);
908       
909       if (!(newconn = aim_directim_connect(sess, command->conn, priv))) {
910         printf("faimtest: icbm: imimage: could not connect\n");
911         break;
912       }
913       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
914       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
915       aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
916
917       printf("faimtest: OFT: DirectIM: connected to %s\n", userinfo->sn);
918
919       aim_send_im_direct(sess, newconn, "goodday");
920
921       break;
922     }
923     default:
924       printf("faimtest: icbm: unknown reqclass (%d)\n", reqclass);
925     } /* switch */
926   } else
927     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
928   printf("faimtest: icbm: done with ICBM handling\n");
929
930   return 1;
931 }
932
933 int faimtest_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
934 {
935   va_list ap;
936   struct aim_directim_priv *priv;
937   struct aim_conn_t *newconn;
938
939   va_start(ap, command);
940   newconn = va_arg(ap, struct aim_conn_t *);
941   va_end(ap);
942
943   priv = (struct aim_directim_priv *)newconn->priv;
944
945   printf("faimtest: OFT: DirectIM: intitiate success to %s\n", priv->ip);
946   
947   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, faimtest_directim_incoming, 0);
948   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT, faimtest_directim_disconnect, 0);
949   aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, faimtest_directim_typing, 0);
950
951   aim_send_im_direct(sess, newconn, "goodday");
952
953   printf("faimtest: OFT: DirectIM: connected to %s\n", priv->sn);
954
955   return 1;
956 }
957
958 int faimtest_directim_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
959 {
960   va_list ap;
961   struct aim_directim_priv *priv;
962   
963   va_start(ap, command);
964   priv = va_arg(ap, struct aim_directim_priv *);
965
966   va_end(ap);
967   
968   printf("faimtest: directim_connect\n");
969
970   return 1;
971 }
972
973 int faimtest_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
974 {
975   va_list ap;
976   char *sn = NULL, *msg = NULL;
977   struct aim_conn_t *conn;
978
979   va_start(ap, command);
980   conn = va_arg(ap, struct aim_conn_t *);
981   sn = va_arg(ap, char *);
982   msg = va_arg(ap, char *);
983   va_end(ap);
984
985   printf("faimtest: Directim from %s: %s\n", sn, msg);
986   if (!strncmp(msg, "sendmsg", 7)) {
987     int i;
988     i = atoi(msg+8);
989     if (i < 10000) {
990       char *newbuf;
991       int z;
992       
993       newbuf = malloc(i+1);
994       for (z = 0; z < i; z++) {
995         newbuf[z] = (z % 10)+0x30;
996       }
997       newbuf[i] = '\0';
998       aim_send_im_direct(sess, conn, newbuf);
999       free(newbuf);
1000     }
1001   } else if (!strncmp(msg, "goodday", 7)) {
1002     aim_send_im_direct(sess, conn, "Good day to you, too");
1003   } else {
1004     char newmsg[1024];
1005     snprintf(newmsg, sizeof(newmsg), "unknown (%s)\n", msg);
1006     aim_send_im_direct(sess, conn, newmsg);
1007   }
1008   return 1;
1009 }
1010
1011 int faimtest_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1012 {
1013   va_list ap;
1014   struct aim_conn_t *conn;
1015   char *sn;
1016
1017   va_start(ap, command);
1018   conn = va_arg(ap, struct aim_conn_t *);
1019   sn = va_arg(ap, char *);
1020   va_end(ap);
1021
1022   printf("faimtest: directim: disconnected from %s\n", sn);
1023
1024   aim_conn_kill(sess, &conn);
1025   return 1;
1026 }
1027
1028 int faimtest_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1029 {
1030   va_list ap;
1031   char *sn;
1032   
1033   va_start(ap, command);
1034   sn = va_arg(ap, char *);
1035   va_end(ap);
1036
1037   printf("faimtest: ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
1038   return 1;
1039 }
1040
1041 int faimtest_authsvrready(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1042 {
1043   printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
1044   sleep(10);
1045   /* should just be able to tell it we're ready too... */
1046   aim_auth_clientready(sess, command->conn);
1047
1048 #if 0
1049   /*
1050    * This is where you'd really begin changing your password.
1051    *   However, this callback may get called for reasons other
1052    *   than you wanting to change your password.  You should 
1053    *   probably check that before actually doing it.
1054    */
1055   aim_auth_changepasswd(sess, command->conn, "PWD1", "PWD2");
1056 #endif
1057
1058   return 1;
1059 }
1060
1061 int faimtest_pwdchngdone(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1062 {
1063   printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
1064   return 1;
1065 }
1066
1067 int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1068 {
1069   struct aim_userinfo_s *userinfo;
1070    
1071   va_list ap;
1072   va_start(ap, command);
1073   userinfo = va_arg(ap, struct aim_userinfo_s *);
1074   va_end(ap);
1075
1076   printf("\n%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
1077          userinfo->sn, userinfo->flags,
1078          (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1079          (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1080          (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1081          (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1082          (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1083          (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1084          (userinfo->flags&AIM_FLAG_UNKNOWN40)?" UNKNOWN40":"",
1085          (userinfo->flags&AIM_FLAG_UNKNOWN80)?" UNKNOWN80":"",
1086          userinfo->capabilities);
1087   return 1;
1088 }
1089
1090 int faimtest_parse_offgoing(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1091 {
1092   char *sn;
1093   va_list ap;
1094   
1095   va_start(ap, command);
1096   sn = va_arg(ap, char *);
1097   va_end(ap);
1098
1099   printf("\n%s has left\n", sn);
1100
1101   return 1;
1102 }
1103
1104 int faimtest_parse_motd(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1105 {
1106   static char *codes[] = {
1107     "Unknown",
1108     "Mandatory upgrade",
1109     "Advisory upgrade",
1110     "System bulletin",
1111     "Top o' the world!"};
1112   static int codeslen = 5;
1113
1114   char *msg;
1115   unsigned short id;
1116   va_list ap;
1117   
1118   va_start(ap, command);
1119   id = va_arg(ap, int);
1120   msg = va_arg(ap, char *);
1121   va_end(ap);
1122
1123   printf("faimtest: motd: %s (%d / %s)\n", msg, id, 
1124          (id < codeslen)?codes[id]:"unknown");
1125
1126   return 1;
1127 }
1128
1129 int faimtest_parse_msgerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1130 {
1131   va_list ap;
1132   char *destsn;
1133   unsigned short reason;
1134
1135   va_start(ap, command);
1136   destsn = va_arg(ap, char *);
1137   reason = va_arg(ap, int);
1138   va_end(ap);
1139
1140   printf("faimtest: message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1141   
1142   return 1;
1143 }
1144
1145 int faimtest_parse_locerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1146 {
1147   va_list ap;
1148   char *destsn;
1149   unsigned short reason;
1150
1151   va_start(ap, command);
1152   destsn = va_arg(ap, char *);
1153   reason = va_arg(ap, int);
1154   va_end(ap);
1155
1156   printf("faimtest: user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown");
1157   
1158   return 1;
1159 }
1160
1161 /* 
1162  * Handles callbacks for AIM_CB_MISSED_CALL.
1163  */
1164 int faimtest_parse_misses(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1165 {
1166   static char *missedreasons[] = {
1167     "Unknown",
1168     "Message too large"};
1169   static int missedreasonslen = 2;
1170
1171   va_list ap;
1172   unsigned short chan, nummissed, reason;
1173   struct aim_userinfo_s *userinfo;
1174   
1175   va_start(ap, command);
1176   chan = va_arg(ap, int);
1177   userinfo = va_arg(ap, struct aim_userinfo_s *);
1178   nummissed = va_arg(ap, int);
1179   reason = va_arg(ap, int);
1180   va_end(ap);
1181
1182   printf("faimtest: missed %d messages from %s (reason %d: %s)\n", nummissed, userinfo->sn, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1183   
1184   return 1;
1185 }
1186
1187 int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1188 {
1189   struct client_info_s info = {"faimtest (with SNAC login)", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x0000004b}; /* 4.1.2010 */
1190   char *key;
1191   va_list ap;
1192   
1193   va_start(ap, command);
1194   key = va_arg(ap, char *);
1195   va_end(ap);
1196
1197   aim_send_login(sess, command->conn, screenname, password, &info, key);
1198  
1199   return 1;
1200 }
1201
1202 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1203 {
1204   va_list ap;
1205   struct aim_userinfo_s *userinfo;
1206   int count = 0, i = 0;
1207   
1208   va_start(ap, command);
1209   count = va_arg(ap, int);
1210   userinfo = va_arg(ap, struct aim_userinfo_s *);
1211   va_end(ap);
1212
1213   printf("faimtest: chat: %s:  New occupants have joined:\n", (char *)command->conn->priv);
1214   while (i < count)
1215     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1216
1217   return 1;
1218 }
1219
1220 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1221 {
1222   va_list ap;
1223   struct aim_userinfo_s *userinfo;
1224   int count = 0, i = 0;
1225   
1226   va_start(ap, command);
1227   count = va_arg(ap, int);
1228   userinfo = va_arg(ap, struct aim_userinfo_s *);
1229   va_end(ap);
1230
1231   printf("faimtest: chat: %s:  Some occupants have left:\n", (char *)command->conn->priv);
1232   while (i < count)
1233     printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1234
1235   return 1;
1236 }
1237
1238 int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1239 {
1240   va_list ap;
1241   struct aim_userinfo_s *userinfo;
1242   struct aim_chat_roominfo *roominfo;
1243   char *roomname;
1244   int usercount,i;
1245   char *roomdesc;
1246   unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen;
1247   unsigned long creationtime;
1248
1249   va_start(ap, command);
1250   roominfo = va_arg(ap, struct aim_chat_roominfo *);
1251   roomname = va_arg(ap, char *);
1252   usercount= va_arg(ap, int);
1253   userinfo = va_arg(ap, struct aim_userinfo_s *);
1254   roomdesc = va_arg(ap, char *);
1255   unknown_c9 = va_arg(ap, int);
1256   creationtime = va_arg(ap, unsigned long);
1257   maxmsglen = va_arg(ap, int);
1258   unknown_d2 = va_arg(ap, int);
1259   unknown_d5 = va_arg(ap, int);
1260   va_end(ap);
1261
1262   printf("faimtest: chat: %s:  info update:\n", (char *)command->conn->priv);
1263   printf("faimtest: chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", 
1264          (char *)command->conn->priv,
1265          roominfo->exchange,
1266          roominfo->name,
1267          roominfo->instance);
1268   printf("faimtest: chat: %s:  \tRoomname: %s\n", (char *)command->conn->priv, roomname);
1269   printf("faimtest: chat: %s:  \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
1270   printf("faimtest: chat: %s:  \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
1271   
1272   i = 0;
1273   while (i < usercount)
1274     printf("faimtest: chat: %s:  \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
1275
1276   printf("faimtest: chat: %s:  \tUnknown_c9: 0x%04x\n", (char *)command->conn->priv, unknown_c9);
1277   printf("faimtest: chat: %s:  \tCreation time: %lu (time_t)\n", (char *)command->conn->priv, creationtime);
1278   printf("faimtest: chat: %s:  \tMax message length: %d bytes\n", (char *)command->conn->priv, maxmsglen);
1279   printf("faimtest: chat: %s:  \tUnknown_d2: 0x%04x\n", (char *)command->conn->priv, unknown_d2);
1280   printf("faimtest: chat: %s:  \tUnknown_d5: 0x%02x\n", (char *)command->conn->priv, unknown_d5);
1281
1282   return 1;
1283 }
1284
1285 int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1286 {
1287   va_list ap;
1288   struct aim_userinfo_s *userinfo;
1289   char *msg;
1290   char tmpbuf[1152];
1291  
1292   va_start(ap, command);
1293   userinfo = va_arg(ap, struct aim_userinfo_s *);       
1294   msg = va_arg(ap, char *);
1295   va_end(ap);
1296
1297   printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
1298
1299   /*
1300    * Do an echo for testing purposes.  But not for ourselves ("oops!")
1301    */
1302   if (strcmp(userinfo->sn, sess->logininfo.screen_name) != 0)
1303     {
1304       sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
1305       aim_chat_send_im(sess, command->conn, tmpbuf);
1306     }
1307
1308   return 1;
1309 }
1310
1311 int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1312 {
1313   unsigned short type;
1314   va_list ap;
1315
1316   va_start(ap, command);
1317   type = va_arg(ap, int);
1318
1319   switch(type) {
1320   case 0x0002: {
1321     int maxrooms;
1322     struct aim_chat_exchangeinfo *exchanges;
1323     int exchangecount,i = 0;
1324     
1325     maxrooms = va_arg(ap, int);
1326     exchangecount = va_arg(ap, int);
1327     exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1328     va_end(ap);
1329     
1330     printf("faimtest: chat info: Chat Rights:\n");
1331     printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1332     
1333     printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
1334     while (i < exchangecount) {
1335       printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n", 
1336              exchanges[i].number,       
1337              exchanges[i].name,
1338              exchanges[i].charset1,
1339              exchanges[i].lang1);
1340       i++;
1341     }
1342     
1343   }
1344   break;
1345   case 0x0008: {
1346     char *fqcn, *name, *ck;
1347     unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
1348     unsigned char createperms;
1349     unsigned long createtime;
1350
1351     fqcn = va_arg(ap, char *);
1352     instance = va_arg(ap, int);
1353     exchange = va_arg(ap, int);
1354     flags = va_arg(ap, int);
1355     createtime = va_arg(ap, unsigned long);
1356     maxmsglen = va_arg(ap, int);
1357     maxoccupancy = va_arg(ap, int);
1358     createperms = va_arg(ap, int);
1359     unknown = va_arg(ap, int);
1360     name = va_arg(ap, char *);
1361     ck = va_arg(ap, char *);
1362     va_end(ap);
1363
1364     printf("faimtest: recieved room create reply for %s/0x%04x\n", fqcn, exchange);
1365   }
1366   break;
1367   default:
1368     va_end(ap);
1369     printf("faimtest: chatnav info: unknown type (%04x)\n", type);
1370   }
1371   return 1;
1372 }
1373
1374 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1375 {
1376   va_list ap;
1377   unsigned short code;
1378   char *msg = NULL;
1379
1380   va_start(ap, command);
1381   code = va_arg(ap, int);
1382   msg = va_arg(ap, char *);
1383   va_end(ap);
1384
1385   printf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
1386   aim_conn_kill(sess, &command->conn); /* this will break the main loop */
1387
1388   return 1;
1389 }
1390
1391 int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1392 {       
1393   printf("faimtest: connecting to an aimdebugd!\n");
1394
1395   /* convert the authorizer connection to a BOS connection */
1396   command->conn->type = AIM_CONN_TYPE_BOS;
1397
1398   aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
1399
1400   /* tell the aimddebugd we're ready */
1401   aim_debugconn_sendconnect(sess, command->conn); 
1402
1403   /* go right into main loop (don't open a BOS connection, etc) */
1404   return 1;
1405 }
1406
1407 /*
1408  * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
1409  */
1410 int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1411 {
1412   va_list ap;
1413   unsigned short type;
1414   char *sn = NULL;
1415
1416   va_start(ap, command);
1417   type = va_arg(ap, int);
1418   sn = va_arg(ap, char *);
1419   va_end(ap);
1420
1421   printf("faimtest: msgack: 0x%04x / %s\n", type, sn);
1422
1423   return 1;
1424 }
1425
1426 #ifdef FILESUPPORT
1427 int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
1428 {
1429   va_list ap;
1430   struct aim_conn_t *oftconn;
1431   struct aim_fileheader_t *fh;
1432   char *cookie;
1433
1434   va_start(ap, command);
1435   oftconn = va_arg(ap, struct aim_conn_t *);
1436   fh = va_arg(ap, struct aim_fileheader_t *);
1437   cookie = va_arg(ap, char *);
1438   va_end(ap);
1439
1440   printf("faimtest: request for file %s.\n", fh->name);
1441
1442   return 1;
1443 }
1444
1445
1446 int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1447 {
1448   va_list ap;
1449   struct aim_conn_t *oftconn;
1450   struct aim_fileheader_t *fh;
1451   char *path, *cookie;
1452
1453   FILE *file;
1454
1455   va_start(ap, command);
1456   oftconn = va_arg(ap, struct aim_conn_t *);
1457   fh = va_arg(ap, struct aim_fileheader_t *);
1458   cookie = va_arg(ap, char *);
1459   va_end(ap);
1460
1461   printf("faimtest: sending file %s.\n", fh->name);
1462
1463   if( (path = (char *)calloc(1, strlen(sess->oft.listingdir) +strlen(fh->name)+2)) == NULL) {
1464     perror("calloc:");
1465     printf("faimtest: error in calloc of path\n");
1466     return 0; /* XXX: no idea what winaim expects here =) */
1467   }
1468   
1469   snprintf(path, strlen(sess->oft.listingdir)+strlen(fh->name)+2, "%s/%s", sess->oft.listingdir, fh->name);
1470
1471
1472   if( (file = fopen(path, "r")) == NULL) {
1473     printf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
1474     return 0;
1475   }
1476
1477   if (aim_getfile_send(oftconn, file, fh) == -1) {
1478     printf("faimtest: getfile_send failed. damn.\n");
1479   } else {
1480     printf("faimtest: looks like getfile went clean\n");
1481   }
1482
1483   free(fh);  
1484   return 1;
1485 }
1486
1487 int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...) 
1488 {
1489   va_list ap;
1490   struct aim_conn_t *conn;
1491   struct aim_fileheader_t *fh;
1492
1493   va_start(ap, command);
1494   conn = va_arg(ap, struct aim_conn_t *);
1495   fh = va_arg(ap, struct aim_fileheader_t *);
1496   va_end(ap);
1497
1498   printf("faimtest: completed file transfer for %s.\n", fh->name);
1499
1500   /*  aim_conn_kill(sess, &conn); */ /* we'll let winaim close the conn */
1501   return 1;
1502 }
1503
1504 int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1505 {
1506   va_list ap;
1507   struct aim_conn_t *conn;
1508   char *sn;
1509
1510   va_start(ap, command);
1511   conn = va_arg(ap, struct aim_conn_t *);
1512   sn = va_arg(ap, char *);
1513   va_end(ap);
1514
1515   aim_conn_kill(sess, &conn);
1516
1517   printf("faimtest: getfile: disconnected from %s\n", sn);
1518   return 1;
1519 }
1520 #endif
1521
1522 int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1523 {
1524   va_list ap;
1525   unsigned long newrate;
1526   
1527   va_start(ap, command); 
1528   newrate = va_arg(ap, unsigned long);
1529   va_end(ap);
1530
1531   printf("faimtest: ratechange: %lu\n", newrate);
1532
1533   return 1;
1534 }
1535
1536 int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
1537 {
1538   va_list ap;
1539   char *sn;
1540
1541   va_start(ap, command);
1542   sn = va_arg(ap, char *);
1543   va_end(ap);
1544
1545   printf("faimtest: warning from: %s\n", sn);
1546
1547   return 1;
1548 }
This page took 0.154131 seconds and 5 git commands to generate.