source: aim.c @ df3a1f4

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