changeset 2866:6d62d4520460

[gaim-migrate @ 2879] try that committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Mon, 10 Dec 2001 00:48:27 +0000
parents 88dc3623a2ae
children b10dbe7de693
files src/protocols/oscar/aim.h src/protocols/oscar/aim_internal.h src/protocols/oscar/im.c src/protocols/oscar/info.c src/protocols/oscar/misc.c src/protocols/oscar/oscar.c src/protocols/oscar/service.c src/protocols/oscar/tlv.c
diffstat 8 files changed, 258 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/oscar/aim.h	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/aim.h	Mon Dec 10 00:48:27 2001 +0000
@@ -360,13 +360,14 @@
 #define AIM_SESS_FLAGS_DONTTIMEOUTONICBM 0x00000008
 
 /* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */
-#define AIM_ICQ_STATE_ONLINE    0x0000
-#define AIM_ICQ_STATE_AWAY      0x0001
-#define AIM_ICQ_STATE_DND       0x0002
-#define AIM_ICQ_STATE_NA        0x0004
-#define AIM_ICQ_STATE_OCCUPIED  0x0010
-#define AIM_ICQ_STATE_CHAT      0x0020
-#define AIM_ICQ_STATE_INVISIBLE 0x0100
+#define AIM_ICQ_STATE_NORMAL    0x00000000
+#define AIM_ICQ_STATE_AWAY      0x00000001
+#define AIM_ICQ_STATE_DND       0x00000002
+#define AIM_ICQ_STATE_OUT       0x00000004
+#define AIM_ICQ_STATE_BUSY      0x00000010
+#define AIM_ICQ_STATE_CHAT      0x00000020
+#define AIM_ICQ_STATE_INVISIBLE 0x00000100
+#define AIM_ICQ_STATE_WEBAWARE  0x00010000
 
 /*
  * AIM User Info, Standard Form.
@@ -380,9 +381,9 @@
 	fu32_t onlinesince;
 	fu32_t sessionlen; 
 	int capspresent;
-	fu16_t capabilities;
+	fu32_t capabilities;
 	struct {
-		fu16_t status;
+		fu32_t status;
 		fu32_t ipaddr;
 		fu8_t crap[0x25]; /* until we figure it out... */
 	} icqinfo;
@@ -395,7 +396,7 @@
 faim_export time_t aim_userinfo_membersince(aim_userinfo_t *ui);
 faim_export time_t aim_userinfo_onlinesince(aim_userinfo_t *ui);
 faim_export fu32_t aim_userinfo_sessionlen(aim_userinfo_t *ui);
-faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu16_t cap);
+faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap);
 
 #define AIM_FLAG_UNCONFIRMED 	0x0001 /* "damned transients" */
 #define AIM_FLAG_ADMINISTRATOR	0x0002
@@ -455,7 +456,7 @@
 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v);
 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t type, const fu32_t v);
 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v);
-faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu16_t caps);
+faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps);
 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t type);
 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui);
 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl);
@@ -578,7 +579,7 @@
 faim_export int aim_bos_setidle(aim_session_t *, aim_conn_t *, fu32_t);
 faim_export int aim_bos_changevisibility(aim_session_t *, aim_conn_t *, int, const char *);
 faim_export int aim_bos_setbuddylist(aim_session_t *, aim_conn_t *, const char *);
-faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu16_t caps);
+faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu32_t caps);
 faim_export int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, fu32_t mask);
 faim_export int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, fu32_t);
 faim_export int aim_reqpersonalinfo(aim_session_t *, aim_conn_t *);
@@ -588,7 +589,7 @@
 faim_export int aim_bos_reqlocaterights(aim_session_t *, aim_conn_t *);
 faim_export int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy);
 faim_export int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy);
-faim_export int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, fu16_t status);
+faim_export int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, fu32_t status);
 
 faim_export struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *);
 
