changeset 2167:edf8c5a70e5b

[gaim-migrate @ 2177] limiting chat message lengths committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 26 Aug 2001 20:21:45 +0000
parents dbd74f49dabb
children 74947d32d3c6
files src/conversation.c src/gaim.h src/protocols/irc/irc.c src/protocols/jabber/jabber.c src/protocols/msn/msn.c src/protocols/napster/napster.c src/protocols/oscar/CHANGES src/protocols/oscar/aim.h src/protocols/oscar/chat.c src/protocols/oscar/im.c src/protocols/oscar/login.c src/protocols/oscar/misc.c src/protocols/oscar/oscar.c src/protocols/toc/toc.c src/protocols/zephyr/zephyr.c src/prpl.h src/server.c
diffstat 17 files changed, 1650 insertions(+), 1399 deletions(-) [+]
line wrap: on
line diff
--- a/src/conversation.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/conversation.c	Sun Aug 26 20:21:45 2001 +0000
@@ -865,7 +865,7 @@
 				play_sound(SEND);
 		}
 	} else {
-		serv_chat_send(c->gc, c->id, buf);
+		err = serv_chat_send(c->gc, c->id, buf);
 
 		/* no sound because we do that when we receive our message */
 	}
--- a/src/gaim.h	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/gaim.h	Sun Aug 26 20:21:45 2001 +0000
@@ -677,7 +677,7 @@
 extern void serv_chat_invite(struct gaim_connection *, int, char *, char *);
 extern void serv_chat_leave(struct gaim_connection *, int);
 extern void serv_chat_whisper(struct gaim_connection *, int, char *, char *);
-extern void serv_chat_send(struct gaim_connection *, int, char *);
+extern int serv_chat_send(struct gaim_connection *, int, char *);
 extern void serv_chat_set_topic(struct gaim_connection *, int, char *);
 extern void update_keepalive(struct gaim_connection *, gboolean);
 
--- a/src/protocols/irc/irc.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/irc/irc.c	Sun Aug 26 20:21:45 2001 +0000
@@ -308,7 +308,7 @@
 }
 
 static void irc_chat_leave(struct gaim_connection *gc, int id);
-static void irc_chat_send(struct gaim_connection *gc, int id, char *message)
+static int irc_chat_send(struct gaim_connection *gc, int id, char *message)
 {
 
 	struct irc_data *idata = (struct irc_data *)gc->proto_data;
@@ -323,7 +323,7 @@
 	if (!channel) {
 		/* If for some reason we've lost our channel, let's bolt */
 		g_free(buf);
-		return;
+		return -EINVAL;
 	}
 
 
@@ -416,7 +416,7 @@
 
 			irc_chat_leave(gc, id);
 			is_command = TRUE;
-			return;
+			return 0;
 
 
 		}
@@ -431,7 +431,7 @@
 			irc_join_chat(gc, 0, temp);
 			g_free(temp);
 			is_command = TRUE;
-			return;
+			return 0;
 		}
 
 		else if (!g_strncasecmp(message, "/raw ", 5) && (strlen(message) > 5)) {
@@ -524,8 +524,9 @@
 
 	g_free(buf);
 
-
+	return 0;
 }
+
 static struct conversation *find_conversation_by_id(struct gaim_connection *gc, int id)
 {
 	GSList *bc = gc->buddy_chats;
--- a/src/protocols/jabber/jabber.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/jabber/jabber.c	Sun Aug 26 20:21:45 2001 +0000
@@ -1447,7 +1447,7 @@
 	jc->b = NULL;
 }
 
-static void jabber_chat_send(struct gaim_connection *gc, int id, char *message)
+static int jabber_chat_send(struct gaim_connection *gc, int id, char *message)
 {
 	GSList *bcs = gc->buddy_chats;
 	struct conversation *b;
@@ -1463,7 +1463,7 @@
 		bcs = bcs->next;
 	}
 	if (!bcs)
-		return;
+		return -EINVAL;
 
 	bcs = jd->existing_chats;
 	while (bcs) {
@@ -1473,7 +1473,7 @@
 		bcs = bcs->next;
 	}
 	if (!bcs)
-		return;
+		return -EINVAL;
 
 	x = xmlnode_new_tag("message");
 	xmlnode_put_attrib(x, "from", jid_full(jc->Jid));
@@ -1491,6 +1491,7 @@
 
 	gjab_send(((struct jabber_data *)gc->proto_data)->jc, x);
 	xmlnode_free(x);
+	return 0;
 }
 
 static void jabber_chat_set_topic(struct gaim_connection *gc, int id, char *topic)
--- a/src/protocols/msn/msn.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/msn/msn.c	Sun Aug 26 20:21:45 2001 +0000
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <gtk/gtk.h>
 #include <string.h>
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -1170,13 +1171,13 @@
 	return 0;
 }
 
-static void msn_chat_send(struct gaim_connection *gc, int id, char *message)
+static int msn_chat_send(struct gaim_connection *gc, int id, char *message)
 {
 	struct msn_switchboard *ms = msn_find_switch_by_id(gc, id);
 	char buf[MSN_BUF_LEN];
 
 	if (!ms)
-		return;
+		return -EINVAL;
 
 	g_snprintf(buf, sizeof(buf), "MSG %d N %d\r\n%s%s", ++ms->trId,
 			strlen(MIME_HEADER) + strlen(message),
@@ -1185,6 +1186,7 @@
 		msn_kill_switch(ms);
 	debug_printf("\n");
 	serv_got_chat_in(gc, id, gc->username, 0, message, time(NULL));
+	return 0;
 }
 
 static void msn_chat_invite(struct gaim_connection *gc, int id, char *msg, char *who)
--- a/src/protocols/napster/napster.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/napster/napster.c	Sun Aug 26 20:21:45 2001 +0000
@@ -952,7 +952,7 @@
 	
 }
 
-static void nap_chat_send(struct gaim_connection *gc, int id, char *message)
+static int nap_chat_send(struct gaim_connection *gc, int id, char *message)
 {
 	struct nap_channel *channel = NULL;
 	gchar buf[NAP_BUF_LEN];
@@ -961,12 +961,12 @@
 
 	if (!channel) {
 		/* This shouldn't happen */
-		return;
+		return -EINVAL;
 	}
 
 	g_snprintf(buf, NAP_BUF_LEN, "%s %s", channel->name, message);
 	nap_write_packet(gc, 0x192, buf);
-
+	return 0;
 }
 
 static void nap_add_buddy(struct gaim_connection *gc, char *name)
--- a/src/protocols/oscar/CHANGES	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/CHANGES	Sun Aug 26 20:21:45 2001 +0000
@@ -1,6 +1,39 @@
 
 No release numbers
 ------------------
+ - Sat Aug 25 19:46:38 PDT 2001
+  - Pass "Maximum visible message length" to client in chat info update
+    - This is the real maximum message length now.  There is still a
+      "complexity" limit that will prevent you from sending messages 
+      even if they are less than this limit (102 right now), but I don't 
+      know how that is calculated.
+
+ - Sat Aug 25 19:19:16 PDT 2001
+  - Keep parsing missed calls for entire packet
+    - This is really easy to test now.  Just talk to someone with
+      their minmsginterval set high (like 10seconds or something)
+
+ - Sat Aug 25 18:35:13 PDT 2001
+  - aim_sendconnack -> aim_sendflapver
+  - Remove addicbmparam.  This was identical to aim_seticbmparam
+  - aim_seticbmparam now takes a struct with the parameters in it.  See
+      faimtest.  !!! REQUIRES CLIENT CHANGES if you use aim_seticbmparam, which
+      you really really should -- the defaults are insanely limited
+  - Fix rendezvous IM parsing that I broke last time.
+  - ICBM parameter info callback gives same struct as above.  !!! REQUIRES
+      CLIENT CHANGES
+  - Reformat login.c and part of faimtest.c
+  - !!! NOTE: don't do anything in your motd handler.  If you do, it will
+      get run twice, sine for some reason AOL is sending two MOTDs now.
+
+ - Wed Aug 22 22:11:18 PDT 2001
+  - Reformat the rest of im.c
+  - Fix a few returns, particularly in error cases
+
+ - Thu Aug 16 06:17:57 PDT 2001
+  - Reformat a bit of im.c and aim.h
+  - Rearrange encoding/subencoding checks in IM parsing
+ 
  - Fri Aug  3 14:19:37 EDT 2001
   - Naje aun_sebd_un retyrn sabe vakyes
 
--- a/src/protocols/oscar/aim.h	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/aim.h	Sun Aug 26 20:21:45 2001 +0000
@@ -484,8 +484,8 @@
 typedef int (*aim_rxcallback_t)(struct aim_session_t *, struct command_rx_struct *, ...);
 
 /* aim_login.c */
-faim_export int aim_sendconnack(struct aim_session_t *sess, struct aim_conn_t *conn);
-faim_export int aim_request_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn);
+faim_export int aim_sendflapver(struct aim_session_t *sess, struct aim_conn_t *conn);
+faim_export int aim_request_login (struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn);
 faim_export int aim_send_login (struct aim_session_t *, struct aim_conn_t *, char *, char *, struct client_info_s *, char *key);
 faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest);
 faim_export unsigned long aim_sendauthresp(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, int errorcode, char *errorurl, char *bosip, char *cookie, char *email, int regstatus);
@@ -563,8 +563,6 @@
 faim_export unsigned long aim_bos_reqrights(struct aim_session_t *, struct aim_conn_t *);
 faim_export unsigned long aim_bos_reqbuddyrights(struct aim_session_t *, struct aim_conn_t *);
 faim_export unsigned long aim_bos_reqlocaterights(struct aim_session_t *, struct aim_conn_t *);
-faim_export unsigned long aim_bos_reqicbmparaminfo(struct aim_session_t *, struct aim_conn_t *);
-faim_export unsigned long aim_addicbmparam(struct aim_session_t *sess,struct aim_conn_t *conn);
 faim_export unsigned long aim_setversions(struct aim_session_t *sess, struct aim_conn_t *conn);
 faim_export unsigned long aim_auth_setversions(struct aim_session_t *sess, struct aim_conn_t *conn);
 faim_export unsigned long aim_auth_reqconfirm(struct aim_session_t *sess, struct aim_conn_t *conn);
@@ -636,17 +634,17 @@
 };
 
 struct aim_filetransfer_priv {
-  char sn[MAXSNLEN];
-  char cookie[8];
-  char ip[30];
-  int state;
-  struct aim_fileheader_t fh;
+	char sn[MAXSNLEN];
+	char cookie[8];
+	char ip[30];
+	int state;
+	struct aim_fileheader_t fh;
 };
 
 struct aim_chat_roominfo {
-  u_short exchange;
-  char *name;
-  u_short instance;
+	unsigned short exchange;
+	char *name;
+	unsigned short instance;
 };
 
 #define AIM_IMFLAGS_AWAY 0x01 /* mark as an autoreply */
@@ -655,53 +653,56 @@
 #define AIM_IMFLAGS_ISO_8859_1 0x08
 #define AIM_IMFLAGS_BUDDYREQ   0x10 /* buddy icon requested */
 #define AIM_IMFLAGS_HASICON    0x20 /* already has icon (timestamp included) */
+#define AIM_IMFLAGS_SUBENC_MACINTOSH	0x40 /* damn that Steve Jobs! */
 
 struct aim_sendimext_args {
-  const char *destsn;
-  unsigned short flags;
-  const char *msg;
-  int msglen;
-  int iconlen;
-  time_t iconstamp;
-  unsigned short iconsum;
+	const char *destsn;
+	unsigned short flags;
+	const char *msg;
+	int msglen;
+	int iconlen;
+	time_t iconstamp;
+	unsigned short iconsum;
 };
 
 struct aim_incomingim_ch1_args {
-  char *msg;
-  int msglen;
-  unsigned long icbmflags;
-  unsigned short flag1;
-  unsigned short flag2;
-  int finlen;
-  unsigned char fingerprint[10];
-  time_t iconstamp;
+	char *msg;
+	int msglen;
+	unsigned long icbmflags;
+	unsigned short flag1;
+	unsigned short flag2;
+	int finlen;
+	unsigned char fingerprint[10];
+	time_t iconstamp;
+	int extdatalen;
+	unsigned char *extdata;
 };
 
 struct aim_incomingim_ch2_args {
-  unsigned short reqclass;
-  unsigned short status;
-  union {
-    struct {
-      unsigned int length;
-      time_t timestamp;
-      unsigned char *icon;
-    } icon;
-    struct {
-    } voice;
-    struct aim_directim_priv *directim;
-    struct {
-      char *msg;
-      char *encoding;
-      char *lang;
-      struct aim_chat_roominfo roominfo;
-    } chat;
-    struct {
-      char *ip;
-      unsigned char *cookie;
-    } getfile;
-    struct {
-    } sendfile;
-  } info;
+	unsigned short reqclass;
+	unsigned short status;
+	union {
+		struct {
+			unsigned int length;
+			time_t timestamp;
+			unsigned char *icon;
+		} icon;
+		struct {
+		} voice;
+		struct aim_directim_priv *directim;
+		struct {
+			char *msg;
+			char *encoding;
+			char *lang;
+		struct aim_chat_roominfo roominfo;
+		} chat;
+		struct {
+			char *ip;
+			unsigned char *cookie;
+		} getfile;
+		struct {
+		} sendfile;
+	} info;
 };
 
 faim_export int aim_send_im_ext(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_sendimext_args *args);
@@ -711,7 +712,6 @@
 faim_export int aim_send_im_direct(struct aim_session_t *, struct aim_conn_t *, char *);
 faim_export struct aim_conn_t * aim_directim_initiate(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *, char *destsn);
 faim_export struct aim_conn_t *aim_directim_connect(struct aim_session_t *, struct aim_conn_t *, struct aim_directim_priv *);
-faim_export unsigned long aim_seticbmparam(struct aim_session_t *, struct aim_conn_t *conn);
 
 faim_export struct aim_conn_t *aim_getfile_initiate(struct aim_session_t *sess, struct aim_conn_t *conn, char *destsn);
 faim_export int aim_oft_getfile_request(struct aim_session_t *sess, struct aim_conn_t *conn, const unsigned char *name, const int size);
@@ -778,13 +778,47 @@
 #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000
 #define AIM_TRANSFER_DENY_DECLINE 0x0001
 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002
-faim_export unsigned long aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sender, char *cookie, unsigned short code);
+faim_export int aim_denytransfer(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sender, const char *cookie, unsigned short code);
 faim_export struct aim_conn_t *aim_accepttransfer(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *cookie, char *ip, unsigned short listingfiles, unsigned short listingtotsize, unsigned short listingsize, unsigned int listingchecksum, unsigned short rendid);
 
 faim_export int aim_getinfo(struct aim_session_t *, struct aim_conn_t *, const char *, unsigned short);
 faim_export int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info);
 faim_export int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn);
 
+#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 \
+}
+
+/* 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 {
+	unsigned short maxchan;
+	unsigned long flags; /* AIM_IMPARAM_FLAG_ */
+	unsigned short maxmsglen; /* message size that you will accept */
+	unsigned short maxsenderwarn; /* this and below are *10 (999=99.9%) */
+	unsigned short maxrecverwarn;
+	unsigned long minmsginterval; /* in milliseconds? */
+};
+
+faim_export unsigned long aim_reqicbmparams(struct aim_session_t *sess, struct aim_conn_t *conn);
+faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_icbmparameters *params);
+
 
 /* aim_auth.c */
 faim_export int aim_auth_sendcookie(struct aim_session_t *, struct aim_conn_t *, u_char *);
