changeset 2672:c41030cfed76

[gaim-migrate @ 2685] Time has told me You're a rare, rare find A troubled cure For a troubled mind And time has told me Not to ask for more Someday our ocean Will find its shore committer: Tailor Script <tailor@pidgin.im>
author Adam Fritzler <mid@auk.cx>
date Mon, 05 Nov 2001 02:05:06 +0000
parents ffa58bbe595d
children 81d658e6ac1e
files src/protocols/oscar/Makefile.am src/protocols/oscar/admin.c src/protocols/oscar/adverts.c src/protocols/oscar/aim.h src/protocols/oscar/aim_internal.h src/protocols/oscar/bos.c src/protocols/oscar/buddylist.c src/protocols/oscar/chat.c src/protocols/oscar/chatnav.c src/protocols/oscar/conn.c src/protocols/oscar/im.c src/protocols/oscar/info.c src/protocols/oscar/invite.c src/protocols/oscar/login.c src/protocols/oscar/meta.c src/protocols/oscar/misc.c src/protocols/oscar/oscar.c src/protocols/oscar/popups.c src/protocols/oscar/rxhandlers.c src/protocols/oscar/search.c src/protocols/oscar/ssi.c src/protocols/oscar/stats.c src/protocols/oscar/translate.c src/protocols/oscar/util.c
diffstat 24 files changed, 473 insertions(+), 217 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/oscar/Makefile.am	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/Makefile.am	Mon Nov 05 02:05:06 2001 +0000
@@ -23,17 +23,21 @@
 			ft.c		\
 			im.c		\
 			info.c		\
+			invite.c	\
 			login.c		\
 			md5.c		\
 			meta.c		\
 			misc.c		\
 			msgcookie.c	\
+			popups.c	\
 			rxhandlers.c	\
 			rxqueue.c	\
 			search.c	\
 			snac.c		\
+			ssi.c		\
 			stats.c		\
 			tlv.c		\
+			translate.c	\
 			txqueue.c	\
 			util.c		\
 			oscar.c
@@ -56,17 +60,21 @@
 			ft.c		\
 			im.c		\
 			info.c		\
+			invite.c	\
 			login.c		\
 			md5.c		\
 			meta.c		\
 			misc.c		\
 			msgcookie.c	\
+			popups.c	\
 			rxhandlers.c	\
 			rxqueue.c	\
 			search.c	\
 			snac.c		\
+			ssi.c		\
 			stats.c		\
 			tlv.c		\
+			translate.c	\
 			txqueue.c	\
 			util.c		\
 			oscar.c
--- a/src/protocols/oscar/admin.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/admin.c	Mon Nov 05 02:05:06 2001 +0000
@@ -77,7 +77,9 @@
 {
 
 	mod->family = 0x0007;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = AIM_TOOL_NEWWIN;
+	mod->toolversion = 0x0361; /* XXX this and above aren't right */
 	mod->flags = 0;
 	strncpy(mod->name, "admin", sizeof(mod->name));
 	mod->snachandler = snachandler;
@@ -85,35 +87,6 @@
 	return 0;
 }
 
-faim_export int aim_auth_clientready(aim_session_t *sess, aim_conn_t *conn)
-{
-	static const struct aim_tool_version tools[] = {
-		{0x0001, 0x0003,    AIM_TOOL_NEWWIN, 0x0361},
-		{0x0007, 0x0001,    AIM_TOOL_NEWWIN, 0x0361},
-	};
-	int j;
-	aim_frame_t *tx;
-	int toolcount = sizeof(tools) / sizeof(struct aim_tool_version);
-	aim_snacid_t snacid;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 1152)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0001, 0x0002, 0x0000, snacid);
-
-	for (j = 0; j < toolcount; j++) {
-		aimbs_put16(&tx->data, tools[j].group);
-		aimbs_put16(&tx->data, tools[j].version);
-		aimbs_put16(&tx->data, tools[j].tool);
-		aimbs_put16(&tx->data, tools[j].toolversion);
-	}
-
-	aim_tx_enqueue(sess, tx);
-
-	return 0;
-}
-
 faim_export int aim_auth_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *newpw, const char *curpw)
 {
 	aim_frame_t *tx;
@@ -140,28 +113,6 @@
 	return 0;
 }
 