@@ -725,6 +726,16 @@
 };
 
 /*
+ * Arguments to aim_send_rtfmsg().
+ */
+struct aim_sendrtfmsg_args {
+	const char *destsn;
+	fu32_t fgcolor;
+	fu32_t bgcolor;
+	const char *rtfmsg; /* must be in RTF */
+};
+
+/*
  * This information is provided in the Incoming ICBM callback for
  * Channel 1 ICBM's.  
  *
@@ -777,7 +788,7 @@
 			fu8_t *icon;
 		} icon;
 		struct {
-			fu8_t junk;
+			fu32_t implementme;
 		} voice;
 		struct {
 			fu8_t ip[22]; /* xxx.xxx.xxx.xxx:xxxxx\0 */
@@ -793,11 +804,17 @@
 			unsigned char *cookie;
 		} getfile;
 		struct {
-			fu8_t junk;
+			fu32_t implementme;
 		} sendfile;
+		struct {
+			fu32_t fgcolor;
+			fu32_t bgcolor;
+			const char *rtfmsg;
+		} rtfmsg;
 	} info;
 };
 
+faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args);
 faim_export int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args);
 faim_export int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg);
 faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum);
@@ -815,19 +832,23 @@
 faim_export int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn);
 
 /* aim_info.c */
-#define AIM_CAPS_BUDDYICON      0x0001
-#define AIM_CAPS_VOICE          0x0002
-#define AIM_CAPS_IMIMAGE        0x0004
-#define AIM_CAPS_CHAT           0x0008
-#define AIM_CAPS_GETFILE        0x0010
-#define AIM_CAPS_SENDFILE       0x0020
-#define AIM_CAPS_GAMES          0x0040
-#define AIM_CAPS_SAVESTOCKS     0x0080
-#define AIM_CAPS_SENDBUDDYLIST  0x0100
-#define AIM_CAPS_GAMES2         0x0200
-#define AIM_CAPS_ICQ            0x0400
-#define AIM_CAPS_ABINTERNAL     0x0800
-#define AIM_CAPS_LAST           0x8000
+#define AIM_CAPS_BUDDYICON      0x00000001
+#define AIM_CAPS_VOICE          0x00000002
+#define AIM_CAPS_IMIMAGE        0x00000004
+#define AIM_CAPS_CHAT           0x00000008
+#define AIM_CAPS_GETFILE        0x00000010
+#define AIM_CAPS_SENDFILE       0x00000020
+#define AIM_CAPS_GAMES          0x00000040
+#define AIM_CAPS_SAVESTOCKS     0x00000080
+#define AIM_CAPS_SENDBUDDYLIST  0x00000100
+#define AIM_CAPS_GAMES2         0x00000200
+#define AIM_CAPS_ICQ            0x00000400
+#define AIM_CAPS_ABINTERNAL     0x00000800
+#define AIM_CAPS_ICQRTF		0x00001000
+#define AIM_CAPS_EMPTY		0x00002000
+#define AIM_CAPS_ICQSERVERRELAY 0x00004000
+#define AIM_CAPS_ICQUNKNOWN     0x00008000
+#define AIM_CAPS_LAST           0x00010000
 
 faim_export int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn);
 
--- a/src/protocols/oscar/aim_internal.h	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/aim_internal.h	Mon Dec 10 00:48:27 2001 +0000
@@ -194,8 +194,8 @@
 
 faim_internal void aim_conn_addgroup(aim_conn_t *conn, fu16_t group);
 
-faim_internal fu16_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len);
-faim_internal int aim_putcap(aim_bstream_t *bs, fu16_t caps);
+faim_internal fu32_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len);
+faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps);
 
 faim_internal int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
 faim_internal aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, fu8_t *cookie, int type);
--- a/src/protocols/oscar/im.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/im.c	Mon Dec 10 00:48:27 2001 +0000
@@ -448,6 +448,122 @@
 	return 0;
 }
 
