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