-faim_export int aim_auth_setversions(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *tx;
-	aim_snacid_t snacid;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 18)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0001, 0x0017, 0x0000, snacid);
-
-	aimbs_put16(&tx->data, 0x0001);
-	aimbs_put16(&tx->data, 0x0003);
-
-	aimbs_put16(&tx->data, 0x0007);
-	aimbs_put16(&tx->data, 0x0001);
-
-	aim_tx_enqueue(sess, tx);
-
-	return 0;
-}
-
 /*
  * Request account confirmation. 
  *
--- a/src/protocols/oscar/adverts.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/adverts.c	Mon Nov 05 02:05:06 2001 +0000
@@ -6,34 +6,28 @@
 #define FAIM_INTERNAL
 #include <aim.h>
 
-faim_export int aim_ads_clientready(aim_session_t *sess, aim_conn_t *conn)
+faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn)
 {
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 0x1a)))
-		return -ENOMEM;
+	return aim_genericreq_n(sess, conn, 0x0005, 0x0002);
+}
 
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
+static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+	return 0;
+}
 
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0002);
-
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0013);
+faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod)
+{
 
-	aimbs_put16(&fr->data, 0x0005);
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0001);
-
-	aim_tx_enqueue(sess, fr);
+	mod->family = 0x0005;
+	mod->version = 0x0001;
+	mod->toolid = 0x0001;
+	mod->toolversion = 0x0001;
+	mod->flags = 0;
+	strncpy(mod->name, "adverts", sizeof(mod->name));
+	mod->snachandler = snachandler;
 
 	return 0;
 }
 
-faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0005, 0x0002);
-}
+
--- a/src/protocols/oscar/aim.h	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/aim.h	Mon Nov 05 02:05:06 2001 +0000
@@ -500,6 +500,7 @@
 typedef int (*aim_rxcallback_t)(aim_session_t *, aim_frame_t *, ...);
 
 /* aim_login.c */
+faim_export int aim_clientready(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn);
 faim_export int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key);
@@ -564,9 +565,8 @@
 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_setgroupperm(aim_session_t *, aim_conn_t *, fu32_t mask);
-faim_export int aim_bos_clientready(aim_session_t *, aim_conn_t *);
-faim_export int aim_bos_reqrate(aim_session_t *, aim_conn_t *);
-faim_export int aim_bos_ackrateresp(aim_session_t *, aim_conn_t *);
+faim_export int aim_reqrates(aim_session_t *, aim_conn_t *);
+faim_export int aim_ratesack(aim_session_t *, aim_conn_t *);
 faim_export int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, fu32_t);
 faim_export int aim_bos_reqpersonalinfo(aim_session_t *, aim_conn_t *);
 faim_export int aim_bos_reqservice(aim_session_t *, aim_conn_t *, fu16_t);
@@ -591,7 +591,6 @@
 #define AIM_RATE_CODE_WARNING    0x0002
 #define AIM_RATE_CODE_LIMIT      0x0003
 #define AIM_RATE_CODE_CLEARLIMIT 0x0004
-faim_export int aim_ads_clientready(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn);
 
 /* aim_im.c */
@@ -896,9 +895,7 @@
 /* auth.c */
 faim_export int aim_auth_sendcookie(aim_session_t *, aim_conn_t *, const fu8_t *);
 
-faim_export int aim_auth_clientready(aim_session_t *, aim_conn_t *);
 faim_export int aim_auth_changepasswd(aim_session_t *, aim_conn_t *, const char *newpw, const char *curpw);
-faim_export int aim_auth_setversions(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_auth_reqconfirm(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_auth_getinfo(aim_session_t *sess, aim_conn_t *conn, fu16_t info);
 faim_export int aim_auth_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail);
@@ -923,19 +920,40 @@
 #define AIM_CHATFLAGS_AWAY      0x0002
 faim_export int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, fu16_t flags, const char *msg, int msglen);
 faim_export int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, fu16_t exchange, const char *roomname, fu16_t instance);
-faim_export int aim_chat_clientready(aim_session_t *sess, aim_conn_t *conn);
 faim_export int aim_chat_attachname(aim_conn_t *conn, const char *roomname);
 faim_export char *aim_chat_getname(aim_conn_t *conn);
 faim_export aim_conn_t *aim_chat_getconn(aim_session_t *, const char *name);
 
 faim_export int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn);
-faim_export int aim_chatnav_clientready(aim_session_t *sess, aim_conn_t *conn);
 
 faim_export int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, fu16_t exchange, const char *roomname, fu16_t instance);
 
 faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange);
 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name);
 