+/*
+ * This only works for ICQ 2001b (thats 2001 not 2000).  Better, only
+ * send it to clients advertising the RTF capability.  In fact, if you send
+ * it to a client that doesn't support that capability, the server will gladly
+ * bounce it back to you.
+ *
+ * You'd think this would be in icq.c, but, well, I'm trying to stick with
+ * the one-group-per-file scheme as much as possible.  This could easily
+ * be an exception, since Rendezvous IMs are external of the Oscar core, 
+ * and therefore are undefined.  Really I just need to think of a good way to
+ * make an interface similar to what AOL actually uses.  But I'm not using COM.
+ *
+ */
+faim_export int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)
+{
+	const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */
+	aim_conn_t *conn;
+	int i;
+	fu8_t ck[8];
+	aim_frame_t *fr;
+	aim_snacid_t snacid;
+	int servdatalen;
+
+	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))
+		return -EINVAL;
+
+	if (!args || !args->destsn || !args->rtfmsg)
+		return -EINVAL;
+
+	servdatalen = 2+2+16+2+4+1+2  +  2+2+4+4+4  +  2+4+2+strlen(args->rtfmsg)+1  +  4+4+4+strlen(rtfcap)+1;
+
+	for (i = 0; i < 8; i++)
+		aimutil_put8(ck+i, (fu8_t) rand());
+
+	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen)))
+		return -ENOMEM;
+
+	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);
+	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
+
+	/*
+	 * Cookie
+	 */
+	aimbs_putraw(&fr->data, ck, 8);
+
+	/*
+	 * Channel (2)
+	 */
+	aimbs_put16(&fr->data, 0x0002);
+
+	/*
+	 * Dest sn
+	 */
+	aimbs_put8(&fr->data, strlen(args->destsn));
+	aimbs_putraw(&fr->data, args->destsn, strlen(args->destsn));
+
+	/*
+	 * TLV t(0005)
+	 *
+	 * Encompasses everything below.
+	 */
+	aimbs_put16(&fr->data, 0x0005);
+	aimbs_put16(&fr->data, 2+8+16  +  2+2+2  +  2+2  +  2+2+servdatalen);
+
+	aimbs_put16(&fr->data, 0x0000);
+	aimbs_putraw(&fr->data, ck, 8);
+	aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);
+
+	/*
+	 * t(000a) l(0002) v(0001)
+	 */
+	aimbs_put16(&fr->data, 0x000a);
+	aimbs_put16(&fr->data, 0x0002);
+	aimbs_put16(&fr->data, 0x0001);
+
+	/*
+	 * t(000f) l(0000) v()
+	 */
+	aimbs_put16(&fr->data, 0x000f);
+	aimbs_put16(&fr->data, 0x0000);
+
+	/*
+	 * Service Data TLV
+	 */
+	aimbs_put16(&fr->data, 0x2711);
+	aimbs_put16(&fr->data, servdatalen);
+
+	aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */);
+	aimbs_putle16(&fr->data, 9);
+	aim_putcap(&fr->data, AIM_CAPS_EMPTY);
+	aimbs_putle16(&fr->data, 0);
+	aimbs_putle32(&fr->data, 0);
+	aimbs_putle8(&fr->data, 0);
+	aimbs_putle16(&fr->data, 0x03ea); /* trid1 */
+
+	aimbs_putle16(&fr->data, 14);
+	aimbs_putle16(&fr->data, 0x03eb); /* trid2 */
+	aimbs_putle32(&fr->data, 0);
+	aimbs_putle32(&fr->data, 0);
+	aimbs_putle32(&fr->data, 0);
+
+	aimbs_putle16(&fr->data, 0x0001);
+	aimbs_putle32(&fr->data, 0);
+	aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1);
+	aimbs_putraw(&fr->data, args->rtfmsg, strlen(args->rtfmsg)+1);
+
+	aimbs_putle32(&fr->data, args->fgcolor);
+	aimbs_putle32(&fr->data, args->bgcolor);
+	aimbs_putle32(&fr->data, strlen(rtfcap)+1);
+	aimbs_putraw(&fr->data, rtfcap, strlen(rtfcap)+1);
+
+	aim_tx_enqueue(sess, fr);
+
+	return 0;
+}
+
 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret)
 {
 	aim_conn_t *conn;
@@ -1368,6 +1484,54 @@
 	return ret;
 }
 