--- a/src/protocols/oscar/chat.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/chat.c	Sun Aug 26 20:21:45 2001 +0000
@@ -401,130 +401,166 @@
  */
 static int infoupdate(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  struct aim_userinfo_s *userinfo = NULL;
-  aim_rxcallback_t userfunc=NULL;	
-  int ret = 0, i = 0;
-  int usercount = 0;
-  unsigned char detaillevel = 0;
-  char *roomname = NULL;
-  struct aim_chat_roominfo roominfo;
-  unsigned short tlvcount = 0;
-  struct aim_tlvlist_t *tlvlist;
-  char *roomdesc = NULL;
-  unsigned short unknown_c9 = 0;
-  unsigned long creationtime = 0;
-  unsigned short maxmsglen = 0;
-  unsigned short unknown_d2 = 0, unknown_d5 = 0;
+	struct aim_userinfo_s *userinfo = NULL;
+	aim_rxcallback_t userfunc=NULL;	
+	int ret = 0, i = 0;
+	int usercount = 0;
+	unsigned char detaillevel = 0;
+	char *roomname = NULL;
+	struct aim_chat_roominfo roominfo;
+	unsigned short tlvcount = 0;
+	struct aim_tlvlist_t *tlvlist;
+	char *roomdesc = NULL;
+	unsigned short unknown_c9 = 0;
+	unsigned long creationtime = 0;
+	unsigned short maxmsglen = 0, maxvisiblemsglen = 0;
+	unsigned short unknown_d2 = 0, unknown_d5 = 0;
 
-  i += aim_chat_readroominfo(data+i, &roominfo);
-  
-  detaillevel = aimutil_get8(data+i);
-  i++;
+	i += aim_chat_readroominfo(data+i, &roominfo);
+
+	detaillevel = aimutil_get8(data+i);
+	i++;
 
-  if (detaillevel != 0x02) {
-    if (detaillevel == 0x01)
-      faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level 1 not supported\n");
-    else
-      faimdprintf(sess, 0, "faim: chat_roomupdateinfo: unknown detail level %d\n", detaillevel);
-    return 1;
-  }
-  
-  tlvcount = aimutil_get16(data+i);
-  i += 2;
+	if (detaillevel != 0x02) {
+		if (detaillevel == 0x01)
+			faimdprintf(sess, 0, "faim: chat_roomupdateinfo: detail level 1 not supported\n");
+		else
+			faimdprintf(sess, 0, "faim: chat_roomupdateinfo: unknown detail level %d\n", detaillevel);
+		return 1;
+	}
+
+	tlvcount = aimutil_get16(data+i);
+	i += 2;
 
-  /*
-   * Everything else are TLVs.
-   */ 
-  tlvlist = aim_readtlvchain(data+i, datalen-i);
-  
-  /*
-   * TLV type 0x006a is the room name in Human Readable Form.
-   */
-  if (aim_gettlv(tlvlist, 0x006a, 1))
-    roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
+	/*
+	 * Everything else are TLVs.
+	 */ 
+	tlvlist = aim_readtlvchain(data+i, datalen-i);
 
-  /*
-   * Type 0x006f: Number of occupants.
-   */
-  if (aim_gettlv(tlvlist, 0x006f, 1))
-    usercount = aim_gettlv16(tlvlist, 0x006f, 1);
+	/*
+	 * TLV type 0x006a is the room name in Human Readable Form.
+	 */
+	if (aim_gettlv(tlvlist, 0x006a, 1))
+		roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
+
+	/*
+	 * Type 0x006f: Number of occupants.
+	 */
+	if (aim_gettlv(tlvlist, 0x006f, 1))
+		usercount = aim_gettlv16(tlvlist, 0x006f, 1);
 
-  /*
-   * Type 0x0073:  Occupant list.
-   */
-  if (aim_gettlv(tlvlist, 0x0073, 1)) {	
-    int curoccupant = 0;
-    struct aim_tlv_t *tmptlv;
-    
-    tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
+	/*
+	 * Type 0x0073:  Occupant list.
+	 */
+	if (aim_gettlv(tlvlist, 0x0073, 1)) {	
+		int curoccupant = 0;
+		struct aim_tlv_t *tmptlv;
+
+		tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
+
+		/* Allocate enough userinfo structs for all occupants */
+		userinfo = calloc(usercount, sizeof(struct aim_userinfo_s));
+
+		for (i = 0; curoccupant < usercount; )
+			i += aim_extractuserinfo(sess, tmptlv->value+i, &userinfo[curoccupant++]);
+	}
+
+	/* 
+	 * Type 0x00c9: Unknown. (2 bytes)
+	 */
+	if (aim_gettlv(tlvlist, 0x00c9, 1))
+		unknown_c9 = aim_gettlv16(tlvlist, 0x00c9, 1);
+
+	/* 
+	 * Type 0x00ca: Creation time (4 bytes)
+	 */
+	if (aim_gettlv(tlvlist, 0x00ca, 1))
+		creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
 
-    /* Allocate enough userinfo structs for all occupants */
-    userinfo = calloc(usercount, sizeof(struct aim_userinfo_s));
-    
-    i = 0;
-    while (curoccupant < usercount)
-      i += aim_extractuserinfo(sess, tmptlv->value+i, &userinfo[curoccupant++]);
-  }
-  
-  /* 
-   * Type 0x00c9: Unknown. (2 bytes)
-   */
-  if (aim_gettlv(tlvlist, 0x00c9, 1))
-    unknown_c9 = aim_gettlv16(tlvlist, 0x00c9, 1);
-  
-  /* 
-   * Type 0x00ca: Creation time (4 bytes)
-   */
-  if (aim_gettlv(tlvlist, 0x00ca, 1))
-    creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
+	/* 
+	 * Type 0x00d1: Maximum Message Length
+	 */
+	if (aim_gettlv(tlvlist, 0x00d1, 1))
+		maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
+
+	/* 
+	 * Type 0x00d2: Unknown. (2 bytes)
+	 */
+	if (aim_gettlv(tlvlist, 0x00d2, 1))
+		unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
 
-  /* 
-   * Type 0x00d1: Maximum Message Length
-   */
-  if (aim_gettlv(tlvlist, 0x00d1, 1))
-    maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
-
-  /* 
-   * Type 0x00d2: Unknown. (2 bytes)
-   */
-  if (aim_gettlv(tlvlist, 0x00d2, 1))
-    unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
+	/* 
+	 * Type 0x00d3: Room Description
+	 */
+	if (aim_gettlv(tlvlist, 0x00d3, 1))
+		roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
 
-  /* 
-   * Type 0x00d3: Room Description
-   */
-  if (aim_gettlv(tlvlist, 0x00d3, 1))
-    roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
+	/*
+	 * Type 0x000d4: Unknown (flag only)
+	 */
+	if (aim_gettlv(tlvlist, 0x000d4, 1))
+		;
 
-  /* 
-   * Type 0x00d5: Unknown. (1 byte)
-   */
-  if (aim_gettlv(tlvlist, 0x00d5, 1))
-    unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
+	/* 
+	 * Type 0x00d5: Unknown. (1 byte)
+	 */
+	if (aim_gettlv(tlvlist, 0x00d5, 1))
+		unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
 
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-    ret = userfunc(sess,
-		   rx, 
-		   &roominfo,
-		   roomname,
-		   usercount,
-		   userinfo,	
-		   roomdesc,
-		   unknown_c9,
-		   creationtime,
-		   maxmsglen,
-		   unknown_d2,
-		   unknown_d5);
-  }
+	/*
+	 * Type 0x00d6: Encoding 1 ("us-ascii")
+	 */
+	if (aim_gettlv(tlvlist, 0x000d6, 1))
+		;
+	
+	/*
+	 * Type 0x00d7: Language 1 ("en")
+	 */
+	if (aim_gettlv(tlvlist, 0x000d7, 1))
+		;
+
+	/*
+	 * Type 0x00d8: Encoding 2 ("us-ascii")
+	 */
+	if (aim_gettlv(tlvlist, 0x000d8, 1))
+		;
+	
+	/*
+	 * Type 0x00d9: Language 2 ("en")
+	 */
+	if (aim_gettlv(tlvlist, 0x000d9, 1))
+		;
 
-  free(roominfo.name);
-  free(userinfo);
-  free(roomname);
-  free(roomdesc);
-  aim_freetlvchain(&tlvlist);
- 
-  return ret;
+	/*
+	 * Type 0x00da: Maximum visible message length
+	 */
+	if (aim_gettlv(tlvlist, 0x000da, 1))
+		maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);
+
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
+		ret = userfunc(sess,
+				rx, 
+				&roominfo,
+				roomname,
+				usercount,
+				userinfo,	
+				roomdesc,
+				unknown_c9,
+				creationtime,
+				maxmsglen,
+				unknown_d2,
+				unknown_d5,
+				maxvisiblemsglen);
+	}
+
+	free(roominfo.name);
+	free(userinfo);
+	free(roomname);
+	free(roomdesc);
+	aim_freetlvchain(&tlvlist);
+
+	return ret;
 }
 
 static int userlistchange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
--- a/src/protocols/oscar/im.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/im.c	Sun Aug 26 20:21:45 2001 +0000
@@ -3,6 +3,20 @@
  *
  *  The 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.
+ *
+ *  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.
+ *
  */
 
 #define FAIM_INTERNAL
@@ -27,56 +41,56 @@
  */
 faim_export unsigned short aim_fingerprintclient(unsigned char *msghdr, int len)
 {
-  static const struct {
-    unsigned short clientid;
-    int len;
-    unsigned char data[10];
-  } fingerprints[] = {
-    /* AOL Mobile Communicator, WinAIM 1.0.414 */
-    { AIM_CLIENTTYPE_MC, 
-      9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01}},
+	static const struct {
+		unsigned short clientid;
+		int len;
+		unsigned char data[10];
+	} fingerprints[] = {
+		/* AOL Mobile Communicator, WinAIM 1.0.414 */
+		{ AIM_CLIENTTYPE_MC, 
+		  9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01}},
 
-    /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */
-    { AIM_CLIENTTYPE_WINAIM, 
-      9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01}},
+		/* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */
+		{ AIM_CLIENTTYPE_WINAIM, 
+		  9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01}},
 
-    /* WinAIM 4.1.2010, libfaim */
-    { AIM_CLIENTTYPE_WINAIM41,
-      10, {0x05, 0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}},
+		/* WinAIM 4.1.2010, libfaim */
+		{ AIM_CLIENTTYPE_WINAIM41,
+		 10, {0x05, 0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}},
 
-    /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */
-    { AIM_CLIENTTYPE_AOL_TOC,
-      7, {0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01}},
+		/* AOL v6.0, CompuServe 2000 v6.0, any TOC client */
+		{ AIM_CLIENTTYPE_AOL_TOC,
+		  7, {0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01}},
 
-    { 0, 0}
-  };
-  int i;
+		{ 0, 0}
+	};
+	int i;
 
-  if (!msghdr || (len <= 0))
-    return 0;
+	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;
-  }
+	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;
+	return AIM_CLIENTTYPE_UNKNOWN;
 }
 
 /* This should be endian-safe now... but who knows... */
 faim_export unsigned short aim_iconsum(const unsigned char *buf, int buflen)
 {
-  unsigned long sum;
-  int i;
+	unsigned long sum;
+	int i;
 
-  for (i = 0, sum = 0; i < buflen; i += 2)
-    sum += (buf[i+1] << 8) + buf[i];
+	for (i = 0, sum = 0; i < buflen; i += 2)
+		sum += (buf[i+1] << 8) + buf[i];
 
-  sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
+	sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
 
-  return sum & 0xffff;
+	return sum & 0xffff;
 }
 
 /*
@@ -284,578 +298,626 @@
 
 faim_export int aim_send_icon(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn, const unsigned char *icon, int iconlen, time_t stamp, unsigned short iconsum)
 {
-  struct command_tx_struct *np;
-  int i,curbyte = 0;
-  unsigned char ck[8];
+	struct command_tx_struct *np;
+	int i, curbyte = 0;
+	unsigned char ck[8];
 
-  if (!sess || !conn || !sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))
-    return -1;
+	if (!sess || !conn || !sn || !icon || 
+			(iconlen <= 0) || (iconlen >= MAXICONLEN))
+	return -EINVAL;
 
-  if (conn->type != AIM_CONN_TYPE_BOS)
-    return -1;
+	if (conn->type != AIM_CONN_TYPE_BOS)
+		return -EINVAL;
 
-  for (i = 0, curbyte = 0; i < 8; i++)
-    curbyte += aimutil_put8(ck+curbyte, (u_char)rand());
+	for (i = 0, curbyte = 0; i < 8; i++)
+		curbyte += aimutil_put8(ck+curbyte, (u_char)rand());
 
-  if (!(np = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 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 -1;
+	if (!(np = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 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;
 
-  np->lock = 1;
+	np->lock = 1;
 
-  curbyte = aim_putsnac(np->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
+	curbyte = aim_putsnac(np->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
 
-  /*
-   * Cookie
-   */
-  memcpy(np->data+curbyte, ck, 8);
-  curbyte += 8;
+	/*
+	 * Cookie
+	 */
+	memcpy(np->data+curbyte, ck, 8);
+	curbyte += 8;
 
-  /*
-   * Channel (2)
-   */
-  curbyte += aimutil_put16(np->data+curbyte, 0x0002);
+	/*
+	 * Channel (2)
+	 */
+	curbyte += aimutil_put16(np->data+curbyte, 0x0002);
 
-  /*
-   * Dest sn
-   */
-  curbyte += aimutil_put8(np->data+curbyte, strlen(sn));
-  curbyte += aimutil_putstr(np->data+curbyte, sn, strlen(sn));
+	/*
+	 * Dest sn
+	 */
+	curbyte += aimutil_put8(np->data+curbyte, strlen(sn));
+	curbyte += aimutil_putstr(np->data+curbyte, sn, strlen(sn));
 
-  /*
-   * TLV t(0005)
-   */
-  curbyte += aimutil_put16(np->data+curbyte, 0x0005);
-  curbyte += aimutil_put16(np->data+curbyte, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));
+	/*
+	 * TLV t(0005)
+	 */
+	curbyte += aimutil_put16(np->data+curbyte, 0x0005);
+	curbyte += aimutil_put16(np->data+curbyte, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));
 
-  curbyte += aimutil_put16(np->data+curbyte, 0x0000);
+	curbyte += aimutil_put16(np->data+curbyte, 0x0000);
 
-  memcpy(np->data+curbyte, ck, 8);
-  curbyte += 8;
+	memcpy(np->data+curbyte, ck, 8);
+	curbyte += 8;
 
-  curbyte += aim_putcap(np->data+curbyte, 16, AIM_CAPS_BUDDYICON);
+	curbyte += aim_putcap(np->data+curbyte, 16, AIM_CAPS_BUDDYICON);
 
-  /* TLV t(000a) */
-  curbyte += aimutil_put16(np->data+curbyte, 0x000a);
-  curbyte += aimutil_put16(np->data+curbyte, 0x0002);
-  curbyte += aimutil_put16(np->data+curbyte, 0x0001);
+	/* TLV t(000a) */
+	curbyte += aimutil_put16(np->data+curbyte, 0x000a);
+	curbyte += aimutil_put16(np->data+curbyte, 0x0002);
+	curbyte += aimutil_put16(np->data+curbyte, 0x0001);
 
-  /* TLV t(000f) */
-  curbyte += aimutil_put16(np->data+curbyte, 0x000f);
-  curbyte += aimutil_put16(np->data+curbyte, 0x0000);
+	/* TLV t(000f) */
+	curbyte += aimutil_put16(np->data+curbyte, 0x000f);
+	curbyte += aimutil_put16(np->data+curbyte, 0x0000);
 
