]> andersk Git - libfaim.git/blob - utils/faimtest/faimtest.c
5ac38c2d12b98998ac397b387830715ecffb7d85
[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 #define FAIMTEST_SCREENNAME "SN"
48 #define FAIMTEST_PASSWORD "PASS"
49
50 #include "aim.h" /* for struct defs, global ptrs, etc */
51
52 int faimtest_parse_oncoming(struct command_rx_struct *, ...);
53 int faimtest_parse_offgoing(struct command_rx_struct *, ...);
54 int faimtest_parse_login_phase3d_f(struct command_rx_struct *, ...);
55 int faimtest_auth_error(struct command_rx_struct *, ...);
56 int faimtest_auth_success(struct command_rx_struct *, ...);
57 int faimtest_parse_incoming_im(struct command_rx_struct *command, ...);
58 int faimtest_parse_userinfo(struct command_rx_struct *command, ...);
59 int faimtest_handleredirect(struct command_rx_struct *command, ...);
60 int faimtest_authsvrready(struct command_rx_struct *command, ...);
61 int faimtest_pwdchngdone(struct command_rx_struct *command, ...);
62 int faimtest_serverready(struct command_rx_struct *command, ...);
63 int faimtest_parse_misses(struct command_rx_struct *command, ...);
64 int main(void)
65 {
66
67 #if 0
68   /*
69     specify your custom command handlers here.  I recommend
70     at least overriding the login_phase3d_f handler so that
71     you can have your own buddy list and profile.  The
72     rest are probably only useful to override for UI
73     reasons.
74    */
75   rxcallback_t faimtest_callbacks[] = {
76     faimtest_parse_incoming_im, /* incoming IM 0 */
77     faimtest_parse_oncoming, /* oncoming buddy 1 */
78     faimtest_parse_offgoing, /* offgoing buddy 2 */
79     faimtest_parse_misses, /* AIM_CB_MISSED_IM 3 */
80     faimtest_parse_misses, /* AIM_CB_MISSED_CALL 4 */
81     NULL, /* login phase 4 packet C command 1 -- depricated 5 */
82     NULL, /* login phase 4 packet C command 2 -- depricated 6 */
83     NULL, /* login phase 2, first resp -- depricated 7 */
84     faimtest_serverready, /* server ready -- **HANDLING REQUIRED** 8 */
85     NULL, /* login phase 3 packet B -- depricated 9 */
86     NULL, /* login phase 3D packet A -- depricated 10 */
87     NULL, /* login phase 3D packet B -- depricated 11 */
88     NULL, /* login phase 3D packet C -- depricated 12 */
89     NULL, /* login phase 3D packet D -- depricated 13 */
90     NULL, /* login phase 3D packet E -- depricated 14 */
91     faimtest_handleredirect, /* redirect -- **HANDLING REQUIRED** 15 */
92     faimtest_parse_misses, /* AIM_CB_RATECHANGE 16 */
93     faimtest_parse_misses, /* AIM_CB_USERERROR 17 */
94     NULL, /* completely unknown command 18 */
95     faimtest_parse_userinfo, /* user info response 19 */
96     NULL, /* user search by address response 20 */
97     NULL, /* user serach by name response 21 */
98     NULL, /* user search fail 22 */
99     faimtest_auth_error, /* 23 */
100     faimtest_auth_success, /* 24 */
101     faimtest_authsvrready, /* 25 */
102     NULL, /* 26 */
103     faimtest_pwdchngdone, /* 27 */
104     faimtest_serverready, /* 28 */
105     0x00 /* terminating NULL -- REQUIRED 29 */
106   };
107 #endif
108
109   struct client_info_s info = {"FAIMtest (Hi guys!)", 3, 90, 42, "us", "en"};
110   struct aim_conn_t *authconn = NULL;
111   int stayconnected = 1;
112   
113   aim_connrst(); /* reset connection array -- there's a better place for this*/
114   /* register our callback array (optional) */
115   //aim_register_callbacks(faimtest_callbacks);
116
117  enter:
118   authconn = aim_newconn(AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER);
119                        
120   if (authconn == NULL)
121     {
122       fprintf(stderr, "faimtest: internal connection error while in aim_login.  bailing out.\n");
123       return -1;
124     }
125   else if (authconn->fd == -1)
126     {
127       if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
128         fprintf(stderr, "faimtest: could not resolve authorizer name\n");
129       else if (authconn->status & AIM_CONN_STATUS_CONNERR)
130         fprintf(stderr, "faimtest: could not connect to authorizer\n");
131       return -1;
132     }
133   else
134     {
135       aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, faimtest_auth_error, 0);
136       aim_conn_addhandler(authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_auth_success, 0);
137       aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
138       aim_send_login(authconn, FAIMTEST_SCREENNAME, FAIMTEST_PASSWORD, &info);
139     }
140
141   while (aim_select(NULL) > (struct aim_conn_t *)0)
142     {
143       if (aim_queue_outgoing)
144         aim_tx_flushqueue();
145
146       if (aim_get_command() < 0)
147         {
148           printf("\afaimtest: connection error!\n");
149         }
150       else
151         aim_rxdispatch();
152     }
153
154   /* Close up */
155   printf("AIM just decided we didn't need to be here anymore, closing up.,,\n");
156   
157   /* close up all connections, dead or no */
158   aim_logoff(); 
159
160   if (stayconnected)
161     {
162       printf("\nTrying to reconnect in 2 seconds...\n");
163       sleep(2);
164       goto enter;
165     }
166
167   /* Get out */
168   exit(0);
169 }
170
171 int faimtest_serverready(struct command_rx_struct *command, ...)
172 {
173   switch (command->conn->type)
174     {
175     case AIM_CONN_TYPE_BOS:
176       aim_bos_reqrate(command->conn); /* request rate info */
177       aim_bos_ackrateresp(command->conn);  /* ack rate info response -- can we say timing? */
178       aim_bos_setprivacyflags(command->conn, 0x00000003);
179       
180 #if 0
181       aim_bos_reqpersonalinfo(command->conn);
182 #endif
183       
184       aim_bos_reqservice(command->conn, AIM_CONN_TYPE_ADS); /* 0x05 == Advertisments */
185
186 #if 0
187       aim_bos_reqrights(NULL);
188       aim_bos_reqbuddyrights(NULL);
189       aim_bos_reqlocaterights(NULL);
190       aim_bos_reqicbmparaminfo(NULL);
191 #endif
192       
193       /* set group permissions */
194       aim_bos_setgroupperm(NULL, 0x1f);
195       fprintf(stderr, "faimtest: done with BOS ServerReady\n");
196       break;
197     case AIM_CONN_TYPE_CHATNAV:
198       fprintf(stderr, "faimtest: chatnav: got server ready\n");
199       break;
200     default:
201       fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
202     }
203   return 1;
204 }
205
206 /*
207   handleredirect()...
208
209   This, of course, handles Service Redirects from OSCAR.
210
211   Should get passed in the following:
212      struct command_rx_struct *command
213        the raw command data
214      int serviceid
215        the destination service ID
216      char *serverip
217        the IP address of the service's server
218      char *cookie
219        the raw auth cookie
220  */
221 int faimtest_handleredirect(struct command_rx_struct *command, ...)
222 {
223   va_list ap;
224   int serviceid;
225   char *ip;
226   char *cookie;
227
228   /* this is the new buddy list */
229   char buddies[] = "Buddy1&Buddy2&";
230   /* this is the new profile */
231   char profile[] = "Hello";  
232
233   va_start(ap, command);
234   serviceid = va_arg(ap, int);
235   ip = va_arg(ap, char *);
236   cookie = va_arg(ap, char *);
237   va_end(ap);
238
239   switch(serviceid)
240     {
241     case 0x0005: /* Advertisements */
242       /*
243        * The craziest explanation yet as to why we finish logging in when
244        * we get the advertisements redirect, of which we don't use anyway....
245        *                    IT WAS EASY!
246        */
247
248       /* send the buddy list and profile (required, even if empty) */
249       aim_bos_setbuddylist(command->conn, buddies);
250       aim_bos_setprofile(command->conn, profile);
251
252       /* send final login command (required) */
253       aim_bos_clientready(command->conn); /* tell BOS we're ready to go live */
254
255       /* you should now be ready to go */
256       printf("\nYou are now officially online. (%s)\n", ip);      
257
258       break;
259     case 0x0007: /* Authorizer */
260       {
261         struct aim_conn_t *tstconn;
262         /* Open a connection to the Auth */
263         tstconn = aim_newconn(AIM_CONN_TYPE_AUTH, ip);
264         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) )
265           fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
266         else
267           /* Send the cookie to the Auth */
268           aim_auth_sendcookie(tstconn, cookie);
269
270       }  
271       break;
272     case 0x000d: /* ChatNav */
273       {
274         struct aim_conn_t *tstconn = NULL;
275         tstconn = aim_newconn(AIM_CONN_TYPE_CHATNAV, ip);
276         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
277           {
278             fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
279             return 1;
280           }
281         aim_conn_addhandler(tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
282         aim_conn_addhandler(tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
283         aim_auth_sendcookie(tstconn, cookie);
284         fprintf(stderr, "\achatnav: connected\n");
285       }
286       break;
287     case 0x000e: /* Chat */
288       {
289 #if 0
290         struct aim_conn_t *tstconn = NULL;
291         tstconn = aim_newconn(AIM_CONN_TYPE_CHAT, ip);
292         if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
293           {
294             fprintf(stderr, "faimtest: unable to connect to chat server\n");
295             return 1;
296           }
297         aim_auth_sendcookie(aim_getconn_type(AIM_CONN_TYPE_CHAT), cookie);
298         fprintf(stderr, "\achat: connected\n");
299 #endif
300       }
301       break;
302     default:
303       printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
304       /* dunno */
305     }
306
307   return 1;
308 }
309
310 int faimtest_auth_error(struct command_rx_struct *command, ...)
311 {
312   va_list ap;
313   struct login_phase1_struct *logininfo;
314   char *errorurl;
315   short errorcode;
316
317   va_start(ap, command);
318   logininfo = va_arg(ap, struct login_phase1_struct *);
319   printf("Screen name: %s\n", logininfo->screen_name);
320   errorurl = va_arg(ap, char *);
321   printf("Error URL: %s\n", errorurl);
322   errorcode = va_arg(ap, short);
323   printf("Error code: 0x%02x\n", errorcode);
324   va_end(ap);
325
326   aim_conn_close(aim_getconn_type(AIM_CONN_TYPE_AUTH));
327   exit(0);
328   
329   return 0;
330 }
331
332 int faimtest_auth_success(struct command_rx_struct *command, ...)
333 {
334   va_list ap;
335   struct login_phase1_struct *logininfo;
336   struct aim_conn_t *bosconn = NULL;
337
338   va_start(ap, command);
339   logininfo = va_arg(ap, struct login_phase1_struct *);
340   va_end(ap);
341   
342   printf("Screen name: %s\n", logininfo->screen_name);
343   printf("Reg status: %2d\n", logininfo->regstatus);
344   printf("Email: %s\n", logininfo->email);
345   printf("Cookie len: %d\n", sizeof(logininfo->cookie));
346   printf("BOS IP: %s\n", logininfo->BOSIP);
347
348   printf("Closing auth connection...\n");
349   aim_conn_close(command->conn);
350   bosconn = aim_newconn(AIM_CONN_TYPE_BOS, logininfo->BOSIP);
351   if (bosconn == NULL)
352     {
353       fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
354     }
355   else if (bosconn->status != 0)
356     {
357       fprintf(stderr, "faimtest: could not connect to BOS\n");
358     }
359   else
360     {
361       aim_conn_addhandler(bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
362       aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
363       aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
364       aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
365       aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, NULL, 0);
366       aim_conn_addhandler(bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0);
367       aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
368       aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
369       aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
370       aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0);
371       aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
372       aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0);
373       aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0);
374       aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
375
376       aim_conn_addhandler(bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
377       aim_conn_addhandler(bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
378       aim_auth_sendcookie(bosconn, logininfo->cookie);
379     }
380   return 1;
381 }
382
383 int faimtest_parse_userinfo(struct command_rx_struct *command, ...)
384 {
385   struct aim_userinfo_s *userinfo;
386   char *prof_encoding = NULL;
387   char *prof = NULL;
388
389   va_list ap;
390   va_start(ap, command);
391   userinfo = va_arg(ap, struct aim_userinfo_s *);
392   prof_encoding = va_arg(ap, char *);
393   prof = va_arg(ap, char *);
394   va_end(ap);
395   
396   printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
397   printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
398   printf("faimtest: userinfo: class: 0x%04x = ", userinfo->class);
399
400   /*
401    *  00000000  (binary)
402    *         1  Trial  
403    *        2   Unknown
404    *       3    AOL
405    *      4     Unknown
406    *     5      Free
407    * 
408    * ORed together.
409    *
410    */
411
412   if (userinfo->class & 0x0001)
413     printf("TRIAL ");
414   if (userinfo->class & 0x0002)
415     printf("UNKNOWN_BIT2 ");
416   if (userinfo->class & 0x0004)
417     printf("AOL ");
418   if (userinfo->class & 0x0008)
419     printf("UNKNOWN_BIT4 ");
420   if (userinfo->class & 0x0010)
421     printf("FREE ");
422   printf("\n");
423   
424   printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
425   printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
426   printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
427   
428   printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
429   printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
430   
431   return 1;
432 }
433
434 /*
435  * The user-level Incoming ICBM callback.
436  *
437  * Arguments:
438  *  struct command_rx_struct *  command     if you feel like doing it yourself
439  *  char *                      srcsn       the source name
440  *  char *                      msg         message
441  *  int                         warnlevel   warning/evil level
442  *  int                         class       user class
443  *  ulong                       membersince time_t of date of signup
444  *  ulong                       onsince     time_t of date of singon
445  *  int                         idletime    min (sec?) idle
446  *  int                         isautoreply TRUE if its an auto-response
447  *
448  */
449 int faimtest_parse_incoming_im(struct command_rx_struct *command, ...)
450 {
451   struct aim_userinfo_s *userinfo;
452   char *msg = NULL;
453   int isautoreply = 0;
454   va_list ap;
455   char *tmpstr = NULL;
456
457   va_start(ap, command);
458   userinfo = va_arg(ap, struct aim_userinfo_s *);
459   msg = va_arg(ap, char *);
460   isautoreply = va_arg(ap, int);
461   va_end(ap);
462
463   printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
464   printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
465   printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
466   if (userinfo->class & 0x0010)
467     printf("(FREE)\n");
468   else if (userinfo->class & 0x0001)
469     printf("(TRIAL)\n");
470   else if (userinfo->class & 0x0004)
471     printf("(AOL)\n");
472   else
473     printf("(UNKNOWN)\n");
474   printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
475   printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
476   printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
477   printf("faimtest: icbm: isautoreply = %s\n", isautoreply ? "TRUE" : "FALSE");  
478
479   printf("faimtest: icbm: message: %s\n", msg);
480
481   if (msg)
482     {
483       tmpstr = index(msg, '>');
484       if (tmpstr != NULL)
485         tmpstr+=1;
486       else
487         tmpstr = msg;
488       
489       if ( (strlen(tmpstr) >= 10) &&
490            (!strncmp(tmpstr, "disconnect", 10)) )
491         {
492           aim_send_im(command->conn, "midendian", 0, "ta ta...");
493           aim_logoff();
494         }
495       else if (strstr(tmpstr, "goodday"))
496         {
497           printf("faimtest: icbm: sending response\n");
498           aim_send_im(command->conn, userinfo->sn, 0, "Good day to you too.");
499         }
500 #if 0
501       else if (!strncmp(tmpstr, "joinchat", 8))
502         {
503           aim_chat_join(command->conn, "GoodDay");
504         }
505 #endif
506       else 
507         {
508 #if 0
509           printf("faimtest: icbm:  starting chat...\n");
510           aim_bos_reqservice(command->conn, AIM_CONN_TYPE_CHATNAV);
511 #else
512           aim_bos_setidle(command->conn, 0x0ffffffe);
513 #endif
514         }
515
516     }
517
518   printf("faimtest: icbm: done with ICBM handling\n");
519
520   return 1;
521 }
522
523 int faimtest_authsvrready(struct command_rx_struct *command, ...)
524 {
525   printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
526   sleep(10);
527   /* should just be able to tell it we're ready too... */
528   aim_auth_clientready(command->conn);
529
530 #if 0
531   /*
532    * This is where you'd really begin changing your password.
533    *   However, this callback may get called for reasons other
534    *   than you wanting to change your password.  You should 
535    *   probably check that before actually doing it.
536    */
537   aim_auth_changepasswd(command->conn, "PWD1", "PWD2");
538 #endif
539
540   return 1;
541 }
542
543 int faimtest_pwdchngdone(struct command_rx_struct *command, ...)
544 {
545   printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
546   return 1;
547 }
548
549 int faimtest_parse_oncoming(struct command_rx_struct *command, ...)
550 {
551   struct aim_userinfo_s *userinfo;
552    
553   va_list ap;
554   va_start(ap, command);
555   userinfo = va_arg(ap, struct aim_userinfo_s *);
556   va_end(ap);
557
558   printf("\n%s is now online\n", userinfo->sn);
559
560   return 1;
561 }
562
563 int faimtest_parse_offgoing(struct command_rx_struct *command, ...)
564 {
565
566   printf("\n%s has left\n", &(command->data[11]));
567
568   return 1;
569 }
570
571
572 /* 
573  * Handles callbacks for: AIM_CB_RATECHANGE, AIM_CB_USERERROR, 
574  *   AIM_CB_MISSED_IM, and AIM_CB_MISSED_CALL.
575  */
576 int faimtest_parse_misses(struct command_rx_struct *command, ...)
577 {
578   u_short family;
579   u_short subtype;
580
581   family = (command->data[0] << 8) + command->data[1];
582   subtype = (command->data[2] << 8) + command->data[3];
583   
584   switch (family)
585     {
586     case 0x0001:
587       if (subtype == 0x000a) /* or AIM_CB_RATECHANGE */
588         printf("\n****STOP SENDING/RECIEVING MESSAGES SO FAST!****\n\n");
589       break;
590     case 0x0002:
591       if (subtype == 0x0001) /* or AIM_CB_USERERROR */
592         {
593           u_long snacid = 0x00000000;
594           
595           snacid = aimutil_get32(&command->data[6]);
596           
597           printf("Received unknown error in SNAC family 0x0002 (snacid = %08lx)\n", snacid);
598         }
599       break;
600     case 0x0004:
601       if (subtype == 0x0001) /* or AIM_CB_MISSED_IM */
602         printf("\n***LAST IM DIDN\'T MAKE IT BECAUSE THE BUDDY IS NOT ONLINE***\n\n");
603       else if (subtype == 0x000a) /* or AIM_CB_MISSED_CALL */
604         printf("You missed some messages from %s because they were sent too fast\n", &(command->data[13]));
605       break;
606     }
607
608   return 0;
609 }
610
611
612
613
614
This page took 0.089119 seconds and 3 git commands to generate.