source: aim.c @ 257a22f

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