-  /* TLV t(2711) */
-  curbyte += aimutil_put16(np->data+curbyte, 0x2711);
-  curbyte += aimutil_put16(np->data+curbyte, 4+4+4+iconlen+strlen(AIM_ICONIDENT));
-  curbyte += aimutil_put16(np->data+curbyte, 0x0000);
-  curbyte += aimutil_put16(np->data+curbyte, iconsum);
-  curbyte += aimutil_put32(np->data+curbyte, iconlen);
-  curbyte += aimutil_put32(np->data+curbyte, stamp);
-  memcpy(np->data+curbyte, icon, iconlen);
-  curbyte += iconlen;
-  memcpy(np->data+curbyte, AIM_ICONIDENT, strlen(AIM_ICONIDENT));
-  curbyte += strlen(AIM_ICONIDENT);
+	/* TLV t(2711) */
+	curbyte += aimutil_put16(np->data+curbyte, 0x2711);
+	curbyte += aimutil_put16(np->data+curbyte, 4+4+4+iconlen+strlen(AIM_ICONIDENT));
+	curbyte += aimutil_put16(np->data+curbyte, 0x0000);
+	curbyte += aimutil_put16(np->data+curbyte, iconsum);
+	curbyte += aimutil_put32(np->data+curbyte, iconlen);
+	curbyte += aimutil_put32(np->data+curbyte, stamp);
+	memcpy(np->data+curbyte, icon, iconlen);
+	curbyte += iconlen;
+	memcpy(np->data+curbyte, AIM_ICONIDENT, strlen(AIM_ICONIDENT));
+	curbyte += strlen(AIM_ICONIDENT);
 
-  /* TLV t(0003) */
-  curbyte += aimutil_put16(np->data+curbyte, 0x0003);
-  curbyte += aimutil_put16(np->data+curbyte, 0x0000);
-  
-  np->commandlen = curbyte;
-  np->lock = 0;
-  aim_tx_enqueue(sess, np);
+	/* TLV t(0003) */
+	curbyte += aimutil_put16(np->data+curbyte, 0x0003);
+	curbyte += aimutil_put16(np->data+curbyte, 0x0000);
 
-  return 0;
+	np->commandlen = curbyte;
+	np->lock = 0;
+	aim_tx_enqueue(sess, np);
+
+	return 0;
 }
 
 static int outgoingim(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  unsigned int i, ret = 0;
-  aim_rxcallback_t userfunc;
-  unsigned char cookie[8];
-  int channel;
-  struct aim_tlvlist_t *tlvlist;
-  char sn[MAXSNLEN];
-  unsigned short icbmflags = 0;
-  unsigned char flag1 = 0, flag2 = 0;
-  unsigned char *msgblock = NULL, *msg = NULL;
+	unsigned int i, ret = 0;
+	aim_rxcallback_t userfunc;
+	unsigned char cookie[8];
+	int channel;
+	struct aim_tlvlist_t *tlvlist;
+	char sn[MAXSNLEN];
+	unsigned short icbmflags = 0;
+	unsigned char flag1 = 0, flag2 = 0;
+	unsigned char *msgblock = NULL, *msg = NULL;
 
-  /* ICBM Cookie. */
-  for (i = 0; i < 8; i++)
-    cookie[i] = aimutil_get8(data+i);
+	/* ICBM Cookie. */
+	for (i = 0; i < 8; i++)
+		cookie[i] = aimutil_get8(data+i);
 
-  /* Channel ID */
-  channel = aimutil_get16(data+i);
-  i += 2;
+	/* Channel ID */
+	channel = aimutil_get16(data+i);
+	i += 2;
 
-  if (channel != 0x01) {
-    faimdprintf(sess, 0, "icbm: ICBM recieved on unsupported channel.  Ignoring. (chan = %04x)\n", channel);
-    return 1;
-  }
+	if (channel != 0x01) {
+		faimdprintf(sess, 0, "icbm: ICBM recieved on unsupported channel.  Ignoring. (chan = %04x)\n", channel);
+		return 1;
+	}
 
-  strncpy(sn, (char *) data+i+1, (int) *(data+i));
-  i += 1 + (int) *(data+i);
+	strncpy(sn, (char *) data+i+1, (int) *(data+i));
+	i += 1 + (int) *(data+i);
 
-  tlvlist = aim_readtlvchain(data+i, datalen-i);
+	tlvlist = aim_readtlvchain(data+i, datalen-i);
 
-  if (aim_gettlv(tlvlist, 0x0003, 1))
-    icbmflags |= AIM_IMFLAGS_ACK;
-  if (aim_gettlv(tlvlist, 0x0004, 1))
-    icbmflags |= AIM_IMFLAGS_AWAY;
-
-  if (aim_gettlv(tlvlist, 0x0002, 1)) {
-    int j = 0;
+	if (aim_gettlv(tlvlist, 0x0003, 1))
+		icbmflags |= AIM_IMFLAGS_ACK;
+	if (aim_gettlv(tlvlist, 0x0004, 1))
+		icbmflags |= AIM_IMFLAGS_AWAY;
 
-    msgblock = (unsigned char *)aim_gettlv_str(tlvlist, 0x0002, 1);
+	if ((msgblock = (unsigned char *)aim_gettlv_str(tlvlist, 0x0002, 1))) {
+		int j = 0;
 
-    /* no, this really is correct.  I'm not high or anything either. */
-    j += 2;
-    j += 2 + aimutil_get16(msgblock+j);
-    j += 2;
-    
-    j += 2; /* final block length */
+		/* no, this really is correct.  I'm not high or anything either. */
+		j += 2;
+		j += 2 + aimutil_get16(msgblock+j);
+		j += 2;
+
+		j += 2; /* final block length */
 
-    flag1 = aimutil_get16(msgblock);
-    j += 2;
-    flag2 = aimutil_get16(msgblock);
-    j += 2;
-    
-    msg = msgblock+j;
-  }
+		flag1 = aimutil_get16(msgblock);
+		j += 2;
+		flag2 = aimutil_get16(msgblock);
+		j += 2;
+
+		msg = msgblock+j;
+	}
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2);
-  
-  if (msgblock)
-    free(msgblock);
-  aim_freetlvchain(&tlvlist);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2);
 
-  return ret;
+	free(msgblock);
+	aim_freetlvchain(&tlvlist);
+
+	return ret;
 }
 
+/*
+ * A multipart IM:
+ *
+ * 0004 0007 0000 8f08 d295 
+ *      0031 6520 3b7b f9fd
+ * 	0001 
+ * 	06 XXXX XXXX XXXX
+ * 	0000 
+ * 	0004 
+ * 		0001 0002 0004 
+ * 		0010 0004 0000 01a3
+ * 		0002 0004 3ab6 94fa
+ * 		0003 0004 3b7b f85a
+ * 	0002 003c 
+ * 		0501 0001 01
+ * 		0101 000a 0000 0000 3c48 544d 4c3e   ASCII part 
+ * 		ISO-8859 part:
+ * 		0101 0016 0003 0000 6c6b 7364 6a6b 6c6a 676c a56b 3b73 646a 6b6a
+ * 		0101 000b 0000 0000 3c2f 4854 4d4c 3e   another ASCII part
+ *
+ */
 static int incomingim_ch1(struct aim_session_t *sess, aim_module_t *mod,  struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned short channel, struct aim_userinfo_s *userinfo, unsigned char *data, int datalen, unsigned char *cookie)
 {
-  unsigned short type, length;
-  aim_rxcallback_t userfunc;
-  int i, ret = 0;
-  struct aim_incomingim_ch1_args args;
+	unsigned short type, length;
+	aim_rxcallback_t userfunc;
+	int i, ret = 0;
+	struct aim_incomingim_ch1_args args;
 
-  memset(&args, 0, sizeof(args));
+	memset(&args, 0, sizeof(args));
 
-  /*
-   * 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.
-   */
-  for (i = 0; i < datalen; ) {
-      
-    type = aimutil_get16(data+i);
-    i += 2;
-      
-    length = aimutil_get16(data+i);
-    i += 2;
+	/*
+	 * 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.
+	 */
+	for (i = 0; i < datalen; ) {
 
-    if (type == 0x0002) { /* Message Block */
-      unsigned short wastebits;
-      unsigned char *msgblock;
-      int j = 0, y = 0, z = 0;
+		type = aimutil_get16(data+i);
+		i += 2;
+		      
+		length = aimutil_get16(data+i);
+		i += 2;
+
+		if (type == 0x0002) { /* Message Block */
+			unsigned short wastebits;
+			unsigned char *msgblock;
+			int j = 0, y = 0, z = 0;
 
-      msgblock = data+i;
-      
-      /*
-       * Extracting the message from the unknown cruft.
-       * 
-       * This is a bit messy, and I'm not really qualified,
-       * even as the author, to comment on it.  At least
-       * its not as bad as a while loop shooting into infinity.
-       *
-       * "Do you believe in magic?"
-       *
-       */
+			msgblock = data+i;
+			      
+			/*
+			 * Extracting the message from the unknown cruft.
+			 * 
+			 * This is a bit messy, and I'm not really qualified,
+			 * even as the author, to comment on it.  At least
+			 * its not as bad as a while loop shooting into 
+			 * infinity.
+			 *
+			 * "Do you believe in magic?"
+			 *
+			 */
 
-      wastebits = aimutil_get8(msgblock+j++);
-      wastebits = aimutil_get8(msgblock+j++);
-      
-      y = aimutil_get16(msgblock+j);
-      j += 2;
-      for (z = 0; z < y; z++)
-	wastebits = aimutil_get8(msgblock+j++);
-      wastebits = aimutil_get8(msgblock+j++);
-      wastebits = aimutil_get8(msgblock+j++);
+			wastebits = aimutil_get8(msgblock+j++);
+			wastebits = aimutil_get8(msgblock+j++);
+			      
+			y = aimutil_get16(msgblock+j);
+			j += 2;
+			for (z = 0; z < y; z++)
+				wastebits = aimutil_get8(msgblock+j++);
+			wastebits = aimutil_get8(msgblock+j++);
+			wastebits = aimutil_get8(msgblock+j++);
 
-      args.finlen = j;
-      if (args.finlen > sizeof(args.fingerprint))
-	args.finlen = sizeof(args.fingerprint);
-      memcpy(args.fingerprint, msgblock, args.finlen);
+			args.finlen = j;
+			if (args.finlen > sizeof(args.fingerprint))
+				args.finlen = sizeof(args.fingerprint);
+			memcpy(args.fingerprint, msgblock, args.finlen);
+
+			/* Message string length, including flag words. */
+			args.msglen = aimutil_get16(msgblock+j);
+			j += 2;
 
-      /* Message string length, including flag words. */
-      args.msglen = aimutil_get16(msgblock+j);
-      j += 2;
+			/* Flag words. */
+			args.flag1 = aimutil_get16(msgblock+j);
+			if (args.flag1 == 0x0000)
+				; /* ASCII */
+			else if (args.flag1 == 0x0002)
+				args.icbmflags |= AIM_IMFLAGS_UNICODE;
+			else if (args.flag1 == 0x0003)
+				args.icbmflags |= AIM_IMFLAGS_ISO_8859_1;
+			else if (args.flag1 == 0xffff)
+				; /* no encoding (yeep!) */
+			j += 2;
 
-      /* Flag words. */
-      args.flag1 = aimutil_get16(msgblock+j);
-      if (args.flag1 == 0x0002)
-	args.icbmflags |= AIM_IMFLAGS_UNICODE;
-      else if (args.flag1 == 0x0003)
-	args.icbmflags |= AIM_IMFLAGS_ISO_8859_1;
-      j += 2;
-
-      args.flag2 = aimutil_get16(msgblock+j);
-      j += 2;
-      
-      if ((args.flag1 && (args.flag1 != 0x0002) && (args.flag1 != 0x0003)) || args.flag2)
-	faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2);
+			args.flag2 = aimutil_get16(msgblock+j);
+			if (args.flag2 == 0x0000)
+				; /* standard subencoding? */
+			else if (args.flag2 == 0x000b)
+				args.icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH;
+			else if (args.flag2 == 0xffff)
+				; /* no subencoding */
+			j += 2;
+			
+			if (	((args.flag1 != 0x0000) &&
+				 (args.flag1 != 0x0002) &&
+				 (args.flag1 != 0x0003) &&
+				 (args.flag1 != 0xffff)) ||
+				((args.flag2 != 0x0000) &&
+				 (args.flag2 != 0x000b) &&
+				 (args.flag2 != 0xffff))) {
+				faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2);
+			}
 
-      /* Message string. */
-      args.msglen -= 4;
-      if (args.icbmflags & AIM_IMFLAGS_UNICODE) {
-	args.msg = malloc(args.msglen+2);
-	memcpy(args.msg, msgblock+j, args.msglen);
-	args.msg[args.msglen] = '\0'; /* wide NULL */
-	args.msg[args.msglen+1] = '\0';
-      } else {
-	args.msg = malloc(args.msglen+1);
-	memcpy(args.msg, msgblock+j, args.msglen);
-	args.msg[args.msglen] = '\0';
-      }
+			/* Message string. */
+			args.msglen -= 4;
+			if (args.icbmflags & AIM_IMFLAGS_UNICODE) {
+				args.msg = malloc(args.msglen+2);
+				memcpy(args.msg, msgblock+j, args.msglen);
+				args.msg[args.msglen] = '\0'; /* wide NULL */
+				args.msg[args.msglen+1] = '\0';
+			} else {
+				args.msg = malloc(args.msglen+1);
+				memcpy(args.msg, msgblock+j, args.msglen);
+				args.msg[args.msglen] = '\0';
+			}
 
-    } else if (type == 0x0003) { /* Server Ack Requested */
+		} else if (type == 0x0003) { /* Server Ack Requested */
+
+			args.icbmflags |= AIM_IMFLAGS_ACK;
 
-      args.icbmflags |= AIM_IMFLAGS_ACK;
+		} else if (type == 0x0004) { /* Message is Auto Response */
 
-    } else if (type == 0x0004) { /* Message is Auto Response */
+			args.icbmflags |= AIM_IMFLAGS_AWAY;
 
-      args.icbmflags |= AIM_IMFLAGS_AWAY;
+		} else if ((type == 0x0008) && (length == 0x000c)) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
 
-    } else if ((type == 0x0008) && 
-	       (length == 0x000c)) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
+			args.iconstamp = aimutil_get32(data+i+8);
+			args.icbmflags |= AIM_IMFLAGS_HASICON;
 
-      args.iconstamp = aimutil_get32(data+i+8);
-      args.icbmflags |= AIM_IMFLAGS_HASICON;
+		} else if (type == 0x0009) {
+
+			args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
 
-    } else if (type == 0x0009) {
+		} else if (type == 0x0017) {
 
-      args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
+			args.extdatalen = length;
+			args.extdata = data+i;
 
-    } else {
-      fprintf(stderr, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length);
-    }
+		} else {
+			faimdprintf(sess, 0, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length);
+		}
 
-    i += length;
-  }
+		i += length;
+	}
 
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret = userfunc(sess, rx, channel, userinfo, &args);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, channel, userinfo, &args);
 
-  free(args.msg);
+	free(args.msg);
 
