source: aim.c @ c93b8b5

release-1.10release-1.7release-1.8release-1.9
Last change on this file since c93b8b5 was c5873be, checked in by Nelson Elhage <nelhage@mit.edu>, 14 years ago
aim: Don't send passwords to the debug log. Signed-off-by: Geoffrey Thomas <geofft@mit.edu>
  • Property mode set to 100644
File size: 59.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 *screenname;
10  char *password;
11  char *server;
12  int connected;
13};
14
15static const char *msgerrreasons[] = {
16        "Invalid error",
17        "Invalid SNAC",
18        "Rate to host",
19        "Rate to client",
20        "Not logged on",
21        "Service unavailable",
22        "Service not defined",
23        "Obsolete SNAC",
24        "Not supported by host",
25        "Not supported by client",
26        "Refused by client",
27        "Reply too big",
28        "Responses lost",
29        "Request denied",
30        "Busted SNAC payload",
31        "Insufficient rights",
32        "In local permit/deny",
33        "Too evil (sender)",
34        "Too evil (receiver)",
35        "User temporarily unavailable",
36        "No match",
37        "List overflow",
38        "Request ambiguous",
39        "Queue full",
40        "Not while on AOL",
41};
42static int msgerrreasonslen = 25;
43
44static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
45static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...);
46static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...);
47int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...);
48int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...);
49void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn);
50static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...);
51static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...);
52static int conninitdone_chat     (aim_session_t *, aim_frame_t *, ...);
53int logout(aim_session_t *sess);
54
55static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...);
56static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...);
57static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...);
58static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...);
59static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...);
60static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...);
61static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...);
62static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...);
63static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...);
64/* static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); */
65static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...);
66/* static void printuserflags(fu16_t flags); */
67static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...);
68static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args);
69static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args);
70static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...);
71static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...);
72static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...);
73int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...);
74static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...);
75static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...);
76static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...);
77static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...);
78static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...);
79static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...);
80static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...);
81static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...);
82static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...);
83static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...);
84static int migrate(aim_session_t *sess, aim_frame_t *fr, ...);
85static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...);
86static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...);
87static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...);
88static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...);
89static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...);
90/*
91static int faimtest_ssi_parseerr     (aim_session_t *, aim_frame_t *, ...);
92static int faimtest_ssi_parserights  (aim_session_t *, aim_frame_t *, ...);
93static int faimtest_ssi_parselist    (aim_session_t *, aim_frame_t *, ...);
94static int faimtest_ssi_parseack     (aim_session_t *, aim_frame_t *, ...);
95static int faimtest_ssi_authgiven    (aim_session_t *, aim_frame_t *, ...);
96static int faimtest_ssi_authrequest  (aim_session_t *, aim_frame_t *, ...);
97static int faimtest_ssi_authreply    (aim_session_t *, aim_frame_t *, ...);
98static int faimtest_ssi_gotadded     (aim_session_t *, aim_frame_t *, ...);
99*/
100
101void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
102void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
103
104/*****************************************************************/
105
106void owl_aim_init(void)
107{
108  /* this has all been moved to owl_aim_login, but we'll leave the
109   * function here, in case there's stuff we want to init in the
110   * future.  It's still called by Owl.
111   */
112     
113}
114
115void owl_aim_send_nop(owl_timer *t, void *data) {
116    if(owl_global_is_doaimevents(&g)) {
117        aim_session_t *sess = owl_global_get_aimsess(&g);
118        aim_flap_nop(sess, aim_getconn_type(sess, AIM_CONN_TYPE_BOS));
119    }
120}
121
122
123int owl_aim_login(const char *screenname, const char *password)
124{
125  struct owlfaim_priv *priv;
126  aim_conn_t *conn;
127  aim_session_t *sess;
128
129  sess=owl_global_get_aimsess(&g);
130
131  aim_session_init(sess, TRUE, 0);
132  aim_setdebuggingcb(sess, faimtest_debugcb);
133  aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
134 
135  /* this will leak, I know and just don't care right now */
136  priv=owl_malloc(sizeof(struct owlfaim_priv));
137  memset(priv, 0, sizeof(struct owlfaim_priv));
138
139  priv->screenname = owl_strdup(screenname);
140  priv->password = owl_strdup(password);
141  priv->server = owl_strdup(FAIM_LOGIN_SERVER);
142  sess->aux_data = priv;
143
144  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, priv->server ? priv->server : FAIM_LOGIN_SERVER);
145  /*  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); */
146  if (!conn) {
147    owl_function_error("owl_aim_login: connection error during AIM login\n");
148    owl_global_set_aimnologgedin(&g);
149    owl_global_set_no_doaimevents(&g);
150    return (-1);
151  }
152
153  /*
154  else if (conn->fd == -1) {
155    if (conn->status & AIM_CONN_STATUS_RESOLVERR) {
156      owl_function_error("owl_aim_login: could not resolve authorize name");
157    } else if (conn->status & AIM_CONN_STATUS_CONNERR) {
158      owl_function_error("owl_aim_login: could not connect to authorizer");
159    } else {
160      owl_function_error("owl_aim_login: unknown connection error");
161    }
162    owl_global_set_aimnologgedin(&g);
163    owl_global_set_no_doaimevents(&g);
164    aim_conn_kill(sess, &conn);
165    return(-1);
166  }
167  */
168
169   
170  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
171  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
172
173  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_AUTHRESPONSE, faimtest_parse_login, 0);
174  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_LOGINRESPONSE, faimtest_parse_authresp, 0);
175  /* aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); */
176  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); */
177  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); */
178   
179  /* start processing AIM events */
180  owl_global_set_doaimevents(&g);
181  /* conn->status |= AIM_CONN_STATUS_INPROGRESS; */
182  owl_function_debugmsg("owl_aim_login: sending login request for %s", screenname);
183  aim_request_login(sess, conn, screenname);
184  owl_function_debugmsg("owl_aim_login: connecting");
185
186  g.aim_nop_timer = owl_select_add_timer(30, 30, owl_aim_send_nop, NULL, NULL);
187
188  return(0);
189}
190
191static void owl_aim_unset_ignorelogin(owl_timer *t, void *data)
192{
193    owl_global_unset_ignore_aimlogin(&g);
194}
195
196/* stuff to run once login has been successful */
197void owl_aim_successful_login(const char *screenname)
198{
199  char *buff;
200  owl_function_debugmsg("doing owl_aim_successful_login");
201  owl_global_set_aimloggedin(&g, screenname);
202  owl_global_set_doaimevents(&g); /* this should already be on */
203  owl_function_makemsg("%s logged in", screenname);
204  buff=owl_sprintf("Logged in to AIM as %s", screenname);
205  owl_function_adminmsg("", buff);
206  owl_free(buff);
207
208  owl_function_debugmsg("Successful AIM login for %s", screenname);
209
210  /* start the ingorelogin timer */
211  owl_global_set_ignore_aimlogin(&g);
212  owl_select_add_timer(owl_global_get_aim_ignorelogin_timer(&g),
213                       0, owl_aim_unset_ignorelogin, NULL, NULL);
214
215  /* aim_ssi_setpresence(owl_global_get_aimsess(&g), 0x00000400); */
216  /* aim_bos_setidle(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), 5000); */
217}
218
219void owl_aim_logout(void)
220{
221  /* need to check if it's connected first, I think */
222  logout(owl_global_get_aimsess(&g));
223
224  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
225  owl_global_set_aimnologgedin(&g);
226  owl_global_set_no_doaimevents(&g);
227  owl_select_remove_timer(g.aim_nop_timer);
228}
229
230void owl_aim_logged_out(void)
231{
232  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
233  owl_aim_logout();
234}
235
236void owl_aim_login_error(const char *message)
237{
238  if (message) {
239    owl_function_error("%s", message);
240  } else {
241    owl_function_error("Authentication error on login");
242  }
243  owl_function_beep();
244  owl_global_set_aimnologgedin(&g);
245  owl_global_set_no_doaimevents(&g);
246  owl_select_remove_timer(g.aim_nop_timer);
247}
248
249/*
250 * I got these constants by skimming libfaim/im.c
251 *
252 * "UNICODE" actually means "UCS-2BE".
253 */
254#define AIM_CHARSET_ISO_8859_1         0x0003
255#define AIM_CHARSET_UNICODE            0x0002
256
257static int owl_aim_do_send(const char *to, const char *msg, int flags)
258{
259  int ret;
260  char *encoded;
261  struct aim_sendimext_args args;
262    gsize len;
263
264  encoded = g_convert(msg, -1, "ISO-8859-1", "UTF-8", NULL, &len, NULL);
265  if (encoded) {
266    owl_function_debugmsg("Encoded outgoing AIM as ISO-8859-1");
267    args.charset = AIM_CHARSET_ISO_8859_1;
268    args.charsubset = 0;
269    args.flags = AIM_IMFLAGS_ISO_8859_1;
270  } else {
271    owl_function_debugmsg("Encoding outgoing IM as UCS-2BE");
272    encoded = g_convert(msg, -1, "UCS-2BE", "UTF-8", NULL, &len, NULL);
273    if (!encoded) {
274      /*
275       * TODO: Strip or HTML-encode characters, or figure out how to
276       * send in a differen charset.
277       */
278      owl_function_error("Unable to encode outgoing AIM message in UCS-2");
279      return 1;
280    }
281
282    args.charset = AIM_CHARSET_UNICODE;
283    args.charsubset = 0;
284    args.flags = AIM_IMFLAGS_UNICODE;
285  }
286
287  args.destsn = to;
288  args.msg = encoded;
289  args.msglen = len;
290  args.flags |= flags;
291
292  ret=aim_im_sendch1_ext(owl_global_get_aimsess(&g), &args);
293
294  owl_free(encoded);
295
296  return(ret);
297}
298
299int owl_aim_send_im(const char *to, const char *msg)
300{
301  return owl_aim_do_send(to, msg, 0);
302}
303
304int owl_aim_send_awaymsg(const char *to, const char *msg)
305{
306  return owl_aim_do_send(to, msg, AIM_IMFLAGS_AWAY);
307}
308
309void owl_aim_addbuddy(const char *name)
310{
311
312  aim_ssi_addbuddy(owl_global_get_aimsess(&g), name, "Buddies", NULL, NULL, NULL, 0);
313
314  /*
315  aim_ssi_addbuddy(owl_global_get_aimsess(&g),
316                   name,
317                   "Buddies",
318                   NULL, NULL, NULL,
319                   aim_ssi_waitingforauth(owl_global_get_aimsess(&g)->ssi.local, "Buddies", name));
320  */
321}
322
323void owl_aim_delbuddy(const char *name)
324{
325  aim_ssi_delbuddy(owl_global_get_aimsess(&g), name, "Buddies");
326  owl_buddylist_offgoing(owl_global_get_buddylist(&g), name);
327}
328
329void owl_aim_search(const char *email)
330{
331  int ret;
332
333  owl_function_debugmsg("owl_aim_search: doing search for %s", email);
334  ret=aim_search_address(owl_global_get_aimsess(&g), 
335                         aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_BOS),
336                         email);
337
338  if (ret) owl_function_error("owl_aim_search: aim_search_address returned %i", ret);
339}
340
341
342int owl_aim_set_awaymsg(const char *msg)
343{
344  int len;
345  char *foo;
346  /* there is a max away message lentgh we should check against */
347
348  foo=owl_strdup(msg);
349  len=strlen(foo);
350  if (len>500) {
351    foo[500]='\0';
352    len=499;
353  }
354   
355  aim_locate_setprofile(owl_global_get_aimsess(&g),
356                        NULL, NULL, 0,
357                        "us-ascii", foo, len);
358  owl_free(foo);
359
360  /*
361  aim_bos_setprofile(owl_global_get_aimsess(&g),
362                     owl_global_get_bosconn(&g),
363                     NULL, NULL, 0, "us-ascii", msg,
364                     strlen(msg), 0);
365  */
366  return(0);
367}
368
369void owl_aim_chat_join(const char *name, int exchange)
370{
371  int ret;
372  aim_conn_t *cur;
373  /*
374  OscarData *od = g->proto_data;
375  const char *name, *exchange;
376  */
377
378  owl_function_debugmsg("Attempting to join chatroom %s exchange %i", name, exchange);
379
380  /*
381  name = g_hash_table_lookup(data, "room");
382  exchange = g_hash_table_lookup(data, "exchange");
383  */
384  if ((cur = aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV))) {
385    owl_function_debugmsg("owl_aim_chat_join: chatnav exists, creating room");
386    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
387  } else {
388    /*    struct create_room *cr = g_new0(struct create_room, 1); */
389    owl_function_debugmsg("owl_aim_chat_join: chatnav does not exist, opening chatnav");
390    /*
391    cr->exchange = atoi(exchange);
392    cr->name = g_strdup(name);
393    od->create_rooms = g_slist_append(od->create_rooms, cr);
394    */
395    aim_reqservice(owl_global_get_aimsess(&g),
396                   aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV),
397                   AIM_CONN_TYPE_CHATNAV);
398    aim_reqservice(owl_global_get_aimsess(&g), NULL, AIM_CONN_TYPE_CHATNAV);
399    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
400    ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
401
402  }
403  return;
404  /******/
405
406
407  /* ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000); */
408  /*
409  ret=aim_chat_join(owl_global_get_aimsess(&g),
410                    aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), exchange, chatroom, 0x0000);
411  */
412
413  aim_reqservice(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), AIM_CONN_TYPE_CHATNAV);
414  ret = aim_chatnav_createroom(owl_global_get_aimsess(&g),
415                               aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), name, exchange);
416   ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
417 
418}
419
420void owl_aim_chat_leave(const char *chatroom)
421{
422}
423
424int owl_aim_chat_sendmsg(const char *chatroom, const char *msg)
425{
426  return(0);
427}
428
429/* caller must free the return */
430char *owl_aim_normalize_screenname(const char *in)
431{
432  char *out;
433  int i, j, k;
434
435  j=strlen(in);
436  out=owl_malloc(j+30);
437  k=0;
438  for (i=0; i<j; i++) {
439    if (in[i]!=' ') {
440      out[k]=in[i];
441      k++;
442    }
443  }
444  out[k]='\0';
445  return(out);
446}
447
448int owl_aim_process_events(void)
449{
450  aim_session_t *aimsess;
451  aim_conn_t *waitingconn = NULL;
452  struct timeval tv;
453  int selstat = 0;
454  struct owlfaim_priv *priv;
455
456  aimsess=owl_global_get_aimsess(&g);
457  priv = aimsess->aux_data;
458
459  /* do a select without blocking */
460  tv.tv_sec = 0;
461  tv.tv_usec = 0;
462  waitingconn = aim_select(aimsess, &tv, &selstat);
463
464  if (selstat == -1) {
465    owl_aim_logged_out();
466  } else if (selstat == 0) { 
467    /* no events pending */
468  } else if (selstat == 1) { /* outgoing data pending */
469    aim_tx_flushqueue(aimsess);
470  } else if (selstat == 2) { /* incoming data pending */
471    /* printf("selstat == 2\n"); */
472   
473    if (aim_get_command(aimsess, waitingconn) >= 0) {
474      aim_rxdispatch(aimsess);
475    } else {
476      /* printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype); */
477      /* we should have callbacks for all these, else the library will do the conn_kill for us. */
478      if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
479        if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
480          /* printf("disconnected from %s\n", aim_directim_getsn(waitingconn)); */
481          aim_conn_kill(aimsess, &waitingconn);
482          owl_aim_logged_out();
483        }
484      } else {
485        aim_conn_kill(aimsess, &waitingconn);
486        owl_aim_logged_out();
487      }
488      if (!aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS)) {
489        /* printf("major connection error\n"); */
490        owl_aim_logged_out();
491        /* break; */
492      }
493    }
494  }
495  /* exit(0); */
496  return(0);
497}
498
499static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
500{
501  return;
502}
503
504static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
505{
506  struct owlfaim_priv *priv = sess->aux_data;
507  struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
508   
509  const char *key;
510  va_list ap;
511
512  va_start(ap, fr);
513  key = va_arg(ap, const char *);
514  va_end(ap);
515
516  aim_send_login(sess, fr->conn, priv->screenname, priv->password, &info, key);
517 
518  return(1);
519}
520
521
522static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
523{
524  va_list ap;
525  struct aim_authresp_info *info;
526  aim_conn_t *bosconn;
527
528  va_start(ap, fr);
529  info = va_arg(ap, struct aim_authresp_info *);
530  va_end(ap);
531
532  /* printf("Screen name: %s\n", info->sn); */
533  owl_function_debugmsg("doing faimtest_parse_authresp");
534  owl_function_debugmsg("faimtest_parse_authresp: %s", info->sn);
535
536  /*
537   * Check for error.
538   */
539  if (info->errorcode || !info->bosip || !info->cookie) {
540    /*
541    printf("Login Error Code 0x%04x\n", info->errorcode);
542    printf("Error URL: %s\n", info->errorurl);
543    */
544    if (info->errorcode==0x05) {
545      owl_aim_login_error("Incorrect nickname or password.");
546    } else if (info->errorcode==0x11) {
547      owl_aim_login_error("Your account is currently suspended.");
548    } else if (info->errorcode==0x14) {
549      owl_aim_login_error("The AOL Instant Messenger service is temporarily unavailable.");
550    } else if (info->errorcode==0x18) {
551      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.");
552    } else if (info->errorcode==0x1c) {
553      owl_aim_login_error("The client version you are using is too old.");
554    } else {
555      owl_aim_login_error(NULL);
556    }
557    aim_conn_kill(sess, &fr->conn);
558    return(1);
559  }
560
561  /*
562  printf("Reg status: %d\n", info->regstatus);
563  printf("Email: %s\n", info->email);
564  printf("BOS IP: %s\n", info->bosip);
565  */
566
567  /* printf("Closing auth connection...\n"); */
568  aim_conn_kill(sess, &fr->conn);
569  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, info->bosip))) {
570    /* printf("could not connect to BOS: internal error\n"); */
571    return(1);
572  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
573    /* printf("could not connect to BOS\n"); */
574    aim_conn_kill(sess, &bosconn);
575    return(1);
576  }
577  owl_global_set_bossconn(&g, bosconn);
578  owl_aim_successful_login(info->sn);
579  addcb_bos(sess, bosconn);
580  aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
581  return(1);
582}
583
584int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
585{
586  owl_function_debugmsg("doing faimtest_flapversion");
587
588#if 0
589  /* XXX fix libfaim to support this */
590  printf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
591
592  /*
593   * This is an alternate location for starting the login process.
594   */
595  /* XXX should do more checking to make sure its really the right AUTH conn */
596  if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
597    /* do NOT send a flapversion, request_login will send it if needed */
598    aim_request_login(sess, fr->conn, priv->screenname);
599    /* printf("faimtest: login request sent\n"); */
600  }
601#endif
602
603  return 1;
604}
605
606
607int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
608{
609  owl_function_debugmsg("doing faimtest_conncomplete");
610  /* owl_aim_successful_login(info->sn); */
611  return 1;
612}
613
614void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
615{
616  owl_function_debugmsg("doing addcb_bos");
617  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
618  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
619
620  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0003,                        ssirights, 0);
621  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0006,                        ssidata, 0);
622  aim_conn_addhandler(sess, bosconn, 0x0013,         0x000f,                        ssidatanochange, 0);
623  aim_conn_addhandler(sess, bosconn, 0x0008,         0x0002,                        handlepopup, 0);
624  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0003,                        faimtest_bosrights, 0);
625  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT,           faimtest_handleredirect, 0);
626  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL,  faimtest_reportinterval, 0);
627  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO,         faimtest_parse_buddyrights, 0);
628  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD,               faimtest_parse_motd, 0);
629  aim_conn_addhandler(sess, bosconn, 0x0004,         0x0005,                        faimtest_icbmparaminfo, 0);
630  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,    faimtest_parse_connerr, 0);
631  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO,         faimtest_locrights, 0);
632  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING,           faimtest_parse_oncoming, 0);
633  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING,           faimtest_parse_offgoing, 0);
634  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING,           faimtest_parse_incoming_im, 0);
635  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR,              faimtest_parse_locerr, 0);
636  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL,         faimtest_parse_misses, 0);
637  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE,         faimtest_parse_ratechange, 0);
638  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL,               faimtest_parse_evilnotify, 0);
639
640  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0001,                        faimtest_parse_searcherror, 0);
641  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0003,                        faimtest_parse_searchreply, 0);
642
643  /*
644  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, faimtest_parse_searcherror, 0);
645  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, faimtest_parse_searchreply, 0);
646  */
647 
648  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR,              faimtest_parse_msgerr, 0);
649  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO,           faimtest_parse_userinfo, 0);
650  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK,                faimtest_parse_msgack, 0);
651
652  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0001,                        faimtest_parse_genericerr, 0);
653  aim_conn_addhandler(sess, bosconn, 0x0003,         0x0001,                        faimtest_parse_genericerr, 0);
654  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0001,                        faimtest_parse_genericerr, 0);
655  aim_conn_addhandler(sess, bosconn, 0x0001,         0x000b,                        serverpause, 0);
656  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0012,                        migrate, 0);
657  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG,         offlinemsg, 0);
658  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, offlinemsgdone, 0);
659
660  /*
661  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,     gaim_connerr, 0);
662  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0);
663  */
664
665  /*
666  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ERROR,              faimtest_ssi_parseerr, 0);
667  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO,         faimtest_ssi_parserights, 0);
668  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST,               faimtest_ssi_parselist, 0);
669  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_NOLIST,             faimtest_ssi_parselist, 0);
670  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK,             faimtest_ssi_parseack, 0);
671  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTH,           faimtest_ssi_authgiven, 0);
672  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREQ,        faimtest_ssi_authrequest, 0);
673  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREP,        faimtest_ssi_authreply, 0);
674  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ADDED,              faimtest_ssi_gotadded, 0);
675  */
676
677  return;
678}
679
680static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
681{
682  owl_function_debugmsg("doing coninitdone_bos");
683
684
685  aim_reqpersonalinfo(sess, fr->conn);
686  aim_ssi_reqrights(sess);
687  aim_ssi_reqdata(sess);
688  aim_locate_reqrights(sess);
689  aim_buddylist_reqrights(sess, fr->conn);
690
691  aim_im_reqparams(sess);
692  /* aim_bos_reqrights(sess, fr->conn); */ /* XXX - Don't call this with ssi */
693
694  owl_function_debugmsg("conninitdone_bos: requesting rights");
695  aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
696  aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
697  aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
698
699  return(1);
700}
701
702static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
703{
704  aim_clientready(sess, fr->conn);
705  owl_function_debugmsg("conninitdone_admin: initializtion done for admin connection");
706  return(1);
707}
708
709int logout(aim_session_t *sess)
710{
711  aim_session_kill(sess);
712  owl_aim_init();
713
714  owl_function_debugmsg("libfaim logout called");
715  /*
716  if (faimtest_init() == -1)
717    printf("faimtest_init failed\n");
718  */
719
720  return(0);
721}
722
723/**************************************************************************************************/
724
725static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
726{
727  struct owlfaim_priv *priv = sess->aux_data;
728  va_list ap;
729  fu16_t code;
730  const char *msg;
731 
732  va_start(ap, fr);
733  code = va_arg(ap, int);
734  msg = va_arg(ap, const char *);
735  va_end(ap);
736 
737  owl_function_error("faimtest_parse_connerr: Code 0x%04x: %s\n", code, msg);
738  aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
739 
740  priv->connected = 0;
741 
742  return 1;
743}
744
745static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
746{
747  int status;
748  va_list ap;
749 
750  va_start(ap, fr);
751  status = va_arg(ap, int); /* status code of confirmation request */
752  va_end(ap);
753
754  /* owl_function_debugmsg("faimtest_accountconfirm: Code 0x%04x: %s\n", code, msg); */
755  owl_function_debugmsg("faimtest_accountconfirm: account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
756 
757  return 1;
758}
759
760static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
761{
762  fu16_t change = 0, perms, type;
763  int length, str;
764  const char *val;
765  va_list ap;
766 
767  va_start(ap, fr);
768  change = va_arg(ap, int);
769  perms = (fu16_t)va_arg(ap, unsigned int);
770  type = (fu16_t)va_arg(ap, unsigned int);
771  length = va_arg(ap, int);
772  val = va_arg(ap, const char *);
773  str = va_arg(ap, int);
774  va_end(ap);
775 
776  owl_function_debugmsg("faimtest_infochange: info%s: perms = %d, type = %x, length = %d, val = %s", change?" change":"", perms, type, length, str?val:"(not string)");
777 
778  return(1);
779}
780
781
782static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
783{
784  va_list ap;
785  struct aim_redirect_data *redir;
786
787  owl_function_debugmsg("faimtest_handledirect:");
788 
789  va_start(ap, fr);
790  redir = va_arg(ap, struct aim_redirect_data *);
791 
792  if (redir->group == 0x0005) {  /* Adverts */
793   
794  } else if (redir->group == 0x0007) {  /* Authorizer */
795    aim_conn_t *tstconn;
796
797    owl_function_debugmsg("faimtest_handledirect: autorizer");
798   
799    tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, redir->ip);
800    if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
801      owl_function_error("faimtest_handleredirect: unable to reconnect with authorizer");
802    } else {
803      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
804      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
805      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
806      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
807      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
808      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
809      /* Send the cookie to the Auth */
810      aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
811      owl_function_debugmsg("faimtest_handleredirect: sent cookie to authorizer host");
812    }
813  } else if (redir->group == 0x000d) {  /* ChatNav */
814    owl_function_debugmsg("faimtest_handledirect: chatnav");
815    chatnav_redirect(sess, redir);
816  } else if (redir->group == 0x000e) { /* Chat */
817    owl_function_debugmsg("faimtest_handledirect: chat");
818    chat_redirect(sess, redir);
819  } else {
820    owl_function_debugmsg("faimtest_handleredirect: uh oh... got redirect for unknown service 0x%04x!!", redir->group);
821  }
822  va_end(ap);
823  return 1;
824}
825
826static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
827{
828  struct aim_icbmparameters *params;
829  va_list ap;
830 
831  va_start(ap, fr);
832  params = va_arg(ap, struct aim_icbmparameters *);
833  va_end(ap);
834 
835  owl_function_debugmsg("faimtest_icbmparaminfo: ICBM Parameters: maxchannel = %d, default flags = 0x%08x, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %u",
836                       params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval);
837     
838  /*
839  * Set these to your taste, or client medium.  Setting minmsginterval
840  * higher is good for keeping yourself from getting flooded (esp
841  * if you're on a slow connection or something where that would be
842  * useful).
843  */
844  params->maxmsglen = 8000;
845  params->minmsginterval = 0; /* in milliseconds */
846  /* aim_seticbmparam(sess, params); */
847  aim_im_setparams(sess, params);
848 
849  return 1;
850}
851
852static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
853{
854  va_list ap;
855  fu16_t maxbuddies, maxwatchers;
856 
857  va_start(ap, fr);
858  maxbuddies = va_arg(ap, int);
859  maxwatchers = va_arg(ap, int);
860  va_end(ap);
861 
862  owl_function_debugmsg("faimtest_parse_buddyrights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
863 
864  /* aim_ssi_reqrights(sess, fr->conn); */
865  aim_ssi_reqrights(sess);
866 
867  return 1;
868}
869
870static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
871{
872  va_list ap;
873  fu16_t maxpermits, maxdenies;
874 
875  va_start(ap, fr);
876  maxpermits = va_arg(ap, int);
877  maxdenies = va_arg(ap, int);
878  va_end(ap);
879 
880  owl_function_debugmsg("faimtest_bosrights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
881  aim_clientready(sess, fr->conn);
882  owl_function_debugmsg("officially connected to BOS.");
883  aim_icq_reqofflinemsgs(sess);
884  return 1;
885}
886
887static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
888{
889  va_list ap;
890  fu16_t maxsiglen;
891 
892  va_start(ap, fr);
893  maxsiglen = va_arg(ap, int);
894  va_end(ap);
895
896  owl_function_debugmsg("faimtest_locrights: rights: max signature length = %d\n", maxsiglen);
897 
898  return(1);
899}
900
901static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
902{
903  struct owlfaim_priv *priv = sess->aux_data;
904  va_list ap;
905  fu16_t interval;
906
907  va_start(ap, fr);
908  interval = va_arg(ap, int);
909  va_end(ap);
910
911  owl_function_debugmsg("faimtest_reportinterval: %d (seconds?)\n", interval);
912
913  if (!priv->connected) {
914    priv->connected++;
915  }
916  /* aim_reqicbmparams(sess); */
917  aim_im_reqparams(sess);
918  /* kretch */
919  return 1;
920}
921
922static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
923{
924  const char *msg;
925  fu16_t id;
926  va_list ap;
927  static int codeslen = 5;
928  static const char *codes[] = {
929    "Unknown",
930    "Mandatory upgrade",
931    "Advisory upgrade",
932    "System bulletin",
933    "Top o' the world!"
934  };
935
936  va_start(ap, fr);
937  id = va_arg(ap, int);
938  msg = va_arg(ap, const char *);
939  va_end(ap);
940
941  owl_function_debugmsg("faimtest_parse_motd: %s (%d / %s)\n", msg?msg:"nomsg", id, (id < codeslen)?codes[id]:"unknown");
942 
943  return 1;
944}
945
946/*
947static void printuserflags(fu16_t flags)
948{
949  if (flags & AIM_FLAG_UNCONFIRMED) printf("UNCONFIRMED ");
950  if (flags & AIM_FLAG_ADMINISTRATOR) printf("ADMINISTRATOR ");
951  if (flags & AIM_FLAG_AOL) printf("AOL ");
952  if (flags & AIM_FLAG_OSCAR_PAY) printf("OSCAR_PAY ");
953  if (flags & AIM_FLAG_FREE) printf("FREE ");
954  if (flags & AIM_FLAG_AWAY) printf("AWAY ");
955  if (flags & AIM_FLAG_ICQ) printf("ICQ ");
956  if (flags & AIM_FLAG_WIRELESS) printf("WIRELESS ");
957  if (flags & AIM_FLAG_ACTIVEBUDDY) printf("ACTIVEBUDDY ");
958 
959  return;
960}
961*/
962
963static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
964{
965  aim_userinfo_t *userinfo;
966  const char *prof_encoding = NULL;
967  const char *prof = NULL;
968  fu16_t inforeq = 0;
969  owl_buddy *b;
970  va_list ap;
971  va_start(ap, fr);
972  userinfo = va_arg(ap, aim_userinfo_t *);
973  inforeq = (fu16_t)va_arg(ap, unsigned int);
974  prof_encoding = va_arg(ap, const char *);
975  prof = va_arg(ap, const char *);
976  va_end(ap);
977
978  /* right now the only reason we call this is for idle times */
979  owl_function_debugmsg("parse_userinfo sn: %s idle: %i", userinfo->sn, userinfo->idletime);
980  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g),
981                                userinfo->sn);
982  if (!b) return(1);
983  owl_buddy_set_idle_since(b, userinfo->idletime);
984  return(1);
985
986  /*
987  printf("userinfo: sn: %s\n", userinfo->sn);
988  printf("userinfo: warnlevel: %f\n", aim_userinfo_warnlevel(userinfo));
989  printf("userinfo: flags: 0x%04x = ", userinfo->flags);
990  printuserflags(userinfo->flags);
991  printf("\n");
992  */
993
994  /*
995  printf("userinfo: membersince: %lu\n", userinfo->membersince);
996  printf("userinfo: onlinesince: %lu\n", userinfo->onlinesince);
997  printf("userinfo: idletime: 0x%04x\n", userinfo->idletime);
998  printf("userinfo: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
999  */
1000
1001  /*
1002  if (inforeq == AIM_GETINFO_GENERALINFO) {
1003    owl_function_debugmsg("userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1004    owl_function_debugmsg("userinfo: prof: %s\n", prof ? prof : "[none]");
1005  } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1006    owl_function_debugmsg("userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1007    owl_function_debugmsg("userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1008  } else if (inforeq == AIM_GETINFO_CAPABILITIES) {
1009    owl_function_debugmsg("userinfo: capabilities: see above\n");
1010  } else {
1011    owl_function_debugmsg("userinfo: unknown info request\n");
1012  }
1013  */
1014  return(1);
1015}
1016
1017/*
1018 * Channel 1: Standard Message
1019 */
1020static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args)
1021{
1022  owl_message *m;
1023  char *stripmsg, *nz_screenname, *wrapmsg;
1024  char *realmsg = NULL;
1025
1026  if (!args->msg) {
1027    realmsg = owl_strdup("");
1028  } else if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1029    realmsg = g_convert(args->msg, args->msglen, "UTF-8", "UCS-2BE",
1030                        NULL, NULL, NULL);
1031  } else if(args->icbmflags & AIM_IMFLAGS_ISO_8859_1) {
1032    realmsg = g_convert(args->msg, args->msglen, "UTF-8", "ISO-8859-1",
1033                        NULL, NULL, NULL);
1034  } else {
1035    realmsg = owl_strdup(args->msg);
1036  }
1037
1038  if (!realmsg) {
1039    realmsg = owl_strdup("[Error decoding incoming IM]");
1040  }
1041
1042  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: message from: %s", userinfo->sn?userinfo->sn:"");
1043  /* create a message, and put it on the message queue */
1044  stripmsg=owl_text_htmlstrip(realmsg);
1045  wrapmsg=owl_text_wordwrap(stripmsg, 70);
1046  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1047  m=owl_malloc(sizeof(owl_message));
1048  owl_message_create_aim(m,
1049                         nz_screenname,
1050                         owl_global_get_aim_screenname(&g),
1051                         wrapmsg,
1052                         OWL_MESSAGE_DIRECTION_IN,
1053                         0);
1054  if (args->icbmflags & AIM_IMFLAGS_AWAY) owl_message_set_attribute(m, "isauto", "");
1055  owl_global_messagequeue_addmsg(&g, m);
1056  owl_free(stripmsg);
1057  owl_free(wrapmsg);
1058  owl_free(nz_screenname);
1059
1060  return(1);
1061
1062  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: message: %s\n", realmsg);
1063 
1064  if (args->icbmflags & AIM_IMFLAGS_MULTIPART) {
1065    aim_mpmsg_section_t *sec;
1066    int z;
1067
1068    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart: this message has %d parts\n", args->mpmsg.numparts);
1069   
1070    for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++) {
1071      if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff)) {
1072        owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, msg = %s\n", z, sec->charset, sec->charsubset, sec->data);
1073      } else {
1074        owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, binary or UNICODE data\n", z, sec->charset, sec->charsubset);
1075      }
1076    }
1077  }
1078 
1079  if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1080    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon"); */
1081    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: their icon: iconstamp = %ld, iconlen = 0x%08x, iconsum = 0x%04x\n", args->iconstamp, args->iconlen, args->iconsum);
1082  }
1083
1084  owl_free(realmsg);
1085
1086  return(1);
1087}
1088
1089/*
1090 * Channel 2: Rendevous Request
1091 */
1092static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args)
1093{
1094  /*
1095  printf("rendezvous: source sn = %s\n", userinfo->sn);
1096  printf("rendezvous: \twarnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1097  printf("rendezvous: \tclass = 0x%04x = ", userinfo->flags);
1098  printuserflags(userinfo->flags);
1099  printf("\n");
1100 
1101  printf("rendezvous: \tonlinesince = %lu\n", userinfo->onlinesince);
1102  printf("rendezvous: \tidletime = 0x%04x\n", userinfo->idletime);
1103 
1104  printf("rendezvous: message/description = %s\n", args->msg);
1105  printf("rendezvous: encoding = %s\n", args->encoding);
1106  printf("rendezvous: language = %s\n", args->language);
1107  */
1108 
1109  if (args->reqclass == AIM_CAPS_SENDFILE) {
1110    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: send file!");
1111  } else if (args->reqclass == AIM_CAPS_CHAT) {
1112    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: chat invite: %s, %i, %i", args->info.chat.roominfo.name, args->info.chat.roominfo.exchange, args->info.chat.roominfo.instance);
1113    /*
1114    printf("chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1115    printf("chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1116    printf("chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1117    */
1118    /* Automatically join room... */
1119    /* printf("chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name); */
1120
1121    /* aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance); */
1122  } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
1123    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: Buddy Icon from %s, length = %u\n",
1124                          userinfo->sn, args->info.icon.length);
1125  } else if (args->reqclass == AIM_CAPS_ICQRTF) {
1126    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: RTF message from %s: (fgcolor = 0x%08x, bgcolor = 0x%08x) %s\n",
1127                          userinfo->sn, args->info.rtfmsg.fgcolor, args->info.rtfmsg.bgcolor, args->info.rtfmsg.rtfmsg);
1128  } else {
1129    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: icbm: unknown reqclass (%d)\n", args->reqclass);
1130  }
1131  return 1;
1132}
1133
1134static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
1135{
1136  fu16_t channel;
1137  aim_userinfo_t *userinfo;
1138  va_list ap;
1139  int ret = 0;
1140 
1141  va_start(ap, fr);
1142  channel = (fu16_t)va_arg(ap, unsigned int);
1143  userinfo = va_arg(ap, aim_userinfo_t *);
1144 
1145  if (channel == 1) {
1146    struct aim_incomingim_ch1_args *args;
1147    args = va_arg(ap, struct aim_incomingim_ch1_args *);
1148    ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
1149  } else if (channel == 2) {
1150    struct aim_incomingim_ch2_args *args;
1151    args = va_arg(ap, struct aim_incomingim_ch2_args *);
1152    ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
1153  } else {
1154    owl_function_debugmsg("faimtest_parse_incoming_im: unsupported channel 0x%04x\n", channel);
1155  }
1156  va_end(ap);
1157  owl_function_debugmsg("faimtest_parse_incoming_im: done with ICBM handling (ret = %d)\n", ret);
1158  return 1;
1159}
1160
1161static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
1162{
1163  aim_userinfo_t *userinfo;
1164  char *nz_screenname;
1165  owl_buddy *b;
1166  va_list ap;
1167  va_start(ap, fr);
1168  userinfo = va_arg(ap, aim_userinfo_t *);
1169  va_end(ap);
1170
1171  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1172 
1173  owl_buddylist_oncoming(owl_global_get_buddylist(&g), nz_screenname);
1174
1175  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1176    owl_function_debugmsg("faimtest_parseoncoming: in empty part of userinfo present and present idle");
1177  }
1178
1179  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g), nz_screenname);
1180  if (!b) {
1181    owl_function_debugmsg("Error: parse_oncoming setting idle time with no buddy present.");
1182    return(1);
1183  }
1184  if (userinfo->idletime==0) {
1185    owl_buddy_set_unidle(b);
1186  } else {
1187    owl_buddy_set_idle(b);
1188    owl_buddy_set_idle_since(b, userinfo->idletime);
1189  }
1190
1191  if (userinfo->flags & AIM_FLAG_AWAY) {
1192    owl_function_debugmsg("parse_oncoming sn: %s away flag!", userinfo->sn);
1193  }
1194 
1195  owl_function_debugmsg("parse_oncoming sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1196   
1197  owl_free(nz_screenname);
1198 
1199  /*
1200    printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1201    time(NULL),
1202    userinfo->sn, userinfo->flags,
1203    (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1204    (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1205    (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1206    (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1207    (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1208    (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1209    (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1210    (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1211    (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1212    userinfo->capabilities);
1213  */
1214  return(1);
1215}
1216
1217static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
1218{
1219  aim_userinfo_t *userinfo;
1220  char *nz_screenname;
1221  va_list ap;
1222 
1223  va_start(ap, fr);
1224  userinfo = va_arg(ap, aim_userinfo_t *);
1225  va_end(ap);
1226
1227  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1228  owl_buddylist_offgoing(owl_global_get_buddylist(&g), nz_screenname);
1229  owl_free(nz_screenname);
1230
1231  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1232    owl_function_debugmsg("parse_offgoing sn: %s idle time %i", userinfo->sn, userinfo->idletime);
1233  }
1234
1235  /*
1236  printf("%ld  %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1237         time(NULL),
1238         userinfo->sn, userinfo->flags,
1239         (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1240         (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1241         (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1242         (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1243         (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1244         (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1245         (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1246         (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1247         (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1248         userinfo->capabilities);
1249  */
1250 
1251  return 1;
1252}
1253
1254/* Used by chat as well. */
1255int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
1256{
1257  va_list ap;
1258  fu16_t reason;
1259 
1260  va_start(ap, fr);
1261  reason = (fu16_t)va_arg(ap, unsigned int);
1262  va_end(ap);
1263 
1264  /* printf("snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1265  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1266 
1267  return 1;
1268}
1269
1270static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
1271{
1272  va_list ap;
1273  const char *destsn;
1274  fu16_t reason;
1275 
1276  va_start(ap, fr);
1277  reason = (fu16_t)va_arg(ap, unsigned int);
1278  destsn = va_arg(ap, const char *);
1279  va_end(ap);
1280 
1281  /* printf("message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1282  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1283
1284  if (reason==4) {
1285    owl_function_adminmsg("", "Could not send AIM message, user not logged on");
1286  }
1287 
1288  return 1;
1289}
1290
1291static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
1292{
1293  va_list ap;
1294  const char *destsn;
1295  fu16_t reason;
1296 
1297  va_start(ap, fr);
1298  reason = (fu16_t)va_arg(ap, unsigned int);
1299  destsn = va_arg(ap, const char *);
1300  va_end(ap);
1301 
1302  /* printf("user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1303  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1304 
1305  return 1;
1306}
1307
1308static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1309{
1310  static const char *missedreasons[] = {
1311    "Invalid (0)",
1312    "Message too large",
1313    "Rate exceeded",
1314    "Evil Sender",
1315    "Evil Receiver"
1316  };
1317  static int missedreasonslen = 5;
1318 
1319  va_list ap;
1320  fu16_t chan, nummissed, reason;
1321  aim_userinfo_t *userinfo;
1322 
1323  va_start(ap, fr);
1324  chan = (fu16_t)va_arg(ap, unsigned int);
1325  userinfo = va_arg(ap, aim_userinfo_t *);
1326  nummissed = (fu16_t)va_arg(ap, unsigned int);
1327  reason = (fu16_t)va_arg(ap, unsigned int);
1328  va_end(ap);
1329 
1330  owl_function_debugmsg("faimtest_parse_misses: missed %d messages from %s on channel %d (reason %d: %s)\n", nummissed, userinfo->sn, chan, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1331 
1332  return 1;
1333}
1334
1335/*
1336 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1337 */
1338static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1339{
1340  va_list ap;
1341  fu16_t type;
1342  const char *sn = NULL;
1343 
1344  va_start(ap, fr);
1345  type = (fu16_t)va_arg(ap, unsigned int);
1346  sn = va_arg(ap, const char *);
1347  va_end(ap);
1348 
1349  owl_function_debugmsg("faimtest_parse_msgack: 0x%04x / %s\n", type, sn);
1350 
1351  return 1;
1352}
1353
1354static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
1355{
1356  static const char *codes[5] = {
1357    "invalid",
1358    "change",
1359    "warning",
1360    "limit",
1361    "limit cleared"
1362  };
1363  va_list ap;
1364  fu16_t code, rateclass;
1365  fu32_t windowsize, clear, alert, limit, disconnect;
1366  fu32_t currentavg, maxavg;
1367 
1368  va_start(ap, fr); 
1369 
1370  /* See code explanations below */
1371  code = (fu16_t)va_arg(ap, unsigned int);
1372 
1373  /*
1374   * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1375   */
1376  rateclass = (fu16_t)va_arg(ap, unsigned int);
1377 
1378  /*
1379   * Not sure what this is exactly.  I think its the temporal
1380   * relation factor (ie, how to make the rest of the numbers
1381   * make sense in the real world).
1382   */
1383  windowsize = va_arg(ap, fu32_t);
1384 
1385  /* Explained below */
1386  clear = va_arg(ap, fu32_t);
1387  alert = va_arg(ap, fu32_t);
1388  limit = va_arg(ap, fu32_t);
1389  disconnect = va_arg(ap, fu32_t);
1390  currentavg = va_arg(ap, fu32_t);
1391  maxavg = va_arg(ap, fu32_t);
1392 
1393  va_end(ap);
1394 
1395  owl_function_debugmsg("faimtest_parse_ratechange: rate %s (rate class 0x%04x): curavg = %u, maxavg = %u, alert at %u, clear warning at %u, limit at %u, disconnect at %u (window size = %u)",
1396                        (code < 5)?codes[code]:"invalid",
1397                        rateclass,
1398                        currentavg, maxavg,
1399                        alert, clear,
1400                        limit, disconnect,
1401                        windowsize);
1402  return 1;
1403}
1404
1405static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
1406{
1407  va_list ap;
1408  fu16_t newevil;
1409  aim_userinfo_t *userinfo;
1410 
1411  va_start(ap, fr);
1412  newevil = (fu16_t)va_arg(ap, unsigned int);
1413  userinfo = va_arg(ap, aim_userinfo_t *);
1414  va_end(ap);
1415 
1416  /*
1417   * Evil Notifications that are lacking userinfo->sn are anon-warns
1418   * if they are an evil increases, but are not warnings at all if its
1419   * a decrease (its the natural backoff happening).
1420   *
1421   * newevil is passed as an int representing the new evil value times
1422   * ten.
1423   */
1424  owl_function_debugmsg("faimtest_parse_evilnotify: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
1425 
1426  return 1;
1427}
1428
1429static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
1430{
1431  va_list ap;
1432  const char *address, *SNs;
1433  int num, i;
1434  owl_list list;
1435 
1436  va_start(ap, fr);
1437  address = va_arg(ap, const char *);
1438  num = va_arg(ap, int);
1439  SNs = va_arg(ap, const char *);
1440  va_end(ap);
1441
1442  owl_list_create(&list);
1443 
1444  owl_function_debugmsg("faimtest_parse_searchreply: E-Mail Search Results for %s: ", address);
1445  for (i=0; i<num; i++) {
1446    owl_function_debugmsg("  %s", &SNs[i*(MAXSNLEN+1)]);
1447    owl_list_append_element(&list, (void *)&SNs[i*(MAXSNLEN+1)]);
1448  }
1449  owl_function_aimsearch_results(address, &list);
1450  owl_list_cleanup(&list, NULL);
1451  return(1);
1452}
1453
1454static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
1455{
1456  va_list ap;
1457  const char *address;
1458 
1459  va_start(ap, fr);
1460  address = va_arg(ap, const char *);
1461  va_end(ap);
1462
1463  owl_function_error("No results searching for %s", address);
1464  owl_function_debugmsg("faimtest_parse_searcherror: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1465 
1466  return(1);
1467}
1468
1469static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...)
1470{
1471  va_list ap;
1472  const char *msg, *url;
1473  fu16_t width, height, delay;
1474 
1475  va_start(ap, fr);
1476  msg = va_arg(ap, const char *);
1477  url = va_arg(ap, const char *);
1478  width = va_arg(ap, unsigned int);
1479  height = va_arg(ap, unsigned int);
1480  delay = va_arg(ap, unsigned int);
1481  va_end(ap);
1482 
1483  owl_function_debugmsg("handlepopup: (%dx%x:%d) %s (%s)\n", width, height, delay, msg, url);
1484 
1485  return 1;
1486}
1487
1488static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
1489{
1490  aim_sendpauseack(sess, fr->conn);
1491  return 1;
1492}
1493
1494static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
1495{
1496  va_list ap;
1497  aim_conn_t *bosconn;
1498  const char *bosip;
1499  fu8_t *cookie;
1500 
1501  va_start(ap, fr);
1502  bosip = va_arg(ap, const char *);
1503  cookie = va_arg(ap, fu8_t *);
1504  va_end(ap);
1505 
1506  owl_function_debugmsg("migrate: migration in progress -- new BOS is %s -- disconnecting", bosip);
1507  aim_conn_kill(sess, &fr->conn);
1508 
1509  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
1510    owl_function_debugmsg("migrate: could not connect to BOS: internal error");
1511    return 1;
1512  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
1513    owl_function_debugmsg("migrate: could not connect to BOS");
1514    aim_conn_kill(sess, &bosconn);
1515    return 1;
1516  }
1517 
1518  /* Login will happen all over again. */
1519  addcb_bos(sess, bosconn);
1520  /* aim_sendcookie(sess, bosconn, cookie); */ /********/
1521  return 1;
1522}
1523
1524static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...)
1525{
1526  owl_function_debugmsg("ssirights: got SSI rights, requesting data\n");
1527  /* aim_ssi_reqdata(sess, fr->conn, 0, 0x0000); */
1528  aim_ssi_reqdata(sess);
1529 
1530  return(1);
1531}
1532
1533static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...)
1534{
1535  va_list ap;
1536  fu8_t fmtver;
1537  fu16_t itemcount;
1538  fu32_t stamp;
1539  struct aim_ssi_item *list;
1540  /*
1541  struct aim_ssi_item *curitem;
1542  struct aim_ssi_item *l;
1543  */
1544 
1545  va_start(ap, fr);
1546  fmtver = va_arg(ap, unsigned int);
1547  itemcount = va_arg(ap, unsigned int);
1548  stamp = va_arg(ap, fu32_t);
1549  list = va_arg(ap, struct aim_ssi_item *);
1550  va_end(ap);
1551 
1552  owl_function_debugmsg("ssiddata: got SSI data (0x%02x, %d items, %u)", fmtver, itemcount, stamp);
1553  /*
1554  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
1555    for (l = list; l; l = l->next) {
1556      owl_function_debugmsg("\t0x%04x (%s) - 0x%04x/0x%04x", l->type, l->name, l->gid, l->bid);
1557    }
1558  }
1559  */
1560  aim_ssi_enable(sess);
1561 
1562  return 1;
1563}
1564
1565static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...)
1566{
1567  owl_function_debugmsg("ssidatanochange: server says we have the latest SSI data already");
1568  /* aim_ssi_enable(sess, fr->conn); */
1569  aim_ssi_enable(sess);
1570  return 1;
1571}
1572
1573static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
1574{
1575  va_list ap;
1576  struct aim_icq_offlinemsg *msg;
1577 
1578  va_start(ap, fr);
1579  msg = va_arg(ap, struct aim_icq_offlinemsg *);
1580  va_end(ap);
1581 
1582  if (msg->type == 0x0001) {
1583    owl_function_debugmsg("offlinemsg: from %u at %d/%d/%d %02d:%02d : %s", msg->sender, msg->year, msg->month, msg->day, msg->hour, msg->minute, msg->msg);
1584  } else {
1585    owl_function_debugmsg("unknown offline message type 0x%04x", msg->type);
1586  }
1587  return 1;
1588}
1589
1590static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
1591{
1592  /* Tell the server to delete them. */
1593  owl_function_debugmsg("offlinemsg done: ");
1594  aim_icq_ackofflinemsgs(sess);
1595  return 1;
1596}
1597
1598
1599/******************** chat.c **************************/
1600
1601static int faimtest_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
1602{
1603  va_list ap;
1604  aim_userinfo_t *userinfo;
1605  int count;
1606  /* int i; */
1607 
1608  va_start(ap, fr);
1609  count = va_arg(ap, int);
1610  userinfo = va_arg(ap, aim_userinfo_t *);
1611  va_end(ap);
1612
1613  owl_function_debugmsg("In faimtest_chat_join");
1614  /*
1615  printf("chat: %s:  New occupants have joined:\n", aim_chat_getname(fr->conn));
1616  for (i = 0; i < count; i++)
1617    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
1618  */
1619  return 1;
1620}
1621
1622static int faimtest_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
1623{
1624  aim_userinfo_t *userinfo;
1625  va_list ap;
1626  int count;
1627  /* int i; */
1628
1629 
1630  va_start(ap, fr);
1631  count = va_arg(ap, int);
1632  userinfo = va_arg(ap, aim_userinfo_t *);
1633  va_end(ap);
1634 
1635  /*
1636    printf("chat: %s:  Some occupants have left:\n", aim_chat_getname(fr->conn));
1637   
1638    for (i = 0; i < count; i++)
1639    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
1640  */
1641  return 1;
1642}
1643
1644static int faimtest_chat_infoupdate(aim_session_t *sess, aim_frame_t *fr, ...)
1645{
1646  va_list ap;
1647  aim_userinfo_t *userinfo;
1648  struct aim_chat_roominfo *roominfo;
1649  const char *roomname;
1650  int usercount;
1651  const char *roomdesc;
1652  fu16_t flags, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
1653  fu32_t creationtime;
1654  const char *croomname;
1655  /* int i; */
1656 
1657  croomname = aim_chat_getname(fr->conn);
1658 
1659  va_start(ap, fr);
1660  roominfo = va_arg(ap, struct aim_chat_roominfo *);
1661  roomname = va_arg(ap, const char *);
1662  usercount = va_arg(ap, int);
1663  userinfo = va_arg(ap, aim_userinfo_t *);
1664  roomdesc = va_arg(ap, const char *);
1665  flags = (fu16_t)va_arg(ap, unsigned int);
1666  creationtime = va_arg(ap, fu32_t);
1667  maxmsglen = (fu16_t)va_arg(ap, unsigned int);
1668  unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
1669  unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
1670  maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
1671  va_end(ap);
1672
1673  owl_function_debugmsg("In faimtest_chat_infoupdate");
1674  /*
1675  printf("chat: %s:  info update:\n", croomname);
1676  printf("chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", croomname, roominfo->exchange, roominfo->name, roominfo->instance);
1677  printf("chat: %s:  \tRoomname: %s\n", croomname, roomname);
1678  printf("chat: %s:  \tRoomdesc: %s\n", croomname, roomdesc);
1679  printf("chat: %s:  \tOccupants: (%d)\n", croomname, usercount);
1680
1681  for (i = 0; i < usercount; i++)
1682    printf("chat: %s:  \t\t%s\n", croomname, userinfo[i].sn);
1683 
1684  owl_function_debugmsg("chat: %s:  \tRoom flags: 0x%04x (%s%s%s%s)\n",
1685         croomname, flags,
1686         (flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
1687         (flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
1688         (flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
1689         (flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
1690  printf("chat: %s:  \tCreation time: %lu (time_t)\n", croomname, creationtime);
1691  printf("chat: %s:  \tUnknown_d2: 0x%04x\n", croomname, unknown_d2);
1692  printf("chat: %s:  \tUnknown_d5: 0x%02x\n", croomname, unknown_d5);
1693  printf("chat: %s:  \tMax message length: %d bytes\n", croomname, maxmsglen);
1694  printf("chat: %s:  \tMax visible message length: %d bytes\n", croomname, maxvisiblemsglen);
1695  */
1696 
1697  return(1);
1698}
1699
1700static int faimtest_chat_incomingmsg(aim_session_t *sess, aim_frame_t *fr, ...)
1701{
1702  va_list ap;
1703  aim_userinfo_t *userinfo;
1704  const char *msg;
1705  char tmpbuf[1152];
1706 
1707  va_start(ap, fr);
1708  userinfo = va_arg(ap, aim_userinfo_t *);     
1709  msg = va_arg(ap, const char *);
1710  va_end(ap);
1711
1712  owl_function_debugmsg("in faimtest_chat_incomingmsg");
1713
1714  /*
1715  printf("chat: %s: incoming msg from %s: %s\n", aim_chat_getname(fr->conn), userinfo->sn, msg);
1716  */
1717 
1718  /*
1719   * Do an echo for testing purposes.  But not for ourselves ("oops!")
1720   */
1721  if (strcmp(userinfo->sn, sess->sn) != 0) {
1722    /* sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg); */
1723    aim_chat_send_im(sess, fr->conn, 0, tmpbuf, strlen(tmpbuf));
1724  }
1725 
1726  return 1;
1727}
1728
1729static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
1730{
1731  owl_function_debugmsg("faimtest_conninitdone_chat:");
1732
1733  aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, faimtest_parse_genericerr, 0);
1734  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
1735  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
1736  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
1737  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
1738 
1739  aim_clientready(sess, fr->conn);
1740 
1741  owl_function_debugmsg("Chat ready");
1742
1743  /*
1744    chatcon = find_oscar_chat_by_conn(gc, fr->conn);
1745    chatcon->id = id;
1746    chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
1747  */
1748  return(1);
1749}
1750
1751void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
1752{
1753  aim_conn_t *tstconn;
1754
1755  owl_function_debugmsg("in faimtest_chatnav_redirect");
1756 
1757  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, redir->ip);
1758  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
1759    /* printf("unable to connect to chat(nav) server\n"); */
1760    if (tstconn)
1761      aim_conn_kill(sess, &tstconn);
1762    return;
1763  }
1764 
1765  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1766  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
1767  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
1768  /* printf("chatnav: connected\n"); */
1769  return;
1770}
1771
1772/* XXX this needs instance too */
1773void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
1774{
1775  aim_conn_t *tstconn;
1776
1777  owl_function_debugmsg("in chat_redirect");
1778 
1779  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, redir->ip);
1780  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
1781    /* printf("unable to connect to chat server\n"); */
1782    if (tstconn) aim_conn_kill(sess, &tstconn);
1783    return; 
1784  }             
1785  /* printf("chat: connected to %s instance %d on exchange %d\n", redir->chat.room, redir->chat.instance, redir->chat.exchange); */
1786 
1787  /*
1788   * We must do this to attach the stored name to the connection!
1789   */
1790  aim_chat_attachname(tstconn, redir->chat.exchange, redir->chat.room, redir->chat.instance);
1791  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1792  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
1793  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
1794  return;       
1795}
1796
1797void owl_process_aim(void)
1798{
1799  if (owl_global_is_doaimevents(&g)) {
1800    owl_aim_process_events();
1801  }
1802}
Note: See TracBrowser for help on using the repository browser.