source: aim.c @ 6700c605

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