-  return ret;
+	return ret;
 }
 
 static int incomingim_ch2(struct aim_session_t *sess, aim_module_t *mod,  struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned short channel, struct aim_userinfo_s *userinfo, struct aim_tlvlist_t *tlvlist, unsigned char *cookie)
 {
-  aim_rxcallback_t userfunc;
-  struct aim_tlv_t *block1;
-  struct aim_tlvlist_t *list2;
-  int ret = 0;
-  struct aim_incomingim_ch2_args args;
+	aim_rxcallback_t userfunc;
+	struct aim_tlv_t *block1;
+	struct aim_tlvlist_t *list2;
+	int ret = 0;
+	struct aim_incomingim_ch2_args args;
+
+	memset(&args, 0, sizeof(args));
 
-  memset(&args, 0, sizeof(args));
-      
-  /*
-   * There's another block of TLVs embedded in the type 5 here. 
-   */
-  block1 = aim_gettlv(tlvlist, 0x0005, 1);
-  if (!block1 || !block1->value) {
-    faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n");
-    return 0;
-  }
+	/*
+	 * There's another block of TLVs embedded in the type 5 here. 
+	 */
+	if (!(block1 = aim_gettlv(tlvlist, 0x0005, 1)) || !block1->value) {
+		faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n");
+		return 0;
+	}
 
-  /*
-   * First two bytes represent the status of the connection.
-   *
-   * 0 is a request, 2 is an accept
-   */ 
-  args.status = aimutil_get16(block1->value+0);
-      
-  /*
-   * Next comes the cookie.  Should match the ICBM cookie.
-   */
-  if (memcmp(block1->value+2, cookie, 8) != 0) 
-    faimdprintf(sess, 0, "rend: warning cookies don't match!\n");
+	/*
+	 * First two bytes represent the status of the connection.
+	 *
+	 * 0 is a request, 2 is an accept
+	 */ 
+	args.status = aimutil_get16(block1->value+0);
+
+	/*
+	 * Next comes the cookie.  Should match the ICBM cookie.
+	 */
+	if (memcmp(block1->value+2, cookie, 8) != 0) 
+		faimdprintf(sess, 0, "rend: warning cookies don't match!\n");
 
-  /*
-   * The next 16bytes are a capability block so we can
-   * identify what type of rendezvous this is.
-   *
-   * Thanks to Eric Warmenhoven <warmenhoven@linux.com> (of GAIM)
-   * for pointing some of this out to me.  In fact, a lot of 
-   * the client-to-client info comes from the work of the GAIM 
-   * developers. Thanks!
-   *
-   * Read off one capability string and we should have it ID'd.
-   * 
-   */
-  if ((args.reqclass = aim_getcap(sess, block1->value+2+8, 0x10)) == 0x0000) {
-    faimdprintf(sess, 0, "rend: no ID block\n");
-    return 0;
-  }
+	/*
+	 * The next 16bytes are a capability block so we can
+	 * identify what type of rendezvous this is.
+	 *
+	 * Thanks to Eric Warmenhoven <warmenhoven@linux.com> (of GAIM)
+	 * for pointing some of this out to me.  In fact, a lot of 
+	 * the client-to-client info comes from the work of the GAIM 
+	 * developers. Thanks!
+	 *
+	 * Read off one capability string and we should have it ID'd.
+	 * 
+	 */
+	if ((args.reqclass = aim_getcap(sess, block1->value+2+8, 0x10)) == 0x0000) {
+		faimdprintf(sess, 0, "rend: no ID block\n");
+		return 0;
+	}
 
-  /* 
-   * 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_readtlvchain(block1->value+2+8+16, block1->length-2-8-16);
-      
-  if (!list2 || ((args.reqclass != AIM_CAPS_IMIMAGE) && !(aim_gettlv(list2, 0x2711, 1)))) {
-    struct aim_msgcookie_t *cook;
-    int type;
-	
-    type = aim_msgcookie_gettype(args.reqclass); /* XXX: fix this shitty code */
+	/* 
+	* 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_readtlvchain(block1->value+2+8+16, block1->length-2-8-16);
+
+	if (!list2 || ((args.reqclass != AIM_CAPS_IMIMAGE) && !(aim_gettlv(list2, 0x2711, 1)))) {
+		struct aim_msgcookie_t *cook;
+		int type;
+
+		type = aim_msgcookie_gettype(args.reqclass); /* XXX: fix this shitty code */
 
-    if ((cook = aim_checkcookie(sess, cookie, type)) == NULL) {
-      faimdprintf(sess, 0, "non-data rendezvous thats not in cache %d/%s!\n", type, cookie);
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if ((cook = aim_checkcookie(sess, cookie, type)) == NULL) {
+			faimdprintf(sess, 0, "non-data rendezvous thats not in cache (type %d)\n", type);
+		aim_freetlvchain(&list2);
+		return 1;
+		}
 
-    if (cook->type == AIM_COOKIETYPE_OFTGET) {
-      struct aim_filetransfer_priv *ft;
+		if (cook->type == AIM_COOKIETYPE_OFTGET) {
+			struct aim_filetransfer_priv *ft;
 
-      if (cook->data) {
-	int errorcode = -1; /* XXX shouldnt this be 0? */
+			if (cook->data) {
+				int errorcode = -1; /* XXX shouldnt this be 0? */
+
+				ft = (struct aim_filetransfer_priv *)cook->data;
 
-	ft = (struct aim_filetransfer_priv *)cook->data;
+				if (args.status != 0x0002) {
 
-	if (args.status != 0x0002) {
+				  if (aim_gettlv(list2, 0x000b, 1))
+					    errorcode = aim_gettlv16(list2, 0x000b, 1);
 
-	  if (aim_gettlv(list2, 0x000b, 1))
-	    errorcode = aim_gettlv16(list2, 0x000b, 1);
+				  /* XXX this should make it up to the client, you know.. */
+				  if (errorcode)
+					faimdprintf(sess, 0, "transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sn, ft->ip, ft->fh.name, errorcode);
+				} /* args.status != 0x0002 */
+				
+			} else {
+				faimdprintf(sess, 0, "no data attached to file transfer\n");
+			} /* !cook->data */
+
+		} else if (cook->type == AIM_CAPS_VOICE) {
 
-	  /* XXX this should make it up to the client, you know.. */
-	  if (errorcode)
-	    faimdprintf(sess, 0, "transfer from %s (%s) for %s cancelled (error code %d)\n", ft->sn, ft->ip, ft->fh.name, errorcode);
+			faimdprintf(sess, 0, "voice request cancelled\n");
+		
+		} else {
+		
+			faimdprintf(sess, 0, "unknown cookie cache type %d\n", cook->type);
+		}
+
+		aim_freetlvchain(&list2);
+
+		return 1;
 	}
-      } else {
-	faimdprintf(sess, 0, "no data attached to file transfer\n");
-      }
-    } else if (cook->type == AIM_CAPS_VOICE) {
-      faimdprintf(sess, 0, "voice request cancelled\n");
-    } else {
-      faimdprintf(sess, 0, "unknown cookie cache type %d\n", cook->type);
-    }
-	
-    aim_freetlvchain(&list2);
 
-    return 1;
-  }
+	/*
+	 * The rest of the handling depends on what type it is.
+	 */
+	if (args.reqclass & AIM_CAPS_BUDDYICON) {
+		struct aim_tlv_t *miscinfo;
+		int curpos = 0;
 
-  /*
-   * The rest of the handling depends on what type it is.
-   */
-  if (args.reqclass & AIM_CAPS_BUDDYICON) {
-    struct aim_tlv_t *miscinfo;
-    int curpos = 0;
-
-    miscinfo = aim_gettlv(list2, 0x2711, 1);
+		miscinfo = aim_gettlv(list2, 0x2711, 1);
 
-    /* aimutil_get32(miscinfo->value+curpos); i don't know what this is */
-    curpos += 4;
-    args.info.icon.length = aimutil_get32(miscinfo->value+curpos);
-    curpos += 4;
-    args.info.icon.timestamp = aimutil_get32(miscinfo->value+curpos);
-    curpos += 4;
-    args.info.icon.icon = malloc(args.info.icon.length);
-    memcpy(args.info.icon.icon, miscinfo->value+curpos, args.info.icon.length);
+		/* aimutil_get32(miscinfo->value+curpos); i don't know what this is */
+		curpos += 4;
+		args.info.icon.length = aimutil_get32(miscinfo->value+curpos);
+		curpos += 4;
+		args.info.icon.timestamp = aimutil_get32(miscinfo->value+curpos);
+		curpos += 4;
+		args.info.icon.icon = malloc(args.info.icon.length);
+		memcpy(args.info.icon.icon, miscinfo->value+curpos, args.info.icon.length);
 
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
-    free(args.info.icon.icon);
+		free(args.info.icon.icon);
 
-  } else if (args.reqclass & AIM_CAPS_VOICE) {
-    struct aim_msgcookie_t *cachedcook;
+	} else if (args.reqclass & AIM_CAPS_VOICE) {
+		struct aim_msgcookie_t *cachedcook;
 
-    faimdprintf(sess, 0, "rend: voice!\n");
+		faimdprintf(sess, 1, "rend: voice!\n");
 
-    if(!(cachedcook = (struct aim_msgcookie_t*)calloc(1, sizeof(struct aim_msgcookie_t)))) {
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if(!(cachedcook = (struct aim_msgcookie_t*)calloc(1, sizeof(struct aim_msgcookie_t)))) {
+			aim_freetlvchain(&list2);
+			return 0;
+		}
 
-    memcpy(cachedcook->cookie, cookie, 8);
-    cachedcook->type = AIM_COOKIETYPE_OFTVOICE;
-    cachedcook->data = NULL;
+		memcpy(cachedcook->cookie, cookie, 8);
+		cachedcook->type = AIM_COOKIETYPE_OFTVOICE;
+		cachedcook->data = NULL;
 
-    if (aim_cachecookie(sess, cachedcook) == -1)
-      faimdprintf(sess, 0, "ERROR caching message cookie\n");
+		if (aim_cachecookie(sess, cachedcook) == -1)
+			faimdprintf(sess, 0, "ERROR caching message cookie\n");
 
-    /* XXX: implement all this */
+		/* XXX: implement all this */
 
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
-  } else if (args.reqclass & AIM_CAPS_IMIMAGE) {
-    char ip[30];
-    struct aim_directim_priv *priv;
+	} else if (args.reqclass & AIM_CAPS_IMIMAGE) {
+		char ip[30];
+		struct aim_directim_priv *priv;
 
-    memset(ip, 0, sizeof(ip));
-	
-    if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0005, 1)) {
-      struct aim_tlv_t *iptlv, *porttlv;
-	  
-      iptlv = aim_gettlv(list2, 0x0003, 1);
-      porttlv = aim_gettlv(list2, 0x0005, 1);
+		memset(ip, 0, sizeof(ip));
+
+		if (aim_gettlv(list2, 0x0003, 1) && aim_gettlv(list2, 0x0005, 1)) {
+			struct aim_tlv_t *iptlv, *porttlv;
+			  
+			iptlv = aim_gettlv(list2, 0x0003, 1);
+			porttlv = aim_gettlv(list2, 0x0005, 1);
 
-      snprintf(ip, 30, "%d.%d.%d.%d:%d", 
-	       aimutil_get8(iptlv->value+0),
-	       aimutil_get8(iptlv->value+1),
-	       aimutil_get8(iptlv->value+2),
-	       aimutil_get8(iptlv->value+3),
-	       4443 /*aimutil_get16(porttlv->value)*/);
-    }
+			snprintf(ip, 30, "%d.%d.%d.%d:%d", 
+				aimutil_get8(iptlv->value+0),
+				aimutil_get8(iptlv->value+1),
+				aimutil_get8(iptlv->value+2),
+				aimutil_get8(iptlv->value+3),
+				4443 /*aimutil_get16(porttlv->value)*/);
+		}
 
-    faimdprintf(sess, 0, "rend: directIM request from %s (%s)\n",
-		userinfo->sn, ip);
+		faimdprintf(sess, 1, "rend: directIM request from %s (%s)\n",
+				userinfo->sn, ip);
 
-    /* 
-     * XXX: there are a couple of different request packets for
-     *          different things 
-     */
+		/* 
+		 * XXX: there are a couple of different request packets for
+		 *          different things 
+		 */
 
-    args.info.directim = priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
-    memcpy(priv->ip, ip, sizeof(priv->ip));
-    memcpy(priv->sn, userinfo->sn, sizeof(priv->sn));
-    memcpy(priv->cookie, cookie, sizeof(priv->cookie));
+		args.info.directim = priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)); /* XXX error */
+		memcpy(priv->ip, ip, sizeof(priv->ip));
+		memcpy(priv->sn, userinfo->sn, sizeof(priv->sn));
+		memcpy(priv->cookie, cookie, sizeof(priv->cookie));
 
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
-  } else if (args.reqclass & AIM_CAPS_CHAT) {
-    struct aim_tlv_t *miscinfo;
+	} else if (args.reqclass & AIM_CAPS_CHAT) {
+		struct aim_tlv_t *miscinfo;
 
-    miscinfo = aim_gettlv(list2, 0x2711, 1);
-    aim_chat_readroominfo(miscinfo->value, &args.info.chat.roominfo);
-		  
-    if (aim_gettlv(list2, 0x000c, 1))
-      args.info.chat.msg = aim_gettlv_str(list2, 0x000c, 1);
-	  
-    if (aim_gettlv(list2, 0x000d, 1))
-      args.info.chat.encoding = aim_gettlv_str(list2, 0x000d, 1);
-	  
-    if (aim_gettlv(list2, 0x000e, 1))
-      args.info.chat.lang = aim_gettlv_str(list2, 0x000e, 1);
-      
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		miscinfo = aim_gettlv(list2, 0x2711, 1);
+		aim_chat_readroominfo(miscinfo->value, &args.info.chat.roominfo);
+			  
+		if (aim_gettlv(list2, 0x000c, 1))
+			args.info.chat.msg = aim_gettlv_str(list2, 0x000c, 1);
+		
+		if (aim_gettlv(list2, 0x000d, 1))
+			args.info.chat.encoding = aim_gettlv_str(list2, 0x000d, 1);
+		
+		if (aim_gettlv(list2, 0x000e, 1))
+			args.info.chat.lang = aim_gettlv_str(list2, 0x000e, 1);
+
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
-    free(args.info.chat.roominfo.name);
-    free(args.info.chat.msg);
-    free(args.info.chat.encoding);
-    free(args.info.chat.lang);
+		free(args.info.chat.roominfo.name);
+		free(args.info.chat.msg);
+		free(args.info.chat.encoding);
+		free(args.info.chat.lang);
 
-  } else if (args.reqclass & AIM_CAPS_GETFILE) {
-    char ip[30];
-    struct aim_msgcookie_t *cachedcook;
-    struct aim_tlv_t *miscinfo;
-    struct aim_tlv_t *iptlv, *porttlv;
+	} else if (args.reqclass & AIM_CAPS_GETFILE) {
+		char ip[30];
+		struct aim_msgcookie_t *cachedcook;
+		struct aim_tlv_t *miscinfo;
+		struct aim_tlv_t *iptlv, *porttlv;
 
-    memset(ip, 0, 30);
+		memset(ip, 0, 30);
 
-    if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) {
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) {
+			aim_freetlvchain(&list2);
+			return 0;
+		}
 
-    if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || 
-	!(iptlv = aim_gettlv(list2, 0x0003, 1)) || 
-	!(porttlv = aim_gettlv(list2, 0x0005, 1))) {
-      faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn);
-      aim_cookie_free(sess, cachedcook);
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || 
+			!(iptlv = aim_gettlv(list2, 0x0003, 1)) || 
+			!(porttlv = aim_gettlv(list2, 0x0005, 1))) {
+			
+			faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn);
+			aim_cookie_free(sess, cachedcook);
+			aim_freetlvchain(&list2);
+			
+			return 0;
+		}
 