+/*
+ * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is 
+ * kind of odd. This sends the client ICQRTF since that is all that I've seen
+ * SERVERRELAY used for.
+ */
+static int incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2)
+{
+	aim_rxcallback_t userfunc;
+	int ret = 0;
+	aim_tlv_t *miscinfo;
+	aim_bstream_t tbs;
+	fu16_t hdrlen, anslen, msglen;
+	fu16_t msgtype;
+
+	if (!(miscinfo = aim_gettlv(list2, 0x2711, 1)))
+		return 0;
+	aim_bstream_init(&tbs, miscinfo->value, miscinfo->length);
+
+	hdrlen = aimbs_getle16(&tbs);
+	aim_bstream_advance(&tbs, hdrlen);
+
+	hdrlen = aimbs_getle16(&tbs);
+	aim_bstream_advance(&tbs, hdrlen);
+
+	msgtype = aimbs_getle16(&tbs);
+	
+	anslen = aimbs_getle32(&tbs);
+	aim_bstream_advance(&tbs, anslen);
+
+	msglen = aimbs_getle16(&tbs);
+	args->info.rtfmsg.rtfmsg = aimbs_getstr(&tbs, msglen);
+
+	args->info.rtfmsg.fgcolor = aimbs_getle32(&tbs);
+	args->info.rtfmsg.bgcolor = aimbs_getle32(&tbs);
+
+	hdrlen = aimbs_getle32(&tbs);
+	aim_bstream_advance(&tbs, hdrlen);
+
+	args->reqclass = AIM_CAPS_ICQRTF;
+
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, 0x0002, userinfo, args);
+
+	free(args->info.icon.icon);
+
+	return ret;
+}
+
 /* XXX Ugh.  I think its obvious. */
 static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie)
 {
@@ -1498,6 +1662,8 @@
 		ret = incomingim_ch2_getfile(sess, mod, rx, snac, userinfo, &args, list2);
 	else if (args.reqclass & AIM_CAPS_SENDFILE)
 		ret = incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, list2);
+	else if (args.reqclass & AIM_CAPS_ICQSERVERRELAY)
+		ret = incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, list2);
 	else
 		faimdprintf(sess, 0, "rend: unknown rendezvous 0x%04x\n", args.reqclass);
 
--- a/src/protocols/oscar/info.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/info.c	Mon Dec 10 00:48:27 2001 +0000
@@ -106,7 +106,7 @@
 	return ui->sessionlen;
 }
 
-faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu16_t cap)
+faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap)
 {
 
 	if (!ui || !ui->capspresent)
@@ -117,11 +117,18 @@
 
 
 /*
- * Capability blocks.  
+ * Capability blocks. 
+ *
+ * These are CLSIDs. They should actually be of the form:
+ *
+ * {0x0946134b, 0x4c7f, 0x11d1,
+ *  {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+ *
+ * But, eh.
  */
 static const struct {
-	unsigned short flag;
-	unsigned char data[16];
+	fu32_t flag;
+	fu8_t data[16];
 } aim_caps[] = {
 
 	/*
@@ -165,6 +172,10 @@
 	 {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
+	{AIM_CAPS_ICQSERVERRELAY,
+	 {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,
+	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
 	/*
 	 * Indeed, there are two of these.  The former appears to be correct, 
 	 * but in some versions of winaim, the second one is set.  Either they 
@@ -186,6 +197,18 @@
 	 {0x09, 0x46, 0x13, 0x4f, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
+	{AIM_CAPS_ICQRTF,
+	 {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 
+	  0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},
+
+	{AIM_CAPS_ICQUNKNOWN,
+	 {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
+	  0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
+
+	{AIM_CAPS_EMPTY,
+	 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+
 	{AIM_CAPS_LAST}
 };
 
@@ -194,9 +217,9 @@
  * are not naturally bounded.
  * 
  */
-faim_internal fu16_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len)
+faim_internal fu32_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len)
 {
-	fu16_t flags = 0;
+	fu32_t flags = 0;
 	int offset;
 
 	for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) {
@@ -224,7 +247,7 @@
 	return flags;
 }
 
