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