-    snprintf(ip, 30, "%d.%d.%d.%d:%d",
-	     aimutil_get8(iptlv->value+0),
-	     aimutil_get8(iptlv->value+1),
-	     aimutil_get8(iptlv->value+2),
-	     aimutil_get8(iptlv->value+3),
-	     aimutil_get16(porttlv->value));
+		snprintf(ip, 30, "%d.%d.%d.%d:%d",
+			aimutil_get8(iptlv->value+0),
+			aimutil_get8(iptlv->value+1),
+			aimutil_get8(iptlv->value+2),
+			aimutil_get8(iptlv->value+3),
+			aimutil_get16(porttlv->value));
 
-    faimdprintf(sess, 0, "rend: file get request from %s (%s)\n", userinfo->sn, ip);
+		faimdprintf(sess, 0, "rend: file get request from %s (%s)\n", userinfo->sn, ip);
 
-    args.info.getfile.ip = ip;
-    args.info.getfile.cookie = cookie;
+		args.info.getfile.ip = ip;
+		args.info.getfile.cookie = cookie;
 
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
-  } else if (args.reqclass & AIM_CAPS_SENDFILE) {
-#if 0
-    char ip[30];
-    struct aim_msgcookie_t *cachedcook;
-    struct aim_tlv_t *miscinfo;
-    struct aim_tlv_t *iptlv, *porttlv;
+	} else if (args.reqclass & AIM_CAPS_SENDFILE) {
+#if 0 
+		char ip[30];
+		struct aim_msgcookie_t *cachedcook;
+		struct aim_tlv_t *miscinfo;
+		struct aim_tlv_t *iptlv, *porttlv;
 
-    memset(ip, 0, 30);
+		memset(ip, 0, 30);
 
-    if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) {
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if (!(cachedcook = calloc(1, sizeof(struct aim_msgcookie_t)))) {
+			aim_freetlvchain(&list2);
+			return 0;
+		}
 
-    if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || 
-	!(iptlv = aim_gettlv(list2, 0x0003, 1)) || 
-	!(porttlv = aim_gettlv(list2, 0x0005, 1))) {
-      faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn);
-      aim_cookie_free(sess, cachedcook);
-      aim_freetlvchain(&list2);
-      return 0;
-    }
+		if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)) || 
+			!(iptlv = aim_gettlv(list2, 0x0003, 1)) || 
+			!(porttlv = aim_gettlv(list2, 0x0005, 1))) {
+		
+			faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn);
+			aim_cookie_free(sess, cachedcook);
+			aim_freetlvchain(&list2);
 
-    snprintf(ip, 30, "%d.%d.%d.%d:%d",
-	     aimutil_get8(iptlv->value+0),
-	     aimutil_get8(iptlv->value+1),
-	     aimutil_get8(iptlv->value+2),
-	     aimutil_get8(iptlv->value+3),
-	     aimutil_get16(porttlv->value));
+			return 0;
+		}
 
-    if (aim_gettlv(list2, 0x000c, 1))
-      desc = aim_gettlv_str(list2, 0x000c, 1);
+		snprintf(ip, 30, "%d.%d.%d.%d:%d",
+			aimutil_get8(iptlv->value+0),
+			aimutil_get8(iptlv->value+1),
+			aimutil_get8(iptlv->value+2),
+			aimutil_get8(iptlv->value+3),
+			aimutil_get16(porttlv->value));
+
+		if (aim_gettlv(list2, 0x000c, 1))
+			desc = aim_gettlv_str(list2, 0x000c, 1);
 
-    faimdprintf(sess, 0, "rend: file transfer request from %s for %s: %s (%s)\n",
-		userinfo->sn, miscinfo->value+8,
-		desc, ip);
-	
-    memcpy(cachedcook->cookie, cookie, 8);
-	
-    ft = malloc(sizeof(struct aim_filetransfer_priv));
-    strncpy(ft->sn, userinfo.sn, sizeof(ft->sn));
-    strncpy(ft->ip, ip, sizeof(ft->ip));
-    strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name));
-    cachedcook->type = AIM_COOKIETYPE_OFTSEND;
-    cachedcook->data = ft;
+		faimdprintf(sess, 0, "rend: file transfer request from %s: %s (%s)\n",
+			userinfo->sn, desc, ip);
+
+		memcpy(cachedcook->cookie, cookie, 8);
 
-    if (aim_cachecookie(sess, cachedcook) == -1)
-      faimdprintf(sess, 0, "ERROR caching message cookie\n");
+		ft = malloc(sizeof(struct aim_filetransfer_priv)); /* XXX */
+		strncpy(ft->sn, userinfo.sn, sizeof(ft->sn));
+		strncpy(ft->ip, ip, sizeof(ft->ip));
+		strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name));
+		cachedcook->type = AIM_COOKIETYPE_OFTSEND;
+		cachedcook->data = ft;
 
-    aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE);
-	
-    if (desc)
-      free(desc);
+		if (aim_cachecookie(sess, cachedcook) == -1)
+			faimdprintf(sess, 0, "ERROR caching message cookie\n");
+
+		aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE);
 
-    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-      ret = userfunc(sess, rx, channel, userinfo, &args);
+		if (desc)
+			free(desc);
+
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			ret = userfunc(sess, rx, channel, userinfo, &args);
 
 #endif	
-  } else
-    faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass);
+	} else
+		faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass);
 
-  aim_freetlvchain(&list2);
+	aim_freetlvchain(&list2);
 
-  return ret;
+	return ret;
 }
 
 /*
@@ -871,90 +933,90 @@
  */
 static int incomingim(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  int i, ret = 0;
-  unsigned char cookie[8];
-  int channel;
-  struct aim_userinfo_s userinfo;
+	int i, ret = 0;
+	unsigned char cookie[8];
+	int channel;
+	struct aim_userinfo_s userinfo;
+
+	memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s));
+
+	/*
+	 * Read ICBM Cookie.  And throw away.
+	 */
+	for (i = 0; i < 8; i++)
+		cookie[i] = aimutil_get8(data+i);
 
-  memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s));
- 
-  /*
-   * Read ICBM Cookie.  And throw away.
-   */
-  for (i = 0; i < 8; i++)
-    cookie[i] = aimutil_get8(data+i);
-  
-  /*
-   * Channel ID.
-   *
-   * Channel 0x0001 is the message channel.  There are 
-   * other channels for things called "rendevous"
-   * which represent chat and some of the other new
-   * features of AIM2/3/3.5. 
-   *
-   * Channel 0x0002 is the Rendevous channel, which
-   * is where Chat Invitiations and various client-client
-   * connection negotiations come from.
-   * 
-   */
-  channel = aimutil_get16(data+i);
-  i += 2;
-  
-  /*
-   *
-   */
-  if ((channel != 0x01) && (channel != 0x02)) {
-    faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.\n (chan = %04x)", channel);
-    return 1;
-  }
+	/*
+	 * Channel ID.
+	 *
+	 * Channel 0x0001 is the message channel.  There are 
+	 * other channels for things called "rendevous"
+	 * which represent chat and some of the other new
+	 * features of AIM2/3/3.5. 
+	 *
+	 * Channel 0x0002 is the Rendevous channel, which
+	 * is where Chat Invitiations and various client-client
+	 * connection negotiations come from.
+	 * 
+	 */
+	channel = aimutil_get16(data+i);
+	i += 2;
+
+	/*
+	 * Technically Channel 3 in chat could be done here too.
+	 */
+	if ((channel != 0x01) && (channel != 0x02)) {
+		faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel.  Ignoring.\n (chan = %04x)", channel);
+		return 1;
+	}
 
-  /*
-   * 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.
-   * aim_extractuserinfo() returns the number of bytes used by the
-   * userinfo tlvs, so you can start reading the rest of them right
-   * afterward.  
-   *
-   * 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.
-   * 
-   */
-  i += aim_extractuserinfo(sess, data+i, &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) {
+	/*
+	 * 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.
+	 * aim_extractuserinfo() returns the number of bytes used by the
+	 * userinfo tlvs, so you can start reading the rest of them right
+	 * afterward.  
+	 *
+	 * 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.
+	 * 
+	 */
+	i += aim_extractuserinfo(sess, data+i, &userinfo);
 
-    ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, data+i, datalen-i, cookie);
+	/*
+	 * 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) {
 
-  } else if (channel == 0x0002) {
-    struct aim_tlvlist_t *tlvlist;
+		ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, data+i, datalen-i, cookie);
+
+	} else if (channel == 0x0002) {
+		struct 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_readtlvchain(data+i, datalen-i);
+		/*
+		 * Read block of TLVs (not including the userinfo data).  All 
+		 * further data is derived from what is parsed here.
+		 */
+		tlvlist = aim_readtlvchain(data+i, datalen-i);
 
-    ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
+		ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
 
-    /*
-     * Free up the TLV chain.
-     */
-    aim_freetlvchain(&tlvlist);
-  }
+		/*
+		 * Free up the TLV chain.
+		 */
+		aim_freetlvchain(&tlvlist);
+	}
 
-  return ret;
+	return ret;
 }
 
 /*
@@ -964,184 +1026,190 @@
  *    AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"
  * 
  */
-faim_export unsigned long aim_denytransfer(struct aim_session_t *sess,
-					   struct aim_conn_t *conn, 
-					   char *sender,
-					   char *cookie, 
-					   unsigned short code)
+faim_export int aim_denytransfer(struct aim_session_t *sess,
+					struct aim_conn_t *conn, 
+					const char *sender,
+					const char *cookie, 
+					unsigned short code)
 {
-  struct command_tx_struct *newpacket;
-  int curbyte, i;
+	struct command_tx_struct *newpacket;
+	int curbyte, i;
 
-  if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sender)+6)))
-    return -1;
+	if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sender)+6)))
+		return -ENOMEM;
 
-  newpacket->lock = 1;
+	newpacket->lock = 1;
 
-  curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid);
-  for (i = 0; i < 8; i++)
-    curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
-  curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender));
-  curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender));
-  curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code);
+	curbyte = aim_putsnac(newpacket->data, 0x0004, 0x000b, 0x0000, sess->snac_nextid++);
+	for (i = 0; i < 8; i++)
+		curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
+	curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
+	curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sender));
+	curbyte += aimutil_putstr(newpacket->data+curbyte, sender, strlen(sender));
+	curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0003, code);
 
-  newpacket->lock = 0;
-  aim_tx_enqueue(sess, newpacket);
+	newpacket->lock = 0;
+	aim_tx_enqueue(sess, newpacket);
 
-  return (sess->snac_nextid++);
+	return 0;
 }
 
 /*
- * Not real sure what this does, nor does anyone I've talk to.
+ * aim_reqicbmparaminfo()
+ *
+ * Request ICBM parameter information.
  *
- * Didn't use to send it.  But now I think it might be a good
- * idea. 
+ */
+faim_export unsigned long aim_reqicbmparams(struct aim_session_t *sess, struct aim_conn_t *conn)
+{
+	return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
+}
+
+/*
  *
  */
-faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess,
-					   struct aim_conn_t *conn)
+faim_export unsigned long aim_seticbmparam(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_icbmparameters *params)
 {
-  struct command_tx_struct *newpacket;
-  int curbyte;
+	struct command_tx_struct *newpacket;
+	int curbyte;
+
+	if (!sess || !conn || !params)
+		return -EINVAL;
 
-  if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+16)))
-    return -1;
+	if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+16)))
+		return -ENOMEM;
 
-  newpacket->lock = 1;
+	newpacket->lock = 1;
+
+	curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, sess->snac_nextid++);
 
-  curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, sess->snac_nextid);
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
-  curbyte += aimutil_put32(newpacket->data+curbyte, 0x00000003);
-  curbyte += aimutil_put16(newpacket->data+curbyte,  0x1f40);
-  curbyte += aimutil_put16(newpacket->data+curbyte,  0x03e7);
-  curbyte += aimutil_put16(newpacket->data+curbyte,  0x03e7);
-  curbyte += aimutil_put32(newpacket->data+curbyte, 0x00000000);
+	/* This is read-only (in Parameter Reply). Must be set to zero here. */
+	curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
 
-  newpacket->lock = 0;
-  aim_tx_enqueue(sess, newpacket);
+	/* These are all read-write */
+	curbyte += aimutil_put32(newpacket->data+curbyte, params->flags); 
+	curbyte += aimutil_put16(newpacket->data+curbyte, params->maxmsglen);
+	curbyte += aimutil_put16(newpacket->data+curbyte, params->maxsenderwarn); 
+	curbyte += aimutil_put16(newpacket->data+curbyte, params->maxrecverwarn); 
+	curbyte += aimutil_put32(newpacket->data+curbyte, params->minmsginterval);
 
-  return (sess->snac_nextid++);
+	newpacket->lock = 0;
+	aim_tx_enqueue(sess, newpacket);
+
+	return 0;
 }
 
 static int paraminfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  unsigned long defflags, minmsginterval;
-  unsigned short maxicbmlen, maxsenderwarn, maxrecverwarn, maxchannel;
-  aim_rxcallback_t userfunc;
-  int i = 0;
+	struct aim_icbmparameters params;
+	aim_rxcallback_t userfunc;
+	int i = 0;
 
-  maxchannel = aimutil_get16(data+i);
-  i += 2;
+	params.maxchan = aimutil_get16(data+i);
+	i += 2;
 
-  defflags = aimutil_get32(data+i);
-  i += 4;
+	params.flags = aimutil_get32(data+i);
+	i += 4;
 
-  maxicbmlen = aimutil_get16(data+i);
-  i += 2;
+	params.maxmsglen = aimutil_get16(data+i);
+	i += 2;
 
-  maxsenderwarn = aimutil_get16(data+i);
-  i += 2;
+	params.maxsenderwarn = aimutil_get16(data+i);
+	i += 2;
 
-  maxrecverwarn = aimutil_get16(data+i);
-  i += 2;
+	params.maxrecverwarn = aimutil_get16(data+i);
+	i += 2;
 
-  minmsginterval = aimutil_get32(data+i);
-  i += 4;
+	params.minmsginterval = aimutil_get32(data+i);
+	i += 4;
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, maxchannel, defflags, maxicbmlen, maxsenderwarn, maxrecverwarn, minmsginterval);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, &params);
 
-  return 0;
+	return 0;
 }
 
 static int missedcall(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  int i = 0;
-  aim_rxcallback_t userfunc;
-  unsigned short channel, nummissed, reason;
-  struct aim_userinfo_s userinfo;
- 
-  /*
-   * XXX: supposedly, this entire packet can repeat as many times
-   * as necessary. Should implement that.
-   */
+	int i, ret = 0;
+	aim_rxcallback_t userfunc;
+	unsigned short channel, nummissed, reason;
+	struct aim_userinfo_s userinfo;
+	
+	for (i = 0; i < datalen; ) {
+
+		/* Channel ID. */
+		channel = aimutil_get16(data+i);
+		i += 2;
 
-  /*
-   * Channel ID.
-   */
-  channel = aimutil_get16(data+i);
-  i += 2;
-  
-  /*
-   * Extract the standard user info block.
-   */
-  i += aim_extractuserinfo(sess, data+i, &userinfo);
-  
-  nummissed = aimutil_get16(data+i);
-  i += 2;
-  
-  reason = aimutil_get16(data+i);
-  i += 2;
+		/* Extract the standard user info block. */
+		i += aim_extractuserinfo(sess, data+i, &userinfo);
+
+		nummissed = aimutil_get16(data+i);
+		i += 2;
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, channel, &userinfo, nummissed, reason);
-  
-  return 0;
+		reason = aimutil_get16(data+i);
+		i += 2;
+
+		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+			 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason);
+	}
+
+	return ret;
 }
 
 static int msgack(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  char sn[MAXSNLEN];
-  unsigned char ck[8];
-  unsigned short type;
-  int i = 0;
-  unsigned char snlen;
+	aim_rxcallback_t userfunc;
+	char sn[MAXSNLEN];
+	unsigned char ck[8];
+	unsigned short type;
+	int i = 0;
+	unsigned char snlen;
 
-  memcpy(ck, data, 8);
-  i += 8;
+	memcpy(ck, data, 8);
+	i += 8;
 
-  type = aimutil_get16(data+i);
-  i += 2;
+	type = aimutil_get16(data+i);
+	i += 2;
 
-  snlen = aimutil_get8(data+i);
-  i++;
+	snlen = aimutil_get8(data+i);
+	i++;
 
-  memset(sn, 0, sizeof(sn));
-  strncpy(sn, (char *)data+i, snlen);
+	memset(sn, 0, sizeof(sn));
+	strncpy(sn, (char *)data+i, snlen);
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, type, sn);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, type, sn);
 