-faim_internal int aim_putcap(aim_bstream_t *bs, fu16_t caps)
+faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps)
 {
 	int i;
 
--- a/src/protocols/oscar/misc.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/misc.c	Mon Dec 10 00:48:27 2001 +0000
@@ -78,7 +78,7 @@
  * Gives BOS your profile.
  * 
  */
-faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu16_t caps)
+faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu32_t caps)
 {
 	static const char defencoding[] = {"text/aolrtf; charset=\"us-ascii\""};
 	aim_frame_t *fr;
--- a/src/protocols/oscar/oscar.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/oscar.c	Mon Dec 10 00:48:27 2001 +0000
@@ -2365,7 +2365,7 @@
 		gc->away = NULL;
 
 	if (!strcmp(state, "Online"))
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_ONLINE);
+		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
 	else if (!strcmp(state, "Away")) {
 		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
 		gc->away = "";
@@ -2373,10 +2373,10 @@
 		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_DND);
 		gc->away = "";
 	} else if (!strcmp(state, "Not Available")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NA);
+		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT);
 		gc->away = "";
 	} else if (!strcmp(state, "Occupied")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OCCUPIED);
+		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_BUSY);
 		gc->away = "";
 	} else if (!strcmp(state, "Free For Chat")) {
 		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT);
@@ -2386,10 +2386,10 @@
 		gc->away = "";
 	} else if (!strcmp(state, GAIM_AWAY_CUSTOM)) {
 		if (message) {
-			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NA);
+			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT);
 			gc->away = "";
 		} else {
-			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_ONLINE);
+			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
 		}
 	}
 }
@@ -2590,9 +2590,9 @@
 			return icon_away_xpm;
 		if (uc & AIM_ICQ_STATE_DND)
 			return icon_dnd_xpm;
-		if (uc & AIM_ICQ_STATE_NA)
+		if (uc & AIM_ICQ_STATE_OUT)
 			return icon_na_xpm;
-		if (uc & AIM_ICQ_STATE_OCCUPIED)
+		if (uc & AIM_ICQ_STATE_BUSY)
 			return icon_occ_xpm;
 		if (uc & AIM_ICQ_STATE_CHAT)
 			return icon_ffc_xpm;
--- a/src/protocols/oscar/service.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/service.c	Mon Dec 10 00:48:27 2001 +0000
@@ -729,7 +729,7 @@
  * Currently only works if using ICQ.
  *
  */
-faim_export int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, fu16_t status)
+faim_export int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, fu32_t status)
 {
 	aim_frame_t *fr;
 	aim_snacid_t snacid;
--- a/src/protocols/oscar/tlv.c	Mon Dec 10 00:14:07 2001 +0000
+++ b/src/protocols/oscar/tlv.c	Mon Dec 10 00:48:27 2001 +0000
@@ -279,9 +279,9 @@
  *      %AIM_CAPS_SENDFILE    Supports Send File functions
  *
  */
-faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu16_t caps)
+faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps)
 {
-	fu8_t buf[16*16]; /* icky fixed length buffer */
+	fu8_t buf[16*16]; /* XXX icky fixed length buffer */
 	aim_bstream_t bs;
 
 	if (!caps)