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