-  return 0;
+	return 0;
 }
 
 static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
 
-  if (snac->subtype == 0x0005)
-    return paraminfo(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0006)
-    return outgoingim(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0007)
-    return incomingim(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x000a)
-    return missedcall(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x000c)
-    return msgack(sess, mod, rx, snac, data, datalen);
+	if (snac->subtype == 0x0005)
+		return paraminfo(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0006)
+		return outgoingim(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0007)
+		return incomingim(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x000a)
+		return missedcall(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x000c)
+		return msgack(sess, mod, rx, snac, data, datalen);
 
-  return 0;
+	return 0;
 }
 
 faim_internal int msg_modfirst(struct aim_session_t *sess, aim_module_t *mod)
 {
 
-  mod->family = 0x0004;
-  mod->version = 0x0000;
-  mod->flags = 0;
-  strncpy(mod->name, "messaging", sizeof(mod->name));
-  mod->snachandler = snachandler;
+	mod->family = 0x0004;
+	mod->version = 0x0000;
+	mod->flags = 0;
+	strncpy(mod->name, "messaging", sizeof(mod->name));
+	mod->snachandler = snachandler;
 
-  return 0;
+	return 0;
 }
--- a/src/protocols/oscar/login.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/login.c	Sun Aug 26 20:21:45 2001 +0000
@@ -12,23 +12,23 @@
 
 static int aim_encode_password(const char *password, unsigned char *encoded);
 
-faim_export int aim_sendconnack(struct aim_session_t *sess,
-				struct aim_conn_t *conn)
+faim_export int aim_sendflapver(struct aim_session_t *sess, struct aim_conn_t *conn)
 {
-  int curbyte=0;
-  
-  struct command_tx_struct *newpacket;
+	int curbyte=0;
+
+	struct command_tx_struct *newpacket;
+
+	if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0001, 4)))
+		return -ENOMEM;
 
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0001, 4)))
-    return -1;
+	newpacket->lock = 1;
 
-  newpacket->lock = 1;
-  
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
+	curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
+	curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
 
-  newpacket->lock = 0;
-  return aim_tx_enqueue(sess, newpacket);
+	newpacket->lock = 0;
+
+	return aim_tx_enqueue(sess, newpacket);
 }
 
 /*
@@ -39,81 +39,82 @@
  * a 0017/0007 comes back, which is the signal to send
  * it the main login command (0017/0002).  
  */
-faim_export int aim_request_login(struct aim_session_t *sess,
-				  struct aim_conn_t *conn, 
-				  char *sn)
+faim_export int aim_request_login(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn)
 {
-  int curbyte;
-  struct command_tx_struct *newpacket;
+	int curbyte;
+	struct command_tx_struct *newpacket;
 
-  if (!sess || !conn || !sn)
-    return -1;
+	if (!sess || !conn || !sn)
+		return -EINVAL;
 
-  /*
-   * For ICQ, we enable the ancient horrible login and stuff
-   * a key packet into the queue to make it look like we got
-   * a reply back. This is so the client doesn't know we're
-   * really not doing MD5 login.
-   *
-   * This may sound stupid, but I'm not in the best of moods and 
-   * I don't plan to keep support for this crap around much longer.
-   * Its all AOL's fault anyway, really. I hate AOL.  Really.  They
-   * always seem to be able to piss me off by doing the dumbest little
-   * things.  Like disabling MD5 logins for ICQ UINs, or adding purposefully
-   * wrong TLV lengths, or adding superfluous information to host strings,
-   * or... I'll stop.
-   *
-   */
-  if ((sn[0] >= '0') && (sn[0] <= '9')) {
-    struct command_rx_struct *newrx;
-    int i;
+	/*
+	 * For ICQ, we enable the ancient horrible login and stuff
+	 * a key packet into the queue to make it look like we got
+	 * a reply back. This is so the client doesn't know we're
+	 * really not doing MD5 login.
+	 *
+	 * This may sound stupid, but I'm not in the best of moods and 
+	 * I don't plan to keep support for this crap around much longer.
+	 * Its all AOL's fault anyway, really. I hate AOL.  Really.  They
+	 * always seem to be able to piss me off by doing the dumbest little
+	 * things.  Like disabling MD5 logins for ICQ UINs, or adding
+	 * purposefully wrong TLV lengths, or adding superfluous information 
+	 * to host strings, or... I'll stop.
+	 *
+	 */
+	if ((sn[0] >= '0') && (sn[0] <= '9')) {
+		struct command_rx_struct *newrx;
+		int i;
+
+		/* XXX Uhm why doesn't this use aim_tx_new? */
+		if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct))))
+			return -ENOMEM;
 
-    if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct))))
-      return -1;
-    memset(newrx, 0x00, sizeof(struct command_rx_struct));
-    newrx->lock = 1; 
-    newrx->hdrtype = AIM_FRAMETYPE_OSCAR;
-    newrx->hdr.oscar.type = 0x02;
-    newrx->hdr.oscar.seqnum = 0;
-    newrx->commandlen = 10+2+1;
-    newrx->nofree = 0; 
-    if (!(newrx->data = malloc(newrx->commandlen))) {
-      free(newrx);
-      return -1;
-    }
+		memset(newrx, 0x00, sizeof(struct command_rx_struct));
+		newrx->lock = 1; 
+		newrx->hdrtype = AIM_FRAMETYPE_OSCAR;
+		newrx->hdr.oscar.type = 0x02;
+		newrx->hdr.oscar.seqnum = 0;
+		newrx->commandlen = 10+2+1;
+		newrx->nofree = 0; 
 
-    i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000);
-    i += aimutil_put16(newrx->data+i, 0x01);
-    i += aimutil_putstr(newrx->data+i, "0", 1);
+		if (!(newrx->data = malloc(newrx->commandlen))) {
+			free(newrx);
+			return -ENOMEM;
+		}
 
-    newrx->conn = conn;
+		i = aim_putsnac(newrx->data, 0x0017, 0x0007, 0x0000, 0x0000);
+		i += aimutil_put16(newrx->data+i, 0x01);
+		i += aimutil_putstr(newrx->data+i, "0", 1);
 
-    newrx->next = sess->queue_incoming;
-    sess->queue_incoming = newrx;
+		newrx->conn = conn;
+
+		newrx->next = sess->queue_incoming;
+		sess->queue_incoming = newrx;
 
-    newrx->lock = 0;
+		newrx->lock = 0;
 
-    sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN;
+		sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN;
 
-    return 0;
-  } 
+		return 0;
+	} 
 
-  sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
+	sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
 
-  aim_sendconnack(sess, conn);
+	aim_sendflapver(sess, conn);
 
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(sn))))
-    return -1;
+	if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(sn))))
+		return -ENOMEM;
+
+	newpacket->lock = 1;
 
-  newpacket->lock = 1;
-  
-  curbyte  = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000);
-  curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
+	curbyte  = aim_putsnac(newpacket->data, 0x0017, 0x0006, 0x0000, 0x00010000);
+	curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
 
-  newpacket->commandlen = curbyte;
-  newpacket->lock = 0;
+	newpacket->commandlen = curbyte;
+	newpacket->lock = 0;
 
-  return aim_tx_enqueue(sess, newpacket);
+	return aim_tx_enqueue(sess, newpacket);
 }
 
 /*
@@ -175,93 +176,89 @@
  *   serverstore = 0x01
  *
  */
-faim_export int aim_send_login (struct aim_session_t *sess,
-				struct aim_conn_t *conn, 
-				char *sn, char *password, 
-				struct client_info_s *clientinfo,
-				char *key)
+faim_export int aim_send_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo, char *key)
 {
-  int curbyte=0;
-  struct command_tx_struct *newpacket;
+	int curbyte=0;
+	struct command_tx_struct *newpacket;
+
+	if (!clientinfo || !sn || !password)
+		return -EINVAL;
 
-  if (!clientinfo || !sn || !password)
-    return -1;
+	if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
+		return -ENOMEM;
 
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
-    return -1;
+	newpacket->lock = 1;
 
-  newpacket->lock = 1;
+	newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01;
 
-  newpacket->hdr.oscar.type = (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)?0x02:0x01;
-  
-  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)
-    curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000);
-  else {
-    curbyte  = aimutil_put16(newpacket->data, 0x0000);
-    curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
-  }
+	if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)
+		curbyte = aim_putsnac(newpacket->data, 0x0017, 0x0002, 0x0000, 0x00010000);
+	else {
+		curbyte  = aimutil_put16(newpacket->data, 0x0000);
+		curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
+	}
 
-  curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
-  
-  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
-    unsigned char digest[16];
+	curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
+
+	if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
+		unsigned char digest[16];
 
-    aim_encode_password_md5(password, key, digest);
-    curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest);
-  } else { 
-    char *password_encoded;
+		aim_encode_password_md5(password, key, digest);
+		curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest);
+	} else { 
+		char *password_encoded;
 
-    password_encoded = (char *) malloc(strlen(password));
-    aim_encode_password(password, password_encoded);
-    curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded);
-    free(password_encoded);
-  }
+		password_encoded = (char *) malloc(strlen(password));
+		aim_encode_password(password, password_encoded);
+		curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0002, strlen(password), password_encoded);
+		free(password_encoded);
+	}
+
+	curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring);
 
-  curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0003, strlen(clientinfo->clientstring), clientinfo->clientstring);
+	if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
 
-  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build);
 
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, (unsigned short)clientinfo->major2);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, (unsigned short)clientinfo->major);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, (unsigned short)clientinfo->minor);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, (unsigned short)clientinfo->minor2);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, (unsigned short)clientinfo->build);
-  
-  } else {
-    /* Use very specific version numbers, to further indicate the hack. */
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce);
-    curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055);
-  }
+	} else {
+		/* Use very specific version numbers, to further indicate the hack. */
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0016, 0x010a);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0017, 0x0004);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0018, 0x003c);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0019, 0x0001);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x001a, 0x0cce);
+		curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, 0x00000055);
+	}
 
-  curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country);
-  curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang);
-  
-  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
-    curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown);
-    curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
-  }
+	curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000e, strlen(clientinfo->country), clientinfo->country);
+	curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x000f, strlen(clientinfo->lang), clientinfo->lang);
 
-  newpacket->commandlen = curbyte;
+	if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
+		curbyte += aim_puttlv_32(newpacket->data+curbyte, 0x0014, clientinfo->unknown);
+		curbyte += aim_puttlv_16(newpacket->data+curbyte, 0x0009, 0x0015);
+	}
 
-  newpacket->lock = 0;
-  return aim_tx_enqueue(sess, newpacket);
+	newpacket->commandlen = curbyte;
+	newpacket->lock = 0;
+
+	return aim_tx_enqueue(sess, newpacket);
 }
 
 faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest)
 {
-  md5_state_t state;
+	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);
+	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;
+	return 0;
 }
 
 /**
@@ -283,26 +280,25 @@
  */
 static int aim_encode_password(const char *password, unsigned char *encoded)
 {
-  u_char encoding_table[] = {
+	unsigned char encoding_table[] = {
 #if 0 /* old v1 table */
-    0xf3, 0xb3, 0x6c, 0x99,
-    0x95, 0x3f, 0xac, 0xb6,
-    0xc5, 0xfa, 0x6b, 0x63,
-    0x69, 0x6c, 0xc3, 0x9f
+		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
+		0xf3, 0x26, 0x81, 0xc4,
+		0x39, 0x86, 0xdb, 0x92,
+		0x71, 0xa3, 0xb9, 0xe6,
+		0x53, 0x7a, 0x95, 0x7c
 #endif
-  };
+	};
+	int i;
 
-  int i;
-  
-  for (i = 0; i < strlen(password); i++)
-      encoded[i] = (password[i] ^ encoding_table[i]);
+	for (i = 0; i < strlen(password); i++)
+		encoded[i] = (password[i] ^ encoding_table[i]);
 
-  return 0;
+	return 0;
 }
 
 /*
@@ -318,33 +314,33 @@
 					   char *cookie, char *email, 
 					   int regstatus)
 {	
-  struct command_tx_struct *tx;
-  struct aim_tlvlist_t *tlvlist = NULL;
+	struct command_tx_struct *tx;
+	struct aim_tlvlist_t *tlvlist = NULL;
+
+	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0004, 1152)))
+		return -ENOMEM;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0004, 1152)))
-    return -1;
-  
-  tx->lock = 1;
+	tx->lock = 1;
 
-  if (sn)
-    aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn));
-  else
-    aim_addtlvtochain_str(&tlvlist, 0x0001, sess->sn, strlen(sess->sn));
+	if (sn)
+		aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn));
+	else
+		aim_addtlvtochain_str(&tlvlist, 0x0001, sess->sn, strlen(sess->sn));
 
-  if (errorcode) {
-    aim_addtlvtochain16(&tlvlist, 0x0008, errorcode);
-    aim_addtlvtochain_str(&tlvlist, 0x0004, errorurl, strlen(errorurl));
-  } else {
-    aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip));
-    aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
-    aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email));
-    aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus);
-  }
+	if (errorcode) {
+		aim_addtlvtochain16(&tlvlist, 0x0008, errorcode);
+		aim_addtlvtochain_str(&tlvlist, 0x0004, errorurl, strlen(errorurl));
+	} else {
+		aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip));
+		aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
+		aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email));
+		aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus);
+	}
 
-  tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist);
-  tx->lock = 0;
+	tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist);
+	tx->lock = 0;
 
-  return aim_tx_enqueue(sess, tx);
+	return aim_tx_enqueue(sess, tx);
 }
 
 /*
@@ -352,14 +348,14 @@
  */
 faim_export int aim_gencookie(unsigned char *buf)
 {
-  int i;
+	int i;
 
-  srand(time(NULL));
+	srand(time(NULL));
 
-  for (i=0; i < AIM_COOKIELEN; i++)
-    buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0));
+	for (i=0; i < AIM_COOKIELEN; i++)
+		buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0));
 
-  return i;
+	return i;
 }
 
 /*
@@ -367,135 +363,132 @@
  */
 faim_export int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn)
 {
-  struct command_tx_struct *tx;
-  int i = 0;
+	struct command_tx_struct *tx;
+	int i;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+0x22)))
-    return -1;
+	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+0x22)))
+		return -ENOMEM;
 
-  tx->lock = 1;
+	tx->lock = 1;
+
+	i = aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++);
 
