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