source: aim.c @ d63690b

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since d63690b was d63690b, checked in by James M. Kretchmar <kretch@mit.edu>, 17 years ago
Turned CAPS_CHAT for release
  • Property mode set to 100644
File size: 75.0 KB
Line 
1#include <stdio.h>
2#include <stdio.h>
3#include <sys/stat.h>
4#include "owl.h"
5
6/**********************************************************************/
7
8struct owlfaim_priv {
9  char *aimbinarypath;
10  char *screenname;
11  char *password;
12  char *server;
13  char *proxy;
14  char *proxyusername;
15  char *proxypass;
16  char *ohcaptainmycaptain;
17  int connected;
18
19  FILE *listingfile;
20  char *listingpath;
21
22  fu8_t *buddyicon;
23  int buddyiconlen;
24  time_t buddyiconstamp;
25  fu16_t buddyiconsum;
26};
27
28static char *msgerrreasons[] = {
29        "Invalid error",
30        "Invalid SNAC",
31        "Rate to host",
32        "Rate to client",
33        "Not logged on",
34        "Service unavailable",
35        "Service not defined",
36        "Obsolete SNAC",
37        "Not supported by host",
38        "Not supported by client",
39        "Refused by client",
40        "Reply too big",
41        "Responses lost",
42        "Request denied",
43        "Busted SNAC payload",
44        "Insufficient rights",
45        "In local permit/deny",
46        "Too evil (sender)",
47        "Too evil (receiver)",
48        "User temporarily unavailable",
49        "No match",
50        "List overflow",
51        "Request ambiguous",
52        "Queue full",
53        "Not while on AOL",
54};
55static int msgerrreasonslen = 25;
56
57static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
58static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...);
59static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...);
60int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...);
61int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...);
62void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn);
63static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...);
64int login(aim_session_t *sess, const char *sn, const char *passwd);
65static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...);
66int logout(aim_session_t *sess);
67
68static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...);
69static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...);
70static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...);
71static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...);
72static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...);
73static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...);
74static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...);
75static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...);
76static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...);
77/* static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); */
78static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...);
79static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname);
80static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...);
81static void printuserflags(fu16_t flags);
82static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...);
83static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr);
84static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args);
85static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args);
86static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...);
87static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...);
88static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...);
89int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...);
90static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...);
91static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...);
92static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...);
93static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...);
94static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...);
95static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...);
96static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...);
97static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...);
98static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...);
99static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...);
100static int migrate(aim_session_t *sess, aim_frame_t *fr, ...);
101static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...);
102static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...);
103static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...);
104static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...);
105static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...);
106
107void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
108void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
109
110/*****************************************************************/
111
112void owl_aim_init(void)
113{
114  aim_session_init(owl_global_get_aimsess(&g), AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
115  aim_setdebuggingcb(owl_global_get_aimsess(&g), faimtest_debugcb);
116
117  /* an experiment to expose idle time */
118  aim_ssi_setpresence(owl_global_get_aimsess(&g), 0x00000400);
119}
120
121
122int owl_aim_login(char *screenname, char *password)
123{
124  int ret;
125  struct owlfaim_priv *priv;
126
127  /* this will leak, I know and just don't care right now */
128  priv=owl_malloc(sizeof(struct owlfaim_priv));
129  memset(priv, 0, sizeof(struct owlfaim_priv));
130
131  priv->screenname = owl_strdup(screenname);
132  priv->password = owl_strdup(password);
133  priv->server = "login.oscar.aol.com";
134  owl_global_get_aimsess(&g)->aux_data = priv;
135
136  aim_tx_setenqueue(owl_global_get_aimsess(&g), AIM_TX_IMMEDIATE, NULL);
137 
138  /* login */
139  ret=login(owl_global_get_aimsess(&g), priv->screenname, priv->password);
140  if (ret) {
141    owl_global_set_aimnologgedin(&g);
142    owl_global_set_no_doaimevents(&g);
143    return(-1);
144  }
145  owl_global_set_doaimevents(&g);
146
147  return(0);
148}
149
150#if 0
151static void oscar_login(GaimAccount *account)
152{
153  aim_session_t *sess;
154  aim_conn_t *conn;
155  char buf[256];
156  GaimConnection *gc = gaim_account_get_connection(account);
157  struct oscar_data *od = gc->proto_data = g_new0(struct oscar_data, 1);
158
159  gaim_debug(GAIM_DEBUG_MISC, "oscar", "oscar_login: gc = %p\n", gc);
160
161  if (isdigit(*(gaim_account_get_username(account)))) {
162    od->icq = TRUE;
163  } else {
164    gc->flags |= GAIM_CONNECTION_HTML;
165    gc->flags |= GAIM_CONNECTION_AUTO_RESP;
166  }
167  od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo);
168
169  sess = g_new0(aim_session_t, 1);
170
171  aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
172  aim_setdebuggingcb(sess, oscar_debug);
173
174  /* we need an immediate queue because we don't use a while-loop to
175   * see if things need to be sent. */
176  aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
177  od->sess = sess;
178  sess->aux_data = gc;
179
180  conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
181  if (conn == NULL) {
182    gaim_debug(GAIM_DEBUG_ERROR, "oscar",
183               "internal connection error\n");
184    gaim_connection_error(gc, _("Unable to login to AIM"));
185    return;
186  }
187
188  g_snprintf(buf, sizeof(buf), _("Signon: %s"), gaim_account_get_username(account));
189  gaim_connection_update_progress(gc, buf, 2, 5);
190
191  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
192  aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
193  aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0);
194
195  conn->status |= AIM_CONN_STATUS_INPROGRESS;
196  if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", FAIM_LOGIN_SERVER),
197                         gaim_account_get_int(account, "port", FAIM_LOGIN_PORT),
198                         oscar_login_connect, gc) < 0) {
199    gaim_connection_error(gc, _("Couldn't connect to host"));
200    return;
201  }
202  aim_request_login(sess, conn, gaim_account_get_username(account));
203}
204#endif
205
206
207/* stuff to run once login has been successful */
208void owl_aim_successful_login(char *screenname)
209{
210  owl_function_debugmsg("doing owl_aim_successful_login");
211  owl_global_set_aimloggedin(&g, screenname);
212  owl_global_set_doaimevents(&g); /* this should already be on */
213  owl_function_makemsg("%s logged in", screenname);
214
215  owl_function_debugmsg("Successful AIM login for %s", screenname);
216
217  /* start the ingorelogin timer */
218  owl_timer_reset_newstart(owl_global_get_aim_login_timer(&g),
219                           owl_global_get_aim_ignorelogin_timer(&g));
220
221  /* aim_bos_setidle(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), 5000); */
222}
223
224void owl_aim_logout(void)
225{
226  /* need to check if it's connected first, I think */
227  logout(owl_global_get_aimsess(&g));
228  owl_global_set_aimnologgedin(&g);
229  owl_global_set_no_doaimevents(&g);
230}
231
232void owl_aim_logged_out()
233{
234  owl_function_adminmsg("", "You have been logged out of AIM");
235  owl_aim_logout();
236}
237
238void owl_aim_login_error(char *message)
239{
240  if (message) {
241    owl_function_error(message);
242  } else {
243    owl_function_error("Authentication error on login");
244  }
245  owl_function_beep();
246  owl_global_set_aimnologgedin(&g);
247  owl_global_set_no_doaimevents(&g);
248}
249
250int owl_aim_send_im(char *to, char *msg)
251{
252  int ret;
253
254  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, NULL, msg);
255   
256  /* aim_send_im(owl_global_get_aimsess(&g), to, AIM_IMFLAGS_ACK, msg); */
257
258  /* I don't know how to check for an error yet */
259  return(ret);
260}
261
262void owl_aim_addbuddy(char *name)
263{
264  aim_ssi_addbuddy(owl_global_get_aimsess(&g), name, "Buddies", NULL, NULL, NULL, 0);
265}
266
267void owl_aim_delbuddy(char *name)
268{
269  aim_ssi_delbuddy(owl_global_get_aimsess(&g), name, "Buddies");
270  owl_buddylist_offgoing(owl_global_get_buddylist(&g), name);
271}
272
273
274int owl_aim_set_awaymsg(char *msg)
275{
276  /* there is a max away message lentgh we should check against */
277
278  aim_bos_setprofile(owl_global_get_aimsess(&g),
279                     owl_global_get_bosconn(&g),
280                     NULL, NULL, 0, "us-ascii", msg, 
281                     strlen(msg), 0);
282  return(0);
283}
284
285void owl_aim_chat_join(char *chatroom, int exchange)
286{
287  int ret;
288
289  /* ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000); */
290  /*
291  ret=aim_chat_join(owl_global_get_aimsess(&g),
292                    aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), exchange, chatroom, 0x0000);
293  */
294
295  aim_reqservice(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), AIM_CONN_TYPE_CHATNAV);
296  ret = aim_chatnav_createroom(owl_global_get_aimsess(&g),
297                               aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), chatroom, exchange);
298   ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000);
299 
300  owl_function_debugmsg("Attempting to join chatroom %s exchange %i", chatroom, exchange);
301}
302
303void owl_aim_chat_leave(char *chatroom)
304{
305}
306
307int owl_aim_chat_sendmsg(char *chatroom, char *msg)
308{
309  return(0);
310}
311
312/* caller must free the return */
313char *owl_aim_normalize_screenname(char *in)
314{
315  char *out;
316  int i, j, k;
317
318  j=strlen(in);
319  out=owl_malloc(j+30);
320  k=0;
321  for (i=0; i<j; i++) {
322    if (in[i]!=' ') {
323      out[k]=in[i];
324      k++;
325    }
326  }
327  out[k]='\0';
328  return(out);
329}
330
331int owl_aim_process_events()
332{
333  aim_session_t *aimsess;
334  aim_conn_t *waitingconn = NULL;
335  struct timeval tv;
336  int selstat = 0;
337  struct owlfaim_priv *priv;
338
339  aimsess=owl_global_get_aimsess(&g);
340  priv = (struct owlfaim_priv *) &(aimsess->aux_data);
341
342  /* do a select without blocking */
343  tv.tv_sec = 0;
344  tv.tv_usec = 0;
345  waitingconn = aim_select(aimsess, &tv, &selstat);
346
347  if (owl_global_is_aimnop_time(&g)) {
348    aim_flap_nop(aimsess, aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS));
349    owl_global_aimnop_sent(&g);
350  }
351
352  if (selstat == -1) {
353    owl_aim_logged_out();
354  } else if (selstat == 0) { 
355    /* no events pending */
356  } else if (selstat == 1) { /* outgoing data pending */
357    aim_tx_flushqueue(aimsess);
358  } else if (selstat == 2) { /* incoming data pending */
359    /* printf("selstat == 2\n"); */
360   
361    if (aim_get_command(aimsess, waitingconn) >= 0) {
362      aim_rxdispatch(aimsess);
363    } else {
364      /* printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype); */
365      /* we should have callbacks for all these, else the library will do the conn_kill for us. */
366      if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
367        if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
368          /* printf("disconnected from %s\n", aim_directim_getsn(waitingconn)); */
369          aim_conn_kill(aimsess, &waitingconn);
370          owl_aim_logged_out();
371        }
372      } else {
373        aim_conn_kill(aimsess, &waitingconn);
374        owl_aim_logged_out();
375      }
376      if (!aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS)) {
377        /* printf("major connection error\n"); */
378        owl_aim_logged_out();
379        /* break; */
380      }
381    }
382  }
383  /* free(priv->buddyicon); */
384  /* exit(0); */
385  return(0);
386}
387
388static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
389{
390  return;
391}
392
393static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
394{
395  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
396  struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
397   
398  char *key;
399  va_list ap;
400
401  va_start(ap, fr);
402  key = va_arg(ap, char *);
403  va_end(ap);
404
405  owl_function_debugmsg("doing faimtest_parse_login");
406
407  aim_send_login(sess, fr->conn, priv->screenname, priv->password, &info, key);
408 
409  return(1);
410}
411
412
413static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
414{
415  va_list ap;
416  struct aim_authresp_info *info;
417  aim_conn_t *bosconn;
418
419  va_start(ap, fr);
420  info = va_arg(ap, struct aim_authresp_info *);
421  va_end(ap);
422
423  /* printf("Screen name: %s\n", info->sn); */
424  owl_function_debugmsg("doing faimtest_parse_authresp");
425  owl_function_debugmsg("faimtest_parse_authresp: %s", info->sn);
426
427  /*
428   * Check for error.
429   */
430  if (info->errorcode || !info->bosip || !info->cookie) {
431    /*
432    printf("Login Error Code 0x%04x\n", info->errorcode);
433    printf("Error URL: %s\n", info->errorurl);
434    */
435    if (info->errorcode==0x05) {
436      owl_aim_login_error("Incorrect nickname or password.");
437    } else if (info->errorcode==0x11) {
438      owl_aim_login_error("Your account is currently suspended.");
439    } else if (info->errorcode==0x14) {
440      owl_aim_login_error("The AOL Instant Messenger service is temporarily unavailable.");
441    } else if (info->errorcode==0x18) {
442      owl_aim_login_error("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.");
443    } else if (info->errorcode==0x1c) {
444      owl_aim_login_error("The client version you are using is too old.");
445    } else {
446      owl_aim_login_error(NULL);
447    }
448    aim_conn_kill(sess, &fr->conn);
449    return(1);
450  }
451
452  /*
453  printf("Reg status: %d\n", info->regstatus);
454  printf("Email: %s\n", info->email);
455  printf("BOS IP: %s\n", info->bosip);
456  */
457
458  /* printf("Closing auth connection...\n"); */
459  aim_conn_kill(sess, &fr->conn);
460  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, info->bosip))) {
461    /* printf("could not connect to BOS: internal error\n"); */
462    return(1);
463  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
464    /* printf("could not connect to BOS\n"); */
465    aim_conn_kill(sess, &bosconn);
466    return(1);
467  }
468  owl_global_set_bossconn(&g, bosconn);
469  owl_aim_successful_login(info->sn);
470  addcb_bos(sess, bosconn);
471  aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
472  return(1);
473}
474
475int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
476{
477  owl_function_debugmsg("doing faimtest_flapversion");
478
479#if 0
480  /* XXX fix libfaim to support this */
481  printf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
482
483  /*
484   * This is an alternate location for starting the login process.
485   */
486  /* XXX should do more checking to make sure its really the right AUTH conn */
487  if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
488    /* do NOT send a flapversion, request_login will send it if needed */
489    aim_request_login(sess, fr->conn, priv->screenname);
490    /* printf("faimtest: login request sent\n"); */
491  }
492#endif
493
494  return 1;
495}
496
497
498int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
499{
500  owl_function_debugmsg("doing faimtest_conncomplete");
501  /* owl_aim_successful_login(info->sn); */
502  return 1;
503}
504
505void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
506{
507  owl_function_debugmsg("doing addcb_bos");
508  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
509  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
510
511  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0003,                        ssirights, 0);
512  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0006,                        ssidata, 0);
513  aim_conn_addhandler(sess, bosconn, 0x0013,         0x000f,                        ssidatanochange, 0);
514  aim_conn_addhandler(sess, bosconn, 0x0008,         0x0002,                        handlepopup, 0);
515  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0003,                        faimtest_bosrights, 0);
516  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT,           faimtest_handleredirect, 0);
517  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL,  faimtest_reportinterval, 0);
518  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO,         faimtest_parse_buddyrights, 0);
519  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD,               faimtest_parse_motd, 0);
520  aim_conn_addhandler(sess, bosconn, 0x0004,         0x0005,                        faimtest_icbmparaminfo, 0);
521  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,    faimtest_parse_connerr, 0);
522  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO,         faimtest_locrights, 0);
523  aim_conn_addhandler(sess, bosconn, 0x0001,         0x001f,                        faimtest_memrequest, 0);
524  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING,           faimtest_parse_oncoming, 0);
525  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING,           faimtest_parse_offgoing, 0);
526  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING,           faimtest_parse_incoming_im, 0);
527  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR,              faimtest_parse_locerr, 0);
528  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL,         faimtest_parse_misses, 0);
529  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE,         faimtest_parse_ratechange, 0);
530  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL,               faimtest_parse_evilnotify, 0);
531  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0001,                        faimtest_parse_searcherror, 0);
532  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0003,                        faimtest_parse_searchreply, 0);
533  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR,              faimtest_parse_msgerr, 0);
534  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO,           faimtest_parse_userinfo, 0);
535  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK,                faimtest_parse_msgack, 0);
536
537  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0001,                        faimtest_parse_genericerr, 0);
538  aim_conn_addhandler(sess, bosconn, 0x0003,         0x0001,                        faimtest_parse_genericerr, 0);
539  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0001,                        faimtest_parse_genericerr, 0);
540  aim_conn_addhandler(sess, bosconn, 0x0001,         0x000b,                        serverpause, 0);
541  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0012,                        migrate, 0);
542  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG,         offlinemsg, 0);
543  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, offlinemsgdone, 0);
544
545  return;
546}
547
548static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
549{
550  owl_function_debugmsg("doing coninitdone_bos");
551  aim_reqpersonalinfo(sess, fr->conn);
552
553  aim_ssi_reqrights(sess);
554  aim_ssi_reqdata(sess);
555
556  aim_bos_reqlocaterights(sess, fr->conn);
557  aim_bos_reqbuddyrights(sess, fr->conn);
558  aim_im_reqparams(sess);
559  aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi? */
560
561  /* aim_bos_setprofile(owl_global_get_aimsess(&g), fr->conn, NULL, NULL, 0, NULL, NULL, 0, AIM_CAPS_CHAT); */
562
563#ifdef NOSSI
564  /*
565  aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
566  aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
567  */
568#endif
569
570  return(1);
571}
572
573int login(aim_session_t *sess, const char *sn, const char *passwd)
574{
575  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
576  aim_conn_t *authconn;
577
578  if (sn) priv->screenname = strdup(sn);
579  if (passwd) priv->password = strdup(passwd);
580  if (priv->proxy) aim_setupproxy(sess, priv->proxy, priv->proxyusername, priv->proxypass);
581
582  if (!priv->screenname || !priv->password) {
583    /* printf("need SN and password\n"); */
584    return(-1);
585  }
586
587  if (!(authconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, priv->server ? priv->server : FAIM_LOGIN_SERVER))) {
588    /* printf("internal connection error during login\n"); */
589    return (-1);
590  } else if (authconn->fd == -1) {
591    if (authconn->status & AIM_CONN_STATUS_RESOLVERR) {
592      /* printf("could not resolve authorizer name\n");*/
593    } else if (authconn->status & AIM_CONN_STATUS_CONNERR) {
594      /* printf("could not connect to authorizer\n"); */
595    }
596    aim_conn_kill(sess, &authconn);
597    return(-1);
598  }
599
600  aim_conn_addhandler(sess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
601  aim_conn_addhandler(sess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
602  aim_conn_addhandler(sess, authconn, 0x0017, 0x0007, faimtest_parse_login, 0);
603  aim_conn_addhandler(sess, authconn, 0x0017, 0x0003, faimtest_parse_authresp, 0);
604
605  /* If the connection is in progress, this will just be queued */
606  aim_request_login(sess, authconn, priv->screenname);
607
608  /* printf("login request sent\n"); */
609  return(0);
610}
611
612
613static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
614{
615  aim_clientready(sess, fr->conn);
616  /* printf("initialization done for admin connection\n"); */
617  return(1);
618}
619
620int logout(aim_session_t *sess)
621{
622  aim_session_kill(sess);
623  owl_aim_init();
624 
625  /* kretch
626  if (faimtest_init() == -1)
627    printf("faimtest_init failed\n");
628  */
629
630  return(0);
631}
632
633/**************************************************************************************************/
634
635static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
636{
637  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
638  va_list ap;
639  fu16_t code;
640  char *msg;
641 
642  va_start(ap, fr);
643  code = va_arg(ap, int);
644  msg = va_arg(ap, char *);
645  va_end(ap);
646 
647  /* printf("connerr: Code 0x%04x: %s\n", code, msg); */
648  aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
649 
650  priv->connected = 0;
651 
652  return 1;
653}
654
655static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
656{
657  int status;
658  va_list ap;
659 
660  va_start(ap, fr);
661  status = va_arg(ap, int); /* status code of confirmation request */
662  va_end(ap);
663 
664  /* printf("account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown"); */
665 
666  return 1;
667}
668
669static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
670{
671  fu16_t change = 0, perms, type;
672  int length, str;
673  char *val;
674  va_list ap;
675 
676  va_start(ap, fr);
677  change = va_arg(ap, int);
678  perms = (fu16_t)va_arg(ap, unsigned int);
679  type = (fu16_t)va_arg(ap, unsigned int);
680  length = va_arg(ap, int);
681  val = va_arg(ap, char *);
682  str = va_arg(ap, int);
683  va_end(ap);
684 
685  /* printf("info%s: perms = %d, type = %x, length = %d, val = %s\n", change?" change":"", perms, type, length, str?val:"(not string)"); */
686 
687  return 1;
688}
689
690
691static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
692{
693  va_list ap;
694  struct aim_redirect_data *redir;
695 
696  va_start(ap, fr);
697  redir = va_arg(ap, struct aim_redirect_data *);
698 
699  if (redir->group == 0x0005) {  /* Adverts */
700   
701  } else if (redir->group == 0x0007) {  /* Authorizer */
702    aim_conn_t *tstconn;
703   
704    tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, redir->ip);
705    if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
706      /* printf("unable to reconnect with authorizer\n"); */
707    } else {
708      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
709      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
710      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
711      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
712      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
713      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
714      /* Send the cookie to the Auth */
715      aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
716      /* printf("sent cookie to authorizer host\n"); */
717    }
718  } else if (redir->group == 0x000d) {  /* ChatNav */
719    chatnav_redirect(sess, redir);
720  } else if (redir->group == 0x000e) { /* Chat */
721    chat_redirect(sess, redir);
722  } else {
723    /* printf("uh oh... got redirect for unknown service 0x%04x!!\n", redir->group); */
724  }
725  va_end(ap);
726  return 1;
727}
728
729static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
730{
731  struct aim_icbmparameters *params;
732  va_list ap;
733 
734  va_start(ap, fr);
735  params = va_arg(ap, struct aim_icbmparameters *);
736  va_end(ap);
737 
738  /* printf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %ld\n", params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval); */
739     
740  /*
741  * Set these to your taste, or client medium.  Setting minmsginterval
742  * higher is good for keeping yourself from getting flooded (esp
743  * if you're on a slow connection or something where that would be
744  * useful).
745  */
746  params->maxmsglen = 8000;
747  params->minmsginterval = 0; /* in milliseconds */
748  /* aim_seticbmparam(sess, params); */
749  aim_im_setparams(sess, params);
750 
751  return 1;
752}
753
754static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
755{
756  va_list ap;
757  fu16_t maxbuddies, maxwatchers;
758 
759  va_start(ap, fr);
760  maxbuddies = va_arg(ap, int);
761  maxwatchers = va_arg(ap, int);
762  va_end(ap);
763 
764  /* printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); */
765 
766  /* aim_ssi_reqrights(sess, fr->conn); */
767  aim_ssi_reqrights(sess);
768 
769  return 1;
770}
771
772static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
773{
774  va_list ap;
775  fu16_t maxpermits, maxdenies;
776 
777  va_start(ap, fr);
778  maxpermits = va_arg(ap, int);
779  maxdenies = va_arg(ap, int);
780  va_end(ap);
781 
782  /* printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); */
783  aim_clientready(sess, fr->conn);
784  owl_function_debugmsg("officially connected to BOS.");
785  aim_icq_reqofflinemsgs(sess);
786  return 1;
787}
788
789static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
790{
791  va_list ap;
792  fu16_t maxsiglen;
793 
794  va_start(ap, fr);
795  maxsiglen = va_arg(ap, int);
796  va_end(ap);
797
798  /* printf("locate rights: max signature length = %d\n", maxsiglen); */
799 
800  return(1);
801}
802
803static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
804{
805  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
806  va_list ap;
807  fu16_t interval;
808
809  va_start(ap, fr);
810  interval = va_arg(ap, int);
811  va_end(ap);
812
813  /* printf("minimum report interval: %d (seconds?)\n", interval); */
814
815  if (!priv->connected) {
816    priv->connected++;
817  }
818  /* aim_reqicbmparams(sess); */
819  aim_im_reqparams(sess);
820  /* kretch */
821  return 1;
822}
823
824static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
825{
826  char *msg;
827  fu16_t id;
828  va_list ap;
829  /* static int codeslen = 5;
830  static char *codes[] = {
831    "Unknown",
832    "Mandatory upgrade",
833    "Advisory upgrade",
834    "System bulletin",
835    "Top o' the world!"
836  };
837  */
838
839  return 1;
840 
841  va_start(ap, fr);
842  id = va_arg(ap, int);
843  msg = va_arg(ap, char *);
844  va_end(ap);
845 
846  /* printf("motd: %s (%d / %s)\n", msg, id, (id < codeslen)?codes[id]:"unknown"); */
847 
848  return 1;
849}
850
851/*
852 * This is a little more complicated than it looks.  The module
853 * name (proto, boscore, etc) may or may not be given.  If it is
854 * not given, then use aim.exe.  If it is given, put ".ocm" on the
855 * end of it.
856 *
857 * Now, if the offset or length requested would cause a read past
858 * the end of the file, then the request is considered invalid.  Invalid
859 * requests are processed specially.  The value hashed is the
860 * the request, put into little-endian (eight bytes: offset followed
861 * by length). 
862 *
863 * Additionally, if the request is valid, the length is mod 4096.  It is
864 * important that the length is checked for validity first before doing
865 * the mod.
866 *
867 * Note to Bosco's Brigade: if you'd like to break this, put the
868 * module name on an invalid request.
869 *
870 */
871static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
872{
873  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
874  FILE *f;
875  static const char defaultmod[] = "aim.exe";
876  char *filename = NULL;
877  struct stat st;
878  unsigned char *buf;
879  int invalid = 0;
880 
881  if (!bufret || !buflenret)
882    return -1;
883 
884  if (modname) {
885    if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
886      /* perror("memrequest: malloc"); */
887      return -1;
888    }
889    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
890  } else {
891    if (!(filename = malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
892      /* perror("memrequest: malloc"); */
893      return -1;
894    }
895    sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
896  }
897 
898  if (stat(filename, &st) == -1) {
899    if (!modname) {
900      /* perror("memrequest: stat"); */
901      free(filename);
902      return -1;
903    }
904    invalid = 1;
905  }
906 
907  if (!invalid) {
908    if ((offset > st.st_size) || (len > st.st_size))
909      invalid = 1;
910    else if ((st.st_size - offset) < len)
911      len = st.st_size - offset;
912    else if ((st.st_size - len) < len)
913      len = st.st_size - len;
914  }
915 
916  if (!invalid && len) {
917    len %= 4096;
918  }
919 
920  if (invalid) {
921    int i;
922   
923    free(filename); /* not needed */
924    printf("memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
925    i = 8;
926    if (modname) {
927      i+=strlen(modname);
928    }
929   
930    if (!(buf = malloc(i))) {
931      return -1;
932    }
933   
934    i=0;
935   
936    if (modname) {
937      memcpy(buf, modname, strlen(modname));
938      i+=strlen(modname);
939    }
940   
941    /* Damn endianness. This must be little (LSB first) endian. */
942    buf[i++] = offset & 0xff;
943    buf[i++] = (offset >> 8) & 0xff;
944    buf[i++] = (offset >> 16) & 0xff;
945    buf[i++] = (offset >> 24) & 0xff;
946    buf[i++] = len & 0xff;
947    buf[i++] = (len >> 8) & 0xff;
948    buf[i++] = (len >> 16) & 0xff;
949    buf[i++] = (len >> 24) & 0xff;
950   
951    *bufret = buf;
952    *buflenret = i;
953  } else {
954    if (!(buf = malloc(len))) {
955      free(filename);
956      return -1;
957    }
958    /* printf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename); */
959    if (!(f = fopen(filename, "r"))) {
960      /* perror("memrequest: fopen"); */
961      free(filename);
962      free(buf);
963      return -1;
964    }
965   
966    free(filename);
967   
968    if (fseek(f, offset, SEEK_SET) == -1) {
969      /* perror("memrequest: fseek"); */
970      fclose(f);
971      free(buf);
972      return -1;
973    }
974   
975    if (fread(buf, len, 1, f) != 1) {
976      /* perror("memrequest: fread"); */
977      fclose(f);
978      free(buf);
979      return -1;
980    }
981   
982    fclose(f);
983    *bufret = buf;
984    *buflenret = len;
985  }
986  return 0; /* success! */
987}
988
989/*
990 * This will get an offset and a length.  The client should read this
991 * data out of whatever AIM.EXE binary the user has provided (hopefully
992 * it matches the client information thats sent at login) and pass a
993 * buffer back to libfaim so it can hash the data and send it to AOL for
994 * inspection by the client police.
995 */
996static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
997{
998  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
999  va_list ap;
1000  fu32_t offset, len;
1001  char *modname;
1002  unsigned char *buf;
1003  int buflen;
1004 
1005  va_start(ap, fr);
1006  offset = va_arg(ap, fu32_t);
1007  len = va_arg(ap, fu32_t);
1008  modname = va_arg(ap, char *);
1009  va_end(ap);
1010 
1011  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
1012    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1013    free(buf);
1014  } else {
1015    /* printf("memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname); */
1016    aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1017  }
1018  return 1;
1019}
1020
1021static void printuserflags(fu16_t flags)
1022{
1023
1024  if (flags & AIM_FLAG_UNCONFIRMED)
1025    printf("UNCONFIRMED ");
1026  if (flags & AIM_FLAG_ADMINISTRATOR)
1027    printf("ADMINISTRATOR ");
1028  if (flags & AIM_FLAG_AOL)
1029    printf("AOL ");
1030  if (flags & AIM_FLAG_OSCAR_PAY)
1031    printf("OSCAR_PAY ");
1032  if (flags & AIM_FLAG_FREE)
1033    printf("FREE ");
1034  if (flags & AIM_FLAG_AWAY)
1035    printf("AWAY ");
1036  if (flags & AIM_FLAG_ICQ)
1037    printf("ICQ ");
1038  if (flags & AIM_FLAG_WIRELESS)
1039    printf("WIRELESS ");
1040  if (flags & AIM_FLAG_ACTIVEBUDDY)
1041    printf("ACTIVEBUDDY ");
1042 
1043  return;
1044}
1045
1046static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
1047{
1048  aim_userinfo_t *userinfo;
1049  char *prof_encoding = NULL;
1050  char *prof = NULL;
1051  fu16_t inforeq = 0;
1052  owl_buddy *b;
1053  va_list ap;
1054  va_start(ap, fr);
1055  userinfo = va_arg(ap, aim_userinfo_t *);
1056  inforeq = (fu16_t)va_arg(ap, unsigned int);
1057  prof_encoding = va_arg(ap, char *);
1058  prof = va_arg(ap, char *);
1059  va_end(ap);
1060
1061  /* right now the only reason we call this is for idle times */
1062  owl_function_debugmsg("parse_userinfo sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1063  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g),
1064                                userinfo->sn);
1065  if (!b) return(1);
1066  owl_buddy_set_idle_since(b, userinfo->idletime);
1067  return(1);
1068
1069  /*
1070  printf("userinfo: sn: %s\n", userinfo->sn);
1071  printf("userinfo: warnlevel: %f\n", aim_userinfo_warnlevel(userinfo));
1072  printf("userinfo: flags: 0x%04x = ", userinfo->flags);
1073  printuserflags(userinfo->flags);
1074  printf("\n");
1075  */
1076
1077  /*
1078  printf("userinfo: membersince: %lu\n", userinfo->membersince);
1079  printf("userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1080  printf("userinfo: idletime: 0x%04x\n", userinfo->idletime);
1081  printf("userinfo: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1082  */
1083 
1084  if (inforeq == AIM_GETINFO_GENERALINFO) {
1085    owl_function_debugmsg("userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1086    owl_function_debugmsg("userinfo: prof: %s\n", prof ? prof : "[none]");
1087  } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1088    owl_function_debugmsg("userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1089    owl_function_debugmsg("userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1090  } else if (inforeq == AIM_GETINFO_CAPABILITIES) {
1091    owl_function_debugmsg("userinfo: capabilities: see above\n");
1092  } else {
1093    owl_function_debugmsg("userinfo: unknown info request\n");
1094  }
1095 
1096  return(1);
1097}
1098
1099#if 0
1100static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr)
1101{
1102  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
1103 
1104  if (!strncmp(tmpstr, "disconnect", 10)) {
1105    logout(sess);
1106  } else if (strstr(tmpstr, "goodday")) {
1107    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too."); */
1108  } else if (strstr(tmpstr, "haveicon") && priv->buddyicon) {
1109    struct aim_sendimext_args args;
1110    /* static const char iconmsg[] = {"I have an icon"}; */
1111    static const char iconmsg[] = {""};
1112   
1113    args.destsn = userinfo->sn;
1114    args.flags = AIM_IMFLAGS_HASICON;
1115    args.msg = iconmsg;
1116    args.msglen = strlen(iconmsg);
1117    args.iconlen = priv->buddyiconlen;
1118    args.iconstamp = priv->buddyiconstamp;
1119    args.iconsum = priv->buddyiconsum;
1120   
1121    /* aim_send_im_ext(sess, &args); */
1122   
1123  } else if (strstr(tmpstr, "sendbin")) {
1124    struct aim_sendimext_args args;
1125    static const unsigned char data[] = {
1126      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1127      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1128      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1129      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1130      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1131      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1132    };
1133   
1134    /*
1135     * I put this here as a demonstration of how to send
1136     * arbitrary binary data via OSCAR ICBM's without the need
1137     * for escape or baseN encoding of any sort. 
1138     *
1139     * Apparently if you set the charset to something WinAIM
1140     * doesn't recognize, it will completly ignore the message.
1141     * That is, it will not display anything in the conversation
1142     * window for the user that recieved it.
1143     *
1144     * HOWEVER, if they do not have a conversation window open
1145     * for you, a new one will be created, but it will not have
1146     * any messages in it.  Therefore sending these things could
1147     * be a great way to seemingly subliminally convince people
1148     * to talk to you...
1149     *
1150     */
1151    args.destsn = userinfo->sn;
1152    /* args.flags = AIM_IMFLAGS_CUSTOMCHARSET; */
1153    args.charset = args.charsubset = 0x4242;
1154    args.msg = data;
1155    args.msglen = sizeof(data);
1156    /* aim_send_im_ext(sess, &args); */
1157   } else if (strstr(tmpstr, "sendmulti")) {
1158    struct aim_sendimext_args args;
1159    aim_mpmsg_t mpm;
1160    static const fu16_t unidata[] = { /* "UNICODE." */
1161      0x0055, 0x004e, 0x0049, 0x0043,
1162      0x004f, 0x0044, 0x0045, 0x002e,
1163    };
1164    static const int unidatalen = 8;
1165   
1166    /*
1167     * This is how multipart messages should be sent.
1168     *
1169     * This should render as:
1170     *        "Part 1, ASCII.  UNICODE.Part 3, ASCII.  "
1171     */
1172   
1173    aim_mpmsg_init(sess, &mpm);
1174    aim_mpmsg_addascii(sess, &mpm, "Part 1, ASCII.  ");
1175    aim_mpmsg_addunicode(sess, &mpm, unidata, unidatalen);
1176    aim_mpmsg_addascii(sess, &mpm, "Part 3, ASCII.  ");
1177   
1178    args.destsn = userinfo->sn;
1179    args.flags = AIM_IMFLAGS_MULTIPART;
1180    args.mpmsg = &mpm;
1181   
1182    /* aim_send_im_ext(sess, &args); */
1183   
1184    aim_mpmsg_free(sess, &mpm);
1185   
1186  } else if (strstr(tmpstr, "sendprebin")) {
1187    static const unsigned char data[] = {
1188      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1189      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1190      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1191      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1192      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1193      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1194    };
1195    struct aim_sendimext_args args;
1196    aim_mpmsg_t mpm;
1197   
1198    /*
1199     * This demonstrates sending a human-readable preamble,
1200     * and then arbitrary binary data.
1201     *
1202     * This means that you can very inconspicuously send binary
1203     * attachments to other users.  In WinAIM, this appears as
1204     * though it only had the ASCII portion.
1205     *
1206     */
1207   
1208    aim_mpmsg_init(sess, &mpm);
1209    aim_mpmsg_addascii(sess, &mpm, "This message has binary data.");
1210    aim_mpmsg_addraw(sess, &mpm, 0x4242, 0x4242, data, sizeof(data));
1211   
1212    args.destsn = userinfo->sn;
1213    args.flags = AIM_IMFLAGS_MULTIPART;
1214    args.mpmsg = &mpm;
1215   
1216    /* aim_send_im_ext(sess, &args); */
1217    aim_mpmsg_free(sess, &mpm);
1218   
1219  } else if (strstr(tmpstr, "havefeat")) {
1220    struct aim_sendimext_args args;
1221    static const char featmsg[] = {"I have nifty features."};
1222    fu8_t features[] = {0x01, 0x01, 0x01, 0x02, 0x42, 0x43, 0x44, 0x45};
1223   
1224    args.destsn = userinfo->sn;
1225    args.flags = AIM_IMFLAGS_CUSTOMFEATURES;
1226    args.msg = featmsg;
1227    args.msglen = strlen(featmsg);
1228    args.features = features;
1229    args.featureslen = sizeof(features);
1230   
1231    /* aim_send_im_ext(sess, &args); */
1232  } else if (strstr(tmpstr, "sendicon") && priv->buddyicon) {
1233    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
1234  } else if (strstr(tmpstr, "warnme")) {
1235    /* printf("icbm: sending non-anon warning\n"); */
1236    /* aim_send_warning(sess, conn, userinfo->sn, 0); */
1237  } else if (strstr(tmpstr, "anonwarn")) {
1238    /* printf("icbm: sending anon warning\n"); */
1239    /* aim_send_warning(sess, conn, userinfo->sn, AIM_WARN_ANON); */
1240  } else if (strstr(tmpstr, "setdirectoryinfo")) {
1241    /* printf("icbm: sending backwards profile data\n"); */
1242    aim_setdirectoryinfo(sess, conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1243  } else if (strstr(tmpstr, "setinterests")) {
1244    /* printf("icbm: setting fun interests\n"); */
1245    aim_setuserinterests(sess, conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1246  } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1247    aim_reqservice(sess, conn, AIM_CONN_TYPE_CHATNAV);
1248  } else if (!strncmp(tmpstr, "create", 6)) {
1249    aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1250  } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1251    aim_conn_t *chatnavconn;
1252    if ((chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)))
1253      aim_conn_kill(sess, &chatnavconn);
1254  } else if (!strncmp(tmpstr, "join", 4)) {
1255    aim_chat_join(sess, conn, 0x0004, "worlddomination", 0x0000);
1256  } else if (!strncmp(tmpstr, "leave", 5)) {
1257    aim_chat_leaveroom(sess, "worlddomination");
1258  } else if (!strncmp(tmpstr, "getinfo", 7)) {
1259    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_GENERALINFO);
1260    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
1261    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_CAPABILITIES);
1262  } else if(strstr(tmpstr, "lookup")) {
1263    /* aim_usersearch_address(sess, conn, "mid@auk.cx"); */
1264  } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1265    /* aim_send_im(sess, priv->ohcaptainmycaptain, 0, "sendmsg 7900"); */
1266  } else if (!strncmp(tmpstr, "reqadmin", 8)) {
1267    aim_reqservice(sess, conn, AIM_CONN_TYPE_AUTH);
1268  } else if (!strncmp(tmpstr, "changenick", 10)) {
1269    aim_admin_setnick(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "diputs8  1");
1270  } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1271    aim_admin_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1272  } else if (!strncmp(tmpstr, "reqemail", 8)) {
1273    aim_admin_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1274  } else if (!strncmp(tmpstr, "changepass", 8)) {
1275    aim_admin_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1276  } else if (!strncmp(tmpstr, "setemail", 8)) {
1277    aim_admin_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1278  } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1279    int i;
1280   
1281    i = atoi(tmpstr+8);
1282    if (i < 10000) {
1283      char *newbuf;
1284      int z;
1285     
1286      newbuf = malloc(i+1);
1287      for (z = 0; z < i; z++)
1288        newbuf[z] = (z % 10)+0x30;
1289      newbuf[i] = '\0';
1290      /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK | AIM_IMFLAGS_AWAY, newbuf); */
1291      free(newbuf);
1292    }
1293  } else if (strstr(tmpstr, "seticqstatus")) {
1294    aim_setextstatus(sess, AIM_ICQ_STATE_DND);
1295  } else if (strstr(tmpstr, "rtfmsg")) {
1296    static const char rtfmsg[] = {"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\froman\\fprq2\\fcharset0 Georgia;}{\\f2\\fmodern\\fprq1\\fcharset0 MS Mincho;}{\\f3\\froman\\fprq2\\fcharset2 Symbol;}}\\viewkind4\\uc1\\pard\\f0\\fs20 Test\\f1 test\\f2\fs44 test\\f3\\fs20 test\\f0\\par}"};
1297    struct aim_sendrtfmsg_args rtfargs;
1298   
1299    memset(&rtfargs, 0, sizeof(rtfargs));
1300    rtfargs.destsn = userinfo->sn;
1301    rtfargs.fgcolor = 0xffffffff;
1302    rtfargs.bgcolor = 0x00000000;
1303    rtfargs.rtfmsg = rtfmsg;
1304    /* aim_send_rtfmsg(sess, &rtfargs); */
1305  } else {
1306    /* printf("unknown command.\n"); */
1307    aim_add_buddy(sess, conn, userinfo->sn);
1308  } 
1309 
1310  return 0;
1311}
1312#endif
1313
1314/*
1315 * Channel 1: Standard Message
1316 */
1317static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args)
1318{
1319  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
1320  owl_message *m;
1321  char *stripmsg, *nz_screenname, *wrapmsg;
1322  char realmsg[8192+1] = {""};
1323  /* int clienttype = AIM_CLIENTTYPE_UNKNOWN; */
1324
1325  /* clienttype = aim_fingerprintclient(args->features, args->featureslen); */
1326
1327  /*
1328  printf("icbm: sn = \"%s\"\n", userinfo->sn);
1329  printf("icbm: probable client type: %d\n", clienttype);
1330  printf("icbm: warnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1331  printf("icbm: flags = 0x%04x = ", userinfo->flags);
1332  printuserflags(userinfo->flags);
1333  printf("\n");
1334  */
1335
1336  /*
1337  printf("icbm: membersince = %lu\n", userinfo->membersince);
1338  printf("icbm: onlinesince = %lu\n", userinfo->onlinesince);
1339  printf("icbm: idletime = 0x%04x\n", userinfo->idletime);
1340  printf("icbm: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1341  */
1342
1343  /*
1344  printf("icbm: icbmflags = ");
1345  if (args->icbmflags & AIM_IMFLAGS_AWAY) printf("away ");
1346  if (args->icbmflags & AIM_IMFLAGS_ACK) printf("ackrequest ");
1347  if (args->icbmflags & AIM_IMFLAGS_OFFLINE) printf("offline ");
1348  if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) printf("buddyreq ");
1349  if (args->icbmflags & AIM_IMFLAGS_HASICON) printf("hasicon ");
1350  printf("\n");
1351  */
1352
1353  /*
1354  if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET) {
1355  printf("icbm: encoding flags = {%04x, %04x}\n", args->charset, args->charsubset);
1356  }
1357  */
1358 
1359  /*
1360   * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1361   * characters with their equivelent HTML entity.
1362   */
1363  if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1364    int i;
1365   
1366    for (i=0; i<args->msglen; i+=2) {
1367      fu16_t uni;
1368
1369      uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
1370      if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
1371        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
1372      } else { /* something else, do UNICODE entity */
1373        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
1374      }
1375    }
1376  } else {
1377    /*
1378     * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1379     * no need to do anything special here.  Most
1380     * terminals/whatever will be able to display such characters
1381     * unmodified.
1382     *
1383     * Beware that PC-ASCII 128 through 159 are _not_ actually
1384     * defined in ASCII or ISO 8859-1, and you should send them as
1385     * UNICODE.  WinAIM will send these characters in a UNICODE
1386     * message, so you need to do so as well.
1387     *
1388     * You may not think it necessary to handle UNICODE messages. 
1389     * You're probably wrong.  For one thing, Microsoft "Smart
1390     * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1391     * but real UNICODE). If you don't parse UNICODE at all, your
1392     * users will get a blank message instead of the message
1393     * containing Smart Quotes.
1394     *
1395     */
1396    strncpy(realmsg, args->msg, sizeof(realmsg));
1397  }
1398
1399  /* create a message, and put it on the message queue */
1400  stripmsg=owl_text_htmlstrip(realmsg);
1401  wrapmsg=owl_text_wordwrap(stripmsg, 70);
1402  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1403  m=owl_malloc(sizeof(owl_message));
1404  owl_message_create_aim(m,
1405                         nz_screenname,
1406                         owl_global_get_aim_screenname(&g),
1407                         wrapmsg,
1408                         OWL_MESSAGE_DIRECTION_IN,
1409                         0);
1410  owl_global_messagequeue_addmsg(&g, m);
1411  owl_free(stripmsg);
1412  owl_free(wrapmsg);
1413  owl_free(nz_screenname);
1414
1415  return(1);
1416 
1417  /* printf("icbm: message: %s\n", realmsg); */
1418 
1419  if (args->icbmflags & AIM_IMFLAGS_MULTIPART) {
1420    aim_mpmsg_section_t *sec;
1421    int z;
1422
1423    /* printf("icbm: multipart: this message has %d parts\n", args->mpmsg.numparts); */
1424   
1425    for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++) {
1426      if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff)) {
1427        /* printf("icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, msg = %s\n", z, sec->charset, sec->charsubset, sec->data); */
1428      } else {
1429        /* printf("icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, binary or UNICODE data\n", z, sec->charset, sec->charsubset); */
1430      }
1431    }
1432  }
1433 
1434  if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1435    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon"); */
1436    /* printf("icbm: their icon: iconstamp = %ld, iconlen = 0x%08lx, iconsum = 0x%04x\n", args->iconstamp, args->iconlen, args->iconsum); */
1437  }
1438
1439  /*
1440  if (realmsg) {
1441    int i = 0;
1442    while (realmsg[i] == '<') {
1443      if (realmsg[i] == '<') {
1444        while (realmsg[i] != '>')
1445          i++;
1446        i++;
1447      }
1448    }
1449    tmpstr = realmsg+i;
1450    faimtest_handlecmd(sess, conn, userinfo, tmpstr);
1451  }
1452  */
1453 
1454  if (priv->buddyicon && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
1455    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
1456  }
1457 
1458  return(1);
1459}
1460
1461/*
1462 * Channel 2: Rendevous Request
1463 */
1464static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args)
1465{
1466  /*
1467  printf("rendezvous: source sn = %s\n", userinfo->sn);
1468  printf("rendezvous: \twarnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1469  printf("rendezvous: \tclass = 0x%04x = ", userinfo->flags);
1470  printuserflags(userinfo->flags);
1471  printf("\n");
1472 
1473  printf("rendezvous: \tonlinesince = %lu\n", userinfo->onlinesince);
1474  printf("rendezvous: \tidletime = 0x%04x\n", userinfo->idletime);
1475 
1476  printf("rendezvous: message/description = %s\n", args->msg);
1477  printf("rendezvous: encoding = %s\n", args->encoding);
1478  printf("rendezvous: language = %s\n", args->language);
1479  */
1480 
1481  if (args->reqclass == AIM_CAPS_SENDFILE) {
1482    /* printf("send file!\n"); */
1483  } else if (args->reqclass == AIM_CAPS_CHAT) {
1484    owl_function_debugmsg("chat invite: %s, %i, %i", args->info.chat.roominfo.name, args->info.chat.roominfo.exchange, args->info.chat.roominfo.instance);
1485    /*
1486    printf("chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1487    printf("chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1488    printf("chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1489    */
1490    /* Automatically join room... */
1491    /* printf("chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name); */
1492
1493    /* aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance); */
1494  } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
1495    /* printf("Buddy Icon from %s, length = %lu\n", userinfo->sn, args->info.icon.length); */
1496  } else if (args->reqclass == AIM_CAPS_ICQRTF) {
1497    /* printf("RTF message from %s: (fgcolor = 0x%08lx, bgcolor = 0x%08lx) %s\n", userinfo->sn, args->info.rtfmsg.fgcolor, args->info.rtfmsg.bgcolor, args->info.rtfmsg.rtfmsg); */
1498  } else {
1499    /* printf("icbm: unknown reqclass (%d)\n", args->reqclass); */
1500  }
1501  return 1;
1502}
1503
1504static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
1505{
1506  fu16_t channel;
1507  aim_userinfo_t *userinfo;
1508  va_list ap;
1509  int ret = 0;
1510 
1511  va_start(ap, fr);
1512  channel = (fu16_t)va_arg(ap, unsigned int);
1513  userinfo = va_arg(ap, aim_userinfo_t *);
1514 
1515  if (channel == 1) {
1516    struct aim_incomingim_ch1_args *args;
1517    args = va_arg(ap, struct aim_incomingim_ch1_args *);
1518    ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
1519  } else if (channel == 2) {
1520    struct aim_incomingim_ch2_args *args;
1521    args = va_arg(ap, struct aim_incomingim_ch2_args *);
1522    ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
1523  } else {
1524    /* printf("unsupported channel 0x%04x\n", channel); */
1525  }
1526  va_end(ap);
1527  /* printf("icbm: done with ICBM handling (ret = %d)\n", ret); */
1528  return 1;
1529}
1530
1531static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
1532{
1533  aim_userinfo_t *userinfo;
1534  char *nz_screenname;
1535  owl_buddy *b;
1536  owl_buddylist *bl;
1537  va_list ap;
1538  va_start(ap, fr);
1539  userinfo = va_arg(ap, aim_userinfo_t *);
1540  va_end(ap);
1541
1542  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1543  bl=owl_global_get_buddylist(&g);
1544 
1545  owl_buddylist_oncoming(owl_global_get_buddylist(&g), nz_screenname);
1546
1547  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1548    /*  */
1549  }
1550
1551  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g), nz_screenname);
1552  if (!b) {
1553    owl_function_debugmsg("Error: parse_oncoming setting idle time with no buddy present.");
1554    return(1);
1555  }
1556  if (userinfo->idletime==0) {
1557    owl_buddy_set_unidle(b);
1558  } else {
1559    owl_buddy_set_idle(b);
1560    owl_buddy_set_idle_since(b, userinfo->idletime);
1561  }
1562
1563  if (userinfo->flags & AIM_FLAG_AWAY) {
1564    owl_function_debugmsg("parse_oncoming sn: %s away flag!", userinfo->sn);
1565  }
1566 
1567  owl_function_debugmsg("parse_oncoming sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1568   
1569  owl_free(nz_screenname);
1570 
1571  /*
1572    printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1573    time(NULL),
1574    userinfo->sn, userinfo->flags,
1575    (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1576    (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1577    (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1578    (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1579    (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1580    (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1581    (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1582    (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1583    (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1584    userinfo->capabilities);
1585  */
1586  return(1);
1587}
1588
1589static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
1590{
1591  aim_userinfo_t *userinfo;
1592  char *nz_screenname;
1593  va_list ap;
1594 
1595  va_start(ap, fr);
1596  userinfo = va_arg(ap, aim_userinfo_t *);
1597  va_end(ap);
1598
1599  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1600  owl_buddylist_offgoing(owl_global_get_buddylist(&g), nz_screenname);
1601  owl_free(nz_screenname);
1602
1603  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1604    owl_function_debugmsg("parse_offgoing sn: %s idle time %i", userinfo->sn, userinfo->idletime);
1605  }
1606
1607  /*
1608  printf("%ld  %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1609         time(NULL),
1610         userinfo->sn, userinfo->flags,
1611         (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1612         (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1613         (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1614         (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1615         (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1616         (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1617         (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1618         (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1619         (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1620         userinfo->capabilities);
1621  */
1622 
1623  return 1;
1624}
1625
1626/* Used by chat as well. */
1627int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
1628{
1629  va_list ap;
1630  fu16_t reason;
1631 
1632  va_start(ap, fr);
1633  reason = (fu16_t)va_arg(ap, unsigned int);
1634  va_end(ap);
1635 
1636  /* printf("snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1637  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
1638 
1639  return 1;
1640}
1641
1642static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
1643{
1644  va_list ap;
1645  char *destsn;
1646  fu16_t reason;
1647 
1648  va_start(ap, fr);
1649  reason = (fu16_t)va_arg(ap, unsigned int);
1650  destsn = va_arg(ap, char *);
1651  va_end(ap);
1652 
1653  /* printf("message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1654  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
1655
1656  if (reason==4) {
1657    owl_function_adminmsg("", "Could not send AIM message, user not logged on");
1658  }
1659 
1660  return 1;
1661}
1662
1663static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
1664{
1665  va_list ap;
1666  char *destsn;
1667  fu16_t reason;
1668 
1669  va_start(ap, fr);
1670  reason = (fu16_t)va_arg(ap, unsigned int);
1671  destsn = va_arg(ap, char *);
1672  va_end(ap);
1673 
1674  /* printf("user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1675  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
1676 
1677  return 1;
1678}
1679
1680static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1681{
1682  /*
1683  static char *missedreasons[] = {
1684    "Invalid (0)",
1685    "Message too large",
1686    "Rate exceeded",
1687    "Evil Sender",
1688    "Evil Receiver"
1689  };
1690  static int missedreasonslen = 5; */
1691 
1692  va_list ap;
1693  fu16_t chan, nummissed, reason;
1694  aim_userinfo_t *userinfo;
1695 
1696  va_start(ap, fr);
1697  chan = (fu16_t)va_arg(ap, unsigned int);
1698  userinfo = va_arg(ap, aim_userinfo_t *);
1699  nummissed = (fu16_t)va_arg(ap, unsigned int);
1700  reason = (fu16_t)va_arg(ap, unsigned int);
1701  va_end(ap);
1702 
1703  /* printf("missed %d messages from %s on channel %d (reason %d: %s)\n", nummissed, userinfo->sn, chan, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown"); */
1704 
1705  return 1;
1706}
1707
1708/*
1709 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1710 */
1711static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1712{
1713  va_list ap;
1714  fu16_t type;
1715  char *sn = NULL;
1716 
1717  va_start(ap, fr);
1718  type = (fu16_t)va_arg(ap, unsigned int);
1719  sn = va_arg(ap, char *);
1720  va_end(ap);
1721 
1722  /* printf("msgack: 0x%04x / %s\n", type, sn); */
1723 
1724  return 1;
1725}
1726
1727static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
1728{
1729  /*
1730  static char *codes[5] = {
1731    "invalid",
1732    "change",
1733    "warning",
1734    "limit",
1735    "limit cleared"
1736  };
1737  */
1738  va_list ap;
1739  fu16_t code, rateclass;
1740  fu32_t windowsize, clear, alert, limit, disconnect;
1741  fu32_t currentavg, maxavg;
1742 
1743  va_start(ap, fr); 
1744 
1745  /* See code explanations below */
1746  code = (fu16_t)va_arg(ap, unsigned int);
1747 
1748  /*
1749   * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1750   */
1751  rateclass = (fu16_t)va_arg(ap, unsigned int);
1752 
1753  /*
1754   * Not sure what this is exactly.  I think its the temporal
1755   * relation factor (ie, how to make the rest of the numbers
1756   * make sense in the real world).
1757   */
1758  windowsize = va_arg(ap, fu32_t);
1759 
1760  /* Explained below */
1761  clear = va_arg(ap, fu32_t);
1762  alert = va_arg(ap, fu32_t);
1763  limit = va_arg(ap, fu32_t);
1764  disconnect = va_arg(ap, fu32_t);
1765  currentavg = va_arg(ap, fu32_t);
1766  maxavg = va_arg(ap, fu32_t);
1767 
1768  va_end(ap);
1769 
1770  /*
1771  printf("rate %s (rate class 0x%04x): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
1772         (code < 5)?codes[code]:"invalid",
1773         rateclass,
1774         currentavg, maxavg,
1775         alert, clear,
1776         limit, disconnect,
1777         windowsize);
1778  */
1779  return 1;
1780}
1781
1782static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
1783{
1784  va_list ap;
1785  fu16_t newevil;
1786  aim_userinfo_t *userinfo;
1787 
1788  va_start(ap, fr);
1789  newevil = (fu16_t)va_arg(ap, unsigned int);
1790  userinfo = va_arg(ap, aim_userinfo_t *);
1791  va_end(ap);
1792 
1793  /*
1794   * Evil Notifications that are lacking userinfo->sn are anon-warns
1795   * if they are an evil increases, but are not warnings at all if its
1796   * a decrease (its the natural backoff happening).
1797   *
1798   * newevil is passed as an int representing the new evil value times
1799   * ten.
1800   */
1801  /* printf("evil level change: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous"); */
1802 
1803  return 1;
1804}
1805
1806static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
1807{
1808  va_list ap;
1809  char *address, *SNs;
1810  int num;
1811  /* int i; */
1812 
1813  va_start(ap, fr);
1814  address = va_arg(ap, char *);
1815  num = va_arg(ap, int);
1816  SNs = va_arg(ap, char *);
1817  va_end(ap);
1818 
1819  /* printf("E-Mail Search Results for %s: ", address);
1820 
1821  for(i = 0; i < num; i++)
1822    printf("%s, ", &SNs[i*(MAXSNLEN+1)]);
1823  printf("\n");
1824  */
1825 
1826  return 1;
1827}
1828
1829static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
1830{
1831  va_list ap;
1832  char *address;
1833 
1834  va_start(ap, fr);
1835  address = va_arg(ap, char *);
1836  va_end(ap);
1837 
1838  /* printf("E-Mail Search Results for %s: No Results or Invalid Email\n", address); */
1839 
1840  return 1;
1841}
1842
1843static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...)
1844{
1845  va_list ap;
1846  char *msg, *url;
1847  fu16_t width, height, delay;
1848 
1849  va_start(ap, fr);
1850  msg = va_arg(ap, char *);
1851  url = va_arg(ap, char *);
1852  width = va_arg(ap, unsigned int);
1853  height = va_arg(ap, unsigned int);
1854  delay = va_arg(ap, unsigned int);
1855  va_end(ap);
1856 
1857  /* printf("popup: (%dx%x:%d) %s (%s)\n", width, height, delay, msg, url); */
1858 
1859  return 1;
1860}
1861
1862static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
1863{
1864  aim_sendpauseack(sess, fr->conn);
1865  return 1;
1866}
1867
1868static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
1869{
1870  va_list ap;
1871  aim_conn_t *bosconn;
1872  char *bosip;
1873  fu8_t *cookie;
1874 
1875  va_start(ap, fr);
1876  bosip = va_arg(ap, char *);
1877  cookie = va_arg(ap, fu8_t *);
1878  va_end(ap);
1879 
1880  /* printf("migration in progress -- new BOS is %s -- disconnecting\n", bosip); */
1881  aim_conn_kill(sess, &fr->conn);
1882 
1883  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
1884    /* printf("migrate: could not connect to BOS: internal error\n"); */
1885    return 1;
1886  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
1887    /* printf("migrate: could not connect to BOS\n"); */
1888    aim_conn_kill(sess, &bosconn);
1889    return 1;
1890  }
1891 
1892  /* Login will happen all over again. */
1893  addcb_bos(sess, bosconn);
1894  /* aim_sendcookie(sess, bosconn, cookie); */
1895  return 1;
1896}
1897
1898static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...)
1899{
1900  /* printf("got SSI rights, requesting data\n"); */
1901  /* aim_ssi_reqdata(sess, fr->conn, 0, 0x0000); */
1902  aim_ssi_reqdata(sess);
1903 
1904  return(1);
1905}
1906
1907static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...)
1908{
1909  va_list ap;
1910  fu8_t fmtver;
1911  fu16_t itemcount;
1912  fu32_t stamp;
1913  struct aim_ssi_item *list;
1914  struct aim_ssi_item *curitem;
1915  /* struct aim_ssi_item *l; */
1916 
1917  va_start(ap, fr);
1918  fmtver = va_arg(ap, unsigned int);
1919  itemcount = va_arg(ap, unsigned int);
1920  stamp = va_arg(ap, fu32_t);
1921  list = va_arg(ap, struct aim_ssi_item *);
1922  va_end(ap);
1923 
1924  /* printf("got SSI data: (0x%02x, %d items, %ld)\n", fmtver, itemcount, stamp); */
1925  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
1926    /* for (l = list; l; l = l->next) { */
1927    /* printf("\t0x%04x (%s) - 0x%04x/0x%04x\n", l->type, l->name, l->gid, l->bid); */
1928    /* printf("I would have printed data here!\n"); */
1929  }
1930 
1931  aim_ssi_enable(sess);
1932 
1933  return 1;
1934}
1935
1936static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...)
1937{
1938  /* printf("server says we have the latest SSI data already\n"); */
1939  /* aim_ssi_enable(sess, fr->conn); */
1940  aim_ssi_enable(sess);
1941  return 1;
1942}
1943
1944static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
1945{
1946  va_list ap;
1947  struct aim_icq_offlinemsg *msg;
1948 
1949  va_start(ap, fr);
1950  msg = va_arg(ap, struct aim_icq_offlinemsg *);
1951  va_end(ap);
1952 
1953  if (msg->type == 0x0001) {
1954    /* printf("offline message from %ld at %d/%d/%d %02d:%02d : %s\n", msg->sender, msg->year, msg->month, msg->day, msg->hour, msg->minute, msg->msg); */
1955  } else {
1956    /* printf("unknown offline message type 0x%04x\n", msg->type); */
1957  }
1958  return 1;
1959}
1960
1961static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
1962{
1963  /* Tell the server to delete them. */
1964  aim_icq_ackofflinemsgs(sess);
1965  return 1;
1966}
1967
1968
1969/******************** chat.c **************************/
1970
1971
1972static int faimtest_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
1973{
1974  va_list ap;
1975  aim_userinfo_t *userinfo;
1976  int count;
1977  /* int i; */
1978 
1979  va_start(ap, fr);
1980  count = va_arg(ap, int);
1981  userinfo = va_arg(ap, aim_userinfo_t *);
1982  va_end(ap);
1983
1984  owl_function_debugmsg("In faimtest_chat_join");
1985  /*
1986  printf("chat: %s:  New occupants have joined:\n", aim_chat_getname(fr->conn));
1987  for (i = 0; i < count; i++)
1988    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
1989  */
1990  return 1;
1991}
1992
1993static int faimtest_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
1994{
1995  aim_userinfo_t *userinfo;
1996  va_list ap;
1997  int count;
1998  /* int i; */
1999
2000 
2001  va_start(ap, fr);
2002  count = va_arg(ap, int);
2003  userinfo = va_arg(ap, aim_userinfo_t *);
2004  va_end(ap);
2005 
2006  /*
2007    printf("chat: %s:  Some occupants have left:\n", aim_chat_getname(fr->conn));
2008   
2009    for (i = 0; i < count; i++)
2010    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
2011  */
2012  return 1;
2013}
2014
2015static int faimtest_chat_infoupdate(aim_session_t *sess, aim_frame_t *fr, ...)
2016{
2017  va_list ap;
2018  aim_userinfo_t *userinfo;
2019  struct aim_chat_roominfo *roominfo;
2020  char *roomname;
2021  int usercount;
2022  char *roomdesc;
2023  fu16_t flags, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
2024  fu32_t creationtime;
2025  const char *croomname;
2026  /* int i; */
2027 
2028  croomname = aim_chat_getname(fr->conn);
2029 
2030  va_start(ap, fr);
2031  roominfo = va_arg(ap, struct aim_chat_roominfo *);
2032  roomname = va_arg(ap, char *);
2033  usercount = va_arg(ap, int);
2034  userinfo = va_arg(ap, aim_userinfo_t *);
2035  roomdesc = va_arg(ap, char *);
2036  flags = (fu16_t)va_arg(ap, unsigned int);
2037  creationtime = va_arg(ap, fu32_t);
2038  maxmsglen = (fu16_t)va_arg(ap, unsigned int);
2039  unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
2040  unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
2041  maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
2042  va_end(ap);
2043
2044  owl_function_debugmsg("In faimtest_chat_infoupdate");
2045  /*
2046  printf("chat: %s:  info update:\n", croomname);
2047  printf("chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", croomname, roominfo->exchange, roominfo->name, roominfo->instance);
2048  printf("chat: %s:  \tRoomname: %s\n", croomname, roomname);
2049  printf("chat: %s:  \tRoomdesc: %s\n", croomname, roomdesc);
2050  printf("chat: %s:  \tOccupants: (%d)\n", croomname, usercount);
2051
2052  for (i = 0; i < usercount; i++)
2053    printf("chat: %s:  \t\t%s\n", croomname, userinfo[i].sn);
2054 
2055  owl_function_debugmsg("chat: %s:  \tRoom flags: 0x%04x (%s%s%s%s)\n",
2056         croomname, flags,
2057         (flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
2058         (flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
2059         (flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
2060         (flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
2061  printf("chat: %s:  \tCreation time: %lu (time_t)\n", croomname, creationtime);
2062  printf("chat: %s:  \tUnknown_d2: 0x%04x\n", croomname, unknown_d2);
2063  printf("chat: %s:  \tUnknown_d5: 0x%02x\n", croomname, unknown_d5);
2064  printf("chat: %s:  \tMax message length: %d bytes\n", croomname, maxmsglen);
2065  printf("chat: %s:  \tMax visible message length: %d bytes\n", croomname, maxvisiblemsglen);
2066  */
2067 
2068  return(1);
2069}
2070
2071static int faimtest_chat_incomingmsg(aim_session_t *sess, aim_frame_t *fr, ...)
2072{
2073  va_list ap;
2074  aim_userinfo_t *userinfo;
2075  char *msg;
2076  char tmpbuf[1152];
2077 
2078  va_start(ap, fr);
2079  userinfo = va_arg(ap, aim_userinfo_t *);     
2080  msg = va_arg(ap, char *);
2081  va_end(ap);
2082
2083  owl_function_debugmsg("in faimtest_chat_incomingmsg");
2084
2085  /*
2086  printf("chat: %s: incoming msg from %s: %s\n", aim_chat_getname(fr->conn), userinfo->sn, msg);
2087  */
2088 
2089  /*
2090   * Do an echo for testing purposes.  But not for ourselves ("oops!")
2091   */
2092  if (strcmp(userinfo->sn, sess->sn) != 0) {
2093    /* sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg); */
2094    aim_chat_send_im(sess, fr->conn, 0, tmpbuf, strlen(tmpbuf));
2095  }
2096 
2097  return 1;
2098}
2099
2100static int faimtest_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...)
2101{
2102  fu16_t type;
2103  va_list ap;
2104 
2105  va_start(ap, fr);
2106  type = (fu16_t)va_arg(ap, unsigned int);
2107
2108  owl_function_debugmsg("in faimtest_chatnav_info");
2109 
2110  if (type == 0x0002) {
2111    int maxrooms;
2112    struct aim_chat_exchangeinfo *exchanges;
2113    int exchangecount;
2114    /* int i; */
2115   
2116    maxrooms = va_arg(ap, int);
2117    exchangecount = va_arg(ap, int);
2118    exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
2119    va_end(ap);
2120
2121    /*
2122    printf("chat info: Chat Rights:\n");
2123    printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
2124    printf("chat info: \tExchange List: (%d total)\n", exchangecount);
2125    for (i = 0; i < exchangecount; i++) {
2126      printf("chat info: \t\t%x: %s (%s/%s) (0x%04x = %s%s%s%s)\n",
2127             exchanges[i].number,
2128             exchanges[i].name,
2129             exchanges[i].charset1,
2130             exchanges[i].lang1,
2131             exchanges[i].flags,
2132             (exchanges[i].flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
2133             (exchanges[i].flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
2134             (exchanges[i].flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
2135             (exchanges[i].flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
2136    }
2137    */
2138  } else if (type == 0x0008) {
2139    char *fqcn, *name, *ck;
2140    fu16_t instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
2141    fu8_t createperms;
2142    fu32_t createtime;
2143   
2144    fqcn = va_arg(ap, char *);
2145    instance = (fu16_t)va_arg(ap, unsigned int);
2146    exchange = (fu16_t)va_arg(ap, unsigned int);
2147    flags = (fu16_t)va_arg(ap, unsigned int);
2148    createtime = va_arg(ap, fu32_t);
2149    maxmsglen = (fu16_t)va_arg(ap, unsigned int);
2150    maxoccupancy = (fu16_t)va_arg(ap, unsigned int);
2151    createperms = (fu8_t)va_arg(ap, unsigned int);
2152    unknown = (fu16_t)va_arg(ap, unsigned int);
2153    name = va_arg(ap, char *);
2154    ck = va_arg(ap, char *);
2155    va_end(ap);
2156   
2157    /* printf("received room create reply for %s/0x%04x\n", fqcn, exchange); */
2158   
2159  } else {
2160    va_end(ap);
2161    /* printf("chatnav info: unknown type (%04x)\n", type); */
2162  }
2163 
2164  return 1;
2165}
2166
2167static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
2168{
2169
2170  owl_function_debugmsg("in faimtest_conninitdone_chat");
2171 
2172  aim_clientready(sess, fr->conn);
2173 
2174  if (fr->conn->type == AIM_CONN_TYPE_CHATNAV) {
2175    /* printf("chatnav ready\n"); */
2176    aim_conn_addhandler(sess, fr->conn, 0x000d, 0x0001, faimtest_parse_genericerr, 0);
2177    aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
2178    aim_chatnav_reqrights(sess, fr->conn);
2179  } else if (fr->conn->type == AIM_CONN_TYPE_CHAT) {
2180    /* printf("chat ready\n"); */
2181    owl_function_debugmsg("Chat ready");
2182    aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, faimtest_parse_genericerr, 0);
2183    aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
2184    aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
2185    aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
2186    aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
2187  }
2188  return 1;
2189}
2190
2191void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
2192{
2193  aim_conn_t *tstconn;
2194
2195  owl_function_debugmsg("in faimtest_chatnav_redirect");
2196 
2197  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, redir->ip);
2198  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
2199    /* printf("unable to connect to chat(nav) server\n"); */
2200    if (tstconn)
2201      aim_conn_kill(sess, &tstconn);
2202    return;
2203  }
2204 
2205  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
2206  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
2207  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
2208  /* printf("chatnav: connected\n"); */
2209  return;
2210}
2211
2212/* XXX this needs instance too */
2213void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
2214{
2215  aim_conn_t *tstconn;
2216
2217  owl_function_debugmsg("in chat_redirect");
2218 
2219  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, redir->ip);
2220  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
2221    /* printf("unable to connect to chat server\n"); */
2222    if (tstconn) aim_conn_kill(sess, &tstconn);
2223    return; 
2224  }             
2225  /* printf("chat: connected to %s instance %d on exchange %d\n", redir->chat.room, redir->chat.instance, redir->chat.exchange); */
2226 
2227  /*
2228   * We must do this to attach the stored name to the connection!
2229   */
2230  aim_chat_attachname(tstconn, redir->chat.exchange, redir->chat.room, redir->chat.instance);
2231  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
2232  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
2233  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
2234  return;       
2235}
2236
2237
2238/****************************************/
2239
2240/*
2241static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
2242        struct gaim_connection *gc = sess->aux_data;
2243        struct oscar_data *od = gc->proto_data;
2244        aim_userinfo_t *info;
2245        time_t time_idle = 0, signon = 0;
2246        int type = 0;
2247        int caps = 0;
2248        char *tmp;
2249
2250        va_list ap;
2251        va_start(ap, fr);
2252        info = va_arg(ap, aim_userinfo_t *);
2253        va_end(ap);
2254
2255        if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES)
2256                caps = info->capabilities;
2257        if (info->flags & AIM_FLAG_ACTIVEBUDDY)
2258                type |= UC_AB;
2259
2260        if ((!od->icq) && (info->present & AIM_USERINFO_PRESENT_FLAGS)) {
2261                        if (info->flags & AIM_FLAG_UNCONFIRMED)
2262                                type |= UC_UNCONFIRMED;
2263                        if (info->flags & AIM_FLAG_ADMINISTRATOR)
2264                                type |= UC_ADMIN;
2265                        if (info->flags & AIM_FLAG_AOL)
2266                                type |= UC_AOL;
2267                        if (info->flags & AIM_FLAG_FREE)
2268                                type |= UC_NORMAL;
2269                        if (info->flags & AIM_FLAG_AWAY)
2270                                type |= UC_UNAVAILABLE;
2271                        if (info->flags & AIM_FLAG_WIRELESS)
2272                                type |= UC_WIRELESS;
2273        }
2274        if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
2275                type = (info->icqinfo.status << 16);
2276                if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
2277                      (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
2278                        type |= UC_UNAVAILABLE;
2279                }
2280        }
2281
2282        if (caps & AIM_CAPS_ICQ)
2283                caps ^= AIM_CAPS_ICQ;
2284
2285        if (info->present & AIM_USERINFO_PRESENT_IDLE) {
2286                time(&time_idle);
2287                time_idle -= info->idletime*60;
2288        }
2289
2290        if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
2291                signon = time(NULL) - info->sessionlen;
2292
2293        tmp = g_strdup(normalize(gc->username));
2294        if (!strcmp(tmp, normalize(info->sn)))
2295                g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", info->sn);
2296        g_free(tmp);
2297
2298        serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon,
2299                        time_idle, type, caps);
2300
2301        return 1;
2302}
2303*/
Note: See TracBrowser for help on using the repository browser.