-  i += aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++);
-  
-  i += aimutil_put16(tx->data+i, 0x0001);  
-  i += aimutil_put16(tx->data+i, 0x0002);
-  i += aimutil_put16(tx->data+i, 0x0003);
-  i += aimutil_put16(tx->data+i, 0x0004);
-  i += aimutil_put16(tx->data+i, 0x0006);
-  i += aimutil_put16(tx->data+i, 0x0008);
-  i += aimutil_put16(tx->data+i, 0x0009);
-  i += aimutil_put16(tx->data+i, 0x000a);
-  i += aimutil_put16(tx->data+i, 0x000b);
-  i += aimutil_put16(tx->data+i, 0x000c);
-  i += aimutil_put16(tx->data+i, 0x0013);
-  i += aimutil_put16(tx->data+i, 0x0015);
+	i += aimutil_put16(tx->data+i, 0x0001);  
+	i += aimutil_put16(tx->data+i, 0x0002);
+	i += aimutil_put16(tx->data+i, 0x0003);
+	i += aimutil_put16(tx->data+i, 0x0004);
+	i += aimutil_put16(tx->data+i, 0x0006);
+	i += aimutil_put16(tx->data+i, 0x0008);
+	i += aimutil_put16(tx->data+i, 0x0009);
+	i += aimutil_put16(tx->data+i, 0x000a);
+	i += aimutil_put16(tx->data+i, 0x000b);
+	i += aimutil_put16(tx->data+i, 0x000c);
+	i += aimutil_put16(tx->data+i, 0x0013);
+	i += aimutil_put16(tx->data+i, 0x0015);
 
-  tx->commandlen = i;
-  tx->lock = 0;
-  return aim_tx_enqueue(sess, tx);
+	tx->commandlen = i;
+	tx->lock = 0;
+
+	return aim_tx_enqueue(sess, tx);
 }
 
 
 /* 
  * Send service redirect.  (Non-Client)
  */
-faim_export unsigned long aim_sendredirect(struct aim_session_t *sess, 
-					   struct aim_conn_t *conn, 
-					   unsigned short servid, 
-					   char *ip,
-					   char *cookie)
+faim_export unsigned long aim_sendredirect(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned short servid, char *ip, char *cookie)
 {	
-  struct command_tx_struct *tx;
-  struct aim_tlvlist_t *tlvlist = NULL;
-  int i = 0;
+	struct command_tx_struct *tx;
+	struct aim_tlvlist_t *tlvlist = NULL;
+	int i;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
-    return -1;
+	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
+		return -ENOMEM;
+
+	tx->lock = 1;
 
-  tx->lock = 1;
+	i = aim_putsnac(tx->data, 0x0001, 0x0005, 0x0000, 0x00000000);
+
+	aim_addtlvtochain16(&tlvlist, 0x000d, servid);
+	aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip));
+	aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
 
-  i += aim_putsnac(tx->data+i, 0x0001, 0x0005, 0x0000, 0x00000000);
-  
-  aim_addtlvtochain16(&tlvlist, 0x000d, servid);
-  aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip));
-  aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
+	tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i;
+	aim_freetlvchain(&tlvlist);
 
-  tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i;
-  aim_freetlvchain(&tlvlist);
+	tx->lock = 0;
 
-  tx->lock = 0;
-  return aim_tx_enqueue(sess, tx);
+	return aim_tx_enqueue(sess, tx);
 }
 
 
 static int hostonline(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  int ret = 0;
-  unsigned short *families;
-  int famcount, i;
+	aim_rxcallback_t userfunc;
+	int ret = 0;
+	unsigned short *families;
+	int famcount, i;
 
-  famcount = datalen/2;
+	famcount = datalen/2;
 
-  if (!(families = malloc(datalen)))
-    return 0;
+	if (!(families = malloc(datalen)))
+		return 0;
 
-  for (i = 0; i < famcount; i++)
-    families[i] = aimutil_get16(data+(i*2));
+	for (i = 0; i < famcount; i++)
+		families[i] = aimutil_get16(data+(i*2));
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret = userfunc(sess, rx, famcount, families);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, famcount, families);
 
-  free(families);
+	free(families);
 
-  return ret;  
+	return ret;  
 }
 
 static int redirect(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  int serviceid;
-  unsigned char *cookie;
-  char *ip;
-  aim_rxcallback_t userfunc;
-  struct aim_tlvlist_t *tlvlist;
-  char *chathack = NULL;
-  int chathackex = 0;
-  int ret = 0;
-  
-  tlvlist = aim_readtlvchain(data, datalen);
+	int serviceid;
+	unsigned char *cookie;
+	char *ip;
+	aim_rxcallback_t userfunc;
+	struct aim_tlvlist_t *tlvlist;
+	char *chathack = NULL;
+	int chathackex = 0;
+	int ret = 0;
 
-  if (!aim_gettlv(tlvlist, 0x000d, 1) ||
-      !aim_gettlv(tlvlist, 0x0005, 1) ||
-      !aim_gettlv(tlvlist, 0x0006, 1)) {
-    aim_freetlvchain(&tlvlist);
-    return 0;
-  }
+	tlvlist = aim_readtlvchain(data, datalen);
 
-  serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
-  ip = aim_gettlv_str(tlvlist, 0x0005, 1);
-  cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
+	if (!aim_gettlv(tlvlist, 0x000d, 1) ||
+			!aim_gettlv(tlvlist, 0x0005, 1) ||
+			!aim_gettlv(tlvlist, 0x0006, 1)) {
+		aim_freetlvchain(&tlvlist);
+		return 0;
+	}
 
-  /*
-   * Chat hack.
-   *
-   */
-  if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
-    chathack = sess->pendingjoin;
-    chathackex = sess->pendingjoinexchange;
-    sess->pendingjoin = NULL;
-    sess->pendingjoinexchange = 0;
-  }
+	serviceid = aim_gettlv16(tlvlist, 0x000d, 1);
+	ip = aim_gettlv_str(tlvlist, 0x0005, 1);
+	cookie = aim_gettlv_str(tlvlist, 0x0006, 1);
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret = userfunc(sess, rx, serviceid, ip, cookie, chathack, chathackex);
+	/*
+	 * Chat hack.
+	 */
+	if ((serviceid == AIM_CONN_TYPE_CHAT) && sess->pendingjoin) {
+		chathack = sess->pendingjoin;
+		chathackex = sess->pendingjoinexchange;
+		sess->pendingjoin = NULL;
+		sess->pendingjoinexchange = 0;
+	}
 
-  free(ip);
-  free(cookie);
-  free(chathack);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, serviceid, ip, cookie, chathack, chathackex);
 
-  aim_freetlvchain(&tlvlist);
+	free(ip);
+	free(cookie);
+	free(chathack);
 
-  return ret;
+	aim_freetlvchain(&tlvlist);
+
+	return ret;
 }
 
 /*
@@ -551,127 +544,127 @@
 /* XXX parse this */
 static int rateresp(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
+	aim_rxcallback_t userfunc;
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx);
 
-  return 0;
+	return 0;
 }
 
 static int ratechange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  int i = 0, code;
-  unsigned long currentavg, maxavg;
-  unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
+	aim_rxcallback_t userfunc;
+	int i = 0, code;
+	unsigned long currentavg, maxavg;
+	unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
 
-  code = aimutil_get16(data+i);
-  i += 2;
+	code = aimutil_get16(data+i);
+	i += 2;
 
-  rateclass = aimutil_get16(data+i);
-  i += 2;
+	rateclass = aimutil_get16(data+i);
+	i += 2;
 
-  windowsize = aimutil_get32(data+i);
-  i += 4;
-  clear = aimutil_get32(data+i);
-  i += 4;
-  alert = aimutil_get32(data+i);
-  i += 4;
-  limit = aimutil_get32(data+i);
-  i += 4;
-  disconnect = aimutil_get32(data+i);
-  i += 4;
-  currentavg = aimutil_get32(data+i);
-  i += 4;
-  maxavg = aimutil_get32(data+i);
-  i += 4;
+	windowsize = aimutil_get32(data+i);
+	i += 4;
+	clear = aimutil_get32(data+i);
+	i += 4;
+	alert = aimutil_get32(data+i);
+	i += 4;
+	limit = aimutil_get32(data+i);
+	i += 4;
+	disconnect = aimutil_get32(data+i);
+	i += 4;
+	currentavg = aimutil_get32(data+i);
+	i += 4;
+	maxavg = aimutil_get32(data+i);
+	i += 4;
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
 
-  return 0;
+	return 0;
 }
 
 /* XXX parse this */
 static int selfinfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
+	aim_rxcallback_t userfunc;
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx);
 
-  return 0;
+	return 0;
 }
 
 static int evilnotify(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc = NULL;
-  int i = 0;
-  unsigned short newevil;
-  struct aim_userinfo_s userinfo;
+	aim_rxcallback_t userfunc = NULL;
+	int i = 0;
+	unsigned short newevil;
+	struct aim_userinfo_s userinfo;
 
-  newevil = aimutil_get16(data);
-  i += 2;
+	newevil = aimutil_get16(data);
+	i += 2;
 
-  memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
+	memset(&userinfo, 0, sizeof(struct aim_userinfo_s));
 
-  if (datalen-i)
-    i += aim_extractuserinfo(sess, data+i, &userinfo);
+	if (datalen-i)
+		i += aim_extractuserinfo(sess, data+i, &userinfo);
 
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, newevil, &userinfo);
-  
-  return 0;
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, newevil, &userinfo);
+
+	return 0;
 }
 
 static int motd(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  char *msg = NULL;
-  int ret = 0;
-  struct aim_tlvlist_t *tlvlist;
-  unsigned short id;
+	aim_rxcallback_t userfunc;
+	char *msg = NULL;
+	int ret = 0;
+	struct aim_tlvlist_t *tlvlist;
+	unsigned short id;
 
-  /*
-   * Code.
-   *
-   * Valid values:
-   *   1 Mandatory upgrade
-   *   2 Advisory upgrade
-   *   3 System bulletin
-   *   4 Nothing's wrong ("top o the world" -- normal)
-   *
-   */
-  id = aimutil_get16(data);
+	/*
+	 * Code.
+	 *
+	 * Valid values:
+	 *   1 Mandatory upgrade
+	 *   2 Advisory upgrade
+	 *   3 System bulletin
+	 *   4 Nothing's wrong ("top o the world" -- normal)
+	 *
+	 */
+	id = aimutil_get16(data);
 
-  /* 
-   * TLVs follow 
-   */
-  if ((tlvlist = aim_readtlvchain(data+2, datalen-2)))
-    msg = aim_gettlv_str(tlvlist, 0x000b, 1);
-  
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret =  userfunc(sess, rx, id, msg);
+	/* 
+	 * TLVs follow 
+	 */
+	if ((tlvlist = aim_readtlvchain(data+2, datalen-2)))
+		msg = aim_gettlv_str(tlvlist, 0x000b, 1);
 
-  free(msg);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, id, msg);
 
-  aim_freetlvchain(&tlvlist);
+	free(msg);
 
-  return ret;
+	aim_freetlvchain(&tlvlist);
+
+	return ret;
 }
 
 static int hostversions(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  int vercount;
+	aim_rxcallback_t userfunc;
+	int vercount;
+
+	vercount = datalen/4;
 
-  vercount = datalen/4;
-  
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    return userfunc(sess, rx, vercount, data);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, vercount, data);
 
-  return 0;
+	return 0;
 }
 
 /*
@@ -713,175 +706,174 @@
  */
 static int memrequest(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  aim_rxcallback_t userfunc;
-  unsigned long offset, len;
-  int i = 0;
-  struct aim_tlvlist_t *list;
-  char *modname = NULL;
+	aim_rxcallback_t userfunc;
+	unsigned long offset, len;
+	int i = 0;
+	struct aim_tlvlist_t *list;
+	char *modname = NULL;
 
-  offset = aimutil_get32(data);
-  i += 4;
+	offset = aimutil_get32(data);
+	i += 4;
 
-  len = aimutil_get32(data+4);
-  i += 4;
+	len = aimutil_get32(data+4);
+	i += 4;
 
-  list = aim_readtlvchain(data+i, datalen-i);
+	list = aim_readtlvchain(data+i, datalen-i);
 
-  if (aim_gettlv(list, 0x0001, 1))
-    modname = aim_gettlv_str(list, 0x0001, 1);
+	if (aim_gettlv(list, 0x0001, 1))
+		modname = aim_gettlv_str(list, 0x0001, 1);
 
-  faimdprintf(sess, 1, "data at 0x%08lx (%d bytes) of requested\n", offset, len, modname?modname:"aim.exe");
+	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)))
-    return userfunc(sess, rx, offset, len, modname);
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		return userfunc(sess, rx, offset, len, modname);
 
-  free(modname);
-  aim_freetlvchain(&list);
+	free(modname);
+	aim_freetlvchain(&list);
 
-  return 0;
+	return 0;
 }
 
 static void dumpbox(struct aim_session_t *sess, unsigned char *buf, int len)
 {
-  int i = 0;
+	int i;
 
-  if (!sess || !buf || !len)
-    return;
+	if (!sess || !buf || !len)
+		return;
 
-  faimdprintf(sess, 1, "\nDump of %d bytes at %p:", len, buf);
+	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");
+	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");
+		faimdprintf(sess, 1, "0x%2x ", buf[i]);
+	}
 
-  return;
+	faimdprintf(sess, 1, "\n\n");
+
+	return;
 }
 
 faim_export int aim_sendmemblock(struct aim_session_t *sess, struct aim_conn_t *conn, unsigned long offset, unsigned long len, const unsigned char *buf, unsigned char flag)
 {
-  struct command_tx_struct *tx;
-  int i = 0;
+	struct command_tx_struct *tx;
+	int i = 0;
 
-  if (!sess || !conn)
-    return 0;
+	if (!sess || !conn)
+		return -EINVAL;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+16)))
-    return -1;
+	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+16)))
+		return -ENOMEM;
 
-  tx->lock = 1;
+	tx->lock = 1;
 
-  i = aim_putsnac(tx->data, 0x0001, 0x0020, 0x0000, sess->snac_nextid++);
-  i += aimutil_put16(tx->data+i, 0x0010); /* md5 is always 16 bytes */
+	i = aim_putsnac(tx->data, 0x0001, 0x0020, 0x0000, sess->snac_nextid++);
+	i += aimutil_put16(tx->data+i, 0x0010); /* md5 is always 16 bytes */
 
