Index: Makefile.in
===================================================================
--- Makefile.in	(revision 84d48cca848890b552a2a95d8c9be5599a741491)
+++ Makefile.in	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -10,6 +10,6 @@
 
 CC=@CC@
-LIBS=@LIBS@ -L./libfaim -lfaim
-CFLAGS=@CFLAGS@ -I. -I./libfaim -DDATADIR=\"${datadir}\" -DOWL_SVN_REVNO=$(shell ./svkversion)
+LIBS=@LIBS@
+CFLAGS=@CFLAGS@ -DDATADIR=\"${datadir}\" -DOWL_SVN_REVNO=$(shell ./svkversion)
 LDFLAGS=@LDFLAGS@
 XSUBPPDIR=@XSUBPPDIR@
@@ -25,5 +25,5 @@
      regex.c history.c view.c dict.c variable.c filterelement.c pair.c \
      keypress.c keymap.c keybinding.c cmd.c context.c zcrypt.c \
-     aim.c buddy.c buddylist.c timer.c style.c errqueue.c \
+     timer.c style.c errqueue.c \
      zbuddylist.c muxevents.c popexec.c obarray.c select.c wcwidth.c \
      glib_compat.c
@@ -50,5 +50,5 @@
 all: $(EXE) $(MODULE_DIRS)
 
-$(EXE): $(AUTOGEN) $(OBJS) owl.o libfaim
+$(EXE): $(AUTOGEN) $(OBJS) owl.o
 	$(ATHSTATIC) $(CC) -o $(EXE) owl.o $(OBJS) $(LDFLAGS) $(LIBS)
 
@@ -67,8 +67,8 @@
 	./tester reg
 
-clean: libfaimclean modules_clean
+clean: modules_clean
 	$(RM) $(EXE) tester *.o $(AUTOGEN) owl_prototypes.h.new
 
-distclean: clean libfaimdistclean
+distclean: clean
 	$(RM) config.cache config.log config.status  Makefile config.h TAGS *~ core
 
@@ -116,15 +116,4 @@
 $(BASE_OBJS) varstubs.h: owl.h config.h owl_prototypes.h
 
-libfaim: libfaim/libfaim.a
-
-libfaim/libfaim.a:
-	(cd libfaim; $(MAKE))
-
-libfaimclean:
-	(cd libfaim; $(MAKE) clean)
-
-libfaimdistclean:
-	(cd libfaim; $(MAKE) distclean)
-
 install: all installdirs
 	${INSTALL_PROGRAM} $(EXE) ${DESTDIR}${bindir}/$(EXE)
Index: m.c
===================================================================
--- aim.c	(revision e3e6cff9f72f2e4f2c72c2a48f95e45db859298d)
+++ 	(revision )
@@ -1,2759 +1,0 @@
-#include <stdio.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include "owl.h"
-
-/**********************************************************************/
-
-struct owlfaim_priv {
-  char *aimbinarypath;
-  char *screenname;
-  char *password;
-  char *server;
-  char *proxy;
-  char *proxyusername;
-  char *proxypass;
-  char *ohcaptainmycaptain;
-  int connected;
-
-  FILE *listingfile;
-  char *listingpath;
-
-  fu8_t *buddyicon;
-  int buddyiconlen;
-  time_t buddyiconstamp;
-  fu16_t buddyiconsum;
-};
-
-static char *msgerrreasons[] = {
-	"Invalid error",
-	"Invalid SNAC",
-	"Rate to host",
-	"Rate to client",
-	"Not logged on",
-	"Service unavailable",
-	"Service not defined",
-	"Obsolete SNAC",
-	"Not supported by host",
-	"Not supported by client",
-	"Refused by client",
-	"Reply too big",
-	"Responses lost",
-	"Request denied",
-	"Busted SNAC payload",
-	"Insufficient rights",
-	"In local permit/deny",
-	"Too evil (sender)",
-	"Too evil (receiver)",
-	"User temporarily unavailable",
-	"No match",
-	"List overflow",
-	"Request ambiguous",
-	"Queue full",
-	"Not while on AOL",
-};
-static int msgerrreasonslen = 25;
-
-static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
-static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...);
-int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...);
-int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...);
-void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn);
-static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...);
-static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...);
-static int conninitdone_chatnav  (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_chat     (aim_session_t *, aim_frame_t *, ...);
-int logout(aim_session_t *sess);
-
-static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...);
-/* static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); */
-static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...);
-static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname);
-static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...);
-/* static void printuserflags(fu16_t flags); */
-static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr);
-static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args);
-static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args);
-static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...);
-int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...);
-static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...);
-static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...);
-static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...);
-static int migrate(aim_session_t *sess, aim_frame_t *fr, ...);
-static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...);
-static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...);
-static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...);
-static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...);
-static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...);
-/*
-static int faimtest_ssi_parseerr     (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_parserights  (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_parselist    (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_parseack     (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_authgiven    (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_authrequest  (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_authreply    (aim_session_t *, aim_frame_t *, ...);
-static int faimtest_ssi_gotadded     (aim_session_t *, aim_frame_t *, ...);
-*/
-
-void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
-void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
-
-/*****************************************************************/
-
-void owl_aim_init(void)
-{
-  /* this has all been moved to owl_aim_login, but we'll leave the
-   * function here, in case there's stuff we want to init in the
-   * future.  It's still called by Owl.
-   */
-     
-}
-
-
-int owl_aim_login(char *screenname, char *password)
-{
-  struct owlfaim_priv *priv;
-  aim_conn_t *conn;
-  aim_session_t *sess;
-
-  sess=owl_global_get_aimsess(&g);
-
-  aim_session_init(sess, TRUE, 0);
-  aim_setdebuggingcb(sess, faimtest_debugcb);
-  aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
-  
-  /* this will leak, I know and just don't care right now */
-  priv=owl_malloc(sizeof(struct owlfaim_priv));
-  memset(priv, 0, sizeof(struct owlfaim_priv));
-
-  priv->screenname = owl_strdup(screenname);
-  priv->password = owl_strdup(password);
-  priv->server = owl_strdup(FAIM_LOGIN_SERVER);
-  sess->aux_data = priv;
-
-  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, priv->server ? priv->server : FAIM_LOGIN_SERVER);
-  /*  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); */
-  if (!conn) {
-    owl_function_error("owl_aim_login: connection error during AIM login\n");
-    owl_global_set_aimnologgedin(&g);
-    owl_global_set_no_doaimevents(&g);
-    return (-1);
-  }
-
-  /*
-  else if (conn->fd == -1) {
-    if (conn->status & AIM_CONN_STATUS_RESOLVERR) {
-      owl_function_error("owl_aim_login: could not resolve authorize name");
-    } else if (conn->status & AIM_CONN_STATUS_CONNERR) {
-      owl_function_error("owl_aim_login: could not connect to authorizer");
-    } else {
-      owl_function_error("owl_aim_login: unknown connection error");
-    }
-    owl_global_set_aimnologgedin(&g);
-    owl_global_set_no_doaimevents(&g);
-    aim_conn_kill(sess, &conn);
-    return(-1);
-  }
-  */
-
-    
-  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
-  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
-
-  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_AUTHRESPONSE, faimtest_parse_login, 0);
-  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_LOGINRESPONSE, faimtest_parse_authresp, 0);
-  /* aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); */
-  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); */
-  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); */
-    
-  /* start processing AIM events */
-  owl_global_set_doaimevents(&g);
-  /* conn->status |= AIM_CONN_STATUS_INPROGRESS; */
-  owl_function_debugmsg("owl_aim_login: sending login request for %s", screenname);
-  aim_request_login(sess, conn, screenname);
-  owl_function_debugmsg("owl_aim_login: connecting");
-
-  return(0);
-}
-
-/* stuff to run once login has been successful */
-void owl_aim_successful_login(char *screenname)
-{
-  char *buff;
-  owl_function_debugmsg("doing owl_aim_successful_login");
-  owl_global_set_aimloggedin(&g, screenname);
-  owl_global_set_doaimevents(&g); /* this should already be on */
-  owl_function_makemsg("%s logged in", screenname);
-  buff=owl_sprintf("Logged in to AIM as %s", screenname);
-  owl_function_adminmsg("", buff);
-  owl_free(buff);
-
-  owl_function_debugmsg("Successful AIM login for %s", screenname);
-
-  /* start the ingorelogin timer */
-  owl_timer_reset_newstart(owl_global_get_aim_login_timer(&g),
-			   owl_global_get_aim_ignorelogin_timer(&g));
-
-  
-  /* aim_ssi_setpresence(owl_global_get_aimsess(&g), 0x00000400); */
-  /* aim_bos_setidle(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), 5000); */
-}
-
-void owl_aim_logout(void)
-{
-  /* need to check if it's connected first, I think */
-  logout(owl_global_get_aimsess(&g));
-
-  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
-  owl_global_set_aimnologgedin(&g);
-  owl_global_set_no_doaimevents(&g);
-}
-
-void owl_aim_logged_out()
-{
-  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
-  owl_aim_logout();
-}
-
-void owl_aim_login_error(char *message)
-{
-  if (message) {
-    owl_function_error(message);
-  } else {
-    owl_function_error("Authentication error on login");
-  }
-  owl_function_beep();
-  owl_global_set_aimnologgedin(&g);
-  owl_global_set_no_doaimevents(&g);
-}
-
-int owl_aim_send_im(char *to, char *msg)
-{
-  int ret;
-
-  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, NULL, msg);
-    
-  /* I don't know how to check for an error yet */
-  return(ret);
-}
-
-int owl_aim_send_awaymsg(char *to, char *msg)
-{
-  int ret;
-
-  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, AIM_IMFLAGS_AWAY, msg);
-
-  /* I don't know how to check for an error yet */
-  return(ret);
-}
-
-void owl_aim_addbuddy(char *name)
-{
-
-  aim_ssi_addbuddy(owl_global_get_aimsess(&g), name, "Buddies", NULL, NULL, NULL, 0);
-
-  /*
-  aim_ssi_addbuddy(owl_global_get_aimsess(&g),
-		   name,
-		   "Buddies",
-		   NULL, NULL, NULL,
-		   aim_ssi_waitingforauth(owl_global_get_aimsess(&g)->ssi.local, "Buddies", name));
-  */
-}
-
-void owl_aim_delbuddy(char *name)
-{
-  aim_ssi_delbuddy(owl_global_get_aimsess(&g), name, "Buddies");
-  owl_buddylist_offgoing(owl_global_get_buddylist(&g), name);
-}
-
-void owl_aim_search(char *email)
-{
-  int ret;
-
-  owl_function_debugmsg("owl_aim_search: doing search for %s", email);
-  ret=aim_search_address(owl_global_get_aimsess(&g), 
-			 aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_BOS),
-			 email);
-
-  if (ret) owl_function_error("owl_aim_search: aim_search_address returned %i", ret);
-}
-
-
-int owl_aim_set_awaymsg(char *msg)
-{
-  int len;
-  char *foo;
-  /* there is a max away message lentgh we should check against */
-
-  foo=owl_strdup(msg);
-  len=strlen(foo);
-  if (len>500) {
-    foo[500]='\0';
-    len=499;
-  }
-    
-  aim_locate_setprofile(owl_global_get_aimsess(&g),
-			NULL, NULL, 0,
-			"us-ascii", foo, len);
-  owl_free(foo);
-
-  /*
-  aim_bos_setprofile(owl_global_get_aimsess(&g),
-		     owl_global_get_bosconn(&g),
-		     NULL, NULL, 0, "us-ascii", msg, 
-		     strlen(msg), 0);
-  */
-  return(0);
-}
-
-void owl_aim_chat_join(char *name, int exchange)
-{
-  int ret;
-  aim_conn_t *cur;
-  /*
-  OscarData *od = (OscarData *)g->proto_data;
-  char *name, *exchange;
-  */
-
-  owl_function_debugmsg("Attempting to join chatroom %s exchange %i", name, exchange);
-
-  /*
-  name = g_hash_table_lookup(data, "room");
-  exchange = g_hash_table_lookup(data, "exchange");
-  */
-  if ((cur = aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV))) {
-    owl_function_debugmsg("owl_aim_chat_join: chatnav exists, creating room");
-    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
-  } else {
-    /*    struct create_room *cr = g_new0(struct create_room, 1); */
-    owl_function_debugmsg("owl_aim_chat_join: chatnav does not exist, opening chatnav");
-    /*
-    cr->exchange = atoi(exchange);
-    cr->name = g_strdup(name);
-    od->create_rooms = g_slist_append(od->create_rooms, cr);
-    */
-    aim_reqservice(owl_global_get_aimsess(&g),
-		   aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV),
-		   AIM_CONN_TYPE_CHATNAV);
-    aim_reqservice(owl_global_get_aimsess(&g), NULL, AIM_CONN_TYPE_CHATNAV);
-    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
-    ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
-
-  }
-  return;
-  /******/
-
-
-  /* ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000); */
-  /*
-  ret=aim_chat_join(owl_global_get_aimsess(&g),
-		    aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), exchange, chatroom, 0x0000);
-  */
-
-  aim_reqservice(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), AIM_CONN_TYPE_CHATNAV);
-  ret = aim_chatnav_createroom(owl_global_get_aimsess(&g),
-			       aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), name, exchange);
-   ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
-  
-}
-
-void owl_aim_chat_leave(char *chatroom)
-{
-}
-
-int owl_aim_chat_sendmsg(char *chatroom, char *msg)
-{
-  return(0);
-}
-
-/* caller must free the return */
-char *owl_aim_normalize_screenname(char *in)
-{
-  char *out;
-  int i, j, k;
-
-  j=strlen(in);
-  out=owl_malloc(j+30);
-  k=0;
-  for (i=0; i<j; i++) {
-    if (in[i]!=' ') {
-      out[k]=in[i];
-      k++;
-    }
-  }
-  out[k]='\0';
-  return(out);
-}
-
-int owl_aim_process_events()
-{
-  aim_session_t *aimsess;
-  aim_conn_t *waitingconn = NULL;
-  struct timeval tv;
-  int selstat = 0;
-  struct owlfaim_priv *priv;
-
-  aimsess=owl_global_get_aimsess(&g);
-  priv = (struct owlfaim_priv *) &(aimsess->aux_data);
-
-  /* do a select without blocking */
-  tv.tv_sec = 0;
-  tv.tv_usec = 0;
-  waitingconn = aim_select(aimsess, &tv, &selstat);
-
-  if (owl_global_is_aimnop_time(&g)) {
-    aim_flap_nop(aimsess, aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS));
-    owl_global_aimnop_sent(&g);
-  }
-
-  if (selstat == -1) {
-    owl_aim_logged_out();
-  } else if (selstat == 0) { 
-    /* no events pending */
-  } else if (selstat == 1) { /* outgoing data pending */
-    aim_tx_flushqueue(aimsess);
-  } else if (selstat == 2) { /* incoming data pending */
-    /* printf("selstat == 2\n"); */
-    
-    if (aim_get_command(aimsess, waitingconn) >= 0) {
-      aim_rxdispatch(aimsess);
-    } else {
-      /* printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype); */
-      /* we should have callbacks for all these, else the library will do the conn_kill for us. */
-      if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
-	if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
-	  /* printf("disconnected from %s\n", aim_directim_getsn(waitingconn)); */
-	  aim_conn_kill(aimsess, &waitingconn);
-	  owl_aim_logged_out();
-	}
-      } else {
-	aim_conn_kill(aimsess, &waitingconn);
-	owl_aim_logged_out();
-      }
-      if (!aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS)) {
-	/* printf("major connection error\n"); */
-	owl_aim_logged_out();
-	/* break; */
-      }
-    }
-  }
-  /* free(priv->buddyicon); */
-  /* exit(0); */
-  return(0);
-}
-
-static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
-{
-  return;
-}
-
-static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
-    
-  char *key;
-  va_list ap;
-
-  va_start(ap, fr);
-  key = va_arg(ap, char *);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_parse_login: %s %s %s", priv->screenname, priv->password, key);
-
-  aim_send_login(sess, fr->conn, priv->screenname, priv->password, &info, key);
-  
-  return(1);
-}
-
-
-static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  struct aim_authresp_info *info;
-  aim_conn_t *bosconn;
-
-  va_start(ap, fr);
-  info = va_arg(ap, struct aim_authresp_info *);
-  va_end(ap);
-
-  /* printf("Screen name: %s\n", info->sn); */
-  owl_function_debugmsg("doing faimtest_parse_authresp");
-  owl_function_debugmsg("faimtest_parse_authresp: %s", info->sn);
-
-  /*
-   * Check for error.
-   */
-  if (info->errorcode || !info->bosip || !info->cookie) {
-    /*
-    printf("Login Error Code 0x%04x\n", info->errorcode);
-    printf("Error URL: %s\n", info->errorurl);
-    */
-    if (info->errorcode==0x05) {
-      owl_aim_login_error("Incorrect nickname or password.");
-    } else if (info->errorcode==0x11) {
-      owl_aim_login_error("Your account is currently suspended.");
-    } else if (info->errorcode==0x14) {
-      owl_aim_login_error("The AOL Instant Messenger service is temporarily unavailable.");
-    } else if (info->errorcode==0x18) {
-      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.");
-    } else if (info->errorcode==0x1c) {
-      owl_aim_login_error("The client version you are using is too old.");
-    } else {
-      owl_aim_login_error(NULL);
-    }
-    aim_conn_kill(sess, &fr->conn);
-    return(1);
-  }
-
-  /*
-  printf("Reg status: %d\n", info->regstatus);
-  printf("Email: %s\n", info->email);
-  printf("BOS IP: %s\n", info->bosip);
-  */
-
-  /* printf("Closing auth connection...\n"); */
-  aim_conn_kill(sess, &fr->conn);
-  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, info->bosip))) {
-    /* printf("could not connect to BOS: internal error\n"); */
-    return(1);
-  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
-    /* printf("could not connect to BOS\n"); */
-    aim_conn_kill(sess, &bosconn);
-    return(1);
-  }
-  owl_global_set_bossconn(&g, bosconn);
-  owl_aim_successful_login(info->sn);
-  addcb_bos(sess, bosconn);
-  aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
-  return(1);
-}
-
-int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("doing faimtest_flapversion");
-
-#if 0
-  /* XXX fix libfaim to support this */
-  printf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
-
-  /*
-   * This is an alternate location for starting the login process.
-   */
-  /* XXX should do more checking to make sure its really the right AUTH conn */
-  if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
-    /* do NOT send a flapversion, request_login will send it if needed */
-    aim_request_login(sess, fr->conn, priv->screenname);
-    /* printf("faimtest: login request sent\n"); */
-  }
-#endif
-
-  return 1;
-}
-
-
-int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("doing faimtest_conncomplete");
-  /* owl_aim_successful_login(info->sn); */
-  return 1;
-}
-
-void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
-{
-  owl_function_debugmsg("doing addcb_bos");
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
-
-  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0003,                        ssirights, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0006,                        ssidata, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0013,         0x000f,                        ssidatanochange, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0008,         0x0002,                        handlepopup, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0003,                        faimtest_bosrights, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT,           faimtest_handleredirect, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL,  faimtest_reportinterval, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO,         faimtest_parse_buddyrights, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD,               faimtest_parse_motd, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0004,         0x0005,                        faimtest_icbmparaminfo, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,    faimtest_parse_connerr, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO,         faimtest_locrights, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0001,         0x001f,                        faimtest_memrequest, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING,           faimtest_parse_oncoming, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING,           faimtest_parse_offgoing, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING,           faimtest_parse_incoming_im, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR,              faimtest_parse_locerr, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL,         faimtest_parse_misses, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE,         faimtest_parse_ratechange, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL,               faimtest_parse_evilnotify, 0);
-
-  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0001,                        faimtest_parse_searcherror, 0);
-  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0003,                        faimtest_parse_searchreply, 0);
-
-  /*
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, faimtest_parse_searcherror, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, faimtest_parse_searchreply, 0);
-  */
-  
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR,              faimtest_parse_msgerr, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO,           faimtest_parse_userinfo, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK,                faimtest_parse_msgack, 0);
-
-  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0001,                        faimtest_parse_genericerr, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0003,         0x0001,                        faimtest_parse_genericerr, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0001,                        faimtest_parse_genericerr, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0001,         0x000b,                        serverpause, 0);
-  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0012,                        migrate, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG,         offlinemsg, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, offlinemsgdone, 0);
-
-  /*
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,     gaim_connerr, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0);
-  */
-
-  /*
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ERROR,              faimtest_ssi_parseerr, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO,         faimtest_ssi_parserights, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST,               faimtest_ssi_parselist, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_NOLIST,             faimtest_ssi_parselist, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK,             faimtest_ssi_parseack, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTH,           faimtest_ssi_authgiven, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREQ,        faimtest_ssi_authrequest, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREP,        faimtest_ssi_authreply, 0);
-  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ADDED,              faimtest_ssi_gotadded, 0);
-  */
-
-  return;
-}
-
-static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("doing coninitdone_bos");
-
-
-  aim_reqpersonalinfo(sess, fr->conn);
-  aim_ssi_reqrights(sess);
-  aim_ssi_reqdata(sess);
-  aim_locate_reqrights(sess);
-  aim_buddylist_reqrights(sess, fr->conn);
-
-  aim_im_reqparams(sess);
-  /* aim_bos_reqrights(sess, fr->conn); */ /* XXX - Don't call this with ssi */
-
-  owl_function_debugmsg("conninitdone_bos: requesting rights");
-  aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
-  aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
-  aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
-
-  return(1);
-}
-
-static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_clientready(sess, fr->conn);
-  owl_function_debugmsg("conninitdone_admin: initializtion done for admin connection");
-  return(1);
-}
-
-int logout(aim_session_t *sess)
-{
-  aim_session_kill(sess);
-  owl_aim_init();
-
-  owl_function_debugmsg("libfaim logout called");
-  /*
-  if (faimtest_init() == -1)
-    printf("faimtest_init failed\n");
-  */
-
-  return(0);
-}
-
-/**************************************************************************************************/
-
-static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  va_list ap;
-  fu16_t code;
-  char *msg;
-  
-  va_start(ap, fr);
-  code = va_arg(ap, int);
-  msg = va_arg(ap, char *);
-  va_end(ap);
-  
-  owl_function_error("faimtest_parse_connerr: Code 0x%04x: %s\n", code, msg);
-  aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
-  
-  priv->connected = 0;
-  
-  return 1;
-}
-
-static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  int status;
-  va_list ap;
-  
-  va_start(ap, fr);
-  status = va_arg(ap, int); /* status code of confirmation request */
-  va_end(ap);
-
-  /* owl_function_debugmsg("faimtest_accountconfirm: Code 0x%04x: %s\n", code, msg); */
-  owl_function_debugmsg("faimtest_accountconfirm: account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
-  
-  return 1;
-}
-
-static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  fu16_t change = 0, perms, type;
-  int length, str;
-  char *val;
-  va_list ap;
-  
-  va_start(ap, fr);
-  change = va_arg(ap, int);
-  perms = (fu16_t)va_arg(ap, unsigned int);
-  type = (fu16_t)va_arg(ap, unsigned int);
-  length = va_arg(ap, int);
-  val = va_arg(ap, char *);
-  str = va_arg(ap, int);
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_infochange: info%s: perms = %d, type = %x, length = %d, val = %s", change?" change":"", perms, type, length, str?val:"(not string)");
-  
-  return(1);
-}
-
-
-static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  struct aim_redirect_data *redir;
-
-  owl_function_debugmsg("faimtest_handledirect:");
-  
-  va_start(ap, fr);
-  redir = va_arg(ap, struct aim_redirect_data *);
-  
-  if (redir->group == 0x0005) {  /* Adverts */
-    
-  } else if (redir->group == 0x0007) {  /* Authorizer */
-    aim_conn_t *tstconn;
-
-    owl_function_debugmsg("faimtest_handledirect: autorizer");
-    
-    tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, redir->ip);
-    if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
-      owl_function_error("faimtest_handleredirect: unable to reconnect with authorizer");
-    } else {
-      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
-      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
-      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
-      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
-      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
-      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
-      /* Send the cookie to the Auth */
-      aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-      owl_function_debugmsg("faimtest_handleredirect: sent cookie to authorizer host");
-    }
-  } else if (redir->group == 0x000d) {  /* ChatNav */
-    owl_function_debugmsg("faimtest_handledirect: chatnav");
-    chatnav_redirect(sess, redir);
-  } else if (redir->group == 0x000e) { /* Chat */
-    owl_function_debugmsg("faimtest_handledirect: chat");
-    chat_redirect(sess, redir);
-  } else {
-    owl_function_debugmsg("faimtest_handleredirect: uh oh... got redirect for unknown service 0x%04x!!", redir->group);
-  }
-  va_end(ap);
-  return 1;
-}
-
-static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  struct aim_icbmparameters *params;
-  va_list ap;
-  
-  va_start(ap, fr);
-  params = va_arg(ap, struct aim_icbmparameters *);
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_icbmparaminfo: ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %ld",
-		       params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval);
-     
-  /*
-  * Set these to your taste, or client medium.  Setting minmsginterval
-  * higher is good for keeping yourself from getting flooded (esp
-  * if you're on a slow connection or something where that would be
-  * useful).
-  */
-  params->maxmsglen = 8000;
-  params->minmsginterval = 0; /* in milliseconds */
-  /* aim_seticbmparam(sess, params); */
-  aim_im_setparams(sess, params);
-  
-  return 1;
-}
-
-static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t maxbuddies, maxwatchers;
-  
-  va_start(ap, fr);
-  maxbuddies = va_arg(ap, int);
-  maxwatchers = va_arg(ap, int);
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_parse_buddyrights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
-  
-  /* aim_ssi_reqrights(sess, fr->conn); */
-  aim_ssi_reqrights(sess);
-  
-  return 1;
-}
-
-static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t maxpermits, maxdenies;
-  
-  va_start(ap, fr);
-  maxpermits = va_arg(ap, int);
-  maxdenies = va_arg(ap, int);
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_bosrights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
-  aim_clientready(sess, fr->conn);
-  owl_function_debugmsg("officially connected to BOS.");
-  aim_icq_reqofflinemsgs(sess);
-  return 1;
-}
-
-static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t maxsiglen;
-  
-  va_start(ap, fr);
-  maxsiglen = va_arg(ap, int);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_locrights: rights: max signature length = %d\n", maxsiglen);
-  
-  return(1);
-}
-
-static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  va_list ap;
-  fu16_t interval;
-
-  va_start(ap, fr);
-  interval = va_arg(ap, int);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_reportinterval: %d (seconds?)\n", interval);
-
-  if (!priv->connected) {
-    priv->connected++;
-  }
-  /* aim_reqicbmparams(sess); */
-  aim_im_reqparams(sess);
-  /* kretch */
-  return 1;
-}
-
-static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  char *msg;
-  fu16_t id;
-  va_list ap;
-  static int codeslen = 5;
-  static char *codes[] = {
-    "Unknown",
-    "Mandatory upgrade",
-    "Advisory upgrade",
-    "System bulletin",
-    "Top o' the world!"
-  };
-
-  va_start(ap, fr);
-  id = va_arg(ap, int);
-  msg = va_arg(ap, char *);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_parse_motd: %s (%d / %s)\n", msg?msg:"nomsg", id, (id < codeslen)?codes[id]:"unknown");
-  
-  return 1;
-}
-
-/*
- * This is a little more complicated than it looks.  The module
- * name (proto, boscore, etc) may or may not be given.  If it is
- * not given, then use aim.exe.  If it is given, put ".ocm" on the
- * end of it.
- *
- * Now, if the offset or length requested would cause a read past
- * the end of the file, then the request is considered invalid.  Invalid
- * requests are processed specially.  The value hashed is the
- * the request, put into little-endian (eight bytes: offset followed
- * by length).  
- *
- * Additionally, if the request is valid, the length is mod 4096.  It is
- * important that the length is checked for validity first before doing
- * the mod.
- *
- * Note to Bosco's Brigade: if you'd like to break this, put the 
- * module name on an invalid request.
- *
- */
-static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  FILE *f;
-  static const char defaultmod[] = "aim.exe";
-  char *filename = NULL;
-  struct stat st;
-  unsigned char *buf;
-  int invalid = 0;
-  
-  if (!bufret || !buflenret)
-    return -1;
-  
-  if (modname) {
-    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
-      /* perror("memrequest: malloc"); */
-      return -1;
-    }
-    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
-  } else {
-    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
-      /* perror("memrequest: malloc"); */
-      return -1;
-    }
-    sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
-  }
-  
-  if (stat(filename, &st) == -1) {
-    if (!modname) {
-      /* perror("memrequest: stat"); */
-      owl_free(filename);
-      return -1;
-    }
-    invalid = 1;
-  }
-  
-  if (!invalid) {
-    if ((offset > st.st_size) || (len > st.st_size))
-      invalid = 1;
-    else if ((st.st_size - offset) < len)
-      len = st.st_size - offset;
-    else if ((st.st_size - len) < len)
-      len = st.st_size - len;
-  }
-  
-  if (!invalid && len) {
-    len %= 4096;
-  }
-  
-  if (invalid) {
-    int i;
-    
-    owl_free(filename); /* not needed */
-    owl_function_error("getaimdata memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
-    i = 8;
-    if (modname) {
-      i+=strlen(modname);
-    }
-    
-    if (!(buf = owl_malloc(i))) {
-      return -1;
-    }
-    
-    i=0;
-    
-    if (modname) {
-      memcpy(buf, modname, strlen(modname));
-      i+=strlen(modname);
-    }
-    
-    /* Damn endianness. This must be little (LSB first) endian. */
-    buf[i++] = offset & 0xff;
-    buf[i++] = (offset >> 8) & 0xff;
-    buf[i++] = (offset >> 16) & 0xff;
-    buf[i++] = (offset >> 24) & 0xff;
-    buf[i++] = len & 0xff;
-    buf[i++] = (len >> 8) & 0xff;
-    buf[i++] = (len >> 16) & 0xff;
-    buf[i++] = (len >> 24) & 0xff;
-    
-    *bufret = buf;
-    *buflenret = i;
-  } else {
-    if (!(buf = owl_malloc(len))) {
-      owl_free(filename);
-      return -1;
-    }
-    /* printf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename); */
-    if (!(f = fopen(filename, "r"))) {
-      /* perror("memrequest: fopen"); */
-      owl_free(filename);
-      owl_free(buf);
-      return -1;
-    }
-    
-    owl_free(filename);
-    
-    if (fseek(f, offset, SEEK_SET) == -1) {
-      /* perror("memrequest: fseek"); */
-      fclose(f);
-      owl_free(buf);
-      return -1;
-    }
-    
-    if (fread(buf, len, 1, f) != 1) {
-      /* perror("memrequest: fread"); */
-      fclose(f);
-      owl_free(buf);
-      return -1;
-    }
-    
-    fclose(f);
-    *bufret = buf;
-    *buflenret = len;
-  }
-  return 0; /* success! */
-}
-
-/*
- * This will get an offset and a length.  The client should read this
- * data out of whatever AIM.EXE binary the user has provided (hopefully
- * it matches the client information thats sent at login) and pass a
- * buffer back to libfaim so it can hash the data and send it to AOL for
- * inspection by the client police.
- */
-static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  va_list ap;
-  fu32_t offset, len;
-  char *modname;
-  unsigned char *buf;
-  int buflen;
-  
-  va_start(ap, fr);
-  offset = va_arg(ap, fu32_t);
-  len = va_arg(ap, fu32_t);
-  modname = va_arg(ap, char *);
-  va_end(ap);
-  
-  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
-    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
-    owl_free(buf);
-  } else {
-    owl_function_debugmsg("faimtest_memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
-    aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
-  }
-  return 1;
-}
-
-/*
-static void printuserflags(fu16_t flags)
-{
-  if (flags & AIM_FLAG_UNCONFIRMED) printf("UNCONFIRMED ");
-  if (flags & AIM_FLAG_ADMINISTRATOR) printf("ADMINISTRATOR ");
-  if (flags & AIM_FLAG_AOL) printf("AOL ");
-  if (flags & AIM_FLAG_OSCAR_PAY) printf("OSCAR_PAY ");
-  if (flags & AIM_FLAG_FREE) printf("FREE ");
-  if (flags & AIM_FLAG_AWAY) printf("AWAY ");
-  if (flags & AIM_FLAG_ICQ) printf("ICQ ");
-  if (flags & AIM_FLAG_WIRELESS) printf("WIRELESS ");
-  if (flags & AIM_FLAG_ACTIVEBUDDY) printf("ACTIVEBUDDY ");
-  
-  return;
-}
-*/
-
-static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_userinfo_t *userinfo;
-  char *prof_encoding = NULL;
-  char *prof = NULL;
-  fu16_t inforeq = 0;
-  owl_buddy *b;
-  va_list ap;
-  va_start(ap, fr);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  inforeq = (fu16_t)va_arg(ap, unsigned int);
-  prof_encoding = va_arg(ap, char *);
-  prof = va_arg(ap, char *);
-  va_end(ap);
-
-  /* right now the only reason we call this is for idle times */
-  owl_function_debugmsg("parse_userinfo sn: %s idle: %i", userinfo->sn, userinfo->idletime);
-  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g),
-				userinfo->sn);
-  if (!b) return(1);
-  owl_buddy_set_idle_since(b, userinfo->idletime);
-  return(1);
-
-  /*
-  printf("userinfo: sn: %s\n", userinfo->sn);
-  printf("userinfo: warnlevel: %f\n", aim_userinfo_warnlevel(userinfo));
-  printf("userinfo: flags: 0x%04x = ", userinfo->flags);
-  printuserflags(userinfo->flags);
-  printf("\n");
-  */
-
-  /*
-  printf("userinfo: membersince: %lu\n", userinfo->membersince);
-  printf("userinfo: onlinesince: %lu\n", userinfo->onlinesince);
-  printf("userinfo: idletime: 0x%04x\n", userinfo->idletime);
-  printf("userinfo: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
-  */
-
-  /*
-  if (inforeq == AIM_GETINFO_GENERALINFO) {
-    owl_function_debugmsg("userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
-    owl_function_debugmsg("userinfo: prof: %s\n", prof ? prof : "[none]");
-  } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
-    owl_function_debugmsg("userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
-    owl_function_debugmsg("userinfo: awaymsg: %s\n", prof ? prof : "[none]");
-  } else if (inforeq == AIM_GETINFO_CAPABILITIES) {
-    owl_function_debugmsg("userinfo: capabilities: see above\n");
-  } else {
-    owl_function_debugmsg("userinfo: unknown info request\n");
-  }
-  */
-  return(1);
-}
-
-#if 0
-static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  
-  if (!strncmp(tmpstr, "disconnect", 10)) {
-    logout(sess);
-  } else if (strstr(tmpstr, "goodday")) {
-    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too."); */
-  } else if (strstr(tmpstr, "haveicon") && priv->buddyicon) {
-    struct aim_sendimext_args args;
-    /* static const char iconmsg[] = {"I have an icon"}; */
-    static const char iconmsg[] = {""};
-    
-    args.destsn = userinfo->sn;
-    args.flags = AIM_IMFLAGS_HASICON;
-    args.msg = iconmsg;
-    args.msglen = strlen(iconmsg);
-    args.iconlen = priv->buddyiconlen;
-    args.iconstamp = priv->buddyiconstamp;
-    args.iconsum = priv->buddyiconsum;
-    
-    /* aim_send_im_ext(sess, &args); */
-    
-  } else if (strstr(tmpstr, "sendbin")) {
-    struct aim_sendimext_args args;
-    static const unsigned char data[] = {
-      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    };
-    
-    /*
-     * I put this here as a demonstration of how to send 
-     * arbitrary binary data via OSCAR ICBM's without the need
-     * for escape or baseN encoding of any sort.  
-     *
-     * Apparently if you set the charset to something WinAIM
-     * doesn't recognize, it will completly ignore the message.
-     * That is, it will not display anything in the conversation
-     * window for the user that recieved it.
-     *
-     * HOWEVER, if they do not have a conversation window open
-     * for you, a new one will be created, but it will not have
-     * any messages in it.  Therefore sending these things could
-     * be a great way to seemingly subliminally convince people
-     * to talk to you...
-     *
-     */
-    args.destsn = userinfo->sn;
-    /* args.flags = AIM_IMFLAGS_CUSTOMCHARSET; */
-    args.charset = args.charsubset = 0x4242;
-    args.msg = data;
-    args.msglen = sizeof(data);
-    /* aim_send_im_ext(sess, &args); */
-   } else if (strstr(tmpstr, "sendmulti")) {
-    struct aim_sendimext_args args;
-    aim_mpmsg_t mpm;
-    static const fu16_t unidata[] = { /* "UNICODE." */
-      0x0055, 0x004e, 0x0049, 0x0043,
-      0x004f, 0x0044, 0x0045, 0x002e,
-    };
-    static const int unidatalen = 8;
-    
-    /*
-     * This is how multipart messages should be sent.
-     *
-     * This should render as:
-     *        "Part 1, ASCII.  UNICODE.Part 3, ASCII.  "
-     */
-    
-    aim_mpmsg_init(sess, &mpm);
-    aim_mpmsg_addascii(sess, &mpm, "Part 1, ASCII.  ");
-    aim_mpmsg_addunicode(sess, &mpm, unidata, unidatalen);
-    aim_mpmsg_addascii(sess, &mpm, "Part 3, ASCII.  ");
-    
-    args.destsn = userinfo->sn;
-    args.flags = AIM_IMFLAGS_MULTIPART;
-    args.mpmsg = &mpm;
-    
-    /* aim_send_im_ext(sess, &args); */
-    
-    aim_mpmsg_free(sess, &mpm);
-    
-  } else if (strstr(tmpstr, "sendprebin")) {
-    static const unsigned char data[] = {
-      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    };
-    struct aim_sendimext_args args;
-    aim_mpmsg_t mpm;
-    
-    /*
-     * This demonstrates sending a human-readable preamble,
-     * and then arbitrary binary data.
-     *
-     * This means that you can very inconspicuously send binary
-     * attachments to other users.  In WinAIM, this appears as
-     * though it only had the ASCII portion.
-     *
-     */
-    
-    aim_mpmsg_init(sess, &mpm);
-    aim_mpmsg_addascii(sess, &mpm, "This message has binary data.");
-    aim_mpmsg_addraw(sess, &mpm, 0x4242, 0x4242, data, sizeof(data));
-    
-    args.destsn = userinfo->sn;
-    args.flags = AIM_IMFLAGS_MULTIPART;
-    args.mpmsg = &mpm;
-    
-    /* aim_send_im_ext(sess, &args); */
-    aim_mpmsg_free(sess, &mpm);
-    
-  } else if (strstr(tmpstr, "havefeat")) {
-    struct aim_sendimext_args args;
-    static const char featmsg[] = {"I have nifty features."};
-    fu8_t features[] = {0x01, 0x01, 0x01, 0x02, 0x42, 0x43, 0x44, 0x45};
-    
-    args.destsn = userinfo->sn;
-    args.flags = AIM_IMFLAGS_CUSTOMFEATURES;
-    args.msg = featmsg;
-    args.msglen = strlen(featmsg);
-    args.features = features;
-    args.featureslen = sizeof(features);
-    
-    /* aim_send_im_ext(sess, &args); */
-  } else if (strstr(tmpstr, "sendicon") && priv->buddyicon) {
-    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
-  } else if (strstr(tmpstr, "warnme")) {
-    /* printf("icbm: sending non-anon warning\n"); */
-    /* aim_send_warning(sess, conn, userinfo->sn, 0); */
-  } else if (strstr(tmpstr, "anonwarn")) {
-    /* printf("icbm: sending anon warning\n"); */
-    /* aim_send_warning(sess, conn, userinfo->sn, AIM_WARN_ANON); */
-  } else if (strstr(tmpstr, "setdirectoryinfo")) {
-    /* printf("icbm: sending backwards profile data\n"); */
-    aim_setdirectoryinfo(sess, conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
-  } else if (strstr(tmpstr, "setinterests")) {
-    /* printf("icbm: setting fun interests\n"); */
-    aim_setuserinterests(sess, conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
-  } else if (!strncmp(tmpstr, "open chatnav", 12)) {
-    aim_reqservice(sess, conn, AIM_CONN_TYPE_CHATNAV);
-  } else if (!strncmp(tmpstr, "create", 6)) {
-    aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
-  } else if (!strncmp(tmpstr, "close chatnav", 13)) {
-    aim_conn_t *chatnavconn;
-    if ((chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)))
-      aim_conn_kill(sess, &chatnavconn);
-  } else if (!strncmp(tmpstr, "join", 4)) {
-    aim_chat_join(sess, conn, 0x0004, "worlddomination", 0x0000);
-  } else if (!strncmp(tmpstr, "leave", 5)) {
-    aim_chat_leaveroom(sess, "worlddomination");
-  } else if (!strncmp(tmpstr, "getinfo", 7)) {
-    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_GENERALINFO);
-    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
-    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_CAPABILITIES);
-  } else if(strstr(tmpstr, "lookup")) {
-    /* aim_usersearch_address(sess, conn, "mid@auk.cx"); */
-  } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
-    /* aim_send_im(sess, priv->ohcaptainmycaptain, 0, "sendmsg 7900"); */
-  } else if (!strncmp(tmpstr, "reqadmin", 8)) {
-    aim_reqservice(sess, conn, AIM_CONN_TYPE_AUTH);
-  } else if (!strncmp(tmpstr, "changenick", 10)) {
-    aim_admin_setnick(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "diputs8  1");
-  } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
-    aim_admin_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
-  } else if (!strncmp(tmpstr, "reqemail", 8)) {
-    aim_admin_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
-  } else if (!strncmp(tmpstr, "changepass", 8)) {
-    aim_admin_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
-  } else if (!strncmp(tmpstr, "setemail", 8)) {
-    aim_admin_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
-  } else if (!strncmp(tmpstr, "sendmsg", 7)) {
-    int i;
-    
-    i = atoi(tmpstr+8);
-    if (i < 10000) {
-      char *newbuf;
-      int z;
-      
-      newbuf = owl_malloc(i+1);
-      for (z = 0; z < i; z++)
-	newbuf[z] = (z % 10)+0x30;
-      newbuf[i] = '\0';
-      /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK | AIM_IMFLAGS_AWAY, newbuf); */
-      owl_free(newbuf);
-    }
-  } else if (strstr(tmpstr, "seticqstatus")) {
-    aim_setextstatus(sess, AIM_ICQ_STATE_DND);
-  } else if (strstr(tmpstr, "rtfmsg")) {
-    static const char rtfmsg[] = {"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\froman\\fprq2\\fcharset0 Georgia;}{\\f2\\fmodern\\fprq1\\fcharset0 MS Mincho;}{\\f3\\froman\\fprq2\\fcharset2 Symbol;}}\\viewkind4\\uc1\\pard\\f0\\fs20 Test\\f1 test\\f2\fs44 test\\f3\\fs20 test\\f0\\par}"};
-    struct aim_sendrtfmsg_args rtfargs;
-    
-    memset(&rtfargs, 0, sizeof(rtfargs));
-    rtfargs.destsn = userinfo->sn;
-    rtfargs.fgcolor = 0xffffffff;
-    rtfargs.bgcolor = 0x00000000;
-    rtfargs.rtfmsg = rtfmsg;
-    /* aim_send_rtfmsg(sess, &rtfargs); */
-  } else {
-    /* printf("unknown command.\n"); */
-    aim_add_buddy(sess, conn, userinfo->sn);
-  }  
-  
-  return 0;
-}
-#endif
-
-/*
- * Channel 1: Standard Message
- */
-static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args)
-{
-  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
-  owl_message *m;
-  char *stripmsg, *nz_screenname, *wrapmsg;
-  char realmsg[8192+1] = {""};
-  /* int clienttype = AIM_CLIENTTYPE_UNKNOWN; */
-
-  /* clienttype = aim_fingerprintclient(args->features, args->featureslen); */
-
-  /*
-  printf("icbm: sn = \"%s\"\n", userinfo->sn);
-  printf("icbm: probable client type: %d\n", clienttype);
-  printf("icbm: warnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
-  printf("icbm: flags = 0x%04x = ", userinfo->flags);
-  printuserflags(userinfo->flags);
-  printf("\n");
-  */
-
-  /*
-  printf("icbm: membersince = %lu\n", userinfo->membersince);
-  printf("icbm: onlinesince = %lu\n", userinfo->onlinesince);
-  printf("icbm: idletime = 0x%04x\n", userinfo->idletime);
-  printf("icbm: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
-  */
-
-  /*
-  printf("icbm: icbmflags = ");
-  if (args->icbmflags & AIM_IMFLAGS_AWAY) printf("away ");
-  if (args->icbmflags & AIM_IMFLAGS_ACK) printf("ackrequest ");
-  if (args->icbmflags & AIM_IMFLAGS_OFFLINE) printf("offline ");
-  if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) printf("buddyreq ");
-  if (args->icbmflags & AIM_IMFLAGS_HASICON) printf("hasicon ");
-  printf("\n");
-  */
-
-  /*
-  if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET) {
-  printf("icbm: encoding flags = {%04x, %04x}\n", args->charset, args->charsubset);
-  }
-  */
-  
-  /*
-   * Quickly convert it to eight bit format, replacing non-ASCII UNICODE 
-   * characters with their equivelent HTML entity.
-   */
-  if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
-    int i;
-    
-    for (i=0; i<args->msglen; i+=2) {
-      fu16_t uni;
-
-      uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
-      if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
-	snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
-      } else { /* something else, do UNICODE entity */
-	snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
-      }
-    }
-  } else {
-    /*
-     * For non-UNICODE encodings (ASCII and ISO 8859-1), there is 
-     * no need to do anything special here.  Most 
-     * terminals/whatever will be able to display such characters 
-     * unmodified.
-     *
-     * Beware that PC-ASCII 128 through 159 are _not_ actually 
-     * defined in ASCII or ISO 8859-1, and you should send them as 
-     * UNICODE.  WinAIM will send these characters in a UNICODE 
-     * message, so you need to do so as well.
-     *
-     * You may not think it necessary to handle UNICODE messages.  
-     * You're probably wrong.  For one thing, Microsoft "Smart
-     * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
-     * but real UNICODE). If you don't parse UNICODE at all, your 
-     * users will get a blank message instead of the message 
-     * containing Smart Quotes.
-     *
-     */
-    if (args->msg && args->msglen)
-      strncpy(realmsg, args->msg, sizeof(realmsg));
-  }
-
-  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: message from: %s", userinfo->sn?userinfo->sn:"");
-  /* create a message, and put it on the message queue */
-  stripmsg=owl_text_htmlstrip(realmsg);
-  wrapmsg=owl_text_wordwrap(stripmsg, 70);
-  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
-  m=owl_malloc(sizeof(owl_message));
-  owl_message_create_aim(m,
-			 nz_screenname,
-			 owl_global_get_aim_screenname(&g),
-			 wrapmsg,
-			 OWL_MESSAGE_DIRECTION_IN,
-			 0);
-  if (args->icbmflags & AIM_IMFLAGS_AWAY) owl_message_set_attribute(m, "isauto", "");
-  owl_global_messagequeue_addmsg(&g, m);
-  owl_free(stripmsg);
-  owl_free(wrapmsg);
-  owl_free(nz_screenname);
-
-  return(1);
-
-  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: message: %s\n", realmsg);
-  
-  if (args->icbmflags & AIM_IMFLAGS_MULTIPART) {
-    aim_mpmsg_section_t *sec;
-    int z;
-
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart: this message has %d parts\n", args->mpmsg.numparts);
-    
-    for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++) {
-      if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff)) {
-	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);
-      } else {
-	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);
-      }
-    }
-  }
-  
-  if (args->icbmflags & AIM_IMFLAGS_HASICON) {
-    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon"); */
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: their icon: iconstamp = %ld, iconlen = 0x%08lx, iconsum = 0x%04x\n", args->iconstamp, args->iconlen, args->iconsum);
-  }
-
-  /*
-  if (realmsg) {
-    int i = 0;
-    while (realmsg[i] == '<') {
-      if (realmsg[i] == '<') {
-	while (realmsg[i] != '>')
-	  i++;
-	i++;
-      }
-    }
-    tmpstr = realmsg+i;
-    faimtest_handlecmd(sess, conn, userinfo, tmpstr);
-  }
-  */
-  
-  if (priv->buddyicon && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
-    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
-  }
-  
-  return(1);
-}
-
-/*
- * Channel 2: Rendevous Request
- */
-static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args)
-{
-  /* 
-  printf("rendezvous: source sn = %s\n", userinfo->sn);
-  printf("rendezvous: \twarnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
-  printf("rendezvous: \tclass = 0x%04x = ", userinfo->flags);
-  printuserflags(userinfo->flags);
-  printf("\n");
-  
-  printf("rendezvous: \tonlinesince = %lu\n", userinfo->onlinesince);
-  printf("rendezvous: \tidletime = 0x%04x\n", userinfo->idletime);
-  
-  printf("rendezvous: message/description = %s\n", args->msg);
-  printf("rendezvous: encoding = %s\n", args->encoding);
-  printf("rendezvous: language = %s\n", args->language);
-  */
-  
-  if (args->reqclass == AIM_CAPS_SENDFILE) {
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: send file!");
-  } else if (args->reqclass == AIM_CAPS_CHAT) {
-    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);
-    /*
-    printf("chat invitation: room name = %s\n", args->info.chat.roominfo.name);
-    printf("chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
-    printf("chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
-    */
-    /* Automatically join room... */
-    /* printf("chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name); */
-
-    /* aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance); */
-  } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: Buddy Icon from %s, length = %lu\n",
-			  userinfo->sn, args->info.icon.length);
-  } else if (args->reqclass == AIM_CAPS_ICQRTF) {
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: RTF message from %s: (fgcolor = 0x%08lx, bgcolor = 0x%08lx) %s\n",
-			  userinfo->sn, args->info.rtfmsg.fgcolor, args->info.rtfmsg.bgcolor, args->info.rtfmsg.rtfmsg);
-  } else {
-    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: icbm: unknown reqclass (%d)\n", args->reqclass);
-  }
-  return 1;
-}
-
-static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  fu16_t channel;
-  aim_userinfo_t *userinfo;
-  va_list ap;
-  int ret = 0;
-  
-  va_start(ap, fr);
-  channel = (fu16_t)va_arg(ap, unsigned int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  
-  if (channel == 1) {
-    struct aim_incomingim_ch1_args *args;
-    args = va_arg(ap, struct aim_incomingim_ch1_args *);
-    ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
-  } else if (channel == 2) {
-    struct aim_incomingim_ch2_args *args;
-    args = va_arg(ap, struct aim_incomingim_ch2_args *);
-    ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
-  } else {
-    owl_function_debugmsg("faimtest_parse_incoming_im: unsupported channel 0x%04x\n", channel);
-  }
-  va_end(ap);
-  owl_function_debugmsg("faimtest_parse_incoming_im: done with ICBM handling (ret = %d)\n", ret);
-  return 1;
-}
-
-static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_userinfo_t *userinfo;
-  char *nz_screenname;
-  owl_buddy *b;
-  owl_buddylist *bl;
-  va_list ap;
-  va_start(ap, fr);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  va_end(ap);
-
-  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
-  bl=owl_global_get_buddylist(&g);
-  
-  owl_buddylist_oncoming(owl_global_get_buddylist(&g), nz_screenname);
-
-  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
-    owl_function_debugmsg("faimtest_parseoncoming: in empty part of userinfo present and present idle");
-  }
-
-  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g), nz_screenname);
-  if (!b) {
-    owl_function_debugmsg("Error: parse_oncoming setting idle time with no buddy present.");
-    return(1);
-  }
-  if (userinfo->idletime==0) {
-    owl_buddy_set_unidle(b);
-  } else {
-    owl_buddy_set_idle(b);
-    owl_buddy_set_idle_since(b, userinfo->idletime);
-  }
-
-  if (userinfo->flags & AIM_FLAG_AWAY) {
-    owl_function_debugmsg("parse_oncoming sn: %s away flag!", userinfo->sn);
-  }
-  
-  owl_function_debugmsg("parse_oncoming sn: %s idle: %i", userinfo->sn, userinfo->idletime);
-    
-  owl_free(nz_screenname);
-  
-  /*
-    printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
-    time(NULL),
-    userinfo->sn, userinfo->flags,
-    (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
-    (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
-    (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
-    (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
-    (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
-    (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
-    (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
-    (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
-    (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
-    userinfo->capabilities);
-  */
-  return(1);
-}
-
-static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_userinfo_t *userinfo;
-  char *nz_screenname;
-  va_list ap;
-  
-  va_start(ap, fr);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  va_end(ap);
-
-  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
-  owl_buddylist_offgoing(owl_global_get_buddylist(&g), nz_screenname);
-  owl_free(nz_screenname);
-
-  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
-    owl_function_debugmsg("parse_offgoing sn: %s idle time %i", userinfo->sn, userinfo->idletime);
-  }
-
-  /*
-  printf("%ld  %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
-	 time(NULL),
-	 userinfo->sn, userinfo->flags,
-	 (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
-	 (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
-	 (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
-	 (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
-	 (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
-	 (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
-	 (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
-	 (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
-	 (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
-	 userinfo->capabilities);
-  */
-  
-  return 1;
-}
-
-/* Used by chat as well. */
-int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t reason;
-  
-  va_start(ap, fr);
-  reason = (fu16_t)va_arg(ap, unsigned int);
-  va_end(ap);
-  
-  /* printf("snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
-  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
-  
-  return 1;
-}
-
-static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  char *destsn;
-  fu16_t reason;
-  
-  va_start(ap, fr);
-  reason = (fu16_t)va_arg(ap, unsigned int);
-  destsn = va_arg(ap, char *);
-  va_end(ap);
-  
-  /* printf("message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
-  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
-
-  if (reason==4) {
-    owl_function_adminmsg("", "Could not send AIM message, user not logged on");
-  }
-  
-  return 1;
-}
-
-static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  char *destsn;
-  fu16_t reason;
-  
-  va_start(ap, fr);
-  reason = (fu16_t)va_arg(ap, unsigned int);
-  destsn = va_arg(ap, char *);
-  va_end(ap);
-  
-  /* printf("user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
-  if (reason<msgerrreasonslen) owl_function_error(msgerrreasons[reason]);
-  
-  return 1;
-}
-
-static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  static char *missedreasons[] = {
-    "Invalid (0)",
-    "Message too large",
-    "Rate exceeded",
-    "Evil Sender",
-    "Evil Receiver"
-  };
-  static int missedreasonslen = 5;
-  
-  va_list ap;
-  fu16_t chan, nummissed, reason;
-  aim_userinfo_t *userinfo;
-  
-  va_start(ap, fr);
-  chan = (fu16_t)va_arg(ap, unsigned int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  nummissed = (fu16_t)va_arg(ap, unsigned int);
-  reason = (fu16_t)va_arg(ap, unsigned int);
-  va_end(ap);
-  
-  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");
-  
-  return 1;
-}
-
-/*
- * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
- */
-static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t type;
-  char *sn = NULL;
-  
-  va_start(ap, fr);
-  type = (fu16_t)va_arg(ap, unsigned int);
-  sn = va_arg(ap, char *);
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_parse_msgack: 0x%04x / %s\n", type, sn);
-  
-  return 1;
-}
-
-static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  static char *codes[5] = {
-    "invalid",
-    "change",
-    "warning",
-    "limit",
-    "limit cleared"
-  };
-  va_list ap;
-  fu16_t code, rateclass;
-  fu32_t windowsize, clear, alert, limit, disconnect;
-  fu32_t currentavg, maxavg;
-  
-  va_start(ap, fr); 
-  
-  /* See code explanations below */
-  code = (fu16_t)va_arg(ap, unsigned int);
-  
-  /*
-   * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
-   */
-  rateclass = (fu16_t)va_arg(ap, unsigned int);
-  
-  /*
-   * Not sure what this is exactly.  I think its the temporal 
-   * relation factor (ie, how to make the rest of the numbers
-   * make sense in the real world). 
-   */
-  windowsize = va_arg(ap, fu32_t);
-  
-  /* Explained below */
-  clear = va_arg(ap, fu32_t);
-  alert = va_arg(ap, fu32_t);
-  limit = va_arg(ap, fu32_t);
-  disconnect = va_arg(ap, fu32_t);
-  currentavg = va_arg(ap, fu32_t);
-  maxavg = va_arg(ap, fu32_t);
-  
-  va_end(ap);
-  
-  owl_function_debugmsg("faimtest_parse_ratechange: rate %s (rate class 0x%04x): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)",
-			(code < 5)?codes[code]:"invalid",
-			rateclass,
-			currentavg, maxavg,
-			alert, clear,
-			limit, disconnect,
-			windowsize);
-  return 1;
-}
-
-static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu16_t newevil;
-  aim_userinfo_t *userinfo;
-  
-  va_start(ap, fr);
-  newevil = (fu16_t)va_arg(ap, unsigned int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  va_end(ap);
-  
-  /*
-   * Evil Notifications that are lacking userinfo->sn are anon-warns
-   * if they are an evil increases, but are not warnings at all if its
-   * a decrease (its the natural backoff happening).
-   *
-   * newevil is passed as an int representing the new evil value times
-   * ten.
-   */
-  owl_function_debugmsg("faimtest_parse_evilnotify: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
-  
-  return 1;
-}
-
-static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  char *address, *SNs;
-  int num, i;
-  owl_list list;
-  
-  va_start(ap, fr);
-  address = va_arg(ap, char *);
-  num = va_arg(ap, int);
-  SNs = va_arg(ap, char *);
-  va_end(ap);
-
-  owl_list_create(&list);
-  
-  owl_function_debugmsg("faimtest_parse_searchreply: E-Mail Search Results for %s: ", address);
-  for (i=0; i<num; i++) {
-    owl_function_debugmsg("  %s", &SNs[i*(MAXSNLEN+1)]);
-    owl_list_append_element(&list, &SNs[i*(MAXSNLEN+1)]);
-  }
-  owl_function_aimsearch_results(address, &list);
-  owl_list_free_simple(&list);
-  return(1);
-}
-
-static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  char *address;
-  
-  va_start(ap, fr);
-  address = va_arg(ap, char *);
-  va_end(ap);
-
-  owl_function_error("No results searching for %s", address);
-  owl_function_debugmsg("faimtest_parse_searcherror: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
-  
-  return(1);
-}
-
-static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  char *msg, *url;
-  fu16_t width, height, delay;
-  
-  va_start(ap, fr);
-  msg = va_arg(ap, char *);
-  url = va_arg(ap, char *);
-  width = va_arg(ap, unsigned int);
-  height = va_arg(ap, unsigned int);
-  delay = va_arg(ap, unsigned int);
-  va_end(ap);
-  
-  owl_function_debugmsg("handlepopup: (%dx%x:%d) %s (%s)\n", width, height, delay, msg, url);
-  
-  return 1;
-}
-
-static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_sendpauseack(sess, fr->conn);
-  return 1;
-}
-
-static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  aim_conn_t *bosconn;
-  char *bosip;
-  fu8_t *cookie;
-  
-  va_start(ap, fr);
-  bosip = va_arg(ap, char *);
-  cookie = va_arg(ap, fu8_t *);
-  va_end(ap);
-  
-  owl_function_debugmsg("migrate: migration in progress -- new BOS is %s -- disconnecting", bosip);
-  aim_conn_kill(sess, &fr->conn);
-  
-  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
-    owl_function_debugmsg("migrate: could not connect to BOS: internal error");
-    return 1;
-  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {	
-    owl_function_debugmsg("migrate: could not connect to BOS");
-    aim_conn_kill(sess, &bosconn);
-    return 1;
-  }
-  
-  /* Login will happen all over again. */
-  addcb_bos(sess, bosconn);
-  /* aim_sendcookie(sess, bosconn, cookie); */ /********/
-  return 1;
-}
-
-static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("ssirights: got SSI rights, requesting data\n");
-  /* aim_ssi_reqdata(sess, fr->conn, 0, 0x0000); */
-  aim_ssi_reqdata(sess);
-  
-  return(1);
-}
-
-static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  fu8_t fmtver;
-  fu16_t itemcount;
-  fu32_t stamp;
-  struct aim_ssi_item *list;
-  /*
-  struct aim_ssi_item *curitem;
-  struct aim_ssi_item *l;
-  */
-  
-  va_start(ap, fr);
-  fmtver = va_arg(ap, unsigned int);
-  itemcount = va_arg(ap, unsigned int);
-  stamp = va_arg(ap, fu32_t);
-  list = va_arg(ap, struct aim_ssi_item *);
-  va_end(ap);
-  
-  owl_function_debugmsg("ssiddata: got SSI data (0x%02x, %d items, %ld)", fmtver, itemcount, stamp);
-  /*
-  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
-    for (l = list; l; l = l->next) {
-      owl_function_debugmsg("\t0x%04x (%s) - 0x%04x/0x%04x", l->type, l->name, l->gid, l->bid);
-    }
-  }
-  */
-  aim_ssi_enable(sess);
-  
-  return 1;
-}
-
-static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("ssidatanochange: server says we have the latest SSI data already");
-  /* aim_ssi_enable(sess, fr->conn); */
-  aim_ssi_enable(sess);
-  return 1;
-}
-
-static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  struct aim_icq_offlinemsg *msg;
-  
-  va_start(ap, fr);
-  msg = va_arg(ap, struct aim_icq_offlinemsg *);
-  va_end(ap);
-  
-  if (msg->type == 0x0001) {
-    owl_function_debugmsg("offlinemsg: from %ld at %d/%d/%d %02d:%02d : %s", msg->sender, msg->year, msg->month, msg->day, msg->hour, msg->minute, msg->msg);
-  } else {
-    owl_function_debugmsg("unknown offline message type 0x%04x", msg->type);
-  }
-  return 1;
-}
-
-static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  /* Tell the server to delete them. */
-  owl_function_debugmsg("offlinemsg done: ");
-  aim_icq_ackofflinemsgs(sess);
-  return 1;
-}
-
-
-/******************** chat.c **************************/
-
-static int faimtest_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  aim_userinfo_t *userinfo;
-  int count;
-  /* int i; */
-  
-  va_start(ap, fr);
-  count = va_arg(ap, int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  va_end(ap);
-
-  owl_function_debugmsg("In faimtest_chat_join");
-  /*
-  printf("chat: %s:  New occupants have joined:\n", aim_chat_getname(fr->conn));
-  for (i = 0; i < count; i++)
-    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
-  */
-  return 1;
-}
-
-static int faimtest_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_userinfo_t *userinfo;
-  va_list ap;
-  int count;
-  /* int i; */
-
-  
-  va_start(ap, fr);
-  count = va_arg(ap, int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  va_end(ap);
-  
-  /*
-    printf("chat: %s:  Some occupants have left:\n", aim_chat_getname(fr->conn));
-    
-    for (i = 0; i < count; i++)
-    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
-  */
-  return 1;
-}
-
-static int faimtest_chat_infoupdate(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  aim_userinfo_t *userinfo;
-  struct aim_chat_roominfo *roominfo;
-  char *roomname;
-  int usercount;
-  char *roomdesc;
-  fu16_t flags, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
-  fu32_t creationtime;
-  const char *croomname;
-  /* int i; */
-  
-  croomname = aim_chat_getname(fr->conn);
-  
-  va_start(ap, fr);
-  roominfo = va_arg(ap, struct aim_chat_roominfo *);
-  roomname = va_arg(ap, char *);
-  usercount = va_arg(ap, int);
-  userinfo = va_arg(ap, aim_userinfo_t *);
-  roomdesc = va_arg(ap, char *);
-  flags = (fu16_t)va_arg(ap, unsigned int);
-  creationtime = va_arg(ap, fu32_t);
-  maxmsglen = (fu16_t)va_arg(ap, unsigned int);
-  unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
-  unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
-  maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
-  va_end(ap);
-
-  owl_function_debugmsg("In faimtest_chat_infoupdate");
-  /*
-  printf("chat: %s:  info update:\n", croomname);
-  printf("chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", croomname, roominfo->exchange, roominfo->name, roominfo->instance);
-  printf("chat: %s:  \tRoomname: %s\n", croomname, roomname);
-  printf("chat: %s:  \tRoomdesc: %s\n", croomname, roomdesc);
-  printf("chat: %s:  \tOccupants: (%d)\n", croomname, usercount);
-
-  for (i = 0; i < usercount; i++)
-    printf("chat: %s:  \t\t%s\n", croomname, userinfo[i].sn);
-  
-  owl_function_debugmsg("chat: %s:  \tRoom flags: 0x%04x (%s%s%s%s)\n", 
-	 croomname, flags,
-	 (flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
-	 (flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
-	 (flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
-	 (flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
-  printf("chat: %s:  \tCreation time: %lu (time_t)\n", croomname, creationtime);
-  printf("chat: %s:  \tUnknown_d2: 0x%04x\n", croomname, unknown_d2);
-  printf("chat: %s:  \tUnknown_d5: 0x%02x\n", croomname, unknown_d5);
-  printf("chat: %s:  \tMax message length: %d bytes\n", croomname, maxmsglen);
-  printf("chat: %s:  \tMax visible message length: %d bytes\n", croomname, maxvisiblemsglen);
-  */
-  
-  return(1);
-}
-
-static int faimtest_chat_incomingmsg(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  va_list ap;
-  aim_userinfo_t *userinfo;
-  char *msg;
-  char tmpbuf[1152];
-  
-  va_start(ap, fr);
-  userinfo = va_arg(ap, aim_userinfo_t *);	
-  msg = va_arg(ap, char *);
-  va_end(ap);
-
-  owl_function_debugmsg("in faimtest_chat_incomingmsg");
-
-  /*
-  printf("chat: %s: incoming msg from %s: %s\n", aim_chat_getname(fr->conn), userinfo->sn, msg);
-  */
-  
-  /*
-   * Do an echo for testing purposes.  But not for ourselves ("oops!")
-   */
-  if (strcmp(userinfo->sn, sess->sn) != 0) {
-    /* sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg); */
-    aim_chat_send_im(sess, fr->conn, 0, tmpbuf, strlen(tmpbuf));
-  }
-  
-  return 1;
-}
-
-static int faimtest_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  fu16_t type;
-  va_list ap;
-  
-  va_start(ap, fr);
-  type = (fu16_t)va_arg(ap, unsigned int);
-
-  owl_function_debugmsg("in faimtest_chatnav_info");
-  
-  if (type == 0x0002) {
-    int maxrooms;
-    struct aim_chat_exchangeinfo *exchanges;
-    int exchangecount;
-    /* int i; */
-    
-    maxrooms = va_arg(ap, int);
-    exchangecount = va_arg(ap, int);
-    exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
-    va_end(ap);
-
-    /*
-    printf("chat info: Chat Rights:\n");
-    printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
-    printf("chat info: \tExchange List: (%d total)\n", exchangecount);
-    for (i = 0; i < exchangecount; i++) {
-      printf("chat info: \t\t%x: %s (%s/%s) (0x%04x = %s%s%s%s)\n", 
-	     exchanges[i].number,
-	     exchanges[i].name,
-	     exchanges[i].charset1,
-	     exchanges[i].lang1,
-	     exchanges[i].flags,
-	     (exchanges[i].flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
-	     (exchanges[i].flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
-	     (exchanges[i].flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
-	     (exchanges[i].flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
-    }
-    */
-  } else if (type == 0x0008) {
-    char *fqcn, *name, *ck;
-    fu16_t instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
-    fu8_t createperms;
-    fu32_t createtime;
-    
-    fqcn = va_arg(ap, char *);
-    instance = (fu16_t)va_arg(ap, unsigned int);
-    exchange = (fu16_t)va_arg(ap, unsigned int);
-    flags = (fu16_t)va_arg(ap, unsigned int);
-    createtime = va_arg(ap, fu32_t);
-    maxmsglen = (fu16_t)va_arg(ap, unsigned int);
-    maxoccupancy = (fu16_t)va_arg(ap, unsigned int);
-    createperms = (fu8_t)va_arg(ap, unsigned int);
-    unknown = (fu16_t)va_arg(ap, unsigned int);
-    name = va_arg(ap, char *);
-    ck = va_arg(ap, char *);
-    va_end(ap);
-    
-    /* printf("received room create reply for %s/0x%04x\n", fqcn, exchange); */
-    
-  } else {
-    va_end(ap);
-    /* printf("chatnav info: unknown type (%04x)\n", type); */
-  }
-  
-  return 1;
-}
-
-static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("faimtest_conninitdone_chat:");
-
-  aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, faimtest_parse_genericerr, 0);
-  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
-  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
-  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
-  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
-  
-  aim_clientready(sess, fr->conn);
-  
-  owl_function_debugmsg("Chat ready");
-
-  /*
-    chatcon = find_oscar_chat_by_conn(gc, fr->conn);
-    chatcon->id = id;
-    chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
-  */
-  return(1);
-}
-
-static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  owl_function_debugmsg("faimtest_conninitdone_chatnav:");
-
-  /* aim_conn_addhandler(sess, fr->conn, 0x000d, 0x0001, gaim_parse_genericerr, 0); */
-  /* aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0); */
-
-  aim_clientready(sess, fr->conn);
-
-  aim_chatnav_reqrights(sess, fr->conn);
-
-  return(1);
-}
-
-void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
-{
-  aim_conn_t *tstconn;
-
-  owl_function_debugmsg("in faimtest_chatnav_redirect");
-  
-  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, redir->ip);
-  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
-    /* printf("unable to connect to chat(nav) server\n"); */
-    if (tstconn)
-      aim_conn_kill(sess, &tstconn);
-    return;
-  }
-  
-  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
-  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
-  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-  /* printf("chatnav: connected\n"); */
-  return;
-}
-
-/* XXX this needs instance too */
-void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
-{
-  aim_conn_t *tstconn;
-
-  owl_function_debugmsg("in chat_redirect");
-  
-  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, redir->ip);
-  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
-    /* printf("unable to connect to chat server\n"); */
-    if (tstconn) aim_conn_kill(sess, &tstconn);
-    return; 
-  }		
-  /* printf("chat: connected to %s instance %d on exchange %d\n", redir->chat.room, redir->chat.instance, redir->chat.exchange); */
-  
-  /*
-   * We must do this to attach the stored name to the connection!
-   */
-  aim_chat_attachname(tstconn, redir->chat.exchange, redir->chat.room, redir->chat.instance);
-  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
-  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
-  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-  return;	
-}
-
-
-/**********************************************************************************/
-
-#if 0
-static int faimtest_ssi_rerequestdata(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  aim_ssi_reqdata(sess);
-  return(0);
-}
-
-static int faimtest_ssi_parseerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  /* GaimConnection *gc = sess->aux_data; */
-  /*	OscarData *od = gc->proto_data; */
-  va_list ap;
-  fu16_t reason;
-
-  va_start(ap, fr);
-  reason = (fu16_t)va_arg(ap, unsigned int);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_ssi_parseerr: ssi: SNAC error %hu", reason);
-
-  if (reason == 0x0005) {
-    owl_function_error("faimtest_ssi_parseerr: unable to retrieve buddy list");
-  }
-
-  /* Activate SSI */
-  /* Sending the enable causes other people to be able to see you, and you to see them */
-  /* Make sure your privacy setting/invisibility is set how you want it before this! */
-  owl_function_debugmsg("faimtest_ssi_parseerr: ssi: activating server-stored buddy list");
-  aim_ssi_enable(sess);
-  
-  return(1);
-}
-
-static int faimtest_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  /* GaimConnection *gc = sess->aux_data; */
-  /* OscarData *od = (OscarData *)gc->proto_data; */
-  int numtypes, i;
-  fu16_t *maxitems;
-  va_list ap;
-
-  va_start(ap, fr);
-  numtypes = va_arg(ap, int);
-  maxitems = va_arg(ap, fu16_t *);
-  va_end(ap);
-
-  owl_function_debugmsg("faimtest_ssi_parserights: ");
-  for (i=0; i<numtypes; i++) {
-    owl_function_debugmsg(" max type 0x%04x=%hd,", i, maxitems[i]);
-  }
-
-  /*
-  if (numtypes >= 0) od->rights.maxbuddies = maxitems[0];
-  if (numtypes >= 1) od->rights.maxgroups = maxitems[1];
-  if (numtypes >= 2) od->rights.maxpermits = maxitems[2];
-  if (numtypes >= 3) od->rights.maxdenies = maxitems[3];
-  */
-  
-  return(1);
-}
-
-static int faimtest_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  /* GaimConnection *gc = sess->aux_data; */
-  /* GaimAccount *account = gaim_connection_get_account(gc); */
-  /* OscarData *od = (OscarData *)gc->proto_data; */
-  struct aim_ssi_item *curitem;
-  int tmp;
-  int export = FALSE;
-  /* XXX - use these?
-     va_list ap;
-     
-     va_start(ap, fr);
-     fmtver = (fu16_t)va_arg(ap, int);
-     numitems = (fu16_t)va_arg(ap, int);
-     items = va_arg(ap, struct aim_ssi_item);
-     timestamp = va_arg(ap, fu32_t);
-     va_end(ap); */
-  
-  owl_function_debugmsg("faimtest_ssi_parselist: syncing local list and server list");
-
-  /* Clean the buddy list */
-  aim_ssi_cleanlist(sess);
-
-  /* Add from server list to local list */
-  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
-    if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
-      switch (curitem->type) {
-      case 0x0000: { /* Buddy */
-	if (curitem->name) {
-	  char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name);
-	  char *gname_utf8 = gname ? gaim_utf8_try_convert(gname) : NULL;
-	  char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
-	  char *alias_utf8 = alias ? gaim_utf8_try_convert(alias) : NULL;
-	  GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
-	  /* Should gname be freed here? -- elb */
-	  /* Not with the current code, but that might be cleaner -- med */
-	  free(alias);
-	  if (buddy) {
-	    /* Get server stored alias */
-	    if (alias_utf8) {
-	      g_free(buddy->alias);
-	      buddy->alias = g_strdup(alias_utf8);
-	    }
-	  } else {
-	    GaimGroup *g;
-	    buddy = gaim_buddy_new(gc->account, curitem->name, alias_utf8);
-	    
-	    if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-	      g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
-	      gaim_blist_add_group(g, NULL);
-	    }
-	    
-	    gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		       "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
-	    gaim_blist_add_buddy(buddy, NULL, g, NULL);
-	    export = TRUE;
-	  }
-	  g_free(gname_utf8);
-	  g_free(alias_utf8);
-	}
-      } break;
-      
-      case 0x0001: { /* Group */
-	/* Shouldn't add empty groups */
-      } break;
-      
-      case 0x0002: { /* Permit buddy */
-	if (curitem->name) {
-	  /* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */
-	  GSList *list;
-	  for (list=account->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
-	  if (!list) {
-	    gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		       "ssi: adding permit buddy %s to local list\n", curitem->name);
-	    gaim_privacy_permit_add(account, curitem->name, TRUE);
-	    export = TRUE;
-	  }
-	}
-      } break;
-      
-      case 0x0003: { /* Deny buddy */
-	if (curitem->name) {
-	  GSList *list;
-	  for (list=account->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
-	  if (!list) {
-	    gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		       "ssi: adding deny buddy %s to local list\n", curitem->name);
-	    gaim_privacy_deny_add(account, curitem->name, TRUE);
-	    export = TRUE;
-	  }
-	}
-      } break;
-      
-      case 0x0004: { /* Permit/deny setting */
-	if (curitem->data) {
-	  fu8_t permdeny;
-	  if ((permdeny = aim_ssi_getpermdeny(sess->ssi.local)) && (permdeny != account->perm_deny)) {
-	    gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		       "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, permdeny);
-	    account->perm_deny = permdeny;
-	    if (od->icq && account->perm_deny == 0x03) {
-	      serv_set_away(gc, "Invisible", "");
-	    }
-	    export = TRUE;
-	  }
-	}
-      } break;
-      
-      case 0x0005: { /* Presence setting */
-	/* We don't want to change Gaim's setting because it applies to all accounts */
-      } break;
-      } /* End of switch on curitem->type */
-  } /* End of for loop */
-  
-  /* If changes were made, then flush buddy list to file */
-  if (export)
-    gaim_blist_save();
-  
-  { /* Add from local list to server list */
-    GaimBlistNode *gnode, *cnode, *bnode;
-    GaimGroup *group;
-    GaimBuddy *buddy;
-    GaimBuddyList *blist;
-    GSList *cur;
-    
-    /* Buddies */
-    if ((blist = gaim_get_blist()))
-      for (gnode = blist->root; gnode; gnode = gnode->next) {
-	if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
-	  continue;
-	group = (GaimGroup *)gnode;
-	for (cnode = gnode->child; cnode; cnode = cnode->next) {
-	  if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
-	    continue;
-	  for (bnode = cnode->child; bnode; bnode = bnode->next) {
-	    if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-	      continue;
-	    buddy = (GaimBuddy *)bnode;
-	    if (buddy->account == gc->account) {
-	      const char *servernick = gaim_buddy_get_setting(buddy, "servernick");
-	      if (servernick)
-		serv_got_alias(gc, buddy->name, servernick);
-	      
-	      if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
-		/* Store local alias on server */
-		char *alias = aim_ssi_getalias(sess->ssi.local, group->name, buddy->name);
-		if (!alias && buddy->alias && strlen(buddy->alias))
-		  aim_ssi_aliasbuddy(sess, group->name, buddy->name, buddy->alias);
-		free(alias);
-	      } else {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: adding buddy %s from local list to server list\n", buddy->name);
-		aim_ssi_addbuddy(sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
-	      }
-	    }
-	  }
-	}
-      }
-    
-    /* Permit list */
-    if (gc->account->permit) {
-      for (cur=gc->account->permit; cur; cur=cur->next)
-	if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
-	  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		     "ssi: adding permit %s from local list to server list\n", (char *)cur->data);
-	  aim_ssi_addpermit(sess, cur->data);
-	}
-    }
-    
-    /* Deny list */
-    if (gc->account->deny) {
-      for (cur=gc->account->deny; cur; cur=cur->next)
-	if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) {
-	  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-		     "ssi: adding deny %s from local list to server list\n", (char *)cur->data);
-	  aim_ssi_adddeny(sess, cur->data);
-	}
-    }
-    /* Presence settings (idle time visibility) */
-    if ((tmp = aim_ssi_getpresence(sess->ssi.local)) != 0xFFFFFFFF)
-      if (!(tmp & 0x400))
-	aim_ssi_setpresence(sess, tmp | 0x400);
-  } /* end adding buddies from local list to server list */
-  
-  /* Set our ICQ status */
-  if  (od->icq && !gc->away) {
-    aim_setextstatus(sess, AIM_ICQ_STATE_NORMAL);
-  }
-  
-  /* Activate SSI */
-  /* Sending the enable causes other people to be able to see you, and you to see them */
-  /* Make sure your privacy setting/invisibility is set how you want it before this! */
-  gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: activating server-stored buddy list\n");
-  aim_ssi_enable(sess);
-  
-  return 1;
-}
-
-static int gaim_ssi_parseack(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  GaimConnection *gc = sess->aux_data;
-  va_list ap;
-  struct aim_ssi_tmp *retval;
-  
-  va_start(ap, fr);
-  retval = va_arg(ap, struct aim_ssi_tmp *);
-  va_end(ap);
-  
-  while (retval) {
-    gaim_debug(GAIM_DEBUG_MISC, "oscar",
-	       "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack,  retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item");
-    
-    if (retval->ack != 0xffff)
-      switch (retval->ack) {
-      case 0x0000: { /* added successfully */
-      } break;
-      
-      case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */
-	gchar *buf;
-	buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list.  Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
-	gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
-	g_free(buf);
-      }
-	
-      case 0x000e: { /* buddy requires authorization */
-	if ((retval->action == AIM_CB_SSI_ADD) && (retval->name))
-	  gaim_auth_sendrequest(gc, retval->name);
-      } break;
-      
-      default: { /* La la la */
-	gchar *buf;
-	gaim_debug(GAIM_DEBUG_ERROR, "oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
-	buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason.  The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)")));
-	gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
-	g_free(buf);
-	/* XXX - Should remove buddy from local list */
-      } break;
-      }
-    
-    retval = retval->next;
-  }
-  
-  return 1;
-}
-
-static int gaim_ssi_authgiven(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  GaimConnection *gc = sess->aux_data;
-  va_list ap;
-  char *sn, *msg;
-  gchar *dialog_msg, *nombre;
-  struct name_data *data;
-  GaimBuddy *buddy;
-  
-  va_start(ap, fr);
-  sn = va_arg(ap, char *);
-  msg = va_arg(ap, char *);
-  va_end(ap);
-  
-  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-	     "ssi: %s has given you permission to add him to your buddy list\n", sn);
-  
-  buddy = gaim_find_buddy(gc->account, sn);
-  if (buddy && (gaim_get_buddy_alias_only(buddy)))
-    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-  else
-    nombre = g_strdup(sn);
-  
-  dialog_msg = g_strdup_printf(_("The user %s has given you permission to add you to their buddy list.  Do you want to add them?"), nombre);
-  data = g_new(struct name_data, 1);
-  data->gc = gc;
-  data->name = g_strdup(sn);
-  data->nick = NULL;
-  
-  gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
-		      0, data,
-		      G_CALLBACK(gaim_icq_buddyadd),
-		      G_CALLBACK(oscar_free_name_data));
-  
-  g_free(dialog_msg);
-  g_free(nombre);
-  
-  return 1;
-}
-
-static int gaim_ssi_authrequest(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  GaimConnection *gc = sess->aux_data;
-  va_list ap;
-  char *sn, *msg;
-  gchar *dialog_msg, *nombre;
-  struct name_data *data;
-  GaimBuddy *buddy;
-  
-  va_start(ap, fr);
-  sn = va_arg(ap, char *);
-  msg = va_arg(ap, char *);
-  va_end(ap);
-  
-  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-	     "ssi: received authorization request from %s\n", sn);
-  
-  buddy = gaim_find_buddy(gc->account, sn);
-  if (buddy && (gaim_get_buddy_alias_only(buddy)))
-    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-  else
-    nombre = g_strdup(sn);
-  
-  dialog_msg = g_strdup_printf(_("The user %s wants to add you to their buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
-  data = g_new(struct name_data, 1);
-  data->gc = gc;
-  data->name = g_strdup(sn);
-  data->nick = NULL;
-  
-  gaim_request_action(gc, NULL, _("Authorization Request"), dialog_msg,
-		      0, data, 2,
-		      _("Authorize"), G_CALLBACK(gaim_auth_grant),
-		      _("Deny"), G_CALLBACK(gaim_auth_dontgrant_msgprompt));
-  
-  g_free(dialog_msg);
-  g_free(nombre);
-  
-  return 1;
-}
-
-static int gaim_ssi_authreply(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  GaimConnection *gc = sess->aux_data;
-  va_list ap;
-  char *sn, *msg;
-  gchar *dialog_msg, *nombre;
-  fu8_t reply;
-  GaimBuddy *buddy;
-  
-  va_start(ap, fr);
-  sn = va_arg(ap, char *);
-  reply = (fu8_t)va_arg(ap, int);
-  msg = va_arg(ap, char *);
-  va_end(ap);
-  
-  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-	     "ssi: received authorization reply from %s.  Reply is 0x%04hhx\n", sn, reply);
-  
-  buddy = gaim_find_buddy(gc->account, sn);
-  if (buddy && (gaim_get_buddy_alias_only(buddy)))
-    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-  else
-    nombre = g_strdup(sn);
-  
-  if (reply) {
-    /* Granted */
-    dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
-    gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
-  } else {
-    /* Denied */
-    dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
-    gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
-  }
-  g_free(dialog_msg);
-  g_free(nombre);
-  
-  return 1;
-}
-
-static int gaim_ssi_gotadded(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-  GaimConnection *gc = sess->aux_data;
-  va_list ap;
-  char *sn;
-  GaimBuddy *buddy;
-  
-  va_start(ap, fr);
-  sn = va_arg(ap, char *);
-  va_end(ap);
-  
-  buddy = gaim_find_buddy(gc->account, sn);
-  gaim_debug(GAIM_DEBUG_INFO, "oscar",
-	     "ssi: %s added you to their buddy list\n", sn);
-  gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
-  
-  return 1;
-}
-#endif
Index: ddy.c
===================================================================
--- buddy.c	(revision f4d0975bed0618ba963347663b4b5de5825c0a22)
+++ 	(revision )
@@ -1,71 +1,0 @@
-#include "owl.h"
-
-static const char fileIdent[] = "$Id$";
-
-void owl_buddy_create(owl_buddy *b, int proto, char *name)
-{
-  b->proto=proto;
-  b->name=owl_strdup(name);
-  b->idlesince=0;
-}
-
-char *owl_buddy_get_name(owl_buddy *b)
-{
-  if (b->name) return(b->name);
-  return("");
-}
-
-int owl_buddy_is_idle(owl_buddy *b)
-{
-  if (b->isidle) return(1);
-  return(0);
-}
-
-void owl_buddy_set_idle(owl_buddy *b)
-{
-  b->isidle=1;
-}
-
-void owl_buddy_set_unidle(owl_buddy *b)
-{
-  b->isidle=0;
-}
-
-int owl_buddy_get_proto(owl_buddy *b)
-{
-  return(b->proto);
-}
-
-int owl_buddy_is_proto_aim(owl_buddy *b)
-{
-  if (b->proto==OWL_PROTOCOL_AIM) return(1);
-  return(0);
-}
-
-/* Set the buddy to have been idle since 'diff' minutes ago
- */
-void owl_buddy_set_idle_since(owl_buddy *b, int diff)
-{
-  time_t now;
-
-  now=time(NULL);
-  b->idlesince=now-(diff*60);
-}
-
-/* return the number of minutes the buddy has been idle
- */
-int owl_buddy_get_idle_time(owl_buddy *b)
-{
-  time_t now;
-
-  if (b->isidle) {
-    now=time(NULL);
-    return((now - b->idlesince)/60);
-  }
-  return(0);
-}
-
-void owl_buddy_free(owl_buddy *b)
-{
-  if (b->name) owl_free(b->name);
-}
Index: ddylist.c
===================================================================
--- buddylist.c	(revision 257a22f9949fe230526eb336a3d6c236f702da66)
+++ 	(revision )
@@ -1,142 +1,0 @@
-#include "owl.h"
-
-static const char fileIdent[] = "$Id$";
-
-void owl_buddylist_init(owl_buddylist *bl)
-{
-  owl_list_create(&(bl->buddies));
-}
-
-/* add a (logged-in) AIM buddy to the buddy list
- */
-void owl_buddylist_add_aim_buddy(owl_buddylist *bl, char *screenname)
-{
-  owl_buddy *b;
-  b=owl_malloc(sizeof(owl_buddy));
-  
-  owl_buddy_create(b, OWL_PROTOCOL_AIM, screenname);
-  owl_list_append_element(&(bl->buddies), b);
-}
-
-/* remove an AIM buddy from the buddy list
- */
-int owl_buddylist_remove_aim_buddy(owl_buddylist *bl, char *name)
-{
-  int i, j;
-  owl_buddy *b;
-
-  j=owl_list_get_size(&(bl->buddies));
-  for (i=0; i<j; i++) {
-    b=owl_list_get_element(&(bl->buddies), i);
-    if (!strcasecmp(name, owl_buddy_get_name(b)) && owl_buddy_is_proto_aim(b)) {
-      owl_list_remove_element(&(bl->buddies), i);
-      owl_buddy_free(b);
-      return(0);
-    }
-  }
-  return(1);
-}
-
-/* Deal with an "oncoming" message.  This means recognizing the user
- * has logged in, and displaying a message if they were not already
- * logged in.
- */
-void owl_buddylist_oncoming(owl_buddylist *bl, char *screenname)
-{
-  owl_message *m;
-
-  if (!owl_buddylist_is_aim_buddy_loggedin(bl, screenname)) {
-
-    owl_buddylist_add_aim_buddy(bl, screenname);
-
-    /* are we ingoring login messages for a while? */
-    if (!owl_timer_is_expired(owl_global_get_aim_login_timer(&g))) return;
-
-    /* if not, create the login message */
-    m=owl_malloc(sizeof(owl_message));
-    owl_message_create_aim(m,
-			   screenname,
-			   owl_global_get_aim_screenname(&g),
-			   "",
-			   OWL_MESSAGE_DIRECTION_IN,
-			   1);
-    owl_global_messagequeue_addmsg(&g, m);
-  }
-}
-
-/* Deal with an "offgoing" message.  This means recognizing the user
- * has logged out, and sending a message if they were logged in.
- */
-void owl_buddylist_offgoing(owl_buddylist *bl, char *screenname)
-{
-  owl_message *m;
-
-  if (owl_buddylist_is_aim_buddy_loggedin(bl, screenname)) {
-    m=owl_malloc(sizeof(owl_message));
-    owl_message_create_aim(m,
-			   screenname,
-			   owl_global_get_aim_screenname(&g),
-			   "",
-			   OWL_MESSAGE_DIRECTION_IN,
-			   -1);
-    owl_global_messagequeue_addmsg(&g, m);
-  }
-
-  owl_buddylist_remove_aim_buddy(bl, screenname);
-}
-
-/* return the number of logged in buddies */
-int owl_buddylist_get_size(owl_buddylist *bl)
-{
-  return(owl_list_get_size(&(bl->buddies)));
-}
-
-/* return the buddy with index N.  If out of range, return NULL
- */
-owl_buddy *owl_buddylist_get_buddy_n(owl_buddylist *bl, int index)
-{
-  if (index<0) return(NULL);
-  if (index>(owl_buddylist_get_size(bl)-1)) return(NULL);
-
-  return(owl_list_get_element(&(bl->buddies), index));
-}
-
-/* return the AIM buddy with screenname 'name'.  If
- * no such buddy is logged in, return NULL.
- */
-owl_buddy *owl_buddylist_get_aim_buddy(owl_buddylist *bl, char *name)
-{
-  int i, j;
-  owl_buddy *b;
-
-  j=owl_list_get_size(&(bl->buddies));
-  for (i=0; i<j; i++) {
-    b=owl_list_get_element(&(bl->buddies), i);
-    if (!strcasecmp(name, owl_buddy_get_name(b))) return(b);
-  }
-  return(NULL);
-}
-
-/* return 1 if the buddy 'screenname' is logged in,
- * otherwise return 0
- */
-int owl_buddylist_is_aim_buddy_loggedin(owl_buddylist *bl, char *screenname)
-{
-  owl_buddy *b;
-
-  b=owl_buddylist_get_aim_buddy(bl, screenname);
-  if (b==NULL) return(0);
-  return(1);
-}
-
-/* remove all buddies from the list */
-void owl_buddylist_clear(owl_buddylist *bl)
-{
-  owl_list_free_all(&(bl->buddies), (void(*)(void*))owl_buddy_free);
-  owl_list_create(&(bl->buddies));
-}
-
-void owl_buddylist_free(owl_buddylist *bl)
-{
-  owl_list_free_all(&(bl->buddies), (void(*)(void*))owl_buddy_free);
-}
Index: commands.c
===================================================================
--- commands.c	(revision b1fd36ed2941a6f89bdffb20226eafa3ab5ec40b)
+++ commands.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -122,11 +122,4 @@
 	      "      Send to the specified opcode\n"),
 
-  OWLCMD_ARGS("aimwrite", owl_command_aimwrite, OWL_CTX_INTERACTIVE,
-	      "send an AIM message",
-	      "aimwrite <user> [-m <message...>]",
-	      "Send an aim message to a user.\n\n" 
-              "The following options are available:\n\n"
-              "-m    Specifies a message to send without prompting.\n"),
-
   OWLCMD_ARGS("loopwrite", owl_command_loopwrite, OWL_CTX_INTERACTIVE,
 	      "send a loopback message",
@@ -232,13 +225,8 @@
 	      "Execute the owl commands in <filename>.\n"),
 
-  OWLCMD_ARGS("aim", owl_command_aim, OWL_CTX_INTERACTIVE,
-	      "AIM specific commands",
-	      "aim search <email>",
-	      ""),
-
   OWLCMD_ARGS("addbuddy", owl_command_addbuddy, OWL_CTX_INTERACTIVE,
 	      "add a buddy to a buddylist",
 	      "addbuddy <protocol> <screenname>",
-	      "Add the named buddy to your buddylist.  <protocol> can be aim or zephyr\n"),
+	      "Add the named buddy to your buddylist.  <protocol> can be zephyr\n"),
 
   OWLCMD_ARGS("delbuddy", owl_command_delbuddy, OWL_CTX_INTERACTIVE,
@@ -246,9 +234,4 @@
 	      "delbuddy <protocol> <screenname>",
 	      "Delete the named buddy from your buddylist.  <protocol> can be aim or zephyr\n"),
-
-  OWLCMD_ARGS("join", owl_command_join, OWL_CTX_INTERACTIVE,
-	      "join a chat group",
-	      "join aim <groupname> [exchange]",
-	      "Join the AIM chatroom with 'groupname'.\n"),
 
   OWLCMD_ARGS("smartzpunt", owl_command_smartzpunt, OWL_CTX_INTERACTIVE,
@@ -306,9 +289,4 @@
 	      "znol [-f file]",
 	      "Print a znol-style listing of users logged in"),
-
-  OWLCMD_ARGS("alist", owl_command_alist, OWL_CTX_INTERACTIVE,
-	      "List AIM users logged in",
-	      "alist",
-	      "Print a listing of AIM users logged in"),
 
   OWLCMD_ARGS("blist", owl_command_blist, OWL_CTX_INTERACTIVE,
@@ -465,12 +443,4 @@
 	      "Turn on or off a zaway message.  If 'message' is\n"
 	      "specified turn on zaway with that message, otherwise\n"
-	      "use the default.\n"),
-
-  OWLCMD_ARGS("aaway", owl_command_aaway, OWL_CTX_INTERACTIVE,
-	      "Set, enable or disable AIM away message",
-	      "aaway [ on | off | toggle ]\n"
-	      "aaway <message>",
-	      "Turn on or off the AIM away message.  If 'message' is\n"
-	      "specified turn on aaway with that message, otherwise\n"
 	      "use the default.\n"),
 
@@ -530,5 +500,5 @@
 	      "    body       -  message body\n"
 	      "    hostname   -  hostname of sending host\n"
-	      "    type       -  message type (zephyr, aim, admin)\n"
+	      "    type       -  message type (zephyr, admin...)\n"
 	      "    direction  -  either 'in' 'out' or 'none'\n"
 	      "    login      -  either 'login' 'logout' or 'none'\n"
@@ -734,14 +704,4 @@
           "no argument, it makes search inactive."),
 
-  OWLCMD_ARGS("aimlogin", owl_command_aimlogin, OWL_CTX_ANY,
-	      "login to an AIM account",
-	      "aimlogin <screenname> [<password>]\n",
-	      ""),
-
-  OWLCMD_ARGS("aimlogout", owl_command_aimlogout, OWL_CTX_ANY,
-	      "logout from AIM",
-	      "aimlogout\n",
-	      ""),
-
   OWLCMD_ARGS("error", owl_command_error, OWL_CTX_ANY,
               "Display an error message",
@@ -1015,10 +975,4 @@
 }
 
-char *owl_command_alist()
-{
-  owl_function_buddylist(1, 0, NULL);
-  return(NULL);
-}
-
 char *owl_command_blist()
 {
@@ -1044,24 +998,4 @@
   sprintf(buff, "Owl version %s", OWL_VERSION_STRING);
   owl_function_makemsg(buff);
-}
-
-char *owl_command_aim(int argc, char **argv, char *buff)
-{
-  if (argc<2) {
-    owl_function_makemsg("not enough arguments to aim command");
-    return(NULL);
-  }
-
-  if (!strcmp(argv[1], "search")) {
-    if (argc!=3) {
-      owl_function_makemsg("not enough arguments to aim search command");
-      return(NULL);
-    }
-    owl_aim_search(argv[2]);
-  } else {
-    owl_function_makemsg("unknown subcommand '%s' for aim command", argv[1]);
-    return(NULL);
-  }
-  return(NULL);
 }
 
@@ -1073,20 +1007,10 @@
   }
 
-  if (!strcasecmp(argv[1], "aim")) {
-    if (!owl_global_is_aimloggedin(&g)) {
-      owl_function_makemsg("addbuddy: You must be logged into aim to use this command.");
-      return(NULL);
-    }
-    /*
-    owl_function_makemsg("This function is not yet operational.  Stay tuned.");
-    return(NULL);
-    */
-    owl_aim_addbuddy(argv[2]);
-    owl_function_makemsg("%s added as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g));
-  } else if (!strcasecmp(argv[1], "zephyr")) {
+  /* TODO add a hook for perl modules */
+  if (!strcasecmp(argv[1], "zephyr")) {
     owl_zephyr_addbuddy(argv[2]);
     owl_function_makemsg("%s added as zephyr buddy", argv[2]);
   } else {
-    owl_function_makemsg("addbuddy: currently the only supported protocols are 'zephyr' and 'aim'");
+    owl_function_makemsg("addbuddy: currently the only supported protocol is 'zephyr'");
   }
 
@@ -1101,42 +1025,12 @@
   }
 
-  if (!strcasecmp(argv[1], "aim")) {
-    if (!owl_global_is_aimloggedin(&g)) {
-      owl_function_makemsg("delbuddy: You must be logged into aim to use this command.");
-      return(NULL);
-    }
-    owl_aim_delbuddy(argv[2]);
-    owl_function_makemsg("%s deleted as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g));
-  } else if (!strcasecmp(argv[1], "zephyr")) {
+  /* TODO add a hook for perl modules */
+  if (!strcasecmp(argv[1], "zephyr")) {
     owl_zephyr_delbuddy(argv[2]);
     owl_function_makemsg("%s deleted as zephyr buddy", argv[2]);
   } else {
-    owl_function_makemsg("delbuddy: currently the only supported protocols are 'zephyr' and 'aim'");
-  }
-
-  return(NULL);
-}
-
-char *owl_command_join(int argc, char **argv, char *buff)
-{
-  if (argc!=3 && argc!=4) {
-    owl_function_makemsg("usage: join <protocol> <buddyname> [exchange]");
-    return(NULL);
-  }
-
-  if (!strcasecmp(argv[1], "aim")) {
-    if (!owl_global_is_aimloggedin(&g)) {
-      owl_function_makemsg("join aim: You must be logged into aim to use this command.");
-      return(NULL);
-    }
-    if (argc==3) {
-      owl_aim_chat_join(argv[2], 4);
-    } else {
-      owl_aim_chat_join(argv[2], atoi(argv[3]));
-    }
-    /* owl_function_makemsg("%s deleted as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g)); */
-  } else {
-    owl_function_makemsg("join: currently the only supported protocol is 'aim'");
-  }
+    owl_function_makemsg("delbuddy: currently the only supported protocol is 'zephyr'");
+  }
+
   return(NULL);
 }
@@ -1421,44 +1315,15 @@
 
 
-char *owl_command_aaway(int argc, char **argv, char *buff)
-{
+char *owl_command_away(int argc, char **argv, char *buff)
+{
+  /* TODO add a hook for perl modules */
   if ((argc==1) ||
       ((argc==2) && !strcmp(argv[1], "on"))) {
-    owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));
-    owl_function_aaway_on();
+    owl_global_set_zaway_msg(&g, owl_global_get_zaway_msg_default(&g));
+    owl_function_zaway_on();
     return NULL;
   }
 
   if (argc==2 && !strcmp(argv[1], "off")) {
-    owl_function_aaway_off();
-    return NULL;
-  }
-
-  if (argc==2 && !strcmp(argv[1], "toggle")) {
-    owl_function_aaway_toggle();
-    return NULL;
-  }
-
-  buff = skiptokens(buff, 1);
-  owl_global_set_aaway_msg(&g, buff);
-  owl_function_aaway_on();
-  return NULL;
-}
-
-
-char *owl_command_away(int argc, char **argv, char *buff)
-{
-  if ((argc==1) ||
-      ((argc==2) && !strcmp(argv[1], "on"))) {
-    owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));
-    owl_global_set_zaway_msg(&g, owl_global_get_zaway_msg_default(&g));
-    owl_function_aaway_on();
-    owl_function_zaway_on();
-    owl_function_makemsg("Away messages set.", owl_global_get_aaway_msg_default(&g));
-    return NULL;
-  }
-
-  if (argc==2 && !strcmp(argv[1], "off")) {
-    owl_function_aaway_off();
     owl_function_zaway_off();
     return NULL;
@@ -1469,11 +1334,9 @@
      *  them both on)
      */
-    if (!owl_global_is_zaway(&g) && !owl_global_is_aaway(&g)) {
-      owl_function_aaway_toggle();
+    if (!owl_global_is_zaway(&g) /* && !owl_global_is_aaway(&g) */) {
       owl_function_zaway_toggle();
       owl_function_makemsg("Away messages set.");
     } else {
       if (owl_global_is_zaway(&g)) owl_function_zaway_toggle();
-      if (owl_global_is_aaway(&g)) owl_function_aaway_toggle();
       owl_function_makemsg("Away messages off.");
     }
@@ -1482,7 +1345,5 @@
 
   buff = skiptokens(buff, 1);
-  owl_global_set_aaway_msg(&g, buff);
   owl_global_set_zaway_msg(&g, buff);
-  owl_function_aaway_on();
   owl_function_zaway_on();
   owl_function_makemsg("Away messages set.");
@@ -1857,83 +1718,4 @@
     owl_function_zwrite_setup(buff);
   }
-  return(NULL);
-}
-
-char *owl_command_aimwrite(int argc, char **argv, char *buff)
-{
-  char *newbuff, *recip, **myargv;
-  int i, j, myargc;
-  owl_message *m;
-  
-  if (!owl_global_is_aimloggedin(&g)) {
-    owl_function_makemsg("You are not logged in to AIM.");
-    return(NULL);
-  }
-
-  if (argc < 2) {
-    owl_function_makemsg("Not enough arguments to the aimwrite command.");
-    return(NULL);
-  }
-
-  myargv=argv;
-  if (argc<0) {
-    owl_function_error("Unbalanced quotes in aimwrite");
-    return(NULL);
-  }
-  myargc=argc;
-  if (myargc && *(myargv[0])!='-') {
-    myargc--;
-    myargv++;
-  }
-  while (myargc) {
-    if (!strcmp(myargv[0], "-m")) {
-      if (myargc<2) {
-	break;
-      }
-
-      /* Once we have -m, gobble up everything else on the line */
-      myargv++;
-      myargc--;
-      newbuff=owl_malloc(1);
-      newbuff=owl_strdup("");
-      while (myargc) {
-	newbuff=realloc(newbuff, strlen(newbuff)+strlen(myargv[0])+5);
-	strcat(newbuff, myargv[0]);
-	strcat(newbuff, " ");
-	myargc--;
-	myargv++;
-      }
-      newbuff[strlen(newbuff)-1]='\0'; /* remove last space */
-
-      recip=owl_malloc(strlen(argv[0])+5);
-      sprintf(recip, "%s ", argv[1]);
-      owl_aim_send_im(recip, newbuff);
-      m=owl_function_make_outgoing_aim(newbuff, recip);
-      if (m) { 
-          owl_global_messagequeue_addmsg(&g, m);
-      } else {
-          owl_function_error("Could not create outgoing AIM message");
-      }
-
-      owl_free(recip);
-      owl_free(newbuff);
-      return(NULL);
-    } else {
-      /* we don't care */
-      myargv++;
-      myargc--;
-    }
-  }
-
-  /* squish arguments together to make one screenname w/o spaces for now */
-  newbuff=owl_malloc(strlen(buff)+5);
-  sprintf(newbuff, "%s ", argv[0]);
-  j=argc-1;
-  for (i=0; i<j; i++) {
-    strcat(newbuff, argv[i+1]);
-  }
-    
-  owl_function_aimwrite_setup(newbuff);
-  owl_free(newbuff);
   return(NULL);
 }
@@ -2499,34 +2281,4 @@
 }
 
-char *owl_command_aimlogin(int argc, char **argv, char *buff)
-{
-  if ((argc<2) || (argc>3)) {
-    owl_function_makemsg("Wrong number of arguments to aimlogin command");
-    return(NULL);
-  }
-
-  /* if we get two arguments, ask for the password */
-  if (argc==2) {
-    owl_global_set_buffercommand(&g, argv[1]);
-    owl_global_set_buffercallback(&g, &owl_callback_aimlogin);
-    owl_function_start_password("AIM Password: ");
-    return(NULL);
-  } else {
-    owl_function_aimlogin(argv[1], argv[2]);
-  }
-
-  /* this is a test */
-  return(NULL);
-}
-
-char *owl_command_aimlogout(int argc, char **argv, char *buff)
-{
-  /* clear the buddylist */
-  owl_buddylist_clear(owl_global_get_buddylist(&g));
-
-  owl_aim_logout();
-  return(NULL);
-}
-
 char *owl_command_getstyle(int argc, char **argv, char *buff)
 {
Index: configure.ac
===================================================================
--- configure.ac	(revision d9337637b38624a9f8d064c1a45062f7762f7b72)
+++ configure.ac	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -126,5 +126,3 @@
 AC_PROG_INSTALL
 
-AC_CONFIG_SUBDIRS(libfaim)
-
 AC_OUTPUT(Makefile)
Index: functions.c
===================================================================
--- functions.c	(revision b1fd36ed2941a6f89bdffb20226eafa3ab5ec40b)
+++ functions.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -211,26 +211,4 @@
 }
 
-/* Create an outgoing AIM message, returns a pointer to the created
- * message or NULL if we're not logged into AIM (and thus unable to
- * create the message).  Does not put it on the global queue.  Use
- * owl_function_add_message() for that .
- */
-owl_message *owl_function_make_outgoing_aim(char *body, char *to)
-{
-  owl_message *m;
-
-  /* error if we're not logged into aim */
-  if (!owl_global_is_aimloggedin(&g)) return(NULL);
-  
-  m=owl_malloc(sizeof(owl_message));
-  owl_message_create_aim(m,
-			 owl_global_get_aim_screenname(&g),
-			 to,
-			 body,
-			 OWL_MESSAGE_DIRECTION_OUT,
-			 0);
-  return(m);
-}
-
 /* Create an outgoing loopback message and return a pointer to it.
  * Does not append it to the global queue, use
@@ -292,35 +270,4 @@
   owl_global_set_buffercommand(&g, line);
   owl_global_set_buffercallback(&g, &owl_callback_zwrite);
-}
-
-void owl_function_aimwrite_setup(char *line)
-{
-  owl_editwin *e;
-  char buff[1024];
-
-  /* check the arguments */
-
-  /* create and setup the editwin */
-  e=owl_global_get_typwin(&g);
-  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE, owl_global_get_msg_history(&g));
-
-  if (!owl_global_get_lockout_ctrld(&g)) {
-    owl_function_makemsg("Type your message below.  End with ^D or a dot on a line by itself.  ^C will quit.");
-  } else {
-    owl_function_makemsg("Type your message below.  End with a dot on a line by itself.  ^C will quit.");
-  }
-
-  owl_editwin_clear(e);
-  owl_editwin_set_dotsend(e);
-  strcpy(buff, "----> ");
-  strcat(buff, line);
-  strcat(buff, "\n");
-  owl_editwin_set_locktext(e, buff);
-
-  /* make it active */
-  owl_global_set_typwin_active(&g);
-
-  owl_global_set_buffercommand(&g, line);
-  owl_global_set_buffercallback(&g, &owl_callback_aimwrite);
 }
 
@@ -449,69 +396,4 @@
   owl_free(cryptmsg);
   owl_zwrite_free(&z);
-}
-
-void owl_callback_aimwrite(owl_editwin *e) {
-  owl_function_aimwrite(owl_editwin_get_command(e),
-                        owl_editwin_get_text(e));
-}
-
-void owl_function_aimwrite(char *line, char *msg)
-{
-  int ret;
-  char *to, *format_msg;
-  owl_message *m;
-
-  to = line + 9;
-
-  /* make a formatted copy of the message */
-  format_msg=owl_strdup(msg);
-  owl_text_wordunwrap(format_msg);
-  
-  /* send the message */
-  ret=owl_aim_send_im(to, format_msg);
-  if (!ret) {
-    owl_function_makemsg("AIM message sent.");
-  } else {
-    owl_function_error("Could not send AIM message.");
-  }
-
-  /* create the outgoing message */
-  m=owl_function_make_outgoing_aim(msg, to);
-
-  if (m) {
-    owl_global_messagequeue_addmsg(&g, m);
-  } else {
-    owl_function_error("Could not create outgoing AIM message");
-  }
-
-  owl_free(format_msg);
-}
-
-void owl_function_send_aimawymsg(char *to, char *msg)
-{
-  int ret;
-  char *format_msg;
-  owl_message *m;
-
-  /* make a formatted copy of the message */
-  format_msg=owl_strdup(msg);
-  owl_text_wordunwrap(format_msg);
-  
-  /* send the message */
-  ret=owl_aim_send_awaymsg(to, format_msg);
-  if (!ret) {
-    /* owl_function_makemsg("AIM message sent."); */
-  } else {
-    owl_function_error("Could not send AIM message.");
-  }
-
-  /* create the message */
-  m=owl_function_make_outgoing_aim(msg, to);
-  if (m) {
-    owl_global_messagequeue_addmsg(&g, m);
-  } else {
-    owl_function_error("Could not create AIM message");
-  }
-  owl_free(format_msg);
 }
 
@@ -895,20 +777,4 @@
 }
 
-void owl_callback_aimlogin(owl_editwin *e) {
-  owl_function_aimlogin(owl_editwin_get_command(e),
-                        owl_editwin_get_text(e));
-}
-
-void owl_function_aimlogin(char *user, char *passwd) {
-  int ret;
-
-  /* clear the buddylist */
-  owl_buddylist_clear(owl_global_get_buddylist(&g));
-
-  /* try to login */
-  ret=owl_aim_login(user, passwd);
-  if (ret) owl_function_makemsg("Warning: login for %s failed.\n", user);
-}
-
 void owl_function_suspend()
 {
@@ -943,28 +809,4 @@
 }
 
-void owl_function_aaway_toggle()
-{
-  if (!owl_global_is_aaway(&g)) {
-    owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));
-    owl_function_aaway_on();
-  } else {
-    owl_function_aaway_off();
-  }
-}
-
-void owl_function_aaway_on()
-{
-  owl_global_set_aaway_on(&g);
-  /* owl_aim_set_awaymsg(owl_global_get_zaway_msg(&g)); */
-  owl_function_makemsg("AIM away set (%s)", owl_global_get_aaway_msg(&g));
-}
-
-void owl_function_aaway_off()
-{
-  owl_global_set_aaway_off(&g);
-  /* owl_aim_set_awaymsg(""); */
-  owl_function_makemsg("AIM away off");
-}
-
 void owl_function_quit()
 {
@@ -988,9 +830,4 @@
   owl_zephyr_shutdown();
   
-  /* Quit AIM */
-  if (owl_global_is_aimloggedin(&g)) {
-    owl_aim_logout();
-  }
-
   /* done with curses */
   endwin();
@@ -1948,5 +1785,5 @@
     owl_fmtext_append_normal(&fm, "no\n");
   }
-  owl_fmtext_append_normal(&fm, "  AIM included       : yes\n");
+  owl_fmtext_append_normal(&fm, "  AIM included       : no\n");
   owl_fmtext_append_normal(&fm, "  Loopback included  : yes\n");
 
@@ -1960,20 +1797,4 @@
 #endif
   
-
-  owl_fmtext_append_normal(&fm, "\nAIM Status:\n");
-  owl_fmtext_append_normal(&fm, "  Logged in: ");
-  if (owl_global_is_aimloggedin(&g)) {
-    owl_fmtext_append_normal(&fm, owl_global_get_aim_screenname(&g));
-    owl_fmtext_append_normal(&fm, "\n");
-  } else {
-    owl_fmtext_append_normal(&fm, "(not logged in)\n");
-  }
-
-  owl_fmtext_append_normal(&fm, "  Processing events: ");
-  if (owl_global_is_doaimevents(&g)) {
-    owl_fmtext_append_normal(&fm, "yes\n");
-  } else {
-    owl_fmtext_append_normal(&fm, "no\n");
-  }
 
   owl_function_popless_fmtext(&fm);
@@ -2120,11 +1941,4 @@
         if (cc) owl_free(cc);
       }
-    } else if (owl_message_is_type_aim(m)) {
-      /* aim */
-      if (owl_message_is_direction_out(m)) {
-	buff=owl_sprintf("aimwrite %s", owl_message_get_recipient(m));
-      } else {
-	buff=owl_sprintf("aimwrite %s", owl_message_get_sender(m));
-      }
     } else {
       char *cmd;
@@ -2676,48 +2490,4 @@
   owl_free(longuser);
   owl_free(shortuser);
-
-  return(filtname);
-}
-
-/* Create a filter for AIM IM messages to or from the specified
- * screenname.  The name of the filter will be 'aimuser-<user>'.  If a
- * filter already exists with this name, no new filter will be
- * created.  This allows the configuration to override this function.
- * Returns the name of the filter, which the caller must free.
- */
-char *owl_function_aimuserfilt(char *user)
-{
-  owl_filter *f;
-  char *argbuff, *filtname;
-  char *escuser;
-
-  /* name for the filter */
-  filtname=owl_malloc(strlen(user)+40);
-  sprintf(filtname, "aimuser-%s", user);
-
-  /* if it already exists then go with it.  This lets users override */
-  if (owl_global_get_filter(&g, filtname)) {
-    return(owl_strdup(filtname));
-  }
-
-  /* create the new-internal filter */
-  f=owl_malloc(sizeof(owl_filter));
-
-  escuser = owl_text_quote(user, OWL_REGEX_QUOTECHARS, OWL_REGEX_QUOTEWITH);
-
-  argbuff=owl_malloc(1000);
-  sprintf(argbuff,
-          "( type ^aim$ and ( ( sender ^%s$ and recipient ^%s$ ) or ( sender ^%s$ and recipient ^%s$ ) ) )",
-          escuser, owl_global_get_aim_screenname_for_filters(&g),
-          owl_global_get_aim_screenname_for_filters(&g), escuser);
-
-  owl_filter_init_fromstring(f, filtname, argbuff);
-
-  /* add it to the global list */
-  owl_global_add_filter(&g, f);
-
-  /* free stuff */
-  owl_free(argbuff);
-  owl_free(escuser);
 
   return(filtname);
@@ -2812,14 +2582,4 @@
   if (owl_message_is_type_loopback(m)) {
     return(owl_function_typefilt("loopback"));
-  }
-
-  /* aim messages */
-  if (owl_message_is_type_aim(m)) {
-    if (owl_message_is_direction_in(m)) {
-      filtname=owl_function_aimuserfilt(owl_message_get_sender(m));
-    } else if (owl_message_is_direction_out(m)) {
-      filtname=owl_function_aimuserfilt(owl_message_get_recipient(m));
-    }
-    return(filtname);
   }
 
@@ -3257,10 +3017,7 @@
 void owl_function_buddylist(int aim, int zephyr, char *filename)
 {
-  int i, j, x, idle;
+  int i, j, x;
   owl_fmtext fm;
-  owl_buddylist *bl;
-  owl_buddy *b;
   owl_list anyone;
-  char *foo, *timestr;
 #ifdef HAVE_LIBZEPHYR
   char *tmp, *user, *line;
@@ -3271,25 +3028,6 @@
   owl_fmtext_init_null(&fm);
 
-  /* AIM first */
-  if (aim && owl_global_is_aimloggedin(&g)) {
-    bl=owl_global_get_buddylist(&g);
-
-    owl_fmtext_append_bold(&fm, "AIM users logged in:\n");
-    /* we're assuming AIM for now */
-    j=owl_buddylist_get_size(bl);
-    for (i=0; i<j; i++) {
-      b=owl_buddylist_get_buddy_n(bl, i);
-      idle=owl_buddy_get_idle_time(b);
-      if (idle!=0) {
-	timestr=owl_util_minutes_to_timestr(idle);
-      } else {
-	timestr=owl_strdup("");
-      }
-      foo=owl_sprintf("  %-20.20s %-12.12s\n", owl_buddy_get_name(b), timestr);
-      owl_fmtext_append_normal(&fm, foo);
-      owl_free(timestr);
-      owl_free(foo);
-    }
-  }
+  if (aim && !zephyr)
+    owl_fmtext_append_normal(&fm, "Warning: AIM support in C has been disabled.\n");
 
 #ifdef HAVE_LIBZEPHYR
Index: glib_compat.c
===================================================================
--- glib_compat.c	(revision c60ade251647a4ea5fe6675372c30ea5a7772244)
+++ glib_compat.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -1,3 +1,3 @@
-#include <owl.h>
+#include "owl.h"
 
 #if (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14)
Index: global.c
===================================================================
--- global.c	(revision 9f4e3f8e63d2376fd3e83432be7691fb45f4ffc3)
+++ global.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -97,15 +97,5 @@
   owl_popwin_init(&(g->pw));
 
-  g->aim_screenname=NULL;
-  g->aim_screenname_for_filters=NULL;
-  g->aim_loggedin=0;
-  owl_timer_create_countdown(&(g->aim_noop_timer), 30);
-  owl_timer_create_countdown(&(g->aim_ignorelogin_timer), 0);
-  owl_timer_create_countdown(&(g->aim_buddyinfo_timer), 60);
-  owl_buddylist_init(&(g->buddylist));
-    
   g->havezephyr=0;
-  g->haveaim=0;
-  owl_global_set_no_doaimevents(g);
 
   owl_errqueue_init(&(g->errqueue));
@@ -733,93 +723,4 @@
 }
 
-/* AIM stuff */
-
-int owl_global_is_aimloggedin(owl_global *g)
-{
-  if (g->aim_loggedin) return(1);
-  return(0);
-}
-
-char *owl_global_get_aim_screenname(owl_global *g)
-{
-  if (owl_global_is_aimloggedin(g)) {
-    return (g->aim_screenname);
-  }
-  return("");
-}
-
-char *owl_global_get_aim_screenname_for_filters(owl_global *g)
-{
-  if (owl_global_is_aimloggedin(g)) {
-    return (g->aim_screenname_for_filters);
-  }
-  return("");
-}
-
-void owl_global_set_aimloggedin(owl_global *g, char *screenname)
-{
-  char *sn_escaped, *quote;
-  g->aim_loggedin=1;
-  if (g->aim_screenname) owl_free(g->aim_screenname);
-  if (g->aim_screenname_for_filters) owl_free(g->aim_screenname_for_filters);
-  g->aim_screenname=owl_strdup(screenname);
-  sn_escaped = owl_text_quote(screenname, OWL_REGEX_QUOTECHARS, OWL_REGEX_QUOTEWITH);
-  quote = owl_getquoting(sn_escaped);
-  g->aim_screenname_for_filters=owl_sprintf("%s%s%s", quote, sn_escaped, quote);
-  owl_free(sn_escaped);
-}
-
-void owl_global_set_aimnologgedin(owl_global *g)
-{
-  g->aim_loggedin=0;
-}
-
-int owl_global_is_doaimevents(owl_global *g)
-{
-  if (g->aim_doprocessing) return(1);
-  return(0);
-}
-
-void owl_global_set_doaimevents(owl_global *g)
-{
-  g->aim_doprocessing=1;
-}
-
-void owl_global_set_no_doaimevents(owl_global *g)
-{
-  g->aim_doprocessing=0;
-}
-
-aim_session_t *owl_global_get_aimsess(owl_global *g)
-{
-  return(&(g->aimsess));
-}
-
-aim_conn_t *owl_global_get_bosconn(owl_global *g)
-{
-  return(&(g->bosconn));
-}
-
-void owl_global_set_bossconn(owl_global *g, aim_conn_t *conn)
-{
-  g->bosconn=*conn;
-}
-
-int owl_global_is_aimnop_time(owl_global *g)
-{
-  if (owl_timer_is_expired(&(g->aim_noop_timer))) return(1);
-  return(0);
-}
-
-void owl_global_aimnop_sent(owl_global *g)
-{
-  owl_timer_reset(&(g->aim_noop_timer));
-}
-
-owl_timer *owl_global_get_aim_login_timer(owl_global *g)
-{
-  return(&(g->aim_ignorelogin_timer));
-}
-
 /* message queue */
 
@@ -883,15 +784,4 @@
 }
 
-void owl_global_set_haveaim(owl_global *g)
-{
-  g->haveaim=1;
-}
-
-int owl_global_is_haveaim(owl_global *g)
-{
-  if (g->haveaim) return(1);
-  return(0);
-}
-
 void owl_global_set_havezephyr(owl_global *g)
 {
@@ -903,9 +793,4 @@
   if (g->havezephyr) return(1);
   return(0);
-}
-
-owl_timer *owl_global_get_aim_buddyinfo_timer(owl_global *g)
-{
-  return(&(g->aim_buddyinfo_timer));
 }
 
Index: help.c
===================================================================
--- help.c	(revision ec53338446a35cf944c72d60bbcf932e633c3020)
+++ help.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -50,5 +50,4 @@
      "\n"
      "    z             Start a zwrite command\n"
-     "    a             Start an aimwrite command\n"
      "    r             Reply to the current message\n"
      "    R             Reply to sender\n"
@@ -85,13 +84,10 @@
      "\n"
      "    zwrite        Send a zephyr\n"
-     "    aimlogin      Login to AIM\n"
-     "    aimwrite      Send an AIM message\n"
-     "\n"
-     "    addbuddy      Add a zephyr or AIM buddy\n"
+     "    addbuddy      Add a zephyr buddy\n"
      "    zaway         Turn zaway on or off, or set the message\n"
      "    zlocate       Locate a user\n"
      "    subscribe     Subscribe to a zephyr class or instance\n"
      "    unsubscribe   Unsubscribe to a zephyr class or instance\n"
-     "    blist         Print a list of zephyr and AIM buddies logged in\n"
+     "    blist         Print a list of zephyr buddies logged in\n"
      "    search        Search for a text string\n"
      "\n"
@@ -107,5 +103,4 @@
      "    zlog          Send a login or logout notification\n"
      "    zlist         Print a list of zephyr buddies logged in\n"
-     "    alist         Print a list of AIM buddies logged in\n"
      "    info          Print detailed information about the current message\n"
      "    filter        Create a message filter\n"
Index: keys.c
===================================================================
--- keys.c	(revision 3004c9f7ea88e3888e2d6a71cbf552f9f9f84afb)
+++ keys.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -276,5 +276,4 @@
 
   BIND_CMD("z",   "start-command zwrite ", "start a zwrite command");
-  BIND_CMD("a",   "start-command aimwrite ", "start an aimwrite command");
   BIND_CMD("r",   "reply",            "reply to the current message");
   BIND_CMD("R",   "reply sender",     "reply to sender of the current message");
Index: bfaim/Makefile.in
===================================================================
--- libfaim/Makefile.in	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,21 +1,0 @@
-CC=@CC@
-LIBS=@LIBS@
-LDFLAGS=@LDFLAGS@
-RANLIB=@RANLIB@
-OBJS=admin.o adverts.o auth.o bos.o buddylist.o bstream.o \
-     chat.o chatnav.o conn.o email.o ft.o icq.o im.o \
-     invite.o md5.o misc.o msgcookie.o locate.o \
-     popups.o rxhandlers.o rxqueue.o search.o service.o \
-     snac.o ssi.o stats.o tlv.o translate.o txqueue.o \
-     util.o odir.o bart.o
-CFLAGS=@CFLAGS@ -I. -DAIM_BUILDDATE=\"x\" -DAIM_BUILDTIME=\"x\"
-
-libfaim: $(OBJS)
-	$(AR) -r libfaim.a $(OBJS)
-	$(RANLIB) libfaim.a
-
-clean:
-	$(RM) *.o libfaim.a
-
-distclean: clean
-	$(RM) config.cache config.log config.status Makefile config.h TAGS *~ core
Index: bfaim/admin.c
===================================================================
--- libfaim/admin.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,238 +1,0 @@
-/*
- * Family 0x0007 - Account Administration.
- *
- * Used for stuff like changing the formating of your screen name, changing your 
- * email address, requesting an account confirmation email, getting account info, 
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/*
- * Subtype 0x0002 - Request a bit of account info.
- *
- * Info should be one of the following:
- * 0x0001 - Screen name formatting
- * 0x0011 - Email address
- * 0x0013 - Unknown
- *
- */ 
-faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0007, 0x0002, 0x0000, snacid);
-
-	aimbs_put16(&fr->data, info);
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtypes 0x0003 and 0x0005 - Parse account info.
- *
- * Called in reply to both an information request (subtype 0x0002) and 
- * an information change (subtype 0x0004).
- *
- */
-static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	char *url=NULL, *sn=NULL, *email=NULL;
-	fu16_t perms, tlvcount, err=0;
-
-	perms = aimbs_get16(bs);
-	tlvcount = aimbs_get16(bs);
-
-	while (tlvcount && aim_bstream_empty(bs)) {
-		fu16_t type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		switch (type) {
-			case 0x0001: {
-				sn = aimbs_getstr(bs, length);
-			} break;
-
-			case 0x0004: {
-				url = aimbs_getstr(bs, length);
-			} break;
-
-			case 0x0008: {
-				err = aimbs_get16(bs);
-			} break;
-
-			case 0x0011: {
-				if (length == 0) {
-					email = (char*)malloc(13*sizeof(char));
-					strcpy(email, "*suppressed*");
-				} else
-					email = aimbs_getstr(bs, length);
-			} break;
-		}
-
-		tlvcount--;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email);
-
-	if (sn) free(sn);
-	if (url) free(url);
-	if (email) free(email);
-
-	return 1;
-}
-
-/*
- * Subtype 0x0004 - Set screenname formatting.
- *
- */
-faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newnick))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	aim_tlvlist_add_raw(&tl, 0x0001, strlen(newnick), newnick);
-	
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-	
-	aim_tx_enqueue(sess, fr);
-
-
-	return 0;
-}
-
-/*
- * Subtype 0x0004 - Change password.
- *
- */
-faim_export int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *newpw, const char *curpw)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+strlen(curpw)+4+strlen(newpw))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	/* new password TLV t(0002) */
-	aim_tlvlist_add_raw(&tl, 0x0002, strlen(newpw), newpw);
-
-	/* current password TLV t(0012) */
-	aim_tlvlist_add_raw(&tl, 0x0012, strlen(curpw), curpw);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0004 - Change email address.
- *
- */
-faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newemail))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	aim_tlvlist_add_raw(&tl, 0x0011, strlen(newemail), newemail);
-	
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-	
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0006 - Request account confirmation.
- *
- * This will cause an email to be sent to the address associated with
- * the account.  By following the instructions in the mail, you can
- * get the TRIAL flag removed from your account.
- *
- */
-faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0007, 0x0006);
-}
-
-/*
- * Subtype 0x0007 - Account confirmation request acknowledgement.
- *
- */
-static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t status;
-	aim_tlvlist_t *tl;
-
-	status = aimbs_get16(bs);
-	/* This is 0x0013 if unable to confirm at this time */
-
-	tl = aim_tlvlist_read(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, status);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005))
-		return infochange(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0007)
-		return accountconfirm(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int admin_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0007;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "admin", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/adverts.c
===================================================================
--- libfaim/adverts.c	(revision 862371bb6a5ff5a6491550028e73824b698508bb)
+++ 	(revision )
@@ -1,31 +1,0 @@
-/*
- * Family 0x0005 - Advertisements.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0005, 0x0002);
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	return 0;
-}
-
-faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0005;
-	mod->version = 0x0001;
-	mod->toolid = 0x0001;
-	mod->toolversion = 0x0001;
-	mod->flags = 0;
-	strncpy(mod->name, "adverts", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/aim.h
===================================================================
--- libfaim/aim.h	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,1484 +1,0 @@
-/* 
- * Main libfaim header.  Must be included in client for prototypes/macros.
- *
- * "come on, i turned a chick lesbian; i think this is the hackish equivalent"
- *                                                -- Josh Myer
- *
- */
-
-#ifndef __AIM_H__
-#define __AIM_H__
-
-#define FAIM_VERSION_MAJOR 0
-#define FAIM_VERSION_MINOR 99
-#define FAIM_VERSION_MINORMINOR 1
-
-#include <faimconfig.h>
-#include <aim_cbtypes.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <time.h>
-
-#ifndef _WIN32
-#include <sys/time.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#else
-#include <winsock.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* XXX adjust these based on autoconf-detected platform */
-typedef unsigned char fu8_t;
-typedef unsigned short fu16_t;
-typedef unsigned int fu32_t;
-typedef fu32_t aim_snacid_t;
-typedef fu16_t flap_seqnum_t;
-
-#if defined(mach) && defined(__APPLE__)
-#define gethostbyname(x) gethostbyname2(x, AF_INET) 
-#endif
-
-#if defined(_WIN32) && !defined(WIN32_STATIC)
-/*
- * For a win32 DLL, we define WIN32_INDLL if this file
- * is included while compiling the DLL. If its not 
- * defined (its included in a client app), the symbols
- * will be imported instead of exported.
- */
-#ifdef WIN32_INDLL
-#define faim_export __declspec(dllexport)
-#else 
-#define faim_export __declspec(dllimport)
-#endif /* WIN32_INDLL */
-#define faim_internal
-#else
-/*
- * Nothing normally needed for unix...
- */
-#define faim_export
-#define faim_internal
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-
-#ifndef bool
-#define bool fu8_t
-#endif
-
-/* 
- * Current Maximum Length for Screen Names (not including NULL) 
- *
- * Currently only names up to 16 characters can be registered
- * however it is aparently legal for them to be larger.
- */
-#define MAXSNLEN 97
-
-/*
- * Current Maximum Length for Instant Messages
- *
- * This was found basically by experiment, but not wholly
- * accurate experiment.  It should not be regarded
- * as completely correct.  But its a decent approximation.
- *
- * Note that although we can send this much, its impossible
- * for WinAIM clients (up through the latest (4.0.1957)) to
- * send any more than 1kb.  Amaze all your windows friends
- * with utterly oversized instant messages!
- *
- * XXX: the real limit is the total SNAC size at 8192. Fix this.
- * 
- */
-#define MAXMSGLEN 7987
-
-/*
- * Maximum size of a Buddy Icon.
- */
-#define MAXICONLEN 7168
-#define AIM_ICONIDENT "AVT1picture.id"
-
-/*
- * Current Maximum Length for Chat Room Messages
- *
- * This is actually defined by the protocol to be
- * dynamic, but I have yet to see due cause to 
- * define it dynamically here.  Maybe later.
- *
- */
-#define MAXCHATMSGLEN 512
-
-/**
- * Maximum length for the password of an ICQ account
- */
-#define MAXICQPASSLEN 8
-
-#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
-
-/*
- * Client info.  Filled in by the client and passed in to 
- * aim_send_login().  The information ends up getting passed to OSCAR
- * through the initial login command.
- *
- */
-struct client_info_s {
-	const char *clientstring;
-	fu16_t clientid;
-	fu16_t major;
-	fu16_t minor;
-	fu16_t point;
-	fu16_t build;
-	fu32_t distrib;
-	const char *country; /* two-letter abbrev */
-	const char *lang; /* two-letter abbrev */
-};
-
-/* Needs to be checked */
-#define CLIENTINFO_AIM_3_5_1670 { \
-	"AOL Instant Messenger (SM), version 3.5.1670/WIN32", \
-	0x0004, \
-	0x0003, 0x0005, \
-	0x0000, 0x0686, \
-	0x0000002a, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-/* Latest winaim without ssi */
-#define CLIENTINFO_AIM_4_1_2010 { \
-	"AOL Instant Messenger (SM), version 4.1.2010/WIN32", \
-	0x0004, \
-	0x0004, 0x0001, \
-	0x0000, 0x07da, \
-	0x0000004b, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-#define CLIENTINFO_AIM_4_3_2188 { \
-	"AOL Instant Messenger (SM), version 4.3.2188/WIN32", \
-	0x0109, \
-	0x0400, 0x0003, \
-	0x0000, 0x088c, \
-	0x00000086, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-#define CLIENTINFO_AIM_4_8_2540 { \
-	"AOL Instant Messenger (SM), version 4.8.2540/WIN32", \
-	0x0109, \
-	0x0004, 0x0008, \
-	0x0000, 0x09ec, \
-	0x000000af, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-#define CLIENTINFO_AIM_5_0_2938 { \
-	"AOL Instant Messenger, version 5.0.2938/WIN32", \
-	0x0109, \
-	0x0005, 0x0000, \
-	0x0000, 0x0b7a, \
-	0x00000000, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_AIM_5_1_3036 { \
-	"AOL Instant Messenger, version 5.1.3036/WIN32", \
-	0x0109, \
-	0x0005, 0x0001, \
-	0x0000, 0x0bdc, \
-	0x000000d2, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_AIM_5_5_3415 { \
-	"AOL Instant Messenger, version 5.5.3415/WIN32", \
-	0x0109, \
-	0x0005, 0x0005, \
-	0x0000, 0x0057, \
-	0x000000ef, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_ICHAT_1_0 { \
-	"Apple iChat", \
-	0x311a, \
-	0x0001, 0x0000, \
-	0x0000, 0x003c, \
-	0x000000c6, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-#define CLIENTINFO_ICQ_4_65_3281 { \
-	"ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85", \
-	0x010a, \
-	0x0004, 0x0041, \
-	0x0001, 0x0cd1, \
-	0x00000055, \
-	"us", "en", \
-}
-
-/* Needs to be checked */
-#define CLIENTINFO_ICQ_5_34_3728 { \
-	"ICQ Inc. - Product of ICQ (TM).2002a.5.34.1.3728.85", \
-	0x010a, \
-	0x0005, 0x0022, \
-	0x0001, 0x0e8f, \
-	0x00000055, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_ICQ_5_45_3777 { \
-	"ICQ Inc. - Product of ICQ (TM).2003a.5.45.1.3777.85", \
-	0x010a, \
-	0x0005, 0x002d, \
-	0x0001, 0x0ec1, \
-	0x00000055, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_ICQBASIC_14_3_1068 { \
-	"ICQBasic", \
-	0x010a, \
-	0x0014, 0x0003, \
-	0x0000, 0x042c, \
-	0x0000043d, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_NETSCAPE_7_0_1 { \
-	"Netscape 2000 an approved user of AOL Instant Messenger (SM)", \
-	0x1d0d, \
-	0x0007, 0x0000, \
-	0x0001, 0x0000, \
-	0x00000058, \
-	"us", "en", \
-}
-
-#define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036
-#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_5_45_3777
-
-/* 
- * These could be arbitrary, but its easier to use the actual AIM values 
- */
-#define AIM_CONN_TYPE_BOS		0x0002
-#define AIM_CONN_TYPE_ADS		0x0005
-#define AIM_CONN_TYPE_AUTH		0x0007
-#define AIM_CONN_TYPE_CHATNAV		0x000d
-#define AIM_CONN_TYPE_CHAT		0x000e
-#define AIM_CONN_TYPE_SEARCH		0x000f
-#define AIM_CONN_TYPE_ICON		0x0010
-#define AIM_CONN_TYPE_EMAIL		0x0018
-
-/* they start getting arbitrary for rendezvous stuff =) */
-#define AIM_CONN_TYPE_RENDEZVOUS	0xfffe /* these do not speak FLAP! */
-#define AIM_CONN_TYPE_LISTENER		0xffff /* socket waiting for accept() */
-
-/*
- * Subtypes, we need these for OFT stuff.
- */
-#define AIM_CONN_SUBTYPE_OFT_DIRECTIM	0x0001
-#define AIM_CONN_SUBTYPE_OFT_GETFILE	0x0002
-#define AIM_CONN_SUBTYPE_OFT_SENDFILE	0x0003
-#define AIM_CONN_SUBTYPE_OFT_BUDDYICON	0x0004
-#define AIM_CONN_SUBTYPE_OFT_VOICE	0x0005
-
-/*
- * Status values returned from aim_conn_new().  ORed together.
- */
-#define AIM_CONN_STATUS_READY		0x0001
-#define AIM_CONN_STATUS_INTERNALERR	0x0002
-#define AIM_CONN_STATUS_RESOLVERR	0x0040
-#define AIM_CONN_STATUS_CONNERR		0x0080
-#define AIM_CONN_STATUS_INPROGRESS	0x0100
-
-#define AIM_FRAMETYPE_FLAP		0x0000
-#define AIM_FRAMETYPE_OFT		0x0001
-
-typedef struct aim_conn_s {
-	int fd;
-	fu16_t type;
-	fu16_t subtype;
-	flap_seqnum_t seqnum;
-	fu32_t status;
-	void *priv; /* misc data the client may want to store */
-	void *internal; /* internal conn-specific libfaim data */
-	time_t lastactivity; /* time of last transmit */
-	int forcedlatency; 
-	void *handlerlist;
-	void *sessv; /* pointer to parent session */
-	void *inside; /* only accessible from inside libfaim */
-	struct aim_conn_s *next;
-} aim_conn_t;
-
-/*
- * Byte Stream type. Sort of.
- *
- * Use of this type serves a couple purposes:
- *   - Buffer/buflen pairs are passed all around everywhere. This turns
- *     that into one value, as well as abstracting it slightly.
- *   - Through the abstraction, it is possible to enable bounds checking
- *     for robustness at the cost of performance.  But a clean failure on
- *     weird packets is much better than a segfault.
- *   - I like having variables named "bs".
- *
- * Don't touch the insides of this struct.  Or I'll have to kill you.
- *
- */
-typedef struct aim_bstream_s {
-	fu8_t *data;
-	fu32_t len;
-	fu32_t offset;
-} aim_bstream_t;
-
-typedef struct aim_frame_s {
-	fu8_t hdrtype; /* defines which piece of the union to use */
-	union {
-		struct { 
-			fu8_t type;
-			flap_seqnum_t seqnum;     
-		} flap;
-		struct {
-			fu8_t magic[4]; /* ODC2 or OFT2 */
-			fu16_t hdrlen;
-			fu16_t type;
-		} rend;
-	} hdr;
-	aim_bstream_t data;	/* payload stream */
-	fu8_t handled;		/* 0 = new, !0 = been handled */
-	fu8_t nofree;		/* 0 = free data on purge, 1 = only unlink */
-	aim_conn_t *conn;	/* the connection it came in on... */
-	struct aim_frame_s *next;
-} aim_frame_t;
-
-typedef struct aim_msgcookie_s {
-	fu8_t cookie[8];
-	int type;
-	void *data;
-	time_t addtime;
-	struct aim_msgcookie_s *next;
-} aim_msgcookie_t;
-
-/*
- * AIM Session: The main client-data interface.  
- *
- */
-typedef struct aim_session_s {
-
-	/* ---- Client Accessible ------------------------ */
-
-	/* Our screen name. */
-	char sn[MAXSNLEN+1];
-
-	/*
-	 * Pointer to anything the client wants to 
-	 * explicitly associate with this session.
-	 *
-	 * This is for use in the callbacks mainly. In any
-	 * callback, you can access this with sess->aux_data.
-	 *
-	 */
-	void *aux_data;
-
-	/* ---- Internal Use Only ------------------------ */
-
-	/* Connection information */
-	aim_conn_t *connlist;
-
-	/*
-	 * Transmit/receive queues.
-	 *
-	 * These are only used when you don't use your own lowlevel
-	 * I/O.  I don't suggest that you use libfaim's internal I/O.
-	 * Its really bad and the API/event model is quirky at best.
-	 *  
-	 */
-	aim_frame_t *queue_outgoing;   
-	aim_frame_t *queue_incoming; 
-
-	/*
-	 * Tx Enqueuing function.
-	 *
-	 * This is how you override the transmit direction of libfaim's
-	 * internal I/O.  This function will be called whenever it needs
-	 * to send something.
-	 *
-	 */
-	int (*tx_enqueue)(struct aim_session_s *, aim_frame_t *);
-
-	void *modlistv;
-
-	struct {
-		char server[128];
-		char username[128];
-		char password[128];
-	} socksproxy;
-
-	bool nonblocking;
-
-	int debug;
-	void (*debugcb)(struct aim_session_s *sess, int level, const char *format, va_list va); /* same as faim_debugging_callback_t */
-
-	/*
-	 * Outstanding snac handling 
-	 *
-	 * XXX: Should these be per-connection? -mid
-	 */
-	void *snac_hash[FAIM_SNAC_HASH_SIZE];
-	aim_snacid_t snacid_next;
-
-	aim_msgcookie_t *msgcookies;
-	struct aim_icq_info *icq_info;
-	struct aim_oft_info *oft_info;
-	struct aim_authresp_info *authinfo;
-	struct aim_emailinfo *emailinfo;
-
-	struct {
-		struct aim_userinfo_s *userinfo;
-		struct userinfo_node *torequest;
-		struct userinfo_node *requested;
-		int waiting_for_response;
-	} locate;
-
-	/* Server-stored information (ssi) */
-	struct {
-		int received_data;
-		fu16_t numitems;
-		struct aim_ssi_item *official;
-		struct aim_ssi_item *local;
-		struct aim_ssi_tmp *pending;
-		time_t timestamp;
-		int waiting_for_ack;
-	} ssi;
-} aim_session_t;
-
-/* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */
-#define AIM_ICQ_STATE_NORMAL		0x00000000
-#define AIM_ICQ_STATE_AWAY		0x00000001
-#define AIM_ICQ_STATE_DND		0x00000002
-#define AIM_ICQ_STATE_OUT		0x00000004
-#define AIM_ICQ_STATE_BUSY		0x00000010
-#define AIM_ICQ_STATE_CHAT		0x00000020
-#define AIM_ICQ_STATE_INVISIBLE		0x00000100
-#define AIM_ICQ_STATE_WEBAWARE		0x00010000
-#define AIM_ICQ_STATE_HIDEIP		0x00020000
-#define AIM_ICQ_STATE_BIRTHDAY		0x00080000
-#define AIM_ICQ_STATE_DIRECTDISABLED	0x00100000
-#define AIM_ICQ_STATE_ICQHOMEPAGE	0x00200000
-#define AIM_ICQ_STATE_DIRECTREQUIREAUTH	0x10000000
-#define AIM_ICQ_STATE_DIRECTCONTACTLIST	0x20000000
-
-
-
-/*
- * Get command from connections
- *
- * aim_get_commmand() is the libfaim lowlevel I/O in the receive direction.
- * XXX Make this easily overridable.
- *
- */
-faim_export int aim_get_command(aim_session_t *, aim_conn_t *);
-
-/*
- * Dispatch commands that are in the rx queue.
- */
-faim_export void aim_rxdispatch(aim_session_t *);
-
-faim_export int aim_debugconn_sendconnect(aim_session_t *sess, aim_conn_t *conn);
-
-faim_export int aim_logoff(aim_session_t *);
-
-#if !defined(FAIM_INTERNAL) || defined(FAIM_INTERNAL_INSANE)
-/* the library should never call aim_conn_kill */
-faim_export void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn);
-#endif
-
-typedef int (*aim_rxcallback_t)(aim_session_t *, aim_frame_t *, ...);
-
-
-/* auth.c */
-struct aim_clientrelease {
-	char *name;
-	fu32_t build;
-	char *url;
-	char *info;
-};
-
-struct aim_authresp_info {
-	char *sn;
-	fu16_t errorcode;
-	char *errorurl;
-	fu16_t regstatus;
-	char *email;
-	char *bosip;
-	fu16_t cookielen;
-	fu8_t *cookie;
-	char *chpassurl;
-	struct aim_clientrelease latestrelease;
-	struct aim_clientrelease latestbeta;
-};
-
-/* Callback data for redirect. */
-struct aim_redirect_data {
-	fu16_t group;
-	const char *ip;
-	fu16_t cookielen;
-	const fu8_t *cookie;
-	struct { /* group == AIM_CONN_TYPE_CHAT */
-		fu16_t exchange;
-		const char *room;
-		fu16_t instance;
-	} chat;
-};
-
-faim_export int aim_clientready(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn);
-faim_export int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key);
-faim_export void aim_purge_rxqueue(aim_session_t *);
-faim_export void aim_cleansnacs(aim_session_t *, int maxage);
-
-#define AIM_TX_QUEUED    0 /* default */
-#define AIM_TX_IMMEDIATE 1
-#define AIM_TX_USER      2
-faim_export int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *));
-
-faim_export int aim_tx_flushqueue(aim_session_t *);
-faim_export void aim_tx_purgequeue(aim_session_t *);
-
-faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval);
-
-faim_export int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t type, aim_rxcallback_t newhandler, fu16_t flags);
-faim_export int aim_clearhandlers(aim_conn_t *conn);
-
-faim_export aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, fu16_t group);
-faim_export aim_session_t *aim_conn_getsess(aim_conn_t *conn);
-faim_export void aim_conn_close(aim_conn_t *deadconn);
-faim_export aim_conn_t *aim_newconn(aim_session_t *, int type, const char *dest);
-faim_export int aim_conngetmaxfd(aim_session_t *);
-faim_export aim_conn_t *aim_select(aim_session_t *, struct timeval *, int *);
-faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_conn_isready(aim_conn_t *);
-faim_export int aim_conn_setstatus(aim_conn_t *, int);
-faim_export int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_conn_isconnecting(aim_conn_t *conn);
-
-typedef void (*faim_debugging_callback_t)(aim_session_t *sess, int level, const char *format, va_list va);
-faim_export int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t);
-faim_export void aim_session_init(aim_session_t *, bool nonblocking, int debuglevel);
-faim_export void aim_session_kill(aim_session_t *);
-faim_export void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password);
-faim_export aim_conn_t *aim_getconn_type(aim_session_t *, int type);
-faim_export aim_conn_t *aim_getconn_type_all(aim_session_t *, int type);
-faim_export aim_conn_t *aim_getconn_fd(aim_session_t *, int fd);
-
-
-
-/* 0x0001 - service.c */
-faim_export int aim_srv_setavailmsg(aim_session_t *sess, char *msg);
-faim_export int aim_srv_setidle(aim_session_t *sess, fu32_t idletime);
-
-
-
-/* misc.c */
-
-#define AIM_VISIBILITYCHANGE_PERMITADD    0x05
-#define AIM_VISIBILITYCHANGE_PERMITREMOVE 0x06
-#define AIM_VISIBILITYCHANGE_DENYADD      0x07
-#define AIM_VISIBILITYCHANGE_DENYREMOVE   0x08
-
-#define AIM_PRIVFLAGS_ALLOWIDLE           0x01
-#define AIM_PRIVFLAGS_ALLOWMEMBERSINCE    0x02
-
-#define AIM_WARN_ANON                     0x01
-
-faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_nop(aim_session_t *, aim_conn_t *);
-faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_bos_changevisibility(aim_session_t *, aim_conn_t *, int, const char *);
-faim_export int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, fu32_t mask);
-faim_export int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, fu32_t);
-faim_export int aim_reqpersonalinfo(aim_session_t *, aim_conn_t *);
-faim_export int aim_reqservice(aim_session_t *, aim_conn_t *, fu16_t);
-faim_export int aim_bos_reqrights(aim_session_t *, aim_conn_t *);
-faim_export int aim_setextstatus(aim_session_t *sess, fu32_t status);
-
-#define AIM_CLIENTTYPE_UNKNOWN  0x0000
-#define AIM_CLIENTTYPE_MC       0x0001
-#define AIM_CLIENTTYPE_WINAIM   0x0002
-#define AIM_CLIENTTYPE_WINAIM41 0x0003
-#define AIM_CLIENTTYPE_AOL_TOC  0x0004
-faim_export fu16_t aim_im_fingerprint(const fu8_t *msghdr, int len);
-
-#define AIM_RATE_CODE_CHANGE     0x0001
-#define AIM_RATE_CODE_WARNING    0x0002
-#define AIM_RATE_CODE_LIMIT      0x0003
-#define AIM_RATE_CODE_CLEARLIMIT 0x0004
-faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn);
-
-
-
-/* im.c */
-#define AIM_OFT_SUBTYPE_SEND_FILE	0x0001
-#define AIM_OFT_SUBTYPE_SEND_DIR	0x0002
-#define AIM_OFT_SUBTYPE_GET_FILE	0x0011
-#define AIM_OPT_SUBTYPE_GET_LIST	0x0012
-
-#define AIM_TRANSFER_DENY_NOTSUPPORTED	0x0000
-#define AIM_TRANSFER_DENY_DECLINE	0x0001
-#define AIM_TRANSFER_DENY_NOTACCEPTING	0x0002
-
-#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED	0x00000001
-#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED	0x00000002
-
-/* This is what the server will give you if you don't set them yourself. */
-#define AIM_IMPARAM_DEFAULTS { \
-	0, \
-	AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \
-	512, /* !! Note how small this is. */ \
-	(99.9)*10, (99.9)*10, \
-	1000 /* !! And how large this is. */ \
-}
-
-/* This is what most AIM versions use. */
-#define AIM_IMPARAM_REASONABLE { \
-	0, \
-	AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \
-	8000, \
-	(99.9)*10, (99.9)*10, \
-	0 \
-}
-
-struct aim_icbmparameters {
-	fu16_t maxchan;
-	fu32_t flags; /* AIM_IMPARAM_FLAG_ */
-	fu16_t maxmsglen; /* message size that you will accept */
-	fu16_t maxsenderwarn; /* this and below are *10 (999=99.9%) */
-	fu16_t maxrecverwarn;
-	fu32_t minmsginterval; /* in milliseconds? */
-};
-
-struct aim_chat_roominfo {
-	fu16_t exchange;
-	char *name;
-	fu16_t instance;
-};
-
-#define AIM_IMFLAGS_AWAY		0x0001 /* mark as an autoreply */
-#define AIM_IMFLAGS_ACK			0x0002 /* request a receipt notice */
-#define AIM_IMFLAGS_UNICODE		0x0004
-#define AIM_IMFLAGS_ISO_8859_1		0x0008
-#define AIM_IMFLAGS_BUDDYREQ		0x0010 /* buddy icon requested */
-#define AIM_IMFLAGS_HASICON		0x0020 /* already has icon */
-#define AIM_IMFLAGS_SUBENC_MACINTOSH	0x0040 /* damn that Steve Jobs! */
-#define AIM_IMFLAGS_CUSTOMFEATURES 	0x0080 /* features field present */
-#define AIM_IMFLAGS_EXTDATA		0x0100
-#define AIM_IMFLAGS_X			0x0200
-#define AIM_IMFLAGS_MULTIPART		0x0400 /* ->mpmsg section valid */
-#define AIM_IMFLAGS_OFFLINE		0x0800 /* send to offline user */
-#define AIM_IMFLAGS_TYPINGNOT		0x1000 /* typing notification */
-
-/*
- * Multipart message structures.
- */
-typedef struct aim_mpmsg_section_s {
-	fu16_t charset;
-	fu16_t charsubset;
-	fu8_t *data;
-	fu16_t datalen;
-	struct aim_mpmsg_section_s *next;
-} aim_mpmsg_section_t;
-
-typedef struct aim_mpmsg_s {
-	int numparts;
-	aim_mpmsg_section_t *parts;
-} aim_mpmsg_t;
-
-faim_export int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm);
-faim_export int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, fu16_t charset, fu16_t charsubset, const fu8_t *data, fu16_t datalen);
-faim_export int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii);
-faim_export int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const fu16_t *unicode, fu16_t unicodelen);
-faim_export void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm);
-
-/*
- * Arguments to aim_send_im_ext().
- *
- * This is really complicated.  But immensely versatile.
- *
- */
-struct aim_sendimext_args {
-
-	/* These are _required_ */
-	const char *destsn;
-	fu32_t flags; /* often 0 */
-
-	/* Only required if not using multipart messages */
-	const char *msg;
-	int msglen;
-
-	/* Required if ->msg is not provided */
-	aim_mpmsg_t *mpmsg;
-
-	/* Only used if AIM_IMFLAGS_HASICON is set */
-	fu32_t iconlen;
-	time_t iconstamp;
-	fu32_t iconsum;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMFEATURES is set */
-	fu8_t *features;
-	fu8_t featureslen;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set and mpmsg not used */
-	fu16_t charset;
-	fu16_t charsubset;
-};
-
-/*
- * Arguments to aim_send_rtfmsg().
- */
-struct aim_sendrtfmsg_args {
-	const char *destsn;
-	fu32_t fgcolor;
-	fu32_t bgcolor;
-	const char *rtfmsg; /* must be in RTF */
-};
-
-/*
- * This information is provided in the Incoming ICBM callback for
- * Channel 1 ICBM's.  
- *
- * Note that although CUSTOMFEATURES and CUSTOMCHARSET say they
- * are optional, both are always set by the current libfaim code.
- * That may or may not change in the future.  It is mainly for
- * consistency with aim_sendimext_args.
- *
- * Multipart messages require some explanation. If you want to use them,
- * I suggest you read all the comments in im.c.
- *
- */
-struct aim_incomingim_ch1_args {
-
-	/* Always provided */
-	aim_mpmsg_t mpmsg;
-	fu32_t icbmflags; /* some flags apply only to ->msg, not all mpmsg */
-	
-	/* Only provided if message has a human-readable section */
-	char *msg;
-	int msglen;
-
-	/* Only provided if AIM_IMFLAGS_HASICON is set */
-	time_t iconstamp;
-	fu32_t iconlen;
-	fu16_t iconsum;
-
-	/* Only provided if AIM_IMFLAGS_CUSTOMFEATURES is set */
-	fu8_t *features;
-	fu8_t featureslen;
-
-	/* Only provided if AIM_IMFLAGS_EXTDATA is set */
-	fu8_t extdatalen;
-	fu8_t *extdata;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set */
-	fu16_t charset;
-	fu16_t charsubset;
-};
-
-/* Valid values for channel 2 args->status */
-#define AIM_RENDEZVOUS_PROPOSE	0x0000
-#define AIM_RENDEZVOUS_CANCEL	0x0001
-#define AIM_RENDEZVOUS_ACCEPT	0x0002
-
-struct aim_incomingim_ch2_args {
-	fu16_t status;
-	fu8_t cookie[8];
-	int reqclass;
-	const char *proxyip;
-	const char *clientip;
-	const char *verifiedip;
-	fu16_t port;
-	fu16_t errorcode;
-	const char *msg; /* invite message or file description */
-	const char *encoding;
-	const char *language;
-	union {
-		struct {
-			fu32_t checksum;
-			fu32_t length;
-			time_t timestamp;
-			fu8_t *icon;
-		} icon;
-		struct {
-			struct aim_chat_roominfo roominfo;
-		} chat;
-		struct {
-			fu32_t fgcolor;
-			fu32_t bgcolor;
-			const char *rtfmsg;
-		} rtfmsg;
-		struct {
-			fu16_t subtype;
-			fu16_t totfiles;
-			fu32_t totsize;
-			char *filename;
-		} sendfile;
-	} info;
-	void *destructor; /* used internally only */
-};
-
-/* Valid values for channel 4 args->type */
-#define AIM_ICQMSG_AUTHREQUEST	0x0006
-#define AIM_ICQMSG_AUTHDENIED	0x0007
-#define AIM_ICQMSG_AUTHGRANTED	0x0008
-
-struct aim_incomingim_ch4_args {
-	fu32_t uin; /* Of the sender of the ICBM */
-	fu8_t type;
-	fu8_t flags;
-	char *msg; /* Reason for auth request, deny, or accept */
-	int msglen;
-};
-
-/* SNAC sending functions */
-/* 0x0002 */ faim_export int aim_im_setparams(aim_session_t *sess, struct aim_icbmparameters *params);
-/* 0x0004 */ faim_export int aim_im_reqparams(aim_session_t *sess);
-/* 0x0006 */ faim_export int aim_im_sendch1_ext(aim_session_t *sess, struct aim_sendimext_args *args);
-/* 0x0006 */ faim_export int aim_im_sendch1(aim_session_t *, const char *destsn, fu16_t flags, const char *msg);
-/* 0x0006 */ faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum);
-/* 0x0006 */ faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args);
-/* 0x0006 */ faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port);
-/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info);
-/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *info);
-/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info);
-/* 0x0006 */ faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type);
-/* 0x0006 */ faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message);
-/* 0x0008 */ faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags);
-/* 0x000b */ faim_export int aim_im_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code);
-/* 0x0014 */ faim_export int aim_im_sendmtn(aim_session_t *sess, fu16_t type1, const char *sn, fu16_t type2);
-
-
-
-/* ft.c */
-struct aim_fileheader_t {
-#if 0
-	char magic[4];		/* 0 */
-	fu16_t hdrlen;		/* 4 */
-	fu16_t hdrtype;		/* 6 */
-#endif
-	char bcookie[8];	/* 8 */
-	fu16_t encrypt;		/* 16 */
-	fu16_t compress;	/* 18 */
-	fu16_t totfiles;	/* 20 */
-	fu16_t filesleft;	/* 22 */
-	fu16_t totparts;	/* 24 */
-	fu16_t partsleft;	/* 26 */
-	fu32_t totsize;		/* 28 */
-	fu32_t size;		/* 32 */
-	fu32_t modtime;		/* 36 */
-	fu32_t checksum;	/* 40 */
-	fu32_t rfrcsum;		/* 44 */
-	fu32_t rfsize;		/* 48 */
-	fu32_t cretime;		/* 52 */
-	fu32_t rfcsum;		/* 56 */
-	fu32_t nrecvd;		/* 60 */
-	fu32_t recvcsum;	/* 64 */
-	fu8_t idstring[32];	/* 68 */
-	fu8_t flags;		/* 100 */
-	fu8_t lnameoffset;	/* 101 */
-	fu8_t lsizeoffset;	/* 102 */
-	char dummy[69];		/* 103 */
-	char macfileinfo[16];	/* 172 */
-	fu16_t nencode;		/* 188 */
-	fu16_t nlanguage;	/* 190 */
-	char name[64];		/* 192 */
-				/* 256 */
-};
-
-struct aim_oft_info {
-	char cookie[8];
-	char *sn;
-	char *proxyip;
-	char *clientip;
-	char *verifiedip;
-	fu16_t port;
-	aim_conn_t *conn;
-	aim_session_t *sess;
-	struct aim_fileheader_t fh;
-	struct aim_oft_info *next;
-};
-
-faim_export fu32_t aim_oft_checksum_chunk(const fu8_t *buffer, int bufferlen, fu32_t prevcheck);
-faim_export fu32_t aim_oft_checksum_file(char *filename);
-faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur);
-faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing);
-faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg);
-faim_export const char *aim_odc_getsn(aim_conn_t *conn);
-faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn);
-faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn);
-faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie);
-
-faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename);
-faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info);
-faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info);
-faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info);
-
-
-
-/* 0x0002 - locate.c */
-/*
- * AIM User Info, Standard Form.
- */
-#define AIM_FLAG_UNCONFIRMED	0x0001 /* "damned transients" */
-#define AIM_FLAG_ADMINISTRATOR	0x0002
-#define AIM_FLAG_AOL			0x0004
-#define AIM_FLAG_OSCAR_PAY		0x0008
-#define AIM_FLAG_FREE 			0x0010
-#define AIM_FLAG_AWAY			0x0020
-#define AIM_FLAG_ICQ			0x0040
-#define AIM_FLAG_WIRELESS		0x0080
-#define AIM_FLAG_UNKNOWN100		0x0100
-#define AIM_FLAG_UNKNOWN200		0x0200
-#define AIM_FLAG_ACTIVEBUDDY	0x0400
-#define AIM_FLAG_UNKNOWN800		0x0800
-#define AIM_FLAG_ABINTERNAL		0x1000
-#define AIM_FLAG_ALLUSERS		0x001f
-
-#define AIM_USERINFO_PRESENT_FLAGS        0x00000001
-#define AIM_USERINFO_PRESENT_MEMBERSINCE  0x00000002
-#define AIM_USERINFO_PRESENT_ONLINESINCE  0x00000004
-#define AIM_USERINFO_PRESENT_IDLE         0x00000008
-#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010
-#define AIM_USERINFO_PRESENT_ICQIPADDR    0x00000020
-#define AIM_USERINFO_PRESENT_ICQDATA      0x00000040
-#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080
-#define AIM_USERINFO_PRESENT_SESSIONLEN   0x00000100
-#define AIM_USERINFO_PRESENT_CREATETIME   0x00000200
-
-struct userinfo_node {
-	char *sn;
-	struct userinfo_node *next;
-};
-
-typedef struct aim_userinfo_s {
-	char *sn;
-	fu16_t warnlevel; /* evil percent * 10 (999 = 99.9%) */
-	fu16_t idletime; /* in seconds */
-	fu16_t flags;
-	fu32_t createtime; /* time_t */
-	fu32_t membersince; /* time_t */
-	fu32_t onlinesince; /* time_t */
-	fu32_t sessionlen;  /* in seconds */
-	fu32_t capabilities;
-	struct {
-		fu32_t status;
-		fu32_t ipaddr;
-		fu8_t crap[0x25]; /* until we figure it out... */
-	} icqinfo;
-	fu32_t present;
-
-	fu16_t iconcsumlen;
-	fu8_t *iconcsum;
-
-	char *info;
-	char *info_encoding;
-	fu16_t info_len;
-
-	char *avail;
-	char *avail_encoding;
-	fu16_t avail_len;
-
-	char *away;
-	char *away_encoding;
-	fu16_t away_len;
-
-	struct aim_userinfo_s *next;
-} aim_userinfo_t;
-
-#define AIM_CAPS_BUDDYICON		0x00000001
-#define AIM_CAPS_VOICE			0x00000002
-#define AIM_CAPS_DIRECTIM		0x00000004
-#define AIM_CAPS_CHAT			0x00000008
-#define AIM_CAPS_GETFILE		0x00000010
-#define AIM_CAPS_SENDFILE		0x00000020
-#define AIM_CAPS_GAMES			0x00000040
-#define AIM_CAPS_SAVESTOCKS		0x00000080
-#define AIM_CAPS_SENDBUDDYLIST	0x00000100
-#define AIM_CAPS_GAMES2			0x00000200
-#define AIM_CAPS_ICQ_DIRECT		0x00000400
-#define AIM_CAPS_APINFO			0x00000800
-#define AIM_CAPS_ICQRTF			0x00001000
-#define AIM_CAPS_EMPTY			0x00002000
-#define AIM_CAPS_ICQSERVERRELAY	0x00004000
-#define AIM_CAPS_ICQUTF8OLD		0x00008000
-#define AIM_CAPS_TRILLIANCRYPT	0x00010000
-#define AIM_CAPS_ICQUTF8		0x00020000
-#define AIM_CAPS_INTEROPERATE	0x00040000
-#define AIM_CAPS_ICHAT			0x00080000
-#define AIM_CAPS_HIPTOP			0x00100000
-#define AIM_CAPS_SECUREIM		0x00200000
-#define AIM_CAPS_SMS			0x00400000
-#define AIM_CAPS_GENERICUNKNOWN	0x00800000
-#define AIM_CAPS_VIDEO			0x01000000
-#define AIM_CAPS_LAST			0x02000000
-
-#define AIM_SENDMEMBLOCK_FLAG_ISREQUEST  0
-#define AIM_SENDMEMBLOCK_FLAG_ISHASH     1
-
-faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, fu32_t offset, fu32_t len, const fu8_t *buf, fu8_t flag);
-
-struct aim_invite_priv {
-	char *sn;
-	char *roomname;
-	fu16_t exchange;
-	fu16_t instance;
-};
-
-#define AIM_COOKIETYPE_UNKNOWN  0x00
-#define AIM_COOKIETYPE_ICBM     0x01
-#define AIM_COOKIETYPE_ADS      0x02
-#define AIM_COOKIETYPE_BOS      0x03
-#define AIM_COOKIETYPE_IM       0x04
-#define AIM_COOKIETYPE_CHAT     0x05
-#define AIM_COOKIETYPE_CHATNAV  0x06
-#define AIM_COOKIETYPE_INVITE   0x07
-/* we'll move OFT up a bit to give breathing room.  not like it really
- * matters. */
-#define AIM_COOKIETYPE_OFTIM    0x10
-#define AIM_COOKIETYPE_OFTGET   0x11
-#define AIM_COOKIETYPE_OFTSEND  0x12
-#define AIM_COOKIETYPE_OFTVOICE 0x13
-#define AIM_COOKIETYPE_OFTIMAGE 0x14
-#define AIM_COOKIETYPE_OFTICON  0x15
-
-faim_export aim_userinfo_t *aim_locate_finduserinfo(aim_session_t *sess, const char *sn);
-
-/* 0x0002 */ faim_export int aim_locate_reqrights(aim_session_t *sess);
-/* 0x0004 */ faim_export int aim_locate_setprofile(aim_session_t *sess, const char *profile_encoding, const char *profile, const int profile_len, const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len);
-/* 0x0004 */ faim_export int aim_locate_setcaps(aim_session_t *sess, fu32_t caps);
-/* 0x0005 */ faim_export int aim_locate_getinfo(aim_session_t *sess, const char *, fu16_t);
-/* 0x0009 */ faim_export int aim_locate_setdirinfo(aim_session_t *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy);
-/* 0x000b */ faim_export int aim_locate_000b(aim_session_t *sess, const char *sn);
-/* 0x000f */ faim_export int aim_locate_setinterests(aim_session_t *sess, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy);
-/* 0x0015 */ faim_export int aim_locate_getinfoshort(aim_session_t *sess, const char *sn, fu32_t flags);
-
-
-
-/* 0x0003 - buddylist.c */
-/* 0x0002 */ faim_export int aim_buddylist_reqrights(aim_session_t *, aim_conn_t *);
-/* 0x0004 */ faim_export int aim_buddylist_set(aim_session_t *, aim_conn_t *, const char *);
-/* 0x0004 */ faim_export int aim_buddylist_addbuddy(aim_session_t *, aim_conn_t *, const char *);
-/* 0x0005 */ faim_export int aim_buddylist_removebuddy(aim_session_t *, aim_conn_t *, const char *);
-/* 0x000b */ faim_export int aim_buddylist_oncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info);
-/* 0x000c */ faim_export int aim_buddylist_offgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn);
-
-
-
-/* 0x000a - search.c */
-faim_export int aim_search_address(aim_session_t *, aim_conn_t *, const char *);
-
-
-
-/* 0x000d - chatnav.c */
-/* 0x000e - chat.c */
-/* These apply to exchanges as well. */
-#define AIM_CHATROOM_FLAG_EVILABLE 0x0001
-#define AIM_CHATROOM_FLAG_NAV_ONLY 0x0002
-#define AIM_CHATROOM_FLAG_INSTANCING_ALLOWED 0x0004
-#define AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED 0x0008
-
-struct aim_chat_exchangeinfo {
-	fu16_t number;
-	fu16_t flags;
-	char *name;
-	char *charset1;
-	char *lang1;
-	char *charset2;
-	char *lang2;
-};
-
-#define AIM_CHATFLAGS_NOREFLECT 0x0001
-#define AIM_CHATFLAGS_AWAY      0x0002
-faim_export int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, fu16_t flags, const char *msg, int msglen);
-faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance);
-faim_export int aim_chat_attachname(aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance);
-faim_export char *aim_chat_getname(aim_conn_t *conn);
-faim_export aim_conn_t *aim_chat_getconn(aim_session_t *, const char *name);
-
-faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn);
-
-faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance);
-
-faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange);
-faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name);
-
-
-
-/* 0x000f - odir.c */
-struct aim_odir {
-	char *first;
-	char *last;
-	char *middle;
-	char *maiden;
-	char *email;
-	char *country;
-	char *state;
-	char *city;
-	char *sn;
-	char *interest;
-	char *nick;
-	char *zip;
-	char *region;
-	char *address;
-	struct aim_odir *next;
-};
-
-faim_export int aim_odir_email(aim_session_t *, const char *, const char *);
-faim_export int aim_odir_name(aim_session_t *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *);
-faim_export int aim_odir_interest(aim_session_t *, const char *, const char *);
-
-
-
-/* 0x0010 - icon.c */
-faim_export int aim_bart_upload(aim_session_t *sess, const fu8_t *icon, fu16_t iconlen);
-faim_export int aim_bart_request(aim_session_t *sess, const char *sn, const fu8_t *iconstr, fu16_t iconstrlen);
-
-
-
-/* 0x0013 - ssi.c */
-#define AIM_SSI_TYPE_BUDDY		0x0000
-#define AIM_SSI_TYPE_GROUP		0x0001
-#define AIM_SSI_TYPE_PERMIT		0x0002
-#define AIM_SSI_TYPE_DENY		0x0003
-#define AIM_SSI_TYPE_PDINFO		0x0004
-#define AIM_SSI_TYPE_PRESENCEPREFS	0x0005
-#define AIM_SSI_TYPE_ICONINFO		0x0014
-
-#define AIM_SSI_ACK_SUCCESS		0x0000
-#define AIM_SSI_ACK_ITEMNOTFOUND	0x0002
-#define AIM_SSI_ACK_IDNUMINUSE		0x000a
-#define AIM_SSI_ACK_ATMAX		0x000c
-#define AIM_SSI_ACK_INVALIDNAME		0x000d
-#define AIM_SSI_ACK_AUTHREQUIRED	0x000e
-
-struct aim_ssi_item {
-	char *name;
-	fu16_t gid;
-	fu16_t bid;
-	fu16_t type;
-	struct aim_tlvlist_s *data;
-	struct aim_ssi_item *next;
-};
-
-struct aim_ssi_tmp {
-	fu16_t action;
-	fu16_t ack;
-	char *name;
-	struct aim_ssi_item *item;
-	struct aim_ssi_tmp *next;
-};
-
-/* These build the actual SNACs and queue them to be sent */
-/* 0x0002 */ faim_export int aim_ssi_reqrights(aim_session_t *sess);
-/* 0x0004 */ faim_export int aim_ssi_reqdata(aim_session_t *sess);
-/* 0x0005 */ faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t localstamp, fu16_t localrev);
-/* 0x0007 */ faim_export int aim_ssi_enable(aim_session_t *sess);
-/* 0x0008 */ faim_export int aim_ssi_addmoddel(aim_session_t *sess);
-/* 0x0011 */ faim_export int aim_ssi_modbegin(aim_session_t *sess);
-/* 0x0012 */ faim_export int aim_ssi_modend(aim_session_t *sess);
-/* 0x0014 */ faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg);
-/* 0x0018 */ faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg);
-/* 0x001a */ faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg);
-
-/* Client functions for retrieving SSI data */
-faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid);
-faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type);
-faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn);
-faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn);
-faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list);
-faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list);
-faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn);
-faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn);
-faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn);
-
-/* Client functions for changing SSI data */
-faim_export int aim_ssi_addbuddy(aim_session_t *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth);
-faim_export int aim_ssi_addpermit(aim_session_t *sess, const char *name);
-faim_export int aim_ssi_adddeny(aim_session_t *sess, const char *name);
-faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group);
-faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name);
-faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name);
-faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn);
-faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias);
-faim_export int aim_ssi_editcomment(aim_session_t *sess, const char *gn, const char *sn, const char *alias);
-faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn);
-faim_export int aim_ssi_cleanlist(aim_session_t *sess);
-faim_export int aim_ssi_deletelist(aim_session_t *sess);
-faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask);
-faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence);
-faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen);
-faim_export int aim_ssi_delicon(aim_session_t *sess);
-
-
-
-/* 0x0015 - icq.c */
-#define AIM_ICQ_INFO_SIMPLE	0x001
-#define AIM_ICQ_INFO_SUMMARY	0x002
-#define AIM_ICQ_INFO_EMAIL	0x004
-#define AIM_ICQ_INFO_PERSONAL	0x008
-#define AIM_ICQ_INFO_ADDITIONAL	0x010
-#define AIM_ICQ_INFO_WORK	0x020
-#define AIM_ICQ_INFO_INTERESTS	0x040
-#define AIM_ICQ_INFO_ORGS	0x080
-#define AIM_ICQ_INFO_UNKNOWN	0x100
-#define AIM_ICQ_INFO_HAVEALL	0x1ff
-
-struct aim_icq_offlinemsg {
-	fu32_t sender;
-	fu16_t year;
-	fu8_t month, day, hour, minute;
-	fu8_t type;
-	fu8_t flags;
-	char *msg;
-	int msglen;
-};
-
-struct aim_icq_info {
-	fu16_t reqid;
-
-	/* simple */
-	fu32_t uin;
-
-	/* general and "home" information (0x00c8) */
-	char *nick;
-	char *first;
-	char *last;
-	char *email;
-	char *homecity;
-	char *homestate;
-	char *homephone;
-	char *homefax;
-	char *homeaddr;
-	char *mobile;
-	char *homezip;
-	fu16_t homecountry;
-/*	fu8_t timezone;
-	fu8_t hideemail; */
-
-	/* personal (0x00dc) */
-	fu8_t age;
-	fu8_t unknown;
-	fu8_t gender;
-	char *personalwebpage;
-	fu16_t birthyear;
-	fu8_t birthmonth;
-	fu8_t birthday;
-	fu8_t language1;
-	fu8_t language2;
-	fu8_t language3;
-
-	/* work (0x00d2) */
-	char *workcity;
-	char *workstate;
-	char *workphone;
-	char *workfax;
-	char *workaddr;
-	char *workzip;
-	fu16_t workcountry;
-	char *workcompany;
-	char *workdivision;
-	char *workposition;
-	char *workwebpage;
-
-	/* additional personal information (0x00e6) */
-	char *info;
-
-	/* email (0x00eb) */
-	fu16_t numaddresses;
-	char **email2;
-
-	/* we keep track of these in a linked list because we're 1337 */
-	struct aim_icq_info *next;
-};
-
-faim_export int aim_icq_reqofflinemsgs(aim_session_t *sess);
-faim_export int aim_icq_ackofflinemsgs(aim_session_t *sess);
-faim_export int aim_icq_hideip(aim_session_t *sess);
-faim_export int aim_icq_changepasswd(aim_session_t *sess, const char *passwd);
-faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin);
-faim_export int aim_icq_getalias(aim_session_t *sess, const char *uin);
-faim_export int aim_icq_getallinfo(aim_session_t *sess, const char *uin);
-
-
-
-/* 0x0017 - auth.c */
-faim_export int aim_sendcookie(aim_session_t *, aim_conn_t *, const fu16_t length, const fu8_t *);
-faim_export int aim_admin_changepasswd(aim_session_t *, aim_conn_t *, const char *newpw, const char *curpw);
-faim_export int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info);
-faim_export int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail);
-faim_export int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick);
-
-
-
-/* 0x0018 - email.c */
-struct aim_emailinfo {
-	fu8_t *cookie16;
-	fu8_t *cookie8;
-	char *url;
-	fu16_t nummsgs;
-	fu8_t unread;
-	char *domain;
-	fu16_t flag;
-	struct aim_emailinfo *next;
-};
-
-faim_export int aim_email_sendcookies(aim_session_t *sess);
-faim_export int aim_email_activate(aim_session_t *sess);
-
-
-
-#if defined(FAIM_INTERNAL) || defined(FAIM_NEED_TLV)
-/* tlv.c - TLV handling */
-
-/* TLV structure */
-typedef struct aim_tlv_s {
-	fu16_t type;
-	fu16_t length;
-	fu8_t *value;
-} aim_tlv_t;
-
-/* TLV List structure */
-typedef struct aim_tlvlist_s {
-	aim_tlv_t *tlv;
-	struct aim_tlvlist_s *next;
-} aim_tlvlist_t;
-
-/* TLV handling functions */
-faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, fu16_t type, const int nth);
-faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const fu16_t type, const int nth);
-faim_internal fu8_t aim_tlv_get8(aim_tlvlist_t *list, const fu16_t type, const int nth);
-faim_internal fu16_t aim_tlv_get16(aim_tlvlist_t *list, const fu16_t type, const int nth);
-faim_internal fu32_t aim_tlv_get32(aim_tlvlist_t *list, const fu16_t type, const int nth);
-
-/* TLV list handling functions */
-faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs);
-faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num);
-faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len);
-faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig);
-
-faim_internal int aim_tlvlist_count(aim_tlvlist_t **list);
-faim_internal int aim_tlvlist_size(aim_tlvlist_t **list);
-faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two);
-faim_internal int aim_tlvlist_write(aim_bstream_t *bs, aim_tlvlist_t **list);
-faim_internal void aim_tlvlist_free(aim_tlvlist_t **list);
-
-faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value);
-faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const fu16_t type);
-faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value);
-faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value);
-faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value);
-faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const fu16_t type, const fu32_t caps);
-faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *userinfo);
-faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl);
-
-faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t lenth, const fu8_t *value);
-faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const fu16_t type);
-faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value);
-faim_internal int aim_tlvlist_replace_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value);
-faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value);
-
-faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const fu16_t type);
-#endif /* FAIM_INTERNAL */
-
-
-
-/* util.c */
-/*
- * These are really ugly.  You'd think this was LISP.  I wish it was.
- *
- * XXX With the advent of bstream's, these should be removed to enforce
- * their use.
- *
- */
-#define aimutil_put8(buf, data) ((*(buf) = (fu8_t)(data)&0xff),1)
-#define aimutil_get8(buf) ((*(buf))&0xff)
-#define aimutil_put16(buf, data) ( \
-		(*(buf) = (fu8_t)((data)>>8)&0xff), \
-		(*((buf)+1) = (fu8_t)(data)&0xff),  \
-		2)
-#define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
-#define aimutil_put32(buf, data) ( \
-		(*((buf)) = (fu8_t)((data)>>24)&0xff), \
-		(*((buf)+1) = (fu8_t)((data)>>16)&0xff), \
-		(*((buf)+2) = (fu8_t)((data)>>8)&0xff), \
-		(*((buf)+3) = (fu8_t)(data)&0xff), \
-		4)
-#define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \
-		(((*((buf)+1))<<16)&0x00ff0000) + \
-		(((*((buf)+2))<< 8)&0x0000ff00) + \
-		(((*((buf)+3)    )&0x000000ff)))
-
-/* Little-endian versions (damn ICQ) */
-#define aimutil_putle8(buf, data) ( \
-		(*(buf) = (fu8_t)(data) & 0xff), \
-		1)
-#define aimutil_getle8(buf) ( \
-		(*(buf)) & 0xff \
-		)
-#define aimutil_putle16(buf, data) ( \
-		(*((buf)+0) = (fu8_t)((data) >> 0) & 0xff),  \
-		(*((buf)+1) = (fu8_t)((data) >> 8) & 0xff), \
-		2)
-#define aimutil_getle16(buf) ( \
-		(((*((buf)+0)) << 0) & 0x00ff) + \
-		(((*((buf)+1)) << 8) & 0xff00) \
-		)
-#define aimutil_putle32(buf, data) ( \
-		(*((buf)+0) = (fu8_t)((data) >>  0) & 0xff), \
-		(*((buf)+1) = (fu8_t)((data) >>  8) & 0xff), \
-		(*((buf)+2) = (fu8_t)((data) >> 16) & 0xff), \
-		(*((buf)+3) = (fu8_t)((data) >> 24) & 0xff), \
-		4)
-#define aimutil_getle32(buf) ( \
-		(((*((buf)+0)) <<  0) & 0x000000ff) + \
-		(((*((buf)+1)) <<  8) & 0x0000ff00) + \
-		(((*((buf)+2)) << 16) & 0x00ff0000) + \
-		(((*((buf)+3)) << 24) & 0xff000000))
-
-
-faim_export int aimutil_putstr(char *, const char *, int);
-faim_export fu16_t aimutil_iconsum(const fu8_t *buf, int buflen);
-faim_export int aim_util_getlocalip(fu8_t *ip);
-faim_export int aimutil_tokslen(char *toSearch, int theindex, char dl);
-faim_export int aimutil_itemcnt(char *toSearch, char dl);
-faim_export char *aimutil_itemindex(char *toSearch, int theindex, char dl);
-
-faim_export int aim_snlen(const char *sn);
-faim_export int aim_sncmp(const char *sn1, const char *sn2);
-
-#include <aim_internal.h>
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __AIM_H__ */
Index: bfaim/aim_cbtypes.h
===================================================================
--- libfaim/aim_cbtypes.h	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,310 +1,0 @@
-/*
- * AIM Callback Types
- *
- */
-#ifndef __AIM_CBTYPES_H__
-#define __AIM_CBTYPES_H__
-
-/*
- * SNAC Families.
- */
-#define AIM_CB_FAM_ACK 0x0000
-#define AIM_CB_FAM_GEN 0x0001
-#define AIM_CB_FAM_LOC 0x0002
-#define AIM_CB_FAM_BUD 0x0003
-#define AIM_CB_FAM_MSG 0x0004
-#define AIM_CB_FAM_ADS 0x0005
-#define AIM_CB_FAM_INV 0x0006
-#define AIM_CB_FAM_ADM 0x0007
-#define AIM_CB_FAM_POP 0x0008
-#define AIM_CB_FAM_BOS 0x0009
-#define AIM_CB_FAM_LOK 0x000a
-#define AIM_CB_FAM_STS 0x000b
-#define AIM_CB_FAM_TRN 0x000c
-#define AIM_CB_FAM_CTN 0x000d /* ChatNav */
-#define AIM_CB_FAM_CHT 0x000e /* Chat */
-#define AIM_CB_FAM_SCH 0x000f /* "New" search */
-#define AIM_CB_FAM_ICO 0x0010 /* Used for uploading buddy icons */
-#define AIM_CB_FAM_SSI 0x0013 /* Server stored information */
-#define AIM_CB_FAM_ICQ 0x0015
-#define AIM_CB_FAM_ATH 0x0017
-#define AIM_CB_FAM_EML 0x0018
-#define AIM_CB_FAM_OFT 0xfffe /* OFT/Rvous */
-#define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */
-
-/*
- * SNAC Family: Ack.
- * 
- * Not really a family, but treating it as one really
- * helps it fit into the libfaim callback structure better.
- *
- */
-#define AIM_CB_ACK_ACK 0x0001
-
-/*
- * SNAC Family: General.
- */ 
-#define AIM_CB_GEN_ERROR 0x0001
-#define AIM_CB_GEN_CLIENTREADY 0x0002
-#define AIM_CB_GEN_SERVERREADY 0x0003
-#define AIM_CB_GEN_SERVICEREQ 0x0004
-#define AIM_CB_GEN_REDIRECT 0x0005
-#define AIM_CB_GEN_RATEINFOREQ 0x0006
-#define AIM_CB_GEN_RATEINFO 0x0007
-#define AIM_CB_GEN_RATEINFOACK 0x0008
-#define AIM_CB_GEN_RATECHANGE 0x000a
-#define AIM_CB_GEN_SERVERPAUSE 0x000b
-#define AIM_CB_GEN_SERVERRESUME 0x000d
-#define AIM_CB_GEN_REQSELFINFO 0x000e
-#define AIM_CB_GEN_SELFINFO 0x000f
-#define AIM_CB_GEN_EVIL 0x0010
-#define AIM_CB_GEN_SETIDLE 0x0011
-#define AIM_CB_GEN_MIGRATIONREQ 0x0012
-#define AIM_CB_GEN_MOTD 0x0013
-#define AIM_CB_GEN_SETPRIVFLAGS 0x0014
-#define AIM_CB_GEN_WELLKNOWNURL 0x0015
-#define AIM_CB_GEN_NOP 0x0016
-#define AIM_CB_GEN_DEFAULT 0xffff
-
-/*
- * SNAC Family: Location Services.
- */ 
-#define AIM_CB_LOC_ERROR 0x0001
-#define AIM_CB_LOC_REQRIGHTS 0x0002
-#define AIM_CB_LOC_RIGHTSINFO 0x0003
-#define AIM_CB_LOC_SETUSERINFO 0x0004
-#define AIM_CB_LOC_REQUSERINFO 0x0005
-#define AIM_CB_LOC_USERINFO 0x0006
-#define AIM_CB_LOC_WATCHERSUBREQ 0x0007
-#define AIM_CB_LOC_WATCHERNOT 0x0008
-#define AIM_CB_LOC_DEFAULT 0xffff
-
-/*
- * SNAC Family: Buddy List Management Services.
- */ 
-#define AIM_CB_BUD_ERROR 0x0001
-#define AIM_CB_BUD_REQRIGHTS 0x0002
-#define AIM_CB_BUD_RIGHTSINFO 0x0003
-#define AIM_CB_BUD_ADDBUDDY 0x0004
-#define AIM_CB_BUD_REMBUDDY 0x0005
-#define AIM_CB_BUD_REJECT 0x000a
-#define AIM_CB_BUD_ONCOMING 0x000b
-#define AIM_CB_BUD_OFFGOING 0x000c
-#define AIM_CB_BUD_DEFAULT 0xffff
-
-/*
- * SNAC Family: Messeging Services.
- */ 
-#define AIM_CB_MSG_ERROR 0x0001
-#define AIM_CB_MSG_PARAMINFO 0x0005
-#define AIM_CB_MSG_INCOMING 0x0007
-#define AIM_CB_MSG_EVIL 0x0009
-#define AIM_CB_MSG_MISSEDCALL 0x000a
-#define AIM_CB_MSG_CLIENTAUTORESP 0x000b
-#define AIM_CB_MSG_ACK 0x000c
-#define AIM_CB_MSG_MTN 0x0014
-#define AIM_CB_MSG_DEFAULT 0xffff
-
-/*
- * SNAC Family: Advertisement Services
- */ 
-#define AIM_CB_ADS_ERROR 0x0001
-#define AIM_CB_ADS_DEFAULT 0xffff
-
-/*
- * SNAC Family: Invitation Services.
- */ 
-#define AIM_CB_INV_ERROR 0x0001
-#define AIM_CB_INV_DEFAULT 0xffff
-
-/*
- * SNAC Family: Administrative Services.
- */ 
-#define AIM_CB_ADM_ERROR 0x0001
-#define AIM_CB_ADM_INFOCHANGE_REPLY 0x0005
-#define AIM_CB_ADM_DEFAULT 0xffff
-
-/*
- * SNAC Family: Popup Messages
- */ 
-#define AIM_CB_POP_ERROR 0x0001
-#define AIM_CB_POP_DEFAULT 0xffff
-
-/*
- * SNAC Family: Misc BOS Services.
- */ 
-#define AIM_CB_BOS_ERROR 0x0001
-#define AIM_CB_BOS_RIGHTSQUERY 0x0002
-#define AIM_CB_BOS_RIGHTS 0x0003
-#define AIM_CB_BOS_DEFAULT 0xffff
-
-/*
- * SNAC Family: User Lookup Services
- */ 
-#define AIM_CB_LOK_ERROR 0x0001
-#define AIM_CB_LOK_DEFAULT 0xffff
-
-/*
- * SNAC Family: User Status Services
- */ 
-#define AIM_CB_STS_ERROR 0x0001
-#define AIM_CB_STS_SETREPORTINTERVAL 0x0002
-#define AIM_CB_STS_REPORTACK 0x0004
-#define AIM_CB_STS_DEFAULT 0xffff
-
-/*
- * SNAC Family: Translation Services
- */ 
-#define AIM_CB_TRN_ERROR 0x0001
-#define AIM_CB_TRN_DEFAULT 0xffff
-
-/*
- * SNAC Family: Chat Navigation Services
- */ 
-#define AIM_CB_CTN_ERROR 0x0001
-#define AIM_CB_CTN_CREATE 0x0008
-#define AIM_CB_CTN_INFO 0x0009
-#define AIM_CB_CTN_DEFAULT 0xffff
-
-/*
- * SNAC Family: Chat Services
- */ 
-#define AIM_CB_CHT_ERROR 0x0001
-#define AIM_CB_CHT_ROOMINFOUPDATE 0x0002
-#define AIM_CB_CHT_USERJOIN 0x0003
-#define AIM_CB_CHT_USERLEAVE 0x0004
-#define AIM_CB_CHT_OUTGOINGMSG 0x0005
-#define AIM_CB_CHT_INCOMINGMSG 0x0006
-#define AIM_CB_CHT_DEFAULT 0xffff
-
-/*
- * SNAC Family: "New" Search
- */ 
-#define AIM_CB_SCH_ERROR 0x0001
-#define AIM_CB_SCH_SEARCH 0x0002
-#define AIM_CB_SCH_RESULTS 0x0003
-
-/*
- * SNAC Family: Buddy icons
- */ 
-#define AIM_CB_ICO_ERROR 0x0001
-#define AIM_CB_ICO_REQUEST 0x0004
-#define AIM_CB_ICO_RESPONSE 0x0005
-
-/*
- * SNAC Family: ICQ
- *
- * Most of these are actually special.
- */ 
-#define AIM_CB_ICQ_ERROR 0x0001
-#define AIM_CB_ICQ_OFFLINEMSG 0x00f0
-#define AIM_CB_ICQ_OFFLINEMSGCOMPLETE 0x00f1
-#define AIM_CB_ICQ_INFO 0x00f2
-#define AIM_CB_ICQ_ALIAS 0x00f3
-#define AIM_CB_ICQ_DEFAULT 0xffff
-
-/*
- * SNAC Family: Server-Stored Buddy Lists
- */
-#define AIM_CB_SSI_ERROR 0x0001
-#define AIM_CB_SSI_REQRIGHTS 0x0002
-#define AIM_CB_SSI_RIGHTSINFO 0x0003
-#define AIM_CB_SSI_REQDATA 0x0004
-#define AIM_CB_SSI_REQIFCHANGED 0x0005
-#define AIM_CB_SSI_LIST 0x0006
-#define AIM_CB_SSI_ACTIVATE 0x0007
-#define AIM_CB_SSI_ADD 0x0008
-#define AIM_CB_SSI_MOD 0x0009
-#define AIM_CB_SSI_DEL 0x000A
-#define AIM_CB_SSI_SRVACK 0x000E
-#define AIM_CB_SSI_NOLIST 0x000F
-#define AIM_CB_SSI_EDITSTART 0x0011
-#define AIM_CB_SSI_EDITSTOP 0x0012
-#define AIM_CB_SSI_SENDAUTH 0x0014
-#define AIM_CB_SSI_RECVAUTH 0x0015
-#define AIM_CB_SSI_SENDAUTHREQ 0x0018
-#define AIM_CB_SSI_RECVAUTHREQ 0x0019
-#define AIM_CB_SSI_SENDAUTHREP 0x001a
-#define AIM_CB_SSI_RECVAUTHREP 0x001b
-#define AIM_CB_SSI_ADDED 0x001c
-
-/*
- * SNAC Family: Authorizer
- *
- * Used only in protocol versions three and above.
- *
- */
-#define AIM_CB_ATH_ERROR 0x0001
-#define AIM_CB_ATH_LOGINREQEST 0x0002
-#define AIM_CB_ATH_LOGINRESPONSE 0x0003
-#define AIM_CB_ATH_AUTHREQ 0x0006
-#define AIM_CB_ATH_AUTHRESPONSE 0x0007
-
-/*
- * SNAC Family: Email
- *
- * Used for getting information on the email address
- * associated with your screen name.
- *
- */
-#define AIM_CB_EML_ERROR 0x0001
-#define AIM_CB_EML_SENDCOOKIES 0x0006
-#define AIM_CB_EML_MAILSTATUS 0x0007
-#define AIM_CB_EML_INIT 0x0016
-
-/*
- * OFT Services
- *
- * For all of the above #defines, the number is the subtype 
- * of the SNAC.  For OFT #defines, the number is the 
- * "hdrtype" which comes after the magic string and OFT 
- * packet length.
- *
- * I'm pretty sure the ODC ones are arbitrary right now, 
- * that should be changed.
- */
-#define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001	/* connect request -- actually an OSCAR CAP */
-#define AIM_CB_OFT_DIRECTIMINCOMING 0x0002
-#define AIM_CB_OFT_DIRECTIMDISCONNECT 0x0003
-#define AIM_CB_OFT_DIRECTIMTYPING 0x0004
-#define AIM_CB_OFT_DIRECTIM_ESTABLISHED 0x0005
-
-#define AIM_CB_OFT_PROMPT 0x0101		/* "I am going to send you this file, is that ok?" */
-#define AIM_CB_OFT_RESUMESOMETHING 0x0106	/* I really don't know */
-#define AIM_CB_OFT_ACK 0x0202			/* "Yes, it is ok for you to send me that file" */
-#define AIM_CB_OFT_DONE 0x0204			/* "I received that file with no problems, thanks a bunch" */
-#define AIM_CB_OFT_RESUME 0x0205		/* Resume transferring, sent by whoever paused? */
-#define AIM_CB_OFT_RESUMEACK 0x0207		/* Not really sure */
-
-#define AIM_CB_OFT_GETFILE_REQUESTLISTING 0x1108 /* "I have a listing.txt file, do you want it?" */
-#define AIM_CB_OFT_GETFILE_RECEIVELISTING 0x1209 /* "Yes, please send me your listing.txt file" */
-#define AIM_CB_OFT_GETFILE_RECEIVEDLISTING 0x120a /* received corrupt listing.txt file? */ /* I'm just guessing about this one... */
-#define AIM_CB_OFT_GETFILE_ACKLISTING 0x120b	/* "I received the listing.txt file successfully" */
-#define AIM_CB_OFT_GETFILE_REQUESTFILE 0x120c	/* "Please send me this file" */
-
-#define AIM_CB_OFT_ESTABLISHED 0xFFFF		/* connection to buddy initiated */
-
-/*
- * SNAC Family: Internal Messages
- *
- * This isn't truely a SNAC family either, but using
- * these, we can integrated non-SNAC services into
- * the SNAC-centered libfaim callback structure.
- *
- */ 
-#define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001
-#define AIM_CB_SPECIAL_AUTHOTHER 0x0002
-#define AIM_CB_SPECIAL_CONNERR 0x0003
-#define AIM_CB_SPECIAL_CONNCOMPLETE 0x0004
-#define AIM_CB_SPECIAL_FLAPVER 0x0005
-#define AIM_CB_SPECIAL_CONNINITDONE 0x0006
-#define AIM_CB_SPECIAL_IMAGETRANSFER 0x0007
-#define AIM_CB_SPECIAL_MSGTIMEOUT 0x0008
-#define AIM_CB_SPECIAL_CONNDEAD 0x0009
-#define AIM_CB_SPECIAL_UNKNOWN 0xffff
-#define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN
-
-/* SNAC flags */
-#define AIM_SNACFLAGS_DESTRUCTOR 0x0001
-
-#endif/*__AIM_CBTYPES_H__ */
Index: bfaim/aim_internal.h
===================================================================
--- libfaim/aim_internal.h	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,226 +1,0 @@
-/*
- * aim_internal.h -- prototypes/structs for the guts of libfaim
- *
- */
-
-#ifdef FAIM_INTERNAL
-#ifndef __AIM_INTERNAL_H__
-#define __AIM_INTERNAL_H__ 1
-
-typedef struct {
-	fu16_t family;
-	fu16_t subtype;
-	fu16_t flags;
-	fu32_t id;
-} aim_modsnac_t;
-
-#define AIM_MODULENAME_MAXLEN 16
-#define AIM_MODFLAG_MULTIFAMILY 0x0001
-typedef struct aim_module_s {
-	fu16_t family;
-	fu16_t version;
-	fu16_t toolid;
-	fu16_t toolversion;
-	fu16_t flags;
-	char name[AIM_MODULENAME_MAXLEN+1];
-	int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs);
-
-	void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod);
-	void *priv;
-	struct aim_module_s *next;
-} aim_module_t;
-
-faim_internal int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, aim_module_t *));
-faim_internal void aim__shutdownmodules(aim_session_t *sess);
-faim_internal aim_module_t *aim__findmodulebygroup(aim_session_t *sess, fu16_t group);
-faim_internal aim_module_t *aim__findmodule(aim_session_t *sess, const char *name);
-
-faim_internal int admin_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int bos_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int search_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int stats_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int auth_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int misc_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int chatnav_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int service_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int odir_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int bart_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int icq_modfirst(aim_session_t *sess, aim_module_t *mod);
-faim_internal int email_modfirst(aim_session_t *sess, aim_module_t *mod);
-
-faim_internal int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype);
-faim_internal int aim_genericreq_n_snacid(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype);
-faim_internal int aim_genericreq_l(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu32_t *);
-faim_internal int aim_genericreq_s(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu16_t *);
-
-#define AIMBS_CURPOSPAIR(x) ((x)->data + (x)->offset), ((x)->len - (x)->offset)
-
-/* bstream.c */
-faim_internal int aim_bstream_init(aim_bstream_t *bs, fu8_t *data, int len);
-faim_internal int aim_bstream_empty(aim_bstream_t *bs);
-faim_internal int aim_bstream_curpos(aim_bstream_t *bs);
-faim_internal int aim_bstream_setpos(aim_bstream_t *bs, int off);
-faim_internal void aim_bstream_rewind(aim_bstream_t *bs);
-faim_internal int aim_bstream_advance(aim_bstream_t *bs, int n);
-faim_internal fu8_t aimbs_get8(aim_bstream_t *bs);
-faim_internal fu16_t aimbs_get16(aim_bstream_t *bs);
-faim_internal fu32_t aimbs_get32(aim_bstream_t *bs);
-faim_internal fu8_t aimbs_getle8(aim_bstream_t *bs);
-faim_internal fu16_t aimbs_getle16(aim_bstream_t *bs);
-faim_internal fu32_t aimbs_getle32(aim_bstream_t *bs);
-faim_internal int aimbs_put8(aim_bstream_t *bs, fu8_t v);
-faim_internal int aimbs_put16(aim_bstream_t *bs, fu16_t v);
-faim_internal int aimbs_put32(aim_bstream_t *bs, fu32_t v);
-faim_internal int aimbs_putle8(aim_bstream_t *bs, fu8_t v);
-faim_internal int aimbs_putle16(aim_bstream_t *bs, fu16_t v);
-faim_internal int aimbs_putle32(aim_bstream_t *bs, fu32_t v);
-faim_internal int aimbs_getrawbuf(aim_bstream_t *bs, fu8_t *buf, int len);
-faim_internal fu8_t *aimbs_getraw(aim_bstream_t *bs, int len);
-faim_internal char *aimbs_getstr(aim_bstream_t *bs, int len);
-faim_internal int aimbs_putraw(aim_bstream_t *bs, const fu8_t *v, int len);
-faim_internal int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len);
-
-/* conn.c */
-faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src);
-
-/* ft.c */
-faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr);
-
-/* rxhandlers.c */
-faim_internal aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type);
-faim_internal int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type, aim_frame_t *ptr);
-faim_internal int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...);
-faim_internal void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src);
-
-/* rxqueue.c */
-faim_internal int aim_recv(int fd, void *buf, size_t count);
-faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count);
-faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn);
-faim_internal void aim_frame_destroy(aim_frame_t *);
-
-/* txqueue.c */
-faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen);
-faim_internal int aim_tx_enqueue(aim_session_t *, aim_frame_t *);
-faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *);
-faim_internal int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *cur);
-faim_internal void aim_tx_cleanqueue(aim_session_t *, aim_conn_t *);
-
-/* XXX - What is this?   faim_internal int aim_tx_printqueue(aim_session_t *); */
-
-/*
- * Generic SNAC structure.  Rarely if ever used.
- */
-typedef struct aim_snac_s {
-	aim_snacid_t id;
-	fu16_t family;
-	fu16_t type;
-	fu16_t flags;
-	void *data;
-	time_t issuetime;
-	struct aim_snac_s *next;
-} aim_snac_t;
-
-/* snac.c */
-faim_internal void aim_initsnachash(aim_session_t *sess);
-faim_internal aim_snacid_t aim_newsnac(aim_session_t *, aim_snac_t *newsnac);
-faim_internal aim_snacid_t aim_cachesnac(aim_session_t *sess, const fu16_t family, const fu16_t type, const fu16_t flags, const void *data, const int datalen);
-faim_internal aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id);
-faim_internal int aim_putsnac(aim_bstream_t *, fu16_t family, fu16_t type, fu16_t flags, aim_snacid_t id);
-
-/* Stored in ->priv of the service request SNAC for chats. */
-struct chatsnacinfo {
-	fu16_t exchange;
-	char name[128];
-	fu16_t instance;
-};
-
-/* 
- * In SNACland, the terms 'family' and 'group' are synonymous -- the former
- * is my term, the latter is AOL's.
- */
-struct snacgroup {
-	fu16_t group;
-	struct snacgroup *next;
-};
-
-#ifdef FAIM_NEED_CONN_INTERNAL
-struct snacpair {
-	fu16_t group;
-	fu16_t subtype;
-	struct snacpair *next;
-};
-
-struct rateclass {
-	fu16_t classid;
-	fu32_t windowsize;
-	fu32_t clear;
-	fu32_t alert;
-	fu32_t limit;
-	fu32_t disconnect;
-	fu32_t current;
-	fu32_t max;
-	fu8_t unknown[5]; /* only present in versions >= 3 */
-	struct snacpair *members;
-	struct rateclass *next;
-};
-#endif /* FAIM_NEED_CONN_INTERNAL */
-
-/*
- * This is inside every connection.  But it is a void * to anything
- * outside of libfaim.  It should remain that way.  It's called data
- * abstraction.  Maybe you've heard of it.  (Probably not if you're a 
- * libfaim user.)
- * 
- */
-typedef struct aim_conn_inside_s {
-	struct snacgroup *groups;
-	struct rateclass *rates;
-} aim_conn_inside_t;
-
-faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group);
-
-faim_internal int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
-faim_internal aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, fu8_t *cookie, int type);
-faim_internal aim_msgcookie_t *aim_mkcookie(fu8_t *, int, void *);
-faim_internal aim_msgcookie_t *aim_checkcookie(aim_session_t *, const unsigned char *, const int);
-faim_internal int aim_freecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
-faim_internal int aim_msgcookie_gettype(int reqclass);
-faim_internal int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie);
-
-/* 0x0002 - locate.c */
-faim_internal void aim_locate_requestuserinfo(aim_session_t *sess, const char *sn);
-faim_internal fu32_t aim_locate_getcaps(aim_session_t *sess, aim_bstream_t *bs, int len);
-faim_internal fu32_t aim_locate_getcaps_short(aim_session_t *sess, aim_bstream_t *bs, int len);
-faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps);
-faim_internal void aim_info_free(aim_userinfo_t *);
-faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *);
-faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info);
-
-faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo);
-
-faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn);
-
-/* These are all handled internally now. */
-faim_internal int aim_setversions(aim_session_t *sess, aim_conn_t *conn);
-faim_internal int aim_reqrates(aim_session_t *, aim_conn_t *);
-faim_internal int aim_rates_addparam(aim_session_t *, aim_conn_t *);
-faim_internal int aim_rates_delparam(aim_session_t *, aim_conn_t *);
-
-faim_internal void faimdprintf(aim_session_t *sess, int dlevel, const char *format, ...);
-
-#ifndef FAIM_INTERNAL_INSANE
-#define printf() printf called inside libfaim
-#define sprintf() unbounded sprintf used inside libfaim
-#endif
-
-#endif /* __AIM_INTERNAL_H__ */
-#endif /* FAIM_INTERNAL */
Index: bfaim/auth.c
===================================================================
--- libfaim/auth.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,558 +1,0 @@
-/*
- * Family 0x0017 - Authentication.
- *
- * Deals with the authorizer for SNAC-based login, and also old-style 
- * non-SNAC login.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-#include "md5.h"
-
-#include <ctype.h>
-
-/**
- * Encode a password using old XOR method
- *
- * This takes a const pointer to a (null terminated) string
- * containing the unencoded password.  It also gets passed
- * an already allocated buffer to store the encoded password.
- * This buffer should be the exact length of the password without
- * the null.  The encoded password buffer /is not %NULL terminated/.
- *
- * The encoding_table seems to be a fixed set of values.  We'll
- * hope it doesn't change over time!  
- *
- * This is only used for the XOR method, not the better MD5 method.
- *
- * @param password Incoming password.
- * @param encoded Buffer to put encoded password.
- */
-static int aim_encode_password(const char *password, fu8_t *encoded)
-{
-	fu8_t encoding_table[] = {
-#if 0 /* old v1 table */
-		0xf3, 0xb3, 0x6c, 0x99,
-		0x95, 0x3f, 0xac, 0xb6,
-		0xc5, 0xfa, 0x6b, 0x63,
-		0x69, 0x6c, 0xc3, 0x9f
-#else /* v2.1 table, also works for ICQ */
-		0xf3, 0x26, 0x81, 0xc4,
-		0x39, 0x86, 0xdb, 0x92,
-		0x71, 0xa3, 0xb9, 0xe6,
-		0x53, 0x7a, 0x95, 0x7c
-#endif
-	};
-	int i;
-
-	for (i = 0; i < strlen(password); i++)
-		encoded[i] = (password[i] ^ encoding_table[i]);
-
-	return 0;
-}
-
-#ifdef USE_OLD_MD5
-static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
-{
-	md5_state_t state;
-
-	md5_init(&state);	
-	md5_append(&state, (const md5_byte_t *)key, strlen(key));
-	md5_append(&state, (const md5_byte_t *)password, strlen(password));
-	md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
-	md5_finish(&state, (md5_byte_t *)digest);
-
-	return 0;
-}
-#else
-static int aim_encode_password_md5(const char *password, const char *key, fu8_t *digest)
-{
-	md5_state_t state;
-	fu8_t passdigest[16];
-
-	md5_init(&state);
-	md5_append(&state, (const md5_byte_t *)password, strlen(password));
-	md5_finish(&state, (md5_byte_t *)&passdigest);
-
-	md5_init(&state);	
-	md5_append(&state, (const md5_byte_t *)key, strlen(key));
-	md5_append(&state, (const md5_byte_t *)&passdigest, 16);
-	md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
-	md5_finish(&state, (md5_byte_t *)digest);
-
-	return 0;
-}
-#endif
-
-/*
- * The FLAP version is sent by itself at the beginning of authorization 
- * connections.  The FLAP version is also sent before the cookie when connecting 
- * for other services (BOS, chatnav, chat, etc.).
- */
-faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4)))
-		return -ENOMEM;
-
-	aimbs_put32(&fr->data, 0x00000001);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * This just pushes the passed cookie onto the passed connection, without
- * the SNAC header or any of that.
- *
- * Very commonly used, as every connection except auth will require this to
- * be the first thing you send.
- *
- */
-faim_export int aim_sendcookie(aim_session_t *sess, aim_conn_t *conn, const fu16_t length, const fu8_t *chipsahoy)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4+2+2+length)))
-		return -ENOMEM;
-
-	aimbs_put32(&fr->data, 0x00000001);
-	aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Part two of the ICQ hack.  Note the ignoring of the key.
- */
-static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, struct client_info_s *ci)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-	int passwdlen;
-	fu8_t *password_encoded;
-
-	passwdlen = strlen(password);
-	if (!(password_encoded = (char *)malloc(passwdlen+1)))
-		return -ENOMEM;
-	if (passwdlen > MAXICQPASSLEN)
-		passwdlen = MAXICQPASSLEN;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 1152))) {
-		free(password_encoded);
-		return -ENOMEM;
-	}
-
-	aim_encode_password(password, password_encoded);
-
-	aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */
-	aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
-	aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded);
-
-	if (ci->clientstring)
-		aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib); /* distribution chan */
-	aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
-	aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
-
-	aim_tlvlist_write(&fr->data, &tl);
-
-	free(password_encoded);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0002
- *
- * This is the initial login request packet.
- *
- * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
- * then the client information you send here must exactly match the
- * executable that you're pulling the data from.
- *
- * Java AIM 1.1.19:
- *   clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
- *   clientid = 0x0001
- *   major  = 0x0001
- *   minor  = 0x0001
- *   point = (not sent)
- *   build  = 0x0013
- *   unknown= (not sent)
- *   
- * AIM for Linux 1.1.112:
- *   clientstring = "AOL Instant Messenger (SM)"
- *   clientid = 0x1d09
- *   major  = 0x0001
- *   minor  = 0x0001
- *   point = 0x0001
- *   build  = 0x0070
- *   unknown= 0x0000008b
- *   serverstore = 0x01
- *
- */
-faim_export int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, struct client_info_s *ci, const char *key)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-	fu8_t digest[16];
-	aim_snacid_t snacid;
-
-	if (!ci || !sn || !password)
-		return -EINVAL;
-
-	/* If we're signing on an ICQ account then use the older, XOR login method */
-	if (isdigit(sn[0]))
-		return goddamnicq2(sess, conn, sn, password, ci);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0017, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid);
-
-	aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
-
-	aim_encode_password_md5(password, key, digest);
-	aim_tlvlist_add_raw(&tl, 0x0025, 16, digest);
-
-#ifndef USE_OLD_MD5
-	aim_tlvlist_add_noval(&tl, 0x004c);
-#endif
-
-	if (ci->clientstring)
-		aim_tlvlist_add_raw(&tl, 0x0003, strlen(ci->clientstring), ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (fu16_t)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (fu16_t)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (fu16_t)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (fu16_t)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (fu16_t)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (fu32_t)ci->distrib);
-	aim_tlvlist_add_raw(&tl, 0x000f, strlen(ci->lang), ci->lang);
-	aim_tlvlist_add_raw(&tl, 0x000e, strlen(ci->country), ci->country);
-
-#ifndef NOSSI
-	/*
-	 * If set, old-fashioned buddy lists will not work. You will need
-	 * to use SSI.
-	 */
-	aim_tlvlist_add_8(&tl, 0x004a, 0x01);
-#endif
-
-	aim_tlvlist_write(&fr->data, &tl);
-
-	aim_tlvlist_free(&tl);
-	
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * This is sent back as a general response to the login command.
- * It can be either an error or a success, depending on the
- * precense of certain TLVs.  
- *
- * The client should check the value passed as errorcode. If
- * its nonzero, there was an error.
- */
-static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_tlvlist_t *tlvlist;
-	aim_rxcallback_t userfunc;
-	struct aim_authresp_info *info;
-	int ret = 0;
-
-	info = (struct aim_authresp_info *)malloc(sizeof(struct aim_authresp_info));
-	memset(info, 0, sizeof(struct aim_authresp_info));
-
-	/*
-	 * Read block of TLVs.  All further data is derived
-	 * from what is parsed here.
-	 */
-	tlvlist = aim_tlvlist_read(bs);
-
-	/*
-	 * No matter what, we should have a screen name.
-	 */
-	memset(sess->sn, 0, sizeof(sess->sn));
-	if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
-		info->sn = aim_tlv_getstr(tlvlist, 0x0001, 1);
-		strncpy(sess->sn, info->sn, sizeof(sess->sn));
-	}
-
-	/*
-	 * Check for an error code.  If so, we should also
-	 * have an error url.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0008, 1)) 
-		info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
-		info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);
-
-	/*
-	 * BOS server address.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
-		info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);
-
-	/*
-	 * Authorization cookie.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-		aim_tlv_t *tmptlv;
-
-		tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
-
-		info->cookielen = tmptlv->length;
-		info->cookie = tmptlv->value;
-	}
-
-	/*
-	 * The email address attached to this account
-	 *   Not available for ICQ or @mac.com logins.
-	 *   If you receive this TLV, then you are allowed to use 
-	 *   family 0x0018 to check the status of your email.
-	 * XXX - Not really true!
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
-		info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);
-
-	/*
-	 * The registration status.  (Not real sure what it means.)
-	 *   Not available for ICQ or @mac.com logins.
-	 *
-	 *   1 = No disclosure
-	 *   2 = Limited disclosure
-	 *   3 = Full disclosure
-	 *
-	 * This has to do with whether your email address is available
-	 * to other users or not.  AFAIK, this feature is no longer used.
-	 *
-	 * Means you can use the admin family? (0x0007)
-	 *
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
-		info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);
-
-	if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
-		info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
-		info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
-		info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
-		info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0048, 1))
-		; /* beta serial */
-
-	if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
-		info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
-		info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
-		info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
-		info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);
-	if (aim_tlv_gettlv(tlvlist, 0x0049, 1))
-		; /* lastest release serial */
-
-	/*
-	 * URL to change password.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
-		info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);
-
-	/*
-	 * Unknown.  Seen on an @mac.com screen name with value of 0x003f
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0055, 1))
-		;
-
-	sess->authinfo = info;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003)))
-		ret = userfunc(sess, rx, info);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0007 (kind of) - Send a fake type 0x0007 SNAC to the client
- *
- * This is a bit confusing.
- *
- * Normal SNAC login goes like this:
- *   - connect
- *   - server sends flap version
- *   - client sends flap version
- *   - client sends screen name (17/6)
- *   - server sends hash key (17/7)
- *   - client sends auth request (17/2 -- aim_send_login)
- *   - server yells
- *
- * XOR login (for ICQ) goes like this:
- *   - connect
- *   - server sends flap version
- *   - client sends auth request which contains flap version (aim_send_login)
- *   - server yells
- *
- * For the client API, we make them implement the most complicated version,
- * and for the simpler version, we fake it and make it look like the more
- * complicated process.
- *
- * This is done by giving the client a faked key, just so we can convince
- * them to call aim_send_login right away, which will detect the session
- * flag that says this is XOR login and ignore the key, sending an ICQ
- * login request instead of the normal SNAC one.
- *
- * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
- *
- * XXX This may cause problems if the client relies on callbacks only
- * being called from the context of aim_rxdispatch()...
- *
- */
-static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t fr;
-	aim_rxcallback_t userfunc;
-	
-	fr.conn = conn;
-	
-	if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007)))
-		userfunc(sess, &fr, "");
-
-	return 0;
-}
-
-/*
- * Subtype 0x0006
- *
- * In AIM 3.5 protocol, the first stage of login is to request login from the 
- * Authorizer, passing it the screen name for verification.  If the name is 
- * invalid, a 0017/0003 is spit back, with the standard error contents.  If 
- * valid, a 0017/0007 comes back, which is the signal to send it the main 
- * login command (0017/0002). 
- *
- */
-faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	
-	if (!sess || !conn || !sn)
-		return -EINVAL;
-
-	if (isdigit(sn[0]))
-		return goddamnicq(sess, conn, sn);
-
-	aim_sendflapver(sess, conn);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn) /*+8*/ )))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
-
-	aim_tlvlist_add_raw(&tl, 0x0001, strlen(sn), sn);
-/*	aim_tlvlist_add_noval(&tl, 0x004b);
-	aim_tlvlist_add_noval(&tl, 0x005a); */
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0007
- *
- * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
- * by only its length in a two byte word.
- *
- * Calls the client, which should then use the value to call aim_send_login.
- *
- */
-static int keyparse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int keylen, ret = 1;
-	aim_rxcallback_t userfunc;
-	char *keystr;
-
-	keylen = aimbs_get16(bs);
-	keystr = aimbs_getstr(bs, keylen);
-
-	/* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register 
-	 * for the netscape network.  This SNAC had a type 0x0058 TLV with length 10.  
-	 * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, keystr);
-
-	free(keystr); 
-
-	return ret;
-}
-
-static void auth_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	if (sess->authinfo) {
-		free(sess->authinfo->sn);
-		free(sess->authinfo->bosip);
-		free(sess->authinfo->errorurl);
-		free(sess->authinfo->email);
-		free(sess->authinfo->chpassurl);
-		free(sess->authinfo->latestrelease.name);
-		free(sess->authinfo->latestrelease.url);
-		free(sess->authinfo->latestrelease.info);
-		free(sess->authinfo->latestbeta.name);
-		free(sess->authinfo->latestbeta.url);
-		free(sess->authinfo->latestbeta.info);
-		free(sess->authinfo);
-	}
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return parse(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0007)
-		return keyparse(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int auth_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0017;
-	mod->version = 0x0000;
-	mod->flags = 0;
-	strncpy(mod->name, "auth", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = auth_shutdown;
-
-	return 0;
-}
Index: bfaim/bart.c
===================================================================
--- libfaim/bart.c	(revision 07ab1cb58191016aa991b7765fc82ce89bd078c3)
+++ 	(revision )
@@ -1,165 +1,0 @@
-/*
- * Family 0x0010 - Server stored buddy art
- *
- * Used for storing and retrieving your cute little buddy icon 
- * from the AIM servers.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/**
- * Subtype 0x0002 - Upload your icon.
- *
- * @param sess The oscar session.
- * @param conn The icon connection for this session.
- * @param icon The raw data of the icon image file.
- * @param iconlen Length of the raw data of the icon image file.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_bart_upload(aim_session_t *sess, const fu8_t *icon, fu16_t iconlen)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !icon || !iconlen)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2+iconlen)))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x0010, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0010, 0x0002, 0x0000, snacid);
-
-	/* The reference number for the icon */
-	aimbs_put16(&fr->data, 1);
-
-	/* The icon */
-	aimbs_put16(&fr->data, iconlen);
-	aimbs_putraw(&fr->data, icon, iconlen);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0003 - Acknowledgement for uploading a buddy icon.
- *
- * You get this honky after you upload a buddy icon.
- */
-static int uploadack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t something, somethingelse;
-	fu8_t onemorething;
-
-	something = aimbs_get16(bs);
-	somethingelse = aimbs_get16(bs);
-	onemorething = aimbs_get8(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx);
-
-	return ret;
-}
-
-/**
- * Subtype 0x0004 - Request someone's icon.
- *
- * @param sess The oscar session.
- * @param conn The icon connection for this session.
- * @param sn The screen name of the person who's icon you are requesting.
- * @param iconcsum The MD5 checksum of the icon you are requesting.
- * @param iconcsumlen Length of the MD5 checksum given above.  Should be 10 bytes.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_bart_request(aim_session_t *sess, const char *sn, const fu8_t *iconcsum, fu16_t iconcsumlen)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 4 + 1+iconcsumlen)))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x0010, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0010, 0x0004, 0x0000, snacid);
-
-	/* Screen name */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	/* Some numbers.  You like numbers, right? */
-	aimbs_put8(&fr->data, 0x01);
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put8(&fr->data, 0x01);
-
-	/* Icon string */
-	aimbs_put8(&fr->data, iconcsumlen);
-	aimbs_putraw(&fr->data, iconcsum, iconcsumlen);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0005 - Receive a buddy icon.
- *
- * This is sent in response to a buddy icon request.
- */
-static int parseicon(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	char *sn;
-	fu16_t flags, iconlen;
-	fu8_t number, iconcsumlen, *iconcsum, *icon;
-
-	sn = aimbs_getstr(bs, aimbs_get8(bs));
-	flags = aimbs_get16(bs);
-	number = aimbs_get8(bs);
-	iconcsumlen = aimbs_get8(bs);
-	iconcsum = aimbs_getraw(bs, iconcsumlen);
-	iconlen = aimbs_get16(bs);
-	icon = aimbs_getraw(bs, iconlen);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sn, iconcsum, iconcsumlen, icon, iconlen);
-
-	free(sn);
-	free(iconcsum);
-	free(icon);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return uploadack(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0005)
-		return parseicon(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int bart_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0010;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "bart", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/bos.c
===================================================================
--- libfaim/bos.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,167 +1,0 @@
-/*
- * Family 0x0009 - Basic Oscar Service.
- *
- * The functionality of this family has been replaced by SSI.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-#include <string.h>
-
-/* Subtype 0x0002 - Request BOS rights. */
-faim_export int aim_bos_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x0009, 0x0002);
-}
-
-/* Subtype 0x0003 - BOS Rights. */
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	fu16_t maxpermits = 0, maxdenies = 0;
-	int ret = 0;
-
-	/* 
-	 * TLVs follow 
-	 */
-	tlvlist = aim_tlvlist_read(bs);
-
-	/*
-	 * TLV type 0x0001: Maximum number of buddies on permit list.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-		maxpermits = aim_tlv_get16(tlvlist, 0x0001, 1);
-
-	/*
-	 * TLV type 0x0002: Maximum number of buddies on deny list.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0002, 1)) 
-		maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, maxpermits, maxdenies);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;  
-}
-
-/* 
- * Subtype 0x0004 - Set group permisson mask.
- *
- * Normally 0x1f (all classes).
- *
- * The group permission mask allows you to keep users of a certain
- * class or classes from talking to you.  The mask should be
- * a bitwise OR of all the user classes you want to see you.
- *
- */
-faim_export int aim_bos_setgroupperm(aim_session_t *sess, aim_conn_t *conn, fu32_t mask)
-{
-	return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
-}
-
-/*
- * Stubtypes 0x0005, 0x0006, 0x0007, and 0x0008 - Modify permit/deny lists.
- *
- * Changes your visibility depending on changetype:
- *
- *  AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you
- *  AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list
- *  AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names
- *  AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again
- *
- * list should be a list of 
- * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
- *
- * Equivelents to options in WinAIM:
- *   - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD
- *      with only your name on it.
- *   - Allow only users on my Buddy List: Send an 
- *      AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your
- *      buddy list
- *   - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD 
- *      with everyone listed that you want to see you.
- *   - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only 
- *      yourself in the list
- *   - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with
- *      the list of users to be blocked
- *
- * XXX ye gods.
- */
-faim_export int aim_bos_changevisibility(aim_session_t *sess, aim_conn_t *conn, int changetype, const char *denylist)
-{
-	aim_frame_t *fr;
-	int packlen = 0;
-	fu16_t subtype;
-	char *localcpy = NULL, *tmpptr = NULL;
-	int i;
-	int listcount;
-	aim_snacid_t snacid;
-
-	if (!denylist)
-		return -EINVAL;
-
-	if (changetype == AIM_VISIBILITYCHANGE_PERMITADD)
-		subtype = 0x05;
-	else if (changetype == AIM_VISIBILITYCHANGE_PERMITREMOVE)
-		subtype = 0x06;
-	else if (changetype == AIM_VISIBILITYCHANGE_DENYADD)
-		subtype = 0x07;
-	else if (changetype == AIM_VISIBILITYCHANGE_DENYREMOVE)
-		subtype = 0x08;
-	else
-		return -EINVAL;
-
-	localcpy = strdup(denylist);
-
-	listcount = aimutil_itemcnt(localcpy, '&');
-	packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, packlen))) {
-		free(localcpy);
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0009, subtype, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0009, subtype, 0x00, snacid);
-
-	for (i = 0; (i < (listcount - 1)) && (i < 99); i++) {
-		tmpptr = aimutil_itemindex(localcpy, i, '&');
-
-		aimbs_put8(&fr->data, strlen(tmpptr));
-		aimbs_putraw(&fr->data, tmpptr, strlen(tmpptr));
-
-		free(tmpptr);
-	}
-	free(localcpy);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return rights(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int bos_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0009;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "bos", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/bstream.c
===================================================================
--- libfaim/bstream.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,265 +1,0 @@
-/*
- * bstream.c
- *
- * This file contains all functions needed to use bstreams.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h> 
-
-faim_internal int aim_bstream_init(aim_bstream_t *bs, fu8_t *data, int len)
-{
-	
-	if (!bs)
-		return -1;
-
-	bs->data = data;
-	bs->len = len;
-	bs->offset = 0;
-
-	return 0;
-}
-
-faim_internal int aim_bstream_empty(aim_bstream_t *bs)
-{
-	return bs->len - bs->offset;
-}
-
-faim_internal int aim_bstream_curpos(aim_bstream_t *bs)
-{
-	return bs->offset;
-}
-
-faim_internal int aim_bstream_setpos(aim_bstream_t *bs, int off)
-{
-
-	if (off > bs->len)
-		return -1;
-
-	bs->offset = off;
-
-	return off;
-}
-
-faim_internal void aim_bstream_rewind(aim_bstream_t *bs)
-{
-
-	aim_bstream_setpos(bs, 0);
-
-	return;
-}
-
-faim_internal int aim_bstream_advance(aim_bstream_t *bs, int n)
-{
-
-	if (aim_bstream_empty(bs) < n)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += n;
-
-	return n;
-}
-
-faim_internal fu8_t aimbs_get8(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 1)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset++;
-	
-	return aimutil_get8(bs->data + bs->offset - 1);
-}
-
-faim_internal fu16_t aimbs_get16(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 2)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset += 2;
-	
-	return aimutil_get16(bs->data + bs->offset - 2);
-}
-
-faim_internal fu32_t aimbs_get32(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 4)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset += 4;
-	
-	return aimutil_get32(bs->data + bs->offset - 4);
-}
-
-faim_internal fu8_t aimbs_getle8(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 1)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset++;
-	
-	return aimutil_getle8(bs->data + bs->offset - 1);
-}
-
-faim_internal fu16_t aimbs_getle16(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 2)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset += 2;
-	
-	return aimutil_getle16(bs->data + bs->offset - 2);
-}
-
-faim_internal fu32_t aimbs_getle32(aim_bstream_t *bs)
-{
-	
-	if (aim_bstream_empty(bs) < 4)
-		return 0; /* XXX throw an exception */
-	
-	bs->offset += 4;
-	
-	return aimutil_getle32(bs->data + bs->offset - 4);
-}
-
-faim_internal int aimbs_put8(aim_bstream_t *bs, fu8_t v)
-{
-
-	if (aim_bstream_empty(bs) < 1)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_put8(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-faim_internal int aimbs_put16(aim_bstream_t *bs, fu16_t v)
-{
-
-	if (aim_bstream_empty(bs) < 2)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_put16(bs->data + bs->offset, v);
-
-	return 2;
-}
-
-faim_internal int aimbs_put32(aim_bstream_t *bs, fu32_t v)
-{
-
-	if (aim_bstream_empty(bs) < 4)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_put32(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-faim_internal int aimbs_putle8(aim_bstream_t *bs, fu8_t v)
-{
-
-	if (aim_bstream_empty(bs) < 1)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_putle8(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-faim_internal int aimbs_putle16(aim_bstream_t *bs, fu16_t v)
-{
-
-	if (aim_bstream_empty(bs) < 2)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_putle16(bs->data + bs->offset, v);
-
-	return 2;
-}
-
-faim_internal int aimbs_putle32(aim_bstream_t *bs, fu32_t v)
-{
-
-	if (aim_bstream_empty(bs) < 4)
-		return 0; /* XXX throw an exception */
-
-	bs->offset += aimutil_putle32(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-faim_internal int aimbs_getrawbuf(aim_bstream_t *bs, fu8_t *buf, int len)
-{
-
-	if (aim_bstream_empty(bs) < len)
-		return 0;
-
-	memcpy(buf, bs->data + bs->offset, len);
-	bs->offset += len;
-
-	return len;
-}
-
-faim_internal fu8_t *aimbs_getraw(aim_bstream_t *bs, int len)
-{
-	fu8_t *ob;
-
-	if (!(ob = malloc(len)))
-		return NULL;
-
-	if (aimbs_getrawbuf(bs, ob, len) < len) {
-		free(ob);
-		return NULL;
-	}
-
-	return ob;
-}
-
-faim_internal char *aimbs_getstr(aim_bstream_t *bs, int len)
-{
-	char *ob;
-
-	if (!(ob = malloc(len+1)))
-		return NULL;
-
-	if (aimbs_getrawbuf(bs, ob, len) < len) {
-		free(ob);
-		return NULL;
-	}
-
-	ob[len] = '\0';
-
-	return ob;
-}
-
-faim_internal int aimbs_putraw(aim_bstream_t *bs, const fu8_t *v, int len)
-{
-
-	if (aim_bstream_empty(bs) < len)
-		return 0; /* XXX throw an exception */
-
-	memcpy(bs->data + bs->offset, v, len);
-	bs->offset += len;
-
-	return len;
-}
-
-faim_internal int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len)
-{
-
-	if (aim_bstream_empty(srcbs) < len)
-		return 0; /* XXX throw exception (underrun) */
-
-	if (aim_bstream_empty(bs) < len)
-		return 0; /* XXX throw exception (overflow) */
-
-	memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
-	bs->offset += len;
-	srcbs->offset += len;
-
-	return len;
-}
Index: bfaim/buddylist.c
===================================================================
--- libfaim/buddylist.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,285 +1,0 @@
-/*
- * Family 0x0003 - Old-style Buddylist Management (non-SSI).
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-#include <string.h>
-
-/*
- * Subtype 0x0002 - Request rights.
- *
- * Request Buddy List rights.
- *
- */
-faim_export int aim_buddylist_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x0003, 0x0002);
-}
-
-/*
- * Subtype 0x0003 - Rights.
- *
- */
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	fu16_t maxbuddies = 0, maxwatchers = 0;
-	int ret = 0;
-
-	/* 
-	 * TLVs follow 
-	 */
-	tlvlist = aim_tlvlist_read(bs);
-
-	/*
-	 * TLV type 0x0001: Maximum number of buddies.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-		maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);
-
-	/*
-	 * TLV type 0x0002: Maximum number of watchers.
-	 *
-	 * Watchers are other users who have you on their buddy
-	 * list.  (This is called the "reverse list" by a certain
-	 * other IM protocol.)
-	 * 
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
-		maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);
-
-	/*
-	 * TLV type 0x0003: Unknown.
-	 *
-	 * ICQ only?
-	 */
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, maxbuddies, maxwatchers);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;  
-}
-
-/*
- * Subtype 0x0004 - Add buddy to list.
- *
- * Adds a single buddy to your buddy list after login.
- * XXX This should just be an extension of setbuddylist()
- *
- */
-faim_export int aim_buddylist_addbuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sn || !strlen(sn))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1);
-	aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
-
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0004 - Add multiple buddies to your buddy list.
- *
- * This just builds the "set buddy list" command then queues it.
- *
- * buddy_list = "Screen Name One&ScreenNameTwo&";
- *
- * XXX Clean this up.  
- *
- */
-faim_export int aim_buddylist_set(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int len = 0;
-	char *localcpy = NULL;
-	char *tmpptr = NULL;
-
-	if (!buddy_list || !(localcpy = strdup(buddy_list))) 
-		return -EINVAL;
-
-	for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
-		faimdprintf(sess, 2, "---adding: %s (%d)\n", tmpptr, strlen(tmpptr));
-		len += 1 + strlen(tmpptr);
-		tmpptr = strtok(NULL, "&");
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
-
-	strncpy(localcpy, buddy_list, strlen(buddy_list) + 1);
-
-	for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
-
-		faimdprintf(sess, 2, "---adding: %s (%d)\n", tmpptr, strlen(tmpptr));
-
-		aimbs_put8(&fr->data, strlen(tmpptr));
-		aimbs_putraw(&fr->data, tmpptr, strlen(tmpptr));
-		tmpptr = strtok(NULL, "&");
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	free(localcpy);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0005 - Remove buddy from list.
- *
- * XXX generalise to support removing multiple buddies (basically, its
- * the same as setbuddylist() but with a different snac subtype).
- *
- */
-faim_export int aim_buddylist_removebuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sn || !strlen(sn))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1);
-	aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid);
-
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* 
- * Subtype 0x000b
- *
- * XXX Why would we send this?
- *
- */
-faim_export int aim_buddylist_oncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn || !info)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0);
-	
-	aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid);
-	aim_putuserinfo(&fr->data, info);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* 
- * Subtype 0x000c
- *
- * XXX Why would we send this?
- *
- */
-faim_export int aim_buddylist_offgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0);
-	
-	aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid);
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtypes 0x000b and 0x000c - Change in buddy status
- *
- * Oncoming Buddy notifications contain a subset of the
- * user information structure.  It's close enough to run
- * through aim_info_extract() however.
- *
- * Although the offgoing notification contains no information,
- * it is still in a format parsable by aim_info_extract().
- *
- */
-static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_userinfo_t userinfo;
-	aim_rxcallback_t userfunc;
-
-	aim_info_extract(sess, bs, &userinfo);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, &userinfo);
-
-	if (snac->subtype == 0x000b)
-		aim_locate_requestuserinfo(sess, userinfo.sn);
-	aim_info_free(&userinfo);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return rights(sess, mod, rx, snac, bs);
-	else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c))
-		return buddychange(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0003;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "buddylist", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/chat.c
===================================================================
--- libfaim/chat.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,702 +1,0 @@
-/*
- * Family 0x000e - Routines for the Chat service.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h> 
-
-#include <string.h>
-
-/* Stored in the ->priv of chat connections */
-struct chatconnpriv {
-	fu16_t exchange;
-	char *name;
-	fu16_t instance;
-};
-
-faim_internal void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn)
-{
-	struct chatconnpriv *ccp = (struct chatconnpriv *)conn->priv;
-
-	if (ccp)
-		free(ccp->name);
-	free(ccp);
-
-	return;
-}
-
-faim_export char *aim_chat_getname(aim_conn_t *conn)
-{
-	struct chatconnpriv *ccp;
-
-	if (!conn)
-		return NULL;
-
-	if (conn->type != AIM_CONN_TYPE_CHAT)
-		return NULL;
-
-	ccp = (struct chatconnpriv *)conn->priv;
-
-	return ccp->name;
-}
-
-/* XXX get this into conn.c -- evil!! */
-faim_export aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		struct chatconnpriv *ccp = (struct chatconnpriv *)cur->priv;
-
-		if (cur->type != AIM_CONN_TYPE_CHAT)
-			continue;
-		if (!cur->priv) {
-			faimdprintf(sess, 0, "faim: chat: chat connection with no name! (fd = %d)\n", cur->fd);
-			continue;
-		}
-
-		if (strcmp(ccp->name, name) == 0)
-			break;
-	}
-
-	return cur;
-}
-
-faim_export int aim_chat_attachname(aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance)
-{
-	struct chatconnpriv *ccp;
-
-	if (!conn || !roomname)
-		return -EINVAL;
-
-	if (conn->priv)
-		free(conn->priv);
-
-	if (!(ccp = malloc(sizeof(struct chatconnpriv))))
-		return -ENOMEM;
-
-	ccp->exchange = exchange;
-	ccp->name = strdup(roomname);
-	ccp->instance = instance;
-
-	conn->priv = (void *)ccp;
-
-	return 0;
-}
-
-static int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, fu16_t type, fu16_t exchange, const char *roomname, fu16_t instance)
-{
-	fu8_t *buf;
-	int buflen;
-	aim_bstream_t bs;
-
-	buflen = 2 + 1 + strlen(roomname) + 2;
-	
-	if (!(buf = malloc(buflen)))
-		return 0;
-
-	aim_bstream_init(&bs, buf, buflen);
-
-	aimbs_put16(&bs, exchange);
-	aimbs_put8(&bs, strlen(roomname));
-	aimbs_putraw(&bs, roomname, strlen(roomname));
-	aimbs_put16(&bs, instance);
-
-	aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
-
-	free(buf);
-
-	return 0;
-}
-
-/*
- * Join a room of name roomname.  This is the first step to joining an 
- * already created room.  It's basically a Service Request for 
- * family 0x000e, with a little added on to specify the exchange and room 
- * name.
- */
-faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	struct chatsnacinfo csi;
-	
-	if (!sess || !conn || !roomname || !strlen(roomname))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
-		return -ENOMEM;
-
-	memset(&csi, 0, sizeof(csi));
-	csi.exchange = exchange;
-	strncpy(csi.name, roomname, sizeof(csi.name));
-	csi.instance = instance;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
-	aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);
-
-	/*
-	 * Requesting service chat (0x000e)
-	 */
-	aimbs_put16(&fr->data, 0x000e);
-
-	aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0; 
-}
-
-faim_internal int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo)
-{
-	int namelen;
-
-	if (!bs || !outinfo)
-		return 0;
-
-	outinfo->exchange = aimbs_get16(bs);
-	namelen = aimbs_get8(bs);
-	outinfo->name = aimbs_getstr(bs, namelen);
-	outinfo->instance = aimbs_get16(bs);
-
-	return 0;
-}
-
-faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name)
-{
-	aim_conn_t *conn;
-
-	if (!(conn = aim_chat_getconn(sess, name)))
-		return -ENOENT;
-
-	aim_conn_close(conn);
-
-	return 0;
-}
-
-/*
- * conn must be a BOS connection!
- */
-faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance)
-{
-	int i;
-	aim_frame_t *fr;
-	aim_msgcookie_t *cookie;
-	struct aim_invite_priv *priv;
-	fu8_t ckstr[8];
-	aim_snacid_t snacid;
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
-	fu8_t *hdr;
-	int hdrlen;
-	aim_bstream_t hdrbs;
-	
-	if (!sess || !conn || !sn || !msg || !roomname)
-		return -EINVAL;
-
-	if (conn->type != AIM_CONN_TYPE_BOS)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/*
-	 * Cookie
-	 */
-	for (i = 0; i < 8; i++)
-		ckstr[i] = (fu8_t)rand();
-
-	/* XXX should be uncached by an unwritten 'invite accept' handler */
-	if ((priv = malloc(sizeof(struct aim_invite_priv)))) {
-		priv->sn = strdup(sn);
-		priv->roomname = strdup(roomname);
-		priv->exchange = exchange;
-		priv->instance = instance;
-	}
-
-	if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv)))
-		aim_cachecookie(sess, cookie);
-	else
-		free(priv);
-
-	/* ICBM Header */
-	aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */
-	aimbs_put16(&fr->data, 0x0002); /* Channel */
-	aimbs_put8(&fr->data, strlen(sn)); /* Screename length */
-	aimbs_putraw(&fr->data, sn, strlen(sn)); /* Screenname */
-
-	/*
-	 * TLV t(0005)
-	 *
-	 * Everything else is inside this TLV.
-	 *
-	 * Sigh.  AOL was rather inconsistent right here.  So we have
-	 * to play some minor tricks.  Right inside the type 5 is some
-	 * raw data, followed by a series of TLVs.  
-	 *
-	 */
-	hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2;
-	hdr = malloc(hdrlen);
-	aim_bstream_init(&hdrbs, hdr, hdrlen);
-	
-	aimbs_put16(&hdrbs, 0x0000); /* Unknown! */
-	aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */
-	aim_putcap(&hdrbs, AIM_CAPS_CHAT);
-
-	aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_raw(&itl, 0x000c, strlen(msg), msg);
-	aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
-	aim_tlvlist_write(&hdrbs, &itl);
-	
-	aim_tlvlist_add_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
-
-	aim_tlvlist_write(&fr->data, &otl);
-
-	free(hdr);
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&otl);
-	
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0002 - General room information.  Lots of stuff.
- *
- * Values I know are in here but I havent attached
- * them to any of the 'Unknown's:
- *	- Language (English)
- *
- */
-static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t *userinfo = NULL;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	int usercount = 0;
-	fu8_t detaillevel = 0;
-	char *roomname = NULL;
-	struct aim_chat_roominfo roominfo;
-	fu16_t tlvcount = 0;
-	aim_tlvlist_t *tlvlist;
-	char *roomdesc = NULL;
-	fu16_t flags = 0;
-	fu32_t creationtime = 0;
-	fu16_t maxmsglen = 0, maxvisiblemsglen = 0;
-	fu16_t unknown_d2 = 0, unknown_d5 = 0;
-
-	aim_chat_readroominfo(bs, &roominfo);
-
-	detaillevel = aimbs_get8(bs);
-
-	if (detaillevel != 0x02) {
-		faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
-		return 1;
-	}
-
-	tlvcount = aimbs_get16(bs);
-
-	/*
-	 * Everything else are TLVs.
-	 */ 
-	tlvlist = aim_tlvlist_read(bs);
-
-	/*
-	 * TLV type 0x006a is the room name in Human Readable Form.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x006a, 1))
-		roomname = aim_tlv_getstr(tlvlist, 0x006a, 1);
-
-	/*
-	 * Type 0x006f: Number of occupants.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x006f, 1))
-		usercount = aim_tlv_get16(tlvlist, 0x006f, 1);
-
-	/*
-	 * Type 0x0073:  Occupant list.
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x0073, 1)) {	
-		int curoccupant = 0;
-		aim_tlv_t *tmptlv;
-		aim_bstream_t occbs;
-
-		tmptlv = aim_tlv_gettlv(tlvlist, 0x0073, 1);
-
-		/* Allocate enough userinfo structs for all occupants */
-		userinfo = calloc(usercount, sizeof(aim_userinfo_t));
-
-		aim_bstream_init(&occbs, tmptlv->value, tmptlv->length);
-
-		while (curoccupant < usercount)
-			aim_info_extract(sess, &occbs, &userinfo[curoccupant++]);
-	}
-
-	/* 
-	 * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00c9, 1))
-		flags = aim_tlv_get16(tlvlist, 0x00c9, 1);
-
-	/* 
-	 * Type 0x00ca: Creation time (4 bytes)
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00ca, 1))
-		creationtime = aim_tlv_get32(tlvlist, 0x00ca, 1);
-
-	/* 
-	 * Type 0x00d1: Maximum Message Length
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00d1, 1))
-		maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1);
-
-	/* 
-	 * Type 0x00d2: Unknown. (2 bytes)
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00d2, 1))
-		unknown_d2 = aim_tlv_get16(tlvlist, 0x00d2, 1);
-
-	/* 
-	 * Type 0x00d3: Room Description
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00d3, 1))
-		roomdesc = aim_tlv_getstr(tlvlist, 0x00d3, 1);
-
-	/*
-	 * Type 0x000d4: Unknown (flag only)
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000d4, 1))
-		;
-
-	/* 
-	 * Type 0x00d5: Unknown. (1 byte)
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x00d5, 1))
-		unknown_d5 = aim_tlv_get8(tlvlist, 0x00d5, 1);
-
-
-	/*
-	 * Type 0x00d6: Encoding 1 ("us-ascii")
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000d6, 1))
-		;
-	
-	/*
-	 * Type 0x00d7: Language 1 ("en")
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000d7, 1))
-		;
-
-	/*
-	 * Type 0x00d8: Encoding 2 ("us-ascii")
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000d8, 1))
-		;
-	
-	/*
-	 * Type 0x00d9: Language 2 ("en")
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000d9, 1))
-		;
-
-	/*
-	 * Type 0x00da: Maximum visible message length
-	 */
-	if (aim_tlv_gettlv(tlvlist, 0x000da, 1))
-		maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess,
-				rx,
-				&roominfo,
-				roomname,
-				usercount,
-				userinfo,
-				roomdesc,
-				flags,
-				creationtime,
-				maxmsglen,
-				unknown_d2,
-				unknown_d5,
-				maxvisiblemsglen);
-	}
-
-	free(roominfo.name);
-
-	while (usercount > 0)
-		aim_info_free(&userinfo[--usercount]);
-
-	free(userinfo);
-	free(roomname);
-	free(roomdesc);
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/* Subtypes 0x0003 and 0x0004 */
-static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t *userinfo = NULL;
-	aim_rxcallback_t userfunc;
-	int curcount = 0, ret = 0;
-
-	while (aim_bstream_empty(bs)) {
-		curcount++;
-		userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t));
-		aim_info_extract(sess, bs, &userinfo[curcount-1]);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, curcount, userinfo);
-
-	aim_info_free(userinfo);
-	free(userinfo);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0005 - Send a Chat Message.
- *
- * Possible flags:
- *   AIM_CHATFLAGS_NOREFLECT   --  Unset the flag that requests messages
- *                                 should be sent to their sender.
- *   AIM_CHATFLAGS_AWAY        --  Mark the message as an autoresponse
- *                                 (Note that WinAIM does not honor this,
- *                                 and displays the message as normal.)
- *
- * XXX convert this to use tlvchains 
- */
-faim_export int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, fu16_t flags, const char *msg, int msglen)
-{   
-	int i;
-	aim_frame_t *fr;
-	aim_msgcookie_t *cookie;
-	aim_snacid_t snacid;
-	fu8_t ckstr[8];
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
-
-	if (!sess || !conn || !msg || (msglen <= 0))
-		return 0;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x000e, 0x0005, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000e, 0x0005, 0x0000, snacid);
-
-	/*
-	 * Cookie
-	 *
-	 * XXX mkcookie should generate the cookie and cache it in one
-	 * operation to preserve uniqueness.
-	 */
-	for (i = 0; i < 8; i++)
-		ckstr[i] = (fu8_t)rand();
-
-	cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL);
-	cookie->data = NULL; /* XXX store something useful here */
-
-	aim_cachecookie(sess, cookie);
-
-	/* ICBM Header */
-	aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */
-	aimbs_put16(&fr->data, 0x0003); /* Channel */
-
-	/*
-	 * Type 1: Flag meaning this message is destined to the room.
-	 */
-	aim_tlvlist_add_noval(&otl, 0x0001);
-
-	/*
-	 * Type 6: Reflect
-	 */
-	if (!(flags & AIM_CHATFLAGS_NOREFLECT))
-		aim_tlvlist_add_noval(&otl, 0x0006);
-
-	/*
-	 * Type 7: Autoresponse
-	 */
-	if (flags & AIM_CHATFLAGS_AWAY)
-		aim_tlvlist_add_noval(&otl, 0x0007);
-
-	/*
-	 * SubTLV: Type 1: Message
-	 */
-	aim_tlvlist_add_raw(&itl, 0x0001, msglen, msg);
-
-	/*
-	 * Type 5: Message block.  Contains more TLVs.
-	 *
-	 * This could include other information... We just
-	 * put in a message TLV however.  
-	 * 
-	 */
-	aim_tlvlist_add_frozentlvlist(&otl, 0x0005, &itl);
-
-	aim_tlvlist_write(&fr->data, &otl);
-	
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&otl);
-	
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0006
- *
- * We could probably include this in the normal ICBM parsing 
- * code as channel 0x0003, however, since only the start
- * would be the same, we might as well do it here.
- *
- * General outline of this SNAC:
- *   snac
- *   cookie
- *   channel id
- *   tlvlist
- *     unknown
- *     source user info
- *       name
- *       evility
- *       userinfo tlvs
- *         online time
- *         etc
- *     message metatlv
- *       message tlv
- *         message string
- *       possibly others
- *  
- */
-static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t userinfo;
-	aim_rxcallback_t userfunc;	
-	int ret = 0;
-	fu8_t *cookie;
-	fu16_t channel;
-	aim_tlvlist_t *otl;
-	char *msg = NULL;
-	aim_msgcookie_t *ck;
-
-	memset(&userinfo, 0, sizeof(aim_userinfo_t));
-
-	/*
-	 * ICBM Cookie.  Uncache it.
-	 */
-	cookie = aimbs_getraw(bs, 8);
-
-	if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) {
-		free(ck->data);
-		free(ck);
-	}
-
-	/*
-	 * Channel ID
-	 *
-	 * Channels 1 and 2 are implemented in the normal ICBM
-	 * parser.
-	 *
-	 * We only do channel 3 here.
-	 *
-	 */
-	channel = aimbs_get16(bs);
-
-	if (channel != 0x0003) {
-		faimdprintf(sess, 0, "faim: chat_incoming: unknown channel! (0x%04x)\n", channel);
-		return 0;
-	}
-
-	/*
-	 * Start parsing TLVs right away. 
-	 */
-	otl = aim_tlvlist_read(bs);
-
-	/*
-	 * Type 0x0003: Source User Information
-	 */
-	if (aim_tlv_gettlv(otl, 0x0003, 1)) {
-		aim_tlv_t *userinfotlv;
-		aim_bstream_t tbs;
-
-		userinfotlv = aim_tlv_gettlv(otl, 0x0003, 1);
-
-		aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length);
-		aim_info_extract(sess, &tbs, &userinfo);
-	}
-
-	/*
-	 * Type 0x0001: If present, it means it was a message to the 
-	 * room (as opposed to a whisper).
-	 */
-	if (aim_tlv_gettlv(otl, 0x0001, 1))
-		;
-
-	/*
-	 * Type 0x0005: Message Block.  Conains more TLVs.
-	 */
-	if (aim_tlv_gettlv(otl, 0x0005, 1)) {
-		aim_tlvlist_t *itl;
-		aim_tlv_t *msgblock;
-		aim_bstream_t tbs;
-
-		msgblock = aim_tlv_gettlv(otl, 0x0005, 1);
-		aim_bstream_init(&tbs, msgblock->value, msgblock->length);
-		itl = aim_tlvlist_read(&tbs);
-
-		/* 
-		 * Type 0x0001: Message.
-		 */	
-		if (aim_tlv_gettlv(itl, 0x0001, 1))
-			msg = aim_tlv_getstr(itl, 0x0001, 1);
-
-		aim_tlvlist_free(&itl); 
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, &userinfo, msg);
-
-	aim_info_free(&userinfo);
-	free(cookie);
-	free(msg);
-	aim_tlvlist_free(&otl);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0002)
-		return infoupdate(sess, mod, rx, snac, bs);
-	else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004))
-		return userlistchange(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0006)
-		return incomingmsg(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000e;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "chat", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/chatnav.c
===================================================================
--- libfaim/chatnav.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,434 +1,0 @@
-/*
- * Family 0x000d - Handle ChatNav.
- *
- * The ChatNav(igation) service does various things to keep chat
- * alive.  It provides room information, room searching and creating,
- * as well as giving users the right ("permission") to use chat.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/*
- * Subtype 0x0002
- *
- * conn must be a chatnav connection!
- *
- */
-faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x000d, 0x0002);
-}
-
-/*
- * Subtype 0x0008
- */
-faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange)
-{
-	static const char ck[] = {"create"};
-	static const char lang[] = {"en"};
-	static const char charset[] = {"us-ascii"};
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x000d, 0x0008, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000d, 0x0008, 0x0000, snacid);
-
-	/* exchange */
-	aimbs_put16(&fr->data, exchange);
-
-	/*
-	 * This looks to be a big hack.  You'll note that this entire
-	 * SNAC is just a room info structure, but the hard room name,
-	 * here, is set to "create".  
-	 *
-	 * Either this goes on the "list of questions concerning
-	 * why-the-hell-did-you-do-that", or this value is completly
-	 * ignored.  Without experimental evidence, but a good knowledge of
-	 * AOL style, I'm going to guess that it is the latter, and that
-	 * the value of the room name in create requests is ignored.
-	 */
-	aimbs_put8(&fr->data, strlen(ck));
-	aimbs_putraw(&fr->data, ck, strlen(ck));
-
-	/* 
-	 * instance
-	 * 
-	 * Setting this to 0xffff apparently assigns the last instance.
-	 *
-	 */
-	aimbs_put16(&fr->data, 0xffff);
-
-	/* detail level */
-	aimbs_put8(&fr->data, 0x01);
-
-	aim_tlvlist_add_raw(&tl, 0x00d3, strlen(name), name);
-	aim_tlvlist_add_raw(&tl, 0x00d6, strlen(charset), charset);
-	aim_tlvlist_add_raw(&tl, 0x00d7, strlen(lang), lang);
-
-	/* tlvcount */
-	aimbs_put16(&fr->data, aim_tlvlist_count(&tl));
-	aim_tlvlist_write(&fr->data, &tl);
-
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs, aim_snac_t *snac2)
-{
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	struct aim_chat_exchangeinfo *exchanges = NULL;
-	int curexchange;
-	aim_tlv_t *exchangetlv;
-	fu8_t maxrooms = 0;
-	aim_tlvlist_t *tlvlist, *innerlist;
-
-	tlvlist = aim_tlvlist_read(bs);
-
-	/* 
-	 * Type 0x0002: Maximum concurrent rooms.
-	 */ 
-	if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
-		maxrooms = aim_tlv_get8(tlvlist, 0x0002, 1);
-
-	/* 
-	 * Type 0x0003: Exchange information
-	 *
-	 * There can be any number of these, each one
-	 * representing another exchange.  
-	 * 
-	 */
-	for (curexchange = 0; ((exchangetlv = aim_tlv_gettlv(tlvlist, 0x0003, curexchange+1))); ) {
-		aim_bstream_t tbs;
-
-		aim_bstream_init(&tbs, exchangetlv->value, exchangetlv->length);
-
-		curexchange++;
-
-		exchanges = realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
-
-		/* exchange number */
-		exchanges[curexchange-1].number = aimbs_get16(&tbs);
-		innerlist = aim_tlvlist_read(&tbs);
-
-		/* 
-		 * Type 0x000a: Unknown.
-		 *
-		 * Usually three bytes: 0x0114 (exchange 1) or 0x010f (others).
-		 *
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x000a, 1))
-			;
-
-		/* 
-		 * Type 0x000d: Unknown.
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x000d, 1))
-			;
-
-		/* 
-		 * Type 0x0004: Unknown
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x0004, 1))
-			;
-
-		/* 
-		 * Type 0x0002: Unknown
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x0002, 1)) {
-			fu16_t classperms;
-
-			classperms = aim_tlv_get16(innerlist, 0x0002, 1);
-			
-			faimdprintf(sess, 1, "faim: class permissions %x\n", classperms);
-		}
-
-		/*
-		 * Type 0x00c9: Flags
-		 *
-		 * 1 Evilable
-		 * 2 Nav Only
-		 * 4 Instancing Allowed
-		 * 8 Occupant Peek Allowed
-		 *
-		 */ 
-		if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
-			exchanges[curexchange-1].flags = aim_tlv_get16(innerlist, 0x00c9, 1);
-		      
-		/*
-		 * Type 0x00ca: Creation Date 
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
-			;
-		      
-		/*
-		 * Type 0x00d0: Mandatory Channels?
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d0, 1))
-			;
-
-		/*
-		 * Type 0x00d1: Maximum Message length
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
-			;
-
-		/*
-		 * Type 0x00d2: Maximum Occupancy?
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d2, 1))	
-			;
-
-		/*
-		 * Type 0x00d3: Exchange Description
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d3, 1))	
-			exchanges[curexchange-1].name = aim_tlv_getstr(innerlist, 0x00d3, 1);
-		else
-			exchanges[curexchange-1].name = NULL;
-
-		/*
-		 * Type 0x00d4: Exchange Description URL
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d4, 1))	
-			;
-
-		/*
-		 * Type 0x00d5: Creation Permissions
-		 *
-		 * 0  Creation not allowed
-		 * 1  Room creation allowed
-		 * 2  Exchange creation allowed
-		 * 
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) {
-			fu8_t createperms;
-
-			createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
-		}
-
-		/*
-		 * Type 0x00d6: Character Set (First Time)
-		 */	      
-		if (aim_tlv_gettlv(innerlist, 0x00d6, 1))	
-			exchanges[curexchange-1].charset1 = aim_tlv_getstr(innerlist, 0x00d6, 1);
-		else
-			exchanges[curexchange-1].charset1 = NULL;
-		      
-		/*
-		 * Type 0x00d7: Language (First Time)
-		 */	      
-		if (aim_tlv_gettlv(innerlist, 0x00d7, 1))	
-			exchanges[curexchange-1].lang1 = aim_tlv_getstr(innerlist, 0x00d7, 1);
-		else
-			exchanges[curexchange-1].lang1 = NULL;
-
-		/*
-		 * Type 0x00d8: Character Set (Second Time)
-		 */	      
-		if (aim_tlv_gettlv(innerlist, 0x00d8, 1))	
-			exchanges[curexchange-1].charset2 = aim_tlv_getstr(innerlist, 0x00d8, 1);
-		else
-			exchanges[curexchange-1].charset2 = NULL;
-
-		/*
-		 * Type 0x00d9: Language (Second Time)
-		 */	      
-		if (aim_tlv_gettlv(innerlist, 0x00d9, 1))	
-			exchanges[curexchange-1].lang2 = aim_tlv_getstr(innerlist, 0x00d9, 1);
-		else
-			exchanges[curexchange-1].lang2 = NULL;
-		      
-		/*
-		 * Type 0x00da: Unknown
-		 */
-		if (aim_tlv_gettlv(innerlist, 0x00da, 1))	
-			;
-
-		aim_tlvlist_free(&innerlist);
-	}
-
-	/*
-	 * Call client.
-	 */
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, snac2->type, maxrooms, curexchange, exchanges);
-
-	for (curexchange--; curexchange >= 0; curexchange--) {
-		free(exchanges[curexchange].name);
-		free(exchanges[curexchange].charset1);
-		free(exchanges[curexchange].lang1);
-		free(exchanges[curexchange].charset2);
-		free(exchanges[curexchange].lang2);
-	}
-	free(exchanges);
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs, aim_snac_t *snac2)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist, *innerlist;
-	char *ck = NULL, *fqcn = NULL, *name = NULL;
-	fu16_t exchange = 0, instance = 0, unknown = 0, flags = 0, maxmsglen = 0, maxoccupancy = 0;
-	fu32_t createtime = 0;
-	fu8_t createperms = 0, detaillevel;
-	int cklen;
-	aim_tlv_t *bigblock;
-	int ret = 0;
-	aim_bstream_t bbbs;
-
-	tlvlist = aim_tlvlist_read(bs);
-
-	if (!(bigblock = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-		faimdprintf(sess, 0, "no bigblock in top tlv in create room response\n");
-		aim_tlvlist_free(&tlvlist);
-		return 0;
-	}
-
-	aim_bstream_init(&bbbs, bigblock->value, bigblock->length);
-
-	exchange = aimbs_get16(&bbbs);
-	cklen = aimbs_get8(&bbbs);
-	ck = aimbs_getstr(&bbbs, cklen);
-	instance = aimbs_get16(&bbbs);
-	detaillevel = aimbs_get8(&bbbs);
-
-	if (detaillevel != 0x02) {
-		faimdprintf(sess, 0, "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
-		aim_tlvlist_free(&tlvlist);
-		free(ck);
-		return 0;
-	}
-
-	unknown = aimbs_get16(&bbbs);
-
-	innerlist = aim_tlvlist_read(&bbbs);
-
-	if (aim_tlv_gettlv(innerlist, 0x006a, 1))
-		fqcn = aim_tlv_getstr(innerlist, 0x006a, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
-		flags = aim_tlv_get16(innerlist, 0x00c9, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
-		createtime = aim_tlv_get32(innerlist, 0x00ca, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
-		maxmsglen = aim_tlv_get16(innerlist, 0x00d1, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00d2, 1))
-		maxoccupancy = aim_tlv_get16(innerlist, 0x00d2, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
-		name = aim_tlv_getstr(innerlist, 0x00d3, 1);
-
-	if (aim_tlv_gettlv(innerlist, 0x00d5, 1))
-		createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck);
-	}
-
-	free(ck);
-	free(name);
-	free(fqcn);
-	aim_tlvlist_free(&innerlist);
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0009
- *
- * Since multiple things can trigger this callback, we must lookup the 
- * snacid to determine the original snac subtype that was called.
- *
- * XXX This isn't really how this works.  But this is:  Every d/9 response
- * has a 16bit value at the beginning. That matches to:
- *    Short Desc = 1
- *    Full Desc = 2
- *    Instance Info = 4
- *    Nav Short Desc = 8
- *    Nav Instance Info = 16
- * And then everything is really asynchronous.  There is no specific 
- * attachment of a response to a create room request, for example.  Creating
- * the room yields no different a response than requesting the room's info.
- *
- */
-static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_snac_t *snac2;
-	int ret = 0;
-
-	if (!(snac2 = aim_remsnac(sess, snac->id))) {
-		faimdprintf(sess, 0, "faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snac->id);
-		return 0;
-	}
-
-	if (snac2->family != 0x000d) {
-		faimdprintf(sess, 0, "faim: chatnav_parse_info: recieved response that maps to corrupt request! (fam=%04x)\n", snac2->family);
-		return 0;
-	}
-
-	/*
-	 * We now know what the original SNAC subtype was.
-	 */
-	if (snac2->type == 0x0002) /* request chat rights */
-		ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2);
-	else if (snac2->type == 0x0003) /* request exchange info */
-		faimdprintf(sess, 0, "chatnav_parse_info: resposne to exchange info\n");
-	else if (snac2->type == 0x0004) /* request room info */
-		faimdprintf(sess, 0, "chatnav_parse_info: response to room info\n");
-	else if (snac2->type == 0x0005) /* request more room info */
-		faimdprintf(sess, 0, "chatnav_parse_info: response to more room info\n");
-	else if (snac2->type == 0x0006) /* request occupant list */
-		faimdprintf(sess, 0, "chatnav_parse_info: response to occupant info\n");
-	else if (snac2->type == 0x0007) /* search for a room */
-		faimdprintf(sess, 0, "chatnav_parse_info: search results\n");
-	else if (snac2->type == 0x0008) /* create room */
-		ret = parseinfo_create(sess, mod, rx, snac, bs, snac2);
-	else
-		faimdprintf(sess, 0, "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type);
-
-	if (snac2)
-		free(snac2->data);
-	free(snac2);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0009)
-		return parseinfo(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int chatnav_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000d;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "chatnav", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/config.h.in
===================================================================
--- libfaim/config.h.in	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ 	(revision )
@@ -1,83 +1,0 @@
-/* include/config.h.in.  Generated automatically from configure.in by autoheader.  */
-
-/* Define to empty if the keyword does not work.  */
-#undef const
-
-/* Define if you don't have vprintf but do have _doprnt.  */
-#undef HAVE_DOPRNT
-
-/* Define if you have the strftime function.  */
-#undef HAVE_STRFTIME
-
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
-#undef HAVE_SYS_WAIT_H
-
-/* Define if you have the vprintf function.  */
-#undef HAVE_VPRINTF
-
-/* Define as __inline if that's what the C compiler calls it.  */
-#undef inline
-
-/* Define to `int' if <sys/types.h> doesn't define.  */
-#undef pid_t
-
-/* Define as the return type of signal handlers (int or void).  */
-#undef RETSIGTYPE
-
-/* Define to `unsigned' if <sys/types.h> doesn't define.  */
-#undef size_t
-
-/* Define if you have the ANSI C header files.  */
-#undef STDC_HEADERS
-
-/* Define if you can safely include both <sys/time.h> and <time.h>.  */
-#undef TIME_WITH_SYS_TIME
-
-/* Define if your <sys/time.h> declares struct tm.  */
-#undef TM_IN_SYS_TIME
-
-/* Define if you have the getaddrinfo function.  */
-#undef HAVE_GETADDRINFO
-
-/* Define if you have the gethostname function.  */
-#undef HAVE_GETHOSTNAME
-
-/* Define if you have the gettimeofday function.  */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define if you have the select function.  */
-#undef HAVE_SELECT
-
-/* Define if you have the socket function.  */
-#undef HAVE_SOCKET
-
-/* Define if you have the strdup function.  */
-#undef HAVE_STRDUP
-
-/* Define if you have the strstr function.  */
-#undef HAVE_STRSTR
-
-/* Define if you have the strtol function.  */
-#undef HAVE_STRTOL
-
-/* Define if you have the uname function.  */
-#undef HAVE_UNAME
-
-/* Define if you have the <fcntl.h> header file.  */
-#undef HAVE_FCNTL_H
-
-/* Define if you have the <sys/time.h> header file.  */
-#undef HAVE_SYS_TIME_H
-
-/* Define if you have the <unistd.h> header file.  */
-#undef HAVE_UNISTD_H
-
-/* Define if you have the faim library (-lfaim).  */
-#undef HAVE_LIBFAIM
-
-/* Name of package */
-#undef PACKAGE
-
-/* Version number of package */
-#undef VERSION
-
Index: bfaim/configure
===================================================================
--- libfaim/configure	(revision 1ef65fbc93f88230a95c10105937627bdfe6708d)
+++ 	(revision )
@@ -1,3170 +1,0 @@
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)$' \| \
-	 .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
-  	  /^X\/\(\/\).*/{ s//\1/; q; }
-  	  s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-	 case $as_dir in
-	 /*)
-	   if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-	     CONFIG_SHELL=$as_dir/$as_base
-	     export CONFIG_SHELL
-	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-	   fi;;
-	 esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='	' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" 	$as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete.  It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-
-ac_unique_file="bos.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT RANLIB ac_ct_RANLIB LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
-  # If the previous option needs an argument, assign it.
-  if test -n "$ac_prev"; then
-    eval "$ac_prev=\$ac_option"
-    ac_prev=
-    continue
-  fi
-
-  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
-  # Accept the important Cygnus configure options, so we can diagnose typos.
-
-  case $ac_option in
-
-  -bindir | --bindir | --bindi | --bind | --bin | --bi)
-    ac_prev=bindir ;;
-  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir=$ac_optarg ;;
-
-  -build | --build | --buil | --bui | --bu)
-    ac_prev=build_alias ;;
-  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build_alias=$ac_optarg ;;
-
-  -cache-file | --cache-file | --cache-fil | --cache-fi \
-  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
-    ac_prev=cache_file ;;
-  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
-  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file=$ac_optarg ;;
-
-  --config-cache | -C)
-    cache_file=config.cache ;;
-
-  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
-    ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
-  | --da=*)
-    datadir=$ac_optarg ;;
-
-  -disable-* | --disable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval "enable_$ac_feature=no" ;;
-
-  -enable-* | --enable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "enable_$ac_feature='$ac_optarg'" ;;
-
-  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
-  | --exec | --exe | --ex)
-    ac_prev=exec_prefix ;;
-  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
-  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
-  | --exec=* | --exe=* | --ex=*)
-    exec_prefix=$ac_optarg ;;
-
-  -gas | --gas | --ga | --g)
-    # Obsolete; use --with-gas.
-    with_gas=yes ;;
-
-  -help | --help | --hel | --he | -h)
-    ac_init_help=long ;;
-  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
-    ac_init_help=recursive ;;
-  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
-    ac_init_help=short ;;
-
-  -host | --host | --hos | --ho)
-    ac_prev=host_alias ;;
-  -host=* | --host=* | --hos=* | --ho=*)
-    host_alias=$ac_optarg ;;
-
-  -includedir | --includedir | --includedi | --included | --include \
-  | --includ | --inclu | --incl | --inc)
-    ac_prev=includedir ;;
-  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
-  | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir=$ac_optarg ;;
-
-  -infodir | --infodir | --infodi | --infod | --info | --inf)
-    ac_prev=infodir ;;
-  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir=$ac_optarg ;;
-
-  -libdir | --libdir | --libdi | --libd)
-    ac_prev=libdir ;;
-  -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir=$ac_optarg ;;
-
-  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
-  | --libexe | --libex | --libe)
-    ac_prev=libexecdir ;;
-  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
-  | --libexe=* | --libex=* | --libe=*)
-    libexecdir=$ac_optarg ;;
-
-  -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst \
-  | --locals | --local | --loca | --loc | --lo)
-    ac_prev=localstatedir ;;
-  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
-  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
-    localstatedir=$ac_optarg ;;
-
-  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
-    ac_prev=mandir ;;
-  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir=$ac_optarg ;;
-
-  -nfp | --nfp | --nf)
-    # Obsolete; use --without-fp.
-    with_fp=no ;;
-
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c | -n)
-    no_create=yes ;;
-
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
-    no_recursion=yes ;;
-
-  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
-  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
-  | --oldin | --oldi | --old | --ol | --o)
-    ac_prev=oldincludedir ;;
-  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
-  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
-  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir=$ac_optarg ;;
-
-  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
-    ac_prev=prefix ;;
-  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix=$ac_optarg ;;
-
-  -program-prefix | --program-prefix | --program-prefi | --program-pref \
-  | --program-pre | --program-pr | --program-p)
-    ac_prev=program_prefix ;;
-  -program-prefix=* | --program-prefix=* | --program-prefi=* \
-  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix=$ac_optarg ;;
-
-  -program-suffix | --program-suffix | --program-suffi | --program-suff \
-  | --program-suf | --program-su | --program-s)
-    ac_prev=program_suffix ;;
-  -program-suffix=* | --program-suffix=* | --program-suffi=* \
-  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix=$ac_optarg ;;
-
-  -program-transform-name | --program-transform-name \
-  | --program-transform-nam | --program-transform-na \
-  | --program-transform-n | --program-transform- \
-  | --program-transform | --program-transfor \
-  | --program-transfo | --program-transf \
-  | --program-trans | --program-tran \
-  | --progr-tra | --program-tr | --program-t)
-    ac_prev=program_transform_name ;;
-  -program-transform-name=* | --program-transform-name=* \
-  | --program-transform-nam=* | --program-transform-na=* \
-  | --program-transform-n=* | --program-transform-=* \
-  | --program-transform=* | --program-transfor=* \
-  | --program-transfo=* | --program-transf=* \
-  | --program-trans=* | --program-tran=* \
-  | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name=$ac_optarg ;;
-
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil)
-    silent=yes ;;
-
-  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
-    ac_prev=sbindir ;;
-  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
-  | --sbi=* | --sb=*)
-    sbindir=$ac_optarg ;;
-
-  -sharedstatedir | --sharedstatedir | --sharedstatedi \
-  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
-  | --sharedst | --shareds | --shared | --share | --shar \
-  | --sha | --sh)
-    ac_prev=sharedstatedir ;;
-  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
-  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
-  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
-  | --sha=* | --sh=*)
-    sharedstatedir=$ac_optarg ;;
-
-  -site | --site | --sit)
-    ac_prev=site ;;
-  -site=* | --site=* | --sit=*)
-    site=$ac_optarg ;;
-
-  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
-    ac_prev=srcdir ;;
-  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir=$ac_optarg ;;
-
-  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
-  | --syscon | --sysco | --sysc | --sys | --sy)
-    ac_prev=sysconfdir ;;
-  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
-  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir=$ac_optarg ;;
-
-  -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target_alias ;;
-  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target_alias=$ac_optarg ;;
-
-  -v | -verbose | --verbose | --verbos | --verbo | --verb)
-    verbose=yes ;;
-
-  -version | --version | --versio | --versi | --vers | -V)
-    ac_init_version=: ;;
-
-  -with-* | --with-*)
-    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "with_$ac_package='$ac_optarg'" ;;
-
-  -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval "with_$ac_package=no" ;;
-
-  --x)
-    # Obsolete; use --with-x.
-    with_x=yes ;;
-
-  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
-  | --x-incl | --x-inc | --x-in | --x-i)
-    ac_prev=x_includes ;;
-  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
-  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes=$ac_optarg ;;
-
-  -x-libraries | --x-libraries | --x-librarie | --x-librari \
-  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
-    ac_prev=x_libraries ;;
-  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
-  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries=$ac_optarg ;;
-
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
-    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
-    eval "$ac_envvar='$ac_optarg'"
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
-    ;;
-
-  esac
-done
-
-if test -n "$ac_prev"; then
-  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
-	      localstatedir libdir includedir oldincludedir infodir mandir
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
-  if test "x$build_alias" = x; then
-    cross_compiling=maybe
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
-  elif test "x$build_alias" != "x$host_alias"; then
-    cross_compiling=yes
-  fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
-  ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then its parent.
-  ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$0" : 'X\(//\)[^/]' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| \
-	 .     : '\(.\)' 2>/dev/null ||
-echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-  	  /^X\(\/\/\)$/{ s//\1/; q; }
-  	  /^X\(\/\).*/{ s//\1/; q; }
-  	  s/.*/./; q'`
-  srcdir=$ac_confdir
-  if test ! -r $srcdir/$ac_unique_file; then
-    srcdir=..
-  fi
-else
-  ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
-  if test "$ac_srcdir_defaulted" = yes; then
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
-   { (exit 1); exit 1; }; }
-  else
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-  fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
-  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
-   { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
-  # Omit some internal or obsolete options to make the list less imposing.
-  # This message is too long to be a string in the A/UX 3.1 sh.
-  cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE.  See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
-  -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
-  -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking...' messages
-      --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for \`--cache-file=config.cache'
-  -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
-  cat <<_ACEOF
-Installation directories:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-			  [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-			  [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR           user executables [EPREFIX/bin]
-  --sbindir=DIR          system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
-  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
-  --libdir=DIR           object code libraries [EPREFIX/lib]
-  --includedir=DIR       C header files [PREFIX/include]
-  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --infodir=DIR          info documentation [PREFIX/info]
-  --mandir=DIR           man documentation [PREFIX/man]
-_ACEOF
-
-  cat <<\_ACEOF
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-
-  cat <<\_ACEOF
-
-Some influential environment variables:
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
-              headers in a nonstandard directory <include dir>
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
-  # If there are subdirs, report their specific --help.
-  ac_popdir=`pwd`
-  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d $ac_dir || continue
-    ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-    cd $ac_dir
-    # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f $ac_srcdir/configure.gnu; then
-      echo
-      $SHELL $ac_srcdir/configure.gnu  --help=recursive
-    elif test -f $ac_srcdir/configure; then
-      echo
-      $SHELL $ac_srcdir/configure  --help=recursive
-    elif test -f $ac_srcdir/configure.ac ||
-	   test -f $ac_srcdir/configure.in; then
-      echo
-      $ac_configure --help
-    else
-      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi
-    cd $ac_popdir
-  done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
-  cat <<\_ACEOF
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
-  exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
-
-/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
-/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
-/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
-  for ac_arg
-  do
-    case $ac_arg in
-    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-    | -silent | --silent | --silen | --sile | --sil)
-      continue ;;
-    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
-    2)
-      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
-      if test $ac_must_keep_next = true; then
-	ac_must_keep_next=false # Got value, back to normal.
-      else
-	case $ac_arg in
-	  *=* | --config-cache | -C | -disable-* | --disable-* \
-	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
-	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
-	  | -with-* | --with-* | -without-* | --without-* | --x)
-	    case "$ac_configure_args0 " in
-	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
-	    esac
-	    ;;
-	  -* ) ac_must_keep_next=true ;;
-	esac
-      fi
-      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
-      # Get rid of the leading space.
-      ac_sep=" "
-      ;;
-    esac
-  done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log.  We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
-  # Save into config.log some information that might help in debugging.
-  {
-    echo
-
-    cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
-    echo
-    # The following way of writing the cache mishandles newlines in values,
-{
-  (set) 2>&1 |
-    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      sed -n \
-	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
-	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
-      ;;
-    *)
-      sed -n \
-	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-}
-    echo
-
-    cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=$`echo $ac_var`
-      echo "$ac_var='"'"'$ac_val'"'"'"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
-      echo
-      for ac_var in $ac_subst_files
-      do
-	eval ac_val=$`echo $ac_var`
-	echo "$ac_var='"'"'$ac_val'"'"'"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
-      echo
-      sed "/^$/d" confdefs.h | sort
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    echo "$as_me: exit $exit_status"
-  } >&5
-  rm -f core *.core &&
-  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
-    exit $exit_status
-     ' 0
-for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
-  if test "x$prefix" != xNONE; then
-    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
-  else
-    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
-  fi
-fi
-for ac_site_file in $CONFIG_SITE; do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
-  fi
-done
-
-if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special
-  # files actually), so we avoid doing that.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . $cache_file;;
-      *)                      . ./$cache_file;;
-    esac
-  fi
-else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
-  >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
-	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
-  eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
-  eval ac_new_val="\$ac_env_${ac_var}_value"
-  case $ac_old_set,$ac_new_set in
-    set,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,);;
-    *)
-      if test "x$ac_old_val" != "x$ac_new_val"; then
-	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-	ac_cache_corrupted=:
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
-    *) ac_arg=$ac_var=$ac_new_val ;;
-    esac
-    case " $ac_configure_args " in
-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  test -n "$ac_ct_CC" && break
-done
-
-  CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
-     "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-  (eval $ac_compiler --version </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
-  (eval $ac_compiler -v </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
-  (eval $ac_compiler -V </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
-  (eval $ac_link_default) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # Find the output, starting from the most likely.  This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
-	;;
-    conftest.$ac_ext )
-	# This is the source file.
-	;;
-    [ab].out )
-	# We found the default executable, but exeext='' is most
-	# certainly right.
-	break;;
-    *.* )
-	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-	# FIXME: I believe we export ac_cv_exeext for Libtool,
-	# but it would be cool to find out if it's true.  Does anybody
-	# maintain Libtool? --akim.
-	export ac_cv_exeext
-	break;;
-    * )
-	break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-	cross_compiling=yes
-    else
-	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-	  export ac_cv_exeext
-	  break;;
-    * ) break;;
-  esac
-done
-else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std1 is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std1.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX			-qlanglvl=ansi
-# Ultrix and OSF/1	-std1
-# HP-UX 10.20 and later	-Ae
-# HP-UX older versions	-Aa -D_HPUX_SOURCE
-# SVR4			-Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_stdc=$ac_arg
-break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
-  x|xno)
-    echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
-  *)
-    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
-    CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C.  Since we use `exit',
-# in C++ we need to declare it.  In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
-  choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  for ac_declaration in \
-   '' \
-   'extern "C" void std::exit (int) throw (); using std::exit;' \
-   'extern "C" void std::exit (int); using std::exit;' \
-   'extern "C" void exit (int) throw ();' \
-   'extern "C" void exit (int);' \
-   'void exit (int);'
-do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"
-			 || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-	 { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
-  echo '#ifdef __cplusplus' >>confdefs.h
-  echo $ac_declaration      >>confdefs.h
-  echo '#endif'             >>confdefs.h
-fi
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-if test "$GCC" = yes; then
-   CFLAGS="$CFLAGS -Wall -g";
-fi
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$RANLIB"; then
-  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
-  echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
-  ac_ct_RANLIB=$RANLIB
-  # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_RANLIB"; then
-  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_RANLIB="ranlib"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
-  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  RANLIB=$ac_ct_RANLIB
-else
-  RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-
-
-          ac_config_files="$ac_config_files Makefile"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems.  If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
-  (set) 2>&1 |
-    case `(ac_space=' '; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      # `set' does not quote correctly, so add quotes (double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \).
-      sed -n \
-	"s/'/'\\\\''/g;
-	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;;
-    *)
-      # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n \
-	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-} |
-  sed '
-     t clear
-     : clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
-     t end
-     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
-  if test -w $cache_file; then
-    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
-    cat confcache >$cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[	 ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[	 ]*$//;
-}'
-fi
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
-t quote
-s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
-
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
-  # 1. Remove the extension, and $U if already installed.
-  ac_i=`echo "$ac_i" |
-	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
-  # 2. Add them.
-  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)$' \| \
-	 .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
-  	  /^X\/\(\/\).*/{ s//\1/; q; }
-  	  s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-	 case $as_dir in
-	 /*)
-	   if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-	     CONFIG_SHELL=$as_dir/$as_base
-	     export CONFIG_SHELL
-	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-	   fi;;
-	 esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='	' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" 	$as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.  Logging --version etc. is OK.
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  CONFIG_FILES    = $CONFIG_FILES
-  CONFIG_HEADERS  = $CONFIG_HEADERS
-  CONFIG_LINKS    = $CONFIG_LINKS
-  CONFIG_COMMANDS = $CONFIG_COMMANDS
-  $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
-  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
-  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
-  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
-  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number, then exit
-  -q, --quiet      do not print progress messages
-  -d, --debug      don't remove temporary files
-      --recheck    update $as_me by reconfiguring in the same conditions
-  --file=FILE[:TEMPLATE]
-		   instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-config.status
-configured by $0, generated by GNU Autoconf 2.59,
-  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
-  case $1 in
-  --*=*)
-    ac_option=`expr "x$1" : 'x\([^=]*\)='`
-    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
-    ac_shift=:
-    ;;
-  -*)
-    ac_option=$1
-    ac_optarg=$2
-    ac_shift=shift
-    ;;
-  *) # This is not an option, so the user has probably given explicit
-     # arguments.
-     ac_option=$1
-     ac_need_defaults=false;;
-  esac
-
-  case $ac_option in
-  # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    ac_cs_recheck=: ;;
-  --version | --vers* | -V )
-    echo "$ac_cs_version"; exit 0 ;;
-  --he | --h)
-    # Conflict between --help and --header
-    { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit 0 ;;
-  --debug | --d* | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil | --si | --s)
-    ac_cs_silent=: ;;
-
-  # This is an error.
-  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; } ;;
-
-  *) ac_config_targets="$ac_config_targets $1" ;;
-
-  esac
-  shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
-  exec 6>/dev/null
-  ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
-  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
-  case "$ac_config_target" in
-  # Handling of arguments.
-  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used.  Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
-  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-fi
-
-# Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
-  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
-}  ||
-{
-  tmp=./confstat$$-$RANDOM
-  (umask 077 && mkdir $tmp)
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@RANLIB@,$RANLIB,;t t
-s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    else
-      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    fi
-    if test ! -s $tmp/subs.frag; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo ':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
-      if test -z "$ac_sed_cmds"; then
-	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
-      else
-	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
-  fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case $ac_file in
-  - | *:- | *:-:* ) # input from stdin
-	cat >$tmp/stdin
-	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  * )   ac_file_in=$ac_file.in ;;
-  esac
-
-  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
-  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$ac_file" : 'X\(//\)[^/]' \| \
-	 X"$ac_file" : 'X\(//\)$' \| \
-	 X"$ac_file" : 'X\(/\)' \| \
-	 .     : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-  	  /^X\(\/\/\)$/{ s//\1/; q; }
-  	  /^X\(\/\).*/{ s//\1/; q; }
-  	  s/.*/./; q'`
-  { if $as_mkdir_p; then
-    mkdir -p "$ac_dir"
-  else
-    as_dir="$ac_dir"
-    as_dirs=
-    while test ! -d "$as_dir"; do
-      as_dirs="$as_dir $as_dirs"
-      as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$as_dir" : 'X\(//\)[^/]' \| \
-	 X"$as_dir" : 'X\(//\)$' \| \
-	 X"$as_dir" : 'X\(/\)' \| \
-	 .     : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-  	  /^X\(\/\/\)$/{ s//\1/; q; }
-  	  /^X\(\/\).*/{ s//\1/; q; }
-  	  s/.*/./; q'`
-    done
-    test ! -n "$as_dirs" || mkdir $as_dirs
-  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
-   { (exit 1); exit 1; }; }; }
-
-  ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-
-
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
-  # Let's still pretend it is `configure' which instantiates (i.e., don't
-  # use $as_me), people would be surprised to read:
-  #    /* config.h.  Generated by config.status.  */
-  if test x"$ac_file" = x-; then
-    configure_input=
-  else
-    configure_input="$ac_file.  "
-  fi
-  configure_input=$configure_input"Generated from `echo $ac_file_in |
-				     sed 's,.*/,,'` by configure."
-
-  # First look for the input files in the build tree, otherwise in the
-  # src tree.
-  ac_file_inputs=`IFS=:
-    for f in $ac_file_in; do
-      case $f in
-      -) echo $tmp/stdin ;;
-      [\\/$]*)
-	 # Absolute (can't be DOS-style, as IFS=:)
-	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-	 echo "$f";;
-      *) # Relative
-	 if test -f "$f"; then
-	   # Build tree
-	   echo "$f"
-	 elif test -f "$srcdir/$f"; then
-	   # Source tree
-	   echo "$srcdir/$f"
-	 else
-	   # /dev/null tree
-	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-	 fi;;
-      esac
-    done` || { (exit 1); exit 1; }
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
-  rm -f $tmp/stdin
-  if test x"$ac_file" != x-; then
-    mv $tmp/out $ac_file
-  else
-    cat $tmp/out
-    rm -f $tmp/out
-  fi
-
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded.  So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status.  When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
-  ac_cs_success=:
-  ac_config_status_args=
-  test "$silent" = yes &&
-    ac_config_status_args="$ac_config_status_args --quiet"
-  exec 5>/dev/null
-  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
-  exec 5>>config.log
-  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
-  # would make configure fail if this is the last instruction.
-  $ac_cs_success || { (exit 1); exit 1; }
-fi
-
Index: bfaim/configure.in
===================================================================
--- libfaim/configure.in	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,13 +1,0 @@
-AC_INIT(bos.c)
-
-dnl AC_CONFIG_HEADER(config.h)
-
-AC_PROG_CC
-dnl we're using GCC, enable all warnings
-if test "$GCC" = yes; then
-   CFLAGS="$CFLAGS -Wall -g";
-fi
-AC_PROG_RANLIB
-
-
-AC_OUTPUT(Makefile)
Index: bfaim/conn.c
===================================================================
--- libfaim/conn.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,1053 +1,0 @@
-/*
- * conn.c
- *
- * Does all this gloriously nifty connection handling stuff...
- *
- */
-
-#define FAIM_INTERNAL
-#define FAIM_NEED_CONN_INTERNAL
-#include <aim.h> 
-
-#ifndef _WIN32
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#endif
-
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-/*
- * In OSCAR, every connection has a set of SNAC groups associated
- * with it.  These are the groups that you can send over this connection
- * without being guarenteed a "Not supported" SNAC error.  
- *
- * The grand theory of things says that these associations transcend 
- * what libfaim calls "connection types" (conn->type).  You can probably
- * see the elegance here, but since I want to revel in it for a bit, you 
- * get to hear it all spelled out.
- *
- * So let us say that you have your core BOS connection running.  One
- * of your modules has just given you a SNAC of the group 0x0004 to send
- * you.  Maybe an IM destined for some twit in Greenland.  So you start
- * at the top of your connection list, looking for a connection that 
- * claims to support group 0x0004.  You find one.  Why, that neat BOS
- * connection of yours can do that.  So you send it on its way.
- *
- * Now, say, that fellow from Greenland has friends and they all want to
- * meet up with you in a lame chat room.  This has landed you a SNAC
- * in the family 0x000e and you have to admit you're a bit lost.  You've
- * searched your connection list for someone who wants to make your life
- * easy and deliver this SNAC for you, but there isn't one there.
- *
- * Here comes the good bit.  Without even letting anyone know, particularly
- * the module that decided to send this SNAC, and definitly not that twit
- * in Greenland, you send out a service request.  In this request, you have
- * marked the need for a connection supporting group 0x000e.  A few seconds
- * later, you receive a service redirect with an IP address and a cookie in
- * it.  Great, you say.  Now I have something to do.  Off you go, making
- * that connection.  One of the first things you get from this new server
- * is a message saying that indeed it does support the group you were looking
- * for.  So you continue and send rate confirmation and all that.  
- * 
- * Then you remember you had that SNAC to send, and now you have a means to
- * do it, and you do, and everyone is happy.  Except the Greenlander, who is
- * still stuck in the bitter cold.
- *
- * Oh, and this is useful for building the Migration SNACs, too.  In the
- * future, this may help convince me to implement rate limit mitigation
- * for real.  We'll see.
- *
- * Just to make me look better, I'll say that I've known about this great
- * scheme for quite some time now.  But I still haven't convinced myself
- * to make libfaim work that way.  It would take a fair amount of effort,
- * and probably some client API changes as well.  (Whenever I don't want
- * to do something, I just say it would change the client API.  Then I 
- * instantly have a couple of supporters of not doing it.)
- *
- * Generally, addgroup is only called by the internal handling of the
- * server ready SNAC.  So if you want to do something before that, you'll
- * have to be more creative.  That is done rather early, though, so I don't
- * think you have to worry about it.  Unless you're me.  I care deeply
- * about such inane things.
- *
- */
-faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	struct snacgroup *sg;
-
-	if (!(sg = malloc(sizeof(struct snacgroup))))
-		return;
-
-	faimdprintf(aim_conn_getsess(conn), 1, "adding group 0x%04x\n", group);
-	sg->group = group;
-
-	sg->next = ins->groups;
-	ins->groups = sg;
-
-	return;
-}
-
-faim_export aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, fu16_t group)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		aim_conn_inside_t *ins = (aim_conn_inside_t *)cur->inside;
-		struct snacgroup *sg;
-
-		for (sg = ins->groups; sg; sg = sg->next) {
-			if (sg->group == group)
-				return cur;
-		}
-	}
-
-	return NULL;
-}
-
-static void connkill_snacgroups(struct snacgroup **head)
-{
-	struct snacgroup *sg;
-
-	for (sg = *head; sg; ) {
-		struct snacgroup *tmp;
-
-		tmp = sg->next;
-		free(sg);
-		sg = tmp;
-	}
-
-	*head = NULL;
-
-	return;
-}
-
-static void connkill_rates(struct rateclass **head)
-{
-	struct rateclass *rc;
-
-	for (rc = *head; rc; ) {
-		struct rateclass *tmp;
-		struct snacpair *sp;
-
-		tmp = rc->next;
-
-		for (sp = rc->members; sp; ) {
-			struct snacpair *tmpsp;
-
-			tmpsp = sp->next;
-			free(sp);
-			sp = tmpsp;
-		}
-		free(rc);
-
-		rc = tmp;
-	}
-
-	*head = NULL;
-
-	return;
-}
-
-static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
-{
-
-	aim_rxqueue_cleanbyconn(sess, *deadconn);
-	aim_tx_cleanqueue(sess, *deadconn);
-
-	if ((*deadconn)->fd != -1) 
-		aim_conn_close(*deadconn);
-
-	/*
-	 * XXX ->priv should never be touched by the library. I know
-	 * it used to be, but I'm getting rid of all that.  Use
-	 * ->internal instead.
-	 */
-	if ((*deadconn)->priv)
-		free((*deadconn)->priv);
-
-	/*
-	 * This will free ->internal if it necessary...
-	 */
-	if ((*deadconn)->type == AIM_CONN_TYPE_CHAT)
-		aim_conn_kill_chat(sess, *deadconn);
-
-	if ((*deadconn)->inside) {
-		aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside;
-
-		connkill_snacgroups(&inside->groups);
-		connkill_rates(&inside->rates);
-
-		free(inside);
-	}
-
-	free(*deadconn);
-	*deadconn = NULL;
-
-	return;
-}
-
-/**
- * Clears out connection list, killing remaining connections.
- *
- * @param sess Session to be cleared
- */
-static void aim_connrst(aim_session_t *sess)
-{
-
-	if (sess->connlist) {
-		aim_conn_t *cur = sess->connlist, *tmp;
-
-		while (cur) {
-			tmp = cur->next;
-			aim_conn_close(cur);
-			connkill_real(sess, &cur);
-			cur = tmp;
-		}
-	}
-
-	sess->connlist = NULL;
-
-	return;
-}
-
-/**
- * Reset a connection to default values.
- * Initializes and/or resets a connection structure.
- *
- * @param deadconn Connection to be reset
- */
-static void aim_conn_init(aim_conn_t *deadconn)
-{
-
-	if (!deadconn)
-		return;
-
-	deadconn->fd = -1;
-	deadconn->subtype = -1;
-	deadconn->type = -1;
-	deadconn->seqnum = 0;
-	deadconn->lastactivity = 0;
-	deadconn->forcedlatency = 0;
-	deadconn->handlerlist = NULL;
-	deadconn->priv = NULL;
-	memset(deadconn->inside, 0, sizeof(aim_conn_inside_t));
-
-	return;
-}
-
-/**
- * aim_conn_getnext - Gets a new connection structure.
- * @sess: Session
- *
- * Allocate a new empty connection structure.
- *
- */
-static aim_conn_t *aim_conn_getnext(aim_session_t *sess)
-{
-	aim_conn_t *newconn;
-
-	if (!(newconn = malloc(sizeof(aim_conn_t)))) 	
-		return NULL;
-	memset(newconn, 0, sizeof(aim_conn_t));
-
-	if (!(newconn->inside = malloc(sizeof(aim_conn_inside_t)))) {
-		free(newconn);
-		return NULL;
-	}
-	memset(newconn->inside, 0, sizeof(aim_conn_inside_t));
-
-	aim_conn_init(newconn);
-
-	newconn->next = sess->connlist;
-	sess->connlist = newconn;
-
-	return newconn;
-}
-
-/**
- * aim_conn_kill - Close and free a connection.
- * @sess: Session for the connection
- * @deadconn: Connection to be freed
- *
- * Close, clear, and free a connection structure. Should never be
- * called from within libfaim.
- *
- */
-faim_export void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn)
-{
-	aim_conn_t *cur, **prev;
-
-	if (!deadconn || !*deadconn)	
-		return;
-
-	for (prev = &sess->connlist; (cur = *prev); ) {
-		if (cur == *deadconn) {
-			*prev = cur->next;
-			break;
-		}
-		prev = &cur->next;
-	}
-
-	if (!cur)
-		return; /* oops */
-
-	connkill_real(sess, &cur);
-
-	return;
-}
-
-/**
- * aim_conn_close - Close a connection
- * @deadconn: Connection to close
- *
- * Close (but not free) a connection.
- *
- * This leaves everything untouched except for clearing the 
- * handler list and setting the fd to -1 (used to recognize
- * dead connections).  It will also remove cookies if necessary.
- *
- */
-faim_export void aim_conn_close(aim_conn_t *deadconn)
-{
-	aim_rxcallback_t userfunc;
-
-	if (deadconn->fd >= 3)
-		close(deadconn->fd);
-
-	deadconn->fd = -1;
-
-	if ((userfunc = aim_callhandler(deadconn->sessv, deadconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNDEAD)))
-		userfunc(deadconn->sessv, NULL, deadconn);
-
-	if (deadconn->handlerlist)
-		aim_clearhandlers(deadconn);
-
-	return;
-}
-
-/**
- * aim_getconn_type - Find a connection of a specific type
- * @sess: Session to search
- * @type: Type of connection to look for
- *
- * Searches for a connection of the specified type in the 
- * specified session.  Returns the first connection of that
- * type found.
- *
- * XXX except for RENDEZVOUS, all uses of this should be removed and
- * use aim_conn_findbygroup() instead.
- */
-faim_export aim_conn_t *aim_getconn_type(aim_session_t *sess, int type)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if ((cur->type == type) && 
-				!(cur->status & AIM_CONN_STATUS_INPROGRESS))
-			break;
-	}
-
-	return cur;
-}
-
-faim_export aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if (cur->type == type)
-			break;
-	}
-
-	return cur;
-}
-
-/* If you pass -1 for the fd, you'll get what you ask for.  Gibberish. */
-faim_export aim_conn_t *aim_getconn_fd(aim_session_t *sess, int fd)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if (cur->fd == fd)
-			break;
-	}
-
-	return cur;
-}
-
-/**
- * aim_proxyconnect - An extrememly quick and dirty SOCKS5 interface. 
- * @sess: Session to connect
- * @host: Host to connect to
- * @port: Port to connect to
- * @statusret: Return value of the connection
- *
- * Attempts to connect to the specified host via the configured
- * proxy settings, if present.  If no proxy is configured for
- * this session, the connection is done directly.
- *
- * XXX this is really awful.
- *
- */
-static int aim_proxyconnect(aim_session_t *sess, const char *host, fu16_t port, fu32_t *statusret)
-{
-	int fd = -1;
-
-	if (strlen(sess->socksproxy.server)) { /* connecting via proxy */
-		int i;
-		unsigned char buf[512];
-		struct sockaddr_in sa;
-		struct hostent *hp;
-		char *proxy;
-		unsigned short proxyport = 1080;
-
-		for(i=0;i<(int)strlen(sess->socksproxy.server);i++) {
-			if (sess->socksproxy.server[i] == ':') {
-				proxyport = atoi(&(sess->socksproxy.server[i+1]));
-				break;
-			}
-		}
-
-		proxy = (char *)malloc(i+1);
-		strncpy(proxy, sess->socksproxy.server, i);
-		proxy[i] = '\0';
-
-		if (!(hp = gethostbyname(proxy))) {
-			faimdprintf(sess, 0, "proxyconnect: unable to resolve proxy name\n");
-			*statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR);
-			return -1;
-		}
-		free(proxy);
-
-		memset(&sa.sin_zero, 0, 8);
-		sa.sin_port = htons(proxyport);
-		memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
-		sa.sin_family = hp->h_addrtype;
-
-		fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
-		if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
-			faimdprintf(sess, 0, "proxyconnect: unable to connect to proxy\n");
-			close(fd);
-			return -1;
-		}
-
-		i = 0;
-		buf[0] = 0x05; /* SOCKS version 5 */
-		if (strlen(sess->socksproxy.username)) {
-			buf[1] = 0x02; /* two methods */
-			buf[2] = 0x00; /* no authentication */
-			buf[3] = 0x02; /* username/password authentication */
-			i = 4;
-		} else {
-			buf[1] = 0x01;
-			buf[2] = 0x00;
-			i = 3;
-		}
-		if (write(fd, buf, i) < i) {
-			*statusret = errno;
-			close(fd);
-			return -1;
-		}
-		if (read(fd, buf, 2) < 2) {
-			*statusret = errno;
-			close(fd);
-			return -1;
-		}
-
-		if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
-			*statusret = EINVAL;
-			close(fd);
-			return -1;
-		}
-
-		/* check if we're doing username authentication */
-		if (buf[1] == 0x02) {
-			i  = aimutil_put8(buf, 0x01); /* version 1 */
-			i += aimutil_put8(buf+i, strlen(sess->socksproxy.username));
-			i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username));
-			i += aimutil_put8(buf+i, strlen(sess->socksproxy.password));
-			i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password));
-			if (write(fd, buf, i) < i) {
-				*statusret = errno;
-				close(fd);
-				return -1;
-			}
-			if (read(fd, buf, 2) < 2) {
-				*statusret = errno;
-				close(fd);
-				return -1;
-			}
-			if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
-				*statusret = EINVAL;
-				close(fd);
-				return -1;
-			}
-		}
-
-		i  = aimutil_put8(buf, 0x05);
-		i += aimutil_put8(buf+i, 0x01); /* CONNECT */
-		i += aimutil_put8(buf+i, 0x00); /* reserved */
-		i += aimutil_put8(buf+i, 0x03); /* address type: host name */
-		i += aimutil_put8(buf+i, strlen(host));
-		i += aimutil_putstr(buf+i, host, strlen(host));
-		i += aimutil_put16(buf+i, port);
-
-		if (write(fd, buf, i) < i) {
-			*statusret = errno;
-			close(fd);
-			return -1;
-		}
-
-		if (read(fd, buf, 10) < 10) {
-			*statusret = errno;
-			close(fd);
-			return -1;
-		}
-		if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
-			*statusret = EINVAL;
-			close(fd);
-			return -1;
-		}
-
-	} else { /* connecting directly */
-		struct sockaddr_in sa;
-		struct hostent *hp;
-
-		if (!(hp = gethostbyname(host))) {
-			*statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR);
-			return -1;
-		}
-
-		memset(&sa, 0, sizeof(struct sockaddr_in));
-		sa.sin_port = htons(port);
-		memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
-		sa.sin_family = hp->h_addrtype;
-
-		fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
-
-		if (sess->nonblocking)
-			fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */
-
-		if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) {
-			if (sess->nonblocking) {
-				if ((errno == EINPROGRESS) || (errno == EINTR)) {
-					if (statusret)
-						*statusret |= AIM_CONN_STATUS_INPROGRESS;
-					return fd;
-				}
-			}
-			close(fd);
-			fd = -1;
-		}
-	}
-	return fd;
-}
-
-/**
- * aim_cloneconn - clone an aim_conn_t
- * @sess: session containing parent
- * @src: connection to clone
- *
- * A new connection is allocated, and the values are filled in
- * appropriately. Note that this function sets the new connnection's
- * ->priv pointer to be equal to that of its parent: only the pointer
- * is copied, not the data it points to.
- *
- * This function returns a pointer to the new aim_conn_t, or %NULL on
- * error
- */
-faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src)
-{
-	aim_conn_t *conn;
-
-	if (!(conn = aim_conn_getnext(sess)))
-		return NULL;
-
-	conn->fd = src->fd;
-	conn->type = src->type;
-	conn->subtype = src->subtype;
-	conn->seqnum = src->seqnum;
-	conn->priv = src->priv;
-	conn->internal = src->internal;
-	conn->lastactivity = src->lastactivity;
-	conn->forcedlatency = src->forcedlatency;
-	conn->sessv = src->sessv;
-	aim_clonehandlers(sess, conn, src);
-
-	if (src->inside) {
-		/*
-		 * XXX should clone this section as well, but since currently
-		 * this function only gets called for some of that rendezvous
-		 * crap, and not on SNAC connections, its probably okay for
-		 * now. 
-		 *
-		 */
-	}
-
-	return conn;
-}
-
-/**
- * aim_newconn - Open a new connection
- * @sess: Session to create connection in
- * @type: Type of connection to create
- * @dest: Host to connect to (in "host:port" syntax)
- *
- * Opens a new connection to the specified dest host of specified
- * type, using the proxy settings if available.  If @host is %NULL,
- * the connection is allocated and returned, but no connection 
- * is made.
- *
- * FIXME: Return errors in a more sane way.
- *
- */
-faim_export aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest)
-{
-	aim_conn_t *connstruct;
-	fu16_t port = FAIM_LOGIN_PORT;
-	char *host;
-	int i, ret;
-
-	if (!(connstruct = aim_conn_getnext(sess)))
-		return NULL;
-
-	connstruct->sessv = (void *)sess;
-	connstruct->type = type;
-
-	if (!dest) { /* just allocate a struct */
-		connstruct->fd = -1;
-		connstruct->status = 0;
-		return connstruct;
-	}
-
-	/* 
-	 * As of 23 Jul 1999, AOL now sends the port number, preceded by a 
-	 * colon, in the BOS redirect.  This fatally breaks all previous 
-	 * libfaims.  Bad, bad AOL.
-	 *
-	 * We put this here to catch every case. 
-	 *
-	 */
-
-	for(i = 0; i < (int)strlen(dest); i++) {
-		if (dest[i] == ':') {
-			port = atoi(&(dest[i+1]));
-			break;
-		}
-	}
-
-	host = (char *)malloc(i+1);
-	strncpy(host, dest, i);
-	host[i] = '\0';
-
-	if ((ret = aim_proxyconnect(sess, host, port, &connstruct->status)) < 0) {
-		connstruct->fd = -1;
-		connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
-		free(host);
-		return connstruct;
-	} else
-		connstruct->fd = ret;
-
-	free(host);
-
-	return connstruct;
-}
-
-/**
- * aim_conngetmaxfd - Return the highest valued file discriptor in session
- * @sess: Session to search
- *
- * Returns the highest valued filed descriptor of all open 
- * connections in @sess.
- *
- */
-faim_export int aim_conngetmaxfd(aim_session_t *sess)
-{
-	int j;
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist, j = 0; cur; cur = cur->next) {
-		if (cur->fd > j)
-			j = cur->fd;
-	}
-
-	return j;
-}
-
-/**
- * aim_conn_in_sess - Predicate to test the precense of a connection in a sess
- * @sess: Session to look in
- * @conn: Connection to look for
- *
- * Searches @sess for the passed connection.  Returns 1 if its present,
- * zero otherwise.
- *
- */
-faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if (cur == conn)
-			return 1;
-	}
-
-	return 0;
-}
-
-/**
- * aim_select - Wait for a socket with data or timeout
- * @sess: Session to wait on
- * @timeout: How long to wait
- * @status: Return status
- *
- * Waits for a socket with data or for timeout, whichever comes first.
- * See select(2).
- * 
- * Return codes in *status:
- *   -1  error in select() (%NULL returned)
- *    0  no events pending (%NULL returned)
- *    1  outgoing data pending (%NULL returned)
- *    2  incoming data pending (connection with pending data returned)
- *
- */ 
-faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout, int *status)
-{
-	aim_conn_t *cur;
-	fd_set fds, wfds;
-	int maxfd, i, haveconnecting = 0;
-
-	if (!sess->connlist) {
-		*status = -1;
-		return NULL;
-	}
-
-	FD_ZERO(&fds);
-	FD_ZERO(&wfds);
-
-	for (cur = sess->connlist, maxfd = 0; cur; cur = cur->next) {
-		if (cur->fd == -1) {
-			/* don't let invalid/dead connections sit around */
-			*status = 2;
-			return cur;
-		} else if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
-			FD_SET(cur->fd, &wfds);
-
-			haveconnecting++;
-		}
-		FD_SET(cur->fd, &fds);
-		if (cur->fd > maxfd)
-			maxfd = cur->fd;
-	}
-
-	/* 
-	 * If we have data waiting to be sent, return
-	 *
-	 * We have to not do this if theres at least one
-	 * connection thats still connecting, since that connection
-	 * may have queued data and this return would prevent
-	 * the connection from ever completing!  This is a major
-	 * inadequacy of the libfaim way of doing things.  It means
-	 * that nothing can transmit as long as there's connecting
-	 * sockets. Evil.
-	 *
-	 * But its still better than having blocking connects.
-	 *
-	 */
-	if (!haveconnecting && sess->queue_outgoing) {
-		*status = 1;
-		return NULL;
-	} 
-
-	if ((i = select(maxfd+1, &fds, &wfds, NULL, timeout))>=1) {
-		for (cur = sess->connlist; cur; cur = cur->next) {
-			if ((FD_ISSET(cur->fd, &fds)) || 
-					((cur->status & AIM_CONN_STATUS_INPROGRESS) && 
-					FD_ISSET(cur->fd, &wfds))) {
-				*status = 2;
-				return cur;
-			}
-		}
-		*status = 0; /* shouldn't happen */
-	} else if ((i == -1) && (errno == EINTR)) /* treat interrupts as a timeout */
-		*status = 0;
-	else
-		*status = i; /* can be 0 or -1 */
-
-	return NULL;  /* no waiting or error, return */
-}
-
-/**
- * aim_conn_setlatency - Set a forced latency value for connection
- * @conn: Conn to set latency for
- * @newval: Number of seconds to force between transmits
- *
- * Causes @newval seconds to be spent between transmits on a connection.
- *
- * This is my lame attempt at overcoming not understanding the rate
- * limiting. 
- *
- * XXX: This should really be replaced with something that scales and
- * backs off like the real rate limiting does.
- *
- */
-faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval)
-{
-
-	if (!conn)
-		return -1;
-
-	conn->forcedlatency = newval;
-	conn->lastactivity = 0; /* reset this just to make sure */
-
-	return 0;
-}
-
-/**
- * aim_setupproxy - Configure a proxy for this session
- * @sess: Session to set proxy for
- * @server: SOCKS server
- * @username: SOCKS username
- * @password: SOCKS password
- *
- * Call this with your SOCKS5 proxy server parameters before
- * the first call to aim_newconn().  If called with all %NULL
- * args, it will clear out a previously set proxy.  
- *
- * Set username and password to %NULL if not applicable.
- *
- */
-faim_export void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password)
-{
-	/* clear out the proxy info */
-	if (!server || !strlen(server)) {
-		memset(sess->socksproxy.server, 0, sizeof(sess->socksproxy.server));
-		memset(sess->socksproxy.username, 0, sizeof(sess->socksproxy.username));
-		memset(sess->socksproxy.password, 0, sizeof(sess->socksproxy.password));
-		return;
-	}
-
-	strncpy(sess->socksproxy.server, server, sizeof(sess->socksproxy.server));
-	if (username && strlen(username)) 
-		strncpy(sess->socksproxy.username, username, sizeof(sess->socksproxy.username));
-	if (password && strlen(password))
-		strncpy(sess->socksproxy.password, password, sizeof(sess->socksproxy.password));
-
-	return;
-}
-
-static void defaultdebugcb(aim_session_t *sess, int level, const char *format, va_list va)
-{
-
-	vfprintf(stderr, format, va);
-
-	return;
-}
-
-/**
- * Initializes a session structure by setting the initial values 
- * stuff in the aim_session_t struct.
- *
- * @param sess Session to initialize.
- * @param nonblocking Set to true if you want connections to be non-blocking.
- * @param debuglevel Level of debugging output (zero is least).
- */
-faim_export void aim_session_init(aim_session_t *sess, bool nonblocking, int debuglevel)
-{
-
-	if (!sess)
-		return;
-
-	memset(sess, 0, sizeof(aim_session_t));
-	aim_connrst(sess);
-	sess->queue_outgoing = NULL;
-	sess->queue_incoming = NULL;
-	aim_initsnachash(sess);
-	sess->msgcookies = NULL;
-	sess->nonblocking = nonblocking;
-	sess->debug = debuglevel;
-	sess->debugcb = defaultdebugcb;
-	sess->modlistv = NULL;
-	sess->snacid_next = 0x00000001;
-
-	sess->locate.userinfo = NULL;
-	sess->locate.torequest = NULL;
-	sess->locate.requested = NULL;
-	sess->locate.waiting_for_response = FALSE;
-	sess->ssi.received_data = 0;
-	sess->ssi.numitems = 0;
-	sess->ssi.official = NULL;
-	sess->ssi.local = NULL;
-	sess->ssi.pending = NULL;
-	sess->ssi.timestamp = (time_t)0;
-	sess->ssi.waiting_for_ack = 0;
-	sess->icq_info = NULL;
-	sess->authinfo = NULL;
-	sess->emailinfo = NULL;
-	sess->oft_info = NULL;
-
-	/*
-	 * This must always be set.  Default to the queue-based
-	 * version for back-compatibility.  
-	 */
-	aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL);
-
-	/*
-	 * Register all the modules for this session...
-	 */
-	aim__registermodule(sess, misc_modfirst); /* load the catch-all first */
-	aim__registermodule(sess, service_modfirst);
-	aim__registermodule(sess, locate_modfirst);
-	aim__registermodule(sess, buddylist_modfirst);
-	aim__registermodule(sess, msg_modfirst);
-	aim__registermodule(sess, adverts_modfirst);
-	aim__registermodule(sess, invite_modfirst);
-	aim__registermodule(sess, admin_modfirst);
-	aim__registermodule(sess, popups_modfirst);
-	aim__registermodule(sess, bos_modfirst);
-	aim__registermodule(sess, search_modfirst);
-	aim__registermodule(sess, stats_modfirst);
-	aim__registermodule(sess, translate_modfirst);
-	aim__registermodule(sess, chatnav_modfirst);
-	aim__registermodule(sess, chat_modfirst);
-	aim__registermodule(sess, odir_modfirst);
-	aim__registermodule(sess, bart_modfirst);
-	/* missing 0x11 - 0x12 */
-	aim__registermodule(sess, ssi_modfirst);
-	/* missing 0x14 */
-	aim__registermodule(sess, icq_modfirst); /* XXX - Make sure this isn't sent for AIM */
-	/* missing 0x16 */
-	aim__registermodule(sess, auth_modfirst);
-	aim__registermodule(sess, email_modfirst);
-
-	return;
-}
-
-/**
- * aim_session_kill - Deallocate a session
- * @sess: Session to kill
- *
- */
-faim_export void aim_session_kill(aim_session_t *sess)
-{
-	aim_cleansnacs(sess, -1);
-
-	aim_logoff(sess);
-
-	aim__shutdownmodules(sess);
-
-	return;
-}
-
-/**
- * aim_setdebuggingcb - Set the function to call when outputting debugging info
- * @sess: Session to change
- * @cb: Function to call
- *
- * The function specified is called whenever faimdprintf() is used within
- * libfaim, and the session's debugging level is greater tha nor equal to
- * the value faimdprintf was called with.
- *
- */
-faim_export int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t cb)
-{
-
-	if (!sess)
-		return -1;
-
-	sess->debugcb = cb;
-
-	return 0;
-}
-
-/**
- * aim_conn_isconnecting - Determine if a connection is connecting
- * @conn: Connection to examine
- *
- * Returns nonzero if the connection is in the process of
- * connecting (or if it just completed and aim_conn_completeconnect()
- * has yet to be called on it).
- *
- */
-faim_export int aim_conn_isconnecting(aim_conn_t *conn)
-{
-
-	if (!conn)
-		return 0;
-
-	return !!(conn->status & AIM_CONN_STATUS_INPROGRESS);
-}
-
-/*
- * XXX this is nearly as ugly as proxyconnect().
- */
-faim_export int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_rxcallback_t userfunc;
-
-	if (!conn || (conn->fd == -1))
-		return -1;
-
-	if (!(conn->status & AIM_CONN_STATUS_INPROGRESS))
-		return -1;
-
-	fcntl(conn->fd, F_SETFL, 0);
-
-	conn->status &= ~AIM_CONN_STATUS_INPROGRESS;
-
-	if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE)))
-		userfunc(sess, NULL, conn);
-
-	/* Flush out the queues if there was something waiting for this conn  */
-	aim_tx_flushqueue(sess);
-
-	return 0;
-}
-
-faim_export aim_session_t *aim_conn_getsess(aim_conn_t *conn)
-{
-
-	if (!conn)
-		return NULL;
-
-	return (aim_session_t *)conn->sessv;
-}
-
-/*
- * aim_logoff()
- *
- * Closes -ALL- open connections.
- *
- */
-faim_export int aim_logoff(aim_session_t *sess)
-{
-
-	aim_connrst(sess);  /* in case we want to connect again */
-
-	return 0;
-}
-
-/*
- * aim_flap_nop()
- *
- * No-op.  WinAIM 4.x sends these _every minute_ to keep
- * the connection alive.
- */
-faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0)))
-		return -ENOMEM;
-
-	aim_tx_enqueue(sess, fr);
-
-	/* clean out SNACs over 60sec old */
-	aim_cleansnacs(sess, 60);
-
-	return 0;
-}
Index: bfaim/email.c
===================================================================
--- libfaim/email.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,216 +1,0 @@
-/*
- * Family 0x0018 - Email notification
- *
- * Used for being alerted when the email address(es) associated with 
- * your screen name get new electronic-m.  For normal AIM accounts, you 
- * get the email address screenname@netscape.net.  AOL accounts have 
- * screenname@aol.com, and can also activate a netscape.net account.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/**
- * Subtype 0x0006 - Request information about your email account
- *
- * @param sess The oscar session.
- * @param conn The email connection for this session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_email_sendcookies(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_EML)))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16+16)))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x0018, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0018, 0x0006, 0x0000, snacid);
-
-	/* Number of cookies to follow */
-	aimbs_put16(&fr->data, 0x0002);
-
-	/* Cookie */
-	aimbs_put16(&fr->data, 0x5d5e);
-	aimbs_put16(&fr->data, 0x1708);
-	aimbs_put16(&fr->data, 0x55aa);
-	aimbs_put16(&fr->data, 0x11d3);
-	aimbs_put16(&fr->data, 0xb143);
-	aimbs_put16(&fr->data, 0x0060);
-	aimbs_put16(&fr->data, 0xb0fb);
-	aimbs_put16(&fr->data, 0x1ecb);
-
-	/* Cookie */
-	aimbs_put16(&fr->data, 0xb380);
-	aimbs_put16(&fr->data, 0x9ad8);
-	aimbs_put16(&fr->data, 0x0dba);
-	aimbs_put16(&fr->data, 0x11d5);
-	aimbs_put16(&fr->data, 0x9f8a);
-	aimbs_put16(&fr->data, 0x0060);
-	aimbs_put16(&fr->data, 0xb0ee);
-	aimbs_put16(&fr->data, 0x0631);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-
-/**
- * Subtype 0x0007 - Receive information about your email account
- *
- * So I don't even know if you can have multiple 16 byte keys, 
- * but this is coded so it will handle that, and handle it well.
- * This tells you if you have unread mail or not, the URL you 
- * should use to access that mail, and the domain name for the 
- * email account (screenname@domainname.com).  If this is the 
- * first 0x0007 SNAC you've received since you signed on, or if 
- * this is just a periodic status update, this will also contain 
- * the number of unread emails that you have.
- */
-static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	struct aim_emailinfo *new;
-	aim_tlvlist_t *tlvlist;
-	fu8_t *cookie8, *cookie16;
-	int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
-
-	char *alertitle = NULL, *alerturl = NULL;
-
-	cookie8 = aimbs_getraw(bs, 8); /* Possibly the code used to log you in to mail? */
-	cookie16 = aimbs_getraw(bs, 16); /* Mail cookie sent above */
-
-	/* See if we already have some info associated with this cookie */
-	for (new=sess->emailinfo; (new && strncmp(cookie16, new->cookie16, 16)); new=new->next);
-	if (new) {
-		/* Free some of the old info, if existant */
-		free(new->cookie8);
-		free(new->cookie16);
-		free(new->url);
-		free(new->domain);
-	} else {
-		/* We don't already have info, so create a new struct for it */
-		if (!(new = malloc(sizeof(struct aim_emailinfo))))
-			return -ENOMEM;
-		memset(new, 0, sizeof(struct aim_emailinfo));
-		new->next = sess->emailinfo;
-		sess->emailinfo = new;
-	}
-
-	new->cookie8 = cookie8;
-	new->cookie16 = cookie16;
-
-	tlvlist = aim_tlvlist_readnum(bs, aimbs_get16(bs));
-
-	tmp = aim_tlv_get16(tlvlist, 0x0080, 1);
-	if (tmp) {
-		if (new->nummsgs < tmp)
-			havenewmail = 1;
-		new->nummsgs = tmp;
-	} else {
-		/* If they don't send a 0x0080 TLV, it means we definately have new mail */
-		/* (ie. this is not just another status update) */
-		havenewmail = 1;
-		new->nummsgs++; /* We know we have at least 1 new email */
-	}
-	new->url = aim_tlv_getstr(tlvlist, 0x0007, 1);
-	if (!(new->unread = aim_tlv_get8(tlvlist, 0x0081, 1))) {
-		havenewmail = 0;
-		new->nummsgs = 0;
-	}
-	new->domain = aim_tlv_getstr(tlvlist, 0x0082, 1);
-	new->flag = aim_tlv_get16(tlvlist, 0x0084, 1);
-
-	alertitle = aim_tlv_getstr(tlvlist, 0x0005, 1);
-	alerturl  = aim_tlv_getstr(tlvlist, 0x000d, 1);
-	
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL));
-
-	aim_tlvlist_free(&tlvlist);
-
-	free(alertitle);
-	free(alerturl);
-
-	return ret;
-}
-
-/**
- * Subtype 0x0016 - Send something or other
- *
- * @param sess The oscar session.
- * @param conn The email connection for this session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_email_activate(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_EML)))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+16)))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x0018, 0x0016, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0018, 0x0016, 0x0000, snacid);
-
-	/* I would guess this tells AIM that you want updates for your mail accounts */
-	/* ...but I really have no idea */
-	aimbs_put8(&fr->data, 0x02);
-	aimbs_put32(&fr->data, 0x04000000);
-	aimbs_put32(&fr->data, 0x04000000);
-	aimbs_put32(&fr->data, 0x04000000);
-	aimbs_put32(&fr->data, 0x00000000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0007)
-		return parseinfo(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-static void email_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	while (sess->emailinfo) {
-		struct aim_emailinfo *tmp = sess->emailinfo;
-		sess->emailinfo = sess->emailinfo->next;
-		free(tmp->cookie16);
-		free(tmp->cookie8);
-		free(tmp->url);
-		free(tmp->domain);
-		free(tmp);
-	}
-
-	return;
-}
-
-faim_internal int email_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0018;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "email", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = email_shutdown;
-
-	return 0;
-}
Index: bfaim/faimconfig.h
===================================================================
--- libfaim/faimconfig.h	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- *  faimconfig.h
- *
- * Contains various compile-time options that apply _only_ to libfaim.
- *
- */
-
-#ifndef __FAIMCONFIG_H__
-#define __FAIMCONFIG_H__
-
-/*
- * USE_SNAC_FOR_IMS is an old feature that allowed better
- * tracking of error messages by caching SNAC IDs of outgoing
- * ICBMs and comparing them to incoming errors.  However,
- * its a helluvalot of overhead for something that should
- * rarely happen.  
- *
- * Default: defined.  This is now defined by default
- * because it should be stable and its not too bad.  
- * And Josh wanted it.
- *
- */
-#define USE_SNAC_FOR_IMS
-
-/*
- * Default Authorizer server name and TCP port for the OSCAR farm.  
- *
- * You shouldn't need to change this unless you're writing
- * your own server. 
- *
- * Note that only one server is needed to start the whole
- * AIM process.  The later server addresses come from
- * the authorizer service.
- *
- * This is only here for convenience.  Its still up to
- * the client to connect to it.
- *
- */
-#define FAIM_LOGIN_SERVER "login.oscar.aol.com"
-#define FAIM_LOGIN_PORT 5190
-
-/*
- * Size of the SNAC caching hash.
- *
- * Default: 16
- *
- */
-#define FAIM_SNAC_HASH_SIZE 16
-
-/*
- * If building on Win32, define WIN32_STATIC if you don't want
- * to compile libfaim as a DLL (and instead link it right into
- * your app).
- */
-#define WIN32_STATIC
-
-#endif /* __FAIMCONFIG_H__ */
-
-
Index: bfaim/ft.c
===================================================================
--- libfaim/ft.c	(revision dd0edbf4e5ea467a25debc666f9fadc1317b7f0c)
+++ 	(revision )
@@ -1,993 +1,0 @@
-/*
- * Oscar File transfer (OFT) and Oscar Direct Connect (ODC).
- * (ODC is also referred to as DirectIM and IM Image.)
- *
- * There are a few static helper functions at the top, then 
- * ODC stuff, then ft stuff.
- *
- * I feel like this is a good place to explain OFT, so I'm going to 
- * do just that.  Each OFT packet has a header type.  I guess this 
- * is pretty similar to the subtype of a SNAC packet.  The type 
- * basically tells the other client the meaning of the OFT packet.  
- * There are two distinct types of file transfer, which I usually 
- * call "sendfile" and "getfile."  Sendfile is when you send a file 
- * to another AIM user.  Getfile is when you share a group of files, 
- * and other users request that you send them the files.
- *
- * A typical sendfile file transfer goes like this:
- *   1) Sender sends a channel 2 ICBM telling the other user that 
- *      we want to send them a file.  At the same time, we open a 
- *      listener socket (this should be done before sending the 
- *      ICBM) on some port, and wait for them to connect to us.  
- *      The ICBM we sent should contain our IP address and the port 
- *      number that we're listening on.
- *   2) The receiver connects to the sender on the given IP address 
- *      and port.  After the connection is established, the receiver 
- *      sends an ICBM signifying that we are ready and waiting.
- *   3) The sender sends an OFT PROMPT message over the OFT 
- *      connection.
- *   4) The receiver of the file sends back an exact copy of this 
- *      OFT packet, except the cookie is filled in with the cookie 
- *      from the ICBM.  I think this might be an attempt to verify 
- *      that the user that is connected is actually the guy that 
- *      we sent the ICBM to.  Oh, I've been calling this the ACK.
- *   5) The sender starts sending raw data across the connection 
- *      until the entire file has been sent.
- *   6) The receiver knows the file is finished because the sender 
- *      sent the file size in an earlier OFT packet.  So then the 
- *      receiver sends the DONE thingy (after filling in the 
- *      "received" checksum and size) and closes the connection.
- */
-
-#define FAIM_INTERNAL
-#ifdef HAVE_CONFIG_H
-#include  <config.h>
-#endif
-
-#include <aim.h>
-
-#ifndef _WIN32
-#include <stdio.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/utsname.h> /* for aim_odc_initiate */
-#include <arpa/inet.h> /* for inet_ntoa */
-#define G_DIR_SEPARATOR '/'
-#endif
-
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-#ifndef socklen_t
-#define socklen_t int
-#endif
-
-struct aim_odc_intdata {
-	fu8_t cookie[8];
-	char sn[MAXSNLEN+1];
-	char ip[22];
-};
-
-/**
- * Convert the directory separator from / (0x2f) to ^A (0x01)
- *
- * @param name The filename to convert.
- */
-static void aim_oft_dirconvert_tostupid(char *name)
-{
-	while (name[0]) {
-		if (name[0] == 0x01)
-			name[0] = G_DIR_SEPARATOR;
-		name++;
-	}
-}
-
-/**
- * Convert the directory separator from ^A (0x01) to / (0x2f)
- *
- * @param name The filename to convert.
- */
-static void aim_oft_dirconvert_fromstupid(char *name)
-{
-	while (name[0]) {
-		if (name[0] == G_DIR_SEPARATOR)
-			name[0] = 0x01;
-		name++;
-	}
-}
-
-/**
- * Calculate oft checksum of buffer
- *
- * Prevcheck should be 0xFFFF0000 when starting a checksum of a file.  The 
- * checksum is kind of a rolling checksum thing, so each time you get bytes 
- * of a file you just call this puppy and it updates the checksum.  You can 
- * calculate the checksum of an entire file by calling this in a while or a 
- * for loop, or something.
- *
- * Thanks to Graham Booker for providing this improved checksum routine, 
- * which is simpler and should be more accurate than Josh Myer's original 
- * code. -- wtm
- *
- * This algorithim works every time I have tried it.  The other fails 
- * sometimes.  So, AOL who thought this up?  It has got to be the weirdest 
- * checksum I have ever seen.
- *
- * @param buffer Buffer of data to checksum.  Man I'd like to buff her...
- * @param bufsize Size of buffer.
- * @param prevcheck Previous checksum.
- */
-faim_export fu32_t aim_oft_checksum_chunk(const fu8_t *buffer, int bufferlen, fu32_t prevcheck)
-{
-	fu32_t check = (prevcheck >> 16) & 0xffff, oldcheck;
-	int i;
-	unsigned short val;
-
-	for (i=0; i<bufferlen; i++) {
-		oldcheck = check;
-		if (i&1)
-			val = buffer[i];
-		else
-			val = buffer[i] << 8;
-		check -= val;
-		/*
-		 * The following appears to be necessary.... It happens 
-		 * every once in a while and the checksum doesn't fail.
-		 */
-		if (check > oldcheck)
-			check--;
-	}
-	check = ((check & 0x0000ffff) + (check >> 16));
-	check = ((check & 0x0000ffff) + (check >> 16));
-	return check << 16;
-}
-
-faim_export fu32_t aim_oft_checksum_file(char *filename) {
-	FILE *fd;
-	fu32_t checksum = 0xffff0000;
-
-	if ((fd = fopen(filename, "rb"))) {
-		int bytes;
-		fu8_t buffer[1024];
-
-		while ((bytes = fread(buffer, 1, 1024, fd)))
-			checksum = aim_oft_checksum_chunk(buffer, bytes, checksum);
-		fclose(fd);
-	}
-
-	return checksum;
-}
-
-/**
- * Create a listening socket on a given port.
- *
- * XXX - Give the client author the responsibility of setting up a 
- *       listener, then we no longer have a libfaim problem with broken 
- *       solaris *innocent smile* -- jbm
- *
- * @param portnum The port number to bind to.
- * @return The file descriptor of the listening socket.
- */
-static int listenestablish(fu16_t portnum)
-{
-#if HAVE_GETADDRINFO
-	int listenfd;
-	const int on = 1;
-	struct addrinfo hints, *res, *ressave;
-	char serv[5];
-
-	snprintf(serv, sizeof(serv), "%d", portnum);
-	memset(&hints, 0, sizeof(struct addrinfo));
-	hints.ai_flags = AI_PASSIVE;
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-	if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) {
-		perror("getaddrinfo");
-		return -1;
-	} 
-	ressave = res;
-	do { 
-		listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-		if (listenfd < 0)
-			continue;
-		setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-		if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
-			break; /* success */
-		close(listenfd);
-	} while ( (res = res->ai_next) );
-
-	if (!res)
-		return -1;
-
-	freeaddrinfo(ressave);
-#else
-	int listenfd;
-	const int on = 1;
-	struct sockaddr_in sockin;
-
-	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket");
-		return -1;
-	}
-
-	if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) {
-		perror("setsockopt");
-		close(listenfd);
-		return -1;
-	}
-
-	memset(&sockin, 0, sizeof(struct sockaddr_in));
-	sockin.sin_family = AF_INET;
-	sockin.sin_port = htons(portnum);
-
-	if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) {
-		perror("bind");
-		close(listenfd);
-		return -1;
-	}
-#endif
-
-	if (listen(listenfd, 4) != 0) {
-		perror("listen");
-		close(listenfd);
-		return -1;
-	}
-	fcntl(listenfd, F_SETFL, O_NONBLOCK);
-
-	return listenfd;
-}
-
-/**
- * After establishing a listening socket, this is called to accept a connection.  It
- * clones the conn used by the listener, and passes both of these to a signal handler.
- * The signal handler should close the listener conn and keep track of the new conn,
- * since this is what is used for file transfers and what not.
- *
- * @param sess The session.
- * @param cur The conn the incoming connection is on.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur)
-{
-	int acceptfd = 0;
-	struct sockaddr addr;
-	socklen_t addrlen = sizeof(addr);
-	int ret = 0;
-	aim_conn_t *newconn;
-	char ip[20];
-	int port;
-
-	if ((acceptfd = accept(cur->fd, &addr, &addrlen)) == -1)
-		return 0; /* not an error */
-
-	if ((addr.sa_family != AF_INET) && (addr.sa_family != AF_INET6)) { /* just in case IPv6 really is happening */
-		close(acceptfd);
-		aim_conn_close(cur);
-		return -1;
-	}
-
-	strncpy(ip, inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr), sizeof(ip));
-	port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
-
-	if (!(newconn = aim_cloneconn(sess, cur))) {
-		close(acceptfd);
-		aim_conn_close(cur);
-		return -ENOMEM;
-	}
-
-	newconn->type = AIM_CONN_TYPE_RENDEZVOUS;
-	newconn->fd = acceptfd;
-
-	if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
-		aim_rxcallback_t userfunc;
-		struct aim_odc_intdata *priv;
-
-		priv = (struct aim_odc_intdata *)(newconn->internal = cur->internal);
-		cur->internal = NULL;
-		snprintf(priv->ip, sizeof(priv->ip), "%s:%u", ip, port);
-
-		if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED)))
-			ret = userfunc(sess, NULL, newconn, cur);
-
-	} else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
-	} else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
-		aim_rxcallback_t userfunc;
-
-		if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED)))
-			ret = userfunc(sess, NULL, newconn, cur);
-
-	} else {
-		faimdprintf(sess, 1,"Got a connection on a listener that's not rendezvous.  Closing connection.\n");
-		aim_conn_close(newconn);
-		ret = -1;
-	}
-
-	return ret;
-}
-
-/**
- * Send client-to-client typing notification over an established direct connection.
- *
- * @param sess The session.
- * @param conn The already-connected ODC connection.
- * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and 
- *        0x0000 sends "stopped."
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing)
-{
-	struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal;
-	aim_frame_t *fr;
-	aim_bstream_t *hdrbs;
-	fu8_t *hdr;
-	int hdrlen = 0x44;
-
-	if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0001, 0)))
-		return -ENOMEM;
-	memcpy(fr->hdr.rend.magic, "ODC2", 4);
-	fr->hdr.rend.hdrlen = hdrlen;
-
-	if (!(hdr = calloc(1, hdrlen))) {
-		aim_frame_destroy(fr);
-		return -ENOMEM;
-	}
-
-	hdrbs = &(fr->data);
-	aim_bstream_init(hdrbs, hdr, hdrlen);
-
-	aimbs_put16(hdrbs, 0x0006);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_putraw(hdrbs, intdata->cookie, 8);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put32(hdrbs, 0x00000000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-
-	if (typing == 0x0002)
-		aimbs_put16(hdrbs, 0x0002 | 0x0008);
-	else if (typing == 0x0001)
-		aimbs_put16(hdrbs, 0x0002 | 0x0004);
-	else
-		aimbs_put16(hdrbs, 0x0002);
-
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn));
-
-	aim_bstream_setpos(hdrbs, 52); /* bleeehh */
-
-	aimbs_put8(hdrbs, 0x00);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put8(hdrbs, 0x00);
-
-	/* end of hdr */
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Send client-to-client IM over an established direct connection.
- * Call this just like you would aim_send_im, to send a directim.
- * 
- * @param sess The session.
- * @param conn The already-connected ODC connection.
- * @param msg Null-terminated string to send.
- * @param len The length of the message to send, including binary data.
- * @param encoding 0 for ascii, 2 for Unicode, 3 for ISO 8859-1.
- * @param isawaymsg 0 if this is not an auto-response, 1 if it is.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg)
-{
-	aim_frame_t *fr;
-	aim_bstream_t *hdrbs;
-	struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal;
-	int hdrlen = 0x44;
-	fu8_t *hdr;
-
-	if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !msg)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0)))
-		return -ENOMEM;
-
-	memcpy(fr->hdr.rend.magic, "ODC2", 4);
-	fr->hdr.rend.hdrlen = hdrlen;
-
-	if (!(hdr = calloc(1, hdrlen + len))) {
-		aim_frame_destroy(fr);
-		return -ENOMEM;
-	}
-
-	hdrbs = &(fr->data);
-	aim_bstream_init(hdrbs, hdr, hdrlen + len);
-
-	aimbs_put16(hdrbs, 0x0006);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_putraw(hdrbs, intdata->cookie, 8);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put32(hdrbs, len);
-	aimbs_put16(hdrbs, encoding);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-
-	/* flags - used for typing notification and to mark if this is an away message */
-	aimbs_put16(hdrbs, 0x0000 | isawaymsg);
-
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_putraw(hdrbs, sess->sn, strlen(sess->sn));
-
-	aim_bstream_setpos(hdrbs, 52); /* bleeehh */
-
-	aimbs_put8(hdrbs, 0x00);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put8(hdrbs, 0x00);
-
-	/* end of hdr2 */
-
-#if 0 /* XXX - this is how you send buddy icon info... */	
-	aimbs_put16(hdrbs, 0x0008);
-	aimbs_put16(hdrbs, 0x000c);
-	aimbs_put16(hdrbs, 0x0000);
-	aimbs_put16(hdrbs, 0x1466);
-	aimbs_put16(hdrbs, 0x0001);
-	aimbs_put16(hdrbs, 0x2e0f);
-	aimbs_put16(hdrbs, 0x393e);
-	aimbs_put16(hdrbs, 0xcac8);
-#endif
-	aimbs_putraw(hdrbs, msg, len);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Get the screen name of the peer of a direct connection.
- * 
- * @param conn The ODC connection.
- * @return The screen name of the dude, or NULL if there was an anomaly.
- */
-faim_export const char *aim_odc_getsn(aim_conn_t *conn)
-{
-	struct aim_odc_intdata *intdata;
-
-	if (!conn || !conn->internal)
-		return NULL;
-
-	if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || 
-			(conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM))
-		return NULL;
-
-	intdata = (struct aim_odc_intdata *)conn->internal;
-
-	return intdata->sn;
-}
-
-/**
- * Find the conn of a direct connection with the given buddy.
- *
- * @param sess The session.
- * @param sn The screen name of the buddy whose direct connection you want to find.
- * @return The conn for the direct connection with the given buddy, or NULL if no 
- *         connection was found.
- */
-faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn)
-{
-	aim_conn_t *cur;
-	struct aim_odc_intdata *intdata;
-
-	if (!sess || !sn || !strlen(sn))
-		return NULL;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if ((cur->type == AIM_CONN_TYPE_RENDEZVOUS) && (cur->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) {
-			intdata = cur->internal;
-			if (!aim_sncmp(intdata->sn, sn))
-				return cur;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * For those times when we want to open up the direct connection channel ourselves.
- *
- * You'll want to set up some kind of watcher on this socket.  
- * When the state changes, call aim_handlerendconnection with 
- * the connection returned by this.  aim_handlerendconnection 
- * will accept the pending connection and stop listening.
- *
- * @param sess The session
- * @param sn The screen name to connect to.
- * @return The new connection.
- */
-faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn)
-{
-	aim_conn_t *newconn;
-	aim_msgcookie_t *cookie;
-	struct aim_odc_intdata *priv;
-	int listenfd;
-	fu16_t port = 4443;
-	fu8_t localip[4];
-	fu8_t ck[8];
-
-	if (aim_util_getlocalip(localip) == -1)
-		return NULL;
-
-	if ((listenfd = listenestablish(port)) == -1)
-		return NULL;
-
-	aim_im_sendch2_odcrequest(sess, ck, sn, localip, port);
-
-	cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t));
-	memcpy(cookie->cookie, ck, 8);
-	cookie->type = AIM_COOKIETYPE_OFTIM;
-
-	/* this one is for the cookie */
-	priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata));
-
-	memcpy(priv->cookie, ck, 8);
-	strncpy(priv->sn, sn, sizeof(priv->sn));
-	cookie->data = priv;
-	aim_cachecookie(sess, cookie);
-
-	/* XXX - switch to aim_cloneconn()? */
-	if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) {
-		close(listenfd);
-		return NULL;
-	}
-
-	/* this one is for the conn */
-	priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata));
-
-	memcpy(priv->cookie, ck, 8);
-	strncpy(priv->sn, sn, sizeof(priv->sn));
-
-	newconn->fd = listenfd;
-	newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
-	newconn->internal = priv;
-	newconn->lastactivity = time(NULL);
-
-	return newconn;
-}
-
-/**
- * Connect directly to the given buddy for directim.
- *
- * This is a wrapper for aim_newconn.
- *
- * If addr is NULL, the socket is not created, but the connection is 
- * allocated and setup to connect.
- *
- * @param sess The Godly session.
- * @param sn The screen name we're connecting to.  I hope it's a girl...
- * @param addr Address to connect to.
- * @return The new connection.
- */
-faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie)
-{
-	aim_conn_t *newconn;
-	struct aim_odc_intdata *intdata;
-
-	if (!sess || !sn)
-		return NULL;
-
-	if (!(intdata = calloc(1, sizeof(struct aim_odc_intdata))))
-		return NULL;
-	memcpy(intdata->cookie, cookie, 8);
-	strncpy(intdata->sn, sn, sizeof(intdata->sn));
-	if (addr)
-		strncpy(intdata->ip, addr, sizeof(intdata->ip));
-
-	/* XXX - verify that non-blocking connects actually work */
-	if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr))) {
-		free(intdata);
-		return NULL;
-	}
-
-	newconn->internal = intdata;
-	newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
-
-	return newconn;
-}
-
-/**
- * Sometimes you just don't know with these kinds of people.
- *
- * @param sess The session.
- * @param conn The ODC connection of the incoming data.
- * @param frr The frame allocated for the incoming data.
- * @param bs It stands for "bologna sandwich."
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int handlehdr_odc(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *frr, aim_bstream_t *bs)
-{
-	aim_frame_t fr;
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu32_t payloadlength;
-	fu16_t flags, encoding;
-	char *snptr = NULL;
-
-	fr.conn = conn;
-
-	/* AAA - ugly */
-	aim_bstream_setpos(bs, 20);
-	payloadlength = aimbs_get32(bs);
-
-	aim_bstream_setpos(bs, 24);
-	encoding = aimbs_get16(bs);
-
-	aim_bstream_setpos(bs, 30);
-	flags = aimbs_get16(bs);
-
-	aim_bstream_setpos(bs, 36);
-	/* XXX - create an aimbs_getnullstr function? */
-	snptr = aimbs_getstr(bs, 32); /* Next 32 bytes contain the sn, padded with null chars */
-
-	faimdprintf(sess, 2, "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr);
-
-	if (flags & 0x0008) {
-		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)))
-			ret = userfunc(sess, &fr, snptr, 2);
-	} else if (flags & 0x0004) {
-		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)))
-			ret = userfunc(sess, &fr, snptr, 1);
-	} else {
-		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)))
-			ret = userfunc(sess, &fr, snptr, 0);
-	}
-
-	if (payloadlength) {
-		char *msg;
-		int recvd = 0;
-		int i, isawaymsg;
-
-		isawaymsg = flags & 0x0001;
-
-		if (!(msg = calloc(1, payloadlength+1))) {
-			free(snptr);
-			return -ENOMEM;
-		}
-
-		while (payloadlength - recvd) {
-			if (payloadlength - recvd >= 1024)
-				i = aim_recv(conn->fd, &msg[recvd], 1024);
-			else 
-				i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd);
-			if (i <= 0) {
-				free(msg);
-				free(snptr);
-				return -1;
-			}
-			recvd = recvd + i;
-			if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER)))
-				ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength);
-		}
-		
-		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)))
-			ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg);
-
-		free(msg);
-	}
-
-	free(snptr);
-
-	return ret;
-}
-
-faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename)
-{
-	struct aim_oft_info *new;
-
-	if (!sess)
-		return NULL;
-
-	if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info))))
-		return NULL;
-
-	new->sess = sess;
-	if (cookie)
-		memcpy(new->cookie, cookie, 8);
-	if (ip)
-		new->clientip = strdup(ip);
-	if (sn)
-		new->sn = strdup(sn);
-	new->port = port;
-	new->fh.totfiles = 1;
-	new->fh.filesleft = 1;
-	new->fh.totparts = 1;
-	new->fh.partsleft = 1;
-	new->fh.totsize = size;
-	new->fh.size = size;
-	new->fh.modtime = modtime;
-	new->fh.checksum = 0xffff0000;
-	new->fh.rfrcsum = 0xffff0000;
-	new->fh.rfcsum = 0xffff0000;
-	new->fh.recvcsum = 0xffff0000;
-	strncpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32", 31);
-	if (filename)
-		strncpy(new->fh.name, filename, 63);
-
-	new->next = sess->oft_info;
-	sess->oft_info = new;
-
-	return new;
-}
-
-/**
- * Remove the given oft_info struct from the oft_info linked list, and 
- * then free its memory.
- *
- * @param sess The session.
- * @param oft_info The aim_oft_info struct that we're destroying.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info)
-{
-	aim_session_t *sess;
-
-	if (!oft_info || !(sess = oft_info->sess))
-		return -EINVAL;
-
-	if (sess->oft_info && (sess->oft_info == oft_info)) {
-		sess->oft_info = sess->oft_info->next;
-	} else {
-		struct aim_oft_info *cur;
-		for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next);
-		if (cur->next)
-			cur->next = cur->next->next;
-	}
-
-	free(oft_info->sn);
-	free(oft_info->proxyip);
-	free(oft_info->clientip);
-	free(oft_info->verifiedip);
-	free(oft_info);
-
-	return 0;
-}
-
-/**
- * Creates a listener socket so the other dude can connect to us.
- *
- * You'll want to set up some kind of watcher on this socket.  
- * When the state changes, call aim_handlerendconnection with 
- * the connection returned by this.  aim_handlerendconnection 
- * will accept the pending connection and stop listening.
- *
- * @param sess The session.
- * @param oft_info File transfer information associated with this 
- *        connection.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info)
-{
-	int listenfd;
-
-	if (!oft_info)
-		return -EINVAL;
-
-	if ((listenfd = listenestablish(oft_info->port)) == -1)
-		return 1;
-
-	if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) {
-		close(listenfd);
-		return -ENOMEM;
-	}
-
-	oft_info->conn->fd = listenfd;
-	oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
-	oft_info->conn->lastactivity = time(NULL);
-
-	return 0;
-}
-
-/**
- * Extract an &aim_fileheader_t from the given buffer.
- *
- * @param bs The should be from an incoming rendezvous packet.
- * @return A pointer to new struct on success, or NULL on error.
- */
-static struct aim_fileheader_t *aim_oft_getheader(aim_bstream_t *bs)
-{
-	struct aim_fileheader_t *fh;
-
-	if (!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
-		return NULL;
-
-	/* The bstream should be positioned after the hdrtype. */
-	aimbs_getrawbuf(bs, fh->bcookie, 8);
-	fh->encrypt = aimbs_get16(bs);
-	fh->compress = aimbs_get16(bs);
-	fh->totfiles = aimbs_get16(bs);
-	fh->filesleft = aimbs_get16(bs);
-	fh->totparts = aimbs_get16(bs);
-	fh->partsleft = aimbs_get16(bs);
-	fh->totsize = aimbs_get32(bs);
-	fh->size = aimbs_get32(bs);
-	fh->modtime = aimbs_get32(bs);
-	fh->checksum = aimbs_get32(bs);
-	fh->rfrcsum = aimbs_get32(bs);
-	fh->rfsize = aimbs_get32(bs);
-	fh->cretime = aimbs_get32(bs);
-	fh->rfcsum = aimbs_get32(bs);
-	fh->nrecvd = aimbs_get32(bs);
-	fh->recvcsum = aimbs_get32(bs);
-	aimbs_getrawbuf(bs, fh->idstring, 32);
-	fh->flags = aimbs_get8(bs);
-	fh->lnameoffset = aimbs_get8(bs);
-	fh->lsizeoffset = aimbs_get8(bs);
-	aimbs_getrawbuf(bs, fh->dummy, 69);
-	aimbs_getrawbuf(bs, fh->macfileinfo, 16);
-	fh->nencode = aimbs_get16(bs);
-	fh->nlanguage = aimbs_get16(bs);
-	aimbs_getrawbuf(bs, fh->name, 64); /* XXX - filenames longer than 64B */
-
-	return fh;
-} 
-
-/**
- * Fills a buffer with network-order fh data
- *
- * @param bs A bstream to fill -- automatically initialized
- * @param fh A struct aim_fileheader_t to get data from.
- * @return Return non-zero on error.
- */
-static int aim_oft_buildheader(aim_bstream_t *bs, struct aim_fileheader_t *fh)
-{ 
-	fu8_t *hdr;
-
-	if (!bs || !fh)
-		return -EINVAL;
-
-	if (!(hdr = (unsigned char *)calloc(1, 0x100 - 8)))
-		return -ENOMEM;
-
-	aim_bstream_init(bs, hdr, 0x100 - 8);
-	aimbs_putraw(bs, fh->bcookie, 8);
-	aimbs_put16(bs, fh->encrypt);
-	aimbs_put16(bs, fh->compress);
-	aimbs_put16(bs, fh->totfiles);
-	aimbs_put16(bs, fh->filesleft);
-	aimbs_put16(bs, fh->totparts);
-	aimbs_put16(bs, fh->partsleft);
-	aimbs_put32(bs, fh->totsize);
-	aimbs_put32(bs, fh->size);
-	aimbs_put32(bs, fh->modtime);
-	aimbs_put32(bs, fh->checksum);
-	aimbs_put32(bs, fh->rfrcsum);
-	aimbs_put32(bs, fh->rfsize);
-	aimbs_put32(bs, fh->cretime);
-	aimbs_put32(bs, fh->rfcsum);
-	aimbs_put32(bs, fh->nrecvd);
-	aimbs_put32(bs, fh->recvcsum);
-	aimbs_putraw(bs, fh->idstring, 32);
-	aimbs_put8(bs, fh->flags);
-	aimbs_put8(bs, fh->lnameoffset);
-	aimbs_put8(bs, fh->lsizeoffset);
-	aimbs_putraw(bs, fh->dummy, 69);
-	aimbs_putraw(bs, fh->macfileinfo, 16);
-	aimbs_put16(bs, fh->nencode);
-	aimbs_put16(bs, fh->nlanguage);
-	aimbs_putraw(bs, fh->name, 64);	/* XXX - filenames longer than 64B */
-
-	return 0;
-}
-
-/**
- * Create an OFT packet based on the given information, and send it on its merry way.
- *
- * @param sess The session.
- * @param type The subtype of the OFT packet we're sending.
- * @param oft_info The aim_oft_info struct with the connection and OFT 
- *        info we're sending.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info)
-{
-	aim_frame_t *fr;
-
-	if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS))
-		return -EINVAL;
-
-#if 0
-	/*
-	 * If you are receiving a file, the cookie should be null, if you are sending a 
-	 * file, the cookie should be the same as the one used in the ICBM negotiation 
-	 * SNACs.
-	 */
-	fh->lnameoffset = 0x1a;
-	fh->lsizeoffset = 0x10;
-
-	/* apparently 0 is ASCII, 2 is UCS-2 */
-	/* it is likely that 3 is ISO 8859-1 */
-	/* I think "nlanguage" might be the same thing as "subenc" in im.c */
-	fh->nencode = 0x0000;
-	fh->nlanguage = 0x0000;
-#endif
-
-	aim_oft_dirconvert_tostupid(oft_info->fh.name);
-
-	if (!(fr = aim_tx_new(sess, oft_info->conn, AIM_FRAMETYPE_OFT, type, 0)))
-		return -ENOMEM;
-
-	if (aim_oft_buildheader(&fr->data, &oft_info->fh) == -1) {
-		aim_frame_destroy(fr);
-		return -ENOMEM;
-	}
-
-	memcpy(fr->hdr.rend.magic, "OFT2", 4);
-	fr->hdr.rend.hdrlen = aim_bstream_curpos(&fr->data);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Handle incoming data on a rendezvous connection.  This is analogous to the 
- * consumesnac function in rxhandlers.c, and I really think this should probably 
- * be in rxhandlers.c as well, but I haven't finished cleaning everything up yet.
- *
- * @param sess The session.
- * @param fr The frame allocated for the incoming data.
- * @return Return 0 if the packet was handled correctly, otherwise return the 
- *         error number.
- */
-faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_conn_t *conn = fr->conn;
-	int ret = 1;
-
-	if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
-		if (fr->hdr.rend.type == 0x0001)
-			ret = handlehdr_odc(sess, conn, fr, &fr->data);
-		else
-			faimdprintf(sess, 0, "faim: ODC directim frame unknown, type is %04x\n", fr->hdr.rend.type);
-
-	} else {
-		aim_rxcallback_t userfunc;
-		struct aim_fileheader_t *header = aim_oft_getheader(&fr->data);
-		aim_oft_dirconvert_fromstupid(header->name); /* XXX - This should be client-side */
-
-		if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, fr->hdr.rend.type)))
-			ret = userfunc(sess, fr, conn, header->bcookie, header);
-
-		free(header);
-	}
-
-	if (ret == -1)
-		aim_conn_close(conn);
-
-	return ret;
-}
Index: bfaim/icq.c
===================================================================
--- libfaim/icq.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,684 +1,0 @@
-/*
- * Family 0x0015 - Encapsulated ICQ.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-faim_export int aim_icq_reqofflinemsgs(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 4 + 2 + 2;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x003c); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_export int aim_icq_ackofflinemsgs(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 4 + 2 + 2;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x003e); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_export int aim_icq_hideip(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2+4+2+2+2+4;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x0424); /* shrug. */
-	aimbs_putle16(&fr->data, 0x0001);
-	aimbs_putle16(&fr->data, 0x0001);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Change your ICQ password.
- *
- * @param sess The oscar session
- * @param passwd The new password.  If this is longer than 8 characters it 
- *        will be truncated.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_icq_changepasswd(aim_session_t *sess, const char *passwd)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen, passwdlen;
-
-	if (!passwd)
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	passwdlen = strlen(passwd);
-	if (passwdlen > MAXICQPASSLEN)
-		passwdlen = MAXICQPASSLEN;
-	bslen = 2+4+2+2+2+2+passwdlen+1;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x042e); /* shrug. */
-	aimbs_putle16(&fr->data, passwdlen+1);
-	aimbs_putraw(&fr->data, passwd, passwdlen);
-	aimbs_putle8(&fr->data, '\0');
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_export int aim_icq_getallinfo(aim_session_t *sess, const char *uin)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-	struct aim_icq_info *info;
-
-	if (!uin || uin[0] < '0' || uin[0] > '9')
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 4 + 2 + 2 + 2 + 4;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x04b2); /* shrug. */
-	aimbs_putle32(&fr->data, atoi(uin));
-
-	aim_tx_enqueue(sess, fr);
-
-	/* Keep track of this request and the ICQ number and request ID */
-	info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info));
-	info->reqid = snacid;
-	info->uin = atoi(uin);
-	info->next = sess->icq_info;
-	sess->icq_info = info;
-
-	return 0;
-}
-
-faim_export int aim_icq_getalias(aim_session_t *sess, const char *uin)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-	struct aim_icq_info *info;
-
-	if (!uin || uin[0] < '0' || uin[0] > '9')
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 4 + 2 + 2 + 2 + 4;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x04ba); /* shrug. */
-	aimbs_putle32(&fr->data, atoi(uin));
-
-	aim_tx_enqueue(sess, fr);
-
-	/* Keep track of this request and the ICQ number and request ID */
-	info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info));
-	info->reqid = snacid;
-	info->uin = atoi(uin);
-	info->next = sess->icq_info;
-	sess->icq_info = info;
-
-	return 0;
-}
-
-faim_export int aim_icq_getsimpleinfo(aim_session_t *sess, const char *uin)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!uin || uin[0] < '0' || uin[0] > '9')
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 4 + 2 + 2 + 2 + 4;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x051f); /* shrug. */
-	aimbs_putle32(&fr->data, atoi(uin));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_export int aim_icq_sendxmlreq(aim_session_t *sess, const char *xml)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!xml || !strlen(xml))
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	bslen = 2 + 10 + 2 + strlen(xml) + 1;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x0998); /* shrug. */
-	aimbs_putle16(&fr->data, strlen(xml) + 1);
-	aimbs_putraw(&fr->data, xml, strlen(xml) + 1);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Send an SMS message.  This is the non-US way.  The US-way is to IM 
- * their cell phone number (+19195551234).
- *
- * We basically construct and send an XML message.  The format is:
- * <icq_sms_message>
- *   <destination>full_phone_without_leading_+</destination>
- *   <text>message</text>
- *   <codepage>1252</codepage>
- *   <senders_UIN>self_uin</senders_UIN>
- *   <senders_name>self_name</senders_name>
- *   <delivery_receipt>Yes|No</delivery_receipt>
- *   <time>Wkd, DD Mmm YYYY HH:MM:SS TMZ</time>
- * </icq_sms_message>
- *
- * Yeah hi Peter, whaaaat's happening.  If there's any way to use 
- * a codepage other than 1252 that would be great.  Thaaaanks.
- */
-faim_export int aim_icq_sendsms(aim_session_t *sess, const char *name, const char *msg, const char *alias)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen, xmllen;
-	char *xml, timestr[30];
-	time_t t;
-	struct tm *tm;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015)))
-		return -EINVAL;
-
-	if (!name || !msg || !alias)
-		return -EINVAL;
-
-	time(&t);
-	tm = gmtime(&t);
-	strftime(timestr, 30, "%a, %d %b %Y %T %Z", tm);
-
-	/* The length of xml included the null terminating character */
-	xmllen = 225 + strlen(name) + strlen(msg) + strlen(sess->sn) + strlen(alias) + strlen(timestr) + 1;
-
-	if (!(xml = (char *)malloc(xmllen*sizeof(char))))
-		return -ENOMEM;
-	snprintf(xml, xmllen, "<icq_sms_message>\n"
-		"\t<destination>%s</destination>\n"
-		"\t<text>%s</text>\n"
-		"\t<codepage>1252</codepage>\n"
-		"\t<senders_UIN>%s</senders_UIN>\n"
-		"\t<senders_name>%s</senders_name>\n"
-		"\t<delivery_receipt>Yes</delivery_receipt>\n"
-		"\t<time>%s</time>\n"
-		"</icq_sms_message>\n",
-		name, msg, sess->sn, alias, timestr);
-
-	bslen = 37 + xmllen;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) {
-		free(xml);
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-
-	/* From libicq200-0.3.2/src/SNAC-SRV.cpp */
-	aimbs_putle16(&fr->data, 0x8214);
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0016);
-	aimbs_put32(&fr->data, 0x00000000);
-	aimbs_put32(&fr->data, 0x00000000);
-	aimbs_put32(&fr->data, 0x00000000);
-	aimbs_put32(&fr->data, 0x00000000);
-
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, xmllen);
-	aimbs_putraw(&fr->data, xml, xmllen);
-
-	aim_tx_enqueue(sess, fr);
-
-	free(xml);
-
-	return 0;
-}
-
-static void aim_icq_freeinfo(struct aim_icq_info *info) {
-	int i;
-
-	if (!info)
-		return;
-	free(info->nick);
-	free(info->first);
-	free(info->last);
-	free(info->email);
-	free(info->homecity);
-	free(info->homestate);
-	free(info->homephone);
-	free(info->homefax);
-	free(info->homeaddr);
-	free(info->mobile);
-	free(info->homezip);
-	free(info->personalwebpage);
-	if (info->email2)
-		for (i = 0; i < info->numaddresses; i++)
-			free(info->email2[i]);
-	free(info->email2);
-	free(info->workcity);
-	free(info->workstate);
-	free(info->workphone);
-	free(info->workfax);
-	free(info->workaddr);
-	free(info->workzip);
-	free(info->workcompany);
-	free(info->workdivision);
-	free(info->workposition);
-	free(info->workwebpage);
-	free(info->info);
-	free(info);
-}
-
-/**
- * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet.
- */
-static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_tlvlist_t *tl;
-	aim_tlv_t *datatlv;
-	aim_bstream_t qbs;
-	fu32_t ouruin;
-	fu16_t cmdlen, cmd, reqid;
-
-	if (!(tl = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tl, 0x0001, 1))) {
-		aim_tlvlist_free(&tl);
-		faimdprintf(sess, 0, "corrupt ICQ response\n");
-		return 0;
-	}
-
-	aim_bstream_init(&qbs, datatlv->value, datatlv->length);
-
-	cmdlen = aimbs_getle16(&qbs);
-	ouruin = aimbs_getle32(&qbs);
-	cmd = aimbs_getle16(&qbs);
-	reqid = aimbs_getle16(&qbs);
-
-	faimdprintf(sess, 1, "icq response: %d bytes, %ld, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);
-
-	if (cmd == 0x0041) { /* offline message */
-		struct aim_icq_offlinemsg msg;
-		aim_rxcallback_t userfunc;
-
-		memset(&msg, 0, sizeof(msg));
-
-		msg.sender = aimbs_getle32(&qbs);
-		msg.year = aimbs_getle16(&qbs);
-		msg.month = aimbs_getle8(&qbs);
-		msg.day = aimbs_getle8(&qbs);
-		msg.hour = aimbs_getle8(&qbs);
-		msg.minute = aimbs_getle8(&qbs);
-		msg.type = aimbs_getle8(&qbs);
-		msg.flags = aimbs_getle8(&qbs);
-		msg.msglen = aimbs_getle16(&qbs);
-		msg.msg = aimbs_getstr(&qbs, msg.msglen);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG)))
-			ret = userfunc(sess, rx, &msg);
-
-		free(msg.msg);
-
-	} else if (cmd == 0x0042) {
-		aim_rxcallback_t userfunc;
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE)))
-			ret = userfunc(sess, rx);
-
-	} else if (cmd == 0x07da) { /* information */
-		fu16_t subtype;
-		struct aim_icq_info *info;
-		aim_rxcallback_t userfunc;
-
-		subtype = aimbs_getle16(&qbs);
-		aim_bstream_advance(&qbs, 1); /* 0x0a */
-
-		/* find other data from the same request */
-		for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next);
-		if (!info) {
-			info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info));
-			info->reqid = reqid;
-			info->next = sess->icq_info;
-			sess->icq_info = info;
-		}
-
-		switch (subtype) {
-		case 0x00a0: { /* hide ip status */
-			/* nothing */
-		} break;
-
-		case 0x00aa: { /* password change status */
-			/* nothing */
-		} break;
-
-		case 0x00c8: { /* general and "home" information */
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homecountry = aimbs_getle16(&qbs);
-			/* 0x0a 00 02 00 */
-			/* 1 byte timezone? */
-			/* 1 byte hide email flag? */
-		} break;
-
-		case 0x00dc: { /* personal information */
-			info->age = aimbs_getle8(&qbs);
-			info->unknown = aimbs_getle8(&qbs);
-			info->gender = aimbs_getle8(&qbs);
-			info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->birthyear = aimbs_getle16(&qbs);
-			info->birthmonth = aimbs_getle8(&qbs);
-			info->birthday = aimbs_getle8(&qbs);
-			info->language1 = aimbs_getle8(&qbs);
-			info->language2 = aimbs_getle8(&qbs);
-			info->language3 = aimbs_getle8(&qbs);
-			/* 0x00 00 01 00 00 01 00 00 00 00 00 */
-		} break;
-
-		case 0x00d2: { /* work information */
-			info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workcountry = aimbs_getle16(&qbs);
-			info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			aim_bstream_advance(&qbs, 2); /* 0x01 00 */
-			info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-		} break;
-
-		case 0x00e6: { /* additional personal information */
-			info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs)-1);
-		} break;
-
-		case 0x00eb: { /* email address(es) */
-			int i;
-			info->numaddresses = aimbs_getle16(&qbs);
-			info->email2 = (char **)calloc(info->numaddresses, sizeof(char *));
-			for (i = 0; i < info->numaddresses; i++) {
-				info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-				if (i+1 != info->numaddresses)
-					aim_bstream_advance(&qbs, 1); /* 0x00 */
-			}
-		} break;
-
-		case 0x00f0: { /* personal interests */
-		} break;
-
-		case 0x00fa: { /* past background and current organizations */
-		} break;
-
-		case 0x0104: { /* alias info */
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); /* email address? */
-			/* Then 0x00 02 00 */
-		} break;
-
-		case 0x010e: { /* unknown */
-			/* 0x00 00 */
-		} break;
-
-		case 0x019a: { /* simple info */
-			aim_bstream_advance(&qbs, 2);
-			info->uin = aimbs_getle32(&qbs);
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			/* Then 0x00 02 00 00 00 00 00 */
-		} break;
-		} /* End switch statement */
-
-		if (!(snac->flags & 0x0001)) {
-			if (subtype != 0x0104)
-				if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO)))
-					ret = userfunc(sess, rx, info);
-
-			if (info->uin && info->nick)
-				if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS)))
-					ret = userfunc(sess, rx, info);
-
-			if (sess->icq_info == info) {
-				sess->icq_info = info->next;
-			} else {
-				struct aim_icq_info *cur;
-				for (cur=sess->icq_info; (cur->next && (cur->next!=info)); cur=cur->next);
-				if (cur->next)
-					cur->next = cur->next->next;
-			}
-			aim_icq_freeinfo(info);
-		}
-	}
-
-	aim_tlvlist_free(&tl);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return icqresponse(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-static void icq_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	struct aim_icq_info *del;
-
-	while (sess->icq_info) {
-		del = sess->icq_info;
-		sess->icq_info = sess->icq_info->next;
-		aim_icq_freeinfo(del);
-	}
-
-	return;
-}
-
-faim_internal int icq_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0015;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x047c;
-	mod->flags = 0;
-	strncpy(mod->name, "icq", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = icq_shutdown;
-
-	return 0;
-}
Index: bfaim/im.c
===================================================================
--- libfaim/im.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,2298 +1,0 @@
-/*
- * Family 0x0004 - Routines for sending/receiving Instant Messages.
- *
- * Note the term ICBM (Inter-Client Basic Message) which blankets
- * all types of genericly routed through-server messages.  Within
- * the ICBM types (family 4), a channel is defined.  Each channel
- * represents a different type of message.  Channel 1 is used for
- * what would commonly be called an "instant message".  Channel 2
- * is used for negotiating "rendezvous".  These transactions end in
- * something more complex happening, such as a chat invitation, or
- * a file transfer.  Channel 3 is used for chat messages (not in 
- * the same family as these channels).  Channel 4 is used for 
- * various ICQ messages.  Examples are normal messages, URLs, and 
- * old-style authorization.
- *
- * In addition to the channel, every ICBM contains a cookie.  For
- * standard IMs, these are only used for error messages.  However,
- * the more complex rendezvous messages make suitably more complex
- * use of this field.
- *
- * TODO: Split this up into an im.c file an an icbm.c file.  It 
- *       will be beautiful, you'll see.
- *
- *       Need to rename all the mpmsg messages to aim_im_bleh.
- *
- *       Make sure aim_conn_findbygroup is used by all functions.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-/**
- * Add a standard ICBM header to the given bstream with the given 
- * information.
- *
- * @param bs The bstream to write the ICBM header to.
- * @param c c is for cookie, and cookie is for me.
- * @param ch The ICBM channel (1 through 4).
- * @param sn Null-terminated scrizeen nizame.
- * @return The number of bytes written.  It's really not useful.
- */
-static int aim_im_puticbm(aim_bstream_t *bs, const fu8_t *c, fu16_t ch, const char *sn)
-{
-	aimbs_putraw(bs, c, 8);
-	aimbs_put16(bs, ch);
-	aimbs_put8(bs, strlen(sn));
-	aimbs_putraw(bs, sn, strlen(sn));
-	return 8+2+1+strlen(sn);
-}
-
-/*
- * Takes a msghdr (and a length) and returns a client type
- * code.  Note that this is *only a guess* and has a low likelihood
- * of actually being accurate.
- *
- * Its based on experimental data, with the help of Eric Warmenhoven
- * who seems to have collected a wide variety of different AIM clients.
- *
- *
- * Heres the current collection:
- *  0501 0003 0101 0101 01		AOL Mobile Communicator, WinAIM 1.0.414
- *  0501 0003 0101 0201 01		WinAIM 2.0.847, 2.1.1187, 3.0.1464, 
- *					4.3.2229, 4.4.2286
- *  0501 0004 0101 0102 0101		WinAIM 4.1.2010, libfaim (right here)
- *  0501 0003 0101 02			WinAIM 5
- *  0501 0001 01			iChat x.x, mobile buddies
- *  0501 0001 0101 01			AOL v6.0, CompuServe 2000 v6.0, any TOC client
- *  0501 0002 0106			WinICQ 5.45.1.3777.85
- *
- * Note that in this function, only the feature bytes are tested, since
- * the rest will always be the same.
- *
- */
-faim_export fu16_t aim_im_fingerprint(const fu8_t *msghdr, int len)
-{
-	static const struct {
-		fu16_t clientid;
-		int len;
-		fu8_t data[10];
-	} fingerprints[] = {
-		/* AOL Mobile Communicator, WinAIM 1.0.414 */
-		{ AIM_CLIENTTYPE_MC, 
-		  3, {0x01, 0x01, 0x01}},
-
-		/* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */
-		{ AIM_CLIENTTYPE_WINAIM, 
-		  3, {0x01, 0x01, 0x02}},
-
-		/* WinAIM 4.1.2010, libfaim */
-		{ AIM_CLIENTTYPE_WINAIM41,
-		  4, {0x01, 0x01, 0x01, 0x02}},
-
-		/* AOL v6.0, CompuServe 2000 v6.0, any TOC client */
-		{ AIM_CLIENTTYPE_AOL_TOC,
-		  1, {0x01}},
-
-		{ 0, 0}
-	};
-	int i;
-
-	if (!msghdr || (len <= 0))
-		return AIM_CLIENTTYPE_UNKNOWN;
-
-	for (i = 0; fingerprints[i].len; i++) {
-		if (fingerprints[i].len != len)
-			continue;
-		if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0)
-			return fingerprints[i].clientid;
-	}
-
-	return AIM_CLIENTTYPE_UNKNOWN;
-}
-
-/** 
- * Subtype 0x0002 - Set ICBM parameters.
- *
- * I definitly recommend sending this.  If you don't, you'll be stuck
- * with the rather unreasonable defaults.
- * 
- */
-faim_export int aim_im_setparams(aim_session_t *sess, struct aim_icbmparameters *params)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!params)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid);
-
-	/* This is read-only (see Parameter Reply). Must be set to zero here. */
-	aimbs_put16(&fr->data, 0x0000);
-
-	/* These are all read-write */
-	aimbs_put32(&fr->data, params->flags); 
-	aimbs_put16(&fr->data, params->maxmsglen);
-	aimbs_put16(&fr->data, params->maxsenderwarn); 
-	aimbs_put16(&fr->data, params->maxrecverwarn); 
-	aimbs_put32(&fr->data, params->minmsginterval);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0004 - Request ICBM parameter information.
- *
- */
-faim_export int aim_im_reqparams(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	return aim_genericreq_n_snacid(sess, conn, 0x0004, 0x0004);
-}
-
-/**
- * Subtype 0x0005 - Receive parameter information.
- *
- */
-static int aim_im_paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	struct aim_icbmparameters params;
-
-	params.maxchan = aimbs_get16(bs);
-	params.flags = aimbs_get32(bs);
-	params.maxmsglen = aimbs_get16(bs);
-	params.maxsenderwarn = aimbs_get16(bs);
-	params.maxrecverwarn = aimbs_get16(bs);
-	params.minmsginterval = aimbs_get32(bs);
-	
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		return userfunc(sess, rx, &params);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send an ICBM (instant message).  
- *
- *
- * Possible flags:
- *   AIM_IMFLAGS_AWAY  -- Marks the message as an autoresponse
- *   AIM_IMFLAGS_ACK   -- Requests that the server send an ack
- *                        when the message is received (of type 0x0004/0x000c)
- *   AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are
- *                        online (probably ICQ only).
- *   AIM_IMFLAGS_UNICODE--Instead of ASCII7, the passed message is
- *                        made up of UNICODE duples.  If you set
- *                        this, you'd better be damn sure you know
- *                        what you're doing.
- *   AIM_IMFLAGS_ISO_8859_1 -- The message contains the ASCII8 subset
- *                        known as ISO-8859-1.  
- *
- * Generally, you should use the lowest encoding possible to send
- * your message.  If you only use basic punctuation and the generic
- * Latin alphabet, use ASCII7 (no flags).  If you happen to use non-ASCII7
- * characters, but they are all clearly defined in ISO-8859-1, then 
- * use that.  Keep in mind that not all characters in the PC ASCII8
- * character set are defined in the ISO standard. For those cases (most
- * notably when the (r) symbol is used), you must use the full UNICODE
- * encoding for your message.  In UNICODE mode, _all_ characters must
- * occupy 16bits, including ones that are not special.  (Remember that
- * the first 128 UNICODE symbols are equivelent to ASCII7, however they
- * must be prefixed with a zero high order byte.)
- *
- * I strongly discourage the use of UNICODE mode, mainly because none
- * of the clients I use can parse those messages (and besides that,
- * wchars are difficult and non-portable to handle in most UNIX environments).
- * If you really need to include special characters, use the HTML UNICODE 
- * entities.  These are of the form &#2026; where 2026 is the hex 
- * representation of the UNICODE index (in this case, UNICODE 
- * "Horizontal Ellipsis", or 133 in in ASCII8).
- *
- * Implementation note:  Since this is one of the most-used functions
- * in all of libfaim, it is written with performance in mind.  As such,
- * it is not as clear as it could be in respect to how this message is
- * supposed to be layed out. Most obviously, tlvlists should be used 
- * instead of writing out the bytes manually. 
- *
- * XXX - more precise verification that we never send SNACs larger than 8192
- * XXX - check SNAC size for multipart
- *
- */
-faim_export int aim_im_sendch1_ext(aim_session_t *sess, struct aim_sendimext_args *args)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	fu8_t ck[8];
-	int i, msgtlvlen;
-	static const fu8_t deffeatures[] = { 0x01, 0x01, 0x01, 0x02 };
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!args)
-		return -EINVAL;
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		if (args->mpmsg->numparts <= 0)
-			return -EINVAL;
-	} else {
-		if (!args->msg || (args->msglen <= 0))
-			return -EINVAL;
-
-		if (args->msglen >= MAXMSGLEN)
-			return -E2BIG;
-	}
-
-	/* Painfully calculate the size of the message TLV */
-	msgtlvlen = 1 + 1; /* 0501 */
-
-	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES)
-		msgtlvlen += 2 + args->featureslen;
-	else
-		msgtlvlen += 2 + sizeof(deffeatures);
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		aim_mpmsg_section_t *sec;
-
-		for (sec = args->mpmsg->parts; sec; sec = sec->next) {
-			msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
-			msgtlvlen += 4 /* charset */ + sec->datalen;
-		}
-
-	} else {
-		msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
-		msgtlvlen += 4 /* charset */ + args->msglen;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128)))
-		return -ENOMEM;
-
-	/* XXX - should be optional */	
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* 
-	 * Generate a random message cookie
-	 *
-	 * We could cache these like we do SNAC IDs.  (In fact, it 
-	 * might be a good idea.)  In the message error functions, 
-	 * the 8byte message cookie is returned as well as the 
-	 * SNAC ID.
-	 *
-	 */
-	for (i = 0; i < 8; i++)
-		ck[i] = (fu8_t)rand();
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0001, args->destsn);
-
-	/* Message TLV (type 0x0002) */
-	aimbs_put16(&fr->data, 0x0002);
-	aimbs_put16(&fr->data, msgtlvlen);
-
-	/* Features TLV (type 0x0501) */
-	aimbs_put16(&fr->data, 0x0501);
-	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) {
-		aimbs_put16(&fr->data, args->featureslen);
-		aimbs_putraw(&fr->data, args->features, args->featureslen);
-	} else {
-		aimbs_put16(&fr->data, sizeof(deffeatures));
-		aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures));
-	}
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		aim_mpmsg_section_t *sec;
-
-		/* Insert each message part in a TLV (type 0x0101) */
-		for (sec = args->mpmsg->parts; sec; sec = sec->next) {
-			aimbs_put16(&fr->data, 0x0101);
-			aimbs_put16(&fr->data, sec->datalen + 4);
-			aimbs_put16(&fr->data, sec->charset);
-			aimbs_put16(&fr->data, sec->charsubset);
-			aimbs_putraw(&fr->data, sec->data, sec->datalen);
-		}
-
-	} else {
-
-		/* Insert message text in a TLV (type 0x0101) */
-		aimbs_put16(&fr->data, 0x0101);
-
-		/* Message block length */
-		aimbs_put16(&fr->data, args->msglen + 0x04);
-
-		/* Character set */
-		aimbs_put16(&fr->data, args->charset);
-		aimbs_put16(&fr->data, args->charsubset);
-
-		/* Message.  Not terminated */
-		aimbs_putraw(&fr->data, args->msg, args->msglen);
-	}
-
-	/* Set the Autoresponse flag */
-	if (args->flags & AIM_IMFLAGS_AWAY) {
-		aimbs_put16(&fr->data, 0x0004);
-		aimbs_put16(&fr->data, 0x0000);
-	} else if (args->flags & AIM_IMFLAGS_ACK) {
-		/* Set the Request Acknowledge flag */
-		aimbs_put16(&fr->data, 0x0003);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	if (args->flags & AIM_IMFLAGS_OFFLINE) {
-		aimbs_put16(&fr->data, 0x0006);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	/*
-	 * Set the I HAVE A REALLY PURTY ICON flag.
-	 * XXX - This should really only be sent on initial 
-	 * IMs and when you change your icon.
-	 */
-	if (args->flags & AIM_IMFLAGS_HASICON) {
-		aimbs_put16(&fr->data, 0x0008);
-		aimbs_put16(&fr->data, 0x000c);
-		aimbs_put32(&fr->data, args->iconlen);
-		aimbs_put16(&fr->data, 0x0001);
-		aimbs_put16(&fr->data, args->iconsum);
-		aimbs_put32(&fr->data, args->iconstamp);
-	}
-
-	/*
-	 * Set the Buddy Icon Requested flag.
-	 * XXX - Everytime?  Surely not...
-	 */
-	if (args->flags & AIM_IMFLAGS_BUDDYREQ) {
-		aimbs_put16(&fr->data, 0x0009);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	/* clean out SNACs over 60sec old */
-	aim_cleansnacs(sess, 60);
-
-	return 0;
-}
-
-/*
- * Simple wrapper for aim_im_sendch1_ext() 
- *
- * You cannot use aim_send_im if you need the HASICON flag.  You must
- * use aim_im_sendch1_ext directly for that.
- *
- * aim_send_im also cannot be used if you require UNICODE messages, because
- * that requires an explicit message length.  Use aim_im_sendch1_ext().
- *
- */
-faim_export int aim_im_sendch1(aim_session_t *sess, const char *sn, fu16_t flags, const char *msg)
-{
-	struct aim_sendimext_args args;
-
-	args.destsn = sn;
-	args.flags = flags;
-	args.msg = msg;
-	args.msglen = strlen(msg);
-	args.charset = 0x0000;
-	args.charsubset = 0x0000;
-
-	/* Make these don't get set by accident -- they need aim_im_sendch1_ext */
-	args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART);
-
-	return aim_im_sendch1_ext(sess, &args);
-}
-
-/**
- * Subtype 0x0006 - Send your icon to a given user.
- *
- * This is also performance sensitive. (If you can believe it...)
- *
- */
-faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	fu8_t ck[8];
-	int i;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))
-		return -EINVAL;
-
-	for (i = 0; i < 8; i++)
-		ck[i] = (fu8_t)rand();
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0002, sn);
-
-	/*
-	 * TLV t(0005)
-	 *
-	 * Encompasses everything below.
-	 */
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));
-
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_putraw(&fr->data, ck, 8);
-	aim_putcap(&fr->data, AIM_CAPS_BUDDYICON);
-
-	/* TLV t(000a) */
-	aimbs_put16(&fr->data, 0x000a);
-	aimbs_put16(&fr->data, 0x0002);
-	aimbs_put16(&fr->data, 0x0001);
-
-	/* TLV t(000f) */
-	aimbs_put16(&fr->data, 0x000f);
-	aimbs_put16(&fr->data, 0x0000);
-
-	/* TLV t(2711) */
-	aimbs_put16(&fr->data, 0x2711);
-	aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT));
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, iconsum);
-	aimbs_put32(&fr->data, iconlen);
-	aimbs_put32(&fr->data, stamp);
-	aimbs_putraw(&fr->data, icon, iconlen);
-	aimbs_putraw(&fr->data, AIM_ICONIDENT, strlen(AIM_ICONIDENT));
-
-	/* TLV t(0003) */
-	aimbs_put16(&fr->data, 0x0003);
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0006 - Send a rich text message.
- *
- * This only works for ICQ 2001b (thats 2001 not 2000).  Better, only
- * send it to clients advertising the RTF capability.  In fact, if you send
- * it to a client that doesn't support that capability, the server will gladly
- * bounce it back to you.
- *
- * You'd think this would be in icq.c, but, well, I'm trying to stick with
- * the one-group-per-file scheme as much as possible.  This could easily
- * be an exception, since Rendezvous IMs are external of the Oscar core, 
- * and therefore are undefined.  Really I just need to think of a good way to
- * make an interface similar to what AOL actually uses.  But I'm not using COM.
- *
- */
-faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	fu8_t ck[8];
-	const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */
-	int i, servdatalen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!args || !args->destsn || !args->rtfmsg)
-		return -EINVAL;
-
-	servdatalen = 2+2+16+2+4+1+2  +  2+2+4+4+4  +  2+4+2+strlen(args->rtfmsg)+1  +  4+4+4+strlen(rtfcap)+1;
-
-	for (i = 0; i < 8; i++)
-		ck[i] = (fu8_t)rand();
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0002, args->destsn);
-
-	/* TLV t(0005) - Encompasses everything below. */
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 2+8+16  +  2+2+2  +  2+2  +  2+2+servdatalen);
-
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_putraw(&fr->data, ck, 8);
-	aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);
-
-	/* t(000a) l(0002) v(0001) */
-	aimbs_put16(&fr->data, 0x000a);
-	aimbs_put16(&fr->data, 0x0002);
-	aimbs_put16(&fr->data, 0x0001);
-
-	/* t(000f) l(0000) v() */
-	aimbs_put16(&fr->data, 0x000f);
-	aimbs_put16(&fr->data, 0x0000);
-
-	/* Service Data TLV */
-	aimbs_put16(&fr->data, 0x2711);
-	aimbs_put16(&fr->data, servdatalen);
-
-	aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */);
-	aimbs_putle16(&fr->data, 9);
-	aim_putcap(&fr->data, AIM_CAPS_EMPTY);
-	aimbs_putle16(&fr->data, 0);
-	aimbs_putle32(&fr->data, 0);
-	aimbs_putle8(&fr->data, 0);
-	aimbs_putle16(&fr->data, 0x03ea); /* trid1 */
-
-	aimbs_putle16(&fr->data, 14);
-	aimbs_putle16(&fr->data, 0x03eb); /* trid2 */
-	aimbs_putle32(&fr->data, 0);
-	aimbs_putle32(&fr->data, 0);
-	aimbs_putle32(&fr->data, 0);
-
-	aimbs_putle16(&fr->data, 0x0001);
-	aimbs_putle32(&fr->data, 0);
-	aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1);
-	aimbs_putraw(&fr->data, args->rtfmsg, strlen(args->rtfmsg)+1);
-
-	aimbs_putle32(&fr->data, args->fgcolor);
-	aimbs_putle32(&fr->data, args->bgcolor);
-	aimbs_putle32(&fr->data, strlen(rtfcap)+1);
-	aimbs_putraw(&fr->data, rtfcap, strlen(rtfcap)+1);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send an "I want to directly connect to you" message
- *
- */
-faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	fu8_t ck[8];
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
-	int hdrlen, i;
-	fu8_t *hdr;
-	aim_bstream_t hdrbs;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* 
-	 * Generate a random message cookie 
-	 *
-	 * This cookie needs to be alphanumeric and NULL-terminated to be 
-	 * TOC-compatible.
-	 *
-	 * XXX - have I mentioned these should be generated in msgcookie.c?
-	 *
-	 */
-	for (i = 0; i < 7; i++)
-	       	ck[i] = 0x30 + ((fu8_t) rand() % 10);
-	ck[7] = '\0';
-
-	if (cookie)
-		memcpy(cookie, ck, 8);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0002, sn);
-
-	aim_tlvlist_add_noval(&tl, 0x0003);
-
-	hdrlen = 2+8+16+6+8+6+4;
-	hdr = malloc(hdrlen);
-	aim_bstream_init(&hdrbs, hdr, hdrlen);
-
-	aimbs_put16(&hdrbs, 0x0000);
-	aimbs_putraw(&hdrbs, ck, 8);
-	aim_putcap(&hdrbs, AIM_CAPS_DIRECTIM);
-
-	aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, port);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
-
-	aim_tlvlist_write(&fr->data, &tl);
-
-	free(hdr);
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send an "I want to send you this file" message
- *
- */
-faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl=NULL, *subtl=NULL;
-	int i;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
-		return -EINVAL;
-
-	/* XXX - Should be like "21CBF95" and null terminated */
-	for (i = 0; i < 7; i++)
-		oft_info->cookie[i] = 0x30 + ((fu8_t)rand() % 10);
-	oft_info->cookie[7] = '\0';
-
-	{ /* Create the subTLV chain */
-		fu8_t *buf;
-		int buflen;
-		aim_bstream_t bs;
-
-		aim_tlvlist_add_16(&subtl, 0x000a, 0x0001);
-		aim_tlvlist_add_noval(&subtl, 0x000f);
-/*		aim_tlvlist_add_raw(&subtl, 0x000e, 2, "en");
-		aim_tlvlist_add_raw(&subtl, 0x000d, 8, "us-ascii");
-		aim_tlvlist_add_raw(&subtl, 0x000c, 24, "Please accept this file."); */
-		if (oft_info->clientip) {
-			fu8_t ip[4];
-			char *nexttoken;
-			int i = 0;
-			nexttoken = strtok(oft_info->clientip, ".");
-			while (nexttoken && i<4) {
-				ip[i] = atoi(nexttoken);
-				nexttoken = strtok(NULL, ".");
-				i++;
-			}
-			aim_tlvlist_add_raw(&subtl, 0x0003, 4, ip);
-		}
-		aim_tlvlist_add_16(&subtl, 0x0005, oft_info->port);
-
-		/* TLV t(2711) */
-		buflen = 2+2+4+strlen(oft_info->fh.name)+1;
-		buf = malloc(buflen);
-		aim_bstream_init(&bs, buf, buflen);
-		aimbs_put16(&bs, (oft_info->fh.totfiles > 1) ? 0x0002 : 0x0001);
-		aimbs_put16(&bs, oft_info->fh.totfiles);
-		aimbs_put32(&bs, oft_info->fh.totsize);
-
-		/* Filename - NULL terminated, for some odd reason */
-		aimbs_putraw(&bs, oft_info->fh.name, strlen(oft_info->fh.name));
-		aimbs_put8(&bs, 0x00);
-
-		aim_tlvlist_add_raw(&subtl, 0x2711, bs.len, bs.data);
-		free(buf);
-	}
-
-	{ /* Create the main TLV chain */
-		fu8_t *buf;
-		int buflen;
-		aim_bstream_t bs;
-
-		/* TLV t(0005) - Encompasses everything from above. Gee. */
-		buflen = 2+8+16+aim_tlvlist_size(&subtl);
-		buf = malloc(buflen);
-		aim_bstream_init(&bs, buf, buflen);
-		aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE);
-		aimbs_putraw(&bs, oft_info->cookie, 8);
-		aim_putcap(&bs, AIM_CAPS_SENDFILE);
-		aim_tlvlist_write(&bs, &subtl);
-		aim_tlvlist_free(&subtl);
-		aim_tlvlist_add_raw(&tl, 0x0005, bs.len, bs.data);
-		free(buf);
-
-		/* TLV t(0003) - Request an ack */
-		aim_tlvlist_add_noval(&tl, 0x0003);
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, oft_info->cookie, sizeof(oft_info->cookie));
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
-
-	/* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send an "I will accept this file" message?
- *
- * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE)
- */
-faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *oft_info)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
-
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 0x001a);
-	aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT);
-	aimbs_putraw(&fr->data, oft_info->cookie, 8);
-	aim_putcap(&fr->data, AIM_CAPS_SENDFILE);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send a "cancel this file transfer" message?
- *
- */
-faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn);
-
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 0x001a);
-	aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL);
-	aimbs_putraw(&fr->data, oft_info->cookie, 8);
-	aim_putcap(&fr->data, AIM_CAPS_SENDFILE);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Request the status message of the given ICQ user.
- *
- * @param sess The oscar session.
- * @param sn The UIN of the user of whom you wish to request info.
- * @param type The type of info you wish to request.  This should be the current 
- *        state of the user, as one of the AIM_ICQ_STATE_* defines.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int i;
-	fu8_t ck[8];
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn)
-		return -EINVAL;
-
-	for (i = 0; i < 8; i++)
-		ck[i] = (fu8_t)rand();
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0002, sn);
-
-	/* TLV t(0005) - Encompasses almost everything below. */
-	aimbs_put16(&fr->data, 0x0005); /* T */
-	aimbs_put16(&fr->data, 0x005e); /* L */
-	{ /* V */
-		aimbs_put16(&fr->data, 0x0000);
-
-		/* Cookie */
-		aimbs_putraw(&fr->data, ck, 8);
-
-		/* Put the 16 byte server relay capability */
-		aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);
-
-		/* TLV t(000a) */
-		aimbs_put16(&fr->data, 0x000a);
-		aimbs_put16(&fr->data, 0x0002);
-		aimbs_put16(&fr->data, 0x0001);
-
-		/* TLV t(000f) */
-		aimbs_put16(&fr->data, 0x000f);
-		aimbs_put16(&fr->data, 0x0000);
-
-		/* TLV t(2711) */
-		aimbs_put16(&fr->data, 0x2711);
-		aimbs_put16(&fr->data, 0x0036);
-		{ /* V */
-			aimbs_putle16(&fr->data, 0x001b); /* L */
-			aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */
-			aim_putcap(&fr->data, AIM_CAPS_EMPTY);
-			aimbs_putle16(&fr->data, 0x0000); /* Unknown */
-			aimbs_putle16(&fr->data, 0x0003); /* Client features? */
-			aimbs_putle16(&fr->data, 0x0000); /* Unknown */
-			aimbs_putle8(&fr->data, 0x00); /* Unkizown */
-			aimbs_putle16(&fr->data, 0xffff); /* Sequence number?  XXX - This should decrement by 1 with each request */
-
-			aimbs_putle16(&fr->data, 0x000e); /* L */
-			aimbs_putle16(&fr->data, 0xffff); /* Sequence number?  XXX - This should decrement by 1 with each request */
-			aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-			aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-			aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-
-			/* The type of status message being requested */
-			if (type & AIM_ICQ_STATE_CHAT)
-				aimbs_putle16(&fr->data, 0x03ec);
-			else if(type & AIM_ICQ_STATE_DND)
-				aimbs_putle16(&fr->data, 0x03eb);
-			else if(type & AIM_ICQ_STATE_OUT)
-				aimbs_putle16(&fr->data, 0x03ea);
-			else if(type & AIM_ICQ_STATE_BUSY)
-				aimbs_putle16(&fr->data, 0x03e9);
-			else if(type & AIM_ICQ_STATE_AWAY)
-				aimbs_putle16(&fr->data, 0x03e8);
-
-			aimbs_putle16(&fr->data, 0x0000); /* Status? */
-			aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */
-			aimbs_putle16(&fr->data, 0x0001); /* L */
-			aimbs_putle8(&fr->data, 0x00); /* String of length L */
-		} /* End TLV t(2711) */
-	} /* End TLV t(0005) */
-
-	/* TLV t(0003) */
-	aimbs_put16(&fr->data, 0x0003);
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/**
- * Subtype 0x0006 - Send an ICQ-esque ICBM.
- *
- * This can be used to send an ICQ authorization reply (deny or grant).  It is the "old way."  
- * The new way is to use SSI.  I like the new way a lot better.  This seems like such a hack, 
- * mostly because it's in network byte order.  Figuring this stuff out sometimes takes a while, 
- * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people 
- * were taking when they merged the two protocols.
- *
- * @param sn The destination screen name.
- * @param type The type of message.  0x0007 for authorization denied.  0x0008 for authorization granted.
- * @param message The message you want to send, it should be null terminated.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int i;
-	char ck[8];
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002)))
-		return -EINVAL;
-
-	if (!sn || !type || !message)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/* Cookie */
-	for (i=0; i<8; i++)
-		ck[i] = (fu8_t)rand();
-
-	/* ICBM header */
-	aim_im_puticbm(&fr->data, ck, 0x0004, sn);
-
-	/*
-	 * TLV t(0005)
-	 *
-	 * ICQ data (the UIN and the message).
-	 */
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 4 + 2+2+strlen(message)+1);
-
-	/*
-	 * Your UIN
-	 */
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-
-	/*
-	 * TLV t(type) l(strlen(message)+1) v(message+NULL)
-	 */
-	aimbs_putle16(&fr->data, type);
-	aimbs_putle16(&fr->data, strlen(message)+1);
-	aimbs_putraw(&fr->data, message, strlen(message)+1);
-
-	/*
-	 * TLV t(0006) l(0000) v()
-	 */
-	aimbs_put16(&fr->data, 0x0006);
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * XXX - I don't see when this would ever get called...
- */
-static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int i, ret = 0;
-	aim_rxcallback_t userfunc;
-	fu8_t cookie[8];
-	fu16_t channel;
-	aim_tlvlist_t *tlvlist;
-	char *sn;
-	int snlen;
-	fu16_t icbmflags = 0;
-	fu8_t flag1 = 0, flag2 = 0;
-	fu8_t *msg = NULL;
-	aim_tlv_t *msgblock;
-
-	/* ICBM Cookie. */
-	for (i = 0; i < 8; i++)
-		cookie[i] = aimbs_get8(bs);
-
-	/* Channel ID */
-	channel = aimbs_get16(bs);
-
-	if (channel != 0x01) {
-		faimdprintf(sess, 0, "icbm: ICBM recieved on unsupported channel.  Ignoring. (chan = %04x)\n", channel);
-		return 0;
-	}
-
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-
-	tlvlist = aim_tlvlist_read(bs);
-
-	if (aim_tlv_gettlv(tlvlist, 0x0003, 1))
-		icbmflags |= AIM_IMFLAGS_ACK;
-	if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
-		icbmflags |= AIM_IMFLAGS_AWAY;
-
-	if ((msgblock = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
-		aim_bstream_t mbs;
-		int featurelen, msglen;
-
-		aim_bstream_init(&mbs, msgblock->value, msgblock->length);
-
-		aimbs_get8(&mbs);
-		aimbs_get8(&mbs);
-		for (featurelen = aimbs_get16(&mbs); featurelen; featurelen--)
-			aimbs_get8(&mbs);
-		aimbs_get8(&mbs);
-		aimbs_get8(&mbs);
-
-		msglen = aimbs_get16(&mbs) - 4; /* final block length */
-
-		flag1 = aimbs_get16(&mbs);
-		flag2 = aimbs_get16(&mbs);
-
-		msg = aimbs_getstr(&mbs, msglen);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2);
-
-	free(sn);
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Ahh, the joys of nearly ridiculous over-engineering.
- *
- * Not only do AIM ICBM's support multiple channels.  Not only do they
- * support multiple character sets.  But they support multiple character 
- * sets / encodings within the same ICBM.
- *
- * These multipart messages allow for complex space savings techniques, which
- * seem utterly unnecessary by today's standards.  In fact, there is only
- * one client still in popular use that still uses this method: AOL for the
- * Macintosh, Version 5.0.  Obscure, yes, I know.  
- *
- * In modern (non-"legacy") clients, if the user tries to send a character
- * that is not ISO-8859-1 or ASCII, the client will send the entire message
- * as UNICODE, meaning that every character in the message will occupy the
- * full 16 bit UNICODE field, even if the high order byte would be zero.
- * Multipart messages prevent this wasted space by allowing the client to
- * only send the characters in UNICODE that need to be sent that way, and
- * the rest of the message can be sent in whatever the native character 
- * set is (probably ASCII).
- *
- * An important note is that sections will be displayed in the order that
- * they appear in the ICBM.  There is no facility for merging or rearranging
- * sections at run time.  So if you have, say, ASCII then UNICODE then ASCII,
- * you must supply two ASCII sections with a UNICODE in the middle, and incur
- * the associated overhead.
- *
- * Normally I would have laughed and given a firm 'no' to supporting this
- * seldom-used feature, but something is attracting me to it.  In the future,
- * it may be possible to abuse this to send mixed-media messages to other
- * open source clients (like encryption or something) -- see faimtest for
- * examples of how to do this.
- *
- * I would definitly recommend avoiding this feature unless you really
- * know what you are doing, and/or you have something neat to do with it.
- *
- */
-faim_export int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm)
-{
-
-	memset(mpm, 0, sizeof(aim_mpmsg_t));
-
-	return 0;
-}
-
-static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, fu16_t charset, fu16_t charsubset, fu8_t *data, fu16_t datalen)
-{
-	aim_mpmsg_section_t *sec; 
-	
-	if (!(sec = malloc(sizeof(aim_mpmsg_section_t))))
-		return -1;
-
-	sec->charset = charset;
-	sec->charsubset = charsubset;
-	sec->data = data;
-	sec->datalen = datalen;
-	sec->next = NULL;
-
-	if (!mpm->parts)
-		mpm->parts = sec;
-	else {
-		aim_mpmsg_section_t *cur;
-
-		for (cur = mpm->parts; cur->next; cur = cur->next)
-			;
-		cur->next = sec;
-	}
-
-	mpm->numparts++;
-
-	return 0;
-}
-
-faim_export int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, fu16_t charset, fu16_t charsubset, const fu8_t *data, fu16_t datalen)
-{
-	fu8_t *dup;
-
-	if (!(dup = malloc(datalen)))
-		return -1;
-	memcpy(dup, data, datalen);
-
-	if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) {
-		free(dup);
-		return -1;
-	}
-
-	return 0;
-}
-
-/* XXX - should provide a way of saying ISO-8859-1 specifically */
-faim_export int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii)
-{
-	fu8_t *dup;
-
-	if (!(dup = strdup(ascii))) 
-		return -1;
-
-	if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) {
-		free(dup);
-		return -1;
-	}
-
-	return 0;
-}
-
-faim_export int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const fu16_t *unicode, fu16_t unicodelen)
-{
-	fu8_t *buf;
-	aim_bstream_t bs;
-	int i;
-
-	if (!(buf = malloc(unicodelen * 2)))
-		return -1;
-
-	aim_bstream_init(&bs, buf, unicodelen * 2);
-
-	/* We assume unicode is in /host/ byte order -- convert to network */
-	for (i = 0; i < unicodelen; i++)
-		aimbs_put16(&bs, unicode[i]);
-
-	if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) {
-		free(buf);
-		return -1;
-	}
-	
-	return 0;
-}
-
-faim_export void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm)
-{
-	aim_mpmsg_section_t *cur;
-
-	for (cur = mpm->parts; cur; ) {
-		aim_mpmsg_section_t *tmp;
-		
-		tmp = cur->next;
-		free(cur->data);
-		free(cur);
-		cur = tmp;
-	}
-	
-	mpm->numparts = 0;
-	mpm->parts = NULL;
-
-	return;
-}
-
-/*
- * Start by building the multipart structures, then pick the first 
- * human-readable section and stuff it into args->msg so no one gets
- * suspicious.
- *
- */
-static int incomingim_ch1_parsemsgs(aim_session_t *sess, fu8_t *data, int len, struct aim_incomingim_ch1_args *args)
-{
-	static const fu16_t charsetpri[] = {
-		0x0000, /* ASCII first */
-		0x0003, /* then ISO-8859-1 */
-		0x0002, /* UNICODE as last resort */
-	};
-	static const int charsetpricount = 3;
-	int i;
-	aim_bstream_t mbs;
-	aim_mpmsg_section_t *sec;
-
-	aim_bstream_init(&mbs, data, len);
-
-	while (aim_bstream_empty(&mbs)) {
-		fu16_t msglen, flag1, flag2;
-		fu8_t *msgbuf;
-
-		aimbs_get8(&mbs); /* 01 */
-		aimbs_get8(&mbs); /* 01 */
-
-		/* Message string length, including character set info. */
-		msglen = aimbs_get16(&mbs);
-
-		/* Character set info */
-		flag1 = aimbs_get16(&mbs);
-		flag2 = aimbs_get16(&mbs);
-
-		/* Message. */
-		msglen -= 4;
-
-		/*
-		 * For now, we don't care what the encoding is.  Just copy
-		 * it into a multipart struct and deal with it later. However,
-		 * always pad the ending with a NULL.  This makes it easier
-		 * to treat ASCII sections as strings.  It won't matter for
-		 * UNICODE or binary data, as you should never read past
-		 * the specified data length, which will not include the pad.
-		 *
-		 * XXX - There's an API bug here.  For sending, the UNICODE is
-		 * given in host byte order (aim_mpmsg_addunicode), but here
-		 * the received messages are given in network byte order.
-		 *
-		 */
-		msgbuf = aimbs_getstr(&mbs, msglen);
-		mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, msgbuf, msglen);
-
-	} /* while */
-
-	args->icbmflags |= AIM_IMFLAGS_MULTIPART; /* always set */
-
-	/*
-	 * Clients that support multiparts should never use args->msg, as it
-	 * will point to an arbitrary section.
-	 *
-	 * Here, we attempt to provide clients that do not support multipart
-	 * messages with something to look at -- hopefully a human-readable
-	 * string.  But, failing that, a UNICODE message, or nothing at all.
-	 *
-	 * Which means that even if args->msg is NULL, it does not mean the
-	 * message was blank.
-	 *
-	 */
-	for (i = 0; i < charsetpricount; i++) {
-		for (sec = args->mpmsg.parts; sec; sec = sec->next) {
-
-			if (sec->charset != charsetpri[i])
-				continue;
-
-			/* Great. We found one.  Fill it in. */
-			args->charset = sec->charset;
-			args->charsubset = sec->charsubset;
-
-			/* Set up the simple flags */
-			if (args->charset == 0x0000)
-				; /* ASCII */
-			else if (args->charset == 0x0002)
-				args->icbmflags |= AIM_IMFLAGS_UNICODE;
-			else if (args->charset == 0x0003)
-				args->icbmflags |= AIM_IMFLAGS_ISO_8859_1;
-			else if (args->charset == 0xffff)
-				; /* no encoding (yeep!) */
-
-			if (args->charsubset == 0x0000)
-				; /* standard subencoding? */
-			else if (args->charsubset == 0x000b)
-				args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH;
-			else if (args->charsubset == 0xffff)
-				; /* no subencoding */
-
-			args->msg = sec->data;
-			args->msglen = sec->datalen;
-
-			return 0;
-		}
-	}
-
-	/* No human-readable sections found.  Oh well. */
-	args->charset = args->charsubset = 0xffff;
-	args->msg = NULL;
-	args->msglen = 0;
-
-	return 0;
-}
-
-static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_bstream_t *bs, fu8_t *cookie)
-{
-	fu16_t type, length;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	struct aim_incomingim_ch1_args args;
-	int endpos;
-
-	memset(&args, 0, sizeof(args));
-
-	aim_mpmsg_init(sess, &args.mpmsg);
-
-	/*
-	 * This used to be done using tlvchains.  For performance reasons,
-	 * I've changed it to process the TLVs in-place.  This avoids lots
-	 * of per-IM memory allocations.
-	 */
-	while (aim_bstream_empty(bs)) {
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		endpos = aim_bstream_curpos(bs) + length;
-
-		if (type == 0x0002) { /* Message Block */
-
-			/*
-			 * This TLV consists of the following:
-			 *   - 0501 -- Unknown
-			 *   - Features: Don't know how to interpret these
-			 *   - 0101 -- Unknown
-			 *   - Message
-			 *
-			 */
-
-			aimbs_get8(bs); /* 05 */
-			aimbs_get8(bs); /* 01 */
-
-			args.featureslen = aimbs_get16(bs);
-			/* XXX XXX this is all evil! */
-			args.features = bs->data + bs->offset;
-			aim_bstream_advance(bs, args.featureslen);
-			args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES;
-
-			/*
-			 * The rest of the TLV contains one or more message
-			 * blocks...
-			 */
-			incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args);
-
-		} else if (type == 0x0003) { /* Server Ack Requested */
-
-			args.icbmflags |= AIM_IMFLAGS_ACK;
-
-		} else if (type == 0x0004) { /* Message is Auto Response */
-
-			args.icbmflags |= AIM_IMFLAGS_AWAY;
-
-		} else if (type == 0x0006) { /* Message was received offline. */
-
-			/* XXX - not sure if this actually gets sent. */
-			args.icbmflags |= AIM_IMFLAGS_OFFLINE;
-
-		} else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
-
-			args.iconlen = aimbs_get32(bs);
-			aimbs_get16(bs); /* 0x0001 */
-			args.iconsum = aimbs_get16(bs);
-			args.iconstamp = aimbs_get32(bs);
-
-			/*
-			 * This looks to be a client bug.  MacAIM 4.3 will
-			 * send this tag, but with all zero values, in the
-			 * first message of a conversation. This makes no
-			 * sense whatsoever, so I'm going to say its a bug.
-			 *
-			 * You really shouldn't advertise a zero-length icon
-			 * anyway.
-			 * 
-			 */
-			if (args.iconlen)
-				args.icbmflags |= AIM_IMFLAGS_HASICON;
-
-		} else if (type == 0x0009) {
-
-			args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
-
-		} else if (type == 0x000b) { /* Non-direct connect typing notification */
-
-			args.icbmflags |= AIM_IMFLAGS_TYPINGNOT;
-
-		} else if (type == 0x0017) {
-
-			args.extdatalen = length;
-			args.extdata = aimbs_getraw(bs, args.extdatalen);
-
-		} else {
-			faimdprintf(sess, 0, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length);
-		}
-
-		/*
-		 * This is here to protect ourselves from ourselves.  That
-		 * is, if something above doesn't completly parse its value
-		 * section, or, worse, overparses it, this will set the
-		 * stream where it needs to be in order to land on the next
-		 * TLV when the loop continues.
-		 *
-		 */
-		aim_bstream_setpos(bs, endpos);
-	}
-
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-
-	aim_mpmsg_free(sess, &args.mpmsg);
-	free(args.extdata);
-
-	return ret;
-}
-
-static void incomingim_ch2_buddylist(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-
-	/*
-	 * This goes like this...
-	 *
-	 *   group name length
-	 *   group name
-	 *     num of buddies in group
-	 *     buddy name length
-	 *     buddy name
-	 *     buddy name length
-	 *     buddy name
-	 *     ...
-	 *   group name length
-	 *   group name
-	 *     num of buddies in group
-	 *     buddy name length
-	 *     buddy name
-	 *     ...
-	 *   ...
-	 */
-	while (servdata && aim_bstream_empty(servdata)) {
-		fu16_t gnlen, numb;
-		int i;
-		char *gn;
-
-		gnlen = aimbs_get16(servdata);
-		gn = aimbs_getstr(servdata, gnlen);
-		numb = aimbs_get16(servdata);
-
-		for (i = 0; i < numb; i++) {
-			fu16_t bnlen;
-			char *bn;
-
-			bnlen = aimbs_get16(servdata);
-			bn = aimbs_getstr(servdata, bnlen);
-
-			faimdprintf(sess, 0, "got a buddy list from %s: group %s, buddy %s\n", userinfo->sn, gn, bn);
-
-			free(bn);
-		}
-
-		free(gn);
-	}
-
-	return;
-}
-
-static void incomingim_ch2_buddyicon_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-
-	free(args->info.icon.icon);
-
-	return;
-}
-
-static void incomingim_ch2_buddyicon(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-
-	if (servdata) {
-		args->info.icon.checksum = aimbs_get32(servdata);
-		args->info.icon.length = aimbs_get32(servdata);
-		args->info.icon.timestamp = aimbs_get32(servdata);
-		args->info.icon.icon = aimbs_getraw(servdata, args->info.icon.length);
-	}
-
-	args->destructor = (void *)incomingim_ch2_buddyicon_free;
-
-	return;
-}
-
-static void incomingim_ch2_chat_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-
-	/* XXX - aim_chat_roominfo_free() */
-	free(args->info.chat.roominfo.name);
-
-	return;
-}
-
-static void incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-
-	/*
-	 * Chat room info.
-	 */
-	if (servdata)
-		aim_chat_readroominfo(servdata, &args->info.chat.roominfo);
-
-	args->destructor = (void *)incomingim_ch2_chat_free;
-
-	return;
-}
-
-static void incomingim_ch2_icqserverrelay_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-
-	free((char *)args->info.rtfmsg.rtfmsg);
-
-	return;
-}
-
-/*
- * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is 
- * kind of odd. This sends the client ICQRTF since that is all that I've seen
- * SERVERRELAY used for.
- *
- * Note that this is all little-endian.  Cringe.
- *
- */
-static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-	fu16_t hdrlen, anslen, msglen;
-	fu16_t msgtype;
-
-	hdrlen = aimbs_getle16(servdata);
-	aim_bstream_advance(servdata, hdrlen);
-
-	hdrlen = aimbs_getle16(servdata);
-	aim_bstream_advance(servdata, hdrlen);
-
-	msgtype = aimbs_getle16(servdata);
-	
-	anslen = aimbs_getle32(servdata);
-	aim_bstream_advance(servdata, anslen);
-
-	msglen = aimbs_getle16(servdata);
-	args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen);
-
-	args->info.rtfmsg.fgcolor = aimbs_getle32(servdata);
-	args->info.rtfmsg.bgcolor = aimbs_getle32(servdata);
-
-	hdrlen = aimbs_getle32(servdata);
-	aim_bstream_advance(servdata, hdrlen);
-
-	/* XXX - This is such a hack. */
-	args->reqclass = AIM_CAPS_ICQRTF;
-
-	args->destructor = (void *)incomingim_ch2_icqserverrelay_free;
-
-	return;
-}
-
-static void incomingim_ch2_sendfile_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-	free(args->info.sendfile.filename);
-}
-
-static void incomingim_ch2_sendfile(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-
-	args->destructor = (void *)incomingim_ch2_sendfile_free;
-
-	/* Maybe there is a better way to tell what kind of sendfile 
-	 * this is?  Maybe TLV t(000a)? */
-	if (servdata) { /* Someone is sending us a file */
-		int flen;
-
-		/* subtype is one of AIM_OFT_SUBTYPE_* */
-		args->info.sendfile.subtype = aimbs_get16(servdata);
-		args->info.sendfile.totfiles = aimbs_get16(servdata);
-		args->info.sendfile.totsize = aimbs_get32(servdata);
-
-		/*
-		 * I hope to God I'm right when I guess that there is a 
-		 * 32 char max filename length for single files.  I think 
-		 * OFT tends to do that.  Gotta love inconsistency.  I saw 
-		 * a 26 byte filename?
-		 */
-		/* AAA - create an aimbs_getnullstr function (don't anymore)(maybe) */
-		/* Use an inelegant way of getting the null-terminated filename, 
-		 * since there's no easy bstream routine. */
-		for (flen = 0; aimbs_get8(servdata); flen++);
-		aim_bstream_advance(servdata, -flen -1);
-		args->info.sendfile.filename = aimbs_getstr(servdata, flen);
-
-		/* There is sometimes more after the null-terminated filename, 
-		 * but I'm unsure of its format. */
-		/* I don't believe him. */
-	}
-
-	return;
-}
-
-typedef void (*ch2_args_destructor_t)(aim_session_t *sess, struct aim_incomingim_ch2_args *args);
-
-static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlv_t *block1, *servdatatlv;
-	aim_tlvlist_t *list2;
-	struct aim_incomingim_ch2_args args;
-	aim_bstream_t bbs, sdbs, *sdbsptr = NULL;
-	fu8_t *cookie2;
-	int ret = 0;
-
-	char proxyip[30] = {""};
-	char clientip[30] = {""};
-	char verifiedip[30] = {""};
-
-	memset(&args, 0, sizeof(args));
-
-	/*
-	 * There's another block of TLVs embedded in the type 5 here. 
-	 */
-	block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1);
-	aim_bstream_init(&bbs, block1->value, block1->length);
-
-	/*
-	 * First two bytes represent the status of the connection.
-	 *
-	 * 0 is a request, 1 is a cancel, 2 is an accept
-	 */ 
-	args.status = aimbs_get16(&bbs);
-
-	/*
-	 * Next comes the cookie.  Should match the ICBM cookie.
-	 */
-	cookie2 = aimbs_getraw(&bbs, 8);
-	if (memcmp(cookie, cookie2, 8) != 0) 
-		faimdprintf(sess, 0, "rend: warning cookies don't match!\n");
-	memcpy(args.cookie, cookie2, 8);
-	free(cookie2);
-
-	/*
-	 * The next 16bytes are a capability block so we can
-	 * identify what type of rendezvous this is.
-	 */
-	args.reqclass = aim_locate_getcaps(sess, &bbs, 0x10);
-
-	/* 
-	 * What follows may be TLVs or nothing, depending on the
-	 * purpose of the message.
-	 *
-	 * Ack packets for instance have nothing more to them.
-	 */
-	list2 = aim_tlvlist_read(&bbs);
-
-	/*
-	 * IP address to proxy the file transfer through.
-	 *
-	 * XXX - I don't like this.  Maybe just read in an int?  Or inet_ntoa...
-	 */
-	if (aim_tlv_gettlv(list2, 0x0002, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_tlv_gettlv(list2, 0x0002, 1);
-		if (iptlv->length == 4)
-			snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",
-				iptlv->value[0], iptlv->value[1],
-				iptlv->value[2], iptlv->value[3]);
-	}
-
-	/*
-	 * IP address from the perspective of the client.
-	 */
-	if (aim_tlv_gettlv(list2, 0x0003, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_tlv_gettlv(list2, 0x0003, 1);
-		if (iptlv->length == 4)
-			snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",
-				iptlv->value[0], iptlv->value[1],
-				iptlv->value[2], iptlv->value[3]);
-	}
-
-	/*
-	 * Verified IP address (from the perspective of Oscar).
-	 *
-	 * This is added by the server.
-	 */
-	if (aim_tlv_gettlv(list2, 0x0004, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_tlv_gettlv(list2, 0x0004, 1);
-		if (iptlv->length == 4)
-			snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",
-				iptlv->value[0], iptlv->value[1],
-				iptlv->value[2], iptlv->value[3]);
-	}
-
-	/*
-	 * Port number for something.
-	 */
-	if (aim_tlv_gettlv(list2, 0x0005, 1))
-		args.port = aim_tlv_get16(list2, 0x0005, 1);
-
-	/*
-	 * Something to do with ft -- two bytes
-	 * 0x0001 - "I want to send you this file"
-	 * 0x0002 - "I will accept this file from you"
-	 */
-	if (aim_tlv_gettlv(list2, 0x000a, 1))
-		;
-
-	/*
-	 * Error code.
-	 */
-	if (aim_tlv_gettlv(list2, 0x000b, 1))
-		args.errorcode = aim_tlv_get16(list2, 0x000b, 1);
-
-	/*
-	 * Invitation message / chat description.
-	 */
-	if (aim_tlv_gettlv(list2, 0x000c, 1))
-		args.msg = aim_tlv_getstr(list2, 0x000c, 1);
-
-	/*
-	 * Character set.
-	 */
-	if (aim_tlv_gettlv(list2, 0x000d, 1))
-		args.encoding = aim_tlv_getstr(list2, 0x000d, 1);
-	
-	/*
-	 * Language.
-	 */
-	if (aim_tlv_gettlv(list2, 0x000e, 1))
-		args.language = aim_tlv_getstr(list2, 0x000e, 1);
-
-	/*
-	 * Unknown -- no value
-	 *
-	 * Maybe means we should connect directly to transfer the file?
-	 */
-	if (aim_tlv_gettlv(list2, 0x000f, 1))
-		;
-
-	/*
-	 * Unknown -- no value
-	 *
-	 * Maybe means we should proxy the file transfer through an AIM server?
-	 */
-	if (aim_tlv_gettlv(list2, 0x0010, 1))
-		;
-
-	if (strlen(proxyip))
-		args.proxyip = (char *)proxyip;
-	if (strlen(clientip))
-		args.clientip = (char *)clientip;
-	if (strlen(verifiedip))
-		args.verifiedip = (char *)verifiedip;
-
-	/*
-	 * This must be present in PROPOSALs, but will probably not
-	 * exist in CANCELs and ACCEPTs.
-	 *
-	 * Service Data blocks are module-specific in format.
-	 */
-	if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) {
-
-		aim_bstream_init(&sdbs, servdatatlv->value, servdatatlv->length);
-		sdbsptr = &sdbs;
-	}
-
-	/*
-	 * The rest of the handling depends on what type it is.
-	 *
-	 * Not all of them have special handling (yet).
-	 */
-	if (args.reqclass & AIM_CAPS_BUDDYICON)
-		incomingim_ch2_buddyicon(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	else if (args.reqclass & AIM_CAPS_SENDBUDDYLIST)
-		incomingim_ch2_buddylist(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	else if (args.reqclass & AIM_CAPS_CHAT)
-		incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	else if (args.reqclass & AIM_CAPS_ICQSERVERRELAY)
-		incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	else if (args.reqclass & AIM_CAPS_SENDFILE)
-		incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-
-
-	if (args.destructor)
-		((ch2_args_destructor_t)args.destructor)(sess, &args);
-
-	free((char *)args.msg);
-	free((char *)args.encoding);
-	free((char *)args.language);
-
-	aim_tlvlist_free(&list2);
-
-	return ret;
-}
-
-static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie)
-{
-	aim_bstream_t meat;
-	aim_rxcallback_t userfunc;
-	aim_tlv_t *block;
-	struct aim_incomingim_ch4_args args;
-	int ret = 0;
-
-	/*
-	 * Make a bstream for the meaty part.  Yum.  Meat.
-	 */
-	if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1)))
-		return -1;
-	aim_bstream_init(&meat, block->value, block->length);
-
-	args.uin = aimbs_getle32(&meat);
-	args.type = aimbs_getle8(&meat);
-	args.flags = aimbs_getle8(&meat);
-	args.msglen = aimbs_getle16(&meat);
-	args.msg = aimbs_getraw(&meat, args.msglen);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-
-	free(args.msg);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0007
- *
- * It can easily be said that parsing ICBMs is THE single
- * most difficult thing to do in the in AIM protocol.  In
- * fact, I think I just did say that.
- *
- * Below is the best damned solution I've come up with
- * over the past sixteen months of battling with it. This
- * can parse both away and normal messages from every client
- * I have access to.  Its not fast, its not clean.  But it works.
- *
- */
-static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int i, ret = 0;
-	fu8_t cookie[8];
-	fu16_t channel;
-	aim_userinfo_t userinfo;
-
-	memset(&userinfo, 0x00, sizeof(aim_userinfo_t));
-
-	/*
-	 * Read ICBM Cookie.  And throw away.
-	 */
-	for (i = 0; i < 8; i++)
-		cookie[i] = aimbs_get8(bs);
-
-	/*
-	 * Channel ID.
-	 *
-	 * Channel 0x0001 is the message channel.  It is 
-	 * used to send basic ICBMs.
-	 *
-	 * Channel 0x0002 is the Rendevous channel, which
-	 * is where Chat Invitiations and various client-client
-	 * connection negotiations come from.
-	 *
-	 * Channel 0x0003 is used for chat messages.
-	 *
-	 * Channel 0x0004 is used for ICQ authorization, or 
-	 * possibly any system notice.
-	 *
-	 */
-	channel = aimbs_get16(bs);
-
-	/*
-	 * Extract the standard user info block.
-	 *
-	 * Note that although this contains TLVs that appear contiguous
-	 * with the TLVs read below, they are two different pieces.  The
-	 * userinfo block contains the number of TLVs that contain user
-	 * information, the rest are not even though there is no seperation.
-	 * You can start reading the message TLVs after aim_info_extract() 
-	 * parses out the standard userinfo block.
-	 *
-	 * That also means that TLV types can be duplicated between the
-	 * userinfo block and the rest of the message, however there should
-	 * never be two TLVs of the same type in one block.
-	 * 
-	 */
-	aim_info_extract(sess, bs, &userinfo);
-
-	/*
-	 * From here on, its depends on what channel we're on.
-	 *
-	 * Technically all channels have a TLV list have this, however,
-	 * for the common channel 1 case, in-place parsing is used for
-	 * performance reasons (less memory allocation).
-	 */
-	if (channel == 1) {
-
-		ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, bs, cookie);
-
-	} else if (channel == 2) {
-		aim_tlvlist_t *tlvlist;
-
-		/*
-		 * Read block of TLVs (not including the userinfo data).  All 
-		 * further data is derived from what is parsed here.
-		 */
-		tlvlist = aim_tlvlist_read(bs);
-
-		ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
-
-		aim_tlvlist_free(&tlvlist);
-
-	} else if (channel == 4) {
-		aim_tlvlist_t *tlvlist;
-
-		tlvlist = aim_tlvlist_read(bs);
-		ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
-		aim_tlvlist_free(&tlvlist);
-
-	} else {
-		faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.  (chan = %04x)\n", channel);
-	}
-
-	aim_info_free(&userinfo);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0008 - Send a warning to sn.
- * 
- * Flags:
- *  AIM_WARN_ANON  Send as an anonymous (doesn't count as much)
- *
- * returns -1 on error (couldn't alloc packet), 0 on success. 
- *
- */
-faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *sn, fu32_t flags)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(sn)+13)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1);
-	aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid);
-
-	aimbs_put16(&fr->data, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000); 
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x000a */
-static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t channel, nummissed, reason;
-	aim_userinfo_t userinfo;
-
-	while (aim_bstream_empty(bs)) {	
-
-		channel = aimbs_get16(bs);
-		aim_info_extract(sess, bs, &userinfo);
-		nummissed = aimbs_get16(bs);
-		reason = aimbs_get16(bs);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason);
-
-		aim_info_free(&userinfo);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x000b
- *
- * Possible codes:
- *    AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support"
- *    AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"
- *    AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"
- * 
- */
-faim_export int aim_im_denytransfer(aim_session_t *sess, const char *sender, const char *cookie, fu16_t code)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid);
-	
-	aimbs_putraw(&fr->data, cookie, 8);
-
-	aimbs_put16(&fr->data, 0x0002); /* channel */
-	aimbs_put8(&fr->data, strlen(sender));
-	aimbs_putraw(&fr->data, sender, strlen(sender));
-
-	aim_tlvlist_add_16(&tl, 0x0003, code);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x000b - Receive the response from an ICQ status message request.
- *
- * This contains the ICQ status message.  Go figure.
- *
- */
-static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t channel, reason;
-	char *sn;
-	fu8_t *ck, snlen;
-
-	ck = aimbs_getraw(bs, 8);
-	channel = aimbs_get16(bs);
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-	reason = aimbs_get16(bs);
-
-	if (channel == 0x0002) { /* File transfer declined */
-		aimbs_get16(bs); /* Unknown */
-		aimbs_get16(bs); /* Unknown */
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx, channel, sn, reason, ck);
-	} else if (channel == 0x0004) { /* ICQ message */
-		switch (reason) {
-			case 0x0003: { /* ICQ status message.  Maybe other stuff too, you never know with these people. */
-				fu8_t statusmsgtype, *msg;
-				fu16_t len;
-				fu32_t state;
-
-				len = aimbs_getle16(bs); /* Should be 0x001b */
-				aim_bstream_advance(bs, len); /* Unknown */
-
-				len = aimbs_getle16(bs); /* Should be 0x000e */
-				aim_bstream_advance(bs, len); /* Unknown */
-
-				statusmsgtype = aimbs_getle8(bs);
-				switch (statusmsgtype) {
-					case 0xe8:
-						state = AIM_ICQ_STATE_AWAY;
-						break;
-					case 0xe9:
-						state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
-						break;
-					case 0xea:
-						state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT;
-						break;
-					case 0xeb:
-						state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
-						break;
-					case 0xec:
-						state = AIM_ICQ_STATE_CHAT;
-						break;
-					default:
-						state = 0;
-						break;
-				}
-
-				aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */
-				aimbs_getle16(bs); /* Unknown - 0x0000 */
-				aimbs_getle16(bs); /* Unknown - 0x0000 */
-
-				len = aimbs_getle16(bs);
-				msg = aimbs_getraw(bs, len);
-
-				if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-					ret = userfunc(sess, rx, channel, sn, reason, state, msg);
-
-				free(msg);
-			} break;
-
-			default: {
-				if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-					ret = userfunc(sess, rx, channel, sn, reason);
-			} break;
-		} /* end switch */
-	}
-
-	free(ck);
-	free(sn);
-
-	return ret;
-}
-
-/*
- * Subtype 0x000c - Receive an ack after sending an ICBM.
- *
- * You have to have send the message with the AIM_IMFLAGS_ACK flag set 
- * (TLV t(0003)).  The ack contains the ICBM header of the message you 
- * sent.
- *
- */
-static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	fu16_t ch;
-	fu8_t *ck;
-	char *sn;
-	int ret = 0;
-
-	ck = aimbs_getraw(bs, 8);
-	ch = aimbs_get16(bs);
-	sn = aimbs_getstr(bs, aimbs_get8(bs));
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, ch, sn);
-
-	free(sn);
-	free(ck);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0014 - Send a mini typing notification (mtn) packet.
- *
- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, 
- * and Gaim 0.60 and newer.
- *
- */
-faim_export int aim_im_sendmtn(aim_session_t *sess, fu16_t type1, const char *sn, fu16_t type2)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002)))
-		return -EINVAL;
-
-	if (!sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+11+strlen(sn)+2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid);
-
-	/*
-	 * 8 days of light
-	 * Er, that is to say, 8 bytes of 0's
-	 */
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-
-	/*
-	 * Type 1 (should be 0x0001 for mtn)
-	 */
-	aimbs_put16(&fr->data, type1);
-
-	/*
-	 * Dest sn
-	 */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	/*
-	 * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn)
-	 */
-	aimbs_put16(&fr->data, type2);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0014 - Receive a mini typing notification (mtn) packet.
- *
- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, 
- * and Gaim 0.60 and newer.
- *
- */
-static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	char *sn;
-	fu8_t snlen;
-	fu16_t type1, type2;
-
-	aim_bstream_advance(bs, 8); /* Unknown - All 0's */
-	type1 = aimbs_get16(bs);
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-	type2 = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, type1, sn, type2);
-
-	free(sn);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0005)
-		return aim_im_paraminfo(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0006)
-		return outgoingim(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0007)
-		return incomingim(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000a)
-		return missedcall(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000b)
-		return clientautoresp(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000c)
-		return msgack(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0014)
-		return mtn_receive(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0004;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "messaging", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/invite.c
===================================================================
--- libfaim/invite.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * Family 0x0006 - This isn't really ever used by anyone anymore.
- *
- * Once upon a time, there used to be a menu item in AIM clients that
- * said something like "Invite a friend to use AIM..." and then it would
- * ask for an email address and it would sent a mail to them saying
- * how perfectly wonderful the AIM service is and why you should use it
- * and click here if you hate the person who sent this to you and want to
- * complain and yell at them in a small box with pretty fonts.
- *
- * I could've sworn libfaim had this implemented once, a long long time ago,
- * but I can't find it.
- *
- * I'm mainly adding this so that I can keep advertising that we support
- * group 6, even though we don't.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0006;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "invite", sizeof(mod->name));
-	mod->snachandler = NULL;
-
-	return 0;
-}
Index: bfaim/locate.c
===================================================================
--- libfaim/locate.c	(revision 6e3980ec43c1493159467eaaec6b67940a4ac6f0)
+++ 	(revision )
@@ -1,1319 +1,0 @@
-/*
- * Family 0x0002 - Locate.
- *
- * The functions here are responsible for requesting and parsing information-
- * gathering SNACs.  Or something like that.  This family contains the SNACs 
- * for getting and setting info, away messages, directory profile thingy, etc.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-/*
- * Capability blocks. 
- *
- * These are CLSIDs. They should actually be of the form:
- *
- * {0x0946134b, 0x4c7f, 0x11d1,
- *  {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
- *
- * But, eh.
- */
-static const struct {
-	fu32_t flag;
-	fu8_t data[16];
-} aim_caps[] = {
-
-	/*
-	 * These are in ascending numerical order.
-	 */
-
-	/*
-	 * Perhaps better called AIM_CAPS_SHORTCAPS
-	 */
-	{AIM_CAPS_ICHAT,
-	 {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_SECUREIM,
-	 {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_VIDEO,
-	 {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	/*
-	 * Not really sure about this one.  In an email from 
-	 * 26 Sep 2003, Matthew Sachs suggested that, "this 
-	 * is probably the capability for the SMS features."
-	 */
-	{AIM_CAPS_SMS,
-	 {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_GENERICUNKNOWN,
-	 {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_GENERICUNKNOWN,
-	 {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_GENERICUNKNOWN,
-	 {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_HIPTOP,
-	 {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_VOICE,
-	 {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_SENDFILE,
-	 {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_ICQ_DIRECT,
-	 {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_DIRECTIM,
-	 {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_BUDDYICON,
-	 {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	/*
-	 * Windows AIM calls this "Add-ins," which is probably more accurate
-	 */
-	{AIM_CAPS_SAVESTOCKS,
-	 {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_GETFILE,
-	 {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_ICQSERVERRELAY,
-	 {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	/*
-	 * Indeed, there are two of these.  The former appears to be correct, 
-	 * but in some versions of winaim, the second one is set.  Either they 
-	 * forgot to fix endianness, or they made a typo. It really doesn't 
-	 * matter which.
-	 */
-	{AIM_CAPS_GAMES,
-	 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-	{AIM_CAPS_GAMES2,
-	 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_SENDBUDDYLIST,
-	 {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	/*
-	 * Setting this lets AIM users receive messages from ICQ users, and ICQ 
-	 * users receive messages from AIM users.  It also lets ICQ users show 
-	 * up in buddy lists for AIM users, and AIM users show up in buddy lists 
-	 * for ICQ users.  And ICQ privacy/invisibility acts like AIM privacy, 
-	 * in that if you add a user to your deny list, you will not be able to 
-	 * see them as online (previous you could still see them, but they 
-	 * couldn't see you.
-	 */
-	{AIM_CAPS_INTEROPERATE,
-	 {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_ICQUTF8,
-	 {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1,
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	{AIM_CAPS_ICQUTF8OLD,
-	 {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
-	  0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
-
-	/*
-	 * Chat is oddball.
-	 */
-	{AIM_CAPS_CHAT,
-	 {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 
-	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-	/*
-	{AIM_CAPS_ICQ2GO,
-	 {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd,
-	  0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}},
-	*/
-
-	{AIM_CAPS_ICQRTF,
-	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
-	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},
-
-	/* This is added by the servers and it only shows up for ourselves... */
-	{AIM_CAPS_GENERICUNKNOWN,
-	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 
-	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}},
-
-	{AIM_CAPS_APINFO, 
-	 {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,
-	  0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},
-
-	{AIM_CAPS_TRILLIANCRYPT,
-	 {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,
-	  0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}},
-
-	{AIM_CAPS_EMPTY,
-	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
-
-	{AIM_CAPS_LAST}
-};
-
-/*
- * Add the userinfo to our linked list.  If we already have userinfo 
- * for this buddy, then just overwrite parts of the old data.
- * @param userinfo Contains the new information for the buddy.
- */
-static void aim_locate_adduserinfo(aim_session_t *sess, aim_userinfo_t *userinfo) {
-	aim_userinfo_t *cur;
-
-	cur = aim_locate_finduserinfo(sess, userinfo->sn);
-
-	if (cur == NULL) {
-		cur = (aim_userinfo_t *)calloc(1, sizeof(aim_userinfo_t));
-		cur->sn = strdup(userinfo->sn);
-		cur->next = sess->locate.userinfo;
-		sess->locate.userinfo = cur;
-	}
-
-	cur->warnlevel = userinfo->warnlevel;
-	cur->idletime = userinfo->idletime;
-	if (userinfo->flags != 0)
-		cur->flags = userinfo->flags;
-	if (userinfo->createtime != 0)
-		cur->createtime = userinfo->createtime;
-	if (userinfo->membersince != 0)
-		cur->membersince = userinfo->membersince;
-	if (userinfo->onlinesince != 0)
-		cur->onlinesince = userinfo->onlinesince;
-	if (userinfo->sessionlen != 0)
-		cur->sessionlen = userinfo->sessionlen;
-	if (userinfo->capabilities != 0)
-		cur->capabilities = userinfo->capabilities;
-	cur->present |= userinfo->present;
-
-	if (userinfo->iconcsumlen > 0) {
-		free(cur->iconcsum);
-		cur->iconcsum = (fu8_t *)malloc(userinfo->iconcsumlen);
-		memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen);
-		cur->iconcsumlen = userinfo->iconcsumlen;
-	}
-
-	if (userinfo->info != NULL) {
-		free(cur->info);
-		free(cur->info_encoding);
-		cur->info = (char *)malloc(userinfo->info_len);
-		memcpy(cur->info, userinfo->info, userinfo->info_len);
-		cur->info_encoding = strdup(userinfo->info_encoding);
-		cur->info_len = userinfo->info_len;
-	}
-
-	if (userinfo->away != NULL) {
-		free(cur->away);
-		free(cur->away_encoding);
-		cur->away = (char *)malloc(userinfo->away_len);
-		memcpy(cur->away, userinfo->away, userinfo->away_len);
-		cur->away_encoding = strdup(userinfo->away_encoding);
-		cur->away_len = userinfo->away_len;
-	}
-}
-
-static void aim_locate_dorequest(aim_session_t *sess) {
-	struct userinfo_node *cur = sess->locate.torequest;
-
-	if (cur == NULL)
-		return;
-
-	if (sess->locate.waiting_for_response == TRUE)
-		return;
-
-	sess->locate.waiting_for_response = TRUE;
-	aim_locate_getinfoshort(sess, cur->sn, 0x00000003);
-
-	/* Move this node to the "requested" queue */
-	sess->locate.torequest = cur->next;
-	cur->next = sess->locate.requested;
-	sess->locate.requested = cur;
-}
-
-/**
- * Remove this screen name from our queue.  If this info was resquested 
- * by our info request queue, then pop the next element off of the queue.
- *
- * @param sess The aim session.
- * @param sn Screen name of the info we just received.
- * @return True if the request was explicit (client requested the info), 
- *         false if the request was implicit (libfaim request the info).
- */
-static int aim_locate_gotuserinfo(aim_session_t *sess, const char *sn) {
-	struct userinfo_node *cur, *del;
-	int was_explicit = TRUE;
-
-	while ((sess->locate.requested != NULL) && (aim_sncmp(sn, sess->locate.requested->sn) == 0)) {
-		del = sess->locate.requested;
-		sess->locate.requested = del->next;
-		was_explicit = FALSE;
-		free(del->sn);
-		free(del);
-	}
-
-	cur = sess->locate.requested;
-	while ((cur != NULL) && (cur->next != NULL)) {
-		if (aim_sncmp(sn, cur->next->sn) == 0) {
-			del = cur->next;
-			cur->next = del->next;
-			was_explicit = FALSE;
-			free(del->sn);
-			free(del);
-		} else
-			cur = cur->next;
-	}
-
-	if (!was_explicit) {
-		sess->locate.waiting_for_response = FALSE;
-		aim_locate_dorequest(sess);
-	}
-
-	return was_explicit;
-}
-
-faim_internal void aim_locate_requestuserinfo(aim_session_t *sess, const char *sn) {
-	struct userinfo_node *cur;
-
-	/* Make sure we aren't already requesting info for this buddy */
-	cur = sess->locate.torequest;
-	while (cur != NULL) {
-		if (aim_sncmp(sn, cur->sn) == 0)
-			return;
-		cur = cur->next;
-	}
-
-	/* Add a new node to our request queue */
-	cur = (struct userinfo_node *)malloc(sizeof(struct userinfo_node));
-	cur->sn = strdup(sn);
-	cur->next = sess->locate.torequest;
-	sess->locate.torequest = cur;
-
-	/* Actually request some info up in this piece */
-	aim_locate_dorequest(sess);
-}
-
-faim_export aim_userinfo_t *aim_locate_finduserinfo(aim_session_t *sess, const char *sn) {
-	aim_userinfo_t *cur = sess->locate.userinfo;
-
-	while (cur != NULL) {
-		if (aim_sncmp(cur->sn, sn) == 0)
-			return cur;
-		cur = cur->next;
-	}
-
-	return NULL;
-}
-
-faim_internal fu32_t aim_locate_getcaps(aim_session_t *sess, aim_bstream_t *bs, int len)
-{
-	fu32_t flags = 0;
-	int offset;
-
-	for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) {
-		fu8_t *cap;
-		int i, identified;
-
-		cap = aimbs_getraw(bs, 0x10);
-
-		for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {
-			if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
-				flags |= aim_caps[i].flag;
-				identified++;
-				break; /* should only match once... */
-			}
-		}
-
-		if (!identified)
-			faimdprintf(sess, 0, "unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
-					cap[0], cap[1], cap[2], cap[3],
-					cap[4], cap[5],
-					cap[6], cap[7],
-					cap[8], cap[9],
-					cap[10], cap[11], cap[12], cap[13],
-					cap[14], cap[15]);
-
-		free(cap);
-	}
-
-	return flags;
-}
-
-faim_internal fu32_t aim_locate_getcaps_short(aim_session_t *sess, aim_bstream_t *bs, int len)
-{
-	fu32_t flags = 0;
-	int offset;
-
-	for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x02) {
-		fu8_t *cap;
-		int i, identified;
-
-		cap = aimbs_getraw(bs, 0x02);
-
-		for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {
-			if (memcmp(&aim_caps[i].data[2], cap, 0x02) == 0) {
-				flags |= aim_caps[i].flag;
-				identified++;
-				break; /* should only match once... */
-			}
-		}
-
-		if (!identified)
-			faimdprintf(sess, 0, "unknown short capability: {%02x%02x}\n", cap[0], cap[1]);
-
-		free(cap);
-	}
-
-	return flags;
-}
-
-faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps)
-{
-	int i;
-
-	if (!bs)
-		return -EINVAL;
-
-	for (i = 0; aim_bstream_empty(bs); i++) {
-
-		if (aim_caps[i].flag == AIM_CAPS_LAST)
-			break;
-
-		if (caps & aim_caps[i].flag)
-			aimbs_putraw(bs, aim_caps[i].data, 0x10);
-
-	}
-
-	return 0;
-}
-
-static void dumptlv(aim_session_t *sess, fu16_t type, aim_bstream_t *bs, fu8_t len)
-{
-	int i;
-
-	if (!sess || !bs || !len)
-		return;
-
-	faimdprintf(sess, 0, "userinfo:   type  =0x%04x\n", type);
-	faimdprintf(sess, 0, "userinfo:   length=0x%04x\n", len);
-	faimdprintf(sess, 0, "userinfo:   value:\n");
-
-	for (i = 0; i < len; i++) {
-		if ((i % 8) == 0)
-			faimdprintf(sess, 0, "\nuserinfo:        ");
-		faimdprintf(sess, 0, "0x%2x ", aimbs_get8(bs));
-	}
-
-	faimdprintf(sess, 0, "\n");
-
-	return;
-}
-
-faim_internal void aim_info_free(aim_userinfo_t *info)
-{
-	free(info->sn);
-	free(info->iconcsum);
-	free(info->info);
-	free(info->info_encoding);
-	free(info->avail);
-	free(info->avail_encoding);
-	free(info->away);
-	free(info->away_encoding);
-}
-
-/*
- * AIM is fairly regular about providing user info.  This is a generic 
- * routine to extract it in its standard form.
- */
-faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo)
-{
-	int curtlv, tlvcnt;
-	fu8_t snlen;
-
-	if (!bs || !outinfo)
-		return -EINVAL;
-
-	/* Clear out old data first */
-	memset(outinfo, 0x00, sizeof(aim_userinfo_t));
-
-	/*
-	 * Screen name.  Stored as an unterminated string prepended with a 
-	 * byte containing its length.
-	 */
-	snlen = aimbs_get8(bs);
-	outinfo->sn = aimbs_getstr(bs, snlen);
-
-	/*
-	 * Warning Level.  Stored as an unsigned short.
-	 */
-	outinfo->warnlevel = aimbs_get16(bs);
-
-	/*
-	 * TLV Count. Unsigned short representing the number of 
-	 * Type-Length-Value triples that follow.
-	 */
-	tlvcnt = aimbs_get16(bs);
-
-	/* 
-	 * Parse out the Type-Length-Value triples as they're found.
-	 */
-	for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
-		int endpos;
-		fu16_t type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		endpos = aim_bstream_curpos(bs) + length;
-
-		if (type == 0x0001) {
-			/*
-			 * Type = 0x0001: User flags
-			 * 
-			 * Specified as any of the following ORed together:
-			 *      0x0001  Trial (user less than 60days)
-			 *      0x0002  Unknown bit 2
-			 *      0x0004  AOL Main Service user
-			 *      0x0008  Unknown bit 4
-			 *      0x0010  Free (AIM) user 
-			 *      0x0020  Away
-			 *      0x0400  ActiveBuddy
-			 *
-			 */
-			outinfo->flags = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_FLAGS;
-
-		} else if (type == 0x0002) {
-			/*
-			 * Type = 0x0002: Account creation time. 
-			 *
-			 * The time/date that the user originally registered for
-			 * the service, stored in time_t format.
-			 *
-			 * I'm not sure how this differs from type 5 ("member
-			 * since").
-			 *
-			 * Note: This is the field formerly known as "member
-			 * since".  All these years and I finally found out
-			 * that I got the name wrong.
-			 */
-			outinfo->createtime = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_CREATETIME;
-
-		} else if (type == 0x0003) {
-			/*
-			 * Type = 0x0003: On-Since date.
-			 *
-			 * The time/date that the user started their current 
-			 * session, stored in time_t format.
-			 */
-			outinfo->onlinesince = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE;
-
-		} else if (type == 0x0004) {
-			/*
-			 * Type = 0x0004: Idle time.
-			 *
-			 * Number of minutes since the user actively used the 
-			 * service.
-			 *
-			 * Note that the client tells the server when to start
-			 * counting idle times, so this may or may not be 
-			 * related to reality.
-			 */
-			outinfo->idletime = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_IDLE;
-
-		} else if (type == 0x0005) {
-			/*
-			 * Type = 0x0005: Member since date. 
-			 *
-			 * The time/date that the user originally registered for
-			 * the service, stored in time_t format.
-			 *
-			 * This is sometimes sent instead of type 2 ("account
-			 * creation time"), particularly in the self-info.
-			 * And particularly for ICQ?
-			 */
-			outinfo->membersince = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE;
-
-		} else if (type == 0x0006) {
-			/*
-			 * Type = 0x0006: ICQ Online Status
-			 *
-			 * ICQ's Away/DND/etc "enriched" status. Some decoding 
-			 * of values done by Scott <darkagl@pcnet.com>
-			 */
-			aimbs_get16(bs);
-			outinfo->icqinfo.status = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS;
-
-		} else if (type == 0x0008) {
-			/*
-			 * Type = 0x0008
-			 *
-			 * Client type, or some such.
-			 */
-
-		} else if (type == 0x000a) {
-			/*
-			 * Type = 0x000a
-			 *
-			 * ICQ User IP Address.
-			 * Ahh, the joy of ICQ security.
-			 */
-			outinfo->icqinfo.ipaddr = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR;
-
-		} else if (type == 0x000c) {
-			/* 
-			 * Type = 0x000c
-			 *
-			 * random crap containing the IP address,
-			 * apparently a port number, and some Other Stuff.
-			 *
-			 * Format is:
-			 * 4 bytes - Our IP address, 0xc0 a8 01 2b for 192.168.1.43
-			 * 
-			 *
-			 */
-			aimbs_getrawbuf(bs, outinfo->icqinfo.crap, 0x25);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA;
-
-		} else if (type == 0x000d) {
-			/*
-			 * Type = 0x000d
-			 *
-			 * OSCAR Capability information.
-			 *
-			 */
-			outinfo->capabilities |= aim_locate_getcaps(sess, bs, length);
-			outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
-
-		} else if (type == 0x000e) {
-			/*
-			 * Type = 0x000e
-			 *
-			 * AOL capability information.
-			 *
-			 */
-
-		} else if ((type == 0x000f) || (type == 0x0010)) {
-			/*
-			 * Type = 0x000f: Session Length. (AIM)
-			 * Type = 0x0010: Session Length. (AOL)
-			 *
-			 * The duration, in seconds, of the user's current 
-			 * session.
-			 *
-			 * Which TLV type this comes in depends on the
-			 * service the user is using (AIM or AOL).
-			 *
-			 */
-			outinfo->sessionlen = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN;
-
-		} else if (type == 0x0019) {
-			/*
-			 * Type = 0x0019
-			 *
-			 * OSCAR short capability information.  A shortened 
-			 * form of the normal capabilities.
-			 */
-			outinfo->capabilities |= aim_locate_getcaps_short(sess, bs, length);
-			outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
-
-		} else if (type == 0x001b) {
-			/*
-			 * Type = 0x001a
-			 *
-			 * AOL short capability information.  A shortened 
-			 * form of the normal capabilities.
-			 */
-
-		} else if (type == 0x001b) {
-			/*
-			 * Type = 0x0019
-			 *
-			 * Encryption certification MD5 checksum.
-			 */
-
-		} else if (type == 0x001d) {
-			/*
-			 * Type = 0x001d
-			 *
-			 * Buddy icon information and available messages.
-			 *
-			 * This almost seems like the AIM protocol guys gave 
-			 * the iChat guys a Type, and the iChat guys tried to 
-			 * cram as much cool shit into it as possible.  Then 
-			 * the Windows AIM guys were like, "hey, that's 
-			 * pretty neat, let's copy those prawns."
-			 *
-			 * In that spirit, this can contain a custom message, 
-			 * kind of like an away message, but you're not away 
-			 * (it's called an "available" message).  Or it can 
-			 * contain information about the buddy icon the user 
-			 * has stored on the server.
-			 */
-			int type2, number, length2;
-
-			while (aim_bstream_curpos(bs) < endpos) {
-				type2 = aimbs_get16(bs);
-				number = aimbs_get8(bs);
-				length2 = aimbs_get8(bs);
-
-				switch (type2) {
-					case 0x0000: { /* This is an official buddy icon? */
-						/* This is always 5 bytes of "0x02 01 d2 04 72"? */
-						aim_bstream_advance(bs, length2);
-					} break;
-
-					case 0x0001: { /* A buddy icon checksum */
-						if ((length2 > 0) && (number == 0x01)) {
-							free(outinfo->iconcsum);
-							outinfo->iconcsum = aimbs_getraw(bs, length2);
-							outinfo->iconcsumlen = length2;
-						} else
-							aim_bstream_advance(bs, length2);
-					} break;
-
-					case 0x0002: { /* An available message */
-						if (length2 > 4) {
-							free(outinfo->avail);
-							outinfo->avail_len = aimbs_get16(bs);
-							outinfo->avail = aimbs_getstr(bs, outinfo->avail_len);
-							if (aimbs_get16(bs) == 0x0001) { /* We have an encoding */
-								aimbs_get16(bs);
-								outinfo->avail_encoding = aimbs_getstr(bs, aimbs_get16(bs));
-							} else {
-								/* No explicit encoding, client should use UTF-8 */
-								outinfo->avail_encoding = NULL;
-							}
-						} else
-							aim_bstream_advance(bs, length2);
-					} break;
-
-					default: {
-						aim_bstream_advance(bs, length2);
-					} break;
-				}
-			}
-
-		} else if (type == 0x001e) {
-			/*
-			 * Type 30: Unknown.
-			 *
-			 * Always four bytes, but it doesn't look like an int.
-			 */
-
-		} else if (type == 0x001f) {
-			/*
-			 * Type 31: Unknown.
-			 *
-			 * Seen on a buddy using DeadAIM.  Data was 4 bytes:
-			 * 0x00 00 00 10
-			 */
-
-		} else {
-
-			/*
-			 * Reaching here indicates that either AOL has
-			 * added yet another TLV for us to deal with, 
-			 * or the parsing has gone Terribly Wrong.
-			 *
-			 * Either way, inform the owner and attempt
-			 * recovery.
-			 *
-			 */
-			faimdprintf(sess, 0, "userinfo: **warning: unexpected TLV:\n");
-			faimdprintf(sess, 0, "userinfo:   sn    =%s\n", outinfo->sn);
-			dumptlv(sess, type, bs, length);
-		}
-
-		/* Save ourselves. */
-		aim_bstream_setpos(bs, endpos);
-	}
-
-	aim_locate_adduserinfo(sess, outinfo);
-
-	return 0;
-}
-
-/*
- * Inverse of aim_info_extract()
- */
-faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info)
-{
-	aim_tlvlist_t *tlvlist = NULL;
-
-	if (!bs || !info)
-		return -EINVAL;
-
-	aimbs_put8(bs, strlen(info->sn));
-	aimbs_putraw(bs, info->sn, strlen(info->sn));
-
-	aimbs_put16(bs, info->warnlevel);
-
-	if (info->present & AIM_USERINFO_PRESENT_FLAGS)
-		aim_tlvlist_add_16(&tlvlist, 0x0001, info->flags);
-	if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE)
-		aim_tlvlist_add_32(&tlvlist, 0x0002, info->membersince);
-	if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
-		aim_tlvlist_add_32(&tlvlist, 0x0003, info->onlinesince);
-	if (info->present & AIM_USERINFO_PRESENT_IDLE)
-		aim_tlvlist_add_16(&tlvlist, 0x0004, info->idletime);
-
-/* XXX - So, ICQ_OSCAR_SUPPORT is never defined anywhere... */
-#if ICQ_OSCAR_SUPPORT
-	if (atoi(info->sn) != 0) {
-		if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS)
-			aim_tlvlist_add_16(&tlvlist, 0x0006, info->icqinfo.status);
-		if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR)
-			aim_tlvlist_add_32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
-	}
-#endif
-
-	if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES)
-		aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities);
- 
-	if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
-		aim_tlvlist_add_32(&tlvlist, (fu16_t)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen);
-
-	aimbs_put16(bs, aim_tlvlist_count(&tlvlist));
-	aim_tlvlist_write(bs, &tlvlist);
-	aim_tlvlist_free(&tlvlist);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0001
- */
-static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-	fu16_t reason;
-	char *sn;
-	int was_explicit;
-
-	if (!(snac2 = aim_remsnac(sess, snac->id))) {
-		faimdprintf(sess, 0, "faim: locate.c, error(): received response from unknown request!\n");
-		return 0;
-	}
-
-	if ((snac2->family != 0x0002) && (snac2->type != 0x0015)) {
-		faimdprintf(sess, 0, "faim: locate.c, error(): received response from invalid request! %d\n", snac2->family);
-		return 0;
-	}
-
-	if (!(sn = snac2->data)) {
-		faimdprintf(sess, 0, "faim: locate.c, error(): received response from request without a screen name!\n");
-		return 0;
-	}
-
-	reason = aimbs_get16(bs);
-
-	/*
-	 * Remove this screen name from our queue.  If the client requested 
-	 * this buddy's info explicitly, then notify them that we do not have 
-	 * info for this buddy.
-	 */
-	was_explicit = aim_locate_gotuserinfo(sess, sn);
-	if (was_explicit == TRUE)
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx, reason, sn);
-
-	if (snac2)
-		free(snac2->data);
-	free(snac2);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0002
- *
- * Request Location services rights.
- *
- */
-faim_export int aim_locate_reqrights(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)))
-		return -EINVAL;
-
-	return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_LOC, AIM_CB_LOC_REQRIGHTS);
-}
-
-/*
- * Subtype 0x0003
- *
- * Normally contains:
- *   t(0001)  - short containing max profile length (value = 1024)
- *   t(0002)  - short - unknown (value = 16) [max MIME type length?]
- *   t(0003)  - short - unknown (value = 10)
- *   t(0004)  - short - unknown (value = 2048) [ICQ only?]
- */
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_tlvlist_t *tlvlist;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	fu16_t maxsiglen = 0;
-
-	tlvlist = aim_tlvlist_read(bs);
-
-	if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-		maxsiglen = aim_tlv_get16(tlvlist, 0x0001, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, maxsiglen);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0004
- *
- * Gives BOS your profile.
- *
- * profile_encoding and awaymsg_encoding MUST be set if profile or
- * away are set, respectively, and their value may or may not be
- * restricted to a few choices.  I am currently aware of:
- * 
- * us-ascii		Just that
- * unicode-2-0		UCS2-BE
- * 
- * profile_len and awaymsg_len MUST be set similarly, and they MUST
- * be the length of their respective strings in bytes.
- *
- * To get the previous behavior of awaymsg == "" un-setting the away
- * message, set awaymsg non-NULL and awaymsg_len to 0 (this is the
- * obvious equivalent).
- * 
- */
-faim_export int aim_locate_setprofile(aim_session_t *sess,
-				  const char *profile_encoding, const char *profile, const int profile_len,
-				  const char *awaymsg_encoding, const char *awaymsg, const int awaymsg_len)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	char *encoding;
-	static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)))
-		return -EINVAL;
-
-	if (!profile && !awaymsg)
-		return -EINVAL;
-
-	if ((profile && profile_encoding == NULL) || (awaymsg && awaymsg_len && awaymsg_encoding == NULL)) {
-		return -EINVAL;
-	}
-
-	/* Build the packet first to get real length */
-	if (profile) {
-		/* no + 1 here because of %s */
-		encoding = malloc(strlen(defencoding) + strlen(profile_encoding));
-		if (encoding == NULL) {
-			return -ENOMEM;
-		}
-		snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding);
-		aim_tlvlist_add_raw(&tl, 0x0001, strlen(encoding), encoding);
-		aim_tlvlist_add_raw(&tl, 0x0002, profile_len, profile);
-		free(encoding);
-	}
-
-	/*
-	 * So here's how this works:
-	 *   - You are away when you have a non-zero-length type 4 TLV stored.
-	 *   - You become unaway when you clear the TLV with a zero-length
-	 *       type 4 TLV.
-	 *   - If you do not send the type 4 TLV, your status does not change
-	 *       (that is, if you were away, you'll remain away).
-	 */
-	if (awaymsg) {
-		if (awaymsg_len) {
-			encoding = malloc(strlen(defencoding) + strlen(awaymsg_encoding));
-			if (encoding == NULL) {
-				return -ENOMEM;
-			}
-			snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
-			aim_tlvlist_add_raw(&tl, 0x0003, strlen(encoding), encoding);
-			aim_tlvlist_add_raw(&tl, 0x0004, awaymsg_len, awaymsg);
-			free(encoding);
-		} else
-			aim_tlvlist_add_noval(&tl, 0x0004);
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0004 - Set your client's capabilities.
- */
-faim_export int aim_locate_setcaps(aim_session_t *sess, fu32_t caps)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)))
-		return -EINVAL;
-
-	aim_tlvlist_add_caps(&tl, 0x0005, caps);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0005 - Request info of another AIM user.
- *
- * @param sn The screenname whose info you wish to request.
- * @param infotype The type of info you wish to request.
- *        0x0001 - Info/profile
- *        0x0003 - Away message
- *        0x0004 - Capabilities
- */
-faim_export int aim_locate_getinfo(aim_session_t *sess, const char *sn, fu16_t infotype)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, NULL, 0);
-	
-	aim_putsnac(&fr->data, 0x0002, 0x0005, 0x0000, snacid);
-	aimbs_put16(&fr->data, infotype);
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x0006 */
-static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_userinfo_t *userinfo, *userinfo2;
-	aim_tlvlist_t *tlvlist;
-	aim_tlv_t *tlv = NULL;
-	int was_explicit;
-
-	userinfo = (aim_userinfo_t *)malloc(sizeof(aim_userinfo_t));
-	aim_info_extract(sess, bs, userinfo);
-	tlvlist = aim_tlvlist_read(bs);
-
-	/* Profile will be 1 and 2 */
-	userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
-	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
-		userinfo->info = (char *)malloc(tlv->length);
-		memcpy(userinfo->info, tlv->value, tlv->length);
-		userinfo->info_len = tlv->length;
-	}
-
-	/* Away message will be 3 and 4 */
-	userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
-	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-		userinfo->away = (char *)malloc(tlv->length);
-		memcpy(userinfo->away, tlv->value, tlv->length);
-		userinfo->away_len = tlv->length;
-	}
-
-	/* Caps will be 5 */
-	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
-		aim_bstream_t cbs;
-		aim_bstream_init(&cbs, tlv->value, tlv->length);
-		userinfo->capabilities = aim_locate_getcaps(sess, &cbs, tlv->length);
-		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
-	}
-	aim_tlvlist_free(&tlvlist);
-
-	aim_locate_adduserinfo(sess, userinfo);
-	userinfo2 = aim_locate_finduserinfo(sess, userinfo->sn);
-	aim_info_free(userinfo);
-	free(userinfo);
-
-	/*
-	 * Remove this screen name from our queue.  If the client requested 
-	 * this buddy's info explicitly, then notify them that we have info 
-	 * for this buddy.
-	 */
-	was_explicit = aim_locate_gotuserinfo(sess, userinfo2->sn);
-	if (was_explicit == TRUE)
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx, userinfo2);
-
-	return ret;
-}
-
-/* 
- * Subtype 0x0009 - Set directory profile data.
- *
- * This is not the same as aim_location_setprofile!
- * privacy: 1 to allow searching, 0 to disallow.
- *
- */
-faim_export int aim_locate_setdirinfo(aim_session_t *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy) 
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)))
-		return -EINVAL;
-
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
-
-	if (first)
-		aim_tlvlist_add_raw(&tl, 0x0001, strlen(first), first);
-	if (last)
-		aim_tlvlist_add_raw(&tl, 0x0002, strlen(last), last);
-	if (middle)
-		aim_tlvlist_add_raw(&tl, 0x0003, strlen(middle), middle);
-	if (maiden)
-		aim_tlvlist_add_raw(&tl, 0x0004, strlen(maiden), maiden);
-
-	if (state)
-		aim_tlvlist_add_raw(&tl, 0x0007, strlen(state), state);
-	if (city)
-		aim_tlvlist_add_raw(&tl, 0x0008, strlen(city), city);
-
-	if (nickname)
-		aim_tlvlist_add_raw(&tl, 0x000c, strlen(nickname), nickname);
-	if (zip)
-		aim_tlvlist_add_raw(&tl, 0x000d, strlen(zip), zip);
-
-	if (street)
-		aim_tlvlist_add_raw(&tl, 0x0021, strlen(street), street);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0009, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, 0x0002, 0x0009, 0x0000, snacid);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x000b - Huh? What is this?
- */
-faim_export int aim_locate_000b(aim_session_t *sess, const char *sn)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-		return -EINVAL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x000b, 0x0000, NULL, 0);
-	
-	aim_putsnac(&fr->data, 0x0002, 0x000b, 0x0000, snacid);
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x000f
- * 
- * XXX pass these in better
- *
- */
-faim_export int aim_locate_setinterests(aim_session_t *sess, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)))
-		return -EINVAL;
-
-	/* ?? privacy ?? */
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
-
-	if (interest1)
-		aim_tlvlist_add_raw(&tl, 0x0000b, strlen(interest1), interest1);
-	if (interest2)
-		aim_tlvlist_add_raw(&tl, 0x0000b, strlen(interest2), interest2);
-	if (interest3)
-		aim_tlvlist_add_raw(&tl, 0x0000b, strlen(interest3), interest3);
-	if (interest4)
-		aim_tlvlist_add_raw(&tl, 0x0000b, strlen(interest4), interest4);
-	if (interest5)
-		aim_tlvlist_add_raw(&tl, 0x0000b, strlen(interest5), interest5);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x000f, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, 0x0002, 0x000f, 0x0000, 0);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0015 - Request the info a user using the short method.  This is 
- * what iChat uses.  It normally is VERY leniently rate limited.
- *
- * @param sn The screen name whose info you wish to request.
- * @param flags The bitmask which specifies the type of info you wish to request.
- *        0x00000001 - Info/profile.
- *        0x00000002 - Away message.
- *        0x00000004 - Capabilities.
- *        0x00000008 - Certification.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_locate_getinfoshort(aim_session_t *sess, const char *sn, fu32_t flags)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+1+strlen(sn))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0015, 0x0000, sn, strlen(sn)+1);
-
-	aim_putsnac(&fr->data, 0x0002, 0x0015, 0x0000, snacid);
-	aimbs_put32(&fr->data, flags);
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0001)
-		return error(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0003)
-		return rights(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0006)
-		return userinfo(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-static void locate_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	aim_userinfo_t *del;
-
-	while (sess->locate.userinfo) {
-		del = sess->locate.userinfo;
-		sess->locate.userinfo = sess->locate.userinfo->next;
-		aim_info_free(del);
-		free(del);
-	}
-}
-
-faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = AIM_CB_FAM_LOC;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "locate", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = locate_shutdown;
-
-	return 0;
-}
Index: bfaim/md5.c
===================================================================
--- libfaim/md5.c	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ 	(revision )
@@ -1,392 +1,0 @@
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.c is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
-  1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#ifdef TEST
-/*
- * Compile with -DTEST to create a self-contained executable test program.
- * The test program should print out the same values as given in section
- * A.5 of RFC 1321, reproduced below.
- */
-#include <string.h>
-main()
-{
-    static const char *const test[7] = {
-	"", /*d41d8cd98f00b204e9800998ecf8427e*/
-	"945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/
-	"abc", /*900150983cd24fb0d6963f7d28e17f72*/
-	"message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
-	"abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-				/*d174ab98d277d9f5a5611c2c9f419d9f*/
-	"12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
-    };
-    int i;
-
-    for (i = 0; i < 7; ++i) {
-	md5_state_t state;
-	md5_byte_t digest[16];
-	int di;
-
-	md5_init(&state);
-	md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
-	md5_finish(&state, digest);
-	printf("MD5 (\"%s\") = ", test[i]);
-	for (di = 0; di < 16; ++di)
-	    printf("%02x", digest[di]);
-	printf("\n");
-    }
-    return 0;
-}
-#endif /* TEST */
-
-
-/*
- * For reference, here is the program that computed the T values.
- */
-#if 0
-#include <math.h>
-main()
-{
-    int i;
-    for (i = 1; i <= 64; ++i) {
-	unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
-	printf("#define T%d 0x%08lx\n", i, v);
-    }
-    return 0;
-}
-#endif
-/*
- * End of T computation program.
- */
-#define T1 0xd76aa478
-#define T2 0xe8c7b756
-#define T3 0x242070db
-#define T4 0xc1bdceee
-#define T5 0xf57c0faf
-#define T6 0x4787c62a
-#define T7 0xa8304613
-#define T8 0xfd469501
-#define T9 0x698098d8
-#define T10 0x8b44f7af
-#define T11 0xffff5bb1
-#define T12 0x895cd7be
-#define T13 0x6b901122
-#define T14 0xfd987193
-#define T15 0xa679438e
-#define T16 0x49b40821
-#define T17 0xf61e2562
-#define T18 0xc040b340
-#define T19 0x265e5a51
-#define T20 0xe9b6c7aa
-#define T21 0xd62f105d
-#define T22 0x02441453
-#define T23 0xd8a1e681
-#define T24 0xe7d3fbc8
-#define T25 0x21e1cde6
-#define T26 0xc33707d6
-#define T27 0xf4d50d87
-#define T28 0x455a14ed
-#define T29 0xa9e3e905
-#define T30 0xfcefa3f8
-#define T31 0x676f02d9
-#define T32 0x8d2a4c8a
-#define T33 0xfffa3942
-#define T34 0x8771f681
-#define T35 0x6d9d6122
-#define T36 0xfde5380c
-#define T37 0xa4beea44
-#define T38 0x4bdecfa9
-#define T39 0xf6bb4b60
-#define T40 0xbebfbc70
-#define T41 0x289b7ec6
-#define T42 0xeaa127fa
-#define T43 0xd4ef3085
-#define T44 0x04881d05
-#define T45 0xd9d4d039
-#define T46 0xe6db99e5
-#define T47 0x1fa27cf8
-#define T48 0xc4ac5665
-#define T49 0xf4292244
-#define T50 0x432aff97
-#define T51 0xab9423a7
-#define T52 0xfc93a039
-#define T53 0x655b59c3
-#define T54 0x8f0ccc92
-#define T55 0xffeff47d
-#define T56 0x85845dd1
-#define T57 0x6fa87e4f
-#define T58 0xfe2ce6e0
-#define T59 0xa3014314
-#define T60 0x4e0811a1
-#define T61 0xf7537e82
-#define T62 0xbd3af235
-#define T63 0x2ad7d2bb
-#define T64 0xeb86d391
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
-    md5_word_t
-	a = pms->abcd[0], b = pms->abcd[1],
-	c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
-
-#ifndef ARCH_IS_BIG_ENDIAN
-# define ARCH_IS_BIG_ENDIAN 1	/* slower, default implementation */
-#endif
-#if ARCH_IS_BIG_ENDIAN
-
-    /*
-     * On big-endian machines, we must arrange the bytes in the right
-     * order.  (This also works on machines of unknown byte order.)
-     */
-    md5_word_t X[16];
-    const md5_byte_t *xp = data;
-    int i;
-
-    for (i = 0; i < 16; ++i, xp += 4)
-	X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-
-#else  /* !ARCH_IS_BIG_ENDIAN */
-
-    /*
-     * On little-endian machines, we can process properly aligned data
-     * without copying it.
-     */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
-
-    if (!((data - (const md5_byte_t *)0) & 3)) {
-	/* data are properly aligned */
-	X = (const md5_word_t *)data;
-    } else {
-	/* not aligned */
-	memcpy(xbuf, data, 64);
-	X = xbuf;
-    }
-#endif
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-     /* Round 2. */
-     /* Let [abcd k s i] denote the operation
-          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-     /* Round 3. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-     /* Round 4. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-     /* Then perform the following additions. (That is increment each
-        of the four registers by the value it had before this block
-        was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = 0xefcdab89;
-    pms->abcd[2] = 0x98badcfe;
-    pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-	return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-	pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-	memcpy(pms->buf + offset, p, copy);
-	if (offset + copy < 64)
-	    return;
-	p += copy;
-	left -= copy;
-	md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-	md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-	memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-    static const md5_byte_t pad[64] = {
-	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
Index: bfaim/md5.h
===================================================================
--- libfaim/md5.h	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ 	(revision )
@@ -1,93 +1,0 @@
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.h is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <purschke@bnl.gov>.
-  1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-#  define md5_INCLUDED
-
-/*
- * This code has some adaptations for the Ghostscript environment, but it
- * will compile and run correctly in any environment with 8-bit chars and
- * 32-bit ints.  Specifically, it assumes that if the following are
- * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
- * ARCH_IS_BIG_ENDIAN.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C" 
-{
-#endif
-
-/* Initialize the algorithm. */
-#ifdef P1
-void md5_init(P1(md5_state_t *pms));
-#else
-void md5_init(md5_state_t *pms);
-#endif
-
-/* Append a string to the message. */
-#ifdef P3
-void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));
-#else
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-#endif
-
-/* Finish the message and return the digest. */
-#ifdef P2
-void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));
-#else
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-#endif
-
-#ifdef __cplusplus
-}  /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
Index: bfaim/misc.c
===================================================================
--- libfaim/misc.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,147 +1,0 @@
-/*
- * misc.c
- *
- * Random stuff.  Basically just a few functions for sending 
- * simple SNACs, and then the generic error handler.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h> 
-
-/*
- * Generic routine for sending commands.
- *
- * I know I can do this in a smarter way...but I'm not thinking straight
- * right now...
- *
- * I had one big function that handled all three cases, but then it broke
- * and I split it up into three.  But then I fixed it.  I just never went
- * back to the single.  I don't see any advantage to doing it either way.
- *
- */
-faim_internal int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid = 0x00000000;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
-		return -ENOMEM;
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_internal int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_internal int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu32_t *longdata)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!longdata)
-		return aim_genericreq_n(sess, conn, family, subtype);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4)))
-		return -ENOMEM; 
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-	aimbs_put32(&fr->data, *longdata);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-faim_internal int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu16_t *shortdata)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!shortdata)
-		return aim_genericreq_n(sess, conn, family, subtype);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2)))
-		return -ENOMEM; 
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-	aimbs_put16(&fr->data, *shortdata);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Should be generic enough to handle the errors for all groups.
- *
- */
-static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	int error = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-
-	snac2 = aim_remsnac(sess, snac->id);
-
-	if (aim_bstream_empty(bs))
-		error = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);
-
-	if (snac2)
-		free(snac2->data);
-	free(snac2);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0001)
-		return generror(sess, mod, rx, snac, bs);
-	else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
-		aim_rxcallback_t userfunc;
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			return userfunc(sess, rx);
-	}
-
-	return 0;
-}
-
-faim_internal int misc_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0xffff;
-	mod->version = 0x0000;
-	mod->flags = AIM_MODFLAG_MULTIFAMILY;
-	strncpy(mod->name, "misc", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/msgcookie.c
===================================================================
--- libfaim/msgcookie.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * Cookie Caching stuff. Adam wrote this, apparently just some
- * derivatives of n's SNAC work. I cleaned it up, added comments.
- * 
- */
-
-/*
- * I'm assuming that cookies are type-specific. that is, we can have
- * "1234578" for type 1 and type 2 concurrently. if i'm wrong, then we
- * lose some error checking. if we assume cookies are not type-specific and are
- * wrong, we get quirky behavior when cookies step on each others' toes.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/**
- * aim_cachecookie - appends a cookie to the cookie list
- * @sess: session to add to
- * @cookie: pointer to struct to append
- *
- * if cookie->cookie for type cookie->type is found, updates the
- * ->addtime of the found structure; otherwise adds the given cookie
- * to the cache
- *
- * returns -1 on error, 0 on append, 1 on update.  the cookie you pass
- * in may be free'd, so don't count on its value after calling this!
- * 
- */
-faim_internal int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie)
-{
-	aim_msgcookie_t *newcook;
-
-	if (!sess || !cookie)
-		return -EINVAL;
-
-	newcook = aim_checkcookie(sess, cookie->cookie, cookie->type);
-	
-	if (newcook == cookie) {
-		newcook->addtime = time(NULL);
-		return 1;
-	} else if (newcook)
-		aim_cookie_free(sess, newcook);
-
-	cookie->addtime = time(NULL);  
-
-	cookie->next = sess->msgcookies;
-	sess->msgcookies = cookie;
-
-	return 0;
-}
-
-/**
- * aim_uncachecookie - grabs a cookie from the cookie cache (removes it from the list)
- * @sess: session to grab cookie from
- * @cookie: cookie string to look for
- * @type: cookie type to look for
- *
- * takes a cookie string and a cookie type and finds the cookie struct associated with that duple, removing it from the cookie list ikn the process.
- *
- * if found, returns the struct; if none found (or on error), returns NULL:
- */
-faim_internal aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, fu8_t *cookie, int type)
-{
-	aim_msgcookie_t *cur, **prev;
-
-	if (!cookie || !sess->msgcookies)
-		return NULL;
-
-	for (prev = &sess->msgcookies; (cur = *prev); ) {
-		if ((cur->type == type) && 
-				(memcmp(cur->cookie, cookie, 8) == 0)) {
-			*prev = cur->next;
-			return cur;
-		}
-		prev = &cur->next;
-	}
-
-	return NULL;
-}
-
-/**
- * aim_mkcookie - generate an aim_msgcookie_t *struct from a cookie string, a type, and a data pointer.
- * @c: pointer to the cookie string array
- * @type: cookie type to use
- * @data: data to be cached with the cookie
- *
- * returns NULL on error, a pointer to the newly-allocated cookie on
- * success.
- *
- */
-faim_internal aim_msgcookie_t *aim_mkcookie(fu8_t *c, int type, void *data) 
-{
-	aim_msgcookie_t *cookie;
-
-	if (!c)
-		return NULL;
-
-	if (!(cookie = calloc(1, sizeof(aim_msgcookie_t))))
-		return NULL;
-
-	cookie->data = data;
-	cookie->type = type;
-	memcpy(cookie->cookie, c, 8);
-
-	return cookie;
-}
-
-/**
- * aim_checkcookie - check to see if a cookietuple has been cached
- * @sess: session to check for the cookie in
- * @cookie: pointer to the cookie string array
- * @type: type of the cookie to look for
- *
- * this returns a pointer to the cookie struct (still in the list) on
- * success; returns NULL on error/not found
- *
- */
-
-faim_internal aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const fu8_t *cookie, int type)
-{
-	aim_msgcookie_t *cur;
-
-	for (cur = sess->msgcookies; cur; cur = cur->next) {
-		if ((cur->type == type) && 
-				(memcmp(cur->cookie, cookie, 8) == 0))
-			return cur;   
-	}
-
-	return NULL;
-}
-
-#if 0 /* debugging feature */
-faim_internal int aim_dumpcookie(aim_session_t *sess, aim_msgcookie_t *cookie) 
-{
-
-	if (!cookie)
-		return -EINVAL;
-
-	faimdprintf(sess, 0, "\tCookie at %p: %d/%s with %p, next %p\n", cookie, 
-			cookie->type, cookie->cookie, cookie->data, cookie->next);
-
-	return 0;
-}
-#endif
-
-/**
- * aim_cookie_free - free an aim_msgcookie_t struct
- * @sess: session to remove the cookie from
- * @cookiep: the address of a pointer to the cookie struct to remove
- *
- * this function removes the cookie *cookie from teh list of cookies
- * in sess, and then frees all memory associated with it. including
- * its data! if you want to use the private data after calling this,
- * make sure you copy it first.
- *
- * returns -1 on error, 0 on success.
- *
- */
-faim_internal int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie) 
-{
-	aim_msgcookie_t *cur, **prev;
-
-	if (!sess || !cookie)
-		return -EINVAL;
-
-	for (prev = &sess->msgcookies; (cur = *prev); ) {
-		if (cur == cookie)
-			*prev = cur->next;
-		else
-			prev = &cur->next;
-	}
-
-	free(cookie->data);
-	free(cookie);
-
-	return 0;
-} 
-
-/* XXX I hate switch */
-faim_internal int aim_msgcookie_gettype(int reqclass) 
-{
-	/* XXX: hokey-assed. needs fixed. */
-	switch(reqclass) {
-	case AIM_CAPS_BUDDYICON: return AIM_COOKIETYPE_OFTICON;
-	case AIM_CAPS_VOICE: return AIM_COOKIETYPE_OFTVOICE;
-	case AIM_CAPS_DIRECTIM: return AIM_COOKIETYPE_OFTIMAGE;
-	case AIM_CAPS_CHAT: return AIM_COOKIETYPE_CHAT;
-	case AIM_CAPS_GETFILE: return AIM_COOKIETYPE_OFTGET;
-	case AIM_CAPS_SENDFILE: return AIM_COOKIETYPE_OFTSEND;
-	default: return AIM_COOKIETYPE_UNKNOWN;
-	}           
-}
Index: bfaim/odir.c
===================================================================
--- libfaim/odir.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,245 +1,0 @@
-/*
- * Family 0x000f - Newer Search Method
- *
- * Used for searching for other AIM users by email address, name, 
- * location, commmon interests, and a few other similar things.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/**
- * Subtype 0x0002 - Submit a User Search Request
- *
- * Search for an AIM screen name based on their email address.
- *
- * @param sess The oscar session.
- * @param region Should be "us-ascii" unless you know what you're doing.
- * @param email The email address you want to search for.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_odir_email(aim_session_t *sess, const char *region, const char *email)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region || !email)
-		return -EINVAL;
-
-	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
-	aim_tlvlist_add_raw(&tl, 0x0005, strlen(email), email);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-
-/**
- * Subtype 0x0002 - Submit a User Search Request
- *
- * Search for an AIM screen name based on various info 
- * about the person.
- *
- * @param sess The oscar session.
- * @param region Should be "us-ascii" unless you know what you're doing.
- * @param first The first name of the person you want to search for.
- * @param middle The middle name of the person you want to search for.
- * @param last The last name of the person you want to search for.
- * @param maiden The maiden name of the person you want to search for.
- * @param nick The nick name of the person you want to search for.
- * @param city The city where the person you want to search for resides.
- * @param state The state where the person you want to search for resides.
- * @param country The country where the person you want to search for resides.
- * @param zip The zip code where the person you want to search for resides.
- * @param address The street address where the person you want to seach for resides.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_odir_name(aim_session_t *sess, const char *region, const char *first, const char *middle, const char *last, const char *maiden, const char *nick, const char *city, const char *state, const char *country, const char *zip, const char *address)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region)
-		return -EINVAL;
-
-	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0000); /* Type of search */
-	if (first)
-		aim_tlvlist_add_raw(&tl, 0x0001, strlen(first), first);
-	if (last)
-		aim_tlvlist_add_raw(&tl, 0x0002, strlen(last), last);
-	if (middle)
-		aim_tlvlist_add_raw(&tl, 0x0003, strlen(middle), middle);
-	if (maiden)
-		aim_tlvlist_add_raw(&tl, 0x0004, strlen(maiden), maiden);
-	if (country)
-		aim_tlvlist_add_raw(&tl, 0x0006, strlen(country), country);
-	if (state)
-		aim_tlvlist_add_raw(&tl, 0x0007, strlen(state), state);
-	if (city)
-		aim_tlvlist_add_raw(&tl, 0x0008, strlen(city), city);
-	if (nick)
-		aim_tlvlist_add_raw(&tl, 0x000c, strlen(nick), nick);
-	if (zip)
-		aim_tlvlist_add_raw(&tl, 0x000d, strlen(zip), zip);
-	if (address)
-		aim_tlvlist_add_raw(&tl, 0x0021, strlen(address), address);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-
-/**
- * Subtype 0x0002 - Submit a User Search Request
- *
- * @param sess The oscar session.
- * @param interest1 An interest you want to search for.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_odir_interest(aim_session_t *sess, const char *region, const char *interest)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region)
-		return -EINVAL;
-
-	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_raw(&tl, 0x001c, strlen(region), region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
-	if (interest)
-		aim_tlvlist_add_raw(&tl, 0x0001, strlen(interest), interest);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl))))
-		return -ENOMEM;
-	snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid);
-
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-
-/**
- * Subtype 0x0003 - Receive Reply From a User Search
- *
- */
-static int parseresults(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t tmp, numresults;
-	struct aim_odir *results = NULL;
-
-	tmp = aimbs_get16(bs); /* Unknown */
-	tmp = aimbs_get16(bs); /* Unknown */
-	aim_bstream_advance(bs, tmp);
-
-	numresults = aimbs_get16(bs); /* Number of results to follow */
-
-	/* Allocate a linked list, 1 node per result */
-	while (numresults) {
-		struct aim_odir *new;
-		aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, aimbs_get16(bs));
-		new = (struct aim_odir *)malloc(sizeof(struct aim_odir));
-		new->first = aim_tlv_getstr(tl, 0x0001, 1);
-		new->last = aim_tlv_getstr(tl, 0x0002, 1);
-		new->middle = aim_tlv_getstr(tl, 0x0003, 1);
-		new->maiden = aim_tlv_getstr(tl, 0x0004, 1);
-		new->email = aim_tlv_getstr(tl, 0x0005, 1);
-		new->country = aim_tlv_getstr(tl, 0x0006, 1);
-		new->state = aim_tlv_getstr(tl, 0x0007, 1);
-		new->city = aim_tlv_getstr(tl, 0x0008, 1);
-		new->sn = aim_tlv_getstr(tl, 0x0009, 1);
-		new->interest = aim_tlv_getstr(tl, 0x000b, 1);
-		new->nick = aim_tlv_getstr(tl, 0x000c, 1);
-		new->zip = aim_tlv_getstr(tl, 0x000d, 1);
-		new->region = aim_tlv_getstr(tl, 0x001c, 1);
-		new->address = aim_tlv_getstr(tl, 0x0021, 1);
-		new->next = results;
-		results = new;
-		numresults--;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, results);
-
-	/* Now free everything from above */
-	while (results) {
-		struct aim_odir *del = results;
-		results = results->next;
-		free(del->first);
-		free(del->last);
-		free(del->middle);
-		free(del->maiden);
-		free(del->email);
-		free(del->country);
-		free(del->state);
-		free(del->city);
-		free(del->sn);
-		free(del->interest);
-		free(del->nick);
-		free(del->zip);
-		free(del->region);
-		free(del->address);
-		free(del);
-	}
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return parseresults(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int odir_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000f;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "odir", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/oscar.c
===================================================================
--- libfaim/oscar.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,6711 +1,0 @@
-/*
- * gaim
- *
- * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- * Some code copyright (C) 1999-2001, Eric Warmenhoven
- * Some code copyright (C) 2001-2003, Sean Egan
- * Some code copyright (C) 2001-2003, Mark Doliner <thekingant@users.sourceforge.net>
- *
- * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx>
- * Some libfaim code copyright (C) 2001-2003 Mark Doliner <thekingant@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#include "internal.h"
-
-#include "account.h"
-#include "accountopt.h"
-#include "buddyicon.h"
-#include "conversation.h"
-#include "core.h"
-#include "debug.h"
-#include "ft.h"
-#include "imgstore.h"
-#include "multi.h"
-#include "notify.h"
-#include "privacy.h"
-#include "prpl.h"
-#include "proxy.h"
-#include "request.h"
-#include "util.h"
-
-#include "aim.h"
-#include "md5.h"
-
-#define UC_AOL		0x02
-#define UC_ADMIN	0x04
-#define UC_UNCONFIRMED	0x08
-#define UC_NORMAL	0x10
-#define UC_AB		0x20
-#define UC_WIRELESS	0x40
-#define UC_HIPTOP	0x80
-
-#define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3"
-
-#define OSCAR_CONNECT_STEPS 6
-
-static GaimPlugin *my_protocol = NULL;
-
-static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
-static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT;
-
-static fu8_t features_aim[] = {0x01, 0x01, 0x01, 0x02};
-static fu8_t features_icq[] = {0x01, 0x06};
-
-typedef struct _OscarData OscarData;
-struct _OscarData {
-	aim_session_t *sess;
-	aim_conn_t *conn;
-
-	guint cnpa;
-	guint paspa;
-	guint emlpa;
-	guint icopa;
-
-	gboolean iconconnecting;
-	gboolean set_icon;
-
-	GSList *create_rooms;
-
-	gboolean conf;
-	gboolean reqemail;
-	gboolean setemail;
-	char *email;
-	gboolean setnick;
-	char *newsn;
-	gboolean chpass;
-	char *oldp;
-	char *newp;
-	
-	GSList *oscar_chats;
-	GSList *direct_ims;
-	GSList *file_transfers;
-	GHashTable *buddyinfo;
-	GSList *requesticon;
-
-	gboolean killme;
-	gboolean icq;
-	guint icontimer;
-	guint getblisttimer;
-
-	struct {
-		guint maxwatchers; /* max users who can watch you */
-		guint maxbuddies; /* max users you can watch */
-		guint maxgroups; /* max groups in server list */
-		guint maxpermits; /* max users on permit list */
-		guint maxdenies; /* max users on deny list */
-		guint maxsiglen; /* max size (bytes) of profile */
-		guint maxawaymsglen; /* max size (bytes) of posted away message */
-	} rights;
-};
-
-struct create_room {
-	char *name;
-	int exchange;
-};
-
-struct chat_connection {
-	char *name;
-	char *show; /* AOL did something funny to us */
-	fu16_t exchange;
-	fu16_t instance;
-	int fd; /* this is redundant since we have the conn below */
-	aim_conn_t *conn;
-	int inpa;
-	int id;
-	GaimConnection *gc; /* i hate this. */
-	GaimConversation *cnv; /* bah. */
-	int maxlen;
-	int maxvis;
-};
-
-struct direct_im {
-	GaimConnection *gc;
-	char name[80];
-	int watcher;
-	aim_conn_t *conn;
-	gboolean connected;
-};
-
-struct ask_direct {
-	GaimConnection *gc;
-	char *sn;
-	char ip[64];
-	fu8_t cookie[8];
-};
-
-/*
- * Various PRPL-specific buddy info that we want to keep track of
- * Some other info is maintained by locate.c, and I'd like to move 
- * the rest of this to libfaim, mostly im.c
- */
-struct buddyinfo {
-	gboolean typingnot;
-	gchar *availmsg;
-	fu32_t ipaddr;
-
-	unsigned long ico_me_len;
-	unsigned long ico_me_csum;
-	time_t ico_me_time;
-	gboolean ico_informed;
-
-	unsigned long ico_len;
-	unsigned long ico_csum;
-	time_t ico_time;
-	gboolean ico_need;
-	gboolean ico_sent;
-};
-
-struct name_data {
-	GaimConnection *gc;
-	gchar *name;
-	gchar *nick;
-};
-
-static char *msgerrreason[] = {
-	N_("Invalid error"),
-	N_("Invalid SNAC"),
-	N_("Rate to host"),
-	N_("Rate to client"),
-	N_("Not logged in"),
-	N_("Service unavailable"),
-	N_("Service not defined"),
-	N_("Obsolete SNAC"),
-	N_("Not supported by host"),
-	N_("Not supported by client"),
-	N_("Refused by client"),
-	N_("Reply too big"),
-	N_("Responses lost"),
-	N_("Request denied"),
-	N_("Busted SNAC payload"),
-	N_("Insufficient rights"),
-	N_("In local permit/deny"),
-	N_("Too evil (sender)"),
-	N_("Too evil (receiver)"),
-	N_("User temporarily unavailable"),
-	N_("No match"),
-	N_("List overflow"),
-	N_("Request ambiguous"),
-	N_("Queue full"),
-	N_("Not while on AOL")
-};
-static int msgerrreasonlen = 25;
-
-/* All the libfaim->gaim callback functions */
-static int gaim_parse_auth_resp  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_login      (aim_session_t *, aim_frame_t *, ...);
-static int gaim_handle_redirect  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_info_change      (aim_session_t *, aim_frame_t *, ...);
-static int gaim_account_confirm  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_oncoming   (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_offgoing   (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_misses     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_userinfo   (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_motd       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_chatnav_info     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_conv_chat_join        (aim_session_t *, aim_frame_t *, ...);
-static int gaim_conv_chat_leave       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_conv_chat_info_update (aim_session_t *, aim_frame_t *, ...);
-static int gaim_conv_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
-static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...);
-static int gaim_icon_error       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_icon_parseicon   (aim_session_t *, aim_frame_t *, ...);
-static int oscar_icon_req        (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_msgack     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_evilnotify (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_searcherror(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_searchreply(aim_session_t *, aim_frame_t *, ...);
-static int gaim_bosrights        (aim_session_t *, aim_frame_t *, ...);
-static int gaim_connerr          (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_admin    (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_bos      (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_chatnav  (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_chat     (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_email    (aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_icon     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_msgerr     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_mtn        (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_locerr     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_icbm_param_info  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...);
-static int gaim_memrequest       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_selfinfo         (aim_session_t *, aim_frame_t *, ...);
-static int gaim_offlinemsg       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_offlinemsgdone   (aim_session_t *, aim_frame_t *, ...);
-static int gaim_icqalias         (aim_session_t *, aim_frame_t *, ...);
-static int gaim_icqinfo          (aim_session_t *, aim_frame_t *, ...);
-static int gaim_popup            (aim_session_t *, aim_frame_t *, ...);
-#ifndef NOSSI
-static int gaim_ssi_parseerr     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parserights  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parselist    (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parseack     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_authgiven    (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_authrequest  (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_authreply    (aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_gotadded     (aim_session_t *, aim_frame_t *, ...);
-#endif
-
-/* for DirectIM/image transfer */
-static int gaim_odc_initiate     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_odc_incoming     (aim_session_t *, aim_frame_t *, ...);
-static int gaim_odc_typing       (aim_session_t *, aim_frame_t *, ...);
-static int gaim_odc_update_ui    (aim_session_t *, aim_frame_t *, ...);
-
-/* for file transfer */
-static int oscar_sendfile_estblsh(aim_session_t *, aim_frame_t *, ...);
-static int oscar_sendfile_prompt (aim_session_t *, aim_frame_t *, ...);
-static int oscar_sendfile_ack    (aim_session_t *, aim_frame_t *, ...);
-static int oscar_sendfile_done   (aim_session_t *, aim_frame_t *, ...);
-
-/* for icons */
-static gboolean gaim_icon_timerfunc(gpointer data);
-
-/* prpl actions - remove this at some point */
-/* Because I don't like forward declarations?  I think that was why... */
-static void oscar_set_info(GaimConnection *gc, const char *text);
-
-static void oscar_free_name_data(struct name_data *data) {
-	g_free(data->name);
-	g_free(data->nick);
-	g_free(data);
-}
-
-static void oscar_free_buddyinfo(void *data) {
-	struct buddyinfo *bi = data;
-	g_free(bi->availmsg);
-	g_free(bi);
-}
-
-static fu32_t oscar_encoding_check(const char *utf8)
-{
-	int i = 0;
-	fu32_t encodingflag = 0;
-
-	/* Determine how we can send this message.  Per the warnings elsewhere 
-	 * in this file, these little checks determine the simplest encoding 
-	 * we can use for a given message send using it. */
-	while (utf8[i]) {
-		if ((unsigned char)utf8[i] > 0x7f) {
-			/* not ASCII! */
-			encodingflag = AIM_IMFLAGS_ISO_8859_1;
-			break;
-		}
-		i++;
-	}
-	while (utf8[i]) {
-		/* ISO-8859-1 is 0x00-0xbf in the first byte
-		 * followed by 0xc0-0xc3 in the second */
-		if ((unsigned char)utf8[i] < 0x80) {
-			i++;
-			continue;
-		} else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 &&
-			   ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) {
-			i += 2;
-			continue;
-		}
-		encodingflag = AIM_IMFLAGS_UNICODE;
-		break;
-	}
-
-	return encodingflag;
-}
-
-static fu32_t oscar_encoding_parse(const char *enc)
-{
-	char *charset;
-
-	/* If anything goes wrong, fall back on ASCII and print a message */
-	if (enc == NULL) {
-		gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-				   "Encoding was null, that's odd\n");
-		return 0;
-	}
-	charset = strstr(enc, "charset=");
-	if (charset == NULL) {
-		gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-				   "No charset specified for info, assuming ASCII\n");
-		return 0;
-	}
-	charset += 8;
-	if (!strcmp(charset, "\"us-ascii\"") || !strcmp(charset, "\"utf-8\"")) {
-		/* UTF-8 is our native charset, ASCII is a proper subset */
-		return 0;
-	} else if (!strcmp(charset, "\"iso-8859-1\"")) {
-		return AIM_IMFLAGS_ISO_8859_1;
-	} else if (!strcmp(charset, "\"unicode-2-0\"")) {
-		return AIM_IMFLAGS_UNICODE;
-	} else {
-		gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-				   "Unrecognized character set '%s', using ASCII\n", charset);
-		return 0;
-	}
-}
-
-gchar *oscar_encoding_to_utf8(const char *encoding, char *text, int textlen)
-{
-	gchar *utf8 = NULL;
-	int flags = oscar_encoding_parse(encoding);
-
-	switch (flags) {
-	case 0:
-		utf8 = g_strndup(text, textlen);
-		break;
-	case AIM_IMFLAGS_ISO_8859_1:
-		utf8 = g_convert(text, textlen, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
-		break;
-	case AIM_IMFLAGS_UNICODE:
-		utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL);
-		break;
-	}
-
-	return utf8;
-}
-
-static struct direct_im *find_direct_im(OscarData *od, const char *who) {
-	GSList *d = od->direct_ims;
-	struct direct_im *m = NULL;
-
-	while (d) {
-		m = (struct direct_im *)d->data;
-		if (!aim_sncmp(who, m->name))
-			return m;
-		d = d->next;
-	}
-
-	return NULL;
-}
-
-static char *extract_name(const char *name) {
-	char *tmp, *x;
-	int i, j;
-
-	if (!name)
-		return NULL;
-	
-	x = strchr(name, '-');
-
-	if (!x) return NULL;
-	x = strchr(++x, '-');
-	if (!x) return NULL;
-	tmp = g_strdup(++x);
-
-	for (i = 0, j = 0; x[i]; i++) {
-		char hex[3];
-		if (x[i] != '%') {
-			tmp[j++] = x[i];
-			continue;
-		}
-		strncpy(hex, x + ++i, 2); hex[2] = 0;
-		i++;
-		tmp[j++] = strtol(hex, NULL, 16);
-	}
-
-	tmp[j] = 0;
-	return tmp;
-}
-
-static struct chat_connection *find_oscar_chat(GaimConnection *gc, int id) {
-	GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
-	struct chat_connection *c = NULL;
-
-	while (g) {
-		c = (struct chat_connection *)g->data;
-		if (c->id == id)
-			break;
-		g = g->next;
-		c = NULL;
-	}
-
-	return c;
-}
-
-static struct chat_connection *find_oscar_chat_by_conn(GaimConnection *gc,
-							aim_conn_t *conn) {
-	GSList *g = ((OscarData *)gc->proto_data)->oscar_chats;
-	struct chat_connection *c = NULL;
-
-	while (g) {
-		c = (struct chat_connection *)g->data;
-		if (c->conn == conn)
-			break;
-		g = g->next;
-		c = NULL;
-	}
-
-	return c;
-}
-
-static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	GaimConversation *cnv;
-	struct direct_im *dim;
-	char *sn;
-	char buf[256];
-
-	sn = g_strdup(aim_odc_getsn(conn));
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "%s disconnected Direct IM.\n", sn);
-
-	dim = find_direct_im(od, sn);
-	od->direct_ims = g_slist_remove(od->direct_ims, dim);
-	gaim_input_remove(dim->watcher);
-
-	if (dim->connected)
-		g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn);
-	else 
-		g_snprintf(buf, sizeof buf, _("Direct IM with %s failed"), sn);
-
-	cnv = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc));
-	if (cnv)
-		gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));
-
-	gaim_conversation_update_progress(cnv, 0);
-
-	g_free(dim); /* I guess? I don't see it anywhere else... -- mid */
-	g_free(sn);
-
-	return;
-}
-
-static void oscar_callback(gpointer data, gint source, GaimInputCondition condition) {
-	aim_conn_t *conn = (aim_conn_t *)data;
-	aim_session_t *sess = aim_conn_getsess(conn);
-	GaimConnection *gc = sess ? sess->aux_data : NULL;
-	OscarData *od;
-
-	if (!gc) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "oscar callback for closed connection (1).\n");
-		return;
-	}
-      
-	od = (OscarData *)gc->proto_data;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		/* oh boy. this is probably bad. i guess the only thing we 
-		 * can really do is return? */
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "oscar callback for closed connection (2).\n");
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "gc = %p\n", gc);
-		return;
-	}
-
-	if (condition & GAIM_INPUT_READ) {
-		if (conn->type == AIM_CONN_TYPE_LISTENER) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "got information on rendezvous listener\n");
-			if (aim_handlerendconnect(od->sess, conn) < 0) {
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "connection error (rendezvous listener)\n");
-				aim_conn_kill(od->sess, &conn);
-			}
-		} else {
-			if (aim_get_command(od->sess, conn) >= 0) {
-				aim_rxdispatch(od->sess);
-				if (od->killme) {
-					gaim_debug(GAIM_DEBUG_ERROR, "oscar", "Waiting to be destroyed\n");
-					return;
-				}
-			} else {
-				if ((conn->type == AIM_CONN_TYPE_BOS) ||
-					   !(aim_getconn_type(od->sess, AIM_CONN_TYPE_BOS))) {
-					gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-							   "major connection error\n");
-					gaim_connection_error(gc, _("Disconnected."));
-				} else if (conn->type == AIM_CONN_TYPE_CHAT) {
-					struct chat_connection *c = find_oscar_chat_by_conn(gc, conn);
-					char *buf;
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "disconnected from chat room %s\n", c->name);
-					c->conn = NULL;
-					if (c->inpa > 0)
-						gaim_input_remove(c->inpa);
-					c->inpa = 0;
-					c->fd = -1;
-					aim_conn_kill(od->sess, &conn);
-					buf = g_strdup_printf(_("You have been disconnected from chat room %s."), c->name);
-					gaim_notify_error(gc, NULL, buf, NULL);
-					g_free(buf);
-				} else if (conn->type == AIM_CONN_TYPE_CHATNAV) {
-					if (od->cnpa > 0)
-						gaim_input_remove(od->cnpa);
-					od->cnpa = 0;
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "removing chatnav input watcher\n");
-					while (od->create_rooms) {
-						struct create_room *cr = od->create_rooms->data;
-						g_free(cr->name);
-						od->create_rooms =
-							g_slist_remove(od->create_rooms, cr);
-						g_free(cr);
-						gaim_notify_error(gc, NULL,
-										  _("Chat is currently unavailable"),
-										  NULL);
-					}
-					aim_conn_kill(od->sess, &conn);
-				} else if (conn->type == AIM_CONN_TYPE_AUTH) {
-					if (od->paspa > 0)
-						gaim_input_remove(od->paspa);
-					od->paspa = 0;
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "removing authconn input watcher\n");
-					aim_conn_kill(od->sess, &conn);
-				} else if (conn->type == AIM_CONN_TYPE_EMAIL) {
-					if (od->emlpa > 0)
-						gaim_input_remove(od->emlpa);
-					od->emlpa = 0;
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "removing email input watcher\n");
-					aim_conn_kill(od->sess, &conn);
-				} else if (conn->type == AIM_CONN_TYPE_ICON) {
-					if (od->icopa > 0)
-						gaim_input_remove(od->icopa);
-					od->icopa = 0;
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "removing icon input watcher\n");
-					aim_conn_kill(od->sess, &conn);
-				} else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
-					if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
-						gaim_odc_disconnect(od->sess, conn);
-					aim_conn_kill(od->sess, &conn);
-				} else {
-					gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-							   "holy crap! generic connection error! %hu\n",
-							   conn->type);
-					aim_conn_kill(od->sess, &conn);
-				}
-			}
-		}
-	}
-}
-
-static void oscar_debug(aim_session_t *sess, int level, const char *format, va_list va) {
-	GaimConnection *gc = sess->aux_data;
-	gchar *s = g_strdup_vprintf(format, va);
-	gchar *buf;
-
-	buf = g_strdup_printf("%s %d: %s", gaim_account_get_username(gaim_connection_get_account(gc)), level, s);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", buf);
-	if (buf[strlen(buf)-1] != '\n')
-		gaim_debug(GAIM_DEBUG_INFO, NULL, "\n");
-	g_free(buf);
-	g_free(s);
-}
-
-static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond)
-{
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *conn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
-	conn->fd = source;
-
-	if (source < 0) {
-		gaim_connection_error(gc, _("Couldn't connect to host"));
-		return;
-	}
-
-	aim_conn_completeconnect(sess, conn);
-	gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn);
-	aim_request_login(sess, conn, gaim_account_get_username(gaim_connection_get_account(gc)));
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Screen name sent, waiting for response\n");
-	gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);
-}
-
-static void oscar_login(GaimAccount *account) {
-	aim_session_t *sess;
-	aim_conn_t *conn;
-	GaimConnection *gc = gaim_account_get_connection(account);
-	OscarData *od = gc->proto_data = g_new0(OscarData, 1);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar", "oscar_login: gc = %p\n", gc);
-
-	if (isdigit(*(gaim_account_get_username(account)))) {
-		od->icq = TRUE;
-	} else {
-		gc->flags |= GAIM_CONNECTION_HTML;
-		gc->flags |= GAIM_CONNECTION_AUTO_RESP;
-	}
-	od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo);
-
-	sess = g_new0(aim_session_t, 1);
-	aim_session_init(sess, TRUE, 0);
-	aim_setdebuggingcb(sess, oscar_debug);
-	/*
-	 * We need an immediate queue because we don't use a while-loop 
-	 * to see if things need to be sent.
-	 */
-	aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
-	od->sess = sess;
-	sess->aux_data = gc;
-
-	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
-	if (conn == NULL) {
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "internal connection error\n");
-		gaim_connection_error(gc, _("Unable to login to AIM"));
-		return;
-	}
-
-	aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-	aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
-	aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0);
-
-	conn->status |= AIM_CONN_STATUS_INPROGRESS;
-	if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", FAIM_LOGIN_SERVER),
-			  gaim_account_get_int(account, "port", FAIM_LOGIN_PORT),
-			  oscar_login_connect, gc) < 0) {
-		gaim_connection_error(gc, _("Couldn't connect to host"));
-		return;
-	}
-
-	gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
-}
-
-static void oscar_close(GaimConnection *gc) {
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	while (od->oscar_chats) {
-		struct chat_connection *n = od->oscar_chats->data;
-		if (n->inpa > 0)
-			gaim_input_remove(n->inpa);
-		g_free(n->name);
-		g_free(n->show);
-		od->oscar_chats = g_slist_remove(od->oscar_chats, n);
-		g_free(n);
-	}
-	while (od->direct_ims) {
-		struct direct_im *n = od->direct_ims->data;
-		if (n->watcher > 0)
-			gaim_input_remove(n->watcher);
-		od->direct_ims = g_slist_remove(od->direct_ims, n);
-		g_free(n);
-	}
-/* BBB */
-	while (od->file_transfers) {
-		GaimXfer *xfer;
-		xfer = (GaimXfer *)od->file_transfers->data;
-		gaim_xfer_destroy(xfer);
-	}
-	while (od->requesticon) {
-		char *sn = od->requesticon->data;
-		od->requesticon = g_slist_remove(od->requesticon, sn);
-		free(sn);
-	}
-	g_hash_table_destroy(od->buddyinfo);
-	while (od->create_rooms) {
-		struct create_room *cr = od->create_rooms->data;
-		g_free(cr->name);
-		od->create_rooms = g_slist_remove(od->create_rooms, cr);
-		g_free(cr);
-	}
-	if (od->email)
-		g_free(od->email);
-	if (od->newp)
-		g_free(od->newp);
-	if (od->oldp)
-		g_free(od->oldp);
-	if (gc->inpa > 0)
-		gaim_input_remove(gc->inpa);
-	if (od->cnpa > 0)
-		gaim_input_remove(od->cnpa);
-	if (od->paspa > 0)
-		gaim_input_remove(od->paspa);
-	if (od->emlpa > 0)
-		gaim_input_remove(od->emlpa);
-	if (od->icopa > 0)
-		gaim_input_remove(od->icopa);
-	if (od->icontimer > 0)
-		g_source_remove(od->icontimer);
-	if (od->getblisttimer)
-		g_source_remove(od->getblisttimer);
-	aim_session_kill(od->sess);
-	g_free(od->sess);
-	od->sess = NULL;
-	g_free(gc->proto_data);
-	gc->proto_data = NULL;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "Signed off.\n");
-}
-
-static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *bosconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	bosconn = od->conn;	
-	bosconn->fd = source;
-
-	if (source < 0) {
-		gaim_connection_error(gc, _("Could Not Connect"));
-		return;
-	}
-
-	aim_conn_completeconnect(sess, bosconn);
-	gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn);
-
-	gaim_connection_update_progress(gc,
-			_("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
-}
-
-/* BBB */
-/*
- * This little area in oscar.c is the nexus of file transfer code, 
- * so I wrote a little explanation of what happens.  I am such a 
- * ninja.
- *
- * The series of events for a file send is:
- *  -Create xfer and call gaim_xfer_request (this happens in oscar_ask_sendfile)
- *  -User chooses a file and oscar_xfer_init is called.  It establishs a 
- *   listening socket, then asks the remote user to connect to us (and 
- *   gives them the file name, port, IP, etc.)
- *  -They connect to us and we send them an AIM_CB_OFT_PROMPT (this happens 
- *   in oscar_sendfile_estblsh)
- *  -They send us an AIM_CB_OFT_ACK and then we start sending data
- *  -When we finish, they send us an AIM_CB_OFT_DONE and they close the 
- *   connection.
- *  -We get drunk because file transfer kicks ass.
- *
- * The series of events for a file receive is:
- *  -Create xfer and call gaim_xfer request (this happens in incomingim_chan2)
- *  -Gaim user selects file to name and location to save file to and 
- *   oscar_xfer_init is called
- *  -It connects to the remote user using the IP they gave us earlier
- *  -After connecting, they send us an AIM_CB_OFT_PROMPT.  In reply, we send 
- *   them an AIM_CB_OFT_ACK.
- *  -They begin to send us lots of raw data.
- *  -When they finish sending data we send an AIM_CB_OFT_DONE and then close 
- *   the connectionn.
- */
-static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition);
-
-/* XXX - This function is pretty ugly */
-static void oscar_xfer_init(GaimXfer *xfer)
-{
-	struct aim_oft_info *oft_info = xfer->data;
-	GaimConnection *gc = oft_info->sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
-		int i;
-
-		xfer->filename = g_path_get_basename(xfer->local_filename);
-		strncpy(oft_info->fh.name, xfer->filename, 64);
-		oft_info->fh.totsize = gaim_xfer_get_size(xfer);
-		oft_info->fh.size = gaim_xfer_get_size(xfer);
-		oft_info->fh.checksum = aim_oft_checksum_file(xfer->local_filename);
-
-		/*
-		 * First try the port specified earlier (5190).  If that fails, 
-		 * increment by 1 and try again.
-		 */
-		aim_sendfile_listen(od->sess, oft_info);
-		for (i=0; (i<5 && !oft_info->conn); i++) {
-			xfer->local_port = oft_info->port = oft_info->port + 1;
-			aim_sendfile_listen(od->sess, oft_info);
-		}
-		gaim_debug(GAIM_DEBUG_MISC, "oscar",
-				   "port is %d, ip is %s\n",
-				   xfer->local_port, oft_info->clientip);
-		if (oft_info->conn) {
-			xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);
-			aim_im_sendch2_sendfile_ask(od->sess, oft_info);
-			aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_estblsh, 0);
-		} else {
-			gaim_notify_error(gc, NULL, _("File Transfer Aborted"),
-							  _("Unable to establish listener socket."));
-			/* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */
-			/* gaim_xfer_cancel_remote(xfer); */
-		}
-	} else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
-		oft_info->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);
-		if (oft_info->conn) {
-			oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
-			aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);
-			oft_info->conn->fd = xfer->fd = gaim_proxy_connect(gaim_connection_get_account(gc), xfer->remote_ip, xfer->remote_port, 
-								      oscar_sendfile_connected, xfer);
-			if (xfer->fd == -1) {
-				gaim_notify_error(gc, NULL, _("File Transfer Aborted"),
-								  _("Unable to establish file descriptor."));
-				/* gaim_xfer_cancel_remote(xfer); */
-			}
-		} else {
-			gaim_notify_error(gc, NULL, _("File Transfer Aborted"),
-							  _("Unable to create new connection."));
-			/* gaim_xfer_cancel_remote(xfer); */
-			/* Try a different port? Ask them to connect to us? */
-		}
-
-	}
-}
-
-static void oscar_xfer_start(GaimXfer *xfer)
-{
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_xfer_start\n");
-	/* I'm pretty sure we don't need to do jack here.  Nor Jill. */
-}
-
-static void oscar_xfer_end(GaimXfer *xfer)
-{
-	struct aim_oft_info *oft_info = xfer->data;
-	GaimConnection *gc = oft_info->sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_xfer_end\n");
-
-	if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
-		oft_info->fh.nrecvd = gaim_xfer_get_bytes_sent(xfer);
-		aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_DONE, oft_info);
-	}
-
-	aim_conn_kill(oft_info->sess, &oft_info->conn);
-	aim_oft_destroyinfo(oft_info);
-	xfer->data = NULL;
-	od->file_transfers = g_slist_remove(od->file_transfers, xfer);
-}
-
-static void oscar_xfer_cancel_send(GaimXfer *xfer)
-{
-	struct aim_oft_info *oft_info = xfer->data;
-	GaimConnection *gc = oft_info->sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "AAA - in oscar_xfer_cancel_send\n");
-
-	aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info);
-
-	aim_conn_kill(oft_info->sess, &oft_info->conn);
-	aim_oft_destroyinfo(oft_info);
-	xfer->data = NULL;
-	od->file_transfers = g_slist_remove(od->file_transfers, xfer);
-}
-
-static void oscar_xfer_cancel_recv(GaimXfer *xfer)
-{
-	struct aim_oft_info *oft_info = xfer->data;
-	GaimConnection *gc = oft_info->sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "AAA - in oscar_xfer_cancel_recv\n");
-
-	aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info);
-
-	aim_conn_kill(oft_info->sess, &oft_info->conn);
-	aim_oft_destroyinfo(oft_info);
-	xfer->data = NULL;
-	od->file_transfers = g_slist_remove(od->file_transfers, xfer);
-}
-
-static void oscar_xfer_ack(GaimXfer *xfer, const char *buffer, size_t size)
-{
-	struct aim_oft_info *oft_info = xfer->data;
-
-	if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
-		/*
-		 * If we're done sending, intercept the socket from the core ft code
-		 * and wait for the other guy to send the "done" OFT packet.
-		 */
-		if (gaim_xfer_get_bytes_remaining(xfer) <= 0) {
-			gaim_input_remove(xfer->watcher);
-			xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);
-			xfer->fd = 0;
-			gaim_xfer_set_completed(xfer, TRUE);
-		}
-	} else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {
-		/* Update our rolling checksum.  Like Walmart, yo. */
-		oft_info->fh.recvcsum = aim_oft_checksum_chunk(buffer, size, oft_info->fh.recvcsum);
-	}
-}
-
-static GaimXfer *oscar_find_xfer_by_cookie(GSList *fts, const char *ck)
-{
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-
-	while (fts) {
-		xfer = fts->data;
-		oft_info = xfer->data;
-
-		if (oft_info && !strcmp(ck, oft_info->cookie))
-			return xfer;
-
-		fts = g_slist_next(fts);
-	}
-
-	return NULL;
-}
-
-static GaimXfer *oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn)
-{
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-
-	while (fts) {
-		xfer = fts->data;
-		oft_info = xfer->data;
-
-		if (oft_info && (conn == oft_info->conn))
-			return xfer;
-
-		fts = g_slist_next(fts);
-	}
-
-	return NULL;
-}
-
-static void oscar_ask_sendfile(GaimConnection *gc, const char *destsn) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-
-	/* You want to send a file to someone else, you're so generous */
-
-	/* Build the file transfer handle */
-	xfer = gaim_xfer_new(gaim_connection_get_account(gc), GAIM_XFER_SEND, destsn);
-	xfer->local_port = 5190;
-
-	/* Create the oscar-specific data */
-	oft_info = aim_oft_createinfo(od->sess, NULL, destsn, xfer->local_ip, xfer->local_port, 0, 0, NULL);
-	xfer->data = oft_info;
-
-	 /* Setup our I/O op functions */
-	gaim_xfer_set_init_fnc(xfer, oscar_xfer_init);
-	gaim_xfer_set_start_fnc(xfer, oscar_xfer_start);
-	gaim_xfer_set_end_fnc(xfer, oscar_xfer_end);
-	gaim_xfer_set_cancel_send_fnc(xfer, oscar_xfer_cancel_send);
-	gaim_xfer_set_cancel_recv_fnc(xfer, oscar_xfer_cancel_recv);
-	gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack);
-
-	/* Keep track of this transfer for later */
-	od->file_transfers = g_slist_append(od->file_transfers, xfer);
-
-	/* Now perform the request */
-	gaim_xfer_request(xfer);
-}
-
-static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimAccount *account = gc->account;
-	aim_conn_t *bosconn;
-	char *host; int port;
-	int i, rc;
-	va_list ap;
-	struct aim_authresp_info *info;
-
-	port = gaim_account_get_int(account, "port", FAIM_LOGIN_PORT);
-
-	va_start(ap, fr);
-	info = va_arg(ap, struct aim_authresp_info *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "inside auth_resp (Screen name: %s)\n", info->sn);
-
-	if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) {
-		char buf[256];
-		switch (info->errorcode) {
-		case 0x05:
-			/* Incorrect nick/password */
-			gc->wants_to_die = TRUE;
-			gaim_connection_error(gc, _("Incorrect nickname or password."));
-			break;
-		case 0x11:
-			/* Suspended account */
-			gc->wants_to_die = TRUE;
-			gaim_connection_error(gc, _("Your account is currently suspended."));
-			break;
-		case 0x14:
-			/* service temporarily unavailable */
-			gaim_connection_error(gc, _("The AOL Instant Messenger service is temporarily unavailable."));
-			break;
-		case 0x18:
-			/* connecting too frequently */
-			gc->wants_to_die = TRUE;
-			gaim_connection_error(gc, _("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."));
-			break;
-		case 0x1c:
-			/* client too old */
-			gc->wants_to_die = TRUE;
-			g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), GAIM_WEBSITE);
-			gaim_connection_error(gc, buf);
-			break;
-		default:
-			gaim_connection_error(gc, _("Authentication failed"));
-			break;
-		}
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "Login Error Code 0x%04hx\n", info->errorcode);
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "Error URL: %s\n", info->errorurl);
-		od->killme = TRUE;
-		return 1;
-	}
-
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "Reg status: %hu\n", info->regstatus);
-
-	if (info->email) {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "Email: %s\n", info->email);
-	} else {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "Email is NULL\n");
-	}
-	
-	gaim_debug(GAIM_DEBUG_MISC, "oscar", "BOSIP: %s\n", info->bosip);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Closing auth connection...\n");
-	aim_conn_kill(sess, &fr->conn);
-
-	bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL);
-	if (bosconn == NULL) {
-		gaim_connection_error(gc, _("Internal Error"));
-		od->killme = TRUE;
-		return 0;
-	}
-
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, gaim_parse_locaterights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_CLIENTAUTORESP, gaim_parse_clientauto, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, gaim_parse_searcherror, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, gaim_parse_searchreply, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parse_mtn, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_userinfo, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, gaim_icbm_param_info, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, gaim_memrequest, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0001, 0x000f, gaim_selfinfo, 0);
-	aim_conn_addhandler(sess, bosconn, 0x0001, 0x0021, oscar_icon_req,0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG, gaim_offlinemsg, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, gaim_offlinemsgdone, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_POP, 0x0002, gaim_popup, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS, gaim_icqalias, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO, gaim_icqinfo, 0);
-#ifndef NOSSI
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ERROR, gaim_ssi_parseerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO, gaim_ssi_parserights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST, gaim_ssi_parselist, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_NOLIST, gaim_ssi_parselist, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK, gaim_ssi_parseack, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTH, gaim_ssi_authgiven, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREQ, gaim_ssi_authrequest, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREP, gaim_ssi_authreply, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ADDED, gaim_ssi_gotadded, 0);
-#endif
-
-	od->conn = bosconn;
-	for (i = 0; i < (int)strlen(info->bosip); i++) {
-		if (info->bosip[i] == ':') {
-			port = atoi(&(info->bosip[i+1]));
-			break;
-		}
-	}
-	host = g_strndup(info->bosip, i);
-	bosconn->status |= AIM_CONN_STATUS_INPROGRESS;
-	rc = gaim_proxy_connect(gc->account, host, port, oscar_bos_connect, gc);
-	g_free(host);
-	if (rc < 0) {
-		gaim_connection_error(gc, _("Could Not Connect"));
-		od->killme = TRUE;
-		return 0;
-	}
-	aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
-	gaim_input_remove(gc->inpa);
-
-	gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
-
-	return 1;
-}
-
-/* XXX - Should use gaim_url_fetch for the below stuff */
-struct pieceofcrap {
-	GaimConnection *gc;
-	unsigned long offset;
-	unsigned long len;
-	char *modname;
-	int fd;
-	aim_conn_t *conn;
-	unsigned int inpa;
-};
-
-static void damn_you(gpointer data, gint source, GaimInputCondition c)
-{
-	struct pieceofcrap *pos = data;
-	OscarData *od = pos->gc->proto_data;
-	char in = '\0';
-	int x = 0;
-	unsigned char m[17];
-
-	while (read(pos->fd, &in, 1) == 1) {
-		if (in == '\n')
-			x++;
-		else if (in != '\r')
-			x = 0;
-		if (x == 2)
-			break;
-		in = '\0';
-	}
-	if (in != '\n') {
-		char buf[256];
-		g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly.  You may want to use TOC until "
-			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
-		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was unable to get a valid AIM login hash."),
-							buf);
-		gaim_input_remove(pos->inpa);
-		close(pos->fd);
-		g_free(pos);
-		return;
-	}
-	read(pos->fd, m, 16);
-	m[16] = '\0';
-	gaim_debug(GAIM_DEBUG_MISC, "oscar", "Sending hash: ");
-	for (x = 0; x < 16; x++)
-		gaim_debug(GAIM_DEBUG_MISC, NULL, "%02hhx ", (unsigned char)m[x]);
-
-	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-	gaim_input_remove(pos->inpa);
-	close(pos->fd);
-	aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
-	g_free(pos);
-}
-
-static void straight_to_hell(gpointer data, gint source, GaimInputCondition cond) {
-	struct pieceofcrap *pos = data;
-	gchar *buf;
-
-	pos->fd = source;
-
-	if (source < 0) {
-		buf = g_strdup_printf(_("You may be disconnected shortly.  You may want to use TOC until "
-			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
-		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was unable to get a valid AIM login hash."),
-							buf);
-		g_free(buf);
-		if (pos->modname)
-			g_free(pos->modname);
-		g_free(pos);
-		return;
-	}
-
-	buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n",
-			pos->offset, pos->len, pos->modname ? pos->modname : "");
-	write(pos->fd, buf, strlen(buf));
-	g_free(buf);
-	if (pos->modname)
-		g_free(pos->modname);
-	pos->inpa = gaim_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos);
-	return;
-}
-
-/* size of icbmui.ocm, the largest module in AIM 3.5 */
-#define AIM_MAX_FILE_SIZE 98304
-
-int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	struct pieceofcrap *pos;
-	fu32_t offset, len;
-	char *modname;
-
-	va_start(ap, fr);
-	offset = va_arg(ap, fu32_t);
-	len = va_arg(ap, fu32_t);
-	modname = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "offset: %u, len: %u, file: %s\n",
-			   offset, len, (modname ? modname : "aim.exe"));
-
-	if (len == 0) {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "len is 0, hashing NULL\n");
-		aim_sendmemblock(sess, fr->conn, offset, len, NULL,
-				AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
-		return 1;
-	}
-	/* uncomment this when you're convinced it's right. remember, it's been wrong before.
-	if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) {
-		char *buf;
-		int i = 8;
-		if (modname)
-			i += strlen(modname);
-		buf = g_malloc(i);
-		i = 0;
-		if (modname) {
-			memcpy(buf, modname, strlen(modname));
-			i += strlen(modname);
-		}
-		buf[i++] = offset & 0xff;
-		buf[i++] = (offset >> 8) & 0xff;
-		buf[i++] = (offset >> 16) & 0xff;
-		buf[i++] = (offset >> 24) & 0xff;
-		buf[i++] = len & 0xff;
-		buf[i++] = (len >> 8) & 0xff;
-		buf[i++] = (len >> 16) & 0xff;
-		buf[i++] = (len >> 24) & 0xff;
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "len + offset is invalid, "
-		           "hashing request\n");
-		aim_sendmemblock(sess, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
-		g_free(buf);
-		return 1;
-	}
-	*/
-
-	pos = g_new0(struct pieceofcrap, 1);
-	pos->gc = sess->aux_data;
-	pos->conn = fr->conn;
-
-	pos->offset = offset;
-	pos->len = len;
-	pos->modname = modname ? g_strdup(modname) : NULL;
-
-	if (gaim_proxy_connect(pos->gc->account, "gaim.sourceforge.net", 80, straight_to_hell, pos) != 0) {
-		char buf[256];
-		if (pos->modname)
-			g_free(pos->modname);
-		g_free(pos);
-		g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly.  You may want to use TOC until "
-			"this is fixed.  Check %s for updates."), GAIM_WEBSITE);
-		gaim_notify_warning(pos->gc, NULL,
-							_("Gaim was unable to get a valid login hash."),
-							buf);
-	}
-
-	return 1;
-}
-
-static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimAccount *account = gaim_connection_get_account(gc);
-	GaimAccount *ac = gaim_connection_get_account(gc);
-#if 0
-	struct client_info_s info = {"gaim", 7, 3, 2003, "us", "en", 0x0004, 0x0000, 0x04b};
-#endif
-	va_list ap;
-	char *key;
-
-	va_start(ap, fr);
-	key = va_arg(ap, char *);
-	va_end(ap);
-
-	if (od->icq) {
-		struct client_info_s info = CLIENTINFO_ICQ_KNOWNGOOD;
-		aim_send_login(sess, fr->conn, gaim_account_get_username(ac),
-					   gaim_account_get_password(account), &info, key);
-	} else {
-		struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
-		aim_send_login(sess, fr->conn, gaim_account_get_username(ac),
-					   gaim_account_get_password(account), &info, key);
-	}
-
-	gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
-
-	return 1;
-}
-
-static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	struct chat_connection *chatcon;
-	static int id = 1;
-
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_conv_chat_join, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_conv_chat_leave, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0);
-
-	aim_clientready(sess, fr->conn);
-
-	chatcon = find_oscar_chat_by_conn(gc, fr->conn);
-	chatcon->id = id;
-	chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
-
-	return 1;
-}
-
-static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) {
-
-	aim_conn_addhandler(sess, fr->conn, 0x000d, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
-
-	aim_clientready(sess, fr->conn);
-
-	aim_chatnav_reqrights(sess, fr->conn);
-
-	return 1;
-}
-
-static int conninitdone_email(aim_session_t *sess, aim_frame_t *fr, ...) {
-
-	aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_EML, AIM_CB_EML_MAILSTATUS, gaim_email_parseupdate, 0);
-
-	aim_email_sendcookies(sess);
-	aim_email_activate(sess);
-	aim_clientready(sess, fr->conn);
-
-	return 1;
-}
-
-static int conninitdone_icon(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ICO, AIM_CB_ICO_ERROR, gaim_icon_error, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ICO, AIM_CB_ICO_RESPONSE, gaim_icon_parseicon, 0);
-
-	aim_clientready(sess, fr->conn);
-
-	od->iconconnecting = FALSE;
-
-	if (od->icontimer)
-		g_source_remove(od->icontimer);
-	od->icontimer = g_timeout_add(100, gaim_icon_timerfunc, gc);
-
-	return 1;
-}
-
-static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) {
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV);
-	tstconn->fd = source;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "unable to connect to chatnav server\n");
-		return;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	od->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "chatnav: connected\n");
-}
-
-static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond)
-{
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
-	tstconn->fd = source;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "unable to connect to authorizer\n");
-		return;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	od->paspa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "admin: connected\n");
-}
-
-static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond)
-{
-	struct chat_connection *ccon = data;
-	GaimConnection *gc = ccon->gc;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		g_free(ccon->show);
-		g_free(ccon->name);
-		g_free(ccon);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	tstconn = ccon->conn;
-	tstconn->fd = source;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		g_free(ccon->show);
-		g_free(ccon->name);
-		g_free(ccon);
-		return;
-	}
-
-	aim_conn_completeconnect(sess, ccon->conn);
-	ccon->inpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn);
-	od->oscar_chats = g_slist_append(od->oscar_chats, ccon);
-}
-
-static void oscar_email_connect(gpointer data, gint source, GaimInputCondition cond) {
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_EMAIL);
-	tstconn->fd = source;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "unable to connect to email server\n");
-		return;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	od->emlpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "email: connected\n");
-}
-
-static void oscar_icon_connect(gpointer data, gint source, GaimInputCondition cond) {
-	GaimConnection *gc = data;
-	OscarData *od;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		close(source);
-		return;
-	}
-
-	od = gc->proto_data;
-	sess = od->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_ICON);
-	tstconn->fd = source;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "unable to connect to icon server\n");
-		return;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	od->icopa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "icon: connected\n");
-}
-
-/* Hrmph. I don't know how to make this look better. --mid */
-static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	GaimAccount *account = gaim_connection_get_account(gc);
-	aim_conn_t *tstconn;
-	int i;
-	char *host;
-	int port;
-	va_list ap;
-	struct aim_redirect_data *redir;
-
-	port = gaim_account_get_int(account, "port", FAIM_LOGIN_PORT);
-
-	va_start(ap, fr);
-	redir = va_arg(ap, struct aim_redirect_data *);
-	va_end(ap);
-
-	for (i = 0; i < (int)strlen(redir->ip); i++) {
-		if (redir->ip[i] == ':') {
-			port = atoi(&(redir->ip[i+1]));
-			break;
-		}
-	}
-	host = g_strndup(redir->ip, i);
-
-	switch(redir->group) {
-	case 0x7: /* Authorizer */
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "Reconnecting with authorizor...\n");
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
-		if (tstconn == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to reconnect with authorizer\n");
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		if (gaim_proxy_connect(account, host, port, oscar_auth_connect, gc) != 0) {
-			aim_conn_kill(sess, &tstconn);
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to reconnect with authorizer\n");
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-	break;
-
-	case 0xd: /* ChatNav */
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, NULL);
-		if (tstconn == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to chatnav server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		if (gaim_proxy_connect(account, host, port, oscar_chatnav_connect, gc) != 0) {
-			aim_conn_kill(sess, &tstconn);
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to chatnav server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-	break;
-
-	case 0xe: { /* Chat */
-		struct chat_connection *ccon;
-
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL);
-		if (tstconn == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to chat server\n");
-			g_free(host);
-			return 1;
-		}
-
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
-
-		ccon = g_new0(struct chat_connection, 1);
-		ccon->conn = tstconn;
-		ccon->gc = gc;
-		ccon->fd = -1;
-		ccon->name = g_strdup(redir->chat.room);
-		ccon->exchange = redir->chat.exchange;
-		ccon->instance = redir->chat.instance;
-		ccon->show = extract_name(redir->chat.room);
-
-		ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS;
-		if (gaim_proxy_connect(account, host, port, oscar_chat_connect, ccon) != 0) {
-			aim_conn_kill(sess, &tstconn);
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to chat server\n");
-			g_free(host);
-			g_free(ccon->show);
-			g_free(ccon->name);
-			g_free(ccon);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "Connected to chat room %s exchange %hu\n",
-				   ccon->name, ccon->exchange);
-	} break;
-
-	case 0x0010: { /* icon */
-		if (!(tstconn = aim_newconn(sess, AIM_CONN_TYPE_ICON, NULL))) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to icon server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_icon, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		if (gaim_proxy_connect(account, host, port, oscar_icon_connect, gc) != 0) {
-			aim_conn_kill(sess, &tstconn);
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to icon server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-	} break;
-
-	case 0x0018: { /* email */
-		if (!(tstconn = aim_newconn(sess, AIM_CONN_TYPE_EMAIL, NULL))) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to email server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_email, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		if (gaim_proxy_connect(account, host, port, oscar_email_connect, gc) != 0) {
-			aim_conn_kill(sess, &tstconn);
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unable to connect to email server\n");
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
-	} break;
-
-	default: /* huh? */
-		gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-				   "got redirect for unknown service 0x%04hx\n",
-				   redir->group);
-		break;
-	}
-
-	g_free(host);
-	return 1;
-}
-
-static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	struct buddyinfo *bi;
-	time_t time_idle = 0, signon = 0;
-	int type = 0;
-	int caps = 0;
-	va_list ap;
-	aim_userinfo_t *info;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES)
-		caps = info->capabilities;
-	if (info->flags & AIM_FLAG_ACTIVEBUDDY)
-		type |= UC_AB;
-	if (caps & AIM_CAPS_HIPTOP)
-		type |= UC_HIPTOP;
-
-	if (info->present & AIM_USERINFO_PRESENT_FLAGS) {
-		if (info->flags & AIM_FLAG_UNCONFIRMED)
-			type |= UC_UNCONFIRMED;
-		if (info->flags & AIM_FLAG_ADMINISTRATOR)
-			type |= UC_ADMIN;
-		if (info->flags & AIM_FLAG_AOL)
-			type |= UC_AOL;
-		if (info->flags & AIM_FLAG_FREE)
-			type |= UC_NORMAL;
-		if (info->flags & AIM_FLAG_AWAY)
-			type |= UC_UNAVAILABLE;
-		if (info->flags & AIM_FLAG_WIRELESS)
-			type |= UC_WIRELESS;
-	}
-	if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
-		type = (info->icqinfo.status << 16);
-		if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
-		      (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
-			type |= UC_UNAVAILABLE;
-		}
-	}
-
-	if (caps & AIM_CAPS_ICQ_DIRECT)
-		caps ^= AIM_CAPS_ICQ_DIRECT;
-
-	if (info->present & AIM_USERINFO_PRESENT_IDLE) {
-		time(&time_idle);
-		time_idle -= info->idletime*60;
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
-		signon = info->onlinesince;
-	else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
-		signon = time(NULL) - info->sessionlen;
-
-	if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), info->sn))
-		gaim_connection_set_display_name(gc, info->sn);
-
-	bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, info->sn));
-	if (!bi) {
-		bi = g_new0(struct buddyinfo, 1);
-		g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, info->sn)), bi);
-	}
-	bi->typingnot = FALSE;
-	bi->ico_informed = FALSE;
-	bi->ipaddr = info->icqinfo.ipaddr;
-
-	/* Available message stuff */
-	free(bi->availmsg);
-	if (info->avail != NULL)
-		if (info->avail_encoding) {
-			gchar *enc = g_strdup_printf("charset=\"%s\"", info->avail_encoding);
-			bi->availmsg = oscar_encoding_to_utf8(enc, info->avail, info->avail_len);
-			g_free(enc);
-		} else {
-			/* No explicit encoding means utf8.  Yay. */
-			bi->availmsg = g_strdup(info->avail);
-		}
-	else
-		bi->availmsg = NULL;
-
-	/* Server stored icon stuff */
-	if (info->iconcsumlen) {
-		const char *filename = NULL, *saved_b16 = NULL;
-		char *b16 = NULL;
-		GaimBuddy *b = NULL;
-
-		b16 = gaim_base16_encode(info->iconcsum, info->iconcsumlen);
-		b = gaim_find_buddy(gc->account, info->sn);
-		/*
-		 * If for some reason the checksum is valid, but cached file is not..
-		 * we want to know.
-		 */
-		filename = gaim_buddy_get_setting(b, "buddy_icon");
-		if (filename != NULL) {
-			if (g_file_test(filename, G_FILE_TEST_EXISTS))
-				saved_b16 = gaim_buddy_get_setting(b, "icon_checksum");
-		} else
-			saved_b16 = NULL;
-
-		if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
-			GSList *cur = od->requesticon;
-			while (cur && aim_sncmp((char *)cur->data, info->sn))
-				cur = cur->next;
-			if (!cur) {
-				od->requesticon = g_slist_append(od->requesticon, g_strdup(gaim_normalize(gc->account, info->sn)));
-				if (od->icontimer)
-					g_source_remove(od->icontimer);
-				od->icontimer = g_timeout_add(500, gaim_icon_timerfunc, gc);
-			}
-		}
-		g_free(b16);
-	}
-
-	serv_got_update(gc, info->sn, 1, (info->warnlevel/10.0) + 0.5, signon, time_idle, type);
-
-	return 1;
-}
-
-static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	va_list ap;
-	aim_userinfo_t *info;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	serv_got_update(gc, info->sn, 0, 0, 0, 0, 0);
-
-	g_hash_table_remove(od->buddyinfo, gaim_normalize(gc->account, info->sn));
-
-	return 1;
-}
-
-static void cancel_direct_im(struct ask_direct *d) {
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "Freeing DirectIM prompts.\n");
-
-	g_free(d->sn);
-	g_free(d);
-}
-
-static void oscar_odc_callback(gpointer data, gint source, GaimInputCondition condition) {
-	struct direct_im *dim = data;
-	GaimConnection *gc = dim->gc;
-	OscarData *od = gc->proto_data;
-	GaimConversation *cnv;
-	char buf[256];
-	struct sockaddr name;
-	socklen_t name_len = 1;
-	
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		g_free(dim);
-		return;
-	}
-
-	if (source < 0) {
-		g_free(dim);
-		return;
-	}
-
-	dim->conn->fd = source;
-	aim_conn_completeconnect(od->sess, dim->conn);
-	cnv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, dim->name);
-
-	/* This is the best way to see if we're connected or not */
-	if (getpeername(source, &name, &name_len) == 0) {
-		g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name);
-		dim->connected = TRUE;
-		gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));
-	}
-	od->direct_ims = g_slist_append(od->direct_ims, dim);
-	
-	dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn);
-}
-
-/* BBB */
-/*
- * This is called after a remote AIM user has connected to us.  We 
- * want to do some voodoo with the socket file descriptors, add a 
- * callback or two, and then send the AIM_CB_OFT_PROMPT.
- */
-static int oscar_sendfile_estblsh(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-	va_list ap;
-	aim_conn_t *conn, *listenerconn;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "AAA - in oscar_sendfile_estblsh\n");
-	va_start(ap, fr);
-	conn = va_arg(ap, aim_conn_t *);
-	listenerconn = va_arg(ap, aim_conn_t *);
-	va_end(ap);
-
-	if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, listenerconn)))
-		return 1;
-
-	if (!(oft_info = xfer->data))
-		return 1;
-
-	/* Stop watching listener conn; watch transfer conn instead */
-	gaim_input_remove(xfer->watcher);
-	aim_conn_kill(sess, &listenerconn);
-
-	oft_info->conn = conn;
-	xfer->fd = oft_info->conn->fd;
-
-	aim_conn_addhandler(sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ACK, oscar_sendfile_ack, 0);
-	aim_conn_addhandler(sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DONE, oscar_sendfile_done, 0);
-	xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);
-
-	/* Inform the other user that we are connected and ready to transfer */
-	aim_oft_sendheader(sess, AIM_CB_OFT_PROMPT, oft_info);
-
-	return 0;
-}
-
-/*
- * This is the gaim callback passed to gaim_proxy_connect when connecting to another AIM 
- * user in order to transfer a file.
- */
-static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) {
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "AAA - in oscar_sendfile_connected\n");
-	if (!(xfer = data))
-		return;
-	if (!(oft_info = xfer->data))
-		return;
-	if (source < 0)
-		return;
-
-	xfer->fd = source;
-	oft_info->conn->fd = source;
-
-	aim_conn_completeconnect(oft_info->sess, oft_info->conn);
-	xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);
-
-	/* Inform the other user that we are connected and ready to transfer */
-	aim_im_sendch2_sendfile_accept(oft_info->sess, oft_info);
-
-	return;
-}
-
-/*
- * This is called when a buddy sends us some file info.  This happens when they 
- * are sending a file to you, and you have just established a connection to them.
- * You should send them the exact same info except use the real cookie.  We also 
- * get like totally ready to like, receive the file, kay?
- */
-static int oscar_sendfile_prompt(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimXfer *xfer;
-	struct aim_oft_info *oft_info;
-	va_list ap;
-	aim_conn_t *conn;
-	fu8_t *cookie;
-	struct aim_fileheader_t *fh;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "AAA - in oscar_sendfile_prompt\n");
-	va_start(ap, fr);
-	conn = va_arg(ap, aim_conn_t *);
-	cookie = va_arg(ap, fu8_t *);
-	fh = va_arg(ap, struct aim_fileheader_t *);
-	va_end(ap);
-
-	if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn)))
-		return 1;
-
-	if (!(oft_info = xfer->data))
-		return 1;
-
-	/* We want to stop listening with a normal thingy */
-	gaim_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
-	/* They sent us some information about the file they're sending */
-	memcpy(&oft_info->fh, fh, sizeof(*fh));
-
-	/* Fill in the cookie */
-	memcpy(&oft_info->fh.bcookie, oft_info->cookie, 8);
-
-	/* XXX - convert the name from UTF-8 to UCS-2 if necessary, and pass the encoding to the call below */
-	aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_ACK, oft_info);
-	gaim_xfer_start(xfer, xfer->fd, NULL, 0);
-
-	return 0;
-}
-
-/*
- * We are sending a file to someone else.  They have just acknowledged our 
- * prompt, so we want to start sending data like there's no tomorrow.
- */
-static int oscar_sendfile_ack(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimXfer *xfer;
-	va_list ap;
-	aim_conn_t *conn;
-	fu8_t *cookie;
-	struct aim_fileheader_t *fh;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_sendfile_ack\n");
-	va_start(ap, fr);
-	conn = va_arg(ap, aim_conn_t *);
-	cookie = va_arg(ap, fu8_t *);
-	fh = va_arg(ap, struct aim_fileheader_t *);
-	va_end(ap);
-
-	if (!(xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie)))
-		return 1;
-
-	/* We want to stop listening with a normal thingy */
-	gaim_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
-	gaim_xfer_start(xfer, xfer->fd, NULL, 0);
-
-	return 0;
-}
-
-/*
- * We just sent a file to someone.  They said they got it and everything, 
- * so we can close our direct connection and what not.
- */
-static int oscar_sendfile_done(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimXfer *xfer;
-	va_list ap;
-	aim_conn_t *conn;
-	fu8_t *cookie;
-	struct aim_fileheader_t *fh;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "AAA - in oscar_sendfile_done\n");
-	va_start(ap, fr);
-	conn = va_arg(ap, aim_conn_t *);
-	cookie = va_arg(ap, fu8_t *);
-	fh = va_arg(ap, struct aim_fileheader_t *);
-	va_end(ap);
-
-	if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn)))
-		return 1;
-
-	xfer->fd = conn->fd;
-	gaim_xfer_end(xfer);
-
-	return 0;
-}
-
-static void accept_direct_im(struct ask_direct *d) {
-	GaimConnection *gc = d->gc;
-	OscarData *od;
-	struct direct_im *dim;
-	char *host; int port = 4443;
-	int i, rc;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		cancel_direct_im(d);
-		return;
-	}
-
-	od = (OscarData *)gc->proto_data;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "Accepted DirectIM.\n");
-
-	dim = find_direct_im(od, d->sn);
-	if (dim) {
-		cancel_direct_im(d); /* 40 */
-		return;
-	}
-	dim = g_new0(struct direct_im, 1);
-	dim->gc = d->gc;
-	g_snprintf(dim->name, sizeof dim->name, "%s", d->sn);
-
-	dim->conn = aim_odc_connect(od->sess, d->sn, NULL, d->cookie);
-	if (!dim->conn) {
-		g_free(dim);
-		cancel_direct_im(d);
-		return;
-	}
-
-	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,
-				gaim_odc_incoming, 0);
-	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,
-				gaim_odc_typing, 0);
-	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER,
-			        gaim_odc_update_ui, 0);
-	for (i = 0; i < (int)strlen(d->ip); i++) {
-		if (d->ip[i] == ':') {
-			port = atoi(&(d->ip[i+1]));
-			break;
-		}
-	}
-	host = g_strndup(d->ip, i);
-	dim->conn->status |= AIM_CONN_STATUS_INPROGRESS;
-	rc = gaim_proxy_connect(gc->account, host, port, oscar_odc_callback, dim);
-	g_free(host);
-	if (rc < 0) {
-		aim_conn_kill(od->sess, &dim->conn);
-		g_free(dim);
-		cancel_direct_im(d);
-		return;
-	}
-
-	cancel_direct_im(d);
-
-	return;
-}
-
-static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	gchar *tmp;
-	GaimConvImFlags flags = 0;
-	gsize convlen;
-	GError *err = NULL;
-	struct buddyinfo *bi;
-	const char *iconfile;
-
-	bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, userinfo->sn));
-	if (!bi) {
-		bi = g_new0(struct buddyinfo, 1);
-		g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, userinfo->sn)), bi);
-	}
-
-	if (args->icbmflags & AIM_IMFLAGS_AWAY)
-		flags |= GAIM_CONV_IM_AUTO_RESP;
-
-	if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
-		bi->typingnot = TRUE;
-	else
-		bi->typingnot = FALSE;
-
-	if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar",
-				   "%s has an icon\n", userinfo->sn);
-		if ((args->iconlen != bi->ico_len) || (args->iconsum != bi->ico_csum) || (args->iconstamp != bi->ico_time)) {
-			bi->ico_need = TRUE;
-			bi->ico_len = args->iconlen;
-			bi->ico_csum = args->iconsum;
-			bi->ico_time = args->iconstamp;
-		}
-	}
-
-	if ((iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc))) && 
-	    (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
-		FILE *file;
-		struct stat st;
-
-		if (!stat(iconfile, &st)) {
-			char *buf = g_malloc(st.st_size);
-			file = fopen(iconfile, "rb");
-			if (file) {
-				int len = fread(buf, 1, st.st_size, file);
-				gaim_debug(GAIM_DEBUG_INFO, "oscar",
-						   "Sending buddy icon to %s (%d bytes, "
-						   "%lu reported)\n",
-						   userinfo->sn, len, st.st_size);
-				aim_im_sendch2_icon(sess, userinfo->sn, buf, st.st_size,
-					st.st_mtime, aimutil_iconsum(buf, st.st_size));
-				fclose(file);
-			} else
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "Can't open buddy icon file!\n");
-			g_free(buf);
-		} else
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Can't stat buddy icon file!\n");
-	}
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "Character set is %hu %hu\n", args->charset, args->charsubset);
-	if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
-		/* This message is marked as UNICODE, so we have to
-		 * convert it to utf-8 before handing it to the gaim core.
-		 * This conversion should *never* fail, if it does it
-		 * means that either the incoming ICBM is corrupted or
-		 * there is something we don't understand about it.
-		 * For the record, AIM Unicode is big-endian UCS-2 */
-
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "Received UNICODE IM\n");
-
-		if (!args->msg || !args->msglen)
-			return 1;
-
-		tmp = g_convert(args->msg, args->msglen, "UTF-8", "UCS-2BE", NULL, &convlen, &err);
-		if (err) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Unicode IM conversion: %s\n", err->message);
-			tmp = g_strdup(_("(There was an error receiving this message)"));
-			g_error_free(err);
-		}
-	} else {
-		/* This will get executed for both AIM_IMFLAGS_ISO_8859_1 and
-		 * unflagged messages, which are ASCII.  That's OK because
-		 * ASCII is a strict subset of ISO-8859-1; this should
-		 * help with compatibility with old, broken versions of
-		 * gaim (everything before 0.60) and other broken clients
-		 * that will happily send ISO-8859-1 without marking it as
-		 * such */
-		if (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Received ISO-8859-1 IM\n");
-
-		if (!args->msg || !args->msglen)
-			return 1;
-
-		tmp = g_convert(args->msg, args->msglen, "UTF-8", "ISO-8859-1", NULL, &convlen, &err);
-		if (err) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ISO-8859-1 IM conversion: %s\n", err->message);
-			tmp = g_strdup(_("(There was an error receiving this message)"));
-			g_error_free(err);
-		}
-	}
-
-	/* gaim_str_strip_cr(tmp); */
-	serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL));
-	g_free(tmp);
-
-	return 1;
-}
-
-static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	const char *username = gaim_account_get_username(gaim_connection_get_account(gc));
-
-	if (!args)
-		return 0;
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "rendezvous with %s, status is %hu\n",
-			   userinfo->sn, args->status);
-
-	if (args->reqclass & AIM_CAPS_CHAT) {
-		char *name;
-		GHashTable *components;
-
-		if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange || !args->msg)
-			return 1;
-		components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-				g_free);
-		name = extract_name(args->info.chat.roominfo.name);
-		g_hash_table_replace(components, g_strdup("room"), g_strdup(name ? name : args->info.chat.roominfo.name));
-		g_hash_table_replace(components, g_strdup("exchange"), g_strdup_printf("%d", args->info.chat.roominfo.exchange));
-		serv_got_chat_invite(gc,
-				     name ? name : args->info.chat.roominfo.name,
-				     userinfo->sn,
-				     args->msg,
-				     components);
-		if (name)
-			g_free(name);
-	} else if (args->reqclass & AIM_CAPS_SENDFILE) {
-/* BBB */
-		if (args->status == AIM_RENDEZVOUS_PROPOSE) {
-			/* Someone wants to send a file (or files) to us */
-			GaimXfer *xfer;
-			struct aim_oft_info *oft_info;
-
-			if (!args->cookie || !args->port || !args->verifiedip || 
-			    !args->info.sendfile.filename || !args->info.sendfile.totsize || 
-			    !args->info.sendfile.totfiles || !args->reqclass) {
-				gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-						   "%s tried to send you a file with incomplete "
-						   "information.\n", userinfo->sn);
-				if (args->proxyip)
-					gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-							   "IP for a proxy server was given.  Gaim "
-							   "does not support this yet.\n");
-				return 1;
-			}
-
-			if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) {
-				/* last char of the ft req is a star, they are sending us a
-				 * directory -- remove the star and trailing slash so we dont save
-				 * directories that look like 'dirname\*'  -- arl */
-				char *tmp = strrchr(args->info.sendfile.filename, '\\');
-				if (tmp && (tmp[1] == '*')) {
-					tmp[0] = '\0';
-				}
-			}
-
-			/* Build the file transfer handle */
-			xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, userinfo->sn);
-			xfer->remote_ip = g_strdup(args->verifiedip);
-			xfer->remote_port = args->port;
-			gaim_xfer_set_filename(xfer, args->info.sendfile.filename);
-			gaim_xfer_set_size(xfer, args->info.sendfile.totsize);
-
-			/* Create the oscar-specific data */
-			oft_info = aim_oft_createinfo(od->sess, args->cookie, userinfo->sn, args->clientip, xfer->remote_port, 0, 0, NULL);
-			if (args->proxyip)
-				oft_info->proxyip = g_strdup(args->proxyip);
-			if (args->verifiedip)
-				oft_info->verifiedip = g_strdup(args->verifiedip);
-			xfer->data = oft_info;
-
-			 /* Setup our I/O op functions */
-			gaim_xfer_set_init_fnc(xfer, oscar_xfer_init);
-			gaim_xfer_set_start_fnc(xfer, oscar_xfer_start);
-			gaim_xfer_set_end_fnc(xfer, oscar_xfer_end);
-			gaim_xfer_set_cancel_send_fnc(xfer, oscar_xfer_cancel_send);
-			gaim_xfer_set_cancel_recv_fnc(xfer, oscar_xfer_cancel_recv);
-			gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack);
-
-			/*
-			 * XXX - Should do something with args->msg, args->encoding, and args->language
-			 *       probably make it apply to all ch2 messages.
-			 */
-
-			/* Keep track of this transfer for later */
-			od->file_transfers = g_slist_append(od->file_transfers, xfer);
-
-			/* Now perform the request */
-			gaim_xfer_request(xfer);
-		} else if (args->status == AIM_RENDEZVOUS_CANCEL) {
-			/* The other user wants to cancel a file transfer */
-			GaimXfer *xfer;
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "AAA - File transfer canceled by remote user\n");
-			if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, args->cookie)))
-				gaim_xfer_cancel_remote(xfer);
-		} else if (args->status == AIM_RENDEZVOUS_ACCEPT) {
-			/*
-			 * This gets sent by the receiver of a file 
-			 * as they connect directly to us.  If we don't 
-			 * get this, then maybe a third party connected 
-			 * to us, and we shouldn't send them anything.
-			 */
-		} else {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "unknown rendezvous status!\n");
-		}
-	} else if (args->reqclass & AIM_CAPS_GETFILE) {
-	} else if (args->reqclass & AIM_CAPS_VOICE) {
-	} else if (args->reqclass & AIM_CAPS_BUDDYICON) {
-		gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc),
-									  userinfo->sn, args->info.icon.icon,
-									  args->info.icon.length);
-	} else if (args->reqclass & AIM_CAPS_DIRECTIM) {
-		struct ask_direct *d = g_new0(struct ask_direct, 1);
-		char buf[256];
-
-		if (!args->verifiedip) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "directim kill blocked (%s)\n", userinfo->sn);
-			return 1;
-		}
-
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "%s received direct im request from %s (%s)\n",
-				   username, userinfo->sn, args->verifiedip);
-
-		d->gc = gc;
-		d->sn = g_strdup(userinfo->sn);
-		strncpy(d->ip, args->verifiedip, sizeof(d->ip));
-		memcpy(d->cookie, args->cookie, 8);
-		g_snprintf(buf, sizeof buf, _("%s has just asked to directly connect to %s"), userinfo->sn, username);
-
-		gaim_request_action(gc, NULL, buf,
-							_("This requires a direct connection between "
-							  "the two computers and is necessary for IM "
-							  "Images.  Because your IP address will be "
-							  "revealed, this may be considered a privacy "
-							  "risk."), 0, d, 2,
-							_("Connect"), G_CALLBACK(accept_direct_im),
-							_("Cancel"), G_CALLBACK(cancel_direct_im));
-	} else {
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "Unknown reqclass %hu\n", args->reqclass);
-	}
-
-	return 1;
-}
-
-/*
- * Authorization Functions
- * Most of these are callbacks from dialogs.  They're used by both 
- * methods of authorization (SSI and old-school channel 4 ICBM)
- */
-/* When you ask other people for authorization */
-static void gaim_auth_request(struct name_data *data, char *msg) {
-	GaimConnection *gc = data->gc;
-
-	if (g_list_find(gaim_connections_get_all(), gc)) {
-		OscarData *od = gc->proto_data;
-		GaimBuddy *buddy = gaim_find_buddy(gc->account, data->name);
-		GaimGroup *group = gaim_find_buddys_group(buddy);
-		if (buddy && group) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: adding buddy %s to group %s\n",
-					   buddy->name, group->name);
-			aim_ssi_sendauthrequest(od->sess, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
-			if (!aim_ssi_itemlist_finditem(od->sess->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))
-				aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 1);
-		}
-	}
-}
-
-static void gaim_auth_request_msgprompt(struct name_data *data) {
-	gaim_request_input(data->gc, NULL, _("Authorization Request Message:"),
-					   NULL, _("Please authorize me!"), TRUE, FALSE,
-					   _("OK"), G_CALLBACK(gaim_auth_request),
-					   _("Cancel"), G_CALLBACK(oscar_free_name_data),
-					   data);
-}
-
-static void gaim_auth_dontrequest(struct name_data *data) {
-	GaimConnection *gc = data->gc;
-
-	if (g_list_find(gaim_connections_get_all(), gc)) {
-		/* OscarData *od = gc->proto_data; */
-		/* XXX - Take the buddy out of our buddy list */
-	}
-
-	oscar_free_name_data(data);
-}
-
-static void gaim_auth_sendrequest(GaimConnection *gc, const char *name) {
-	struct name_data *data = g_new(struct name_data, 1);
-	GaimBuddy *buddy;
-	gchar *dialog_msg, *nombre;
-
-	buddy = gaim_find_buddy(gc->account, name);
-	if (buddy && (gaim_get_buddy_alias_only(buddy)))
-		nombre = g_strdup_printf("%s (%s)", name, gaim_get_buddy_alias_only(buddy));
-	else
-		nombre = NULL;
-
-	dialog_msg = g_strdup_printf(_("The user %s requires authorization before being added to a buddy list.  Do you want to send an authorization request?"), (nombre ? nombre : name));
-	data->gc = gc;
-	data->name = g_strdup(name);
-	data->nick = NULL;
-
-	gaim_request_action(gc, NULL, _("Request Authorization"), dialog_msg,
-						0, data, 2,
-						_("Request Authorization"),
-						G_CALLBACK(gaim_auth_request_msgprompt),
-						_("Cancel"), G_CALLBACK(gaim_auth_dontrequest));
-
-	g_free(dialog_msg);
-	g_free(nombre);
-}
-
-/* When other people ask you for authorization */
-static void gaim_auth_grant(struct name_data *data) {
-	GaimConnection *gc = data->gc;
-
-	if (g_list_find(gaim_connections_get_all(), gc)) {
-		OscarData *od = gc->proto_data;
-#ifdef NOSSI
-		GaimBuddy *buddy;
-		gchar message;
-		message = 0;
-		buddy = gaim_find_buddy(gc->account, data->name);
-		aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHGRANTED, &message);
-		gaim_account_notify_added(gc->account, NULL, data->name, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
-#else
-		aim_ssi_sendauthreply(od->sess, data->name, 0x01, NULL);
-#endif
-	}
-
-	oscar_free_name_data(data);
-}
-
-/* When other people ask you for authorization */
-static void gaim_auth_dontgrant(struct name_data *data, char *msg) {
-	GaimConnection *gc = data->gc;
-
-	if (g_list_find(gaim_connections_get_all(), gc)) {
-		OscarData *od = gc->proto_data;
-#ifdef NOSSI
-		aim_im_sendch4(od->sess, data->name, AIM_ICQMSG_AUTHDENIED, msg ? msg : _("No reason given."));
-#else
-		aim_ssi_sendauthreply(od->sess, data->name, 0x00, msg ? msg : _("No reason given."));
-#endif
-	}
-}
-
-static void gaim_auth_dontgrant_msgprompt(struct name_data *data) {
-	gaim_request_input(data->gc, NULL, _("Authorization Denied Message:"),
-					   NULL, _("No reason given."), TRUE, FALSE,
-					   _("OK"), G_CALLBACK(gaim_auth_dontgrant),
-					   _("Cancel"), G_CALLBACK(oscar_free_name_data),
-					   data);
-}
-
-/* When someone sends you buddies */
-static void gaim_icq_buddyadd(struct name_data *data) {
-	GaimConnection *gc = data->gc;
-
-	if (g_list_find(gaim_connections_get_all(), gc)) {
-		gaim_blist_request_add_buddy(gaim_connection_get_account(gc), data->name, NULL, data->nick);
-	}
-
-	oscar_free_name_data(data);
-}
-
-static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t) {
-	GaimConnection *gc = sess->aux_data;
-	gchar **msg1, **msg2;
-	GError *err = NULL;
-	int i, numtoks;
-
-	if (!args->type || !args->msg || !args->uin)
-		return 1;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Received a channel 4 message of type 0x%02hhx.\n", args->type);
-
-	/* Split up the message at the delimeter character, then convert each string to UTF-8 */
-	msg1 = g_strsplit(args->msg, "\376", 0);
-	for (numtoks=0; msg1[numtoks]; numtoks++);
-	msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
-	for (i=0; msg1[i]; i++) {
-		gaim_str_strip_cr(msg1[i]);
-		msg2[i] = g_convert(msg1[i], strlen(msg1[i]), "UTF-8", "ISO-8859-1", NULL, NULL, &err);
-		if (err) {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Error converting a string from ISO-8859-1 to "
-					   "UTF-8 in oscar ICBM channel 4 parsing\n");
-			g_error_free(err);
-		}
-	}
-	msg2[i] = NULL;
-
-	switch (args->type) {
-		case 0x01: { /* MacICQ message or basic offline message */
-			if (i >= 1) {
-				gchar *uin = g_strdup_printf("%u", args->uin);
-				if (t) { /* This is an offline message */
-					/* I think this timestamp is in UTC, or something */
-					serv_got_im(gc, uin, msg2[0], 0, t);
-				} else { /* This is a message from MacICQ/Miranda */
-					serv_got_im(gc, uin, msg2[0], 0, time(NULL));
-				}
-				g_free(uin);
-			}
-		} break;
-
-		case 0x04: { /* Someone sent you a URL */
-			if (i >= 2) {
-				if (msg2[1] != NULL) {
-					gchar *uin = g_strdup_printf("%u", args->uin);
-					gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>",
-													 msg2[1],
-													 (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]);
-					serv_got_im(gc, uin, message, 0, time(NULL));
-					g_free(uin);
-					g_free(message);
-				}
-			}
-		} break;
-
-		case 0x06: { /* Someone requested authorization */
-			if (i >= 6) {
-				struct name_data *data = g_new(struct name_data, 1);
-				gchar *dialog_msg = g_strdup_printf(_("The user %u wants to add you to their buddy list for the following reason:\n%s"), args->uin, msg2[5] ? msg2[5] : _("No reason given."));
-				gaim_debug(GAIM_DEBUG_INFO, "oscar",
-						   "Received an authorization request from UIN %u\n",
-						   args->uin);
-				data->gc = gc;
-				data->name = g_strdup_printf("%u", args->uin);
-				data->nick = NULL;
-
-				gaim_request_action(gc, NULL, _("Authorization Request"),
-									dialog_msg, 0, data, 2,
-									_("Authorize"),
-									G_CALLBACK(gaim_auth_grant),
-									_("Deny"),
-									G_CALLBACK(gaim_auth_dontgrant_msgprompt));
-				g_free(dialog_msg);
-			}
-		} break;
-
-		case 0x07: { /* Someone has denied you authorization */
-			if (i >= 1) {
-				gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
-				gaim_notify_info(gc, NULL, _("ICQ authorization denied."),
-								 dialog_msg);
-				g_free(dialog_msg);
-			}
-		} break;
-
-		case 0x08: { /* Someone has granted you authorization */
-			gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin);
-			gaim_notify_info(gc, NULL, "ICQ authorization accepted.",
-							 dialog_msg);
-			g_free(dialog_msg);
-		} break;
-
-		case 0x09: { /* Message from the Godly ICQ server itself, I think */
-			if (i >= 5) {
-				gchar *dialog_msg = g_strdup_printf(_("You have received a special message\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
-				gaim_notify_info(gc, NULL, "ICQ Server Message", dialog_msg);
-				g_free(dialog_msg);
-			}
-		} break;
-
-		case 0x0d: { /* Someone has sent you a pager message from http://www.icq.com/your_uin */
-			if (i >= 6) {
-				gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ page\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
-				gaim_notify_info(gc, NULL, "ICQ Page", dialog_msg);
-				g_free(dialog_msg);
-			}
-		} break;
-
-		case 0x0e: { /* Someone has emailed you at your_uin@pager.icq.com */
-			if (i >= 6) {
-				gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ email from %s [%s]\n\nMessage is:\n%s"), msg2[0], msg2[3], msg2[5]);
-				gaim_notify_info(gc, NULL, "ICQ Email", dialog_msg);
-				g_free(dialog_msg);
-			}
-		} break;
-
-		case 0x12: {
-			/* Ack for authorizing/denying someone.  Or possibly an ack for sending any system notice */
-			/* Someone added you to their buddy list? */
-		} break;
-
-		case 0x13: { /* Someone has sent you some ICQ buddies */
-			int i, num;
-			gchar **text;
-			text = g_strsplit(args->msg, "\376", 0);
-			if (text) {
-				num = 0;
-				for (i=0; i<strlen(text[0]); i++)
-					num = num*10 + text[0][i]-48;
-				for (i=0; i<num; i++) {
-					struct name_data *data = g_new(struct name_data, 1);
-					gchar *message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
-					data->gc = gc;
-					data->name = g_strdup(text[i*2+1]);
-					data->nick = g_strdup(text[i*2+2]);
-
-					gaim_request_action(gc, NULL, message,
-										_("Do you want to add this buddy "
-										  "to your buddy list?"),
-										0, data, 2,
-										_("Add"), G_CALLBACK(gaim_icq_buddyadd),
-										_("Decline"), G_CALLBACK(oscar_free_name_data));
-					g_free(message);
-				}
-				g_strfreev(text);
-			}
-		} break;
-
-		case 0x1a: { /* Someone has sent you a greeting card or requested buddies? */
-			/* This is boring and silly. */
-		} break;
-
-		default: {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Received a channel 4 message of unknown type "
-					   "(type 0x%02hhx).\n", args->type);
-		} break;
-	}
-
-	g_strfreev(msg1);
-	g_strfreev(msg2);
-
-	return 1;
-}
-
-static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) {
-	fu16_t channel;
-	int ret = 0;
-	aim_userinfo_t *userinfo;
-	va_list ap;
-
-	va_start(ap, fr);
-	channel = (fu16_t)va_arg(ap, unsigned int);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-
-	switch (channel) {
-		case 1: { /* standard message */
-			struct aim_incomingim_ch1_args *args;
-			args = va_arg(ap, struct aim_incomingim_ch1_args *);
-			ret = incomingim_chan1(sess, fr->conn, userinfo, args);
-		} break;
-
-		case 2: { /* rendevous */
-			struct aim_incomingim_ch2_args *args;
-			args = va_arg(ap, struct aim_incomingim_ch2_args *);
-			ret = incomingim_chan2(sess, fr->conn, userinfo, args);
-		} break;
-
-		case 4: { /* ICQ */
-			struct aim_incomingim_ch4_args *args;
-			args = va_arg(ap, struct aim_incomingim_ch4_args *);
-			ret = incomingim_chan4(sess, fr->conn, userinfo, args, 0);
-		} break;
-
-		default: {
-			gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-					   "ICBM received on unsupported channel (channel "
-					   "0x%04hx).", channel);
-		} break;
-	}
-
-	va_end(ap);
-
-	return ret;
-}
-
-static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) {
-	char *buf;
-	va_list ap;
-	fu16_t chan, nummissed, reason;
-	aim_userinfo_t *userinfo;
-
-	va_start(ap, fr);
-	chan = (fu16_t)va_arg(ap, unsigned int);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	nummissed = (fu16_t)va_arg(ap, unsigned int);
-	reason = (fu16_t)va_arg(ap, unsigned int);
-	va_end(ap);
-
-	switch(reason) {
-		case 0: /* Invalid (0) */
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s because it was invalid.",
-				   "You missed %hu messages from %s because they were invalid.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-		case 1: /* Message too large */
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s because it was too large.",
-				   "You missed %hu messages from %s because they were too large.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-		case 2: /* Rate exceeded */
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s because the rate limit has been exceeded.",
-				   "You missed %hu messages from %s because the rate limit has been exceeded.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-		case 3: /* Evil Sender */
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s because he/she was too evil.",
-				   "You missed %hu messages from %s because he/she was too evil.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-		case 4: /* Evil Receiver */
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s because you are too evil.",
-				   "You missed %hu messages from %s because you are too evil.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-		default:
-			buf = g_strdup_printf(
-				   ngettext(
-				   "You missed %hu message from %s for an unknown reason.",
-				   "You missed %hu messages from %s for an unknown reason.",
-				   nummissed),
-				   nummissed,
-				   userinfo->sn);
-			break;
-	}
-	gaim_notify_error(sess->aux_data, NULL, buf, NULL);
-	g_free(buf);
-
-	return 1;
-}
-
-static char *gaim_icq_status(int state) {
-	/* Make a cute little string that shows the status of the dude or dudet */
-	if (state & AIM_ICQ_STATE_CHAT)
-		return g_strdup_printf(_("Free For Chat"));
-	else if (state & AIM_ICQ_STATE_DND)
-		return g_strdup_printf(_("Do Not Disturb"));
-	else if (state & AIM_ICQ_STATE_OUT)
-		return g_strdup_printf(_("Not Available"));
-	else if (state & AIM_ICQ_STATE_BUSY)
-		return g_strdup_printf(_("Occupied"));
-	else if (state & AIM_ICQ_STATE_AWAY)
-		return g_strdup_printf(_("Away"));
-	else if (state & AIM_ICQ_STATE_WEBAWARE)
-		return g_strdup_printf(_("Web Aware"));
-	else if (state & AIM_ICQ_STATE_INVISIBLE)
-		return g_strdup_printf(_("Invisible"));
-	else
-		return g_strdup_printf(_("Online"));
-}
-
-static int gaim_parse_clientauto_ch2(aim_session_t *sess, const char *who, fu16_t reason, const char *cookie) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-/* BBB */
-	switch (reason) {
-		case 3: { /* Decline sendfile. */
-			GaimXfer *xfer;
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "AAA - Other user declined file transfer\n");
-			if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie)))
-				gaim_xfer_cancel_remote(xfer);
-		} break;
-
-		default: {
-			gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-					   "Received an unknown rendezvous client auto-response "
-					   "from %s.  Type 0x%04hx\n", who, reason);
-		}
-
-	}
-
-	return 0;
-}
-
-static int gaim_parse_clientauto_ch4(aim_session_t *sess, char *who, fu16_t reason, fu32_t state, char *msg) {
-	GaimConnection *gc = sess->aux_data;
-
-	switch(reason) {
-		case 0x0003: { /* Reply from an ICQ status message request */
-			char *status_msg = gaim_icq_status(state);
-			char *dialog_msg, **splitmsg;
-
-			/* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
-			splitmsg = g_strsplit(msg, "\r\n", 0);
-
-			dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, status_msg, g_strjoinv("<BR>", splitmsg));
-			gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, dialog_msg, NULL, NULL);
-
-			g_free(status_msg);
-			g_free(dialog_msg);
-			g_strfreev(splitmsg);
-		} break;
-
-		default: {
-			gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-					   "Received an unknown client auto-response from %s.  "
-					   "Type 0x%04hx\n", who, reason);
-		} break;
-	} /* end of switch */
-
-	return 0;
-}
-
-static int gaim_parse_clientauto(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t chan, reason;
-	char *who;
-
-	va_start(ap, fr);
-	chan = (fu16_t)va_arg(ap, unsigned int);
-	who = va_arg(ap, char *);
-	reason = (fu16_t)va_arg(ap, unsigned int);
-
-	if (chan == 0x0002) { /* File transfer declined */
-		char *cookie = va_arg(ap, char *);
-		return gaim_parse_clientauto_ch2(sess, who, reason, cookie);
-	} else if (chan == 0x0004) { /* ICQ message */
-		fu32_t state = 0;
-		char *msg = NULL;
-		if (reason == 0x0003) {
-			state = va_arg(ap, fu32_t);
-			msg = va_arg(ap, char *);
-		}
-		return gaim_parse_clientauto_ch4(sess, who, reason, state, msg);
-	}
-
-	va_end(ap);
-
-	return 1;
-}
-
-static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t reason;
-	char *m;
-
-	va_start(ap, fr);
-	reason = (fu16_t) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-			   "snac threw error (reason 0x%04hx: %s)\n", reason,
-			   (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown");
-
-	m = g_strdup_printf(_("SNAC threw error: %s\n"),
-			reason < msgerrreasonlen ? _(msgerrreason[reason]) : _("Unknown error"));
-	gaim_notify_error(sess->aux_data, NULL, m, NULL);
-	g_free(m);
-
-	return 1;
-}
-
-static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-#if 0
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GaimXfer *xfer;
-#endif
-	va_list ap;
-	fu16_t reason;
-	char *data, *buf;
-
-	va_start(ap, fr);
-	reason = (fu16_t)va_arg(ap, unsigned int);
-	data = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-			   "Message error with data %s and reason %hu\n", data, reason);
-
-/* BBB */
-#if 0
-	/* If this was a file transfer request, data is a cookie */
-	if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, data))) {
-		gaim_xfer_cancel_remote(xfer);
-		return 1;
-	}
-#endif
-
-	/* Data is assumed to be the destination sn */
-	buf = g_strdup_printf(_("Your message to %s did not get sent:"), data);
-	gaim_notify_error(sess->aux_data, NULL, buf,
-					  (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
-	g_free(buf);
-
-	return 1;
-}
-
-static int gaim_parse_mtn(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	fu16_t type1, type2;
-	char *sn;
-
-	va_start(ap, fr);
-	type1 = (fu16_t) va_arg(ap, unsigned int);
-	sn = va_arg(ap, char *);
-	type2 = (fu16_t) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	switch (type2) {
-		case 0x0000: { /* Text has been cleared */
-			serv_got_typing_stopped(gc, sn);
-		} break;
-
-		case 0x0001: { /* Paused typing */
-			serv_got_typing(gc, sn, 0, GAIM_TYPED);
-		} break;
-
-		case 0x0002: { /* Typing */
-			serv_got_typing(gc, sn, 0, GAIM_TYPING);
-		} break;
-
-		default: {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar", "Received unknown typing notification message from %s.  Type1 is 0x%04x and type2 is 0x%04hx.\n", sn, type1, type2);
-		} break;
-	}
-
-	return 1;
-}
-
-/*
- * We get this error when there was an error in the locate family.  This 
- * happens when you request info of someone who is offline.
- */
-static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-	gchar *buf;
-	va_list ap;
-	fu16_t reason;
-	char *destn;
-
-	va_start(ap, fr);
-	reason = (fu16_t) va_arg(ap, unsigned int);
-	destn = va_arg(ap, char *);
-	va_end(ap);
-
-	if (destn != NULL) {
-		buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
-		gaim_notify_error(sess->aux_data, NULL, buf,
-						  (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("No reason given."));
-		g_free(buf);
-	}
-
-	return 1;
-}
-
-#if 0
-static char *images(int flags) {
-	static char buf[1024];
-	g_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
-			(flags & AIM_FLAG_ACTIVEBUDDY) ? "<IMG SRC=\"ab_icon.gif\">" : "",
-			(flags & AIM_FLAG_UNCONFIRMED) ? "<IMG SRC=\"dt_icon.gif\">" : "",
-			(flags & AIM_FLAG_AOL) ? "<IMG SRC=\"aol_icon.gif\">" : "",
-			(flags & AIM_FLAG_ICQ) ? "<IMG SRC=\"icq_icon.gif\">" : "",
-			(flags & AIM_FLAG_ADMINISTRATOR) ? "<IMG SRC=\"admin_icon.gif\">" : "",
-			(flags & AIM_FLAG_FREE) ? "<IMG SRC=\"free_icon.gif\">" : "",
-			(flags & AIM_FLAG_WIRELESS) ? "<IMG SRC=\"wireless_icon.gif\">" : "");
-	return buf;
-}
-#endif
-
-static char *caps_string(guint caps)
-{
-	static char buf[512], *tmp;
-	int count = 0, i = 0;
-	guint bit = 1;
-
-	if (!caps) {
-		return NULL;
-	} else while (bit <= AIM_CAPS_LAST) {
-		if (bit & caps) {
-			switch (bit) {
-			case AIM_CAPS_BUDDYICON:
-				tmp = _("Buddy Icon");
-				break;
-			case AIM_CAPS_VOICE:
-				tmp = _("Voice");
-				break;
-			case AIM_CAPS_DIRECTIM:
-				tmp = _("AIM Direct IM");
-				break;
-			case AIM_CAPS_CHAT:
-				tmp = _("Chat");
-				break;
-			case AIM_CAPS_GETFILE:
-				tmp = _("Get File");
-				break;
-			case AIM_CAPS_SENDFILE:
-				tmp = _("Send File");
-				break;
-			case AIM_CAPS_GAMES:
-			case AIM_CAPS_GAMES2:
-				tmp = _("Games");
-				break;
-			case AIM_CAPS_SAVESTOCKS:
-				tmp = _("Add-Ins");
-				break;
-			case AIM_CAPS_SENDBUDDYLIST:
-				tmp = _("Send Buddy List");
-				break;
-			case AIM_CAPS_ICQ_DIRECT:
-				tmp = _("ICQ Direct Connect");
-				break;
-			case AIM_CAPS_APINFO:
-				tmp = _("AP User");
-				break;
-			case AIM_CAPS_ICQRTF:
-				tmp = _("ICQ RTF");
-				break;
-			case AIM_CAPS_EMPTY:
-				tmp = _("Nihilist");
-				break;
-			case AIM_CAPS_ICQSERVERRELAY:
-				tmp = _("ICQ Server Relay");
-				break;
-			case AIM_CAPS_ICQUTF8OLD:
-				tmp = _("Old ICQ UTF8");
-				break;
-			case AIM_CAPS_TRILLIANCRYPT:
-				tmp = _("Trillian Encryption");
-				break;
-			case AIM_CAPS_ICQUTF8:
-				tmp = _("ICQ UTF8");
-				break;
-			case AIM_CAPS_HIPTOP:
-				tmp = _("Hiptop");
-				break;
-			case AIM_CAPS_SECUREIM:
-				tmp = _("Security Enabled");
-				break;
-			case AIM_CAPS_VIDEO:
-				tmp = _("Video Chat");
-				break;
-			default:
-				tmp = NULL;
-				break;
-			}
-			if (tmp)
-				i += g_snprintf(buf + i, sizeof(buf) - i, "%s%s", (count ? ", " : ""),
-						tmp);
-			count++;
-		}
-		bit <<= 1;
-	}
-	return buf; 
-}
-
-static int gaim_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	GString *text;
-	gchar *info_utf8 = NULL, *away_utf8 = NULL;
-	const char *final = NULL;
-	va_list ap;
-	aim_userinfo_t *userinfo;
-
-	va_start(ap, fr);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	text = g_string_new("");
-	g_string_append_printf(text, _("Username: <b>%s</b><br>\n"), userinfo->sn);
-	g_string_append_printf(text, _("Warning Level: <b>%d%%</b><br>\n"), (int)((userinfo->warnlevel/10.0) + 0.5));
-
-	if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE)
-		g_string_append_printf(text, _("Online Since: <b>%s</b><br>\n"),
-					asctime(localtime((time_t *)&userinfo->onlinesince)));
-
-	if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE)
-		g_string_append_printf(text, _("Member Since: <b>%s</b><br>\n"),
-					asctime(localtime((time_t *)&userinfo->membersince)));
-
-	if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
-		gchar *itime = gaim_str_seconds_to_string(userinfo->idletime*60);
-		g_string_append_printf(text, _("Idle: <b>%s</b>"), itime);
-		g_free(itime);
-	} else
-		g_string_append_printf(text, _("Idle: <b>Active</b>"));
-
-	if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
-		away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
-		if (away_utf8 != NULL) {
-			g_string_append_printf(text, "<hr>%s", away_utf8);
-			g_free(away_utf8);
-		}
-	}
-
-	if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
-		info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
-		if (info_utf8 != NULL) {
-			g_string_append_printf(text, "<hr>%s", info_utf8);
-			g_free(info_utf8);
-		}
-	}
-
-	final = gaim_str_sub_away_formatters(text->str, gaim_account_get_username(gaim_connection_get_account(gc)));
-	g_string_free(text, TRUE);
-	gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, final, NULL, NULL);
-
-	return 1;
-}
-
-static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) {
-	char *msg;
-	fu16_t id;
-	va_list ap;
-
-	va_start(ap, fr);
-	id  = (fu16_t) va_arg(ap, unsigned int);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "MOTD: %s (%hu)\n", msg ? msg : "Unknown", id);
-	if (id < 4)
-		gaim_notify_warning(sess->aux_data, NULL,
-							_("Your AIM connection may be lost."), NULL);
-
-	return 1;
-}
-
-static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t type;
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	va_start(ap, fr);
-	type = (fu16_t) va_arg(ap, unsigned int);
-
-	switch(type) {
-		case 0x0002: {
-			fu8_t maxrooms;
-			struct aim_chat_exchangeinfo *exchanges;
-			int exchangecount, i;
-
-			maxrooms = (fu8_t) va_arg(ap, unsigned int);
-			exchangecount = va_arg(ap, int);
-			exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
-
-			gaim_debug(GAIM_DEBUG_MISC, "oscar",
-					   "chat info: Chat Rights:\n");
-			gaim_debug(GAIM_DEBUG_MISC, "oscar",
-					   "chat info: \tMax Concurrent Rooms: %hhd\n", maxrooms);
-			gaim_debug(GAIM_DEBUG_MISC, "oscar",
-					   "chat info: \tExchange List: (%d total)\n", exchangecount);
-			for (i = 0; i < exchangecount; i++)
-				gaim_debug(GAIM_DEBUG_MISC, "oscar",
-						   "chat info: \t\t%hu    %s\n",
-						   exchanges[i].number, exchanges[i].name ? exchanges[i].name : "");
-			while (od->create_rooms) {
-				struct create_room *cr = od->create_rooms->data;
-				gaim_debug(GAIM_DEBUG_INFO, "oscar",
-						   "creating room %s\n", cr->name);
-				aim_chatnav_createroom(sess, fr->conn, cr->name, cr->exchange);
-				g_free(cr->name);
-				od->create_rooms = g_slist_remove(od->create_rooms, cr);
-				g_free(cr);
-			}
-			}
-			break;
-		case 0x0008: {
-			char *fqcn, *name, *ck;
-			fu16_t instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
-			fu8_t createperms;
-			fu32_t createtime;
-
-			fqcn = va_arg(ap, char *);
-			instance = (fu16_t)va_arg(ap, unsigned int);
-			exchange = (fu16_t)va_arg(ap, unsigned int);
-			flags = (fu16_t)va_arg(ap, unsigned int);
-			createtime = va_arg(ap, fu32_t);
-			maxmsglen = (fu16_t)va_arg(ap, unsigned int);
-			maxoccupancy = (fu16_t)va_arg(ap, unsigned int);
-			createperms = (fu8_t)va_arg(ap, unsigned int);
-			unknown = (fu16_t)va_arg(ap, unsigned int);
-			name = va_arg(ap, char *);
-			ck = va_arg(ap, char *);
-
-			gaim_debug(GAIM_DEBUG_MISC, "oscar",
-					   "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n",
-					fqcn,
-					exchange, instance, flags,
-					createtime,
-					maxmsglen, maxoccupancy, createperms, unknown,
-					name, ck);
-			aim_chat_join(od->sess, od->conn, exchange, ck, instance);
-			}
-			break;
-		default:
-			gaim_debug(GAIM_DEBUG_WARNING, "oscar",
-					   "chatnav info: unknown type (%04hx)\n", type);
-			break;
-	}
-
-	va_end(ap);
-
-	return 1;
-}
-
-static int gaim_conv_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	int count, i;
-	aim_userinfo_t *info;
-	GaimConnection *g = sess->aux_data;
-
-	struct chat_connection *c = NULL;
-
-	va_start(ap, fr);
-	count = va_arg(ap, int);
-	info  = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	c = find_oscar_chat_by_conn(g, fr->conn);
-	if (!c)
-		return 1;
-
-	for (i = 0; i < count; i++)
-		gaim_conv_chat_add_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
-
-	return 1;
-}
-
-static int gaim_conv_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	int count, i;
-	aim_userinfo_t *info;
-	GaimConnection *g = sess->aux_data;
-
-	struct chat_connection *c = NULL;
-
-	va_start(ap, fr);
-	count = va_arg(ap, int);
-	info  = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	c = find_oscar_chat_by_conn(g, fr->conn);
-	if (!c)
-		return 1;
-
-	for (i = 0; i < count; i++)
-		gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c->cnv), info[i].sn, NULL);
-
-	return 1;
-}
-
-static int gaim_conv_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	aim_userinfo_t *userinfo;
-	struct aim_chat_roominfo *roominfo;
-	char *roomname;
-	int usercount;
-	char *roomdesc;
-	fu16_t unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
-	fu32_t creationtime;
-	GaimConnection *gc = sess->aux_data;
-	struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn);
-
-	va_start(ap, fr);
-	roominfo = va_arg(ap, struct aim_chat_roominfo *);
-	roomname = va_arg(ap, char *);
-	usercount= va_arg(ap, int);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	roomdesc = va_arg(ap, char *);
-	unknown_c9 = (fu16_t)va_arg(ap, unsigned int);
-	creationtime = va_arg(ap, fu32_t);
-	maxmsglen = (fu16_t)va_arg(ap, unsigned int);
-	unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
-	unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
-	maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "inside chat_info_update (maxmsglen = %hu, maxvislen = %hu)\n",
-			   maxmsglen, maxvisiblemsglen);
-
-	ccon->maxlen = maxmsglen;
-	ccon->maxvis = maxvisiblemsglen;
-
-	return 1;
-}
-
-static int gaim_conv_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	aim_userinfo_t *info;
-	char *msg;
-	struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn);
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	serv_got_chat_in(gc, ccon->id, info->sn, 0, msg, time((time_t)NULL));
-
-	return 1;
-}
-
-static int gaim_email_parseupdate(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	GaimConnection *gc = sess->aux_data;
-	struct aim_emailinfo *emailinfo;
-	int havenewmail;
-	char *alertitle, *alerturl;
-
-	va_start(ap, fr);
-	emailinfo = va_arg(ap, struct aim_emailinfo *);
-	havenewmail = va_arg(ap, int);
-	alertitle = va_arg(ap, char *);
-	alerturl  = va_arg(ap, char *);
-	va_end(ap);
-
-	if (emailinfo && gaim_account_get_check_mail(gc->account)) {
-		gchar *to = g_strdup_printf("%s@%s", gaim_account_get_username(gaim_connection_get_account(gc)), emailinfo->domain);
-		if (emailinfo->unread && havenewmail)
-			gaim_notify_emails(gc, emailinfo->nummsgs, FALSE, NULL, NULL, (const char **)&to, (const char **)&emailinfo->url, NULL, NULL);
-		g_free(to);
-	}
-	
-	if (alertitle)
-		gaim_debug(GAIM_DEBUG_MISC, "oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : "");
-
-	return 1;
-}
-
-static int gaim_icon_error(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	char *sn;
-
-	sn = od->requesticon->data;
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "removing %s from hash table\n", sn);
-	od->requesticon = g_slist_remove(od->requesticon, sn);
-	free(sn);
-
-	if (od->icontimer)
-		g_source_remove(od->icontimer);
-	od->icontimer = g_timeout_add(500, gaim_icon_timerfunc, gc);
-
-	return 1;
-}
-
-static int gaim_icon_parseicon(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	GSList *cur;
-	va_list ap;
-	char *sn;
-	fu8_t *iconcsum, *icon;
-	fu16_t iconcsumlen, iconlen;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	iconcsum = va_arg(ap, fu8_t *);
-	iconcsumlen = va_arg(ap, int);
-	icon = va_arg(ap, fu8_t *);
-	iconlen = va_arg(ap, int);
-	va_end(ap);
-
-	if (iconlen > 0) {
-		char *b16;
-		GaimBuddy *b = gaim_find_buddy(gc->account, sn);
-		gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc),
-									  sn, icon, iconlen);
-		b16 = gaim_base16_encode(iconcsum, iconcsumlen);
-		if (b16) {
-			gaim_buddy_set_setting(b, "icon_checksum", b16);
-			gaim_blist_save();
-			g_free(b16);
-		}
-	}
-
-	cur = od->requesticon;
-	while (cur) {
-		char *cursn = cur->data;
-		if (!aim_sncmp(cursn, sn)) {
-			od->requesticon = g_slist_remove(od->requesticon, cursn);
-			free(cursn);
-			cur = od->requesticon;
-		} else
-			cur = cur->next;
-	}
-
-	if (od->icontimer)
-		g_source_remove(od->icontimer);
-	od->icontimer = g_timeout_add(250, gaim_icon_timerfunc, gc);
-
-	return 1;
-}
-
-static gboolean gaim_icon_timerfunc(gpointer data) {
-	GaimConnection *gc = data;
-	OscarData *od = gc->proto_data;
-	aim_userinfo_t *userinfo;
-	aim_conn_t *conn;
-
-	conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_ICON);
-	if (!conn) {
-		if (!od->iconconnecting) {
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_ICON);
-			od->iconconnecting = TRUE;
-		}
-		return FALSE;
-	}
-
-	if (od->set_icon) {
-		struct stat st;
-		const char *iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc));
-		if (iconfile == NULL) {
-			/* Set an empty icon, or something */
-		} else if (!stat(iconfile, &st)) {
-			char *buf = g_malloc(st.st_size);
-			FILE *file = fopen(iconfile, "rb");
-			if (file) {
-				fread(buf, 1, st.st_size, file);
-				fclose(file);
-				gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Uploading icon to icon server\n");
-				aim_bart_upload(od->sess, buf, st.st_size);
-			} else
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Can't open buddy icon file!\n");
-			g_free(buf);
-		} else {
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "Can't stat buddy icon file!\n");
-		}
-		od->set_icon = FALSE;
-	}
-
-	if (!od->requesticon) {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar",
-				   "no more icons to request\n");
-		return FALSE;
-	}
-
-	userinfo = aim_locate_finduserinfo(od->sess, (char *)od->requesticon->data);
-	if ((userinfo != NULL) && (userinfo->iconcsumlen > 0)) {
-		aim_bart_request(od->sess, od->requesticon->data, userinfo->iconcsum, userinfo->iconcsumlen);
-		return FALSE;
-	} else {
-		char *sn = od->requesticon->data;
-		od->requesticon = g_slist_remove(od->requesticon, sn);
-		free(sn);
-	}
-
-	return TRUE;
-}
-
-/*
- * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
- */
-static int gaim_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t type;
-	char *sn;
-
-	va_start(ap, fr);
-	type = (fu16_t) va_arg(ap, unsigned int);
-	sn = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "Sent message to %s.\n", sn);
-
-	return 1;
-}
-
-static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) {
-	static const char *codes[5] = {
-		"invalid",
-		"change",
-		"warning",
-		"limit",
-		"limit cleared",
-	};
-	va_list ap;
-	fu16_t code, rateclass;
-	fu32_t windowsize, clear, alert, limit, disconnect, currentavg, maxavg;
-
-	va_start(ap, fr); 
-	code = (fu16_t)va_arg(ap, unsigned int);
-	rateclass= (fu16_t)va_arg(ap, unsigned int);
-	windowsize = va_arg(ap, fu32_t);
-	clear = va_arg(ap, fu32_t);
-	alert = va_arg(ap, fu32_t);
-	limit = va_arg(ap, fu32_t);
-	disconnect = va_arg(ap, fu32_t);
-	currentavg = va_arg(ap, fu32_t);
-	maxavg = va_arg(ap, fu32_t);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "rate %s (param ID 0x%04hx): curavg = %u, maxavg = %u, alert at %u, "
-		     "clear warning at %u, limit at %u, disconnect at %u (window size = %u)\n",
-		     (code < 5) ? codes[code] : codes[0],
-		     rateclass,
-		     currentavg, maxavg,
-		     alert, clear,
-		     limit, disconnect,
-		     windowsize);
-
-	/* XXX fix these values */
-	if (code == AIM_RATE_CODE_CHANGE) {
-		if (currentavg >= clear)
-			aim_conn_setlatency(fr->conn, 0);
-	} else if (code == AIM_RATE_CODE_WARNING) {
-		aim_conn_setlatency(fr->conn, windowsize/4);
-	} else if (code == AIM_RATE_CODE_LIMIT) {
-		gaim_notify_error(sess->aux_data, NULL, _("Rate limiting error."),
-						  _("The last action you attempted could not be "
-							"performed because you are over the rate limit. "
-							"Please wait 10 seconds and try again."));
-		aim_conn_setlatency(fr->conn, windowsize/2);
-	} else if (code == AIM_RATE_CODE_CLEARLIMIT) {
-		aim_conn_setlatency(fr->conn, 0);
-	}
-
-	return 1;
-}
-
-static int gaim_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t newevil;
-	aim_userinfo_t *userinfo;
-	GaimConnection *gc = sess->aux_data;
-
-	va_start(ap, fr);
-	newevil = (fu16_t) va_arg(ap, unsigned int);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	serv_got_eviled(gc, (userinfo && userinfo->sn) ? userinfo->sn : NULL, (newevil/10.0) + 0.5);
-
-	return 1;
-}
-
-static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	aim_userinfo_t *info;
-	GaimConnection *gc = sess->aux_data;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	gc->evil = (info->warnlevel/10.0) + 0.5;
-
-	if (info->onlinesince)
-		gc->login_time_official = info->onlinesince;
-
-	return 1;
-}
-
-static int gaim_connerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	va_list ap;
-	fu16_t code;
-	char *msg;
-
-	va_start(ap, fr);
-	code = (fu16_t)va_arg(ap, int);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Disconnected.  Code is 0x%04x and msg is %s\n", code, msg);
-	if ((fr) && (fr->conn) && (fr->conn->type == AIM_CONN_TYPE_BOS)) {
-		if (code == 0x0001) {
-			gc->wants_to_die = TRUE;
-			gaim_connection_error(gc, _("You have been disconnected because you have signed on with this screen name at another location."));
-		} else {
-			gaim_connection_error(gc, _("You have been signed off for an unknown reason."));
-		}
-		od->killme = TRUE;
-	}
-
-	return 1;
-}
-
-static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-
-	aim_reqpersonalinfo(sess, fr->conn);
-
-#ifndef NOSSI
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: requesting rights and list\n");
-	aim_ssi_reqrights(sess);
-	aim_ssi_reqdata(sess);
-#endif
-
-	aim_locate_reqrights(sess);
-	aim_buddylist_reqrights(sess, fr->conn);
-	aim_im_reqparams(sess);
-	aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
-
-#ifdef NOSSI
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "bos: requesting rights\n");
-	aim_bos_reqrights(sess, fr->conn);
-	aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
-	aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
-#endif
-
-	gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS);
-
-	return 1;
-}
-
-static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ADM, 0x0003, gaim_info_change, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ADM, 0x0005, gaim_info_change, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_ADM, 0x0007, gaim_account_confirm, 0);
-
-	aim_clientready(sess, fr->conn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "connected to admin\n");
-
-	if (od->chpass) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "changing password\n");
-		aim_admin_changepasswd(sess, fr->conn, od->newp, od->oldp);
-		g_free(od->oldp);
-		od->oldp = NULL;
-		g_free(od->newp);
-		od->newp = NULL;
-		od->chpass = FALSE;
-	}
-	if (od->setnick) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "formatting screenname\n");
-		aim_admin_setnick(sess, fr->conn, od->newsn);
-		g_free(od->newsn);
-		od->newsn = NULL;
-		od->setnick = FALSE;
-	}
-	if (od->conf) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "confirming account\n");
-		aim_admin_reqconfirm(sess, fr->conn);
-		od->conf = FALSE;
-	}
-	if (od->reqemail) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "requesting email\n");
-		aim_admin_getinfo(sess, fr->conn, 0x0011);
-		od->reqemail = FALSE;
-	}
-	if (od->setemail) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar", "setting email\n");
-		aim_admin_setemail(sess, fr->conn, od->email);
-		g_free(od->email);
-		od->email = NULL;
-		od->setemail = FALSE;
-	}
-
-	return 1;
-}
-
-static int gaim_icbm_param_info(aim_session_t *sess, aim_frame_t *fr, ...) {
-	struct aim_icbmparameters *params;
-	va_list ap;
-
-	va_start(ap, fr);
-	params = va_arg(ap, struct aim_icbmparameters *);
-	va_end(ap);
-
-	/* XXX - evidently this crashes on solaris. i have no clue why
-	gaim_debug(GAIM_DEBUG_MISC, "oscar", "ICBM Parameters: maxchannel = %hu, default flags = 0x%08lx, max msg len = %hu, "
-			"max sender evil = %f, max receiver evil = %f, min msg interval = %u\n",
-			params->maxchan, params->flags, params->maxmsglen,
-			((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0,
-			params->minmsginterval);
-	*/
-
-	/* Maybe senderwarn and recverwarn should be user preferences... */
-	params->flags = 0x0000000b;
-	params->maxmsglen = 8000;
-	params->minmsginterval = 0;
-
-	aim_im_setparams(sess, params);
-
-	return 1;
-}
-
-static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	va_list ap;
-	fu16_t maxsiglen;
-
-	va_start(ap, fr);
-	maxsiglen = (fu16_t) va_arg(ap, int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "locate rights: max sig len = %d\n", maxsiglen);
-
-	od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen;
-
-	if (od->icq)
-		aim_locate_setcaps(od->sess, caps_icq);
-	else
-		aim_locate_setcaps(od->sess, caps_aim);
-	oscar_set_info(gc, gc->account->user_info);
-
-	return 1;
-}
-
-static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	fu16_t maxbuddies, maxwatchers;
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	va_start(ap, fr);
-	maxbuddies = (fu16_t) va_arg(ap, unsigned int);
-	maxwatchers = (fu16_t) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "buddy list rights: Max buddies = %hu / Max watchers = %hu\n", maxbuddies, maxwatchers);
-
-	od->rights.maxbuddies = (guint)maxbuddies;
-	od->rights.maxwatchers = (guint)maxwatchers;
-
-	return 1;
-}
-
-static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	va_list ap;
-	fu16_t maxpermits, maxdenies;
-
-	va_start(ap, fr);
-	maxpermits = (fu16_t) va_arg(ap, unsigned int);
-	maxdenies = (fu16_t) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "BOS rights: Max permit = %hu / Max deny = %hu\n", maxpermits, maxdenies);
-
-	od->rights.maxpermits = (guint)maxpermits;
-	od->rights.maxdenies = (guint)maxdenies;
-
-	gaim_connection_set_state(gc, GAIM_CONNECTED);
-	serv_finish_login(gc);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "buddy list loaded\n");
-
-	aim_clientready(sess, fr->conn);
-	aim_srv_setavailmsg(sess, NULL);
-	aim_srv_setidle(sess, 0);
-
-	if (od->icq) {
-		aim_icq_reqofflinemsgs(sess);
-		aim_icq_hideip(sess);
-	}
-
-	aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV);
-	if (sess->authinfo->email)
-		aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_EMAIL);
-
-	return 1;
-}
-
-static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	struct aim_icq_offlinemsg *msg;
-	struct aim_incomingim_ch4_args args;
-	time_t t;
-
-	va_start(ap, fr);
-	msg = va_arg(ap, struct aim_icq_offlinemsg *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Received offline message.  Converting to channel 4 ICBM...\n");
-	args.uin = msg->sender;
-	args.type = msg->type;
-	args.flags = msg->flags;
-	args.msglen = msg->msglen;
-	args.msg = msg->msg;
-	t = gaim_time_build(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
-	incomingim_chan4(sess, fr->conn, NULL, &args, t);
-
-	return 1;
-}
-
-static int gaim_offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	aim_icq_ackofflinemsgs(sess);
-	return 1;
-}
-
-#if 0
-/*
- * Update, 2003-11-09:
- * Joseph S. Myers, a gcc dude, fixed this for gcc 3.4!  Rock on!
- *
- * It may not be my place to do this, but...
- * I feel pretty strongly that the "last 2 digits" warning is ridiculously 
- * stupid, and should not exist for % switches (%x in our case) that request 
- * a year in the preferred representation for the current locale.  For that 
- * reason I've chosen to not use this workaround (n., see kluge).
- *
- * I have a date.  I want to show it to the user in the "preferred" way.  
- * Whether that displays a 2 digit year is perfectly fine--after all, it's 
- * what the locale wanted.
- * 
- * If I have a necessity for a full representation of the year in the current 
- * locale, then I'll use a switch that returns a full representation of the 
- * year.
- *
- * If you think the preferred locale should show 4 digits instead of 2 digits 
- * (because you're anal, or whatever), then change the f***ing locale.
- *
- * I guess the bottom line is--I'm trying to show a date to the user how they 
- * prefer to see it, why the hell does gcc want me to change that?
- *
- * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3190
- * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8714
- */
-
-/*
- * This function was recommended by the STRFTIME(3) man page to remove the
- * "last 2 digits" warning.
- */
-static size_t my_strftime(char *s, size_t max, const char  *fmt,  
-			const struct tm *tm)
-{
-	return strftime(s, max, fmt, tm);
-}
-#endif
-
-static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	GaimConnection *gc = sess->aux_data;
-	gchar *buf, *tmp, *utf8;
-	gchar who[16];
-	GaimBuddy *buddy;
-	gchar *primary;
-	va_list ap;
-	struct aim_icq_info *info;
-
-	va_start(ap, fr);
-	info = va_arg(ap, struct aim_icq_info *);
-	va_end(ap);
-
-	if (!info->uin)
-		return 0;
-
-	g_snprintf(who, sizeof(who), "%u", info->uin);
-	buf = g_strdup_printf("<b>%s:</b> %s", _("UIN"), who);
-	if (info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Nick"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->first && info->first[0] && (utf8 = gaim_utf8_try_convert(info->first))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("First Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->last && info->last[0] && (utf8 = gaim_utf8_try_convert(info->last))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Last Name"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->email && info->email[0] && (utf8 = gaim_utf8_try_convert(info->email))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->numaddresses && info->email2) {
-		int i;
-		for (i = 0; i < info->numaddresses; i++) {
-			if (info->email2[i] && info->email2[i][0] && (utf8 = gaim_utf8_try_convert(info->email2[i]))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Email Address"), ":</b> <a href=\"mailto:", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
-			}
-		}
-	}
-	if (info->mobile && info->mobile[0] && (utf8 = gaim_utf8_try_convert(info->mobile))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Mobile Phone"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->gender) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Gender"), ":</b> ", info->gender==1 ? _("Female") : _("Male"), NULL);  g_free(tmp);
-	}
-	if (info->birthyear || info->birthmonth || info->birthday) {
-		char date[30];
-		struct tm tm;
-		tm.tm_mday = (int)info->birthday;
-		tm.tm_mon = (int)info->birthmonth-1;
-		tm.tm_year = (int)info->birthyear-1900;
-		strftime(date, sizeof(date), "%x", &tm);
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Birthday"), ":</b> ", date, NULL);  g_free(tmp);
-	}
-	if (info->age) {
-		char age[5];
-		snprintf(age, sizeof(age), "%hhd", info->age);
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Age"), ":</b> ", age, NULL);  g_free(tmp);
-	}
-	if (info->personalwebpage && info->personalwebpage[0] && (utf8 = gaim_utf8_try_convert(info->personalwebpage))) {
-		tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Personal Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
-	}
-	if (info->info && info->info[0] && (utf8 = gaim_utf8_try_convert(info->info))) {
-		tmp = buf;  buf = g_strconcat(tmp, "<hr><b>", _("Additional Information"), ":</b><br>", utf8, NULL);  g_free(tmp); g_free(utf8);
-	}
-	tmp = buf;  buf = g_strconcat(tmp, "<hr>\n", NULL);  g_free(tmp);
-	if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
-		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Home Address"), ":</b>", NULL);  g_free(tmp);
-		if (info->homeaddr && info->homeaddr[0] && (utf8 = gaim_utf8_try_convert(info->homeaddr))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->homecity && info->homecity[0] && (utf8 = gaim_utf8_try_convert(info->homecity))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8,  NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->homestate && info->homestate[0] && (utf8 = gaim_utf8_try_convert(info->homestate))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->homezip && info->homezip[0] && (utf8 = gaim_utf8_try_convert(info->homezip))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		tmp = buf; buf = g_strconcat(tmp, "\n<hr>\n", NULL); g_free(tmp);
-	}
-	if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
-		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Address"), ":</b>", NULL);  g_free(tmp);
-		if (info->workaddr && info->workaddr[0] && (utf8 = gaim_utf8_try_convert(info->workaddr))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Address"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workcity && info->workcity[0] && (utf8 = gaim_utf8_try_convert(info->workcity))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("City"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workstate && info->workstate[0] && (utf8 = gaim_utf8_try_convert(info->workstate))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("State"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workzip && info->workzip[0] && (utf8 = gaim_utf8_try_convert(info->workzip))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Zip Code"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		tmp = buf; buf = g_strconcat(tmp, "\n<hr>\n", NULL); g_free(tmp);
-	}
-	if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
-		tmp = buf;  buf = g_strconcat(tmp, "<b>", _("Work Information"), ":</b>", NULL);  g_free(tmp);
-		if (info->workcompany && info->workcompany[0] && (utf8 = gaim_utf8_try_convert(info->workcompany))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Company"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workdivision && info->workdivision[0] && (utf8 = gaim_utf8_try_convert(info->workdivision))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Division"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workposition && info->workposition[0] && (utf8 = gaim_utf8_try_convert(info->workposition))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Position"), ":</b> ", utf8, NULL);  g_free(tmp); g_free(utf8);
-		}
-		if (info->workwebpage && info->workwebpage[0] && (utf8 = gaim_utf8_try_convert(info->workwebpage))) {
-			tmp = buf;  buf = g_strconcat(tmp, "\n<br><b>", _("Web Page"), ":</b> <a href=\"", utf8, "\">", utf8, "</a>", NULL);  g_free(tmp); g_free(utf8);
-		}
-		tmp = buf; buf = g_strconcat(tmp, "\n<hr>\n", NULL); g_free(tmp);
-	}
-
-	buddy = gaim_find_buddy(gaim_connection_get_account(gc), who);
-	primary = g_strdup_printf(_("ICQ Info for %s"), gaim_get_buddy_alias(buddy));
-	gaim_notify_formatted(gc, NULL, primary, NULL, buf, NULL, NULL);
-	g_free(primary);
-	g_free(buf);
-
-	return 1;
-}
-
-static int gaim_icqalias(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	GaimConnection *gc = sess->aux_data;
-	gchar who[16], *utf8;
-	GaimBuddy *b;
-	va_list ap;
-	struct aim_icq_info *info;
-
-	va_start(ap, fr);
-	info = va_arg(ap, struct aim_icq_info *);
-	va_end(ap);
-
-	if (info->uin && info->nick && info->nick[0] && (utf8 = gaim_utf8_try_convert(info->nick))) {
-		g_snprintf(who, sizeof(who), "%u", info->uin);
-		serv_got_alias(gc, who, utf8);
-		if ((b = gaim_find_buddy(gc->account, who))) {
-			gaim_buddy_set_setting(b, "servernick", utf8);
-			gaim_blist_save();
-		}
-		g_free(utf8);
-	}
-
-	return 1;
-}
-
-static int gaim_popup(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	GaimConnection *gc = sess->aux_data;
-	gchar *text;
-	va_list ap;
-	char *msg, *url;
-	fu16_t wid, hei, delay;
-
-	va_start(ap, fr);
-	msg = va_arg(ap, char *);
-	url = va_arg(ap, char *);
-	wid = (fu16_t) va_arg(ap, int);
-	hei = (fu16_t) va_arg(ap, int);
-	delay = (fu16_t) va_arg(ap, int);
-	va_end(ap);
-
-	text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url);
-	gaim_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL);
-	g_free(text);
-
-	return 1;
-}
-
-static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	GaimConnection *gc = sess->aux_data;
-	gchar *secondary;
-	GString *text;
-	int i, num;
-	va_list ap;
-	char *email, *SNs;
-
-	va_start(ap, fr);
-	email = va_arg(ap, char *);
-	num = va_arg(ap, int);
-	SNs = va_arg(ap, char *);
-	va_end(ap);
-
-	secondary = g_strdup_printf(_("The following screennames are associated with %s"), email);
-	text = g_string_new("");
-	for (i = 0; i < num; i++)
-		g_string_append_printf(text, "%s<br>", &SNs[i * (MAXSNLEN + 1)]);
-	gaim_notify_formatted(gc, NULL, _("Search Results"), secondary, text->str, NULL, NULL);
-
-	g_free(secondary);
-	g_string_free(text, TRUE);
-
-	return 1;
-}
-
-static int gaim_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	char *email;
-	char *buf;
-
-	va_start(ap, fr);
-	email = va_arg(ap, char *);
-	va_end(ap);
-
-	buf = g_strdup_printf(_("No results found for email address %s"), email);
-	gaim_notify_error(sess->aux_data, NULL, buf, NULL);
-	g_free(buf);
-
-	return 1;
-}
-
-static int gaim_account_confirm(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	fu16_t status;
-	va_list ap;
-	char msg[256];
-
-	va_start(ap, fr);
-	status = (fu16_t) va_arg(ap, unsigned int); /* status code of confirmation request */
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "account confirmation returned status 0x%04x (%s)\n", status,
-			status ? "unknown" : "email sent");
-	if (!status) {
-		g_snprintf(msg, sizeof(msg), _("You should receive an email asking to confirm %s."),
-				gaim_account_get_username(gaim_connection_get_account(gc)));
-		gaim_notify_info(gc, NULL, _("Account Confirmation Requested"), msg);
-	}
-
-	return 1;
-}
-
-static int gaim_info_change(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	fu16_t perms, err;
-	char *url, *sn, *email;
-	int change;
-
-	va_start(ap, fr);
-	change = va_arg(ap, int);
-	perms = (fu16_t) va_arg(ap, unsigned int);
-	err = (fu16_t) va_arg(ap, unsigned int);
-	url = va_arg(ap, char *);
-	sn = va_arg(ap, char *);
-	email = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar",
-			   "account info: because of %s, perms=0x%04x, err=0x%04x, url=%s, sn=%s, email=%s\n",
-		change ? "change" : "request", perms, err, url, sn, email);
-
-	if (err && url) {
-		char *dialog_msg;
-		char *dialog_top = g_strdup_printf(_("Error Changing Account Info"));
-		switch (err) {
-			case 0x0001: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name differs from the original."), err);
-			} break;
-			case 0x0006: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name ends in a space."), err);
-			} break;
-			case 0x000b: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name is too long."), err);
-			} break;
-			case 0x001d: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because there is already a request pending for this screen name."), err);
-			} break;
-			case 0x0021: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address has too many screen names associated with it."), err);
-			} break;
-			case 0x0023: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address is invalid."), err);
-			} break;
-			default: {
-				dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err);
-			} break;
-		}
-		gaim_notify_error(gc, NULL, dialog_top, dialog_msg);
-		g_free(dialog_top);
-		g_free(dialog_msg);
-		return 1;
-	}
-
-	if (sn) {
-		char *dialog_msg = g_strdup_printf(_("Your screen name is currently formatted as follows:\n%s"), sn);
-		gaim_notify_info(gc, NULL, _("Account Info"), dialog_msg);
-		g_free(dialog_msg);
-	}
-
-	if (email) {
-		char *dialog_msg = g_strdup_printf(_("The email address for %s is %s"), 
-						   gaim_account_get_username(gaim_connection_get_account(gc)), email);
-		gaim_notify_info(gc, NULL, _("Account Info"), dialog_msg);
-		g_free(dialog_msg);
-	}
-
-	return 1;
-}
-
-static void oscar_keepalive(GaimConnection *gc) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	aim_flap_nop(od->sess, od->conn);
-}
-
-static int oscar_send_typing(GaimConnection *gc, const char *name, int typing) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	struct direct_im *dim = find_direct_im(od, name);
-	if (dim)
-		if (typing == GAIM_TYPING)
-			aim_odc_send_typing(od->sess, dim->conn, 0x0002);
-		else if (typing == GAIM_TYPED)
-			aim_odc_send_typing(od->sess, dim->conn, 0x0001);
-		else
-			aim_odc_send_typing(od->sess, dim->conn, 0x0000);
-	else {
-		/* Don't send if this turkey is in our deny list */
-		GSList *list;
-		for (list=gc->account->deny; (list && aim_sncmp(name, list->data)); list=list->next);
-		if (!list) {
-			struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
-			if (bi && bi->typingnot) {
-				if (typing == GAIM_TYPING)
-					aim_im_sendmtn(od->sess, 0x0001, name, 0x0002);
-				else if (typing == GAIM_TYPED)
-					aim_im_sendmtn(od->sess, 0x0001, name, 0x0001);
-				else
-					aim_im_sendmtn(od->sess, 0x0001, name, 0x0000);
-			}
-		}
-	}
-	return 0;
-}
-static void oscar_ask_direct_im(GaimConnection *gc, const char *name);
-static int gaim_odc_send_im(aim_session_t *, aim_conn_t *, const char *, GaimConvImFlags);
-
-static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimConvImFlags imflags) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	struct direct_im *dim = find_direct_im(od, name);
-	int ret = 0;
-	GError *err = NULL;
-	const char *iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc));
-	char *tmpmsg = NULL;
-
-	if (dim && dim->connected) {
-		/* If we're directly connected, send a direct IM */
-		ret = gaim_odc_send_im(od->sess, dim->conn, message, imflags);
-	} else if (imflags & GAIM_CONV_IM_IMAGES) {
-		/* Trying to send an IM image outside of a direct connection. */
-		oscar_ask_direct_im(gc, name);
-		ret = -ENOTCONN;
-	} else {
-		struct buddyinfo *bi;
-		struct aim_sendimext_args args;
-		struct stat st;
-		gsize len;
-
-		bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name));
-		if (!bi) {
-			bi = g_new0(struct buddyinfo, 1);
-			g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(gc->account, name)), bi);
-		}
-
-		args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES;
-		if (od->icq) {
-			args.features = features_icq;
-			args.featureslen = sizeof(features_icq);
-			args.flags |= AIM_IMFLAGS_OFFLINE;
-		} else {
-			args.features = features_aim;
-			args.featureslen = sizeof(features_aim);
-
-			if (imflags & GAIM_CONV_IM_AUTO_RESP)
-				args.flags |= AIM_IMFLAGS_AWAY;
-		}
-
-		if (bi->ico_need) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Sending buddy icon request with message\n");
-			args.flags |= AIM_IMFLAGS_BUDDYREQ;
-			bi->ico_need = FALSE;
-		}
-
-		if (iconfile && !stat(iconfile, &st)) {
-			FILE *file = fopen(iconfile, "r");
-			if (file) {
-				char *buf = g_malloc(st.st_size);
-				fread(buf, 1, st.st_size, file);
-				fclose(file);
-
-				args.iconlen   = st.st_size;
-				args.iconsum   = aimutil_iconsum(buf, st.st_size);
-				args.iconstamp = st.st_mtime;
-
-				if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) {
-					bi->ico_informed = FALSE;
-					bi->ico_sent     = FALSE;
-				}
-
-				if (!bi->ico_informed) {
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "Claiming to have a buddy icon\n");
-					args.flags |= AIM_IMFLAGS_HASICON;
-					bi->ico_me_len = args.iconlen;
-					bi->ico_me_csum = args.iconsum;
-					bi->ico_me_time = args.iconstamp;
-					bi->ico_informed = TRUE;
-				}
-
-				g_free(buf);
-			}
-		}
-
-		args.destsn = name;
-
-		/* For ICQ send newlines as CR/LF, for AIM send newlines as <BR> */
-		if (isdigit(name[0]))
-			tmpmsg = gaim_str_add_cr(message);
-		else
-			tmpmsg = gaim_strdup_withhtml(message);
-		len = strlen(tmpmsg);
-
-		args.flags |= oscar_encoding_check(tmpmsg);
-		if (args.flags & AIM_IMFLAGS_UNICODE) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar", "Sending Unicode IM\n");
-			args.charset = 0x0002;
-			args.charsubset = 0x0000;
-			args.msg = g_convert(tmpmsg, len, "UCS-2BE", "UTF-8", NULL, &len, &err);
-			if (err) {
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "Error converting a unicode message: %s\n", err->message);
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "This really shouldn't happen!\n");
-				/* We really shouldn't try to send the
-				 * IM now, but I'm not sure what to do */
-				g_error_free(err);
-			}
-		} else if (args.flags & AIM_IMFLAGS_ISO_8859_1) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Sending ISO-8859-1 IM\n");
-			args.charset = 0x0003;
-			args.charsubset = 0x0000;
-			args.msg = g_convert(tmpmsg, len, "ISO-8859-1", "UTF-8", NULL, &len, &err);
-			if (err) {
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "conversion error: %s\n", err->message);
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "Someone tell Ethan his 8859-1 detection is wrong\n");
-				args.flags ^= AIM_IMFLAGS_ISO_8859_1 | AIM_IMFLAGS_UNICODE;
-				len = strlen(tmpmsg);
-				g_error_free(err);
-				args.msg = g_convert(tmpmsg, len, "UCS-2BE", "UTF8", NULL, &len, &err);
-				if (err) {
-					gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-							   "Error in unicode fallback: %s\n", err->message);
-					g_error_free(err);
-				}
-			}
-		} else {
-			args.charset = 0x0000;
-			args.charsubset = 0x0000;
-			args.msg = tmpmsg;
-		}
-		args.msglen = len;
-
-		ret = aim_im_sendch1_ext(od->sess, &args);
-	}
-
-	g_free(tmpmsg);
-
-	if (ret >= 0)
-		return 1;
-
-	return ret;
-}
-
-static void oscar_get_info(GaimConnection *gc, const char *name) {
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	if (od->icq && isdigit(name[0]))
-		aim_icq_getallinfo(od->sess, name);
-	else
-		aim_locate_getinfoshort(od->sess, name, 0x00000003);
-}
-
-static void oscar_get_away(GaimConnection *gc, const char *who) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	if (od->icq) {
-		GaimBuddy *budlight = gaim_find_buddy(gc->account, who);
-		if (budlight)
-			if ((budlight->uc & 0xffff0000) >> 16)
-				aim_im_sendch2_geticqaway(od->sess, who, (budlight->uc & 0xffff0000) >> 16);
-			else
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-						   "Error: The user %s has no status message, therefore not requesting.\n", who);
-		else
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-					   "Error: Could not find %s in local buddy list, therefore unable to request status message.\n", who);
-	} else
-		aim_locate_getinfoshort(od->sess, who, 0x00000002);
-}
-
-static void oscar_set_dir(GaimConnection *gc, const char *first, const char *middle, const char *last,
-			  const char *maiden, const char *city, const char *state, const char *country, int web) {
-	/* XXX - some of these things are wrong, but i'm lazy */
-	OscarData *od = (OscarData *)gc->proto_data;
-	aim_locate_setdirinfo(od->sess, first, middle, last,
-				maiden, NULL, NULL, city, state, NULL, 0, web);
-}
-
-static void oscar_set_idle(GaimConnection *gc, int time) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	aim_srv_setidle(od->sess, time);
-}
-
-static void oscar_set_info(GaimConnection *gc, const char *text) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	fu32_t flags = 0;
-	char *text_html = NULL;
-	char *msg = NULL;
-	gsize msglen = 0;
-
-	if (od->rights.maxsiglen == 0)
-		gaim_notify_warning(gc, NULL, _("Unable to set AIM profile."),
-							_("You have probably requested to set your "
-							  "profile before the login procedure completed.  "
-							  "Your profile remains unset; try setting it "
-							  "again when you are fully connected."));
-
-	if (!text) {
-		aim_locate_setprofile(od->sess, NULL, "", 0, NULL, NULL, 0);
-		return;
-	}
-		
-	text_html = gaim_strdup_withhtml(text);
-	flags = oscar_encoding_check(text_html);
-	if (flags & AIM_IMFLAGS_UNICODE) {
-		msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
-		aim_locate_setprofile(od->sess, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
-		g_free(msg);
-	} else if (flags & AIM_IMFLAGS_ISO_8859_1) {
-		msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
-		aim_locate_setprofile(od->sess, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
-		g_free(msg);
-	} else {
-		msglen = strlen(text_html);
-		aim_locate_setprofile(od->sess, "us-ascii", text_html, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0);
-	}
-
-	if (msglen > od->rights.maxsiglen) {
-		gchar *errstr;
-		errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte "
-								 "has been exceeded.  Gaim has truncated it for you.",
-								 "The maximum profile length of %d bytes "
-								 "has been exceeded.  Gaim has truncated it for you.",
-								 od->rights.maxsiglen), od->rights.maxsiglen);
-		gaim_notify_warning(gc, NULL, _("Profile too long."), errstr);
-		g_free(errstr);
-	}
-
-	g_free(text_html);
-
-	return;
-}
-
-static void oscar_set_away_aim(GaimConnection *gc, OscarData *od, const char *text)
-{
-	fu32_t flags = 0;
-	gchar *text_html = NULL;
-	char *msg = NULL;
-	gsize msglen = 0;
-
-	if (od->rights.maxawaymsglen == 0)
-		gaim_notify_warning(gc, NULL, _("Unable to set AIM away message."),
-							_("You have probably requested to set your "
-							  "away message before the login procedure "
-							  "completed.  You remain in a \"present\" "
-							  "state; try setting it again when you are "
-							  "fully connected."));
-
-	if (gc->away) {
-		g_free(gc->away);
-		gc->away = NULL;
-	}
-
-	if (!text) {
-		aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
-		return;
-	}
-
-	text_html = gaim_strdup_withhtml(text);
-	flags = oscar_encoding_check(text_html);
-	if (flags & AIM_IMFLAGS_UNICODE) {
-		msg = g_convert(text_html, strlen(text_html), "UCS-2BE", "UTF-8", NULL, &msglen, NULL);
-		aim_locate_setprofile(od->sess, NULL, NULL, 0, "unicode-2-0", msg, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
-		g_free(msg);
-		gc->away = g_strndup(text, od->rights.maxawaymsglen/2);
-	} else if (flags & AIM_IMFLAGS_ISO_8859_1) {
-		msg = g_convert(text_html, strlen(text_html), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL);
-		aim_locate_setprofile(od->sess, NULL, NULL, 0, "iso-8859-1", msg, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
-		g_free(msg);
-		gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
-	} else {
-		msglen = strlen(text_html);
-		aim_locate_setprofile(od->sess, NULL, NULL, 0, "us-ascii", text_html, 
-			(msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen));
-		gc->away = g_strndup(text_html, od->rights.maxawaymsglen);
-	}
-
-	if (msglen > od->rights.maxawaymsglen) {
-		gchar *errstr;
-
-		errstr = g_strdup_printf(ngettext("The maximum away message length of %d byte "
-								 "has been exceeded.  Gaim has truncated it for you.",
-								 "The maximum away message length of %d bytes "
-								 "has been exceeded.  Gaim has truncated it for you.",
-								 od->rights.maxawaymsglen), od->rights.maxawaymsglen);
-		gaim_notify_warning(gc, NULL, _("Away message too long."), errstr);
-		g_free(errstr);
-	}
-	
-	g_free(text_html);
-	return;
-}
-
-static void oscar_set_away_icq(GaimConnection *gc, OscarData *od, const char *state, const char *message)
-{
-	GaimAccount *account = gaim_connection_get_account(gc);
-	if (gc->away) {
-		g_free(gc->away);
-		gc->away = NULL;
-	}
-
-	if (strcmp(state, _("Invisible"))) {
-		if ((od->sess->ssi.received_data) && (aim_ssi_getpermdeny(od->sess->ssi.local) != account->perm_deny))
-			aim_ssi_setpermdeny(od->sess, account->perm_deny, 0xffffffff);
-		account->perm_deny = 4;
-	} else {
-		if ((od->sess->ssi.received_data) && (aim_ssi_getpermdeny(od->sess->ssi.local) != 0x03))
-			aim_ssi_setpermdeny(od->sess, 0x03, 0xffffffff);
-		account->perm_deny = 3;
-	}
-
-	if (!strcmp(state, _("Online")))
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_NORMAL);
-	else if (!strcmp(state, _("Away"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_AWAY);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, _("Do Not Disturb"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, _("Not Available"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, _("Occupied"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, _("Free For Chat"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_CHAT);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, _("Invisible"))) {
-		aim_setextstatus(od->sess, AIM_ICQ_STATE_INVISIBLE);
-		gc->away = g_strdup("");
-	} else if (!strcmp(state, GAIM_AWAY_CUSTOM)) {
-	 	if (message) {
-			aim_setextstatus(od->sess, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY);
-			gc->away = g_strdup("");
-		} else {
-			aim_setextstatus(od->sess, AIM_ICQ_STATE_NORMAL);
-		}
-	}
-
-	return;
-}
-
-static void oscar_set_away(GaimConnection *gc, const char *state, const char *message)
-{
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	if (od->icq)
-		oscar_set_away_icq(gc, od, state, message);
-	else
-		oscar_set_away_aim(gc, od, message);
-
-	return;
-}
-
-static void oscar_warn(GaimConnection *gc, const char *name, int anon) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	aim_im_warn(od->sess, od->conn, name, anon ? AIM_WARN_ANON : 0);
-}
-
-static void oscar_dir_search(GaimConnection *gc, const char *first, const char *middle, const char *last,
-			     const char *maiden, const char *city, const char *state, const char *country, const char *email) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	if (strlen(email))
-		aim_search_address(od->sess, od->conn, email);
-}
-
-static void oscar_add_buddy(GaimConnection *gc, const char *name, GaimGroup *g) {
-	OscarData *od = (OscarData *)gc->proto_data;
-#ifdef NOSSI
-	aim_add_buddy(od->sess, od->conn, name);
-#else
-	if ((od->sess->ssi.received_data) && !(aim_ssi_itemlist_exists(od->sess->ssi.local, name))) {
-		GaimBuddy *buddy = gaim_find_buddy(gc->account, name);
-		GaimGroup *group = gaim_find_buddys_group(buddy);
-		if (buddy && group) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: adding buddy %s to group %s\n", name, group->name);
-			aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
-		}
-	}
-#endif
-	if (od->icq)
-		aim_icq_getalias(od->sess, name);
-}
-
-static void oscar_add_buddies(GaimConnection *gc, GList *buddies) {
-	OscarData *od = (OscarData *)gc->proto_data;
-#ifdef NOSSI
-	char buf[MSG_LEN];
-	int n=0;
-	while (buddies) {
-		if (n > MSG_LEN - 18) {
-			aim_buddylist_set(od->sess, od->conn, buf);
-			n = 0;
-		}
-		n += g_snprintf(buf + n, sizeof(buf) - n, "%s&", (char *)buddies->data);
-		buddies = buddies->next;
-	}
-	aim_buddylist_set(od->sess, od->conn, buf);
-#else
-	if (od->sess->ssi.received_data) {
-		while (buddies) {
-			oscar_add_buddy(gc, (const char *)buddies->data, NULL);
-			buddies = buddies->next;
-		}
-	}
-#endif
-}
-
-static void oscar_remove_buddy(GaimConnection *gc, const char *name, const char *group) {
-	OscarData *od = (OscarData *)gc->proto_data;
-#ifdef NOSSI
-	aim_remove_buddy(od->sess, od->conn, name);
-#else
-	if (od->sess->ssi.received_data) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "ssi: deleting buddy %s from group %s\n", name, group);
-		aim_ssi_delbuddy(od->sess, name, group);
-	}
-#endif
-}
-
-static void oscar_remove_buddies(GaimConnection *gc, GList *buddies, const char *group) {
-	OscarData *od = (OscarData *)gc->proto_data;
-#ifdef NOSSI
-	GList *cur;
-	for (cur=buddies; cur; cur=cur->next)
-		aim_remove_buddy(od->sess, od->conn, cur->data);
-#else
-	if (od->sess->ssi.received_data) {
-		while (buddies) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: deleting buddy %s from group %s\n", (char *)buddies->data, group);
-			aim_ssi_delbuddy(od->sess, buddies->data, group);
-			buddies = buddies->next;
-		}
-	}
-#endif
-}
-
-#ifndef NOSSI
-static void oscar_move_buddy(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	if (od->sess->ssi.received_data && strcmp(old_group, new_group)) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "ssi: moving buddy %s from group %s to group %s\n", name, old_group, new_group);
-		aim_ssi_movebuddy(od->sess, old_group, new_group, name);
-	}
-}
-
-static void oscar_alias_buddy(GaimConnection *gc, const char *name, const char *alias) {
-	OscarData *od = (OscarData *)gc->proto_data;
-	if (od->sess->ssi.received_data) {
-		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, name);
-		if (gname) {
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: changing the alias for buddy %s to %s\n", name, alias);
-			aim_ssi_aliasbuddy(od->sess, gname, name, alias);
-		}
-	}
-}
-
-static void oscar_rename_group(GaimConnection *g, const char *old_group, const char *new_group, GList *members) {
-	OscarData *od = (OscarData *)g->proto_data;
-
-	if (od->sess->ssi.received_data) {
-		if (aim_ssi_itemlist_finditem(od->sess->ssi.local, new_group, NULL, AIM_SSI_TYPE_GROUP)) {
-			oscar_remove_buddies(g, members, old_group);
-			oscar_add_buddies(g, members);
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: moved all buddies from group %s to %s\n", old_group, new_group);
-		} else {
-			aim_ssi_rename_group(od->sess, old_group, new_group);
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "ssi: renamed group %s to %s\n", old_group, new_group);
-		}
-	}
-}
-
-static gboolean gaim_ssi_rerequestdata(gpointer data) {
-	aim_session_t *sess = data;
-	aim_ssi_reqdata(sess);
-	return FALSE;
-}
-
-static int gaim_ssi_parseerr(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	va_list ap;
-	fu16_t reason;
-
-	va_start(ap, fr);
-	reason = (fu16_t)va_arg(ap, unsigned int);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_ERROR, "oscar", "ssi: SNAC error %hu\n", reason);
-
-	if (reason == 0x0005) {
-		gaim_notify_error(gc, NULL, _("Unable To Retrieve Buddy List"),
-						  _("Gaim was temporarily unable to retrieve your buddy list from the AIM servers.  Your buddy list is not lost, and will probably become available in a few hours."));
-		od->getblisttimer = g_timeout_add(300000, gaim_ssi_rerequestdata, od->sess);
-	}
-
-	/* Activate SSI */
-	/* Sending the enable causes other people to be able to see you, and you to see them */
-	/* Make sure your privacy setting/invisibility is set how you want it before this! */
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: activating server-stored buddy list\n");
-	aim_ssi_enable(od->sess);
-
-	return 1;
-}
-
-static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	int numtypes, i;
-	fu16_t *maxitems;
-	va_list ap;
-
-	va_start(ap, fr);
-	numtypes = va_arg(ap, int);
-	maxitems = va_arg(ap, fu16_t *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_MISC, "oscar", "ssi rights:");
-
-	for (i=0; i<numtypes; i++)
-		gaim_debug(GAIM_DEBUG_MISC, NULL, " max type 0x%04x=%hd,",
-				   i, maxitems[i]);
-
-	gaim_debug(GAIM_DEBUG_MISC, NULL, "\n");
-
-	if (numtypes >= 0)
-		od->rights.maxbuddies = maxitems[0];
-	if (numtypes >= 1)
-		od->rights.maxgroups = maxitems[1];
-	if (numtypes >= 2)
-		od->rights.maxpermits = maxitems[2];
-	if (numtypes >= 3)
-		od->rights.maxdenies = maxitems[3];
-
-	return 1;
-}
-
-static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	GaimAccount *account = gaim_connection_get_account(gc);
-	OscarData *od = (OscarData *)gc->proto_data;
-	struct aim_ssi_item *curitem;
-	int tmp;
-	gboolean export = FALSE;
-	/* XXX - use these?
-	va_list ap;
-
-	va_start(ap, fr);
-	fmtver = (fu16_t)va_arg(ap, int);
-	numitems = (fu16_t)va_arg(ap, int);
-	items = va_arg(ap, struct aim_ssi_item);
-	timestamp = va_arg(ap, fu32_t);
-	va_end(ap); */
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: syncing local list and server list\n");
-
-	/* Clean the buddy list */
-	aim_ssi_cleanlist(sess);
-
-	/* Add from server list to local list */
-	for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
-		if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
-		switch (curitem->type) {
-			case 0x0000: { /* Buddy */
-				if (curitem->name) {
-					char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name);
-					char *gname_utf8 = gname ? gaim_utf8_try_convert(gname) : NULL;
-					char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
-					char *alias_utf8 = alias ? gaim_utf8_try_convert(alias) : NULL;
-					GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
-					/* Should gname be freed here? -- elb */
-					/* Not with the current code, but that might be cleaner -- med */
-					free(alias);
-					if (buddy) {
-						/* Get server stored alias */
-						if (alias_utf8) {
-							g_free(buddy->alias);
-							buddy->alias = g_strdup(alias_utf8);
-						}
-					} else {
-						GaimGroup *g;
-						buddy = gaim_buddy_new(gc->account, curitem->name, alias_utf8);
-
-						if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-							g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
-							gaim_blist_add_group(g, NULL);
-						}
-
-						gaim_debug(GAIM_DEBUG_INFO, "oscar",
-								   "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
-						gaim_blist_add_buddy(buddy, NULL, g, NULL);
-						export = TRUE;
-					}
-					g_free(gname_utf8);
-					g_free(alias_utf8);
-				}
-			} break;
-
-			case 0x0001: { /* Group */
-				/* Shouldn't add empty groups */
-			} break;
-
-			case 0x0002: { /* Permit buddy */
-				if (curitem->name) {
-					/* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */
-					GSList *list;
-					for (list=account->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
-					if (!list) {
-						gaim_debug(GAIM_DEBUG_INFO, "oscar",
-								   "ssi: adding permit buddy %s to local list\n", curitem->name);
-						gaim_privacy_permit_add(account, curitem->name, TRUE);
-						export = TRUE;
-					}
-				}
-			} break;
-
-			case 0x0003: { /* Deny buddy */
-				if (curitem->name) {
-					GSList *list;
-					for (list=account->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
-					if (!list) {
-						gaim_debug(GAIM_DEBUG_INFO, "oscar",
-								   "ssi: adding deny buddy %s to local list\n", curitem->name);
-						gaim_privacy_deny_add(account, curitem->name, TRUE);
-						export = TRUE;
-					}
-				}
-			} break;
-
-			case 0x0004: { /* Permit/deny setting */
-				if (curitem->data) {
-					fu8_t permdeny;
-					if ((permdeny = aim_ssi_getpermdeny(sess->ssi.local)) && (permdeny != account->perm_deny)) {
-						gaim_debug(GAIM_DEBUG_INFO, "oscar",
-								   "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, permdeny);
-						account->perm_deny = permdeny;
-						if (od->icq && account->perm_deny == 0x03) {
-							serv_set_away(gc, "Invisible", "");
-						}
-						export = TRUE;
-					}
-				}
-			} break;
-
-			case 0x0005: { /* Presence setting */
-				/* We don't want to change Gaim's setting because it applies to all accounts */
-			} break;
-		} /* End of switch on curitem->type */
-	} /* End of for loop */
-
-	/* If changes were made, then flush buddy list to file */
-	if (export)
-		gaim_blist_save();
-
-	{ /* Add from local list to server list */
-		GaimBlistNode *gnode, *cnode, *bnode;
-		GaimGroup *group;
-		GaimBuddy *buddy;
-		GaimBuddyList *blist;
-		GSList *cur;
-
-		/* Buddies */
-		if ((blist = gaim_get_blist()))
-			for (gnode = blist->root; gnode; gnode = gnode->next) {
-				if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
-					continue;
-				group = (GaimGroup *)gnode;
-				for (cnode = gnode->child; cnode; cnode = cnode->next) {
-					if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
-						continue;
-					for (bnode = cnode->child; bnode; bnode = bnode->next) {
-						if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-							continue;
-						buddy = (GaimBuddy *)bnode;
-						if (buddy->account == gc->account) {
-							const char *servernick = gaim_buddy_get_setting(buddy, "servernick");
-							if (servernick)
-								serv_got_alias(gc, buddy->name, servernick);
-
-							if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
-								/* Store local alias on server */
-								char *alias = aim_ssi_getalias(sess->ssi.local, group->name, buddy->name);
-								if (!alias && buddy->alias && strlen(buddy->alias))
-									aim_ssi_aliasbuddy(sess, group->name, buddy->name, buddy->alias);
-								free(alias);
-							} else {
-								gaim_debug(GAIM_DEBUG_INFO, "oscar",
-										"ssi: adding buddy %s from local list to server list\n", buddy->name);
-								aim_ssi_addbuddy(sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
-							}
-						}
-					}
-				}
-			}
-
-		/* Permit list */
-		if (gc->account->permit) {
-			for (cur=gc->account->permit; cur; cur=cur->next)
-				if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							"ssi: adding permit %s from local list to server list\n", (char *)cur->data);
-					aim_ssi_addpermit(sess, cur->data);
-				}
-		}
-
-		/* Deny list */
-		if (gc->account->deny) {
-			for (cur=gc->account->deny; cur; cur=cur->next)
-				if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) {
-					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							"ssi: adding deny %s from local list to server list\n", (char *)cur->data);
-					aim_ssi_adddeny(sess, cur->data);
-				}
-		}
-		/* Presence settings (idle time visibility) */
-		if ((tmp = aim_ssi_getpresence(sess->ssi.local)) != 0xFFFFFFFF)
-			if (!(tmp & 0x400))
-				aim_ssi_setpresence(sess, tmp | 0x400);
-	} /* end adding buddies from local list to server list */
-
-	/* Set our ICQ status */
-	if  (od->icq && !gc->away) {
-		aim_setextstatus(sess, AIM_ICQ_STATE_NORMAL);
-	}
-
-	/* Activate SSI */
-	/* Sending the enable causes other people to be able to see you, and you to see them */
-	/* Make sure your privacy setting/invisibility is set how you want it before this! */
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: activating server-stored buddy list\n");
-	aim_ssi_enable(sess);
-
-	return 1;
-}
-
-static int gaim_ssi_parseack(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	struct aim_ssi_tmp *retval;
-
-	va_start(ap, fr);
-	retval = va_arg(ap, struct aim_ssi_tmp *);
-	va_end(ap);
-
-	while (retval) {
-		gaim_debug(GAIM_DEBUG_MISC, "oscar",
-				   "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack,  retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item");
-
-		if (retval->ack != 0xffff)
-		switch (retval->ack) {
-			case 0x0000: { /* added successfully */
-			} break;
-
-			case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */
-				gchar *buf;
-				buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list.  Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
-				gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
-				g_free(buf);
-			}
-
-			case 0x000e: { /* buddy requires authorization */
-				if ((retval->action == AIM_CB_SSI_ADD) && (retval->name))
-					gaim_auth_sendrequest(gc, retval->name);
-			} break;
-
-			default: { /* La la la */
-				gchar *buf;
-				gaim_debug(GAIM_DEBUG_ERROR, "oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
-				buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason.  The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)")));
-				gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
-				g_free(buf);
-				/* XXX - Should remove buddy from local list */
-			} break;
-		}
-
-		retval = retval->next;
-	}
-
-	return 1;
-}
-
-static int gaim_ssi_authgiven(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	char *sn, *msg;
-	gchar *dialog_msg, *nombre;
-	struct name_data *data;
-	GaimBuddy *buddy;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: %s has given you permission to add him to your buddy list\n", sn);
-
-	buddy = gaim_find_buddy(gc->account, sn);
-	if (buddy && (gaim_get_buddy_alias_only(buddy)))
-		nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-	else
-		nombre = g_strdup(sn);
-
-	dialog_msg = g_strdup_printf(_("The user %s has given you permission to add you to their buddy list.  Do you want to add them?"), nombre);
-	data = g_new(struct name_data, 1);
-	data->gc = gc;
-	data->name = g_strdup(sn);
-	data->nick = NULL;
-
-	gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
-						0, data,
-						G_CALLBACK(gaim_icq_buddyadd),
-						G_CALLBACK(oscar_free_name_data));
-
-	g_free(dialog_msg);
-	g_free(nombre);
-
-	return 1;
-}
-
-static int gaim_ssi_authrequest(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	char *sn, *msg;
-	gchar *dialog_msg, *nombre;
-	struct name_data *data;
-	GaimBuddy *buddy;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: received authorization request from %s\n", sn);
-
-	buddy = gaim_find_buddy(gc->account, sn);
-	if (buddy && (gaim_get_buddy_alias_only(buddy)))
-		nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-	else
-		nombre = g_strdup(sn);
-
-	dialog_msg = g_strdup_printf(_("The user %s wants to add you to their buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
-	data = g_new(struct name_data, 1);
-	data->gc = gc;
-	data->name = g_strdup(sn);
-	data->nick = NULL;
-
-	gaim_request_action(gc, NULL, _("Authorization Request"), dialog_msg,
-						0, data, 2,
-						_("Authorize"), G_CALLBACK(gaim_auth_grant),
-						_("Deny"), G_CALLBACK(gaim_auth_dontgrant_msgprompt));
-
-	g_free(dialog_msg);
-	g_free(nombre);
-
-	return 1;
-}
-
-static int gaim_ssi_authreply(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	char *sn, *msg;
-	gchar *dialog_msg, *nombre;
-	fu8_t reply;
-	GaimBuddy *buddy;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	reply = (fu8_t)va_arg(ap, int);
-	msg = va_arg(ap, char *);
-	va_end(ap);
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: received authorization reply from %s.  Reply is 0x%04hhx\n", sn, reply);
-
-	buddy = gaim_find_buddy(gc->account, sn);
-	if (buddy && (gaim_get_buddy_alias_only(buddy)))
-		nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
-	else
-		nombre = g_strdup(sn);
-
-	if (reply) {
-		/* Granted */
-		dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
-		gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
-	} else {
-		/* Denied */
-		dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
-		gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
-	}
-	g_free(dialog_msg);
-	g_free(nombre);
-
-	return 1;
-}
-
-static int gaim_ssi_gotadded(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	va_list ap;
-	char *sn;
-	GaimBuddy *buddy;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	va_end(ap);
-
-	buddy = gaim_find_buddy(gc->account, sn);
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "ssi: %s added you to their buddy list\n", sn);
-	gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
-
-	return 1;
-}
-#endif
-
-static GList *oscar_chat_info(GaimConnection *gc) {
-	GList *m = NULL;
-	struct proto_chat_entry *pce;
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("Join what group:");
-	pce->identifier = "room";
-	m = g_list_append(m, pce);
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("Exchange:");
-	pce->identifier = "exchange";
-	pce->is_int = TRUE;
-	pce->min = 4;
-	pce->max = 20;
-	m = g_list_append(m, pce);
-
-	return m;
-}
-
-static void oscar_join_chat(GaimConnection *g, GHashTable *data) {
-	OscarData *od = (OscarData *)g->proto_data;
-	aim_conn_t *cur;
-	char *name, *exchange;
-
-	name = g_hash_table_lookup(data, "room");
-	exchange = g_hash_table_lookup(data, "exchange");
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Attempting to join chat room %s.\n", name);
-	if ((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) {
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "chatnav exists, creating room\n");
-		aim_chatnav_createroom(od->sess, cur, name, atoi(exchange));
-	} else {
-		/* this gets tricky */
-		struct create_room *cr = g_new0(struct create_room, 1);
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "chatnav does not exist, opening chatnav\n");
-		cr->exchange = atoi(exchange);
-		cr->name = g_strdup(name);
-		od->create_rooms = g_slist_append(od->create_rooms, cr);
-		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_CHATNAV);
-	}
-}
-
-static void oscar_chat_invite(GaimConnection *g, int id, const char *message, const char *name) {
-	OscarData *od = (OscarData *)g->proto_data;
-	struct chat_connection *ccon = find_oscar_chat(g, id);
-	
-	if (!ccon)
-		return;
-	
-	aim_chat_invite(od->sess, od->conn, name, message ? message : "",
-			ccon->exchange, ccon->name, 0x0);
-}
-
-static void oscar_chat_leave(GaimConnection *g, int id) {
-	OscarData *od = g ? (OscarData *)g->proto_data : NULL;
-	GSList *bcs = g->buddy_chats;
-	GaimConversation *b = NULL;
-	struct chat_connection *c = NULL;
-	int count = 0;
-
-	while (bcs) {
-		count++;
-		b = (GaimConversation *)bcs->data;
-		if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
-			break;
-		bcs = bcs->next;
-		b = NULL;
-	}
-
-	if (!b)
-		return;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Attempting to leave room %s (currently in %d rooms)\n", b->name, count);
-	
-	c = find_oscar_chat(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
-	if (c != NULL) {
-		if (od)
-			od->oscar_chats = g_slist_remove(od->oscar_chats, c);
-		if (c->inpa > 0)
-			gaim_input_remove(c->inpa);
-		if (g && od->sess)
-			aim_conn_kill(od->sess, &c->conn);
-		g_free(c->name);
-		g_free(c->show);
-		g_free(c);
-	}
-	/* we do this because with Oscar it doesn't tell us we left */
-	serv_got_chat_left(g, gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)));
-}
-
-static int oscar_chat_send(GaimConnection *g, int id, const char *message) {
-	OscarData *od = (OscarData *)g->proto_data;
-	GSList *bcs = g->buddy_chats;
-	GaimConversation *b = NULL;
-	struct chat_connection *c = NULL;
-	char *buf, *buf2;
-	int i, j;
-
-	while (bcs) {
-		b = (GaimConversation *)bcs->data;
-		if (id == gaim_conv_chat_get_id(GAIM_CONV_CHAT(b)))
-			break;
-		bcs = bcs->next;
-		b = NULL;
-	}
-	if (!b)
-		return -EINVAL;
-
-	bcs = od->oscar_chats;
-	while (bcs) {
-		c = (struct chat_connection *)bcs->data;
-		if (b == c->cnv)
-			break;
-		bcs = bcs->next;
-		c = NULL;
-	}
-	if (!c)
-		return -EINVAL;
-
-	buf = g_malloc(strlen(message) * 4 + 1);
-	for (i = 0, j = 0; i < strlen(message); i++) {
-		if (message[i] == '\n') {
-			buf[j++] = '<';
-			buf[j++] = 'B';
-			buf[j++] = 'R';
-			buf[j++] = '>';
-		} else {
-			buf[j++] = message[i];
-		}
-	}
-	buf[j] = '\0';
-
-	if (strlen(buf) > c->maxlen)
-		return -E2BIG;
-
-	buf2 = gaim_markup_strip_html(buf);
-	if (strlen(buf2) > c->maxvis) {
-		g_free(buf2);
-		return -E2BIG;
-	}
-	g_free(buf2);
-
-	aim_chat_send_im(od->sess, c->conn, 0, buf, strlen(buf));
-	g_free(buf);
-	return 0;
-}
-
-static const char *oscar_list_icon(GaimAccount *a, GaimBuddy *b) {
-	if (!b || (b && b->name && b->name[0] == '+')) {
-		if (a != NULL && isdigit(*gaim_account_get_username(a)))
-			return "icq";
-		else
-			return "aim";
-	}
-
-	if (b != NULL && isdigit(b->name[0]))
-		return "icq";
-	return "aim";
-}
-
-static void oscar_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
-{
-	GaimAccount *account = NULL;
-	GaimConnection *gc = NULL;
-	OscarData *od = NULL;
-	char *emblems[4] = {NULL,NULL,NULL,NULL};
-	int i = 0;
-	aim_userinfo_t *userinfo = NULL;
-
-	if (b != NULL)
-		account = b->account;
-	if (account != NULL)
-		gc = account->gc;
-	if (gc != NULL)
-		od = gc->proto_data;
-
-	if (!GAIM_BUDDY_IS_ONLINE(b)) {
-		char *gname;
-		if ((b->name) && (od) && (od->sess->ssi.received_data) && 
-			(gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name)) && 
-			(aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name))) {
-			emblems[i++] = "notauthorized";
-		} else {
-			emblems[i++] = "offline";
-		}
-	}
-
-	if (b->name && (b->uc & 0xffff0000) && isdigit(b->name[0])) {
-		int uc = b->uc >> 16;
-		if (uc & AIM_ICQ_STATE_INVISIBLE)
-			emblems[i++] = "invisible";
-		else if (uc & AIM_ICQ_STATE_CHAT)
-			emblems[i++] = "freeforchat";
-		else if (uc & AIM_ICQ_STATE_DND)
-			emblems[i++] = "dnd";
-		else if (uc & AIM_ICQ_STATE_OUT)
-			emblems[i++] = "na";
-		else if (uc & AIM_ICQ_STATE_BUSY)
-			emblems[i++] = "occupied";
-		else if (uc & AIM_ICQ_STATE_AWAY)
-			emblems[i++] = "away";
-	} else {
-		if (b->uc & UC_UNAVAILABLE) 
-			emblems[i++] = "away";
-	}
-	if (b->uc & UC_WIRELESS)
-		emblems[i++] = "wireless";
-	if (b->uc & UC_AOL)
-		emblems[i++] = "aol";
-	if (b->uc & UC_ADMIN)
-		emblems[i++] = "admin";
-	if (b->uc & UC_AB && i < 4)
-		emblems[i++] = "activebuddy";
-	if (b->uc & UC_HIPTOP && i < 4)
-		emblems[i++] = "hiptop";
-/*	if (b->uc & UC_UNCONFIRMED && i < 4)
-		emblems[i++] = "unconfirmed"; */
-
-	if ((i < 4) && (od != NULL)) {
-		userinfo = aim_locate_finduserinfo(od->sess, b->name);
-		if ((userinfo != NULL) && (userinfo->capabilities & AIM_CAPS_SECUREIM))
-			emblems[i++] = "secure";
-	}
-
-	*se = emblems[0];
-	*sw = emblems[1];
-	*nw = emblems[2];
-	*ne = emblems[3];
-}
-
-static char *oscar_tooltip_text(GaimBuddy *b) {
-	GaimConnection *gc = b->account->gc;
-	OscarData *od = gc->proto_data;
-	struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
-	aim_userinfo_t *userinfo = aim_locate_finduserinfo(od->sess, b->name);
-	gchar *tmp = NULL, *ret = g_strdup("");
-
-	if (GAIM_BUDDY_IS_ONLINE(b)) {
-		if (isdigit(b->name[0])) {
-			char *status;
-			status = gaim_icq_status((b->uc & 0xffff0000) >> 16);
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Status:</b> "), status, "\n", NULL);
-			g_free(tmp);
-			g_free(status);
-		}
-
-		if (userinfo != NULL) {
-			char *tstr = gaim_str_seconds_to_string(time(NULL) - userinfo->onlinesince +
-				(gc->login_time_official ? gc->login_time_official - gc->login_time : 0));
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Logged In:</b> "), tstr, "\n", NULL);
-			g_free(tmp);
-			g_free(tstr);
-		}
-
-		if ((bi != NULL) && (bi->ipaddr)) {
-			char *tstr =  g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
-							(bi->ipaddr & 0xff000000) >> 24,
-							(bi->ipaddr & 0x00ff0000) >> 16,
-							(bi->ipaddr & 0x0000ff00) >> 8,
-							(bi->ipaddr & 0x000000ff));
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>IP Address:</b> "), tstr, "\n", NULL);
-			g_free(tmp);
-			g_free(tstr);
-		}
-
-		if ((userinfo != NULL) && (userinfo->capabilities)) {
-			char *caps = caps_string(userinfo->capabilities);
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Capabilities:</b> "), caps, "\n", NULL);
-			g_free(tmp);
-		}
-
-		if ((bi != NULL) && (bi->availmsg != NULL) && !(b->uc & UC_UNAVAILABLE)) {
-			gchar *escaped = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Available:</b> "), escaped, "\n", NULL);
-			g_free(tmp);
-			g_free(escaped);
-		}
-
-		if ((userinfo != NULL) && (userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
-			gchar *away_utf8 = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
-			if (away_utf8 != NULL) {
-				gchar *tmp1, *tmp2;
-				const char *tmp3;
-				tmp1 = gaim_strreplace(away_utf8, "<BR>", "\n");
-				tmp2 = gaim_markup_strip_html(tmp1);
-				g_free(tmp1);
-				tmp1 = g_markup_escape_text(tmp2, strlen(tmp2));
-				g_free(tmp2);
-				tmp3 = gaim_str_sub_away_formatters(tmp1, gaim_account_get_username(gaim_connection_get_account(gc)));
-				g_free(tmp1);
-				tmp = ret;
-				ret = g_strconcat(tmp, _("<b>Away Message:</b> "), tmp3, "\n", NULL);
-				g_free(tmp);
-				g_free(away_utf8);
-			}
-		}
-	} else {
-		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name);
-		if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name)) {
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Status:</b> Not Authorized"), "\n", NULL);
-			g_free(tmp);
-		} else {
-			tmp = ret;
-			ret = g_strconcat(tmp, _("<b>Status:</b> Offline"), "\n", NULL);
-			g_free(tmp);
-		}
-	}
-
-	/* remove the trailing newline character */
-	if (ret)
-		ret[strlen(ret)-1] = '\0';
-	return ret;
-}
-
-static char *oscar_status_text(GaimBuddy *b) {
-	GaimConnection *gc = b->account->gc;
-	OscarData *od = gc->proto_data;
-	gchar *ret = NULL;
-
-	if ((b->uc & UC_UNAVAILABLE) || (((b->uc & 0xffff0000) >> 16) & AIM_ICQ_STATE_CHAT)) {
-		if (isdigit(b->name[0]))
-			ret = gaim_icq_status((b->uc & 0xffff0000) >> 16);
-		else
-			ret = g_strdup(_("Away"));
-	} else if (GAIM_BUDDY_IS_ONLINE(b)) {
-		struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(b->account, b->name));
-		if (bi->availmsg)
-			ret = g_markup_escape_text(bi->availmsg, strlen(bi->availmsg));
-	} else {
-		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name);
-		if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name))
-			ret = g_strdup(_("Not Authorized"));
-		else
-			ret = g_strdup(_("Offline"));
-	}
-
-	return ret;
-}
-
-
-static int oscar_icon_req(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = gc->proto_data;
-	va_list ap;
-	fu16_t type;
-	fu8_t flags = 0, length = 0;
-	char *md5 = NULL;
-
-
-	va_start(ap, fr);
-	type = va_arg(ap, int);
-
-	switch(type) {
-		case 0x0000:
-		case 0x0001: {
-			flags = va_arg(ap, int);
-			length = va_arg(ap, int);
-			md5 = va_arg(ap, char *);
-
-			if (flags == 0x41) {
-				if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_ICON) && !od->iconconnecting) {
-					od->iconconnecting = TRUE;
-					od->set_icon = TRUE;
-					aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_ICON);
-				} else {
-					struct stat st;
-					const char *iconfile = gaim_account_get_buddy_icon(gaim_connection_get_account(gc));
-					if (iconfile == NULL) {
-						/* Set an empty icon, or something */
-					} else if (!stat(iconfile, &st)) {
-						char *buf = g_malloc(st.st_size);
-						FILE *file = fopen(iconfile, "rb");
-						if (file) {
-							fread(buf, 1, st.st_size, file);
-							fclose(file);
-							gaim_debug(GAIM_DEBUG_INFO, "oscar",
-								   "Uploading icon to icon server\n");
-							aim_bart_upload(od->sess, buf, st.st_size);
-						} else
-							gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-								   "Can't open buddy icon file!\n");
-						g_free(buf);
-					} else {
-						gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-							   "Can't stat buddy icon file!\n");
-					}
-				}
-			} else if (flags == 0x81)
-				aim_ssi_seticon(od->sess, md5, length); 
-		} break;
-
-		case 0x0002: { /* We just set an "available" message? */
-		} break;
-	}
-
-	va_end(ap);
-
-	return 0;
-}
-
-/*
- * We have just established a socket with the other dude, so set up some handlers.
- */
-static int gaim_odc_initiate(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	GaimConversation *cnv;
-	struct direct_im *dim;
-	char buf[256];
-	char *sn;
-	va_list ap;
-	aim_conn_t *newconn, *listenerconn;
-
-	va_start(ap, fr);
-	newconn = va_arg(ap, aim_conn_t *);
-	listenerconn = va_arg(ap, aim_conn_t *);
-	va_end(ap);
-
-	aim_conn_close(listenerconn);
-	aim_conn_kill(sess, &listenerconn);
-
-	sn = g_strdup(aim_odc_getsn(newconn));
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "DirectIM: initiate success to %s\n", sn);
-	dim = find_direct_im(od, sn);
-
-	cnv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, sn);
-	gaim_input_remove(dim->watcher);
-	dim->conn = newconn;
-	dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn);
-	dim->connected = TRUE;
-	g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn);
-	g_free(sn);
-	gaim_conversation_write(cnv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));
-
-	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_odc_incoming, 0);
-	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_odc_typing, 0);
-	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, gaim_odc_update_ui, 0);
-
-	return 1;
-}
-
-/*
- * This is called when each chunk of an image is received.  It can be used to 
- * update a progress bar, or to eat lots of dry cat food.  Wet cat food is 
- * nasty, you sicko.
- */
-static int gaim_odc_update_ui(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	char *sn;
-	double percent;
-	GaimConnection *gc = sess->aux_data;
-	OscarData *od = (OscarData *)gc->proto_data;
-	GaimConversation *c;
-	struct direct_im *dim;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	percent = va_arg(ap, double);
-	va_end(ap);
-
-	if (!(dim = find_direct_im(od, sn)))
-		return 1;
-	if (dim->watcher) {
-		gaim_input_remove(dim->watcher);   /* Otherwise, the callback will callback */
-		dim->watcher = 0;
-	}
-	/* XXX is this really necessary? */
-	gaim_core_mainloop_finish_events();
-
-	c = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc));
-	if (c != NULL)
-		gaim_conversation_update_progress(c, percent);
-	dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
-				      oscar_callback, dim->conn);
-
-	return 1;
-}
-
-/*
- * This is called after a direct IM has been received in its entirety.  This 
- * function is passed a long chunk of data which contains the IM with any 
- * data chunks (images) appended to it.
- *
- * This function rips out all the data chunks and creates an imgstore for 
- * each one.  In order to do this, it first goes through the IM and takes 
- * out all the IMG tags.  When doing so, it rewrites the original IMG tag 
- * with one compatable with the imgstore Gaim core code. For each one, we 
- * then read in chunks of data from the end of the message and actually 
- * create the img store using the given data.
- *
- * For somewhat easy reference, here's a sample message
- * (without the whitespace and asterisks):
- *
- * <HTML><BODY BGCOLOR="#ffffff">
- *     <FONT LANG="0">
- *     This is a really stupid picture:<BR>
- *     <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR>
- *     Yeah it is<BR>
- *     Here is another one:<BR>
- *     <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978">   
- *     </FONT>
- * </BODY></HTML>
- * <BINARY>
- *     <DATA ID="1" SIZE="9894">datadatadatadata</DATA>
- *     <DATA ID="2" SIZE="65978">datadatadatadata</DATA>
- * </BINARY>
- */
-static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) {
-	GaimConnection *gc = sess->aux_data;
-	GaimConvImFlags imflags = 0;
-	GString *newmsg = g_string_new("");
-	GSList *images = NULL;
-	va_list ap;
-	const char *sn, *msg, *msgend, *binary;
-	size_t len;
-	int encoding, isawaymsg;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, const char *);
-	msg = va_arg(ap, const char *);
-	len = va_arg(ap, size_t);
-	encoding = va_arg(ap, int);
-	isawaymsg = va_arg(ap, int);
-	va_end(ap);
-	msgend = msg + len;
-
-	gaim_debug(GAIM_DEBUG_INFO, "oscar",
-			   "Got DirectIM message from %s\n", sn);
-
-	if (isawaymsg)
-		imflags |= GAIM_CONV_IM_AUTO_RESP;
-
-	/* message has a binary trailer */
-	if ((binary = gaim_strcasestr(msg, "<binary>"))) {
-		GData *attribs;
-		const char *tmp, *start, *end, *last = NULL;
-
-		tmp = msg;
-
-		/* for each valid image tag... */
-		while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) {
-			const char *id, *src, *datasize;
-			const char *tag = NULL, *data = NULL;
-			size_t size;
-			int imgid = 0;
-
-			/* update the location of the last img tag */
-			last = end;
-
-			/* grab attributes */
-			id       = g_datalist_get_data(&attribs, "id");
-			src      = g_datalist_get_data(&attribs, "src");
-			datasize = g_datalist_get_data(&attribs, "datasize");
-
-			/* if we have id & datasize, build the data tag */
-			if (id && datasize)
-				tag = g_strdup_printf("<data id=\"%s\" size=\"%s\">", id, datasize);
-
-			/* if we have a tag, find the start of the data */
-			if (tag && (data = gaim_strcasestr(binary, tag)))
-				data += strlen(tag);
-
-			/* check the data is here and store it */
-			if (data + (size = atoi(datasize)) <= msgend)
-				imgid = gaim_imgstore_add(data, size, src);
-
-			/* if we have a stored image... */
-			if (imgid) {
-				/* append the message up to the tag */
-				newmsg = g_string_append_len(newmsg, tmp, start - tmp);
-
-				/* write the new image tag */
-				g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid);
-
-				/* and record the image number */
-				images = g_slist_append(images, GINT_TO_POINTER(imgid));
-			} else {
-				/* otherwise, copy up to the end of the tag */
-				newmsg = g_string_append_len(newmsg, tmp, (end + 1) - tmp);
-			}
-
-			/* clear the attribute list */
-			g_datalist_clear(&attribs);
-
-			/* continue from the end of the tag */
-			tmp = end + 1;
-		}
-
-		/* append any remaining message data (without the > :-) */
-		if (last++ && (last < binary))
-			newmsg = g_string_append_len(newmsg, last, binary - last);
-
-		/* set the flag if we caught any images */
-		if (images)
-			imflags |= GAIM_CONV_IM_IMAGES;
-	} else {
-		g_string_append_len(newmsg, msg, len);
-	}
-
-	/* XXX - I imagine Paco-Paco will want to do some voodoo with the encoding here */
-	serv_got_im(gc, sn, newmsg->str, imflags, time(NULL));
-
-	/* free up the message */
-	g_string_free(newmsg, TRUE);
-
-	/* unref any images we allocated */
-	if (images) {
-		GSList *tmp;
-		int id;
-
-		for (tmp = images; tmp != NULL; tmp = tmp->next) {
-			id = GPOINTER_TO_INT(tmp->data);
-			gaim_imgstore_unref(id);
-		}
-
-		g_slist_free(images);
-	}
-
-	return 1;
-}
-
-static int gaim_odc_typing(aim_session_t *sess, aim_frame_t *fr, ...) {
-	va_list ap;
-	char *sn;
-	int typing;
-	GaimConnection *gc = sess->aux_data;
-
-	va_start(ap, fr);
-	sn = va_arg(ap, char *);
-	typing = va_arg(ap, int);
-	va_end(ap);
-
-	if (typing == 0x0002) {
-		/* I had to leave this. It's just too funny. It reminds me of my sister. */
-		gaim_debug(GAIM_DEBUG_INFO, "oscar",
-				   "ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
-		serv_got_typing(gc, sn, 0, GAIM_TYPING);
-	} else if (typing == 0x0001)
-		serv_got_typing(gc, sn, 0, GAIM_TYPED);
-	else
-		serv_got_typing_stopped(gc, sn);
-	return 1;
-}
-
-static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimConvImFlags imflags) {
-	char *buf;
-	size_t len;
-	int ret;
-
-	if (imflags & GAIM_CONV_IM_IMAGES) {
-		GString *msg = g_string_new("");
-		GString *data = g_string_new("<BINARY>");
-		GData *attribs;
-		const char *tmp, *start, *end, *last = NULL;
-		int oscar_id = 0;
-
-		tmp = message;
-
-		/* for each valid IMG tag... */
-		while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) {
-			GaimStoredImage *image = NULL;
-			const char *id;
-
-			last = end;
-			id = g_datalist_get_data(&attribs, "id");
-
-			/* ... if it refers to a valid gaim image ... */
-			if (id && (image = gaim_imgstore_get(atoi(id)))) {
-				/* ... append the message from start to the tag ... */
-				msg = g_string_append_len(msg, tmp, start - tmp);
-				oscar_id++;
-
-				/* ... insert a new img tag with the oscar id ... */
-				if (image->filename)
-					g_string_append_printf(msg,
-						"<IMG SRC=\"file://%s\" ID=\"%d\" DATASIZE=\"%d\">",
-						image->filename, oscar_id, (int)image->size);
-				else
-					g_string_append_printf(msg,
-						"<IMG ID=\"%d\" DATASIZE=\"%d\">",
-						oscar_id, (int)image->size);
-
-				/* ... and append the data to the binary section ... */
-				g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%d\">",
-					oscar_id, (int)image->size);
-				data = g_string_append_len(data, image->data, image->size);
-				data = g_string_append(data, "</DATA>");
-			} else {
-				/* ... otherwise, allow the possibly invalid img tag through. */
-				/* should we do something else? */
-				msg = g_string_append_len(msg, tmp, (end + 1) - tmp);
-			}
-
-			g_datalist_clear(&attribs);
-
-			/* continue from the end of the tag */
-			tmp = end + 1;
-		}
-
-		/* append any remaining message data (without the > :-) */
-		if (last++ && *last)
-			msg = g_string_append(msg, last);
-
-		/* if we inserted any images in the binary section, append it */
-		if (oscar_id) {
-			msg = g_string_append_len(msg, data->str, data->len);
-			msg = g_string_append(msg, "</BINARY>");
-		}
-
-		len = msg->len;
-		buf = msg->str;
-		g_string_free(msg, FALSE);
-		g_string_free(data, TRUE);
-	} else {
-		len = strlen(message);
-		buf = g_memdup(message, len+1);
-	}
-
-	/* XXX - The last parameter below is the encoding.  Let Paco-Paco do something with it. */
-	if (imflags & GAIM_CONV_IM_AUTO_RESP)
-		ret =  aim_odc_send_im(sess, conn, buf, len, 0, 1);
-	else
-		ret =  aim_odc_send_im(sess, conn, buf, len, 0, 0);
-
-	g_free(buf);
-
-	return ret;
-}
-
-struct ask_do_dir_im {
-	char *who;
-	GaimConnection *gc;
-};
-
-static void oscar_cancel_direct_im(struct ask_do_dir_im *data) {
-	g_free(data->who);
-	g_free(data);
-}
-
-static void oscar_direct_im(struct ask_do_dir_im *data) {
-	GaimConnection *gc = data->gc;
-	OscarData *od;
-	struct direct_im *dim;
-
-	if (!g_list_find(gaim_connections_get_all(), gc)) {
-		g_free(data->who);
-		g_free(data);
-		return;
-	}
-
-	od = (OscarData *)gc->proto_data;
-
-	dim = find_direct_im(od, data->who);
-	if (dim) {
-		if (!(dim->connected)) {  /* We'll free the old, unconnected dim, and start over */
-			od->direct_ims = g_slist_remove(od->direct_ims, dim);
-			gaim_input_remove(dim->watcher);
-			g_free(dim);
-			gaim_debug(GAIM_DEBUG_INFO, "oscar",
-					   "Gave up on old direct IM, trying again\n");
-		} else {
-			gaim_notify_error(gc, NULL, "DirectIM already open.", NULL);
-			g_free(data->who);
-			g_free(data);
-			return;
-		}
-	}
-	dim = g_new0(struct direct_im, 1);
-	dim->gc = gc;
-	g_snprintf(dim->name, sizeof dim->name, "%s", data->who);
-
-	dim->conn = aim_odc_initiate(od->sess, data->who);
-	if (dim->conn != NULL) {
-		od->direct_ims = g_slist_append(od->direct_ims, dim);
-		dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
-						oscar_callback, dim->conn);
-		aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED,
-					gaim_odc_initiate, 0);
-	} else {
-		gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL);
-		g_free(dim);
-	}
-
-	g_free(data->who);
-	g_free(data);
-}
-
-static void oscar_ask_direct_im(GaimConnection *gc, const char *who) {
-	gchar *buf;
-	struct ask_do_dir_im *data = g_new0(struct ask_do_dir_im, 1);
-	data->who = g_strdup(who);
-	data->gc = gc;
-	buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."), who);
-
-	gaim_request_action(gc, NULL, buf,
-						_("Because this reveals your IP address, it "
-						  "may be considered a privacy risk.  Do you "
-						  "wish to continue?"),
-						0, data, 2,
-						_("Connect"), G_CALLBACK(oscar_direct_im),
-						_("Cancel"), G_CALLBACK(oscar_cancel_direct_im));
-	g_free(buf);
-}
-
-static void oscar_set_permit_deny(GaimConnection *gc) {
-	GaimAccount *account = gaim_connection_get_account(gc);
-	OscarData *od = (OscarData *)gc->proto_data;
-#ifdef NOSSI
-	GSList *list, *g = gaim_blist_groups(), *g1;
-	char buf[MAXMSGLEN];
-	int at;
-
-	switch(account->perm_deny) {
-	case 1: 
-		aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, gaim_account_get_username(account));
-		break;
-	case 2:
-		aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, gaim_account_get_username(account));
-		break;
-	case 3:
-		list = account->permit;
-		at = 0;
-		while (list) {
-			at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data);
-			list = list->next;
-		}
-		aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf);
-		break;
-	case 4:
-		list = account->deny;
-		at = 0;
-		while (list) {
-			at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data);
-			list = list->next;
-		}
-		aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, buf);
-		break;
-	case 5:
-		g1 = g;
-		at = 0;
-		while (g1) {
-			list = gaim_blist_members((struct group *)g->data);
-			GSList list1 = list;
-			while (list1) {
-				struct buddy *b = list1->data;
-				if(b->account == account)
-					at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", b->name);
-				list1 = list1->next;
-			}
-			g_slist_free(list);
-			g1 = g1->next;
-		}
-		g_slist_free(g);
-		aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf);
-		break;
-	default:
-		break;
-	}
-	signoff_blocked(gc);
-#else
-	if (od->sess->ssi.received_data)
-		aim_ssi_setpermdeny(od->sess, account->perm_deny, 0xffffffff);
-#endif
-}
-
-static void oscar_add_permit(GaimConnection *gc, const char *who) {
-#ifdef NOSSI
-	if (gc->account->permdeny == 3)
-		oscar_set_permit_deny(gc);
-#else
-	OscarData *od = (OscarData *)gc->proto_data;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a permit\n");
-	if (od->sess->ssi.received_data)
-		aim_ssi_addpermit(od->sess, who);
-#endif
-}
-
-static void oscar_add_deny(GaimConnection *gc, const char *who) {
-#ifdef NOSSI
-	if (gc->account->permdeny == 4)
-		oscar_set_permit_deny(gc);
-#else
-	OscarData *od = (OscarData *)gc->proto_data;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to add a deny\n");
-	if (od->sess->ssi.received_data)
-		aim_ssi_adddeny(od->sess, who);
-#endif
-}
-
-static void oscar_rem_permit(GaimConnection *gc, const char *who) {
-#ifdef NOSSI
-	if (gc->account->permdeny == 3)
-		oscar_set_permit_deny(gc);
-#else
-	OscarData *od = (OscarData *)gc->proto_data;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a permit\n");
-	if (od->sess->ssi.received_data)
-		aim_ssi_delpermit(od->sess, who);
-#endif
-}
-
-static void oscar_rem_deny(GaimConnection *gc, const char *who) {
-#ifdef NOSSI
-	if (gc->account->permdeny == 4)
-		oscar_set_permit_deny(gc);
-#else
-	OscarData *od = (OscarData *)gc->proto_data;
-	gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: About to delete a deny\n");
-	if (od->sess->ssi.received_data)
-		aim_ssi_deldeny(od->sess, who);
-#endif
-}
-
-static GList *oscar_away_states(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	GList *m = NULL;
-
-	if (!od->icq)
-		return g_list_append(m, GAIM_AWAY_CUSTOM);
-
-	m = g_list_append(m, _("Online"));
-	m = g_list_append(m, _("Away"));
-	m = g_list_append(m, _("Do Not Disturb"));
-	m = g_list_append(m, _("Not Available"));
-	m = g_list_append(m, _("Occupied"));
-	m = g_list_append(m, _("Free For Chat"));
-	m = g_list_append(m, _("Invisible"));
-
-	return m;
-}
-
-static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
-	OscarData *od = data->gc->proto_data;
-	GaimBuddy *b;
-	GaimGroup *g;
-
-	if (!(b = gaim_find_buddy(gaim_connection_get_account(data->gc), data->name))) {
-		oscar_free_name_data(data);
-		return;
-	}
-
-	if (!(g = gaim_find_buddys_group(b))) {
-		oscar_free_name_data(data);
-		return;
-	}
-
-	aim_ssi_editcomment(od->sess, g->name, data->name, text);
-	oscar_free_name_data(data);
-}
-
-static void oscar_buddycb_edit_comment(GaimConnection *gc, const char *name) {
-	OscarData *od = gc->proto_data;
-	struct name_data *data = g_new(struct name_data, 1);
-	GaimBuddy *b;
-	GaimGroup *g;
-	char *comment;
-	gchar *comment_utf8;
-
-	if (!(b = gaim_find_buddy(gaim_connection_get_account(gc), name)))
-		return;
-	if (!(g = gaim_find_buddys_group(b)))
-		return;
-	comment = aim_ssi_getcomment(od->sess->ssi.local, g->name, name);
-	comment_utf8 = comment ? gaim_utf8_try_convert(comment) : NULL;
-
-	data->gc = gc;
-	data->name = g_strdup(name);
-	data->nick = NULL;
-
-	gaim_request_input(gc, NULL, _("Buddy Comment:"), NULL,
-					   comment_utf8, TRUE, FALSE,
-					   _("OK"), G_CALLBACK(oscar_ssi_editcomment),
-					   _("Cancel"), G_CALLBACK(oscar_free_name_data),
-					   data);
-
-	free(comment);
-	g_free(comment_utf8);
-}
-
-static GList *oscar_buddy_menu(GaimConnection *gc, const char *who) {
-	OscarData *od = gc->proto_data;
-	GList *m = NULL;
-	struct proto_buddy_menu *pbm;
-
-	pbm = g_new0(struct proto_buddy_menu, 1);
-	pbm->label = _("Edit Buddy Comment");
-	pbm->callback = oscar_buddycb_edit_comment;
-	pbm->gc = gc;
-	m = g_list_append(m, pbm);
-
-	if (od->icq) {
-#if 0
-		pbm = g_new0(struct proto_buddy_menu, 1);
-		pbm->label = _("Get Status Msg");
-		pbm->callback = oscar_get_icqstatusmsg;
-		pbm->gc = gc;
-		m = g_list_append(m, pbm);
-#endif
-	} else {
-		GaimBuddy *b = gaim_find_buddy(gc->account, who);
-		aim_userinfo_t *userinfo;
-
-		if (b)
-			userinfo = aim_locate_finduserinfo(od->sess, b->name);
-
-		if (b && userinfo && aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), who) && GAIM_BUDDY_IS_ONLINE(b)) {
-			if (userinfo->capabilities & AIM_CAPS_DIRECTIM) {
-				pbm = g_new0(struct proto_buddy_menu, 1);
-				pbm->label = _("Direct IM");
-				pbm->callback = oscar_ask_direct_im;
-				pbm->gc = gc;
-				m = g_list_append(m, pbm);
-			}
-
-			if (userinfo->capabilities & AIM_CAPS_SENDFILE) {
-				pbm = g_new0(struct proto_buddy_menu, 1);
-				pbm->label = _("Send File");
-				pbm->callback = oscar_ask_sendfile;
-				pbm->gc = gc;
-				m = g_list_append(m, pbm);
-			}
-#if 0
-			if (userinfo->capabilities & AIM_CAPS_GETFILE) {
-				pbm = g_new0(struct proto_buddy_menu, 1);
-				pbm->label = _("Get File");
-				pbm->callback = oscar_ask_getfile;
-				pbm->gc = gc;
-				m = g_list_append(m, pbm);
-			}
-#endif
-		}
-	}
-
-	if (od->sess->ssi.received_data) {
-		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, who);
-		if (gname && aim_ssi_waitingforauth(od->sess->ssi.local, gname, who)) {
-			pbm = g_new0(struct proto_buddy_menu, 1);
-			pbm->label = _("Re-request Authorization");
-			pbm->callback = gaim_auth_sendrequest;
-			pbm->gc = gc;
-			m = g_list_append(m, pbm);
-		}
-	}
-	
-	return m;
-}
-
-static void oscar_format_screenname(GaimConnection *gc, const char *nick) {
-	OscarData *od = gc->proto_data;
-	if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), nick)) {
-		if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
-			od->setnick = TRUE;
-			od->newsn = g_strdup(nick);
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-		} else {
-			aim_admin_setnick(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), nick);
-		}
-	} else {
-		gaim_notify_error(gc, NULL, _("The new formatting is invalid."),
-						  _("Screenname formatting can change only capitalization and whitespace."));
-	}
-}
-
-static void oscar_show_format_screenname(GaimConnection *gc)
-{
-	gaim_request_input(gc, NULL, _("New screenname formatting:"), NULL,
-					   gaim_connection_get_display_name(gc), FALSE, FALSE,
-					   _("OK"), G_CALLBACK(oscar_format_screenname),
-					   _("Cancel"), NULL,
-					   gc);
-}
-
-static void oscar_confirm_account(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
-
-	if (conn) {
-		aim_admin_reqconfirm(od->sess, conn);
-	} else {
-		od->conf = TRUE;
-		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-	}
-}
-
-static void oscar_show_email(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
-
-	if (conn) {
-		aim_admin_getinfo(od->sess, conn, 0x11);
-	} else {
-		od->reqemail = TRUE;
-		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-	}
-}
-
-static void oscar_change_email(GaimConnection *gc, const char *email)
-{
-	OscarData *od = gc->proto_data;
-	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
-
-	if (conn) {
-		aim_admin_setemail(od->sess, conn, email);
-	} else {
-		od->setemail = TRUE;
-		od->email = g_strdup(email);
-		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-	}
-}
-
-static void oscar_show_change_email(GaimConnection *gc)
-{
-	gaim_request_input(gc, NULL, _("Change Address To:"), NULL, NULL,
-					   FALSE, FALSE,
-					   _("OK"), G_CALLBACK(oscar_change_email),
-					   _("Cancel"), NULL,
-					   gc);
-}
-
-static void oscar_show_awaitingauth(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	gchar *nombre, *text, *tmp;
-	GaimBlistNode *gnode, *cnode, *bnode;
-	int num=0;
-
-	text = g_strdup("");
-
-	for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
-		GaimGroup *group = (GaimGroup *)gnode;
-		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
-			continue;
-		for (cnode = gnode->child; cnode; cnode = cnode->next) {
-			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
-				continue;
-			for (bnode = cnode->child; bnode; bnode = bnode->next) {
-				GaimBuddy *buddy = (GaimBuddy *)bnode;
-				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-					continue;
-				if (buddy->account == gc->account && aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) {
-					if (gaim_get_buddy_alias_only(buddy))
-						nombre = g_strdup_printf(" %s (%s)", buddy->name, gaim_get_buddy_alias_only(buddy));
-					else
-						nombre = g_strdup_printf(" %s", buddy->name);
-					tmp = g_strdup_printf("%s%s<br>", text, nombre);
-					g_free(text);
-					text = tmp;
-					g_free(nombre);
-					num++;
-				}
-			}
-		}
-	}
-
-	if (!num) {
-		g_free(text);
-		text = g_strdup(_("<i>you are not waiting for authorization</i>"));
-	}
-
-	gaim_notify_formatted(gc, NULL, _("You are awaiting authorization from "
-						  "the following buddies"),	_("You can re-request "
-						  "authorization from these buddies by "
-						  "right-clicking on them and selecting "
-						  "\"Re-request Authorization.\""), text, NULL, NULL);
-	g_free(text);
-}
-
-static void search_by_email_cb(GaimConnection *gc, const char *email)
-{
-	serv_dir_search(gc, "", "", "", "", "", "", "", email);
-}
-
-static void oscar_show_find_email(GaimConnection *gc)
-{
-	gaim_request_input(gc, _("Find Buddy by E-mail"),
-					   _("Search for a buddy by e-mail address"),
-					   _("Type the e-mail address of the buddy you are "
-						 "searching for."),
-					   NULL, FALSE, FALSE,
-					   _("Search"), G_CALLBACK(search_by_email_cb),
-					   _("Cancel"), NULL, gc);
-}
-
-#if 0
-static void oscar_setavailmsg(GaimConnection *gc, char *text) {
-	OscarData *od = (OscarData *)gc->proto_data;
-
-	aim_locate_setprofile(od->sess, NULL, NULL, 0, NULL, "", 0);
-	aim_srv_setavailmsg(od->sess, text);
-}
-
-static void oscar_show_setavailmsg(GaimConnection *gc)
-{
-	gaim_request_input(gc, NULL, _("Available Message:"), NULL,
-					   _("I'm doing work and hoping for a distraction--IM me!"), 
-					   TRUE, FALSE,
-					   _("OK"), G_CALLBACK(oscar_setavailmsg),
-					   _("Cancel"), NULL,
-					   gc);
-}
-#endif
-
-static void oscar_show_set_info(GaimConnection *gc)
-{
-	gaim_account_request_change_user_info(gaim_connection_get_account(gc));
-}
-
-static void oscar_change_pass(GaimConnection *gc)
-{
-	gaim_account_request_change_password(gaim_connection_get_account(gc));
-}
-
-static void oscar_show_chpassurl(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	gchar *substituted = gaim_strreplace(od->sess->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc)));
-	gaim_notify_uri(gc, substituted);
-	g_free(substituted);
-}
-
-static void oscar_show_imforwardingurl(GaimConnection *gc)
-{
-	gaim_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
-}
-
-static void oscar_set_icon(GaimConnection *gc, const char *iconfile)
-{
-	OscarData *od = gc->proto_data;
-	aim_session_t *sess = od->sess;
-	FILE *file;
-	struct stat st;
-
-	if (iconfile == NULL) {
-		/* Set an empty icon, or something */
-	} else if (!stat(iconfile, &st)) {
-		char *buf = g_malloc(st.st_size);
-		file = fopen(iconfile, "rb");
-		if (file) {
-			md5_state_t *state;
-			char md5[16];
-			int len = fread(buf, 1, st.st_size, file);
-			fclose(file);
-			state = g_malloc(sizeof(md5_state_t));
-			md5_init(state);
-			md5_append(state, buf, len);
-			md5_finish(state, md5);
-			g_free(state);
-			aim_ssi_seticon(sess, md5, 16);
-		} else
-			gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-				   "Can't open buddy icon file!\n");
-		g_free(buf);
-	} else
-		gaim_debug(GAIM_DEBUG_ERROR, "oscar",
-			   "Can't stat buddy icon file!\n");
-}
-
-
-static GList *oscar_actions(GaimConnection *gc)
-{
-	OscarData *od = gc->proto_data;
-	struct proto_actions_menu *pam;
-	GList *m = NULL;
-
-	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Set User Info");
-	pam->callback = oscar_show_set_info;
-	pam->gc = gc;
-	m = g_list_append(m, pam);
-
-#if 0
-	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Set Available Message");
-	pam->callback = oscar_show_setavailmsg;
-	pam->gc = gc;
-	m = g_list_append(m, pam);
-#endif
-
-	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Change Password");
-	pam->callback = oscar_change_pass;
-	pam->gc = gc;
-	m = g_list_append(m, pam);
-
-	if (od->sess->authinfo->chpassurl) {
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Change Password (URL)");
-		pam->callback = oscar_show_chpassurl;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-	}
-
-	if (od->sess->authinfo->chpassurl) {
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Configure IM Forwarding (URL)");
-		pam->callback = oscar_show_imforwardingurl;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-	}
-
-	if (!od->icq) {
-		/* AIM actions */
-		m = g_list_append(m, NULL);
-
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Format Screenname");
-		pam->callback = oscar_show_format_screenname;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Confirm Account");
-		pam->callback = oscar_confirm_account;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Display Current Registered Address");
-		pam->callback = oscar_show_email;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-
-		pam = g_new0(struct proto_actions_menu, 1);
-		pam->label = _("Change Current Registered Address");
-		pam->callback = oscar_show_change_email;
-		pam->gc = gc;
-		m = g_list_append(m, pam);
-	}
-
-	m = g_list_append(m, NULL);
-
-	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Show Buddies Awaiting Authorization");
-	pam->callback = oscar_show_awaitingauth;
-	pam->gc = gc;
-	m = g_list_append(m, pam);
-
-	m = g_list_append(m, NULL);
-
-	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Search for Buddy by Email");
-	pam->callback = oscar_show_find_email;
-	pam->gc = gc;
-	m = g_list_append(m, pam);
-
-/*	pam = g_new0(struct proto_actions_menu, 1);
-	pam->label = _("Search for Buddy by Information");
-	pam->callback = show_find_info;
-	pam->gc = gc;
-	m = g_list_append(m, pam); */
-
-	return m;
-}
-
-static void oscar_change_passwd(GaimConnection *gc, const char *old, const char *new)
-{
-	OscarData *od = gc->proto_data;
-
-	if (od->icq) {
-		aim_icq_changepasswd(od->sess, new);
-	} else {
-		aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
-		if (conn) {
-			aim_admin_changepasswd(od->sess, conn, new, old);
-		} else {
-			od->chpass = TRUE;
-			od->oldp = g_strdup(old);
-			od->newp = g_strdup(new);
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-		}
-	}
-}
-
-static void oscar_convo_closed(GaimConnection *gc, const char *who)
-{
-	OscarData *od = gc->proto_data;
-	struct direct_im *dim = find_direct_im(od, who);
-
-	if (!dim)
-		return;
-
-	od->direct_ims = g_slist_remove(od->direct_ims, dim);
-	gaim_input_remove(dim->watcher);
-	aim_conn_kill(od->sess, &dim->conn);
-	g_free(dim);
-}
-
-static GaimPluginProtocolInfo prpl_info =
-{
-	GAIM_PROTO_OSCAR,
-	OPT_PROTO_MAIL_CHECK | OPT_PROTO_BUDDY_ICON | OPT_PROTO_IM_IMAGE,
-	NULL,
-	NULL,
-	oscar_list_icon,
-	oscar_list_emblems,
-	oscar_status_text,
-	oscar_tooltip_text,
-	oscar_away_states,
-	oscar_actions,
-	oscar_buddy_menu,
-	oscar_chat_info,
-	oscar_login,
-	oscar_close,
-	oscar_send_im,
-	oscar_set_info,
-	oscar_send_typing,
-	oscar_get_info,
-	oscar_set_away,
-	oscar_get_away,
-	oscar_set_dir,
-	NULL,
-	oscar_dir_search,
-	oscar_set_idle,
-	oscar_change_passwd,
-	oscar_add_buddy,
-	oscar_add_buddies,
-	oscar_remove_buddy,
-	oscar_remove_buddies,
-	oscar_add_permit,
-	oscar_add_deny,
-	oscar_rem_permit,
-	oscar_rem_deny,
-	oscar_set_permit_deny,
-	oscar_warn,
-	oscar_join_chat,
-	oscar_chat_invite,
-	oscar_chat_leave,
-	NULL,
-	oscar_chat_send,
-	oscar_keepalive,
-	NULL,
-	NULL,
-	NULL,
-#ifndef NOSSI
-	oscar_alias_buddy,
-	oscar_move_buddy,
-	oscar_rename_group,
-#else
-	NULL,
-	NULL,
-	NULL,
-#endif
-	NULL,
-	oscar_convo_closed,
-	NULL,
-	oscar_set_icon
-};
-
-static GaimPluginInfo info =
-{
-	2,                                                /**< api_version    */
-	GAIM_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	GAIM_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-oscar",                                     /**< id             */
-	"AIM/ICQ",                                        /**< name           */
-	VERSION,                                          /**< version        */
-	                                                  /**  summary        */
-	N_("AIM/ICQ Protocol Plugin"),
-	                                                  /**  description    */
-	N_("AIM/ICQ Protocol Plugin"),
-	NULL,                                             /**< author         */
-	GAIM_WEBSITE,                                     /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info                                        /**< extra_info     */
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-	GaimAccountOption *option;
-
-	option = gaim_account_option_string_new(_("Auth host"), "server",
-											"login.oscar.aol.com");
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = gaim_account_option_int_new(_("Auth port"), "port", 5190);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	my_protocol = plugin;
-}
-
-GAIM_INIT_PLUGIN(oscar, init_plugin, info);
Index: bfaim/popups.c
===================================================================
--- libfaim/popups.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Family 0x0008 - Popups.
- *
- * Popups are just what it sounds like.  They're a way for the server to
- * open up an informative box on the client's screen.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/*
- * This is all there is to it.
- *
- * The message is probably HTML.
- * 
- */
-static int parsepopup(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tl;
-	int ret = 0;
-	char *msg, *url;
-	fu16_t width, height, delay;
-
-	tl = aim_tlvlist_read(bs);
-
-	msg = aim_tlv_getstr(tl, 0x0001, 1);
-	url = aim_tlv_getstr(tl, 0x0002, 1);
-	width = aim_tlv_get16(tl, 0x0003, 1);
-	height = aim_tlv_get16(tl, 0x0004, 1);
-	delay = aim_tlv_get16(tl, 0x0005, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, msg, url, width, height, delay);
-
-	aim_tlvlist_free(&tl);
-	free(msg);
-	free(url);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0002)
-		return parsepopup(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0008;
-	mod->version = 0x0001;
-	mod->toolid = 0x0104;
-	mod->toolversion = 0x0001;
-	mod->flags = 0;
-	strncpy(mod->name, "popups", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/rxhandlers.c
===================================================================
--- libfaim/rxhandlers.c	(revision 54666e08c3ce1872c899386b31a80bca27a0874a)
+++ 	(revision )
@@ -1,583 +1,0 @@
-/*
- * rxhandlers.c
- *
- * This file contains most all of the incoming packet handlers, along
- * with aim_rxdispatch(), the Rx dispatcher.  Queue/list management is
- * actually done in aim_rxqueue.c.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-struct aim_rxcblist_s {
-	fu16_t family;
-	fu16_t type;
-	aim_rxcallback_t handler;
-	fu16_t flags;
-	struct aim_rxcblist_s *next;
-};
-
-faim_internal aim_module_t *aim__findmodulebygroup(aim_session_t *sess, fu16_t group)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
-		if (cur->family == group)
-			return cur;
-	}
-
-	return NULL;
-}
-
-faim_internal aim_module_t *aim__findmodule(aim_session_t *sess, const char *name)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
-		if (strcmp(name, cur->name) == 0)
-			return cur;
-	}
-
-	return NULL;
-}
-
-faim_internal int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, aim_module_t *))
-{
-	aim_module_t *mod;
-
-	if (!sess || !modfirst)
-		return -1;
-
-	if (!(mod = malloc(sizeof(aim_module_t))))
-		return -1;
-	memset(mod, 0, sizeof(aim_module_t));
-
-	if (modfirst(sess, mod) == -1) {
-		free(mod);
-		return -1;
-	}
-
-	if (aim__findmodule(sess, mod->name)) {
-		if (mod->shutdown)
-			mod->shutdown(sess, mod);
-		free(mod);
-		return -1;
-	}
-
-	mod->next = (aim_module_t *)sess->modlistv;
-	sess->modlistv = mod;
-
-	faimdprintf(sess, 1, "registered module %s (family 0x%04x, version = 0x%04x, tool 0x%04x, tool version 0x%04x)\n", mod->name, mod->family, mod->version, mod->toolid, mod->toolversion);
-
-	return 0;
-}
-
-faim_internal void aim__shutdownmodules(aim_session_t *sess)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *)sess->modlistv; cur; ) {
-		aim_module_t *tmp;
-
-		tmp = cur->next;
-
-		if (cur->shutdown)
-			cur->shutdown(sess, cur);
-
-		free(cur);
-
-		cur = tmp;
-	}
-
-	sess->modlistv = NULL;
-
-	return;
-}
-
-static int consumesnac(aim_session_t *sess, aim_frame_t *rx)
-{
-	aim_module_t *cur;
-	aim_modsnac_t snac;
-
-	if (aim_bstream_empty(&rx->data) < 10)
-		return 0;
-
-	snac.family = aimbs_get16(&rx->data);
-	snac.subtype = aimbs_get16(&rx->data);
-	snac.flags = aimbs_get16(&rx->data);
-	snac.id = aimbs_get32(&rx->data);
-
-	/* SNAC flags are apparently uniform across all SNACs, so we handle them here */
-	if (snac.flags & 0x0001) {
-		/*
-		 * This means the SNAC will be followed by another SNAC with 
-		 * related information.  We don't need to do anything about 
-		 * this here.
-		 */
-	}
-	if (snac.flags & 0x8000) {
-		/*
-		 * This packet contains the version of the family that this SNAC is 
-		 * in.  You get this when your SSI module is version 2 or higher.  
-		 * For now we have no need for this, but you could always save 
-		 * it as a part of aim_modnsac_t, or something.  The format is...
-		 * 2 byte length of total mini-header (which is 6 bytes), then TLV 
-		 * of  type 0x0001, length 0x0002, value is the 2 byte version 
-		 * number
-		 */
-		aim_bstream_advance(&rx->data, aimbs_get16(&rx->data));
-	}
-
-	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
-
-		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && 
-				(cur->family != snac.family))
-			continue;
-
-		if (cur->snachandler(sess, cur, rx, &snac, &rx->data))
-			return 1;
-
-	}
-
-	return 0;
-}
-
-static int consumenonsnac(aim_session_t *sess, aim_frame_t *rx, fu16_t family, fu16_t subtype)
-{
-	aim_module_t *cur;
-	aim_modsnac_t snac;
-
-	snac.family = family;
-	snac.subtype = subtype;
-	snac.flags = snac.id = 0;
-
-	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
-
-		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && 
-				(cur->family != snac.family))
-			continue;
-
-		if (cur->snachandler(sess, cur, rx, &snac, &rx->data))
-			return 1;
-
-	}
-
-	return 0;
-}
-
-static int negchan_middle(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_tlvlist_t *tlvlist;
-	char *msg = NULL;
-	fu16_t code = 0;
-	aim_rxcallback_t userfunc;
-	int ret = 1;
-
-	if (aim_bstream_empty(&fr->data) == 0) {
-		/* XXX should do something with this */
-		return 1;
-	}
-
-	/* Used only by the older login protocol */
-	/* XXX remove this special case? */
-	if (fr->conn->type == AIM_CONN_TYPE_AUTH)
-		return consumenonsnac(sess, fr, 0x0017, 0x0003);
-
-	tlvlist = aim_tlvlist_read(&fr->data);
-
-	if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
-		code = aim_tlv_get16(tlvlist, 0x0009, 1);
-
-	if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
-		msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
-
-	if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) 
-		ret = userfunc(sess, fr, code, msg);
-
-	aim_tlvlist_free(&tlvlist);
-
-	free(msg);
-
-	return ret;
-}
-
-/*
- * Bleck functions get called when there's no non-bleck functions
- * around to cleanup the mess...
- */
-faim_internal int bleck(aim_session_t *sess, aim_frame_t *frame, ...)
-{
-	fu16_t family, subtype;
-	fu16_t maxf, maxs;
-
-	static const char *channels[6] = {
-		"Invalid (0)",
-		"FLAP Version",
-		"SNAC",
-		"Invalid (3)",
-		"Negotiation",
-		"FLAP NOP"
-	};
-	static const int maxchannels = 5;
-	
-	/* XXX: this is ugly. and big just for debugging. */
-	static const char *literals[14][25] = {
-		{"Invalid", 
-		 NULL
-		},
-		{"General", 
-		 "Invalid",
-		 "Error",
-		 "Client Ready",
-		 "Server Ready",
-		 "Service Request",
-		 "Redirect",
-		 "Rate Information Request",
-		 "Rate Information",
-		 "Rate Information Ack",
-		 NULL,
-		 "Rate Information Change",
-		 "Server Pause",
-		 NULL,
-		 "Server Resume",
-		 "Request Personal User Information",
-		 "Personal User Information",
-		 "Evil Notification",
-		 NULL,
-		 "Migration notice",
-		 "Message of the Day",
-		 "Set Privacy Flags",
-		 "Well Known URL",
-		 "NOP"
-		},
-		{"Location", 
-		 "Invalid",
-		 "Error",
-		 "Request Rights",
-		 "Rights Information", 
-		 "Set user information", 
-		 "Request User Information", 
-		 "User Information", 
-		 "Watcher Sub Request",
-		 "Watcher Notification"
-		},
-		{"Buddy List Management", 
-		 "Invalid", 
-		 "Error", 
-		 "Request Rights",
-		 "Rights Information",
-		 "Add Buddy", 
-		 "Remove Buddy", 
-		 "Watcher List Query", 
-		 "Watcher List Response", 
-		 "Watcher SubRequest", 
-		 "Watcher Notification", 
-		 "Reject Notification", 
-		 "Oncoming Buddy", 
-		 "Offgoing Buddy"
-		},
-		{"Messeging", 
-		 "Invalid",
-		 "Error", 
-		 "Add ICBM Parameter",
-		 "Remove ICBM Parameter", 
-		 "Request Parameter Information",
-		 "Parameter Information",
-		 "Outgoing Message", 
-		 "Incoming Message",
-		 "Evil Request",
-		 "Evil Reply", 
-		 "Missed Calls",
-		 "Message Error", 
-		 "Host Ack"
-		},
-		{"Advertisements", 
-		 "Invalid", 
-		 "Error", 
-		 "Request Ad",
-		 "Ad Data (GIFs)"
-		},
-		{"Invitation / Client-to-Client", 
-		 "Invalid",
-		 "Error",
-		 "Invite a Friend",
-		 "Invitation Ack"
-		},
-		{"Administrative", 
-		 "Invalid",
-		 "Error",
-		 "Information Request",
-		 "Information Reply",
-		 "Information Change Request",
-		 "Information Chat Reply",
-		 "Account Confirm Request",
-		 "Account Confirm Reply",
-		 "Account Delete Request",
-		 "Account Delete Reply"
-		},
-		{"Popups", 
-		 "Invalid",
-		 "Error",
-		 "Display Popup"
-		},
-		{"BOS", 
-		 "Invalid",
-		 "Error",
-		 "Request Rights",
-		 "Rights Response",
-		 "Set group permission mask",
-		 "Add permission list entries",
-		 "Delete permission list entries",
-		 "Add deny list entries",
-		 "Delete deny list entries",
-		 "Server Error"
-		},
-		{"User Lookup", 
-		 "Invalid",
-		 "Error",
-		 "Search Request",
-		 "Search Response"
-		},
-		{"Stats", 
-		 "Invalid",
-		 "Error",
-		 "Set minimum report interval",
-		 "Report Events"
-		},
-		{"Translate", 
-		 "Invalid",
-		 "Error",
-		 "Translate Request",
-		 "Translate Reply",
-		},
-		{"Chat Navigation", 
-		 "Invalid",
-		 "Error",
-		 "Request rights",
-		 "Request Exchange Information",
-		 "Request Room Information",
-		 "Request Occupant List",
-		 "Search for Room",
-		 "Outgoing Message", 
-		 "Incoming Message",
-		 "Evil Request", 
-		 "Evil Reply", 
-		 "Chat Error",
-		}
-	};
-
-	maxf = sizeof(literals) / sizeof(literals[0]);
-	maxs = sizeof(literals[0]) / sizeof(literals[0][0]);
-
-	if (frame->hdr.flap.type == 0x02) {
-
-		family = aimbs_get16(&frame->data);
-		subtype = aimbs_get16(&frame->data);
-		
-		if ((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL))
-			faimdprintf(sess, 0, "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->hdr.flap.type], family, subtype, literals[family][subtype+1]);
-		else
-			faimdprintf(sess, 0, "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->hdr.flap.type], family, subtype);
-	} else {
-
-		if (frame->hdr.flap.type <= maxchannels)
-			faimdprintf(sess, 0, "bleck: channel %s (0x%02x)\n", channels[frame->hdr.flap.type], frame->hdr.flap.type);
-		else
-			faimdprintf(sess, 0, "bleck: unknown channel 0x%02x\n", frame->hdr.flap.type);
-
-	}
-		
-	return 1;
-}
-
-faim_export int aim_conn_addhandler(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type, aim_rxcallback_t newhandler, fu16_t flags)
-{
-	struct aim_rxcblist_s *newcb;
-
-	if (!conn)
-		return -1;
-
-	faimdprintf(sess, 1, "aim_conn_addhandler: adding for %04x/%04x\n", family, type);
-
-	if (!(newcb = (struct aim_rxcblist_s *)calloc(1, sizeof(struct aim_rxcblist_s))))
-		return -1;
-
-	newcb->family = family;
-	newcb->type = type;
-	newcb->flags = flags;
-	newcb->handler = newhandler ? newhandler : bleck;
-	newcb->next = NULL;
-
-	if (!conn->handlerlist)
-		conn->handlerlist = (void *)newcb;
-	else {
-		struct aim_rxcblist_s *cur;
-
-		for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur->next; cur = cur->next)
-			;
-		cur->next = newcb;
-	}
-
-	return 0;
-}
-
-faim_export int aim_clearhandlers(aim_conn_t *conn)
-{
-	struct aim_rxcblist_s *cur;
-
-	if (!conn)
-		return -1;
-
-	for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; ) {
-		struct aim_rxcblist_s *tmp;
-
-		tmp = cur->next;
-		free(cur);
-		cur = tmp;
-	}
-	conn->handlerlist = NULL;
-
-	return 0;
-}
-
-faim_internal aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t type)
-{
-	struct aim_rxcblist_s *cur;
-
-	if (!conn)
-		return NULL;
-
-	faimdprintf(sess, 1, "aim_callhandler: calling for %04x/%04x\n", family, type);
-
-	for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; cur = cur->next) {
-		if ((cur->family == family) && (cur->type == type))
-			return cur->handler;
-	}
-
-	if (type == AIM_CB_SPECIAL_DEFAULT) {
-		faimdprintf(sess, 1, "aim_callhandler: no default handler for family 0x%04x\n", family);
-		return NULL; /* prevent infinite recursion */
-	}
-
-	faimdprintf(sess, 1, "aim_callhandler: no handler for  0x%04x/0x%04x\n", family, type);
-
-	return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT);
-}
-
-faim_internal void aim_clonehandlers(aim_session_t *sess, aim_conn_t *dest, aim_conn_t *src)
-{
-	struct aim_rxcblist_s *cur;
-
-	for (cur = (struct aim_rxcblist_s *)src->handlerlist; cur; cur = cur->next) {
-		aim_conn_addhandler(sess, dest, cur->family, cur->type, 
-						cur->handler, cur->flags);
-	}
-
-	return;
-}
-
-faim_internal int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn,fu16_t family, fu16_t type, aim_frame_t *ptr)
-{
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, conn, family, type)))
-		return userfunc(sess, ptr);
-
-	return 1; /* XXX */
-}
-
-/*
- * aim_rxdispatch()
- *
- * Basically, heres what this should do:
- *   1) Determine correct packet handler for this packet
- *   2) Mark the packet handled (so it can be dequeued in purge_queue())
- *   3) Send the packet to the packet handler
- *   4) Go to next packet in the queue and start over
- *   5) When done, run purge_queue() to purge handled commands
- *
- * TODO: Clean up.
- * TODO: More support for mid-level handlers.
- * TODO: Allow for NULL handlers.
- *
- */
-faim_export void aim_rxdispatch(aim_session_t *sess)
-{
-	int i;
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_incoming, i = 0; cur; cur = cur->next, i++) {
-
-		/*
-		 * XXX: This is still fairly ugly.
-		 */
-
-		if (cur->handled)
-			continue;
-
-		if (cur->hdrtype == AIM_FRAMETYPE_FLAP) {
-			if (cur->hdr.flap.type == 0x01) {
-				cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, cur); /* XXX use consumenonsnac */
-				continue;
-
-			} else if (cur->hdr.flap.type == 0x02) {
-				if ((cur->handled = consumesnac(sess, cur)))
-					continue;
-
-			} else if (cur->hdr.flap.type == 0x04) {
-				cur->handled = negchan_middle(sess, cur);
-				continue;
-
-			} else if (cur->hdr.flap.type == 0x05) {
-
-			}
-
-		} else if (cur->hdrtype == AIM_FRAMETYPE_OFT) {
-			if (cur->conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
-				aim_rxdispatch_rendezvous(sess, cur);
-				cur->handled = 1;
-				continue;
-
-			} else if (cur->conn->type == AIM_CONN_TYPE_LISTENER) {
-				/* not possible */
-				faimdprintf(sess, 0, "rxdispatch called on LISTENER connection!\n");
-				cur->handled = 1;
-				continue;
-			}
-		}
-
-		if (!cur->handled) {
-			consumenonsnac(sess, cur, 0xffff, 0xffff); /* last chance! */
-			cur->handled = 1;
-		}
-	}
-
-	/* 
-	 * This doesn't have to be called here.  It could easily be done
-	 * by a seperate thread or something. It's an administrative operation,
-	 * and can take a while. Though the less you call it the less memory
-	 * you'll have :)
-	 */
-	aim_purge_rxqueue(sess);
-
-	return;
-}
-
-faim_internal int aim_parse_unknown(aim_session_t *sess, aim_frame_t *frame, ...)
-{
-	int i;
-
-	faimdprintf(sess, 1, "\nRecieved unknown packet:");
-
-	for (i = 0; aim_bstream_empty(&frame->data); i++) {
-		if ((i % 8) == 0)
-			faimdprintf(sess, 1, "\n\t");
-
-		faimdprintf(sess, 1, "0x%2x ", aimbs_get8(&frame->data));
-	}
-
-	faimdprintf(sess, 1, "\n\n");
-
-	return 1;
-}
Index: bfaim/rxqueue.c
===================================================================
--- libfaim/rxqueue.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,290 +1,0 @@
-/*
- * rxqueue.c
- *
- * This file contains the management routines for the receive
- * (incoming packet) queue.  The actual packet handlers are in
- * aim_rxhandlers.c.
- */
-
-#define FAIM_INTERNAL
-#include <aim.h> 
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#endif
-
-/*
- *
- */
-faim_internal int aim_recv(int fd, void *buf, size_t count)
-{
-	int left, cur; 
-
-	for (cur = 0, left = count; left; ) {
-		int ret;
-		
-		ret = recv(fd, ((unsigned char *)buf)+cur, left, 0);
-
-		/* Of course EOF is an error, only morons disagree with that. */
-		if (ret <= 0)
-			return -1;
-
-		cur += ret;
-		left -= ret;
-	}
-
-	return cur;
-}
-
-/*
- * Read into a byte stream.  Will not read more than count, but may read
- * less if there is not enough room in the stream buffer.
- */
-faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count)
-{
-	int red = 0;
-
-	if (!bs || (fd < 0) || (count < 0))
-		return -1;
-	
-	if (count > (bs->len - bs->offset))
-		count = bs->len - bs->offset; /* truncate to remaining space */
-
-	if (count) {
-
-		red = aim_recv(fd, bs->data + bs->offset, count);
-
-		if (red <= 0)
-			return -1;
-	}
-
-	bs->offset += red;
-
-	return red;
-}
-
-/**
- * aim_frame_destroy - free aim_frame_t
- * @frame: the frame to free
- *
- * returns -1 on error; 0 on success.
- *
- */
-faim_internal void aim_frame_destroy(aim_frame_t *frame)
-{
-
-	free(frame->data.data); /* XXX aim_bstream_free */
-	free(frame);
-
-	return;
-}
-
-/*
- * Read a FLAP header from conn into fr, and return the number of bytes in the payload.
- */
-static int aim_get_command_flap(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr)
-{
-	fu8_t flaphdr_raw[6];
-	aim_bstream_t flaphdr;
-	fu16_t payloadlen;
-	
-	aim_bstream_init(&flaphdr, flaphdr_raw, sizeof(flaphdr_raw));
-
-	/*
-	 * Read FLAP header.  Six bytes:
-	 *   0 char  -- Always 0x2a
-	 *   1 char  -- Channel ID.  Usually 2 -- 1 and 4 are used during login.
-	 *   2 short -- Sequence number
-	 *   4 short -- Number of data bytes that follow.
-	 */
-	if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) {
-		aim_conn_close(conn);
-		return -1;
-	}
-
-	aim_bstream_rewind(&flaphdr);
-
-	/*
-	 * This shouldn't happen unless the socket breaks, the server breaks,
-	 * or we break.  We must handle it just in case.
-	 */
-	if (aimbs_get8(&flaphdr) != 0x2a) {
-		fu8_t start;
-
-		aim_bstream_rewind(&flaphdr);
-		start = aimbs_get8(&flaphdr);
-		faimdprintf(sess, 0, "FLAP framing disrupted (0x%02x)", start);
-		aim_conn_close(conn);
-		return -1;
-	}	
-
-	/* we're doing FLAP if we're here */
-	fr->hdrtype = AIM_FRAMETYPE_FLAP;
-
-	fr->hdr.flap.type = aimbs_get8(&flaphdr);
-	fr->hdr.flap.seqnum = aimbs_get16(&flaphdr);
-	payloadlen = aimbs_get16(&flaphdr); /* length of payload */
-
-	return payloadlen;
-}
-
-/*
- * Read a rendezvous header from conn into fr, and return the number of bytes in the payload.
- */
-static int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr)
-{
-	fu8_t rendhdr_raw[8];
-	aim_bstream_t rendhdr;
-
-	aim_bstream_init(&rendhdr, rendhdr_raw, sizeof(rendhdr_raw));
-
-	if (aim_bstream_recv(&rendhdr, conn->fd, 8) < 8) {
-		aim_conn_close(conn);
-		return -1;
-	}
-
-	aim_bstream_rewind(&rendhdr);
-
-	fr->hdrtype = AIM_FRAMETYPE_OFT; /* a misnomer--rendezvous */
-
-	aimbs_getrawbuf(&rendhdr, fr->hdr.rend.magic, 4);
-	fr->hdr.rend.hdrlen = aimbs_get16(&rendhdr) - 8;
-	fr->hdr.rend.type = aimbs_get16(&rendhdr);
-
-	return fr->hdr.rend.hdrlen;
-}
-
-/*
- * Grab a single command sequence off the socket, and enqueue it in the incoming event queue 
- * in a separate struct.
- */
-faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *newrx;
-	fu16_t payloadlen;
-
-	if (!sess || !conn)
-		return -EINVAL;
-
-	if (conn->fd == -1)
-		return -1; /* it's an aim_conn_close()'d connection */
-
-	if (conn->fd < 3) /* can happen when people abuse the interface */
-		return -1;
-
-	if (conn->status & AIM_CONN_STATUS_INPROGRESS)
-		return aim_conn_completeconnect(sess, conn);
-
-	if (!(newrx = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1)))
-		return -ENOMEM;
-
-	/*
-	 * Rendezvous (client to client) connections do not speak FLAP, so this 
-	 * function will break on them.
-	 */
-	if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
-		int ret = aim_get_command_rendezvous(sess, conn, newrx);
-
-		if (ret < 0) {
-			free(newrx);
-			return -1;
-		}
-
-		payloadlen = ret;
-	} else if (conn->type == AIM_CONN_TYPE_LISTENER) {
-		faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd);
-		free(newrx);
-		return -1;
-	} else
-		payloadlen = aim_get_command_flap(sess, conn, newrx);
-
-	newrx->nofree = 0; /* free by default */
-
-	if (payloadlen) {
-		fu8_t *payload = NULL;
-
-		if (!(payload = (fu8_t *) malloc(payloadlen))) {
-			aim_frame_destroy(newrx);
-			return -1;
-		}
-
-		aim_bstream_init(&newrx->data, payload, payloadlen);
-
-		/* read the payload */
-		if (aim_bstream_recv(&newrx->data, conn->fd, payloadlen) < payloadlen) {
-			aim_frame_destroy(newrx); /* free's payload */
-			aim_conn_close(conn);
-			return -1;
-		}
-	} else
-		aim_bstream_init(&newrx->data, NULL, 0);
-
-
-	aim_bstream_rewind(&newrx->data);
-
-	newrx->conn = conn;
-
-	newrx->next = NULL;  /* this will always be at the bottom */
-
-	if (!sess->queue_incoming)
-		sess->queue_incoming = newrx;
-	else {
-		aim_frame_t *cur;
-
-		for (cur = sess->queue_incoming; cur->next; cur = cur->next)
-			;
-		cur->next = newrx;
-	}
-
-	newrx->conn->lastactivity = time(NULL);
-
-	return 0;  
-}
-
-/*
- * Purge recieve queue of all handled commands (->handled==1).  Also
- * allows for selective freeing using ->nofree so that the client can
- * keep the data for various purposes.  
- *
- * If ->nofree is nonzero, the frame will be delinked from the global list, 
- * but will not be free'ed.  The client _must_ keep a pointer to the
- * data -- libfaim will not!  If the client marks ->nofree but
- * does not keep a pointer, it's lost forever.
- *
- */
-faim_export void aim_purge_rxqueue(aim_session_t *sess)
-{
-	aim_frame_t *cur, **prev;
-
-	for (prev = &sess->queue_incoming; (cur = *prev); ) {
-		if (cur->handled) {
-
-			*prev = cur->next;
-			
-			if (!cur->nofree)
-				aim_frame_destroy(cur);
-
-		} else
-			prev = &cur->next;
-	}
-
-	return;
-}
-
-/*
- * Since aim_get_command will aim_conn_kill dead connections, we need
- * to clean up the rxqueue of unprocessed connections on that socket.
- *
- * XXX: this is something that was handled better in the old connection
- * handling method, but eh.
- */
-faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *currx;
-
-	for (currx = sess->queue_incoming; currx; currx = currx->next) {
-		if ((!currx->handled) && (currx->conn == conn))
-			currx->handled = 1;
-	}	
-	return;
-}
Index: bfaim/search.c
===================================================================
--- libfaim/search.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,134 +1,0 @@
-/*
- * Family 0x000a - User Search.
- *
- * TODO: Add aim_usersearch_name()
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/*
- * Subtype 0x0001
- *
- * XXX can this be integrated with the rest of the error handling?
- */
-static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-
-	/* XXX the modules interface should have already retrieved this for us */
-	if (!(snac2 = aim_remsnac(sess, snac->id))) {
-		faimdprintf(sess, 2, "search error: couldn't get a snac for 0x%08lx\n", snac->id);
-		return 0;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, snac2->data /* address */);
-
-	/* XXX freesnac()? */
-	if (snac2)
-		free(snac2->data);
-	free(snac2);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0002
- *
- */
-faim_export int aim_search_address(aim_session_t *sess, aim_conn_t *conn, const char *address)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn || !address)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+strlen(address))))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x000a, 0x0002, 0x0000, strdup(address), strlen(address)+1);
-	aim_putsnac(&fr->data, 0x000a, 0x0002, 0x0000, snacid);
-	
-	aimbs_putraw(&fr->data, address, strlen(address)); 
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0003
- *
- */
-static int reply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int j = 0, m, ret = 0;
-	aim_tlvlist_t *tlvlist;
-	char *cur = NULL, *buf = NULL;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-	char *searchaddr = NULL;
-
-	if ((snac2 = aim_remsnac(sess, snac->id)))
-		searchaddr = (char *)snac2->data;
-
-	tlvlist = aim_tlvlist_read(bs);
-	m = aim_tlvlist_count(&tlvlist);
-
-	/* XXX uhm.
-	 * This is the only place that uses something other than 1 for the 3rd 
-	 * parameter to aim_tlv_gettlv_whatever().
-	 */
-	while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m) {
-		buf = realloc(buf, (j+1) * (MAXSNLEN+1));
-
-		strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN);
-		free(cur);
-
-		j++; 
-	}
-
-	aim_tlvlist_free(&tlvlist);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, searchaddr, j, buf);
-
-	/* XXX freesnac()? */
-	if (snac2)
-		free(snac2->data);
-	free(snac2);
-
-	free(buf);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0001)
-		return error(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0003)
-		return reply(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int search_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000a;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "search", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/service.c
===================================================================
--- libfaim/service.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,1089 +1,0 @@
-/*
- * Family 0x0001 - This is a very special group.  All connections support
- * this group, as it does some particularly good things (like rate limiting).
- */
-
-#define FAIM_INTERNAL
-#define FAIM_NEED_CONN_INTERNAL
-#include <aim.h>
-
-#include "md5.h"
-
-/* Subtype 0x0002 - Client Online */
-faim_export int aim_clientready(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	struct snacgroup *sg;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!ins)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
-
-	/*
-	 * Send only the tool versions that the server cares about (that it
-	 * marked as supporting in the server ready SNAC).  
-	 */
-	for (sg = ins->groups; sg; sg = sg->next) {
-		aim_module_t *mod;
-
-		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
-			aimbs_put16(&fr->data, mod->family);
-			aimbs_put16(&fr->data, mod->version);
-			aimbs_put16(&fr->data, mod->toolid);
-			aimbs_put16(&fr->data, mod->toolversion);
-		} else
-			faimdprintf(sess, 1, "aim_clientready: server supports group 0x%04x but we don't!\n", sg->group);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0003 - Host Online
- * 
- * See comments in conn.c about how the group associations are supposed
- * to work, and how they really work.
- *
- * This info probably doesn't even need to make it to the client.
- *
- * We don't actually call the client here.  This starts off the connection
- * initialization routine required by all AIM connections.  The next time
- * the client is called is the CONNINITDONE callback, which should be 
- * shortly after the rate information is acknowledged.
- * 
- */
-static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	fu16_t *families;
-	int famcount;
-
-
-	if (!(families = malloc(aim_bstream_empty(bs))))
-		return 0;
-
-	for (famcount = 0; aim_bstream_empty(bs); famcount++) {
-		families[famcount] = aimbs_get16(bs);
-		aim_conn_addgroup(rx->conn, families[famcount]);
-	}
-
-	free(families);
-
-
-	/*
-	 * Next step is in the Host Versions handler.
-	 *
-	 * Note that we must send this before we request rates, since
-	 * the format of the rate information depends on the versions we
-	 * give it.
-	 *
-	 */
-	aim_setversions(sess, rx->conn);
-
-	return 1; 
-}
-
-/* Subtype 0x0004 - Service request */
-faim_export int aim_reqservice(aim_session_t *sess, aim_conn_t *conn, fu16_t serviceid)
-{
-	return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
-}
-
-/* Subtype 0x0005 - Redirect */
-static int redirect(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	struct aim_redirect_data redir;
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	aim_snac_t *origsnac = NULL;
-	int ret = 0;
-
-	memset(&redir, 0, sizeof(redir));
-
-	tlvlist = aim_tlvlist_read(bs);
-
-	if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
-			!aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
-			!aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-		aim_tlvlist_free(&tlvlist);
-		return 0;
-	}
-
-	redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);
-	redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
-	redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;
-	redir.cookie = aim_tlv_getstr(tlvlist, 0x0006, 1);
-
-	/* Fetch original SNAC so we can get csi if needed */
-	origsnac = aim_remsnac(sess, snac->id);
-
-	if ((redir.group == AIM_CONN_TYPE_CHAT) && origsnac) {
-		struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data;
-
-		redir.chat.exchange = csi->exchange;
-		redir.chat.room = csi->name;
-		redir.chat.instance = csi->instance;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, &redir);
-
-	free((void *)redir.ip);
-	free((void *)redir.cookie);
-
-	if (origsnac)
-		free(origsnac->data);
-	free(origsnac);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/* Subtype 0x0006 - Request Rate Information. */
-faim_internal int aim_reqrates(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x0006);
-}
-
-/*
- * OSCAR defines several 'rate classes'.  Each class has seperate
- * rate limiting properties (limit level, alert level, disconnect
- * level, etc), and a set of SNAC family/type pairs associated with
- * it.  The rate classes, their limiting properties, and the definitions
- * of which SNACs are belong to which class, are defined in the
- * Rate Response packet at login to each host.  
- *
- * Logically, all rate offenses within one class count against further
- * offenses for other SNACs in the same class (ie, sending messages
- * too fast will limit the number of user info requests you can send,
- * since those two SNACs are in the same rate class).
- *
- * Since the rate classes are defined dynamically at login, the values
- * below may change. But they seem to be fairly constant.
- *
- * Currently, BOS defines five rate classes, with the commonly used
- * members as follows...
- *
- *  Rate class 0x0001:
- *  	- Everything thats not in any of the other classes
- *
- *  Rate class 0x0002:
- * 	- Buddy list add/remove
- *	- Permit list add/remove
- *	- Deny list add/remove
- *
- *  Rate class 0x0003:
- *	- User information requests
- *	- Outgoing ICBMs
- *
- *  Rate class 0x0004:
- *	- A few unknowns: 2/9, 2/b, and f/2
- *
- *  Rate class 0x0005:
- *	- Chat room create
- *	- Outgoing chat ICBMs
- *
- * The only other thing of note is that class 5 (chat) has slightly looser
- * limiting properties than class 3 (normal messages).  But thats just a 
- * small bit of trivia for you.
- *
- * The last thing that needs to be learned about the rate limiting
- * system is how the actual numbers relate to the passing of time.  This
- * seems to be a big mystery.
- * 
- */
-
-static void rc_addclass(struct rateclass **head, struct rateclass *inrc)
-{
-	struct rateclass *rc, *rc2;
-
-	if (!(rc = malloc(sizeof(struct rateclass))))
-		return;
-
-	memcpy(rc, inrc, sizeof(struct rateclass));
-	rc->next = NULL;
-
-	for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next)
-		;
-
-	if (!rc2)
-		*head = rc;
-	else
-		rc2->next = rc;
-
-	return;
-}
-
-static struct rateclass *rc_findclass(struct rateclass **head, fu16_t id)
-{
-	struct rateclass *rc;
-
-	for (rc = *head; rc; rc = rc->next) {
-		if (rc->classid == id)
-			return rc;
-	}
-
-	return NULL;
-}
-
-static void rc_addpair(struct rateclass *rc, fu16_t group, fu16_t type)
-{
-	struct snacpair *sp, *sp2;
-
-	if (!(sp = malloc(sizeof(struct snacpair))))
-		return;
-	memset(sp, 0, sizeof(struct snacpair));
-
-	sp->group = group;
-	sp->subtype = type;
-	sp->next = NULL;
-
-	for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next)
-		;
-
-	if (!sp2)
-		rc->members = sp;
-	else
-		sp2->next = sp;
-
-	return;
-}
-
-/* Subtype 0x0007 - Rate Parameters */
-static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)rx->conn->inside;
-	fu16_t numclasses, i;
-	aim_rxcallback_t userfunc;
-
-
-	/*
-	 * First are the parameters for each rate class.
-	 */
-	numclasses = aimbs_get16(bs);
-	for (i = 0; i < numclasses; i++) {
-		struct rateclass rc;
-
-		memset(&rc, 0, sizeof(struct rateclass));
-
-		rc.classid = aimbs_get16(bs);
-		rc.windowsize = aimbs_get32(bs);
-		rc.clear = aimbs_get32(bs);
-		rc.alert = aimbs_get32(bs);
-		rc.limit = aimbs_get32(bs);
-		rc.disconnect = aimbs_get32(bs);
-		rc.current = aimbs_get32(bs);
-		rc.max = aimbs_get32(bs);
-
-		/*
-		 * The server will send an extra five bytes of parameters
-		 * depending on the version we advertised in 1/17.  If we
-		 * didn't send 1/17 (evil!), then this will crash and you
-		 * die, as it will default to the old version but we have 
-		 * the new version hardcoded here. 
-		 */
-		if (mod->version >= 3)
-			aimbs_getrawbuf(bs, rc.unknown, sizeof(rc.unknown));
-
-		faimdprintf(sess, 1, "--- Adding rate class %d to connection type %d: window size = %ld, clear = %ld, alert = %ld, limit = %ld, disconnect = %ld, current = %ld, max = %ld\n", rx->conn->type, rc.classid, rc.windowsize, rc.clear, rc.alert, rc.limit, rc.disconnect, rc.current, rc.max);
-
-		rc_addclass(&ins->rates, &rc);
-	}
-
-	/*
-	 * Then the members of each class.
-	 */
-	for (i = 0; i < numclasses; i++) {
-		fu16_t classid, count;
-		struct rateclass *rc;
-		int j;
-
-		classid = aimbs_get16(bs);
-		count = aimbs_get16(bs);
-
-		rc = rc_findclass(&ins->rates, classid);
-
-		for (j = 0; j < count; j++) {
-			fu16_t group, subtype;
-
-			group = aimbs_get16(bs);
-			subtype = aimbs_get16(bs);
-
-			if (rc)
-				rc_addpair(rc, group, subtype);
-		}
-	}
-
-	/*
-	 * We don't pass the rate information up to the client, as it really
-	 * doesn't care.  The information is stored in the connection, however
-	 * so that we can do more fun stuff later (not really).
-	 */
-
-	/*
-	 * Last step in the conn init procedure is to acknowledge that we
-	 * agree to these draconian limitations.
-	 */
-	aim_rates_addparam(sess, rx->conn);
-
-	/*
-	 * Finally, tell the client it's ready to go...
-	 */
-	if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE)))
-		userfunc(sess, rx);
-
-
-	return 1;
-}
-
-/* Subtype 0x0008 - Add Rate Parameter */
-faim_internal int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	aim_frame_t *fr;	
-	aim_snacid_t snacid;
-	struct rateclass *rc;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
-		return -ENOMEM; 
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid);
-
-	for (rc = ins->rates; rc; rc = rc->next)
-		aimbs_put16(&fr->data, rc->classid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x0009 - Delete Rate Parameter */
-faim_internal int aim_rates_delparam(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	aim_frame_t *fr;	
-	aim_snacid_t snacid;
-	struct rateclass *rc;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512)))
-		return -ENOMEM; 
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0009, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0009, 0x0000, snacid);
-
-	for (rc = ins->rates; rc; rc = rc->next)
-		aimbs_put16(&fr->data, rc->classid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x000a - Rate Change */
-static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t code, rateclass;
-	fu32_t currentavg, maxavg, windowsize, clear, alert, limit, disconnect;
-
-	code = aimbs_get16(bs);
-	rateclass = aimbs_get16(bs);
-	
-	windowsize = aimbs_get32(bs);
-	clear = aimbs_get32(bs);
-	alert = aimbs_get32(bs);
-	limit = aimbs_get32(bs);
-	disconnect = aimbs_get32(bs);
-	currentavg = aimbs_get32(bs);
-	maxavg = aimbs_get32(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
-
-	return ret;
-}
-
-/*
- * How Migrations work.
- *
- * The server sends a Server Pause message, which the client should respond to 
- * with a Server Pause Ack, which contains the families it needs on this 
- * connection. The server will send a Migration Notice with an IP address, and 
- * then disconnect. Next the client should open the connection and send the 
- * cookie.  Repeat the normal login process and pretend this never happened.
- *
- * The Server Pause contains no data.
- *
- */
-
-/* Subtype 0x000b - Service Pause */
-static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx);
-
-	return ret;
-}
-
-/*
- * Subtype 0x000c - Service Pause Acknowledgement
- *
- * It is rather important that aim_sendpauseack() gets called for the exact
- * same connection that the Server Pause callback was called for, since
- * libfaim extracts the data for the SNAC from the connection structure.
- *
- * Of course, if you don't do that, more bad things happen than just what
- * libfaim can cause.
- *
- */
-faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	struct snacgroup *sg;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid);
-
-	/*
-	 * This list should have all the groups that the original 
-	 * Host Online / Server Ready said this host supports.  And 
-	 * we want them all back after the migration.
-	 */
-	for (sg = ins->groups; sg; sg = sg->next)
-		aimbs_put16(&fr->data, sg->group);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x000d - Service Resume */
-static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx);
-
-	return ret;
-}
-
-/* Subtype 0x000e - Request self-info */
-faim_export int aim_reqpersonalinfo(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x000e);
-}
-
-/* Subtype 0x000f - Self User Info */
-static int selfinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_userinfo_t userinfo;
-
-	aim_info_extract(sess, bs, &userinfo);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, &userinfo);
-
-	aim_info_free(&userinfo);
-
-	return ret;
-}
-
-/* Subtype 0x0010 - Evil Notification */
-static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t newevil;
-	aim_userinfo_t userinfo;
-
-	memset(&userinfo, 0, sizeof(aim_userinfo_t));
-	
-	newevil = aimbs_get16(bs);
-
-	if (aim_bstream_empty(bs))
-		aim_info_extract(sess, bs, &userinfo);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, newevil, &userinfo);
-
-	aim_info_free(&userinfo);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0011 - Idle Notification
- *
- * Should set your current idle time in seconds.  Note that this should
- * never be called consecutively with a non-zero idle time.  That makes
- * OSCAR do funny things.  Instead, just set it once you go idle, and then
- * call it again with zero when you're back.
- *
- */
-faim_export int aim_srv_setidle(aim_session_t *sess, fu32_t idletime)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_BOS)))
-		return -EINVAL;
-
-	return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);
-}
-
-/*
- * Subtype 0x0012 - Service Migrate
- *
- * This is the final SNAC sent on the original connection during a migration.
- * It contains the IP and cookie used to connect to the new server, and 
- * optionally a list of the SNAC groups being migrated.
- *
- */
-static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	fu16_t groupcount, i;
-	aim_tlvlist_t *tl;
-	char *ip = NULL;
-	aim_tlv_t *cktlv;
-
-	/*
-	 * Apparently there's some fun stuff that can happen right here. The
-	 * migration can actually be quite selective about what groups it
-	 * moves to the new server.  When not all the groups for a connection
-	 * are migrated, or they are all migrated but some groups are moved
-	 * to a different server than others, it is called a bifurcated 
-	 * migration.
-	 *
-	 * Let's play dumb and not support that.
-	 *
-	 */
-	groupcount = aimbs_get16(bs);
-	for (i = 0; i < groupcount; i++) {
-		fu16_t group;
-
-		group = aimbs_get16(bs);
-
-		faimdprintf(sess, 0, "bifurcated migration unsupported -- group 0x%04x\n", group);
-	}
-
-	tl = aim_tlvlist_read(bs);
-
-	if (aim_tlv_gettlv(tl, 0x0005, 1))
-		ip = aim_tlv_getstr(tl, 0x0005, 1);
-
-	cktlv = aim_tlv_gettlv(tl, 0x0006, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL);
-
-	aim_tlvlist_free(&tl);
-	free(ip);
-
-	return ret;
-}
-
-/* Subtype 0x0013 - Message of the Day */
-static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	char *msg = NULL;
-	int ret = 0;
-	aim_tlvlist_t *tlvlist;
-	fu16_t id;
-
-	/*
-	 * Code.
-	 *
-	 * Valid values:
-	 *   1 Mandatory upgrade
-	 *   2 Advisory upgrade
-	 *   3 System bulletin
-	 *   4 Nothing's wrong ("top o the world" -- normal)
-	 *   5 Lets-break-something. 
-	 *
-	 */
-	id = aimbs_get16(bs);
-
-	/* 
-	 * TLVs follow 
-	 */
-	tlvlist = aim_tlvlist_read(bs);
-
-	msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, id, msg);
-
-	free(msg);
-
-	aim_tlvlist_free(&tlvlist);
-
-	return ret;
-}
-
-/* 
- * Subtype 0x0014 - Set privacy flags
- *
- * Normally 0x03.
- *
- *  Bit 1:  Allows other AIM users to see how long you've been idle.
- *  Bit 2:  Allows other AIM users to see how long you've been a member.
- *
- */
-faim_export int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, fu32_t flags)
-{
-	return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
-}
-
-/*
- * Subtype 0x0016 - No-op
- *
- * WinAIM sends these every 4min or so to keep the connection alive.  Its not 
- * really necessary.
- *
- * Wha?  No?  Since when?  I think WinAIM sends an empty channel 3 
- * SNAC as a no-op...
- */
-faim_export int aim_nop(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
-}
-
-/* 
- * Subtype 0x0017 - Set client versions
- *
- * If you've seen the clientonline/clientready SNAC you're probably 
- * wondering what the point of this one is.  And that point seems to be
- * that the versions in the client online SNAC are sent too late for the
- * server to be able to use them to change the protocol for the earlier
- * login packets (client versions are sent right after Host Online is 
- * received, but client online versions aren't sent until quite a bit later).
- * We can see them already making use of this by changing the format of
- * the rate information based on what version of group 1 we advertise here.
- *
- */
-faim_internal int aim_setversions(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
-	struct snacgroup *sg;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!ins)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid);
-
-	/*
-	 * Send only the versions that the server cares about (that it
-	 * marked as supporting in the server ready SNAC).  
-	 */
-	for (sg = ins->groups; sg; sg = sg->next) {
-		aim_module_t *mod;
-
-		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
-			aimbs_put16(&fr->data, mod->family);
-			aimbs_put16(&fr->data, mod->version);
-		} else
-			faimdprintf(sess, 1, "aim_setversions: server supports group 0x%04x but we don't!\n", sg->group);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Subtype 0x0018 - Host versions */
-static int hostversions(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int vercount;
-	fu8_t *versions;
-
-	/* This is frivolous. (Thank you SmarterChild.) */
-	vercount = aim_bstream_empty(bs)/4;
-	versions = aimbs_getraw(bs, aim_bstream_empty(bs));
-	free(versions);
-
-	/*
-	 * Now request rates.
-	 */
-	aim_reqrates(sess, rx->conn);
-
-	return 1;
-}
-
-/* 
- * Subtype 0x001e - Extended Status
- *
- * Sets your ICQ status (available, away, do not disturb, etc.)
- *
- * These are the same TLVs seen in user info.  You can 
- * also set 0x0008 and 0x000c.
- */
-faim_export int aim_setextstatus(aim_session_t *sess, fu32_t status)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	fu32_t data;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
-		return -EINVAL;
-
-	data = AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_WEBAWARE | status; /* yay for error checking ;^) */
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
-	
-	aim_tlvlist_add_32(&tl, 0x0006, data);
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
-	
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* 
- * Subtype 0x001e - Extended Status.
- *
- * Sets your "available" message.  This is currently only supported by iChat 
- * and Gaim.
- *
- * These are the same TLVs seen in user info.  You can 
- * also set 0x0008 and 0x000c.
- */
-faim_export int aim_srv_setavailmsg(aim_session_t *sess, char *msg)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0001)))
-		return -EINVAL;
-
-	if (msg != NULL) {
-		if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + strlen(msg) + 8)))
-			return -ENOMEM;
-
-		snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0);
-		aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
-
-		aimbs_put16(&fr->data, 0x001d); /* userinfo TLV type */
-		aimbs_put16(&fr->data, strlen(msg)+8); /* total length of userinfo TLV data */
-		aimbs_put16(&fr->data, 0x0002);
-		aimbs_put8(&fr->data, 0x04);
-		aimbs_put8(&fr->data, strlen(msg)+4);
-		aimbs_put16(&fr->data, strlen(msg));
-		aimbs_putraw(&fr->data, msg, strlen(msg));
-		aimbs_put16(&fr->data, 0x0000);
-	} else {
-		if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + 8)))
-			return -ENOMEM;
-
-		snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0);
-		aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
-
-		aimbs_put16(&fr->data, 0x001d);
-		aimbs_put16(&fr->data, 0x0008);
-		aimbs_put16(&fr->data, 0x0002);
-		aimbs_put16(&fr->data, 0x0404);
-		aimbs_put16(&fr->data, 0x0000);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Starting this past week (26 Mar 2001, say), AOL has started sending
- * this nice little extra SNAC.  AFAIK, it has never been used until now.
- *
- * The request contains eight bytes.  The first four are an offset, the
- * second four are a length.
- *
- * The offset is an offset into aim.exe when it is mapped during execution
- * on Win32.  So far, AOL has only been requesting bytes in static regions
- * of memory.  (I won't put it past them to start requesting data in
- * less static regions -- regions that are initialized at run time, but still
- * before the client recieves this request.)
- *
- * When the client recieves the request, it adds it to the current ds
- * (0x00400000) and dereferences it, copying the data into a buffer which
- * it then runs directly through the MD5 hasher.  The 16 byte output of
- * the hash is then sent back to the server.
- *
- * If the client does not send any data back, or the data does not match
- * the data that the specific client should have, the client will get the
- * following message from "AOL Instant Messenger":
- *    "You have been disconnected from the AOL Instant Message Service (SM) 
- *     for accessing the AOL network using unauthorized software.  You can
- *     download a FREE, fully featured, and authorized client, here 
- *     http://www.aol.com/aim/download2.html"
- * The connection is then closed, recieving disconnect code 1, URL
- * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.  
- *
- * Note, however, that numerous inconsistencies can cause the above error, 
- * not just sending back a bad hash.  Do not immediatly suspect this code
- * if you get disconnected.  AOL and the open/free software community have
- * played this game for a couple years now, generating the above message
- * on numerous ocassions.
- *
- * Anyway, neener.  We win again.
- *
- */
-/* Subtype 0x001f - Client verification */
-static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu32_t offset, len;
-	aim_tlvlist_t *list;
-	char *modname;
-
-	offset = aimbs_get32(bs);
-	len = aimbs_get32(bs);
-	list = aim_tlvlist_read(bs);
-
-	modname = aim_tlv_getstr(list, 0x0001, 1);
-
-	faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname ? modname : "aim.exe");
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, offset, len, modname);
-
-	free(modname);
-	aim_tlvlist_free(&list);
-
-	return ret;
-}
-
-#if 0
-static void dumpbox(aim_session_t *sess, unsigned char *buf, int len)
-{
-	int i;
-
-	if (!sess || !buf || !len)
-		return;
-
-	faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf);
-
-	for (i = 0; i < len; i++) {
-		if ((i % 8) == 0)
-			faimdprintf(sess, 1, "\n\t");
-
-		faimdprintf(sess, 1, "0x%2x ", buf[i]);
-	}
-
-	faimdprintf(sess, 1, "\n\n");
-
-	return;
-}
-#endif
-
-/* Subtype 0x0020 - Client verification reply */
-faim_export int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, fu32_t offset, fu32_t len, const fu8_t *buf, fu8_t flag)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0020, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, 0x0001, 0x0020, 0x0000, snacid);
-	aimbs_put16(&fr->data, 0x0010); /* md5 is always 16 bytes */
-
-	if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
-
-		aimbs_putraw(&fr->data, buf, 0x10); 
-
-	} else if (buf && (len > 0)) { /* use input buffer */
-		md5_state_t state;
-		md5_byte_t digest[0x10];
-
-		md5_init(&state);	
-		md5_append(&state, (const md5_byte_t *)buf, len);
-		md5_finish(&state, digest);
-
-		aimbs_putraw(&fr->data, (fu8_t *)digest, 0x10);
-
-	} else if (len == 0) { /* no length, just hash NULL (buf is optional) */
-		md5_state_t state;
-		fu8_t nil = '\0';
-		md5_byte_t digest[0x10];
-
-		/*
-		 * These MD5 routines are stupid in that you have to have
-		 * at least one append.  So thats why this doesn't look 
-		 * real logical.
-		 */
-		md5_init(&state);
-		md5_append(&state, (const md5_byte_t *)&nil, 0);
-		md5_finish(&state, digest);
-
-		aimbs_putraw(&fr->data, (fu8_t *)digest, 0x10);
-
-	} else {
-
-		/* 
-		 * This data is correct for AIM 3.5.1670.
-		 *
-		 * Using these blocks is as close to "legal" as you can get
-		 * without using an AIM binary.
-		 *
-		 */
-		if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {
-
-#if 1 /* with "AnrbnrAqhfzcd" */
-			aimbs_put32(&fr->data, 0x44a95d26);
-			aimbs_put32(&fr->data, 0xd2490423);
-			aimbs_put32(&fr->data, 0x93b8821f);
-			aimbs_put32(&fr->data, 0x51c54b01);
-#else /* no filename */
-			aimbs_put32(&fr->data, 0x1df8cbae);
-			aimbs_put32(&fr->data, 0x5523b839);
-			aimbs_put32(&fr->data, 0xa0e10db3);
-			aimbs_put32(&fr->data, 0xa46d3b39);
-#endif
-
-		} else if ((offset == 0x00001000) && (len == 0x00000000)) {
-
-			aimbs_put32(&fr->data, 0xd41d8cd9);
-			aimbs_put32(&fr->data, 0x8f00b204);
-			aimbs_put32(&fr->data, 0xe9800998);
-			aimbs_put32(&fr->data, 0xecf8427e);
-
-		} else
-			faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n");
-
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0021 - Receive our extended status
- *
- * This is used for iChat's "available" messages, and maybe ICQ extended 
- * status messages?  It's also used to tell the client whether or not it 
- * needs to upload an SSI buddy icon... who engineers this stuff, anyway?
- */
-static int aim_parse_extstatus(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t type;
-	fu8_t flags, length;
-
-	type = aimbs_get16(bs); 
-	flags = aimbs_get8(bs);
-	length = aimbs_get8(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		switch (type) {
-		case 0x0000:
-		case 0x0001: { /* buddy icon checksum */
-			/* not sure what the difference between 1 and 0 is */
-			fu8_t *md5 = aimbs_getraw(bs, length);
-			ret = userfunc(sess, rx, type, flags, length, md5);
-			free(md5);
-			} break;
-		case 0x0002: { /* available message */
-			/* there is a second length that is just for the message */
-			char *msg = aimbs_getstr(bs, aimbs_get16(bs));
-			ret = userfunc(sess, rx, msg);
-			free(msg);
-			} break;
-		}
-	}
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003)
-		return hostonline(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0005)
-		return redirect(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0007)
-		return rateresp(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000a)
-		return ratechange(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000b)
-		return serverpause(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000d)
-		return serverresume(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x000f)
-		return selfinfo(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0010)
-		return evilnotify(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0012)
-		return migrate(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0013)
-		return motd(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0018)
-		return hostversions(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x001f)
-		return memrequest(sess, mod, rx, snac, bs);
-	else if (snac->subtype == 0x0021)
-		return aim_parse_extstatus(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int service_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0001;
-	mod->version = 0x0003;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "service", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/snac.c
===================================================================
--- libfaim/snac.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,148 +1,0 @@
-/*
- *
- * Various SNAC-related dodads... 
- *
- * outstanding_snacs is a list of aim_snac_t structs.  A SNAC should be added
- * whenever a new SNAC is sent and it should remain in the list until the
- * response for it has been receieved.  
- *
- * cleansnacs() should be called periodically by the client in order
- * to facilitate the aging out of unreplied-to SNACs. This can and does
- * happen, so it should be handled.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/*
- * Called from aim_session_init() to initialize the hash.
- */
-faim_internal void aim_initsnachash(aim_session_t *sess)
-{
-	int i;
-
-	for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
-		sess->snac_hash[i] = NULL;
-
-	return;
-}
-
-faim_internal aim_snacid_t aim_cachesnac(aim_session_t *sess, const fu16_t family, const fu16_t type, const fu16_t flags, const void *data, const int datalen)
-{
-	aim_snac_t snac;
-
-	snac.id = sess->snacid_next++;
-	snac.family = family;
-	snac.type = type;
-	snac.flags = flags;
-
-	if (datalen) {
-		if (!(snac.data = malloc(datalen)))
-			return 0; /* er... */
-		memcpy(snac.data, data, datalen);
-	} else
-		snac.data = NULL;
-
-	return aim_newsnac(sess, &snac);
-}
-
-/*
- * Clones the passed snac structure and caches it in the
- * list/hash.
- */
-faim_internal aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
-{
-	aim_snac_t *snac;
-	int index;
-
-	if (!newsnac)
-		return 0;
-
-	if (!(snac = malloc(sizeof(aim_snac_t))))
-		return 0;
-	memcpy(snac, newsnac, sizeof(aim_snac_t));
-	snac->issuetime = time(NULL);
-
-	index = snac->id % FAIM_SNAC_HASH_SIZE;
-
-	snac->next = (aim_snac_t *)sess->snac_hash[index];
-	sess->snac_hash[index] = (void *)snac;
-
-	return snac->id;
-}
-
-/*
- * Finds a snac structure with the passed SNAC ID, 
- * removes it from the list/hash, and returns a pointer to it.
- *
- * The returned structure must be freed by the caller.
- *
- */
-faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id) 
-{
-	aim_snac_t *cur, **prev;
-	int index;
-
-	index = id % FAIM_SNAC_HASH_SIZE;
-
-	for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) {
-		if (cur->id == id) {
-			*prev = cur->next;
-			if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
-				free(cur->data);
-				cur->data = NULL;
-			}
-			return cur;
-		} else
-			prev = &cur->next;
-	}
-
-	return cur;
-}
-
-/*
- * This is for cleaning up old SNACs that either don't get replies or
- * a reply was never received for.  Garabage collection. Plain and simple.
- *
- * maxage is the _minimum_ age in seconds to keep SNACs.
- *
- */
-faim_export void aim_cleansnacs(aim_session_t *sess, int maxage)
-{
-	int i;
-
-	for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
-		aim_snac_t *cur, **prev;
-		time_t curtime;
-
-		if (!sess->snac_hash[i])
-			continue;
-
-		curtime = time(NULL); /* done here in case we waited for the lock */
-
-		for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) {
-			if ((curtime - cur->issuetime) > maxage) {
-
-				*prev = cur->next;
-
-				free(cur->data);
-				free(cur);
-			} else
-				prev = &cur->next;
-		}
-	}
-
-	return;
-}
-
-faim_internal int aim_putsnac(aim_bstream_t *bs, fu16_t family, fu16_t subtype, fu16_t flags, aim_snacid_t snacid)
-{
-
-	aimbs_put16(bs, family);
-	aimbs_put16(bs, subtype);
-	aimbs_put16(bs, flags);
-	aimbs_put32(bs, snacid);
-
-	return 10;
-}
Index: bfaim/ssi.c
===================================================================
--- libfaim/ssi.c	(revision 0154e2d932e8d0248f6052152feb1fd0ffceedc4)
+++ 	(revision )
@@ -1,1963 +1,0 @@
-/*
- * Family 0x0013 - Server-Side/Stored Information.
- *
- * Relatively new facility that allows certain types of information, such as 
- * a user's buddy list, permit/deny list, and permit/deny preferences, to be 
- * stored on the server, so that they can be accessed from any client.
- *
- * We keep 2 copies of SSI data:
- * 1) An exact copy of what is stored on the AIM servers.
- * 2) A local copy that we make changes to, and then send diffs 
- *    between this and the exact copy to keep them in sync.
- *
- * All the "aim_ssi_itemlist_bleh" functions near the top just modify the list 
- * that is given to them (i.e. they don't send SNACs).
- *
- * The SNAC sending and receiving functions are lower down in the file, and 
- * they're simpler.  They are in the order of the subtypes they deal with, 
- * starting with the request rights function (subtype 0x0002), then parse 
- * rights (subtype 0x0003), then--well, you get the idea.
- *
- * This is entirely too complicated.
- * You don't know the half of it.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-/**
- * Locally rebuild the 0x00c8 TLV in the additional data of the given group.
- *
- * @param list A pointer to a pointer to the current list of items.
- * @param name A null terminated string containing the group name, or NULL 
- *        if you want to modify the master group.
- * @return Return a pointer to the modified item.
- */
-static struct aim_ssi_item *aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
-{
-	int newlen;
-	struct aim_ssi_item *cur, *group;
-
-	if (!list)
-		return NULL;
-
-	/* Find the group */
-	if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))
-		return NULL;
-
-	/* Find the length for the new additional data */
-	newlen = 0;
-	if (group->gid == 0x0000) {
-		for (cur=list; cur; cur=cur->next)
-			if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
-				newlen += 2;
-	} else {
-		for (cur=list; cur; cur=cur->next)
-			if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
-				newlen += 2;
-	}
-
-	/* Build the new TLV list */
-	if (newlen > 0) {
-		fu8_t *newdata;
-
-		if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t))))
-			return NULL;
-		newlen = 0;
-		if (group->gid == 0x0000) {
-			for (cur=list; cur; cur=cur->next)
-				if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
-						newlen += aimutil_put16(newdata+newlen, cur->gid);
-		} else {
-			for (cur=list; cur; cur=cur->next)
-				if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
-						newlen += aimutil_put16(newdata+newlen, cur->bid);
-		}
-		aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata);
-
-		free(newdata);
-	}
-
-	return group;
-}
-
-/**
- * Locally add a new item to the given item list.
- *
- * @param list A pointer to a pointer to the current list of items.
- * @param name A null terminated string of the name of the new item, or NULL if the 
- *        item should have no name.
- * @param gid The group ID# you want the new item to have, or 0xFFFF if we should pick something.
- * @param bid The buddy ID# you want the new item to have, or 0xFFFF if we should pick something.
- * @param type The type of the item, 0x0000 for a contact, 0x0001 for a group, etc.
- * @param data The additional data for the new item.
- * @return A pointer to the newly created item.
- */
-static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, fu16_t gid, fu16_t bid, fu16_t type, aim_tlvlist_t *data)
-{
-	int i;
-	struct aim_ssi_item *cur, *new;
-
-	if (!list)
-		return NULL;
-
-	if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))
-		return NULL;
-
-	/* Set the name */
-	if (name) {
-		new->name = (char *)malloc((strlen(name)+1)*sizeof(char));
-		strcpy(new->name, name);
-	} else
-		new->name = NULL;
-
-	/* Set the group ID# and buddy ID# */
-	new->gid = gid;
-	new->bid = bid;
-	if (type == AIM_SSI_TYPE_GROUP) {
-		if ((new->gid == 0xFFFF) && name) {
-			do {
-				new->gid += 0x0001;
-				for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
-					if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid))
-						i=1;
-			} while (i);
-		}
-	} else {
-		if (new->bid == 0xFFFF) {
-			do {
-				new->bid += 0x0001;
-				for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next)
-					if ((cur->bid == new->bid) && (cur->gid == new->gid))
-						i=1;
-			} while (i);
-		}
-	}
-
-	/* Set the type */
-	new->type = type;
-
-	/* Set the TLV list */
-	new->data = aim_tlvlist_copy(data);
-
-	/* Add the item to the list in the correct numerical position.  Fancy, eh? */
-	if (*list) {
-		if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
-			new->next = *list;
-			*list = new;
-		} else {
-			struct aim_ssi_item *prev;
-			for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
-			new->next = prev->next;
-			prev->next = new;
-		}
-	} else {
-		new->next = *list;
-		*list = new;
-	}
-
-	return new;
-}
-
-/**
- * Locally delete an item from the given item list.
- *
- * @param list A pointer to a pointer to the current list of items.
- * @param del A pointer to the item you want to remove from the list.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
-{
-	if (!list || !(*list) || !del)
-		return -EINVAL;
-
-	/* Remove the item from the list */
-	if (*list == del) {
-		*list = (*list)->next;
-	} else {
-		struct aim_ssi_item *cur;
-		for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
-		if (cur->next)
-			cur->next = del->next;
-	}
-
-	/* Free the removed item */
-	free(del->name);
-	aim_tlvlist_free(&del->data);
-	free(del);
-
-	return 0;
-}
-
-/**
- * Compare two items to see if they have the same data.
- *
- * @param cur1 A pointer to a pointer to the first item.
- * @param cur2 A pointer to a pointer to the second item.
- * @return Return 0 if no differences, or a number if there are differences.
- */
-static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2)
-{
-	if (!cur1 || !cur2)
-		return 1;
-
-	if (cur1->data && !cur2->data)
-		return 2;
-
-	if (!cur1->data && cur2->data)
-		return 3;
-
-	if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
-			return 4;
-
-	if (cur1->name && !cur2->name)
-		return 5;
-
-	if (!cur1->name && cur2->name)
-		return 6;
-
-	if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))
-		return 7;
-
-	if (cur1->gid != cur2->gid)
-		return 8;
-
-	if (cur1->bid != cur2->bid)
-		return 9;
-
-	if (cur1->type != cur2->type)
-		return 10;
-
-	return 0;
-}
-
-faim_export int aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
-{
-	struct aim_ssi_item *cur;
-	for (cur=list; cur; cur=cur->next)
-		if (cur == item)
-			return 1;
-	return 0;
-}
-
-/**
- * Locally find an item given a group ID# and a buddy ID#.
- *
- * @param list A pointer to the current list of items.
- * @param gid The group ID# of the desired item.
- * @param bid The buddy ID# of the desired item.
- * @return Return a pointer to the item if found, else return NULL;
- */
-faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid)
-{
-	struct aim_ssi_item *cur;
-	for (cur=list; cur; cur=cur->next)
-		if ((cur->gid == gid) && (cur->bid == bid))
-			return cur;
-	return NULL;
-}
-
-/**
- * Locally find an item given a group name, screen name, and type.  If group name 
- * and screen name are null, then just return the first item of the given type.
- *
- * @param list A pointer to the current list of items.
- * @param gn The group name of the desired item.
- * @param bn The buddy name of the desired item.
- * @param type The type of the desired item.
- * @return Return a pointer to the item if found, else return NULL;
- */
-faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type)
-{
-	struct aim_ssi_item *cur;
-	if (!list)
-		return NULL;
-
-	if (gn && sn) { /* For finding buddies in groups */
-		for (cur=list; cur; cur=cur->next)
-			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
-				struct aim_ssi_item *curg;
-				for (curg=list; curg; curg=curg->next)
-					if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))
-						return cur;
-			}
-
-	} else if (gn) { /* For finding groups */
-		for (cur=list; cur; cur=cur->next) {
-			if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {
-				return cur;
-			}
-		}
-
-	} else if (sn) { /* For finding permits, denies, and ignores */
-		for (cur=list; cur; cur=cur->next) {
-			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
-				return cur;
-			}
-		}
-
-	/* For stuff without names--permit deny setting, visibility mask, etc. */
-	} else for (cur=list; cur; cur=cur->next) {
-		if ((cur->type == type) && (!cur->name))
-			return cur;
-	}
-
-	return NULL;
-}
-
-/**
- * Check if the given buddy exists in any group in the buddy list.
- *
- * @param list A pointer to the current list of items.
- * @param sn The group name of the desired item.
- * @return Return a pointer to the name of the item if found, else return NULL;
- */
-faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn)
-{
-	struct aim_ssi_item *cur;
-	if (!list || !sn)
-		return NULL;
-	for (cur=list; cur; cur=cur->next)
-		if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))
-			return cur;
-	return NULL;
-}
-
-/**
- * Locally find the parent item of the given buddy name.
- *
- * @param list A pointer to the current list of items.
- * @param bn The buddy name of the desired item.
- * @return Return a pointer to the name of the item if found, else return NULL;
- */
-faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn)
-{
-	struct aim_ssi_item *cur, *curg;
-	if (!list || !sn)
-		return NULL;
-	if (!(cur = aim_ssi_itemlist_exists(list, sn)))
-		return NULL;
-	if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
-		return NULL;
-	return curg->name;
-}
-
-/**
- * Locally find the permit/deny setting item, and return the setting.
- *
- * @param list A pointer to the current list of items.
- * @return Return the current SSI permit deny setting, or 0 if no setting was found.
- */
-faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
-	if (cur) {
-		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1);
-		if (tlv && tlv->value)
-			return aimutil_get8(tlv->value);
-	}
-	return 0;
-}
-
-/**
- * Locally find the presence flag item, and return the setting.  The returned setting is a 
- * bitmask of the user flags that you are visible to.  See the AIM_FLAG_* #defines 
- * in aim.h
- *
- * @param list A pointer to the current list of items.
- * @return Return the current visibility mask.
- */
-faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
-	if (cur) {
-		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1);
-		if (tlv && tlv->length)
-			return aimutil_get32(tlv->value);
-	}
-	return 0xFFFFFFFF;
-}
-
-/**
- * Locally find the alias of the given buddy.
- *
- * @param list A pointer to the current list of items.
- * @param gn The group of the buddy.
- * @param sn The name of the buddy.
- * @return A pointer to a NULL terminated string that is the buddy's 
- *         alias, or NULL if the buddy has no alias.  You should free
- *         this returned value!
- */
-faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
-	if (cur) {
-		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
-		if (tlv && tlv->length) {
-			char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
-			strncpy(alias, tlv->value, tlv->length);
-			alias[tlv->length] = 0;
-			return alias;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Locally find the comment of the given buddy.
- *
- * @param list A pointer to the current list of items.
- * @param gn The group of the buddy.
- * @param sn The name of the buddy.
- * @return A pointer to a NULL terminated string that is the buddy's 
- *         comment, or NULL if the buddy has no comment.  You should free
- *         this returned value!
- */
-faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
-	if (cur) {
-		aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1);
-		if (tlv && tlv->length) {
-			char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
-			strncpy(alias, tlv->value, tlv->length);
-			alias[tlv->length] = 0;
-			return alias;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Locally find if you are waiting for authorization for a buddy.
- *
- * @param list A pointer to the current list of items.
- * @param gn The group of the buddy.
- * @param sn The name of the buddy.
- * @return A pointer to a NULL terminated string that is the buddies 
- *         alias, or NULL if the buddy has no alias.  You should free
- *         this returned value!
- */
-faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
-	if (cur) {
-		if (aim_tlv_gettlv(cur->data, 0x0066, 1))
-			return 1;
-	}
-	return 0;
-}
-
-/**
- * If there are changes, then create temporary items and 
- * call addmoddel.
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_sync(aim_session_t *sess)
-{
-	struct aim_ssi_item *cur1, *cur2;
-	struct aim_ssi_tmp *cur, *new;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* If we're waiting for an ack, we shouldn't do anything else */
-	if (sess->ssi.waiting_for_ack)
-		return 0;
-
-	/*
-	 * Compare the 2 lists and create an aim_ssi_tmp for each difference.  
-	 * We should only send either additions, modifications, or deletions 
-	 * before waiting for an acknowledgement.  So first do deletions, then 
-	 * additions, then modifications.  Also, both the official and the local 
-	 * list should be in ascending numerical order for the group ID#s and the 
-	 * buddy ID#s, which makes things more efficient.  I think.
-	 */
-
-	/* Additions */
-	if (!sess->ssi.pending) {
-		for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
-			if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) {
-				new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
-				new->action = AIM_CB_SSI_ADD;
-				new->ack = 0xffff;
-				new->name = NULL;
-				new->item = cur1;
-				new->next = NULL;
-				if (sess->ssi.pending) {
-					for (cur=sess->ssi.pending; cur->next; cur=cur->next);
-					cur->next = new;
-				} else
-					sess->ssi.pending = new;
-			}
-		}
-	}
-
-	/* Deletions */
-	if (!sess->ssi.pending) {
-		for (cur1=sess->ssi.official; cur1; cur1=cur1->next) {
-			if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) {
-				new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
-				new->action = AIM_CB_SSI_DEL;
-				new->ack = 0xffff;
-				new->name = NULL;
-				new->item = cur1;
-				new->next = NULL;
-				if (sess->ssi.pending) {
-					for (cur=sess->ssi.pending; cur->next; cur=cur->next);
-					cur->next = new;
-				} else
-					sess->ssi.pending = new;
-			}
-		}
-	}
-
-	/* Modifications */
-	if (!sess->ssi.pending) {
-		for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
-			cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid);
-			if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
-				new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
-				new->action = AIM_CB_SSI_MOD;
-				new->ack = 0xffff;
-				new->name = NULL;
-				new->item = cur1;
-				new->next = NULL;
-				if (sess->ssi.pending) {
-					for (cur=sess->ssi.pending; cur->next; cur=cur->next);
-					cur->next = new;
-				} else
-					sess->ssi.pending = new;
-			}
-		}
-	}
-
-	/* We're out of stuff to do, so tell the AIM servers we're done and exit */
-	if (!sess->ssi.pending) {
-		aim_ssi_modend(sess);
-		return 0;
-	}
-
-	/* Make sure we don't send anything else between now 
-	 * and when we receive the ack for the following operation */
-	sess->ssi.waiting_for_ack = 1;
-
-	/* Now go mail off our data and wait 4 to 6 weeks */
-	aim_ssi_addmoddel(sess);
-
-	return 0;
-}
-
-/**
- * Free all SSI data.
- *
- * This doesn't remove it from the server, that's different.
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_freelist(aim_session_t *sess)
-{
-	struct aim_ssi_item *cur, *del;
-	struct aim_ssi_tmp *curtmp, *deltmp;
-
-	cur = sess->ssi.official;
-	while (cur) {
-		del = cur;
-		cur = cur->next;
-		free(del->name);
-		aim_tlvlist_free(&del->data);
-		free(del);
-	}
-
-	cur = sess->ssi.local;
-	while (cur) {
-		del = cur;
-		cur = cur->next;
-		free(del->name);
-		aim_tlvlist_free(&del->data);
-		free(del);
-	}
-
-	curtmp = sess->ssi.pending;
-	while (curtmp) {
-		deltmp = curtmp;
-		curtmp = curtmp->next;
-		free(deltmp);
-	}
-
-	sess->ssi.numitems = 0;
-	sess->ssi.official = NULL;
-	sess->ssi.local = NULL;
-	sess->ssi.pending = NULL;
-	sess->ssi.timestamp = (time_t)0;
-
-	return 0;
-}
-
-/**
- * Delete all SSI data.
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_deletelist(aim_session_t *sess)
-{
-	struct aim_ssi_item *cur, *del;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Free the local list */
-	cur = sess->ssi.local;
-	while (cur) {
-		del = cur;
-		cur = cur->next;
-		free(del->name);
-		aim_tlvlist_free(&del->data);
-		free(del);
-	}
-	sess->ssi.local = NULL;
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * This "cleans" the ssi list.  It does the following:
- * 1) Makes sure all buddies, permits, and denies have names.
- * 2) Makes sure that all buddies are in a group that exist.
- * 3) Deletes any empty groups
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_cleanlist(aim_session_t *sess)
-{
-	struct aim_ssi_item *cur, *next;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Delete any buddies, permits, or denies with empty names. */
-	/* If there are any buddies directly in the master group, add them to a real group. */
-	/* DESTROY any buddies that are directly in the master group. */
-	/* Do the same for buddies that are in a non-existant group. */
-	/* This will kind of mess up if you hit the item limit, but this function isn't too critical */
-	cur = sess->ssi.local;
-	while (cur) {
-		next = cur->next;
-		if (!cur->name) {
-			if (cur->type == AIM_SSI_TYPE_BUDDY)
-				aim_ssi_delbuddy(sess, NULL, NULL);
-			else if (cur->type == AIM_SSI_TYPE_PERMIT)
-				aim_ssi_delpermit(sess, NULL);
-			else if (cur->type == AIM_SSI_TYPE_DENY)
-				aim_ssi_deldeny(sess, NULL);
-		} else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) {
-			aim_ssi_addbuddy(sess, cur->name, "orphans", NULL, NULL, NULL, 0);
-			aim_ssi_delbuddy(sess, cur->name, NULL);
-		}
-		cur = next;
-	}
-
-	/* Check if there are empty groups and delete them */
-	cur = sess->ssi.local;
-	while (cur) {
-		next = cur->next;
-		if (cur->type == AIM_SSI_TYPE_GROUP) {
-			aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c8, 1);
-			if (!tlv || !tlv->length)
-				aim_ssi_itemlist_del(&sess->ssi.local, cur);
-		}
-		cur = next;
-	}
-
-	/* Check if the master group is empty */
-	if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data))
-		aim_ssi_itemlist_del(&sess->ssi.local, cur);
-
-	return 0;
-}
-
-/**
- * Add a buddy to the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item.
- * @param group The group of the item.
- * @param alias The alias/nickname of the item, or NULL.
- * @param comment The buddy comment for the item, or NULL.
- * @param smsnum The locally assigned SMS number, or NULL.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_addbuddy(aim_session_t *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth)
-{
-	struct aim_ssi_item *parent;
-	aim_tlvlist_t *data = NULL;
-
-	if (!sess || !name || !group)
-		return -EINVAL;
-
-	/* Find the parent */
-	if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
-		/* Find the parent's parent (the master group) */
-		if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)))
-			if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL)))
-				return -ENOMEM;
-		/* Add the parent */
-		if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL)))
-			return -ENOMEM;
-
-		/* Modify the parent's parent (the master group) */
-		aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
-	}
-
-	/* Create a TLV list for the new buddy */
-	if (needauth)
-		aim_tlvlist_add_noval(&data, 0x0066);
-	if (alias)
-		aim_tlvlist_add_raw(&data, 0x0131, strlen(alias), alias);
-	if (smsnum)
-		aim_tlvlist_add_raw(&data, 0x013a, strlen(smsnum), smsnum);
-	if (comment)
-		aim_tlvlist_add_raw(&data, 0x013c, strlen(comment), comment);
-
-	/* Add that bad boy */
-	aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
-	aim_tlvlist_free(&data);
-
-	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Add a permit buddy to the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item..
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_addpermit(aim_session_t *sess, const char *name)
-{
-
-	if (!sess || !name)
-		return -EINVAL;
-
-	/* Add that bad boy */
-	aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Add a deny buddy to the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item..
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_adddeny(aim_session_t *sess, const char *name)
-{
-
-	if (!sess || !name)
-		return -EINVAL;
-
-	/* Add that bad boy */
-	aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Deletes a buddy from the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item, or NULL.
- * @param group The group of the item, or NULL.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group)
-{
-	struct aim_ssi_item *del;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the buddy */
-	if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
-		return -EINVAL;
-
-	/* Remove the item from the list */
-	aim_ssi_itemlist_del(&sess->ssi.local, del);
-
-	/* Modify the parent group */
-	aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group);
-
-	/* Check if we should delete the parent group */
-	if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) {
-		aim_ssi_itemlist_del(&sess->ssi.local, del);
-
-		/* Modify the parent group */
-		aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL);
-
-		/* Check if we should delete the parent's parent (the master group) */
-		if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) {
-			aim_ssi_itemlist_del(&sess->ssi.local, del);
-		}
-	}
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Deletes a permit buddy from the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item, or NULL.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name)
-{
-	struct aim_ssi_item *del;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the item */
-	if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT)))
-		return -EINVAL;
-
-	/* Remove the item from the list */
-	aim_ssi_itemlist_del(&sess->ssi.local, del);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Deletes a deny buddy from the list.
- *
- * @param sess The oscar session.
- * @param name The name of the item, or NULL.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name)
-{
-	struct aim_ssi_item *del;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the item */
-	if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))
-		return -EINVAL;
-
-	/* Remove the item from the list */
-	aim_ssi_itemlist_del(&sess->ssi.local, del);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Move a buddy from one group to another group.  This basically just deletes the 
- * buddy and re-adds it.
- *
- * @param sess The oscar session.
- * @param oldgn The group that the buddy is currently in.
- * @param newgn The group that the buddy should be moved in to.
- * @param sn The name of the buddy to be moved.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn)
-{
-	aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn));
-	aim_ssi_delbuddy(sess, sn, oldgn);
-	return 0;
-}
-
-/**
- * Change the alias stored on the server for a given buddy.
- *
- * @param sess The oscar session.
- * @param gn The group that the buddy is currently in.
- * @param sn The screen name of the buddy.
- * @param alias The new alias for the buddy, or NULL if you want to remove 
- *        a buddy's comment.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias)
-{
-	struct aim_ssi_item *tmp;
-
-	if (!sess || !gn || !sn)
-		return -EINVAL;
-
-	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
-		return -EINVAL;
-
-	/* Either add or remove the 0x0131 TLV from the TLV chain */
-	if ((alias != NULL) && (strlen(alias) > 0))
-		aim_tlvlist_replace_raw(&tmp->data, 0x0131, strlen(alias), alias);
-	else
-		aim_tlvlist_remove(&tmp->data, 0x0131);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Change the comment stored on the server for a given buddy.
- *
- * @param sess The oscar session.
- * @param gn The group that the buddy is currently in.
- * @param sn The screen name of the buddy.
- * @param alias The new comment for the buddy, or NULL if you want to remove 
- *        a buddy's comment.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_editcomment(aim_session_t *sess, const char *gn, const char *sn, const char *comment)
-{
-	struct aim_ssi_item *tmp;
-
-	if (!sess || !gn || !sn)
-		return -EINVAL;
-
-	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
-		return -EINVAL;
-
-	/* Either add or remove the 0x0131 TLV from the TLV chain */
-	if ((comment != NULL) && (strlen(comment) > 0))
-		aim_tlvlist_replace_raw(&tmp->data, 0x013c, strlen(comment), comment);
-	else
-		aim_tlvlist_remove(&tmp->data, 0x013c);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Rename a group.
- *
- * @param sess The oscar session.
- * @param oldgn The old group name.
- * @param newgn The new group name.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn)
-{
-	struct aim_ssi_item *group;
-
-	if (!sess || !oldgn || !newgn)
-		return -EINVAL;
-
-	if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
-		return -EINVAL;
-
-	free(group->name);
-	group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));
-	strcpy(group->name, newgn);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Stores your permit/deny setting on the server, and starts using it.
- *
- * @param sess The oscar session.
- * @param permdeny Your permit/deny setting.  Can be one of the following:
- *        1 - Allow all users
- *        2 - Block all users
- *        3 - Allow only the users below
- *        4 - Block only the users below
- *        5 - Allow only users on my buddy list
- * @param vismask A bitmask of the class of users to whom you want to be 
- *        visible.  See the AIM_FLAG_BLEH #defines in aim.h
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask)
-{
-	struct aim_ssi_item *tmp;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the PDINFO item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO)))
-		tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
-
-	/* Need to add the 0x00ca TLV to the TLV chain */
-	aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);
-
-	/* Need to add the 0x00cb TLV to the TLV chain */
-	aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/**
- * Set buddy icon information
- *
- * @param sess The oscar session.
- * @param iconcsum The MD5 checksum of the icon you are using.
- * @param iconcsumlen Length of the MD5 checksum given above.  Should be 0x10 bytes.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen)
-{
-	struct aim_ssi_item *tmp;
-	fu8_t *csumdata;
-
-	if (!sess || !iconsum || !iconsumlen)
-		return -EINVAL;
-
-	/* Find the ICONINFO item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
-		tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL);
-	}
-
-	/* Need to add the 0x00d5 TLV to the TLV chain */
-	if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t))))
-		return -ENOMEM;
-	csumdata[0] = 0x00;
-	csumdata[1] = 0x10;
-	memcpy(&csumdata[2], iconsum, iconsumlen);
-	aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata);
-	free(csumdata);
-
-	/* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */
-	aim_tlvlist_replace_noval(&tmp->data, 0x0131);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-	return 0;
-}
-
-/**
- * Remove a reference to a server stored buddy icon.  This will make your 
- * icon stop showing up to other people.
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_delicon(aim_session_t *sess)
-{
-	struct aim_ssi_item *tmp;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the ICONINFO item and delete it if it exists*/
-	if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO)))
-		aim_ssi_itemlist_del(&sess->ssi.local, tmp);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-	return 0;
-}
-
-/**
- * Stores your setting for whether you should show up as idle or not.
- *
- * @param sess The oscar session.
- * @param presence I think it's a bitmask, but I only know what one of the bits is:
- *        0x00000002 - Hide wireless?
- *        0x00000400 - Allow others to see your idle time
- * @return Return 0 if no errors, otherwise return the error number.
- */
-faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) {
-	struct aim_ssi_item *tmp;
-
-	if (!sess)
-		return -EINVAL;
-
-	/* Find the PRESENCEPREFS item, or add it if it does not exist */
-	if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS)))
-		tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
-
-	/* Need to add the x00c9 TLV to the TLV chain */
-	aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence);
-
-	/* Sync our local list with the server list */
-	aim_ssi_sync(sess);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0002 - Request SSI Rights.
- */
-faim_export int aim_ssi_reqrights(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
-}
-
-/*
- * Subtype 0x0003 - SSI Rights Information.
- */
-static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0, i;
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	aim_tlv_t *tlv;
-	aim_bstream_t bstream;
-	fu16_t *maxitems;
-
-	/* This SNAC is made up of a bunch of TLVs */
-	tlvlist = aim_tlvlist_read(bs);
-
-	/* TLV 0x0004 contains the maximum number of each item */
-	if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-		aim_tlvlist_free(&tlvlist);
-		return 0;
-	}
-
-	aim_bstream_init(&bstream, tlv->value, tlv->length);
-
-	if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {
-		aim_tlvlist_free(&tlvlist);
-		return 0;
-	}
-
-	for (i=0; i<(tlv->length/2); i++)
-		maxitems[i] = aimbs_get16(&bstream);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, tlv->length/2, maxitems);
-
-	aim_tlvlist_free(&tlvlist);
-	free(maxitems);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and 
- * revision number.
- * 
- */
-faim_export int aim_ssi_reqdata(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	/* Free any current data, just in case */
-	aim_ssi_freelist(sess);
-
-	return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);
-}
-
-/*
- * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision 
- * number.
- *
- * The data will only be sent if it is newer than the posted local
- * timestamp and revision.
- * 
- * Note that the client should never increment the revision, only the server.
- * 
- */
-faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);
-	aimbs_put32(&fr->data, timestamp);
-	aimbs_put16(&fr->data, numitems);
-
-	aim_tx_enqueue(sess, fr);
-
-	/* Free any current data, just in case */
-	aim_ssi_freelist(sess);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0006 - SSI Data.
- */
-static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu8_t fmtver; /* guess */
-	fu16_t namelen, gid, bid, type;
-	char *name;
-	aim_tlvlist_t *data;
-
-	fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */
-	sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */
-
-	/* Read in the list */
-	while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */
-		if ((namelen = aimbs_get16(bs)))
-			name = aimbs_getstr(bs, namelen);
-		else
-			name = NULL;
-		gid = aimbs_get16(bs);
-		bid = aimbs_get16(bs);
-		type = aimbs_get16(bs);
-		data = aim_tlvlist_readlen(bs, aimbs_get16(bs));
-		aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
-		free(name);
-		aim_tlvlist_free(&data);
-	}
-
-	/* Read in the timestamp */
-	sess->ssi.timestamp = aimbs_get32(bs);
-
-	if (!(snac->flags & 0x0001)) {
-		/* Make a copy of the list */
-		struct aim_ssi_item *cur;
-		for (cur=sess->ssi.official; cur; cur=cur->next)
-			aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
-
-		sess->ssi.received_data = 1;
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x0007 - SSI Activate Data.
- *
- * Should be sent after receiving 13/6 or 13/f to tell the server you
- * are ready to begin using the list.  It will promptly give you the
- * presence information for everyone in your list and put your permit/deny
- * settings into effect.
- * 
- */
-faim_export int aim_ssi_enable(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
-}
-
-/*
- * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s).
- *
- * Sends the SNAC to add, modify, or delete an item from the server-stored
- * information.  These 3 SNACs all have an identical structure.  The only
- * difference is the subtype that is set for the SNAC.
- * 
- */
-faim_export int aim_ssi_addmoddel(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int snaclen;
-	struct aim_ssi_tmp *cur;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item)
-		return -EINVAL;
-
-	/* Calculate total SNAC size */
-	snaclen = 10; /* For family, subtype, flags, and SNAC ID */
-	for (cur=sess->ssi.pending; cur; cur=cur->next) {
-		snaclen += 10; /* For length, GID, BID, type, and length */
-		if (cur->item->name)
-			snaclen += strlen(cur->item->name);
-		if (cur->item->data)
-			snaclen += aim_tlvlist_size(&cur->item->data);
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid);
-
-	for (cur=sess->ssi.pending; cur; cur=cur->next) {
-		aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0);
-		if (cur->item->name)
-			aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name));
-		aimbs_put16(&fr->data, cur->item->gid);
-		aimbs_put16(&fr->data, cur->item->bid);
-		aimbs_put16(&fr->data, cur->item->type);
-		aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0);
-		if (cur->item->data)
-			aim_tlvlist_write(&fr->data, &cur->item->data);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0008 - Incoming SSI add.
- *
- * XXX - It would probably be good for the client to actually do something when it gets this.
- */
-static int parseadd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	char *name;
-	fu16_t len, gid, bid, type;
-	aim_tlvlist_t *data;
-
-	while (aim_bstream_empty(bs)) {
-		if ((len = aimbs_get16(bs)))
-			name = aimbs_getstr(bs, len);
-		else
-			name = NULL;
-		gid = aimbs_get16(bs);
-		bid = aimbs_get16(bs);
-		type = aimbs_get16(bs);
-		if ((len = aimbs_get16(bs)))
-			data = aim_tlvlist_readlen(bs, len);
-		else
-			data = NULL;
-
-		aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data);
-		aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
-		aim_tlvlist_free(&data);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx);
-
-		free(name);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x0009 - Incoming SSI mod.
- *
- * XXX - It would probably be good for the client to actually do something when it gets this.
- */
-static int parsemod(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	char *name;
-	fu16_t len, gid, bid, type;
-	aim_tlvlist_t *data;
-	struct aim_ssi_item *item;
-
-	while (aim_bstream_empty(bs)) {
-		if ((len = aimbs_get16(bs)))
-			name = aimbs_getstr(bs, len);
-		else
-			name = NULL;
-		gid = aimbs_get16(bs);
-		bid = aimbs_get16(bs);
-		type = aimbs_get16(bs);
-		if ((len = aimbs_get16(bs)))
-			data = aim_tlvlist_readlen(bs, len);
-		else
-			data = NULL;
-
-		/* Replace the 2 local items with the given one */
-		if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) {
-			item->type = type;
-			free(item->name);
-			if (name) {
-				item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
-				strcpy(item->name, name);
-			} else
-				item->name = NULL;
-			aim_tlvlist_free(&item->data);
-			item->data = aim_tlvlist_copy(data);
-		}
-
-		if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) {
-			item->type = type;
-			free(item->name);
-			if (name) {
-				item->name = (char *)malloc((strlen(name)+1)*sizeof(char));
-				strcpy(item->name, name);
-			} else
-				item->name = NULL;
-			aim_tlvlist_free(&item->data);
-			item->data = aim_tlvlist_copy(data);
-		}
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx);
-
-		free(name);
-		aim_tlvlist_free(&data);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x000a - Incoming SSI del.
- *
- * XXX - It would probably be good for the client to actually do something when it gets this.
- */
-static int parsedel(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t gid, bid;
-	struct aim_ssi_item *del;
-
-	while (aim_bstream_empty(bs)) {
-		aim_bstream_advance(bs, aimbs_get16(bs));
-		gid = aimbs_get16(bs);
-		bid = aimbs_get16(bs);
-		aimbs_get16(bs);
-		aim_bstream_advance(bs, aimbs_get16(bs));
-
-		if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid)))
-			aim_ssi_itemlist_del(&sess->ssi.local, del);
-		if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid)))
-			aim_ssi_itemlist_del(&sess->ssi.official, del);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-			ret = userfunc(sess, rx);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x000e - SSI Add/Mod/Del Ack.
- *
- * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel).
- *
- */
-static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	struct aim_ssi_tmp *cur, *del;
-
-	/* Read in the success/failure flags from the ack SNAC */
-	cur = sess->ssi.pending;
-	while (cur && (aim_bstream_empty(bs)>0)) {
-		cur->ack = aimbs_get16(bs);
-		cur = cur->next;
-	}
-
-	/*
-	 * If outcome is 0, then add the item to the item list, or replace the other item, 
-	 * or remove the old item.  If outcome is non-zero, then remove the item from the 
-	 * local list, or unmodify it, or add it.
-	 */
-	for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) {
-	if (cur->item) {
-		if (cur->ack) {
-			/* Our action was unsuccessful, so change the local list back to how it was */
-			if (cur->action == AIM_CB_SSI_ADD) {
-				/* Remove the item from the local list */
-				/* Make sure cur->item is still valid memory */
-				if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
-					if (cur->item->name) {
-						cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
-						strcpy(cur->name, cur->item->name);
-					}
-					aim_ssi_itemlist_del(&sess->ssi.local, cur->item);
-				}
-				cur->item = NULL;
-
-			} else if (cur->action == AIM_CB_SSI_MOD) {
-				/* Replace the local item with the item from the official list */
-				if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
-					struct aim_ssi_item *cur1;
-					if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
-						free(cur->item->name);
-						if (cur1->name) {
-							cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char));
-							strcpy(cur->item->name, cur1->name);
-						} else
-							cur->item->name = NULL;
-						aim_tlvlist_free(&cur->item->data);
-						cur->item->data = aim_tlvlist_copy(cur1->data);
-					}
-				} else
-					cur->item = NULL;
-
-			} else if (cur->action == AIM_CB_SSI_DEL) {
-				/* Add the item back into the local list */
-				if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) {
-					aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
-				} else
-					cur->item = NULL;
-			}
-
-		} else {
-			/* Do the exact opposite */
-			if (cur->action == AIM_CB_SSI_ADD) {
-			/* Add the local item to the official list */
-				if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
-					aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
-				} else
-					cur->item = NULL;
-
-			} else if (cur->action == AIM_CB_SSI_MOD) {
-				/* Replace the official item with the item from the local list */
-				if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) {
-					struct aim_ssi_item *cur1;
-					if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) {
-						free(cur1->name);
-						if (cur->item->name) {
-							cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char));
-							strcpy(cur1->name, cur->item->name);
-						} else
-							cur1->name = NULL;
-						aim_tlvlist_free(&cur1->data);
-						cur1->data = aim_tlvlist_copy(cur->item->data);
-					}
-				} else
-					cur->item = NULL;
-
-			} else if (cur->action == AIM_CB_SSI_DEL) {
-				/* Remove the item from the official list */
-				if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item))
-					aim_ssi_itemlist_del(&sess->ssi.official, cur->item);
-				cur->item = NULL;
-			}
-
-		}
-	} /* End if (cur->item) */
-	} /* End for loop */
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sess->ssi.pending);
-
-	/* Free all aim_ssi_tmp's with an outcome */
-	cur = sess->ssi.pending;
-	while (cur && (cur->ack != 0xffff)) {
-		del = cur;
-		cur = cur->next;
-		free(del->name);
-		free(del);
-	}
-	sess->ssi.pending = cur;
-
-	/* If we're not waiting for any more acks, then send more SNACs */
-	if (!sess->ssi.pending) {
-		sess->ssi.pending = NULL;
-		sess->ssi.waiting_for_ack = 0;
-		aim_ssi_sync(sess);
-	}
-
-	return ret;
-}
-
-/*
- * Subtype 0x000f - SSI Data Unchanged.
- *
- * Response to aim_ssi_reqifchanged() if the server-side data is not newer than
- * posted local stamp/revision.
- *
- */
-static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-
-	sess->ssi.received_data = 1;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0011 - SSI Begin Data Modification.
- *
- * Tells the server you're going to start modifying data.
- * 
- */
-faim_export int aim_ssi_modbegin(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
-}
-
-/*
- * Subtype 0x0012 - SSI End Data Modification.
- *
- * Tells the server you're finished modifying data.
- *
- */
-faim_export int aim_ssi_modend(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
-		return -EINVAL;
-
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
-}
-
-/*
- * Subtype 0x0014 - Grant authorization
- *
- * Authorizes a contact so they can add you to their contact list.
- *
- */
-faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid);
-
-	/* Screen name */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	/* Message (null terminated) */
-	aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
-	if (msg) {
-		aimbs_putraw(&fr->data, msg, strlen(msg));
-		aimbs_put8(&fr->data, 0x00);
-	}
-
-	/* Unknown */
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0015 - Receive an authorization grant
- */
-static int receiveauthgrant(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t tmp;
-	char *sn, *msg;
-
-	/* Read screen name */
-	if ((tmp = aimbs_get8(bs)))
-		sn = aimbs_getstr(bs, tmp);
-	else
-		sn = NULL;
-
-	/* Read message (null terminated) */
-	if ((tmp = aimbs_get16(bs)))
-		msg = aimbs_getstr(bs, tmp);
-	else
-		msg = NULL;
-
-	/* Unknown */
-	tmp = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sn, msg);
-
-	free(sn);
-	free(msg);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0018 - Send authorization request
- *
- * Sends a request for authorization to the given contact.  The request will either be
- * granted, denied, or dropped.
- *
- */
-faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);
-
-	/* Screen name */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	/* Message (null terminated) */
-	aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
-	if (msg) {
-		aimbs_putraw(&fr->data, msg, strlen(msg));
-		aimbs_put8(&fr->data, 0x00);
-	}
-
-	/* Unknown */
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0019 - Receive an authorization request
- */
-static int receiveauthrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t tmp;
-	char *sn, *msg;
-
-	/* Read screen name */
-	if ((tmp = aimbs_get8(bs)))
-		sn = aimbs_getstr(bs, tmp);
-	else
-		sn = NULL;
-
-	/* Read message (null terminated) */
-	if ((tmp = aimbs_get16(bs)))
-		msg = aimbs_getstr(bs, tmp);
-	else
-		msg = NULL;
-
-	/* Unknown */
-	tmp = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sn, msg);
-
-	free(sn);
-	free(msg);
-
-	return ret;
-}
-
-/*
- * Subtype 0x001a - Send authorization reply
- *
- * Sends a reply to a request for authorization.  The reply can either 
- * grant authorization or deny authorization.
- *
- * if reply=0x00 then deny
- * if reply=0x01 then grant
- *
- */
-faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
-		return -EINVAL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);
-
-	/* Screen name */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, sn, strlen(sn));
-
-	/* Grant or deny */
-	aimbs_put8(&fr->data, reply);
-
-	/* Message (null terminated) */
-	aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0);
-	if (msg) {
-		aimbs_putraw(&fr->data, msg, strlen(msg));
-		aimbs_put8(&fr->data, 0x00);
-	}
-
-	/* Unknown */
-	aimbs_put16(&fr->data, 0x0000);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x001b - Receive an authorization reply
- * You get this bad boy when other people respond to the authorization 
- * request that you have previously sent them.
- */
-static int receiveauthreply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t tmp;
-	fu8_t reply;
-	char *sn, *msg;
-
-	/* Read screen name */
-	if ((tmp = aimbs_get8(bs)))
-		sn = aimbs_getstr(bs, tmp);
-	else
-		sn = NULL;
-
-	/* Read reply */
-	reply = aimbs_get8(bs);
-
-	/* Read message (null terminated) */
-	if ((tmp = aimbs_get16(bs)))
-		msg = aimbs_getstr(bs, tmp);
-	else
-		msg = NULL;
-
-	/* Unknown */
-	tmp = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sn, reply, msg);
-
-	free(sn);
-	free(msg);
-
-	return ret;
-}
-
-/*
- * Subtype 0x001c - Receive a message telling you someone added you to their list.
- */
-static int receiveadded(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t tmp;
-	char *sn;
-
-	/* Read screen name */
-	if ((tmp = aimbs_get8(bs)))
-		sn = aimbs_getstr(bs, tmp);
-	else
-		sn = NULL;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, sn);
-
-	free(sn);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == AIM_CB_SSI_RIGHTSINFO)
-		return parserights(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_LIST)
-		return parsedata(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_ADD)
-		return parseadd(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_MOD)
-		return parsemod(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_DEL)
-		return parsedel(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_SRVACK)
-		return parseack(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_NOLIST)
-		return parsedataunchanged(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_RECVAUTH)
-		return receiveauthgrant(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_RECVAUTHREQ)
-		return receiveauthrequest(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_RECVAUTHREP)
-		return receiveauthreply(sess, mod, rx, snac, bs);
-	else if (snac->subtype == AIM_CB_SSI_ADDED)
-		return receiveadded(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-static void ssi_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	aim_ssi_freelist(sess);
-}
-
-faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = AIM_CB_FAM_SSI;
-	mod->version = 0x0004;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "ssi", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = ssi_shutdown;
-
-	return 0;
-}
Index: bfaim/stamp-h
===================================================================
--- libfaim/stamp-h	(revision 5e53c4a15eca8b264df0aedf726d4545bc5b4b46)
+++ 	(revision )
@@ -1,1 +1,0 @@
-timestamp
Index: bfaim/stats.c
===================================================================
--- libfaim/stats.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Family 0x000b - Statistics.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	fu16_t interval;
-
-	interval = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-		ret = userfunc(sess, rx, interval);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0002)
-		return reportinterval(sess, mod, rx, snac, bs);
-
-	return 0;
-}
-
-faim_internal int stats_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000b;
-	mod->version = 0x0001;
-	mod->toolid = 0x0104;
-	mod->toolversion = 0x0001;
-	mod->flags = 0;
-	strncpy(mod->name, "stats", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: bfaim/tlv.c
===================================================================
--- libfaim/tlv.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,823 +1,0 @@
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-static aim_tlv_t *createtlv(fu16_t type, fu16_t length, fu8_t *value)
-{
-	aim_tlv_t *ret;
-
-	if (!(ret = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
-		return NULL;
-	ret->type = type;
-	ret->length = length;
-	ret->value = value;
-
-	return ret;
-}
-
-static void freetlv(aim_tlv_t **oldtlv)
-{
-
-	if (!oldtlv || !*oldtlv)
-		return;
-	
-	free((*oldtlv)->value);
-	free(*oldtlv);
-	*oldtlv = NULL;
-
-	return;
-}
-
-/**
- * Read a TLV chain from a buffer.
- *
- * Reads and parses a series of TLV patterns from a data buffer; the
- * returned structure is manipulatable with the rest of the TLV
- * routines.  When done with a TLV chain, aim_tlvlist_free() should
- * be called to free the dynamic substructures.
- *
- * XXX There should be a flag setable here to have the tlvlist contain
- * bstream references, so that at least the ->value portion of each 
- * element doesn't need to be malloc/memcpy'd.  This could prove to be
- * just as effecient as the in-place TLV parsing used in a couple places
- * in libfaim.
- *
- * @param bs Input bstream
- */
-faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs)
-{
-	aim_tlvlist_t *list = NULL, *cur;
-	
-	while (aim_bstream_empty(bs) > 0) {
-		fu16_t type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-#if 0 /* temporarily disabled until I know if they're still doing it or not */
-		/*
-		 * Okay, so now AOL has decided that any TLV of
-		 * type 0x0013 can only be two bytes, despite
-		 * what the actual given length is.  So here 
-		 * we dump any invalid TLVs of that sort.  Hopefully
-		 * theres no special cases to this special case.
-		 *   - mid (30jun2000)
-		 */
-		if ((type == 0x0013) && (length != 0x0002))
-			length = 0x0002;
-#else
-		if (0)
-			;
-#endif
-		else {
-
-			if (length > aim_bstream_empty(bs)) {
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-
-			cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
-			if (!cur) {
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-
-			memset(cur, 0, sizeof(aim_tlvlist_t));
-
-			cur->tlv = createtlv(type, length, NULL);
-			if (!cur->tlv) {
-				free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-			if (cur->tlv->length > 0) {
-				cur->tlv->value = aimbs_getraw(bs, length);	
-				if (!cur->tlv->value) {
-					freetlv(&cur->tlv);
-					free(cur);
-					aim_tlvlist_free(&list);
-					return NULL;
-				}
-			}
-
-			cur->next = list;
-			list = cur;
-		}
-	}
-
-	return list;
-}
-
-/**
- * Read a TLV chain from a buffer.
- *
- * Reads and parses a series of TLV patterns from a data buffer; the
- * returned structure is manipulatable with the rest of the TLV
- * routines.  When done with a TLV chain, aim_tlvlist_free() should
- * be called to free the dynamic substructures.
- *
- * XXX There should be a flag setable here to have the tlvlist contain
- * bstream references, so that at least the ->value portion of each 
- * element doesn't need to be malloc/memcpy'd.  This could prove to be
- * just as effecient as the in-place TLV parsing used in a couple places
- * in libfaim.
- *
- * @param bs Input bstream
- * @param num The max number of TLVs that will be read, or -1 if unlimited.  
- *        There are a number of places where you want to read in a tlvchain, 
- *        but the chain is not at the end of the SNAC, and the chain is 
- *        preceeded by the number of TLVs.  So you can limit that with this.
- */
-faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num)
-{
-	aim_tlvlist_t *list = NULL, *cur;
-
-	while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
-		fu16_t type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		if (length > aim_bstream_empty(bs)) {
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-
-		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
-		if (!cur) {
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-
-		memset(cur, 0, sizeof(aim_tlvlist_t));
-
-		cur->tlv = createtlv(type, length, NULL);
-		if (!cur->tlv) {
-			free(cur);
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = aimbs_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		if (num > 0)
-			num--;
-		cur->next = list;
-		list = cur;
-	}
-
-	return list;
-}
-
-/**
- * Read a TLV chain from a buffer.
- *
- * Reads and parses a series of TLV patterns from a data buffer; the
- * returned structure is manipulatable with the rest of the TLV
- * routines.  When done with a TLV chain, aim_tlvlist_free() should
- * be called to free the dynamic substructures.
- *
- * XXX There should be a flag setable here to have the tlvlist contain
- * bstream references, so that at least the ->value portion of each 
- * element doesn't need to be malloc/memcpy'd.  This could prove to be
- * just as effecient as the in-place TLV parsing used in a couple places
- * in libfaim.
- *
- * @param bs Input bstream
- * @param len The max length in bytes that will be read.
- *        There are a number of places where you want to read in a tlvchain, 
- *        but the chain is not at the end of the SNAC, and the chain is 
- *        preceeded by the length of the TLVs.  So you can limit that with this.
- */
-faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len)
-{
-	aim_tlvlist_t *list = NULL, *cur;
-
-	while ((aim_bstream_empty(bs) > 0) && (len > 0)) {
-		fu16_t type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		if (length > aim_bstream_empty(bs)) {
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-
-		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
-		if (!cur) {
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-
-		memset(cur, 0, sizeof(aim_tlvlist_t));
-
-		cur->tlv = createtlv(type, length, NULL);
-		if (!cur->tlv) {
-			free(cur);
-			aim_tlvlist_free(&list);
-			return NULL;
-		}
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = aimbs_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		len -= aim_tlvlist_size(&cur);
-		cur->next = list;
-		list = cur;
-	}
-
-	return list;
-}
-
-/**
- * Duplicate a TLV chain.
- * This is pretty pelf exslanatory.
- *
- * @param orig The TLV chain you want to make a copy of.
- * @return A newly allocated TLV chain.
- */
-faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig)
-{
-	aim_tlvlist_t *new = NULL;
-
-	while (orig) {
-		aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
-		orig = orig->next;
-	}
-
-	return new;
-}
-
-/*
- * Compare two TLV lists for equality.  This probably is not the most 
- * efficient way to do this.
- *
- * @param one One of the TLV chains to compare.
- * @param two The other TLV chain to compare.
- * @preturn Retrun 0 if the lists are the same, return 1 if they are different.
- */
-faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two)
-{
-	aim_bstream_t bs1, bs2;
-
-	if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))
-		return 1;
-
-	aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_tlvlist_size(&one)*sizeof(fu8_t))), aim_tlvlist_size(&one));
-	aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_tlvlist_size(&two)*sizeof(fu8_t))), aim_tlvlist_size(&two));
-
-	aim_tlvlist_write(&bs1, &one);
-	aim_tlvlist_write(&bs2, &two);
-
-	if (memcmp(bs1.data, bs2.data, bs1.len)) {
-		free(bs1.data);
-		free(bs2.data);
-		return 1;
-	}
-
-	free(bs1.data);
-	free(bs2.data);
-
-	return 0;
-}
-
-/**
- * Free a TLV chain structure
- * @list: Chain to be freed
- *
- * Walks the list of TLVs in the passed TLV chain and
- * frees each one. Note that any references to this data
- * should be removed before calling this.
- *
- */
-faim_internal void aim_tlvlist_free(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-
-	if (!list || !*list)
-		return;
-
-	for (cur = *list; cur; ) {
-		aim_tlvlist_t *tmp;
-		
-		freetlv(&cur->tlv);
-
-		tmp = cur->next;
-		free(cur);
-		cur = tmp;
-	}
-
-	list = NULL;
-
-	return;
-}
-
-/**
- * Count the number of TLVs in a chain.
- *
- * @param list Chain to be counted.
- * @return The number of TLVs stored in the passed chain.
- */
-faim_internal int aim_tlvlist_count(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-	int count;
-
-	if (!list || !*list)
-		return 0;
-
-	for (cur = *list, count = 0; cur; cur = cur->next)
-		count++;
-
-	return count;
-}
-
-/**
- * Count the number of bytes in a TLV chain.
- *
- * @param list Chain to be sized
- * @return The number of bytes that would be needed to 
- *         write the passed TLV chain to a data buffer.
- */
-faim_internal int aim_tlvlist_size(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-	int size;
-
-	if (!list || !*list)
-		return 0;
-
-	for (cur = *list, size = 0; cur; cur = cur->next)
-		size += (4 + cur->tlv->length);
-
-	return size;
-}
-
-/**
- * Adds the passed string as a TLV element of the passed type
- * to the TLV chain.
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- * @length Length of string to add (not including %NULL).
- * @value String to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
-{
-	aim_tlvlist_t *newtlv, *cur;
-
-	if (list == NULL)
-		return 0;
-
-	if (!(newtlv = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t))))
-		return 0;
-	memset(newtlv, 0x00, sizeof(aim_tlvlist_t));
-
-	if (!(newtlv->tlv = createtlv(type, length, NULL))) {
-		free(newtlv);
-		return 0;
-	}
-	if (newtlv->tlv->length > 0) {
-		newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length);
-		memcpy(newtlv->tlv->value, value, newtlv->tlv->length);
-	}
-
-	if (!*list)
-		*list = newtlv;
-	else {
-		for(cur = *list; cur->next; cur = cur->next)
-			;
-		cur->next = newtlv;
-	}
-
-	return newtlv->tlv->length;
-}
-
-/**
- * Add a one byte integer to a TLV chain.
- *
- * @param list Destination chain.
- * @param type TLV type to add.
- * @param value Value to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
-{
-	fu8_t v8[1];
-
-	aimutil_put8(v8, value);
-
-	return aim_tlvlist_add_raw(list, type, 1, v8);
-}
-
-/**
- * Add a two byte integer to a TLV chain.
- *
- * @param list Destination chain.
- * @param type TLV type to add.
- * @param value Value to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value)
-{
-	fu8_t v16[2];
-
-	aimutil_put16(v16, value);
-
-	return aim_tlvlist_add_raw(list, type, 2, v16);
-}
-
-/**
- * Add a four byte integer to a TLV chain.
- *
- * @param list Destination chain.
- * @param type TLV type to add.
- * @param value Value to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
-{
-	fu8_t v32[4];
-
-	aimutil_put32(v32, value);
-
-	return aim_tlvlist_add_raw(list, type, 4, v32);
-}
-
-/**
- * Adds a block of capability blocks to a TLV chain. The bitfield
- * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
- *
- *     %AIM_CAPS_BUDDYICON   Supports Buddy Icons
- *     %AIM_CAPS_VOICE       Supports Voice Chat
- *     %AIM_CAPS_IMIMAGE     Supports DirectIM/IMImage
- *     %AIM_CAPS_CHAT        Supports Chat
- *     %AIM_CAPS_GETFILE     Supports Get File functions
- *     %AIM_CAPS_SENDFILE    Supports Send File functions
- *
- * @param list Destination chain
- * @param type TLV type to add
- * @param caps Bitfield of capability flags to send
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const fu16_t type, const fu32_t caps)
-{
-	fu8_t buf[16*16]; /* XXX icky fixed length buffer */
-	aim_bstream_t bs;
-
-	if (!caps)
-		return 0; /* nothing there anyway */
-
-	aim_bstream_init(&bs, buf, sizeof(buf));
-
-	aim_putcap(&bs, caps);
-
-	return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
-}
-
-/**
- * Adds the given userinfo struct to a TLV chain.
- *
- * @param list Destination chain.
- * @param type TLV type to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *userinfo)
-{
-	fu8_t buf[1024]; /* bleh */
-	aim_bstream_t bs;
-
-	aim_bstream_init(&bs, buf, sizeof(buf));
-
-	aim_putuserinfo(&bs, userinfo);
-
-	return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
-}
-
-/**
- * Adds a TLV with a zero length to a TLV chain.
- *
- * @param list Destination chain.
- * @param type TLV type to add.
- * @retun The size of the value added.
- */
-faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const fu16_t type)
-{
-	return aim_tlvlist_add_raw(list, type, 0, NULL);
-}
-
-/*
- * Note that the inner TLV chain will not be modifiable as a tlvchain once
- * it is written using this.  Or rather, it can be, but updates won't be
- * made to this.
- *
- * XXX should probably support sublists for real.
- * 
- * This is so neat.
- *
- */
-faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
-{
-	fu8_t *buf;
-	int buflen;
-	aim_bstream_t bs;
-
-	buflen = aim_tlvlist_size(tl);
-
-	if (buflen <= 0)
-		return 0;
-
-	if (!(buf = malloc(buflen)))
-		return 0;
-
-	aim_bstream_init(&bs, buf, buflen);
-
-	aim_tlvlist_write(&bs, tl);
-
-	aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
-
-	free(buf);
-
-	return buflen;
-}
-
-/**
- * Substitute a TLV of a given type with a new TLV of the same type.  If 
- * you attempt to replace a TLV that does not exist, this function will 
- * just add a new TLV as if you called aim_tlvlist_add_raw().
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- * @param length Length of string to add (not including %NULL).
- * @param value String to add.
- * @return The length of the TLV.
- */
-faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
-{
-	aim_tlvlist_t *cur;
-
-	if (list == NULL)
-		return 0;
-
-	for (cur = *list; ((cur != NULL) && (cur->tlv->type != type)); cur = cur->next);
-	if (cur == NULL)
-		return aim_tlvlist_add_raw(list, type, length, value);
-
-	free(cur->tlv->value);
-	cur->tlv->length = length;
-	if (cur->tlv->length > 0) {
-		cur->tlv->value = (fu8_t *)malloc(cur->tlv->length);
-		memcpy(cur->tlv->value, value, cur->tlv->length);
-	} else
-		cur->tlv->value = NULL;
-
-	return cur->tlv->length;
-}
-
-/**
- * Substitute a TLV of a given type with a new TLV of the same type.  If 
- * you attempt to replace a TLV that does not exist, this function will 
- * just add a new TLV as if you called aim_tlvlist_add_raw().
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- * @return The length of the TLV.
- */
-faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const fu16_t type)
-{
-	return aim_tlvlist_replace_raw(list, type, 0, NULL);
-}
-
-/**
- * Substitute a TLV of a given type with a new TLV of the same type.  If 
- * you attempt to replace a TLV that does not exist, this function will 
- * just add a new TLV as if you called aim_tlvlist_add_raw().
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- * @param value 8 bit value to add.
- * @return The length of the TLV.
- */
-faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
-{
-	fu8_t v8[1];
-
-	aimutil_put8(v8, value);
-
-	return aim_tlvlist_replace_raw(list, type, 1, v8);
-}
-
-/**
- * Substitute a TLV of a given type with a new TLV of the same type.  If 
- * you attempt to replace a TLV that does not exist, this function will 
- * just add a new TLV as if you called aim_tlvlist_add_raw().
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- * @param value 32 bit value to add.
- * @return The length of the TLV.
- */
-faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
-{
-	fu8_t v32[4];
-
-	aimutil_put32(v32, value);
-
-	return aim_tlvlist_replace_raw(list, type, 4, v32);
-}
-
-/**
- * Remove a TLV of a given type.  If you attempt to remove a TLV that 
- * does not exist, nothing happens.
- *
- * @param list Desination chain (%NULL pointer if empty).
- * @param type TLV type.
- */
-faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const fu16_t type)
-{
-	aim_tlvlist_t *del;
-
-	if (!list || !(*list))
-		return;
-
-	/* Remove the item from the list */
-	if ((*list)->tlv->type == type) {
-		del = *list;
-		*list = (*list)->next;
-	} else {
-		aim_tlvlist_t *cur;
-		for (cur=*list; (cur->next && (cur->next->tlv->type!=type)); cur=cur->next);
-		if (!cur->next)
-			return;
-		del = cur->next;
-		cur->next = del->next;
-	}
-
-	/* Free the removed item */
-	free(del->tlv->value);
-	free(del->tlv);
-	free(del);
-}
-
-/**
- * aim_tlvlist_write - Write a TLV chain into a data buffer.
- * @buf: Destination buffer
- * @buflen: Maximum number of bytes that will be written to buffer
- * @list: Source TLV chain
- *
- * Copies a TLV chain into a raw data buffer, writing only the number
- * of bytes specified. This operation does not free the chain; 
- * aim_tlvlist_free() must still be called to free up the memory used
- * by the chain structures.
- *
- * XXX clean this up, make better use of bstreams 
- */
-faim_internal int aim_tlvlist_write(aim_bstream_t *bs, aim_tlvlist_t **list)
-{
-	int goodbuflen;
-	aim_tlvlist_t *cur;
-
-	/* do an initial run to test total length */
-	goodbuflen = aim_tlvlist_size(list);
-
-	if (goodbuflen > aim_bstream_empty(bs))
-		return 0; /* not enough buffer */
-
-	/* do the real write-out */
-	for (cur = *list; cur; cur = cur->next) {
-		aimbs_put16(bs, cur->tlv->type);
-		aimbs_put16(bs, cur->tlv->length);
-		if (cur->tlv->length)
-			aimbs_putraw(bs, cur->tlv->value, cur->tlv->length);
-	}
-
-	return 1; /* XXX this is a nonsensical return */
-}
-
-
-/**
- * Grab the Nth TLV of type type in the TLV list list.
- *
- * Returns a pointer to an aim_tlv_t of the specified type; 
- * %NULL on error.  The @nth parameter is specified starting at %1.
- * In most cases, there will be no more than one TLV of any type
- * in a chain.
- *
- * @param list Source chain.
- * @param type Requested TLV type.
- * @param nth Index of TLV of type to get.
- * @return The TLV you were looking for, or NULL if one could not be found.
- */
-faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const fu16_t type, const int nth)
-{
-	aim_tlvlist_t *cur;
-	int i;
-
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == type)
-				i++;
-			if (i >= nth)
-				return cur->tlv;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * Retrieve the data from the nth TLV in the given TLV chain as a string.
- *
- * @param list Source TLV chain.
- * @param type TLV type to search for.
- * @param nth Index of TLV to return.
- * @return The value of the TLV you were looking for, or NULL if one could 
- *         not be found.  This is a dynamic buffer and must be freed by the 
- *         caller.
- */
-faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const fu16_t type, const int nth)
-{
-	aim_tlv_t *tlv;
-	char *newstr;
-
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
-		return NULL;
-
-	newstr = (char *) malloc(tlv->length + 1);
-	memcpy(newstr, tlv->value, tlv->length);
-	newstr[tlv->length] = '\0';
-
-	return newstr;
-}
-
-/**
- * Retrieve the data from the nth TLV in the given TLV chain as an 8bit 
- * integer.
- *
- * @param list Source TLV chain.
- * @param type TLV type to search for.
- * @param nth Index of TLV to return.
- * @return The value the TLV you were looking for, or 0 if one could 
- *         not be found.
- */
-faim_internal fu8_t aim_tlv_get8(aim_tlvlist_t *list, const fu16_t type, const int nth)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
-		return 0; /* erm */
-	return aimutil_get8(tlv->value);
-}
-
-/**
- * Retrieve the data from the nth TLV in the given TLV chain as a 16bit 
- * integer.
- *
- * @param list Source TLV chain.
- * @param type TLV type to search for.
- * @param nth Index of TLV to return.
- * @return The value the TLV you were looking for, or 0 if one could 
- *         not be found.
- */
-faim_internal fu16_t aim_tlv_get16(aim_tlvlist_t *list, const fu16_t type, const int nth)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
-		return 0; /* erm */
-	return aimutil_get16(tlv->value);
-}
-
-/**
- * Retrieve the data from the nth TLV in the given TLV chain as a 32bit 
- * integer.
- *
- * @param list Source TLV chain.
- * @param type TLV type to search for.
- * @param nth Index of TLV to return.
- * @return The value the TLV you were looking for, or 0 if one could 
- *         not be found.
- */
-faim_internal fu32_t aim_tlv_get32(aim_tlvlist_t *list, const fu16_t type, const int nth)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
-		return 0; /* erm */
-	return aimutil_get32(tlv->value);
-}
Index: bfaim/translate.c
===================================================================
--- libfaim/translate.c	(revision 862371bb6a5ff5a6491550028e73824b698508bb)
+++ 	(revision )
@@ -1,27 +1,0 @@
-/*
- * Family 0x000c - Translation.
- *
- * I have no idea why this group was issued.  I have never seen anything
- * that uses it.  From what I remember, the last time I tried to poke at
- * the server with this group, it whined about not supporting it.
- *
- * But we advertise it anyway, because its fun.
- * 
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000c;
-	mod->version = 0x0001;
-	mod->toolid = 0x0104;
-	mod->toolversion = 0x0001;
-	mod->flags = 0;
-	strncpy(mod->name, "translate", sizeof(mod->name));
-	mod->snachandler = NULL;
-
-	return 0;
-}
Index: bfaim/txqueue.c
===================================================================
--- libfaim/txqueue.c	(revision cf02dd64c267036375fdf872c3528766fe980d54)
+++ 	(revision )
@@ -1,439 +1,0 @@
-/*
- * txqueue.c
- *
- * Herein lies all the mangement routines for the transmit (Tx) queue.
- *
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-
-#ifndef _WIN32
-#include <sys/socket.h>
-#else
-#include "win32dep.h"
-#endif
-
-/*
- * Allocate a new tx frame.
- *
- * This is more for looks than anything else.
- *
- * Right now, that is.  If/when we implement a pool of transmit
- * frames, this will become the request-an-unused-frame part.
- *
- * framing = AIM_FRAMETYPE_OFT/FLAP
- * chan = channel for FLAP, hdrtype for OFT
- *
- */
-faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen)
-{
-	aim_frame_t *fr;
-
-	if (!conn) {
-		faimdprintf(sess, 0, "aim_tx_new: ERROR: no connection specified\n");
-		return NULL;
-	}
-
-	/* For sanity... */
-	if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) {
-		if (framing != AIM_FRAMETYPE_OFT) {
-			faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for rendezvous connection\n");
-			return NULL;
-		}
-	} else {
-		if (framing != AIM_FRAMETYPE_FLAP) {
-			faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n");
-			return NULL;
-		}
-	}
-
-	if (!(fr = (aim_frame_t *)malloc(sizeof(aim_frame_t))))
-		return NULL;
-	memset(fr, 0, sizeof(aim_frame_t));
-
-	fr->conn = conn; 
-
-	fr->hdrtype = framing;
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-
-		fr->hdr.flap.type = chan;
-
-	} else if (fr->hdrtype == AIM_FRAMETYPE_OFT) {
-
-		fr->hdr.rend.type = chan;
-
-	} else 
-		faimdprintf(sess, 0, "tx_new: unknown framing\n");
-
-	if (datalen > 0) {
-		fu8_t *data;
-
-		if (!(data = (unsigned char *)malloc(datalen))) {
-			aim_frame_destroy(fr);
-			return NULL;
-		}
-
-		aim_bstream_init(&fr->data, data, datalen);
-	}
-
-	return fr;
-}
-
-/*
- * aim_tx_enqeue__queuebased()
- *
- * The overall purpose here is to enqueue the passed in command struct
- * into the outgoing (tx) queue.  Basically...
- *   1) Make a scope-irrelevent copy of the struct
- *   3) Mark as not-sent-yet
- *   4) Enqueue the struct into the list
- *   6) Return
- *
- * Note that this is only used when doing queue-based transmitting;
- * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased.
- *
- */
-static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr)
-{
-
-	if (!fr->conn) {
-		faimdprintf(sess, 1, "aim_tx_enqueue: WARNING: enqueueing packet with no connecetion\n");
-		fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
-	}
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-		/* assign seqnum -- XXX should really not assign until hardxmit */
-		fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
-	}
-
-	fr->handled = 0; /* not sent yet */
-
-	/* see overhead note in aim_rxqueue counterpart */
-	if (!sess->queue_outgoing)
-		sess->queue_outgoing = fr;
-	else {
-		aim_frame_t *cur;
-
-		for (cur = sess->queue_outgoing; cur->next; cur = cur->next)
-			;
-		cur->next = fr;
-	}
-
-	return 0;
-}
-
-/*
- * aim_tx_enqueue__immediate()
- *
- * Parallel to aim_tx_enqueue__queuebased, however, this bypasses
- * the whole queue mess when you want immediate writes to happen.
- *
- * Basically the same as its __queuebased couterpart, however
- * instead of doing a list append, it just calls aim_tx_sendframe()
- * right here. 
- * 
- */
-static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr)
-{
-
-	if (!fr->conn) {
-		faimdprintf(sess, 1, "aim_tx_enqueue: ERROR: packet has no connection\n");
-		aim_frame_destroy(fr);
-		return 0;
-	}
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP)
-		fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
-
-	fr->handled = 0; /* not sent yet */
-
-	aim_tx_sendframe(sess, fr);
-
-	aim_frame_destroy(fr);
-
-	return 0;
-}
-
-faim_export int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *))
-{
-	
-	if (what == AIM_TX_QUEUED)
-		sess->tx_enqueue = &aim_tx_enqueue__queuebased;
-	else if (what == AIM_TX_IMMEDIATE) 
-		sess->tx_enqueue = &aim_tx_enqueue__immediate;
-	else if (what == AIM_TX_USER) {
-		if (!func)
-			return -EINVAL;
-		sess->tx_enqueue = func;
-	} else
-		return -EINVAL; /* unknown action */
-
-	return 0;
-}
-
-faim_internal int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr)
-{
-	
-	/*
-	 * If we want to send a connection thats inprogress, we have to force
-	 * them to use the queue based version. Otherwise, use whatever they
-	 * want.
-	 */
-	if (fr && fr->conn && 
-			(fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
-		return aim_tx_enqueue__queuebased(sess, fr);
-	}
-
-	return (*sess->tx_enqueue)(sess, fr);
-}
-
-/* 
- *  aim_get_next_txseqnum()
- *
- *   This increments the tx command count, and returns the seqnum
- *   that should be stamped on the next FLAP packet sent.  This is
- *   normally called during the final step of packet preparation
- *   before enqueuement (in aim_tx_enqueue()).
- *
- */
-faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn)
-{
-	flap_seqnum_t ret;
-	
-	ret = ++conn->seqnum;
-
-	return ret;
-}
-
-static int aim_send(int fd, const void *buf, size_t count)
-{
-	int left, cur;
-
-	for (cur = 0, left = count; left; ) {
-		int ret;
-
-		ret = send(fd, ((unsigned char *)buf)+cur, left, 0);
-		if (ret == -1)
-			return -1;
-		else if (ret == 0)
-			return cur;
-
-		cur += ret;
-		left -= ret;
-	}
-
-	return cur;
-}
-
-static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count)
-{
-	int wrote = 0;
-	if (!bs || !conn || (count < 0))
-		return -EINVAL;
-
-	if (count > aim_bstream_empty(bs))
-		count = aim_bstream_empty(bs); /* truncate to remaining space */
-
-	if (count) {
-		if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) && 
-		    (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) {
-			/* I strongly suspect that this is a horrible thing to do
-			 * and I feel really guilty doing it. */
-			const char *sn = aim_odc_getsn(conn);
-			aim_rxcallback_t userfunc;
-			while (count - wrote > 1024) {
-				wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, 1024);
-				if ((userfunc=aim_callhandler(conn->sessv, conn, 
-								AIM_CB_FAM_SPECIAL, 
-								AIM_CB_SPECIAL_IMAGETRANSFER)))
-				  userfunc(conn->sessv, NULL, sn, 
-					   count-wrote>1024 ? ((double)wrote / count) : 1);
-			}
-		}
-		if (count - wrote) {
-			wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote);
-		}
-
-	}
-
-	if (((aim_session_t *)conn->sessv)->debug >= 2) {
-		int i;
-		aim_session_t *sess = (aim_session_t *)conn->sessv;
-
-		faimdprintf(sess, 2, "\nOutgoing data: (%d bytes)", wrote);
-		for (i = 0; i < wrote; i++) {
-			if (!(i % 8)) 
-				faimdprintf(sess, 2, "\n\t");
-			faimdprintf(sess, 2, "0x%02x ", *(bs->data + bs->offset + i));
-		}
-		faimdprintf(sess, 2, "\n");
-	}
-
-	bs->offset += wrote;
-
-	return wrote;
-}
-
-static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_bstream_t obs;
-	fu8_t *obs_raw;
-	int payloadlen, err = 0, obslen;
-
-	payloadlen = aim_bstream_curpos(&fr->data);
-
-	if (!(obs_raw = malloc(6 + payloadlen)))
-		return -ENOMEM;
-
-	aim_bstream_init(&obs, obs_raw, 6 + payloadlen);
-
-	/* FLAP header */
-	aimbs_put8(&obs, 0x2a);
-	aimbs_put8(&obs, fr->hdr.flap.type);
-	aimbs_put16(&obs, fr->hdr.flap.seqnum);
-	aimbs_put16(&obs, payloadlen);
-
-	/* payload */
-	aim_bstream_rewind(&fr->data);
-	aimbs_putbs(&obs, &fr->data, payloadlen);
-
-	obslen = aim_bstream_curpos(&obs);
-	aim_bstream_rewind(&obs);
-	if (aim_bstream_send(&obs, fr->conn, obslen) != obslen)
-		err = -errno;
-	
-	free(obs_raw); /* XXX aim_bstream_free */
-
-	fr->handled = 1;
-	fr->conn->lastactivity = time(NULL);
-
-	return err;
-}
-
-static int sendframe_rendezvous(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_bstream_t bs;
-	fu8_t *bs_raw;
-	int err = 0;
-	int totlen = 8 + aim_bstream_curpos(&fr->data);
-
-	if (!(bs_raw = malloc(totlen)))
-		return -1;
-
-	aim_bstream_init(&bs, bs_raw, totlen);
-
-	aimbs_putraw(&bs, fr->hdr.rend.magic, 4);
-	aimbs_put16(&bs, 8 + fr->hdr.rend.hdrlen);
-	aimbs_put16(&bs, fr->hdr.rend.type);
-
-	/* payload */
-	aim_bstream_rewind(&fr->data);
-	aimbs_putbs(&bs, &fr->data, totlen - 8);
-
-	aim_bstream_rewind(&bs);
-
-	if (aim_bstream_send(&bs, fr->conn, totlen) != totlen)
-		err = -errno;
-
-	free(bs_raw); /* XXX aim_bstream_free */
-
-	fr->handled = 1;
-	fr->conn->lastactivity = time(NULL);
-
-	return err;
-}
-
-faim_internal int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *fr)
-{
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP)
-		return sendframe_flap(sess, fr);
-	else if (fr->hdrtype == AIM_FRAMETYPE_OFT)
-		return sendframe_rendezvous(sess, fr);
-	return -1;
-}
-
-faim_export int aim_tx_flushqueue(aim_session_t *sess)
-{
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_outgoing; cur; cur = cur->next) {
-
-		if (cur->handled)
-	       		continue; /* already been sent */
-
-		if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS))
-			continue;
-
-		/*
-		 * And now for the meager attempt to force transmit
-		 * latency and avoid missed messages.
-		 */
-		if ((cur->conn->lastactivity + cur->conn->forcedlatency) >= time(NULL)) {
-			/* 
-			 * XXX should be a break! we dont want to block the 
-			 * upper layers
-			 *
-			 * XXX or better, just do this right.
-			 *
-			 */
-			sleep((cur->conn->lastactivity + cur->conn->forcedlatency) - time(NULL));
-		}
-
-		/* XXX this should call the custom "queuing" function!! */
-		aim_tx_sendframe(sess, cur);
-	}
-
-	/* purge sent commands from queue */
-	aim_tx_purgequeue(sess);
-
-	return 0;
-}
-
-/*
- *  aim_tx_purgequeue()
- *  
- *  This is responsable for removing sent commands from the transmit 
- *  queue. This is not a required operation, but it of course helps
- *  reduce memory footprint at run time!  
- *
- */
-faim_export void aim_tx_purgequeue(aim_session_t *sess)
-{
-	aim_frame_t *cur, **prev;
-
-	for (prev = &sess->queue_outgoing; (cur = *prev); ) {
-
-		if (cur->handled) {
-			*prev = cur->next;
-
-			aim_frame_destroy(cur);
-
-		} else
-			prev = &cur->next;
-	}
-
-	return;
-}
-
-/**
- * aim_tx_cleanqueue - get rid of packets waiting for tx on a dying conn
- * @sess: session
- * @conn: connection that's dying
- *
- * for now this simply marks all packets as sent and lets them
- * disappear without warning.
- *
- */
-faim_internal void aim_tx_cleanqueue(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_outgoing; cur; cur = cur->next) {
-		if (cur->conn == conn)
-			cur->handled = 1;
-	}
-
-	return;
-}
Index: bfaim/util.c
===================================================================
--- libfaim/util.c	(revision e374dee70435f8c596358571092675644a9ba731)
+++ 	(revision )
@@ -1,210 +1,0 @@
-/*
- * A little bit of this
- * A little bit of that
- * It started with a kiss
- * Now we're up to bat
- */
-
-#define FAIM_INTERNAL
-#include <aim.h>
-#include <ctype.h>
-
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-faim_internal void faimdprintf(aim_session_t *sess, int dlevel, const char *format, ...)
-{
-	if (!sess) {
-		fprintf(stderr, "faimdprintf: no session! boo! (%d, %s)\n", dlevel, format);
-		return;
-	}
-	if ((dlevel <= sess->debug) && sess->debugcb) {
-		va_list ap;
-		va_start(ap, format);
-		sess->debugcb(sess, dlevel, format, ap);
-		va_end(ap);
-	}
-
-	return;
-}
-
-faim_export int aimutil_putstr(char *dest, const char *src, int len)
-{
-	memcpy(dest, src, len);
-	return len;
-}
-
-/*
- * Tokenizing functions.  Used to portably replace strtok/sep.
- *   -- DMP.
- *
- */
-faim_export int aimutil_tokslen(char *toSearch, int theindex, char dl)
-{
-	int curCount = 1;
-	char *next;
-	char *last;
-	int toReturn;
-
-	last = toSearch;
-	next = strchr(toSearch, dl);
-
-	while(curCount < theindex && next != NULL) {
-		curCount++;
-		last = next + 1;
-		next = strchr(last, dl);
-	}
-
-	if ((curCount < theindex) || (next == NULL))
-		toReturn = strlen(toSearch) - (curCount - 1);
-	else
-		toReturn = next - toSearch - (curCount - 1);
-
-	return toReturn;
-}
-
-faim_export int aimutil_itemcnt(char *toSearch, char dl)
-{
-	int curCount;
-	char *next;
-
-	curCount = 1;
-
-	next = strchr(toSearch, dl);
-
-	while(next != NULL) {
-		curCount++;
-		next = strchr(next + 1, dl);
-	}
-
-	return curCount;
-}
-
-faim_export char *aimutil_itemindex(char *toSearch, int theindex, char dl)
-{
-	int curCount;
-	char *next;
-	char *last;
-	char *toReturn;
-
-	curCount = 0;
-
-	last = toSearch;
-	next = strchr(toSearch, dl);
-
-	while (curCount < theindex && next != NULL) {
-		curCount++;
-		last = next + 1;
-		next = strchr(last, dl);
-	}
-
-	if (curCount < theindex) {
-		toReturn = malloc(sizeof(char));
-		*toReturn = '\0';
-	}
-	next = strchr(last, dl);
-
-	if (curCount < theindex) {
-		toReturn = malloc(sizeof(char));
-		*toReturn = '\0';
-	} else {
-		if (next == NULL) {
-			toReturn = malloc((strlen(last) + 1) * sizeof(char));
-			strcpy(toReturn, last);
-		} else {
-			toReturn = malloc((next - last + 1) * sizeof(char));
-			memcpy(toReturn, last, (next - last));
-			toReturn[next - last] = '\0';
-		}
-	}
-	return toReturn;
-}
-
-/**
- * Calculate the checksum of a given icon.
- *
- */
-faim_export fu16_t aimutil_iconsum(const fu8_t *buf, int buflen)
-{
-	fu32_t sum;
-	int i;
-
-	for (i=0, sum=0; i+1<buflen; i+=2)
-		sum += (buf[i+1] << 8) + buf[i];
-	if (i < buflen)
-		sum += buf[i];
-	sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
-
-	return sum;
-}
-
-faim_export int aim_util_getlocalip(fu8_t *ip)
-{
-	struct hostent *hptr;
-	char localhost[129];
-
-	/* XXX if available, use getaddrinfo() */
-	/* XXX allow client to specify which IP to use for multihomed boxes */
-
-	if (gethostname(localhost, 128) < 0)
-		return -1;
-
-	if (!(hptr = gethostbyname(localhost)))
-		return -1;
-	memcpy(ip, hptr->h_addr_list[0], 4);
-
-	return 0;
-}
-
-/*
-* int snlen(const char *)
-* 
-* This takes a screen name and returns its length without
-* spaces.  If there are no spaces in the SN, then the 
-* return is equal to that of strlen().
-*
-*/
-faim_export int aim_snlen(const char *sn)
-{
-	int i = 0;
-
-	if (!sn)
-		return 0;
-
-	while (*sn != '\0') {
-		if (*sn != ' ')
-			i++;
-		sn++;
-	}
-
-	return i;
-}
-
-/*
-* int sncmp(const char *, const char *)
-*
-* This takes two screen names and compares them using the rules
-* on screen names for AIM/AOL.  Mainly, this means case and space
-* insensitivity (all case differences and spacing differences are
-* ignored, with the exception that screen names can not start with 
-* a space).
-*
-* Return: 0 if equal
-*     non-0 if different
-*
-*/
-faim_export int aim_sncmp(const char *sn1, const char *sn2)
-{
-
-	do {
-		while (*sn2 == ' ')
-			sn2++;
-		while (*sn1 == ' ')
-			sn1++;
-		if (toupper(*sn1) != toupper(*sn2))
-			return 1;
-	} while ((*sn1 != '\0') && sn1++ && sn2++);
-
-	return 0;
-}
Index: logging.c
===================================================================
--- logging.c	(revision af1920fd98d8d860245a197dee998e0e5c337285)
+++ logging.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -87,15 +87,4 @@
 }
 
-void owl_log_aim(owl_message *m, FILE *file) {
-    fprintf(file, "From: <%s> To: <%s>\n", owl_message_get_sender(m), owl_message_get_recipient(m));
-    fprintf(file, "Time: %s\n\n", owl_message_get_timestr(m));
-    if (owl_message_is_login(m))
-        fprintf(file, "LOGIN\n\n");
-    else if (owl_message_is_logout(m))
-        fprintf(file, "LOGOUT\n\n");
-    else
-        fprintf(file, "%s\n\n", owl_message_get_body(m));
-}
-
 void owl_log_jabber(owl_message *m, FILE *file) {
     fprintf(file, "From: <%s> To: <%s>\n",owl_message_get_sender(m), owl_message_get_recipient(m));
@@ -121,6 +110,4 @@
     } else if (owl_message_is_type_jabber(m)) {
         owl_log_jabber(m, file);
-    } else if (owl_message_is_type_aim(m)) {
-        owl_log_aim(m, file);
     } else {
         owl_log_generic(m, file);
@@ -154,11 +141,4 @@
   } else if (owl_message_is_type_jabber(m)) {
     to = owl_sprintf("jabber:%s", owl_message_get_recipient(m));
-  } else if (owl_message_is_type_aim(m)) {
-    char *temp2;
-    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
-    temp2 = g_utf8_strdown(temp,-1);
-    to = owl_sprintf("aim:%s", temp2);
-    owl_free(temp2);
-    owl_free(temp);
   } else {
     to = owl_sprintf("loopback");
@@ -267,12 +247,4 @@
       from=frombuff=owl_strdup(owl_message_get_class(m));
     }
-  } else if (owl_message_is_type_aim(m)) {
-    /* we do not yet handle chat rooms */
-    char *normalto, *temp;
-    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
-    normalto = g_utf8_strdown(temp, -1);
-    from=frombuff=owl_sprintf("aim:%s", normalto);
-    owl_free(normalto);
-    owl_free(temp);
   } else if (owl_message_is_type_loopback(m)) {
     from=frombuff=owl_strdup("loopback");
Index: message.c
===================================================================
--- message.c	(revision 18108b1ebf65a6a18509f966ce68618ad5aae46d)
+++ message.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -575,24 +575,4 @@
 }
 
-int owl_message_is_from_me(owl_message *m)
-{
-  if (owl_message_is_type_zephyr(m)) {
-    if (!strcasecmp(owl_message_get_sender(m), owl_zephyr_get_sender())) {
-      return(1);
-    } else {
-      return(0);
-    }
-  } else if (owl_message_is_type_aim(m)) {
-    if (!strcasecmp(owl_message_get_sender(m), owl_global_get_aim_screenname(&g))) {
-      return(1);
-    } else {
-      return(0);
-    }
-  } else if (owl_message_is_type_admin(m)) {
-    return(0);
-  }
-  return(0);
-}
-
 int owl_message_is_mail(owl_message *m)
 {
@@ -615,28 +595,4 @@
       return(0);
     }
-  }
-  return(0);
-}
-
-int owl_message_is_burningears(owl_message *m)
-{
-  /* we should add a global to cache the short zsender */
-  char sender[LINE], *ptr;
-
-  /* if the message is from us or to us, it doesn't count */
-  if (owl_message_is_from_me(m) || owl_message_is_private(m)) return(0);
-
-  if (owl_message_is_type_zephyr(m)) {
-    strcpy(sender, owl_zephyr_get_sender());
-    ptr=strchr(sender, '@');
-    if (ptr) *ptr='\0';
-  } else if (owl_message_is_type_aim(m)) {
-    strcpy(sender, owl_global_get_aim_screenname(&g));
-  } else {
-    return(0);
-  }
-
-  if (stristr(owl_message_get_body(m), sender)) {
-    return(1);
   }
   return(0);
Index: owl.c
===================================================================
--- owl.c	(revision b1fd36ed2941a6f89bdffb20226eafa3ab5ec40b)
+++ owl.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -183,5 +183,4 @@
   owl_function_debugmsg("startup: first available debugging message");
   owl_global_set_startupargs(&g, argcsave, argvsave);
-  owl_global_set_haveaim(&g);
 
   /* prepare stdin dispatch */
@@ -300,8 +299,4 @@
   owl_function_debugmsg("startup: setting the current view");
   owl_view_create(owl_global_get_current_view(&g), "main", f, owl_global_get_style_by_name(&g, "default"));
-
-  /* AIM init */
-  owl_function_debugmsg("startup: doing AIM initialization");
-  owl_aim_init();
 
   /* execute the startup function in the configfile */
@@ -564,9 +559,6 @@
       if (owl_message_is_type_zephyr(m)) {
         owl_zephyr_zaway(m);
-      } else if (owl_message_is_type_aim(m)) {
-        if (owl_message_is_private(m)) {
-          owl_function_send_aimawymsg(owl_message_get_sender(m), owl_global_get_zaway_msg(&g));
-        }
-      }
+      }
+      /* TODO add perl hooks for away messages */
     }
 
@@ -609,18 +601,4 @@
 
   return 1;
-}
-
-void owl_process_aim()
-{
-  if (owl_global_is_doaimevents(&g)) {
-    owl_aim_process_events();
-    
-    if (owl_global_is_aimloggedin(&g)) {
-      if (owl_timer_is_expired(owl_global_get_aim_buddyinfo_timer(&g))) {
-        /* owl_buddylist_request_idletimes(owl_global_get_buddylist(&g)); */
-        owl_timer_reset(owl_global_get_aim_buddyinfo_timer(&g));
-      }
-    }
-  }
 }
 
Index: owl.h
===================================================================
--- owl.h	(revision d7a3188828e158c5556573d6f9230747505a1c8b)
+++ owl.h	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -20,6 +20,8 @@
 #include <signal.h>
 #include <termios.h>
-#include <libfaim/aim.h>
 #include <wchar.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
 #include "config.h"
 #include "glib.h"
@@ -36,6 +38,4 @@
 /* logout is defined in FreeBSD. */
 #define logout logout_
-/* aim.h defines bool */
-#define HAS_BOOL
 #include <perl.h>
 #include "owl_perl.h"
@@ -56,5 +56,5 @@
 
 #ifndef OWL_VERSION_STRING
-#define OWL_VERSION_STRING "1.0.1"
+#define OWL_VERSION_STRING "1.0.1-perlaim-r" BARNOWL_STRINGIFY(OWL_SVN_REVNO)
 #endif
 
@@ -583,13 +583,4 @@
   int malloced, freed;
   char *searchstring;
-  aim_session_t aimsess;
-  aim_conn_t bosconn;
-  owl_timer aim_noop_timer;
-  owl_timer aim_ignorelogin_timer;
-  owl_timer aim_buddyinfo_timer;
-  int aim_loggedin;         /* true if currently logged into AIM */
-  int aim_doprocessing;     /* true if we should process AIM events (like pending login) */
-  char *aim_screenname;     /* currently logged in AIM screen name */
-  char *aim_screenname_for_filters;     /* currently logged in AIM screen name */
   owl_buddylist buddylist;  /* list of logged in AIM buddies */
   owl_list messagequeue;    /* for queueing up aim and other messages */
@@ -597,5 +588,4 @@
   char *response;           /* response to the last question asked */
   int havezephyr;
-  int haveaim;
   int got_err_signal;	    /* 1 if we got an unexpected signal */
   siginfo_t err_signal_info;
Index: select.c
===================================================================
--- select.c	(revision 2f690811f743b0ec04fdd98ce530c5a296c031df)
+++ select.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -148,36 +148,9 @@
 }
 
-int owl_select_aim_hack(fd_set *rfds, fd_set *wfds)
-{
-  aim_conn_t *cur;
-  aim_session_t *sess;
-  int max_fd;
-
-  FD_ZERO(rfds);
-  FD_ZERO(wfds);
-  max_fd = 0;
-  sess = owl_global_get_aimsess(&g);
-  for (cur = sess->connlist, max_fd = 0; cur; cur = cur->next) {
-    if (cur->fd != -1) {
-      FD_SET(cur->fd, rfds);
-      if (cur->status & AIM_CONN_STATUS_INPROGRESS) {
-        /* Yes, we're checking writable sockets here. Without it, AIM
-           login is really slow. */
-        FD_SET(cur->fd, wfds);
-      }
-      
-      if (cur->fd > max_fd)
-        max_fd = cur->fd;
-    }
-  }
-  return max_fd;
-}
-
 void owl_select()
 {
-  int i, max_fd, aim_max_fd, aim_done;
+  int max_fd;
   fd_set r;
   fd_set e;
-  fd_set aim_rfds, aim_wfds;
   struct timeval timeout;
 
@@ -187,47 +160,5 @@
   max_fd = owl_select_dispatch_prepare_fd_sets(&r, &e);
 
-  /* AIM HACK: 
-   *
-   *  The problem - I'm not sure where to hook into the owl/faim
-   *  interface to keep track of when the AIM socket(s) open and
-   *  close. In particular, the bosconn thing throws me off. So,
-   *  rather than register particular dispatchers for AIM, I look up
-   *  the relevant FDs and add them to select's watch lists, then
-   *  check for them individually before moving on to the other
-   *  dispatchers. --asedeno
-   */
-  aim_done = 1;
-  FD_ZERO(&aim_rfds);
-  FD_ZERO(&aim_wfds);
-  if (owl_global_is_doaimevents(&g)) {
-    aim_done = 0;
-    aim_max_fd = owl_select_aim_hack(&aim_rfds, &aim_wfds);
-    if (max_fd < aim_max_fd) max_fd = aim_max_fd;
-    for(i = 0; i <= aim_max_fd; i++) {
-      if (FD_ISSET(i, &aim_rfds)) {
-        FD_SET(i, &r);
-        FD_SET(i, &e);
-      }
-    }
-  }
-  /* END AIM HACK */
-
-  if ( select(max_fd+1, &r, &aim_wfds, &e, &timeout) ) {
-    /* Merge fd_sets and clear AIM FDs. */
-    for(i = 0; i <= max_fd; i++) {
-      /* Merge all interesting FDs into one set, since we have a
-         single dispatch per FD. */
-      if (FD_ISSET(i, &r) || FD_ISSET(i, &aim_wfds) || FD_ISSET(i, &e)) {
-        /* AIM HACK: no separate dispatch, just process here if
-           needed, and only once per run through. */
-        if (!aim_done && (FD_ISSET(i, &aim_rfds) || FD_ISSET(i, &aim_wfds))) {
-          owl_process_aim();
-          aim_done = 1;
-        }
-        else {
-          FD_SET(i, &r);
-        }
-      }
-    }
+  if ( select(max_fd+1, &r, NULL, &e, &timeout) ) {
     /* NOTE: the same dispatch function is called for both exceptional
        and read ready FDs. */
Index: util.c
===================================================================
--- util.c	(revision af1920fd98d8d860245a197dee998e0e5c337285)
+++ util.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -78,16 +78,13 @@
   }
 
-  if (owl_global_is_zaway(&g) || owl_global_is_aaway(&g)) {
+  /* TODO add perl hooks for sepbar away, etc. status */
+  if (owl_global_is_zaway(&g)) {
     getyx(sepwin, y, x);
     wmove(sepwin, y, x+2);
     wattron(sepwin, A_BOLD);
     wattroff(sepwin, A_REVERSE);
-    if (owl_global_is_zaway(&g) && owl_global_is_aaway(&g)) {
+    if (owl_global_is_zaway(&g)) {
       waddstr(sepwin, " AWAY ");
-    } else if (owl_global_is_zaway(&g)) {
-      waddstr(sepwin, " Z-AWAY ");
-    } else if (owl_global_is_aaway(&g)) {
-      waddstr(sepwin, " A-AWAY ");
-    }
+    } /* else if... */
     wattron(sepwin, A_REVERSE);
     wattroff(sepwin, A_BOLD);
Index: variable.c
===================================================================
--- variable.c	(revision 52f8dd6f954e971462a0a3fedc3550d1d0060e91)
+++ variable.c	(revision c453adace14d4a6f0102ec68792c215c09060625)
@@ -239,17 +239,4 @@
 	         "default zaway message", "" ),
 
-  OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
-		    "Set AIM away status",
-		    "",
-		    NULL, owl_variable_aaway_set, NULL),
-
-  OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
-		 OWL_DEFAULT_AAWAYMSG,
-	         "AIM away msg for responding when away", "" ),
-
-  OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
-		 OWL_DEFAULT_AAWAYMSG,
-	         "default AIM away message", "" ),
-
   OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
 	         "home view to switch to after 'X' and 'V'", 
@@ -299,12 +286,4 @@
 		 "than 60 columns, as a courtesy to recipients.\n"),
 
-  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,
-	      "number of seconds after AIM login to ignore login messages",
-	      "This specifies the number of seconds to wait after an\n"
-	      "AIM login before allowing the recipt of AIM login notifications.\n"
-	      "By default this is set to 15.  If you would like to view login\n"
-	      "notifications of buddies as soon as you login, set it to 0 instead."),
-
-	      
   OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
 		   OWL_TYPWIN_SIZE,
@@ -403,17 +382,4 @@
   if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
     g.debug = *(int*)newval;
-  }
-  return owl_variable_bool_set_default(v, newval);
-}
-
-/* When 'aaway' is changed, need to notify the AIM server */
-int owl_variable_aaway_set(owl_variable *v, void *newval)
-{
-  if (newval) {
-    if (*(int*)newval == 1) {
-      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
-    } else if (*(int*)newval == 0) {
-      owl_aim_set_awaymsg("");
-    }
   }
   return owl_variable_bool_set_default(v, newval);