+
+#define AIM_SSI_TYPE_BUDDY         0x0000
+#define AIM_SSI_TYPE_GROUP         0x0001
+#define AIM_SSI_TYPE_PERMITLIST    0x0002
+#define AIM_SSI_TYPE_DENYLIST      0x0003
+#define AIM_SSI_TYPE_PDINFO        0x0004
+#define AIM_SSI_TYPE_PRESENCEPREFS 0x0005
+
+struct aim_ssi_item {
+	char *name;
+	fu16_t gid;
+	fu16_t bid;
+	fu16_t type;
+	void *data;
+	struct aim_ssi_item *next;
+};
+
+faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn);
+faim_export int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, fu16_t localrev);
+faim_export int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn);
+faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn);
+faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn);
+
 /* aim_util.c */
 /*
  * These are really ugly.  You'd think this was LISP.  I wish it was.
--- a/src/protocols/oscar/aim_internal.h	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/aim_internal.h	Mon Nov 05 02:05:06 2001 +0000
@@ -17,9 +17,11 @@
 #define AIM_MODULENAME_MAXLEN 16
 #define AIM_MODFLAG_MULTIFAMILY 0x0001
 typedef struct aim_module_s {
-	unsigned short family;
-	unsigned short flags;
-	unsigned short version;
+	fu16_t family;
+	fu16_t version;
+	fu16_t toolid;
+	fu16_t toolversion;
+	fu16_t flags;
 	char name[AIM_MODULENAME_MAXLEN+1];
 	int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs);
 	void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod);
@@ -29,7 +31,8 @@
 
 faim_internal int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, aim_module_t *));
 faim_internal void aim__shutdownmodules(aim_session_t *sess);
-
+faim_internal aim_module_t *aim__findmodulebygroup(aim_session_t *sess, fu16_t group);
+faim_internal aim_module_t *aim__findmodule(aim_session_t *sess, const char *name);
 
 faim_internal int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod);
 faim_internal int admin_modfirst(aim_session_t *sess, aim_module_t *mod);
@@ -43,6 +46,11 @@
 faim_internal int chat_modfirst(aim_session_t *sess, aim_module_t *mod);
 faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod);
 faim_internal int general_modfirst(aim_session_t *sess, aim_module_t *mod);
+faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod);
+faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod);
+faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod);
+faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod);
+faim_internal int adverts_modfirst(aim_session_t *sess, aim_module_t *mod);
 
 faim_internal int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype);
 faim_internal int aim_genericreq_n_snacid(aim_session_t *, aim_conn_t *conn, fu16_t family, fu16_t subtype);
--- a/src/protocols/oscar/bos.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/bos.c	Mon Nov 05 02:05:06 2001 +0000
@@ -62,7 +62,9 @@
 {
 
 	mod->family = 0x0009;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "bos", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/buddylist.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/buddylist.c	Mon Nov 05 02:05:06 2001 +0000
@@ -76,7 +76,9 @@
 {
 
 	mod->family = 0x0003;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "buddylist", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/chat.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/chat.c	Mon Nov 05 02:05:06 2001 +0000
@@ -238,34 +238,6 @@
 	return 0;
 }
 
-faim_export int aim_chat_clientready(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 0x20)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
-
-	aimbs_put16(&fr->data, 0x000e);
-	aimbs_put16(&fr->data, 0x0001);
-
-	aimbs_put16(&fr->data, 0x0004);
-	aimbs_put16(&fr->data, 0x0001);
-
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0003);
-
-	aimbs_put16(&fr->data, 0x0004);
-	aimbs_put16(&fr->data, 0x0686);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
 faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name)
 {
 	aim_conn_t *conn;
@@ -704,7 +676,9 @@
 {
 
 	mod->family = 0x000e;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0004; /* XXX this doesn't look right */
+	mod->toolversion = 0x0001; /* nor does this */
 	mod->flags = 0;
 	strncpy(mod->name, "chat", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/chatnav.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/chatnav.c	Mon Nov 05 02:05:06 2001 +0000
@@ -18,34 +18,6 @@
 	return aim_genericreq_n_snacid(sess, conn, 0x000d, 0x0002);
 }
 