-  if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) &&
-      buf && (len == 0x10)) { /* we're getting a hash */
+	if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
 
-    memcpy(tx->data+i, buf, 0x10);
-    i += 0x10;
+		memcpy(tx->data+i, buf, 0x10);
+		i += 0x10;
 
-  } else if (buf && (len > 0)) { /* use input buffer */
-    md5_state_t state;
+	} else if (buf && (len > 0)) { /* use input buffer */
+		md5_state_t state;
 
-    md5_init(&state);	
-    md5_append(&state, (const md5_byte_t *)buf, len);
-    md5_finish(&state, (md5_byte_t *)(tx->data+i));
-    i += 0x10;
+		md5_init(&state);	
+		md5_append(&state, (const md5_byte_t *)buf, len);
+		md5_finish(&state, (md5_byte_t *)(tx->data+i));
+		i += 0x10;
 
-  } else if (len == 0) { /* no length, just hash NULL (buf is optional) */
-    md5_state_t state;
-    unsigned char nil = '\0';
+	} else if (len == 0) { /* no length, just hash NULL (buf is optional) */
+		md5_state_t state;
+		unsigned char nil = '\0';
 
-    /*
-     * 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, (md5_byte_t *)(tx->data+i));
-    i += 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, (md5_byte_t *)(tx->data+i));
+		i += 0x10;
 
-  } else {
+	} 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)) {
+		/* 
+		 * 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" */
-      i += aimutil_put32(tx->data+i, 0x44a95d26);
-      i += aimutil_put32(tx->data+i, 0xd2490423);
-      i += aimutil_put32(tx->data+i, 0x93b8821f);
-      i += aimutil_put32(tx->data+i, 0x51c54b01);
+			i += aimutil_put32(tx->data+i, 0x44a95d26);
+			i += aimutil_put32(tx->data+i, 0xd2490423);
+			i += aimutil_put32(tx->data+i, 0x93b8821f);
+			i += aimutil_put32(tx->data+i, 0x51c54b01);
 #else /* no filename */
-      i += aimutil_put32(tx->data+i, 0x1df8cbae);
-      i += aimutil_put32(tx->data+i, 0x5523b839);
-      i += aimutil_put32(tx->data+i, 0xa0e10db3);
-      i += aimutil_put32(tx->data+i, 0xa46d3b39);
+			i += aimutil_put32(tx->data+i, 0x1df8cbae);
+			i += aimutil_put32(tx->data+i, 0x5523b839);
+			i += aimutil_put32(tx->data+i, 0xa0e10db3);
+			i += aimutil_put32(tx->data+i, 0xa46d3b39);
 #endif
 
-    } else if ((offset == 0x00001000) && (len == 0x00000000)) {
+		} else if ((offset == 0x00001000) && (len == 0x00000000)) {
 
-      i += aimutil_put32(tx->data+i, 0xd41d8cd9);
-      i += aimutil_put32(tx->data+i, 0x8f00b204);
-      i += aimutil_put32(tx->data+i, 0xe9800998);
-      i += aimutil_put32(tx->data+i, 0xecf8427e);
+			i += aimutil_put32(tx->data+i, 0xd41d8cd9);
+			i += aimutil_put32(tx->data+i, 0x8f00b204);
+			i += aimutil_put32(tx->data+i, 0xe9800998);
+			i += aimutil_put32(tx->data+i, 0xecf8427e);
 
-    } else
-      faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n");
+		} else
+			faimdprintf(sess, 0, "sendmemblock: WARNING: unknown hash request\n");
 
-  }
+	}
 
-  tx->commandlen = i;
-  tx->lock = 0;
-  aim_tx_enqueue(sess, tx);
+	tx->commandlen = i;
+	tx->lock = 0;
+	aim_tx_enqueue(sess, tx);
 
-  return 0;
+	return 0;
 }
 
 static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
 
-  if (snac->subtype == 0x0003)
-    return hostonline(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0005)
-    return redirect(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0007)
-    return rateresp(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x000a)
-    return ratechange(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x000f)
-    return selfinfo(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0010)
-    return evilnotify(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0013)
-    return motd(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0018)
-    return hostversions(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x001f)
-    return memrequest(sess, mod, rx, snac, data, datalen);
+	if (snac->subtype == 0x0003)
+		return hostonline(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0005)
+		return redirect(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0007)
+		return rateresp(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x000a)
+		return ratechange(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x000f)
+		return selfinfo(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0010)
+		return evilnotify(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0013)
+		return motd(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x0018)
+		return hostversions(sess, mod, rx, snac, data, datalen);
+	else if (snac->subtype == 0x001f)
+		return memrequest(sess, mod, rx, snac, data, datalen);
 
-  return 0;
+	return 0;
 }
 
 faim_internal int general_modfirst(struct aim_session_t *sess, aim_module_t *mod)
 {
 
-  mod->family = 0x0001;
-  mod->version = 0x0000;
-  mod->flags = 0;
-  strncpy(mod->name, "general", sizeof(mod->name));
-  mod->snachandler = snachandler;
+	mod->family = 0x0001;
+	mod->version = 0x0000;
+	mod->flags = 0;
+	strncpy(mod->name, "general", sizeof(mod->name));
+	mod->snachandler = snachandler;
 
-  return 0;
+	return 0;
 }
+
--- a/src/protocols/oscar/misc.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/misc.c	Sun Aug 26 20:21:45 2001 +0000
@@ -669,48 +669,6 @@
   return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
 }
 
-/*
-* aim_bos_reqicbmparaminfo()
- *
- * Request ICBM parameter information.
- *
- */
-faim_export unsigned long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
-						   struct aim_conn_t *conn)
-{
-  return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
-}
-
-/*
- * Add ICBM parameter? Huh?
- */
-faim_export unsigned long aim_addicbmparam(struct aim_session_t *sess,
-					   struct aim_conn_t *conn)
-{
-  struct command_tx_struct *newpacket;
-  int packlen = 10+16, i=0;
-
-  if(!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, packlen)))
-    return (sess->snac_nextid);
-  
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0004, 0x0002, 0x0000, 0x00000000);
-
-  i += aimutil_put16(newpacket->data+i, 0x0000); 
-  i += aimutil_put16(newpacket->data+i, 0x0000);
-  i += aimutil_put16(newpacket->data+i, 0x0003);
-  i += aimutil_put16(newpacket->data+i, 0x1f40);
-  i += aimutil_put16(newpacket->data+i, 0x03e7);
-  i += aimutil_put16(newpacket->data+i, 0x03e7);
-  i += aimutil_put16(newpacket->data+i, 0x0000); 
-  i += aimutil_put16(newpacket->data+i, 0x0000); 
-  
-  aim_tx_enqueue(sess, newpacket);
-
-  return sess->snac_nextid;
-}
-
 /* 
  * Set directory profile data (not the same as aim_bos_setprofile!)
  */
--- a/src/protocols/oscar/oscar.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/oscar/oscar.c	Sun Aug 26 20:21:45 2001 +0000
@@ -106,6 +106,8 @@
 	int id;
 	struct gaim_connection *gc; /* i hate this. */
 	struct conversation *cnv; /* bah. */
+	int maxlen;
+	int maxvis;
 };
 
 struct direct_im {
@@ -281,6 +283,7 @@
 static int gaim_parse_msgerr     (struct aim_session_t *, struct command_rx_struct *, ...);
 static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...);
 static int gaim_parse_locerr     (struct aim_session_t *, struct command_rx_struct *, ...);
+static int gaim_icbm_param_info  (struct aim_session_t *, struct command_rx_struct *, ...);
 static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...);
 static int gaim_memrequest       (struct aim_session_t *, struct command_rx_struct *, ...);
 
@@ -692,6 +695,7 @@
 	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 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);
@@ -1915,18 +1919,63 @@
 	va_end(ap);
 
 	switch(reason) {
+		case 0:
+			/* Invalid (0) */
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s because %s invalid."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   nummissed == 1 ? "it was" : "they were",
+				   userinfo->sn);
+			break;
 		case 1:
-			/* message too large */
-			sprintf(buf, _("You missed a message from %s because it was too large."), userinfo->sn);
-			do_error_dialog(buf, _("Gaim - Error"));
-			plugin_event(event_error, (void *)961, 0, 0, 0);
+			/* Message too large */
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s because %s too large."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   nummissed == 1 ? "it was" : "they were",
+				   userinfo->sn);
+			break;
+		case 2:
+			/* Rate exceeded */
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s because the rate limit has been exceeded."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   userinfo->sn);
+			break;
+		case 3:
+			/* Evil Sender */
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s because they are too evil."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   userinfo->sn);
+			break;
+		case 4:
+			/* Evil Receiver */
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s because you are too evil."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   userinfo->sn);
 			break;
 		default:
-			sprintf(buf, _("You missed a message from %s for unknown reasons."), userinfo->sn);
-			do_error_dialog(buf, _("Gaim - Error"));
-			plugin_event(event_error, (void *)970, 0, 0, 0);
+			g_snprintf(buf,
+				   sizeof(buf),
+				   _("You missed %d message%s from %s for unknown reasons."),
+				   nummissed,
+				   nummissed == 1 ? "" : "s",
+				   userinfo->sn);
 			break;
 	}
+	do_error_dialog(buf, _("Gaim - Error"));
 
 	return 1;
 }
@@ -2194,7 +2243,37 @@
 
 int gaim_chat_info_update(struct aim_session_t *sess,
 			  struct command_rx_struct *command, ...) {
-	debug_printf("inside chat_info_update\n");
+	va_list ap;
+	struct aim_userinfo_s *userinfo;
+	struct aim_chat_roominfo *roominfo;
+	char *roomname;
+	int usercount;
+	char *roomdesc;
+	unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
+	unsigned long creationtime;
+	struct gaim_connection *gc = sess->aux_data;
+	struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn);
+
+	va_start(ap, command);
+	roominfo = va_arg(ap, struct aim_chat_roominfo *);
+	roomname = va_arg(ap, char *);
+	usercount= va_arg(ap, int);
+	userinfo = va_arg(ap, struct aim_userinfo_s *);
+	roomdesc = va_arg(ap, char *);
+	unknown_c9 = va_arg(ap, int);
+	creationtime = va_arg(ap, unsigned long);
+	maxmsglen = va_arg(ap, int);
+	unknown_d2 = va_arg(ap, int);
+	unknown_d5 = va_arg(ap, int);
+	maxvisiblemsglen = va_arg(ap, int);
+	va_end(ap);
+
+	debug_printf("inside chat_info_update (maxmsglen = %d, maxvislen = %d)\n",
+			maxmsglen, maxvisiblemsglen);
+
+	ccon->maxlen = maxmsglen;
+	ccon->maxvis = maxvisiblemsglen;
+
 	return 1;
 }
 
@@ -2317,8 +2396,7 @@
 
 		debug_printf("buddy list loaded\n");
 
-		aim_addicbmparam(sess, command->conn);
-		aim_bos_reqicbmparaminfo(sess, command->conn);
+		aim_reqicbmparams(sess, command->conn);
 
 		aim_bos_reqrights(sess, command->conn);
 		aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS);
@@ -2340,11 +2418,40 @@
 	return 1;
 }
 
+int gaim_icbm_param_info(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
+	struct aim_icbmparameters *params;
+	va_list ap;
+
+	va_start(ap, command);
+	params = va_arg(ap, struct aim_icbmparameters *);
+	va_end(ap);
+
+	debug_printf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, "
+			"max sender evil = %f, max receiver evil = %f, min msg interval = %ld\n",
+			params->maxchan, params->flags, params->maxmsglen,
+			((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0,
+			params->minmsginterval);
+
+	params->maxmsglen = 8000;
+	params->minmsginterval = 0;
+
+	aim_seticbmparam(sess, command->conn, params);
+
+	return 1;
+}
+
 int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
-	if (command->data) {
-		debug_printf("minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10));
-	} else
-		debug_printf("NULL minimum report interval!\n");
+	va_list ap;
+	unsigned short interval = 0;
+
+	va_start(ap, command);
+	interval = va_arg(ap, int);
+	va_end(ap);
+
+	debug_printf("minimum report interval: %d (seconds?)\n", interval);
+
+	aim_reqicbmparams(sess, command->conn);
+
 	return 1;
 }
 
@@ -2713,12 +2820,12 @@
 	serv_got_chat_left(g, b->id);
 }
 
-static void oscar_chat_send(struct gaim_connection *g, int id, char *message) {
+static int oscar_chat_send(struct gaim_connection *g, int id, char *message) {
 	struct oscar_data *odata = (struct oscar_data *)g->proto_data;
 	GSList *bcs = g->buddy_chats;
 	struct conversation *b = NULL;
 	struct chat_connection *c = NULL;
-	char *buf;
+	char *buf, *buf2;
 	int i, j;
 
 	while (bcs) {
@@ -2729,7 +2836,7 @@
 		b = NULL;
 	}
 	if (!b)
-		return;
+		return -EINVAL;
 
 	bcs = odata->oscar_chats;
 	while (bcs) {
@@ -2740,7 +2847,7 @@
 		c = NULL;
 	}
 	if (!c)
-		return;
+		return -EINVAL;
 
 	buf = g_malloc(strlen(message) * 4 + 1);
 	for (i = 0, j = 0; i < strlen(message); i++) {
@@ -2754,8 +2861,20 @@
 		}
 	}
 	buf[j] = '\0';
+
+	if (strlen(buf) > c->maxlen)
+		return -E2BIG;
+
+	buf2 = strip_html(buf);
+	if (strlen(buf2) > c->maxvis) {
+		g_free(buf2);
+		return -E2BIG;
+	}
+	g_free(buf2);
+
 	aim_chat_send_im(odata->sess, c->conn, 0, buf, strlen(buf));
 	g_free(buf);
+	return 0;
 }
 
 static char **oscar_list_icon(int uc) {
--- a/src/protocols/toc/toc.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/toc/toc.c	Sun Aug 26 20:21:45 2001 +0000
@@ -945,12 +945,15 @@
 	sflap_send(g, buf2, -1, TYPE_DATA);
 }
 
-static void toc_chat_send(struct gaim_connection *g, int id, char *message)
+static int toc_chat_send(struct gaim_connection *g, int id, char *message)
 {
 	char buf[BUF_LEN * 2];
 	escape_text(message);
+	if (strlen(message) > 2000)
+		return -E2BIG;
 	g_snprintf(buf, sizeof(buf), "toc_chat_send %d \"%s\"", id, message);
 	sflap_send(g, buf, -1, TYPE_DATA);
+	return 0;
 }
 
 static void toc_keepalive(struct gaim_connection *gc)
--- a/src/protocols/zephyr/zephyr.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/protocols/zephyr/zephyr.c	Sun Aug 26 20:21:45 2001 +0000
@@ -30,6 +30,7 @@
 #include <gtk/gtk.h>
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
 #include "gaim.h"
 #include "prpl.h"
 #include "zephyr/zephyr.h"
@@ -683,7 +684,7 @@
 static void zephyr_add_buddy(struct gaim_connection *gc, char *buddy) { }
 static void zephyr_remove_buddy(struct gaim_connection *gc, char *buddy) { }
 
-static void zephyr_chat_send(struct gaim_connection *gc, int id, char *im)
+static int zephyr_chat_send(struct gaim_connection *gc, int id, char *im)
 {
 	ZNotice_t notice;
 	zephyr_triple *zt;
@@ -693,7 +694,7 @@
 	zt = find_sub_by_id(id);
 	if (!zt)
 		/* this should never happen. */
-		return;
+		return -EINVAL;
 	
 	sig = ZGetVariable("zwrite-signature");
 	if (!sig) {
@@ -720,6 +721,7 @@
 	notice.z_message = buf;
 	ZSendNotice(&notice, ZAUTH);
 	g_free(buf);
+	return 0;
 }
 
 static int zephyr_send_im(struct gaim_connection *gc, char *who, char *im, int away) {
--- a/src/prpl.h	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/prpl.h	Sun Aug 26 20:21:45 2001 +0000
@@ -135,7 +135,7 @@
 	void (* chat_invite)	(struct gaim_connection *, int id, char *who, char *message);
 	void (* chat_leave)	(struct gaim_connection *, int id);
 	void (* chat_whisper)	(struct gaim_connection *, int id, char *who, char *message);
-	void (* chat_send)	(struct gaim_connection *, int id, char *message);
+	int  (* chat_send)	(struct gaim_connection *, int id, char *message);
 	void (* keepalive)	(struct gaim_connection *);
 	void (* chat_set_topic) (struct gaim_connection *, int id, char *topic);
 
--- a/src/server.c	Sun Aug 26 19:18:39 2001 +0000
+++ b/src/server.c	Sun Aug 26 20:21:45 2001 +0000
@@ -327,11 +327,13 @@
 	   	(*g->prpl->chat_set_topic)(g, id, topic);
 }
 
-void serv_chat_send(struct gaim_connection *g, int id, char *message)
+int serv_chat_send(struct gaim_connection *g, int id, char *message)
 {
+	int val = -EINVAL;
 	if (g->prpl && g->prpl->chat_send)
-		(*g->prpl->chat_send)(g, id, message);
+		val = (*g->prpl->chat_send)(g, id, message);
 	serv_touch_idle(g);
+	return val;
 }
 
 int find_queue_row_by_name(char *name)