source: aim.c @ f4d0975

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