-faim_export int aim_chatnav_clientready(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 0x20)))
-		return -ENOMEM;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
-
-	aimbs_put16(&fr->data, 0x000d);
-	aimbs_put16(&fr->data, 0x0001);
-
-	aimbs_put16(&fr->data, 0x0004);
-	aimbs_put16(&fr->data, 0x0001);
-
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, 0x0003);
-
-	aimbs_put16(&fr->data, 0x0004);
-	aimbs_put16(&fr->data, 0x0686);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
 faim_export int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, fu16_t exchange)
 {
 	aim_frame_t *fr;
@@ -390,7 +362,9 @@
 {
 
 	mod->family = 0x000d;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0004; /* XXX this doesn't look right */
+	mod->toolversion = 0x0001; /* XXX nor does this */
 	mod->flags = 0;
 	strncpy(mod->name, "chatnav", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/conn.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/conn.c	Mon Nov 05 02:05:06 2001 +0000
@@ -862,17 +862,24 @@
 	 * Register all the modules for this session...
 	 */
 	aim__registermodule(sess, misc_modfirst); /* load the catch-all first */
+	aim__registermodule(sess, general_modfirst);
+	aim__registermodule(sess, locate_modfirst);
 	aim__registermodule(sess, buddylist_modfirst);
+	aim__registermodule(sess, msg_modfirst);
+	aim__registermodule(sess, adverts_modfirst);
+	aim__registermodule(sess, invite_modfirst);
 	aim__registermodule(sess, admin_modfirst);
+	aim__registermodule(sess, popups_modfirst);
 	aim__registermodule(sess, bos_modfirst);
 	aim__registermodule(sess, search_modfirst);
 	aim__registermodule(sess, stats_modfirst);
-	aim__registermodule(sess, auth_modfirst);
-	aim__registermodule(sess, msg_modfirst);
+	aim__registermodule(sess, translate_modfirst);
 	aim__registermodule(sess, chatnav_modfirst);
 	aim__registermodule(sess, chat_modfirst);
-	aim__registermodule(sess, locate_modfirst);
-	aim__registermodule(sess, general_modfirst);
+	/* missing 0x0f - 0x12 */
+	aim__registermodule(sess, ssi_modfirst);
+	/* missing 0x14 - 0x16 */
+	aim__registermodule(sess, auth_modfirst);
 
 	return;
 }
--- a/src/protocols/oscar/im.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/im.c	Mon Nov 05 02:05:06 2001 +0000
@@ -1626,7 +1626,9 @@
 {
 
 	mod->family = 0x0004;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "messaging", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/info.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/info.c	Mon Nov 05 02:05:06 2001 +0000
@@ -627,7 +627,9 @@
 {
 
 	mod->family = 0x0002;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0101;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "locate", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/oscar/invite.c	Mon Nov 05 02:05:06 2001 +0000
@@ -0,0 +1,36 @@
+/*
+ * This isn't really ever used by anyone anymore.
+ *
+ * Once upon a time, there used to be a menu item in AIM clients that
+ * said something like "Invite a friend to use AIM..." and then it would
+ * ask for an email address and it would sent a mail to them saying
+ * how perfectly wonderful the AIM service is and why you should use it
+ * and click here if you hate the person who sent this to you and want to
+ * complain and yell at them in a small box with pretty fonts.
+ *
+ * I could've sworn libfaim had this implemented once, a long long time ago,
+ * but I can't find it.
+ *
+ * I'm mainly adding this so that I can keep advertising that we support
+ * group 6, even though we don't.
+ *
+ */
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+faim_internal int invite_modfirst(aim_session_t *sess, aim_module_t *mod)
+{
+
+	mod->family = 0x0006;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
+	mod->flags = 0;
+	strncpy(mod->name, "invite", sizeof(mod->name));
+	mod->snachandler = NULL;
+
+	return 0;
+}
+
+
--- a/src/protocols/oscar/login.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/login.c	Mon Nov 05 02:05:06 2001 +0000
@@ -1001,7 +1001,9 @@
 {
 
 	mod->family = 0x0001;
-	mod->version = 0x0000;
+	mod->version = 0x0003;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "general", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- a/src/protocols/oscar/meta.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/meta.c	Mon Nov 05 02:05:06 2001 +0000
@@ -4,6 +4,7 @@
  *  
  */
 
+#define FAIM_INTERNAL
 #include <aim.h>
 
 faim_export char *aim_getbuilddate(void)
--- a/src/protocols/oscar/misc.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/misc.c	Mon Nov 05 02:05:06 2001 +0000
@@ -215,23 +215,15 @@
  * Send Client Ready.  
  *
  */
-faim_export int aim_bos_clientready(aim_session_t *sess, aim_conn_t *conn)
+faim_export int aim_clientready(aim_session_t *sess, aim_conn_t *conn)
 {
-	struct aim_tool_version tools[] = {
-		{0x0001, 0x0003,    AIM_TOOL_WIN32, 0x0686},
-		{0x0002, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
-		{0x0003, 0x0001,    AIM_TOOL_WIN32, 0x0001},
-		{0x0004, 0x0001,    AIM_TOOL_WIN32, 0x0001},
-		{0x0006, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
-		{0x0008, 0x0001,    AIM_TOOL_WIN32, 0x0001},
-		{0x0009, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
-		{0x000a, 0x0001,    AIM_TOOL_WIN32, 0x0001},
-		{0x000b, 0x0001,    AIM_TOOL_WIN32, 0x0001}
-	};
-	int j;
+	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
+	struct snacgroup *sg;
 	aim_frame_t *fr;
 	aim_snacid_t snacid;
-	int toolcount = sizeof(tools)/sizeof(struct aim_tool_version);
+
+	if (!ins)
+		return -EINVAL;
 
 	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
 		return -ENOMEM;
@@ -239,11 +231,20 @@
 	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
 
-	for (j = 0; j < toolcount; j++) {
-		aimbs_put16(&fr->data, tools[j].group);
-		aimbs_put16(&fr->data, tools[j].version);
-		aimbs_put16(&fr->data, tools[j].tool);
-		aimbs_put16(&fr->data, tools[j].toolversion);
+	/*
+	 * Send only the tool versions that the server cares about (that it
+	 * marked as supporting in the server ready SNAC).  
+	 */
+	for (sg = ins->groups; sg; sg = sg->next) {
+		aim_module_t *mod;
+
+		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
+			aimbs_put16(&fr->data, mod->family);
+			aimbs_put16(&fr->data, mod->version);
+			aimbs_put16(&fr->data, mod->toolid);
+			aimbs_put16(&fr->data, mod->toolversion);
+		} else
+			faimdprintf(sess, 1, "aim_clientready: server supports group 0x%04x but we don't!\n", sg->group);
 	}
 
 	aim_tx_enqueue(sess, fr);
@@ -255,7 +256,7 @@
  *  Request Rate Information.
  * 
  */
-faim_export int aim_bos_reqrate(aim_session_t *sess, aim_conn_t *conn)
+faim_export int aim_reqrates(aim_session_t *sess, aim_conn_t *conn)
 {
 	return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
 }
@@ -264,7 +265,7 @@
  *  Rate Information Response Acknowledge.
  *
  */
-faim_export int aim_bos_ackrateresp(aim_session_t *sess, aim_conn_t *conn)
+faim_export int aim_ratesack(aim_session_t *sess, aim_conn_t *conn)
 {
 	aim_frame_t *fr;	
 	aim_snacid_t snacid;
@@ -275,6 +276,8 @@
 	snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0);
 	
 	aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid);
+
+	/* XXX store the rate info in the inside struct, make this dynamic */
 	aimbs_put16(&fr->data, 0x0001); 
 	aimbs_put16(&fr->data, 0x0002);
 	aimbs_put16(&fr->data, 0x0003);
@@ -311,37 +314,32 @@
 
 faim_export int aim_setversions(aim_session_t *sess, aim_conn_t *conn)
 {
+	aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
+	struct snacgroup *sg;
 	aim_frame_t *fr;
 	aim_snacid_t snacid;
-	static const struct version {
-		fu16_t group;
-		fu16_t version;
-	} versions[] = {
-		{0x0001, 0x0003},
-		{0x0002, 0x0001},
-		{0x0003, 0x0001},
-		{0x0004, 0x0001},
-		{0x0006, 0x0001},
-		{0x0008, 0x0001},
-		{0x0009, 0x0001},
-		{0x000a, 0x0001},
-		{0x000b, 0x0002},
-		{0x000c, 0x0001},
-		{0x0013, 0x0001},
-		{0x0015, 0x0001},
-	};
-	int numversions = sizeof(versions) / sizeof(struct version);
-	int i;
 
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + (4*numversions))))
+	if (!ins)
+		return -EINVAL;
+
+	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
 		return -ENOMEM;
 
 	snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
+	aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid);
 
-	aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid);
-	for (i = 0; i < numversions; i++) {
-		aimbs_put16(&fr->data, versions[i].group);
-		aimbs_put16(&fr->data, versions[i].version);
+	/*
+	 * Send only the versions that the server cares about (that it
+	 * marked as supporting in the server ready SNAC).  
+	 */
+	for (sg = ins->groups; sg; sg = sg->next) {
+		aim_module_t *mod;
+
+		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
+			aimbs_put16(&fr->data, mod->family);
+			aimbs_put16(&fr->data, mod->version);
+		} else
+			faimdprintf(sess, 1, "aim_setversions: server supports group 0x%04x but we don't!\n", sg->group);
 	}
 
 	aim_tx_enqueue(sess, fr);
--- a/src/protocols/oscar/oscar.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/oscar.c	Mon Nov 05 02:05:06 2001 +0000
@@ -859,8 +859,8 @@
 
 static int server_ready_auth(aim_session_t *sess, aim_frame_t *fr, ...) {
 
-	aim_auth_setversions(sess, fr->conn);
-	aim_bos_reqrate(sess, fr->conn);
+	aim_setversions(sess, fr->conn);
+	aim_reqrates(sess, fr->conn);
 	debug_printf("done with AUTH ServerReady\n");
 
 	return 1;
@@ -868,7 +868,7 @@
 
 static int server_ready_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
 	aim_setversions(sess, fr->conn);
-	aim_bos_reqrate(sess, fr->conn); /* request rate info */
+	aim_reqrates(sess, fr->conn); /* request rate info */
 	debug_printf("done with BOS ServerReady\n");
 
 	return 1;
@@ -879,8 +879,8 @@
 	struct chat_connection *chatcon;
 	static int id = 1;
 
-	aim_bos_ackrateresp(sess, fr->conn);
-	aim_chat_clientready(sess, fr->conn);
+	aim_ratesack(sess, fr->conn);
+	aim_clientready(sess, fr->conn);
 	chatcon = find_oscar_chat_by_conn(gc, fr->conn);
 	chatcon->id = id;
 	chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
@@ -890,8 +890,8 @@
 
 static int rateresp_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) {
 
-	aim_bos_ackrateresp(sess, fr->conn);
-	aim_chatnav_clientready(sess, fr->conn);
+	aim_ratesack(sess, fr->conn);
+	aim_clientready(sess, fr->conn);
 	aim_chatnav_reqrights(sess, fr->conn);
 
 	return 1;
@@ -901,7 +901,7 @@
 	debug_printf("chatnav: got server ready\n");
 	aim_conn_addhandler(sess, fr->conn, 0x0001, 0x0007, rateresp_chatnav, 0);
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
-	aim_bos_reqrate(sess, fr->conn);
+	aim_reqrates(sess, fr->conn);
 
 	return 1;
 }
@@ -914,7 +914,7 @@
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
 	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
-	aim_bos_reqrate(sess, fr->conn);
+	aim_reqrates(sess, fr->conn);
 
 	return 1;
 }
@@ -1935,7 +1935,7 @@
 static int rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
 	struct gaim_connection *gc = sess->aux_data;
 
-	aim_bos_ackrateresp(sess, fr->conn);
+	aim_ratesack(sess, fr->conn);
 	aim_bos_reqpersonalinfo(sess, fr->conn);
 	aim_bos_reqlocaterights(sess, fr->conn);
 	aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps);
@@ -1963,8 +1963,8 @@
 	struct gaim_connection *gc = sess->aux_data;
 	struct oscar_data *od = gc->proto_data;
 
-	aim_bos_ackrateresp(sess, fr->conn);
-	aim_auth_clientready(sess, fr->conn);
+	aim_ratesack(sess, fr->conn);
+	aim_clientready(sess, fr->conn);
 	debug_printf("connected to auth (admin)\n");
 
 	if (od->chpass) {
@@ -2039,7 +2039,7 @@
 
 	debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
 
-	aim_bos_clientready(sess, fr->conn);
+	aim_clientready(sess, fr->conn);
 
 	aim_bos_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/oscar/popups.c	Mon Nov 05 02:05:06 2001 +0000
@@ -0,0 +1,22 @@
+/*
+ * This might be fun to implement. Right? Maybe not. 
+ */
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+faim_internal int popups_modfirst(aim_session_t *sess, aim_module_t *mod)
+{
+
+	mod->family = 0x0008;
+	mod->version = 0x0001;
+	mod->toolid = 0x0104;
+	mod->toolversion = 0x0001;
+	mod->flags = 0;
+	strncpy(mod->name, "popups", sizeof(mod->name));
+	mod->snachandler = NULL;
+
+	return 0;
+}
+
+
--- a/src/protocols/oscar/rxhandlers.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/rxhandlers.c	Mon Nov 05 02:05:06 2001 +0000
@@ -18,7 +18,19 @@
 	struct aim_rxcblist_s *next;
 };
 
-static aim_module_t *findmodule(aim_session_t *sess, const char *name)
+faim_internal aim_module_t *aim__findmodulebygroup(aim_session_t *sess, fu16_t group)
+{
+	aim_module_t *cur;
+
+	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
+		if (cur->family == group)
+			return cur;
+	}
+
+	return NULL;
+}
+
+faim_internal aim_module_t *aim__findmodule(aim_session_t *sess, const char *name)
 {
 	aim_module_t *cur;
 
@@ -46,7 +58,7 @@
 		return -1;
 	}
 
-	if (findmodule(sess, mod->name)) {
+	if (aim__findmodule(sess, mod->name)) {
 		if (mod->shutdown)
 			mod->shutdown(sess, mod);
 		free(mod);
@@ -56,7 +68,7 @@
 	mod->next = (aim_module_t *)sess->modlistv;
 	(aim_module_t *)sess->modlistv = mod;
 
-	faimdprintf(sess, 1, "registered module %s (family 0x%04x)\n", mod->name, mod->family);
+	faimdprintf(sess, 1, "registered module %s (family 0x%04x, version = 0x%04x, tool 0x%04x, tool version 0x%04x)\n", mod->name, mod->family, mod->version, mod->toolid, mod->toolversion);
 
 	return 0;
 }
--- a/src/protocols/oscar/search.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/search.c	Mon Nov 05 02:05:06 2001 +0000
@@ -109,7 +109,9 @@
 {
 
 	mod->family = 0x000a;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
 	mod->flags = 0;
 	strncpy(mod->name, "search", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/oscar/ssi.c	Mon Nov 05 02:05:06 2001 +0000
@@ -0,0 +1,211 @@
+/*
+ * Server-Side/Stored Information.
+ *
+ * Relatively new facility that allows storing of certain types of information,
+ * such as a users buddy list, permit/deny list, and permit/deny preferences, 
+ * to be stored on the server, so that they can be accessed from any client.
+ *
+ * This is entirely too complicated.
+ *
+ */
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+/*
+ * Request SSI Rights.
+ */
+faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn)
+{
+	return aim_genericreq_n(sess, conn, 0x0013, 0x0002);
+}
+
+/*
+ * SSI Rights Information.
+ */
+static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+	int ret = 0;
+	aim_rxcallback_t userfunc;
+
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx);
+
+	return ret;
+}
+
+/*
+ * Request SSI Data.
+ *
+ * The data will only be sent if it is newer than the posted local
+ * timestamp and revision.
+ * 
+ * Note that the client should never increment the revision, only the server.
+ * 
+ */
+faim_export int aim_ssi_reqdata(aim_session_t *sess, aim_conn_t *conn, time_t localstamp, fu16_t localrev)
+{
+	aim_frame_t *fr;
+	aim_snacid_t snacid;
+
+	if (!sess || !conn)
+		return -EINVAL;
+
+	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
+		return -ENOMEM;
+
+	snacid = aim_cachesnac(sess, 0x0013, 0x0005, 0x0000, NULL, 0);
+
+	aim_putsnac(&fr->data, 0x0013, 0x0005, 0x0000, snacid);
+	aimbs_put32(&fr->data, localstamp);
+	aimbs_put16(&fr->data, localrev);
+
+	aim_tx_enqueue(sess, fr);
+
+	return 0;
+}
+
+/*
+ * SSI Data.
+ */
+static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+	int ret = 0;
+	aim_rxcallback_t userfunc;
+	struct aim_ssi_item *list = NULL;
+	fu8_t fmtver; /* guess */
+	fu16_t itemcount;
+	fu32_t stamp;
+
+	fmtver = aimbs_get8(bs);
+	itemcount = aimbs_get16(bs);
+
+	while (aim_bstream_empty(bs) > 4) { /* last four bytes are stamp */
+		fu16_t namelen, tbslen;
+		struct aim_ssi_item *nl, *el;
+
+		if (!(nl = malloc(sizeof(struct aim_ssi_item))))
+			break;
+		memset(nl, 0, sizeof(struct aim_ssi_item));
+
+		if ((namelen = aimbs_get16(bs)))
+			nl->name = aimbs_getstr(bs, namelen);
+		nl->gid = aimbs_get16(bs);
+		nl->bid = aimbs_get16(bs);
+		nl->type = aimbs_get16(bs);
+
+		if ((tbslen = aimbs_get16(bs))) {
+			aim_bstream_t tbs;
+
+			aim_bstream_init(&tbs, bs->data + bs->offset /* XXX */, tbslen);
+			nl->data = (void *)aim_readtlvchain(&tbs);
+			aim_bstream_advance(bs, tbslen);
+		}
+
+		for (el = list; el && el->next; el = el->next)
+			;
+		if (el)
+			el->next = nl;
+		else
+			list = nl;
+	}
+
+	stamp = aimbs_get32(bs);
+
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx, fmtver, itemcount, stamp, list);
+
+	while (list) {
+		struct aim_ssi_item *tmp;
+
+		tmp = list->next;
+		aim_freetlvchain((aim_tlvlist_t **)&list->data);
+		free(list);
+		list = tmp;
+	}
+
+	return ret;
+}
+
+/*
+ * SSI Data Enable Presence.
+ *
+ * Should be sent after receiving 13/6 or 13/f to tell the server you
+ * are ready to begin using the list.  It will promptly give you the
+ * presence information for everyone in your list and put your permit/deny
+ * settings into effect.
+ * 
+ */
+faim_export int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn)
+{
+	return aim_genericreq_n(sess, conn, 0x0013, 0x0007);
+}
+
+/*
+ * SSI Begin Data Modification.
+ *
+ * Tells the server you're going to start modifying data.
+ * 
+ */
+faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn)
+{
+	return aim_genericreq_n(sess, conn, 0x0013, 0x0011);
+}
+
+/*
+ * SSI End Data Modification.
+ *
+ * Tells the server you're done modifying data.
+ *
+ */
+faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn)
+{
+	return aim_genericreq_n(sess, conn, 0x0013, 0x0012);
+}
+
+/*
+ * SSI Data Unchanged.
+ *
+ * Response to aim_ssi_reqdata() if the server-side data is not newer than
+ * posted local stamp/revision.
+ *
+ */
+static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+	int ret = 0;
+	aim_rxcallback_t userfunc;
+
+	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+		ret = userfunc(sess, rx);
+
+	return ret;
+}
+
+static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
+{
+
+	if (snac->subtype == 0x0003)
+		return parserights(sess, mod, rx, snac, bs);
+	else if (snac->subtype == 0x006)
+		return parsedata(sess, mod, rx, snac, bs);
+	else if (snac->subtype == 0x00f)
+		return parsedataunchanged(sess, mod, rx, snac, bs);
+
+	return 0;
+}
+
+faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
+{
+
+	mod->family = 0x0013;
+	mod->version = 0x0001;
+	mod->toolid = 0x0110;
+	mod->toolversion = 0x047b;
+	mod->flags = 0;
+	strncpy(mod->name, "ssi", sizeof(mod->name));
+	mod->snachandler = snachandler;
+
+	return 0;
+}
+
+
--- a/src/protocols/oscar/stats.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/stats.c	Mon Nov 05 02:05:06 2001 +0000
@@ -28,7 +28,9 @@
 {
 
 	mod->family = 0x000b;
-	mod->version = 0x0000;
+	mod->version = 0x0001;
+	mod->toolid = 0x0104;
+	mod->toolversion = 0x0001;
 	mod->flags = 0;
 	strncpy(mod->name, "stats", sizeof(mod->name));
 	mod->snachandler = snachandler;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/oscar/translate.c	Mon Nov 05 02:05:06 2001 +0000
@@ -0,0 +1,27 @@
+/*
+ * I have no idea why this group was issued.  I have never seen anything
+ * that uses it.  From what I remember, the last time I tried to poke at
+ * the server with this group, it whined about not supporting it.
+ *
+ * But we advertise it anyway, because its fun.
+ * 
+ */
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+faim_internal int translate_modfirst(aim_session_t *sess, aim_module_t *mod)
+{
+
+	mod->family = 0x000c;
+	mod->version = 0x0001;
+	mod->toolid = 0x0104;
+	mod->toolversion = 0x0001;
+	mod->flags = 0;
+	strncpy(mod->name, "translate", sizeof(mod->name));
+	mod->snachandler = NULL;
+
+	return 0;
+}
+
+
--- a/src/protocols/oscar/util.c	Sun Nov 04 12:54:41 2001 +0000
+++ b/src/protocols/oscar/util.c	Mon Nov 05 02:05:06 2001 +0000
@@ -4,6 +4,7 @@
  *
  */
 
+#define FAIM_INTERNAL
 #include <aim.h>
 #include <ctype.h>