changeset 23336:2cc744b5925c

merge of '6f45eed99c94f8e63e46ad382a70c0c4e266b833' and 'ba8d3b144d041faa33c133fc7dd605eea606c66a'
author Mark Doliner <mark@kingant.net>
date Mon, 09 Jun 2008 06:35:52 +0000
parents 9776a2fc2370 (diff) 67581872c47f (current diff)
children a7711cdafa6b
files
diffstat 41 files changed, 481 insertions(+), 286 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Jun 07 01:06:41 2008 +0000
+++ b/ChangeLog	Mon Jun 09 06:35:52 2008 +0000
@@ -7,12 +7,17 @@
 	  Marcus Lundblad, Jorge Villaseñor and other contributors)
 	* Yahoo! Japan now uses UTF-8, matching the behavior of official clients
 	  and restoring compatibility with the web messenger (Yusuke Odate)
+	* Add a configure option, --with-ssl-certificates to allow packagers
+	  to specify a system-wide SSL CA certificates directory.  Also, when
+	  set, we don't install our SSL CA certs.
 
 	Pidgin:
-	* Custom buddy icons can now be added and removed to buddy list
+	* Custom buddy icons can now be added to and removed from buddy list
 	  entries via the buddy list entry right-click menu.
 	* Resize large incoming custom smileys to a maximum of 96px on either
 	  side.
+	* Offer to add new buddies into the same contact as existing buddies
+          in the same group if the alias given is the same.
 
 	General:
 	* Group and Chat buddy list entries can now be given custom buddy
@@ -22,6 +27,8 @@
 	* Added "Invite..." menu to chats.
 	* Added "View All Logs" menu in the buddylist to display a list of all IM
 	  logs.
+	* Added '/msgcolor' command to change colors of different classes of
+	  messages in a conversation. See '/help msgcolor' for details.
 
 version 2.4.2 (05/17/2008):
 	libpurple:
--- a/configure.ac	Sat Jun 07 01:06:41 2008 +0000
+++ b/configure.ac	Mon Jun 09 06:35:52 2008 +0000
@@ -1207,8 +1207,8 @@
 dnl # Check for D-Bus libraries
 dnl #######################################################################
 
-AC_ARG_ENABLE(dbus, [AC_HELP_STRING([--enable-dbus], [enable D-Bus support])], , enable_dbus=yes)
-AC_ARG_ENABLE(nm, [AC_HELP_STRING([--enable-nm], [enable NetworkManager support (requires D-Bus)])], enable_nm=$enableval, enable_nm=yes)
+AC_ARG_ENABLE(dbus, [AC_HELP_STRING([--disable-dbus], [disable D-Bus support])], , enable_dbus=yes)
+AC_ARG_ENABLE(nm, [AC_HELP_STRING([--disable-nm], [disable NetworkManager support (requires D-Bus)])], enable_nm=$enableval, enable_nm=yes)
 
 if test "x$enable_dbus" = "xyes" ; then
 	AC_CHECK_PROG(enable_dbus, dbus-binding-tool, yes, no)
@@ -1561,6 +1561,18 @@
 dnl # Thanks go to Evolution for the checks.
 dnl #######################################################################
 
+AC_ARG_WITH(ssl-certificates, [AC_HELP_STRING([--with-ssl-certificates=<dir>], [directory containing system-wide SSL CA certificates])])
+
+SSL_CERTIFICATES_DIR=""
+if ! test -z "$with_ssl_certificates" ; then
+	if ! test -d "$with_ssl_certificates" ; then
+		AC_MSG_ERROR([$with_ssl_certificates does not exist, if this is the correct location please make sure that it exists.])
+	fi
+	SSL_CERTIFICATES_DIR="$with_ssl_certificates"
+fi
+AC_SUBST(SSL_CERTIFICATES_DIR)
+AM_CONDITIONAL(INSTALL_SSL_CERTIFICATES, test "x$SSL_CERTIFICATES_DIR" = "x")
+
 dnl These two are inverses of each other <-- stolen from evolution!
 
 AC_ARG_ENABLE(gnutls,
@@ -2409,6 +2421,9 @@
 fi
 echo Build with NetworkManager..... : $enable_nm
 echo SSL Library/Libraries......... : $msg_ssl
+if test "x$SSL_CERTIFICATES_DIR" != "x" ; then
+	eval eval echo SSL CA certificates directory. : $SSL_CERTIFICATES_DIR
+fi
 echo Build with Cyrus SASL support. : $enable_cyrus_sasl
 echo Use kerberos 4 with zephyr.... : $kerberos
 echo Use external libzephyr........ : $zephyr
--- a/finch/gntconv.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/finch/gntconv.c	Mon Jun 09 06:35:52 2008 +0000
@@ -1241,6 +1241,47 @@
 }
 
 static PurpleCmdRet
+cmd_message_color(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data)
+{
+	int *msgclass  = NULL;
+	int fg, bg;
+
+	if (strcmp(args[0], "receive") == 0)
+		msgclass = &color_message_receive;
+	else if (strcmp(args[0], "send") == 0)
+		msgclass = &color_message_send;
+	else if (strcmp(args[0], "highlight") == 0)
+		msgclass = &color_message_highlight;
+	else if (strcmp(args[0], "action") == 0)
+		msgclass = &color_message_action;
+	else if (strcmp(args[0], "timestamp") == 0)
+		msgclass = &color_timestamp;
+	else {
+		if (error)
+			*error = g_strdup_printf(_("%s is not a valid message class. See '/help msgcolor' for valid message classes."), args[0]);
+		return PURPLE_CMD_STATUS_FAILED;
+	}
+
+	fg = gnt_colors_get_color(args[1]);
+	if (fg == -EINVAL) {
+		if (error)
+			*error = g_strdup_printf(_("%s is not a valid color. See '/help msgcolor' for valid colors."), args[1]);
+		return PURPLE_CMD_STATUS_FAILED;
+	}
+
+	bg = gnt_colors_get_color(args[2]);
+	if (bg == -EINVAL) {
+		if (error)
+			*error = g_strdup_printf(_("%s is not a valid color. See '/help msgcolor' for valid colors."), args[2]);
+		return PURPLE_CMD_STATUS_FAILED;
+	}
+
+	init_pair(*msgclass, fg, bg);
+
+	return PURPLE_CMD_STATUS_OK;
+}
+
+static PurpleCmdRet
 users_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data)
 {
 	FinchConv *fc = FINCH_GET_DATA(conv);
@@ -1324,6 +1365,16 @@
 	                  PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL,
 	                  cmd_show_window, _("statuses: Show the savedstatuses window."), finch_savedstatus_show_all);
 
+	/* Allow customizing the message colors using a command during run-time */
+	purple_cmd_register("msgcolor", "www", PURPLE_CMD_P_DEFAULT,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL,
+			cmd_message_color, _("msgcolor &lt;class&gt; &lt;foreground&gt; &lt;background&gt;: "
+				                 "Set the color for different classes of messages in the conversation window.<br>"
+				                 "    &lt;class&gt;: receive, send, highlight, action, timestamp<br>"
+				                 "    &lt;foreground/background&gt;: black, red, green, blue, white, gray, darkgray, magenta, cyan, default<br><br>"
+								 "EXAMPLE:<br>    msgcolor send cyan default"),
+			NULL);
+
 	purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", finch_conv_get_handle(),
 					PURPLE_CALLBACK(update_buddy_typing), NULL);
 	purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", finch_conv_get_handle(),
--- a/finch/gntft.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/finch/gntft.c	Mon Jun 09 06:35:52 2008 +0000
@@ -117,7 +117,9 @@
 			total_pct = 100 * total_bytes_xferred / total_file_size;
 		}
 
-		title = g_strdup_printf(_("File Transfers - %d%% of %d files"),
+		title = g_strdup_printf(ngettext("File Transfers - %d%% of %d file",
+						 "File Transfers - %d%% of %d files",
+						 num_active_xfers),
 				total_pct, num_active_xfers);
 		gnt_screen_rename_widget((xfer_dialog->window), title);
 		g_free(title);
--- a/finch/libgnt/gntcolors.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/finch/libgnt/gntcolors.c	Mon Jun 09 06:35:52 2008 +0000
@@ -29,6 +29,7 @@
 
 #include <glib.h>
 
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -168,7 +169,7 @@
 		color = -1;
 	else {
 		g_warning("Invalid color name: %s\n", key);
-		color = -1;
+		color = -EINVAL;
 	}
 	return color;
 }
--- a/finch/libgnt/gntcolors.h	Sat Jun 07 01:06:41 2008 +0000
+++ b/finch/libgnt/gntcolors.h	Mon Jun 09 06:35:52 2008 +0000
@@ -91,7 +91,7 @@
  *
  * @param kfile The string value
  *
- * @return A color
+ * @return A color. For an unknown color name, returns -EINVAL.
  *
  * @since 2.4.0
  */
--- a/libpurple/Makefile.am	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/Makefile.am	Mon Jun 09 06:35:52 2008 +0000
@@ -261,3 +261,9 @@
 	$(DBUS_CFLAGS) \
 	$(LIBXML_CFLAGS) \
 	$(NETWORKMANAGER_CFLAGS)
+
+# INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
+# We want to use SSL_CERTIFICATES_DIR when it's not empty.
+if ! INSTALL_SSL_CERTIFICATES
+AM_CPPFLAGS += -DSSL_CERTIFICATES_DIR=\"$(SSL_CERTIFICATES_DIR)\"
+endif
--- a/libpurple/certificate.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/certificate.c	Mon Jun 09 06:35:52 2008 +0000
@@ -745,8 +745,12 @@
 		x509_ca_paths = g_list_append(NULL, g_build_filename(DATADIR,
 						   "ca-certs", NULL));
 #else
+# ifdef SSL_CERTIFICATES_DIR
+		x509_ca_paths = g_list_append(NULL, SSL_CERTIFICATES_DIR);
+# else
 		x509_ca_paths = g_list_append(NULL, g_build_filename(DATADIR,
 						   "purple", "ca-certs", NULL));
+# endif
 #endif
 	}
 
@@ -787,8 +791,7 @@
 
 	for (cur = lst; cur; cur = cur->next) {
 		x509_ca_element *el = cur->data;
-		/* TODO: Unsafe? */
-		if ( !strcmp(dn, el->dn) ) {
+		if (el->dn && !strcmp(dn, el->dn)) {
 			return el;
 		}
 	}
--- a/libpurple/plugins/perl/perl-handlers.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/plugins/perl/perl-handlers.c	Mon Jun 09 06:35:52 2008 +0000
@@ -383,6 +383,9 @@
 				case PURPLE_TYPE_BOXED:
 					*((void **)copy_args[i]) = (void *)SvIV(sv_args[i]);
 					break;
+				case PURPLE_TYPE_SUBTYPE:
+					*((void **)copy_args[i]) = purple_perl_ref_object(sv_args[i]);
+					break;
 
 				default:
 					break;
--- a/libpurple/protocols/irc/msgs.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/irc/msgs.c	Mon Jun 09 06:35:52 2008 +0000
@@ -215,7 +215,9 @@
 			/* This is an extended syntax, not in RFC 1459 */
 			int t1 = atoi(args[4]);
 			time_t t2 = time(NULL);
-			msg = g_strdup_printf(_("Ban on %s by %s, set %ld seconds ago"),
+			msg = g_strdup_printf(ngettext("Ban on %s by %s, set %ld second ago",
+						       "Ban on %s by %s, set %ld seconds ago",
+						       t2 - t1),
 			                      args[2], args[3], t2 - t1);
 		} else {
 			msg = g_strdup_printf(_("Ban on %s"), args[2]);
--- a/libpurple/protocols/msn/soap2.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/msn/soap2.c	Mon Jun 09 06:35:52 2008 +0000
@@ -82,6 +82,7 @@
 
 static void msn_soap_request_destroy(MsnSoapRequest *req);
 static void msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect);
+static void msn_soap_process(MsnSoapConnection *conn);
 
 static gboolean
 msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data)
@@ -264,45 +265,53 @@
 msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
 {
 	MsnSoapConnection *conn = data;
-	int count = 0, cnt;
-	char buf[8192];
-	char *linebreak;
-	char *cursor;
-	gboolean handled = FALSE;
+	int count = 0, cnt, perrno;
+	/* This buffer needs to be larger than any packets received from
+		login.live.com or Adium will fail to receive the packet
+		(something weird with the login.live.com server). With NSS it works
+		fine, so I believe it's some bug with OS X */ 
+	char buf[16 * 1024];
 
 	if (conn->message == NULL) {
 		conn->message = msn_soap_message_new(NULL, NULL);
 	}
 
+	if (conn->buf == NULL) {
+		conn->buf = g_string_new_len(buf, 0);
+	}
+	
 	while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
 		purple_debug_info("soap", "read %d bytes\n", cnt);
 		count += cnt;
-		if (conn->buf == NULL) {
-			conn->buf = g_string_new_len(buf, cnt);
-		} else {
-			g_string_append_len(conn->buf, buf, cnt);
-		}
+		g_string_append_len(conn->buf, buf, cnt);
 	}
 
-	if (cnt < 0) {
-		if (errno != EAGAIN) {
-			purple_debug_info("soap", "read: %s\n", g_strerror(errno));
+	/* && count is necessary for Adium, on OS X the last read always
+	   return an error, so we want to proceed anyway. See #5212 for
+	   discussion on this and the above buffer size issues */
+	if(cnt < 0 && errno == EAGAIN && count == 0)
+		return;
+
+	// msn_soap_process could alter errno
+	perrno = errno;
+	msn_soap_process(conn);
+	
+	if (cnt < 0 && perrno != EAGAIN) {
+		purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
+		// It's possible msn_soap_process closed the ssl connection
+		if (conn->ssl) {
 			purple_ssl_close(conn->ssl);
 			conn->ssl = NULL;
 			msn_soap_connection_handle_next(conn);
-			return;
-		} else if (count == 0) {
-			return;
 		}
 	}
+}
 
-	if (cnt == 0 && count == 0) {
-		purple_debug_info("soap", "msn_soap_read_cb() called, but no data available?\n");
-		purple_ssl_close(conn->ssl);
-		conn->ssl = NULL;
-		msn_soap_connection_handle_next(conn);
-		return;
-	}
+static void
+msn_soap_process(MsnSoapConnection *conn) {
+	gboolean handled = FALSE;
+	char *cursor;
+	char *linebreak;
 
 	purple_debug_info("soap", "current %s\n", conn->buf->str);
 
--- a/libpurple/protocols/myspace/myspace.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Mon Jun 09 06:35:52 2008 +0000
@@ -1328,7 +1328,10 @@
 	delta = time(NULL) - session->last_comm;
 	/* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */
 	if (delta >= MSIM_KEEPALIVE_INTERVAL) {
-		errmsg = g_strdup_printf(_("Connection to server lost (no data received within %d seconds)"), (int)delta);
+	        errmsg = g_strdup_printf(ngettext("Connection to server lost (no data received within %d second)",
+						  "Connection to server lost (no data received within %d seconds)",
+						  (int)delta),
+					 (int)delta);
 
 		purple_debug_info("msim", "msim_check_alive: %s > interval of %d, presumed dead\n",
 				errmsg, MSIM_KEEPALIVE_INTERVAL);
@@ -2404,7 +2407,7 @@
 		const char *username;
 
 		/* If the account does not exist, we can't look up the user. */
-		if (!account)
+		if (!account || !account->gc)
 			return str;
 
 		id = atol(str);
@@ -2946,7 +2949,10 @@
 
 	switch (GPOINTER_TO_UINT(user_data)) {
 		case MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS:
-			msg = g_strdup_printf(_("%d buddies were added or updated from the server (including buddies already on the server-side list)"), buddy_count);
+		        msg = g_strdup_printf(ngettext("%d buddy was added or updated from the server (including buddies already on the server-side list)",
+						       "%d buddies were added or updated from the server (including buddies already on the server-side list)",
+						       buddy_count),
+					      buddy_count);
 			purple_notify_info(session->account, _("Add contacts from server"), msg, NULL);
 			g_free(msg);
 			break;
--- a/libpurple/protocols/oscar/family_admin.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_admin.c	Mon Jun 09 06:35:52 2008 +0000
@@ -47,8 +47,8 @@
 	byte_stream_put16(&bs, info);
 	byte_stream_put16(&bs, 0x0000);
 
-	snacid = aim_cachesnac(od, 0x0007, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0007, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -127,8 +127,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -154,8 +154,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -177,8 +177,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -194,11 +194,11 @@
 void
 aim_admin_reqconfirm(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n(od, conn, 0x0007, 0x0006);
+	aim_genericreq_n(od, conn, SNAC_FAMILY_ADMIN, 0x0006);
 }
 
 /**
- * Subtype 0x0007 - Account confirmation request acknowledgement.
+ * Subtype SNAC_FAMILY_ADMIN - Account confirmation request acknowledgement.
  */
 static int
 accountconfirm(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
@@ -227,7 +227,7 @@
 	if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) {
 		infochange(od, conn, mod, frame, snac, bs);
 		return 1;
-	} else if (snac->subtype == 0x0007)
+	} else if (snac->subtype == SNAC_FAMILY_ADMIN)
 		return accountconfirm(od, conn, mod, frame, snac, bs);
 
 	return 0;
@@ -235,7 +235,7 @@
 
 int admin_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0007;
+	mod->family = SNAC_FAMILY_ADMIN;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_advert.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_advert.c	Mon Jun 09 06:35:52 2008 +0000
@@ -28,7 +28,7 @@
 void
 aim_ads_requestads(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n(od, conn, 0x0005, 0x0002);
+	aim_genericreq_n(od, conn, SNAC_FAMILY_ADVERT, 0x0002);
 }
 
 static int snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs)
@@ -39,7 +39,7 @@
 int adverts_modfirst(OscarData *od, aim_module_t *mod)
 {
 
-	mod->family = 0x0005;
+	mod->family = SNAC_FAMILY_ADVERT;
 	mod->version = 0x0001;
 	mod->toolid = 0x0001;
 	mod->toolversion = 0x0001;
--- a/libpurple/protocols/oscar/family_alert.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_alert.c	Mon Jun 09 06:35:52 2008 +0000
@@ -72,8 +72,8 @@
 	byte_stream_put16(&bs, 0xb0ee);
 	byte_stream_put16(&bs, 0x0631);
 
-	snacid = aim_cachesnac(od, 0x0018, 0x0006, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0018, 0x0006, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0006, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -188,8 +188,8 @@
 	byte_stream_put32(&bs, 0x04000000);
 	byte_stream_put32(&bs, 0x00000000);
 
-	snacid = aim_cachesnac(od, 0x0018, 0x0016, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0018, 0x0006, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0016, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -225,7 +225,7 @@
 int
 email_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0018;
+	mod->family = SNAC_FAMILY_ALERT;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_auth.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Mon Jun 09 06:35:52 2008 +0000
@@ -200,9 +200,13 @@
  *        usually happens for AOL accounts.  We are told that we
  *        should truncate it if the 0x0017/0x0007 SNAC contains
  *        a TLV of type 0x0026 with data 0x0000.
+ * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
+ *        server will prompt the user when multiple logins occur. If
+ *        FALSE, existing connections (on other clients) will be
+ *        disconnected automatically as we connect.
  */
 int
-aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key)
+aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
 {
 	FlapFrame *frame;
 	GSList *tlvlist = NULL;
@@ -221,8 +225,8 @@
 
 	frame = flap_frame_new(od, 0x02, 1152);
 
-	snacid = aim_cachesnac(od, 0x0017, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&frame->data, 0x0017, 0x0002, 0x0000, snacid);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
+	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, 0x0000, snacid);
 
 	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
@@ -256,7 +260,7 @@
 	 * If set, old-fashioned buddy lists will not work. You will need
 	 * to use SSI.
 	 */
-	aim_tlvlist_add_8(&tlvlist, 0x004a, 0x01);
+	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x02));
 
 	aim_tlvlist_write(&frame->data, &tlvlist);
 
@@ -403,7 +407,7 @@
 
 	od->authinfo = info;
 
-	if ((userfunc = aim_callhandler(od, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003)))
+	if ((userfunc = aim_callhandler(od, snac ? snac->family : SNAC_FAMILY_AUTH, snac ? snac->subtype : 0x0003)))
 		ret = userfunc(od, conn, frame, info);
 
 	aim_tlvlist_free(tlvlist);
@@ -449,7 +453,7 @@
 	FlapFrame frame;
 	aim_rxcallback_t userfunc;
 
-	if ((userfunc = aim_callhandler(od, 0x0017, 0x0007)))
+	if ((userfunc = aim_callhandler(od, SNAC_FAMILY_AUTH, 0x0007)))
 		userfunc(od, conn, &frame, "");
 
 	return 0;
@@ -483,8 +487,8 @@
 
 	frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8);
 
-	snacid = aim_cachesnac(od, 0x0017, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&frame->data, 0x0017, 0x0006, 0x0000, snacid);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0006, 0x0000, NULL, 0);
+	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0006, 0x0000, snacid);
 
 	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
@@ -628,7 +632,7 @@
 int
 auth_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0017;
+	mod->family = SNAC_FAMILY_AUTH;
 	mod->version = 0x0000;
 	mod->flags = 0;
 	strncpy(mod->name, "auth", sizeof(mod->name));
--- a/libpurple/protocols/oscar/family_bart.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_bart.c	Mon Jun 09 06:35:52 2008 +0000
@@ -43,7 +43,7 @@
 	ByteStream bs;
 	aim_snacid_t snacid;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0010)) || !icon || !iconlen)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !icon || !iconlen)
 		return -EINVAL;
 
 	byte_stream_new(&bs, 2 + 2 + iconlen);
@@ -55,8 +55,8 @@
 	byte_stream_put16(&bs, iconlen);
 	byte_stream_putraw(&bs, icon, iconlen);
 
-	snacid = aim_cachesnac(od, 0x0010, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0010, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -102,7 +102,7 @@
 	ByteStream bs;
 	aim_snacid_t snacid;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0010)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen)
 		return -EINVAL;
 
 	byte_stream_new(&bs, 1+strlen(sn) + 4 + 1+iconcsumlen);
@@ -120,8 +120,8 @@
 	byte_stream_put8(&bs, iconcsumlen);
 	byte_stream_putraw(&bs, iconcsum, iconcsumlen);
 
-	snacid = aim_cachesnac(od, 0x0010, 0x0004, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0010, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0004, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -174,7 +174,7 @@
 int
 bart_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0010;
+	mod->family = SNAC_FAMILY_BART;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_bos.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_bos.c	Mon Jun 09 06:35:52 2008 +0000
@@ -32,7 +32,7 @@
 void
 aim_bos_reqrights(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n_snacid(od, conn, 0x0009, 0x0002);
+	aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_BOS, 0x0002);
 }
 
 /* Subtype 0x0003 - BOS Rights. */
@@ -81,7 +81,7 @@
 void
 aim_bos_setgroupperm(OscarData *od, FlapConnection *conn, guint32 mask)
 {
-	aim_genericreq_l(od, conn, 0x0009, 0x0004, &mask);
+	aim_genericreq_l(od, conn, SNAC_FAMILY_BOS, 0x0004, &mask);
 }
 
 /*
@@ -153,8 +153,8 @@
 	}
 	g_free(localcpy);
 
-	snacid = aim_cachesnac(od, 0x0009, subtype, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0009, subtype, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BOS, subtype, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BOS, subtype, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -173,7 +173,7 @@
 int
 bos_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0009;
+	mod->family = SNAC_FAMILY_BOS;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_buddy.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_buddy.c	Mon Jun 09 06:35:52 2008 +0000
@@ -108,8 +108,8 @@
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	snacid = aim_cachesnac(od, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1);
-	flap_connection_send_snac(od, conn, 0x0003, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, sn, strlen(sn)+1);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -159,8 +159,8 @@
 		tmpptr = strtok(NULL, "&");
 	}
 
-	snacid = aim_cachesnac(od, 0x0003, 0x0004, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0003, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -190,8 +190,8 @@
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	snacid = aim_cachesnac(od, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1);
-	flap_connection_send_snac(od, conn, 0x0003, 0x0005, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0005, 0x0000, sn, strlen(sn)+1);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0005, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -243,7 +243,7 @@
 int
 buddylist_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0003;
+	mod->family = SNAC_FAMILY_BUDDY;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_chat.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_chat.c	Mon Jun 09 06:35:52 2008 +0000
@@ -364,7 +364,7 @@
 
 	byte_stream_new(&bs, 1142);
 
-	snacid = aim_cachesnac(od, 0x000e, 0x0005, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_CHAT, 0x0005, 0x0000, NULL, 0);
 
 	/*
 	 * Cookie
@@ -432,7 +432,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x000e, 0x0005, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_CHAT, 0x0005, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -594,7 +594,7 @@
 int
 chat_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x000e;
+	mod->family = SNAC_FAMILY_CHAT;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_chatnav.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_chatnav.c	Mon Jun 09 06:35:52 2008 +0000
@@ -42,7 +42,7 @@
 		return 0;
 	}
 
-	if (snac2->family != 0x000d) {
+	if (snac2->family != SNAC_FAMILY_CHATNAV) {
 		purple_debug_warning("oscar", "chatnav error: received response that maps to corrupt request (fam=%04x)\n", snac2->family);
 		return 0;
 	}
@@ -80,7 +80,7 @@
  */
 void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n_snacid(od, conn, 0x000d, 0x0002);
+	aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_CHATNAV, 0x0002);
 }
 
 /*
@@ -97,7 +97,7 @@
 
 	byte_stream_new(&bs, 1142);
 
-	snacid = aim_cachesnac(od, 0x000d, 0x0008, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_CHATNAV, 0x0008, 0x0000, NULL, 0);
 
 	/* exchange */
 	byte_stream_put16(&bs, exchange);
@@ -137,7 +137,7 @@
 
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x000d, 0x0008, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_CHATNAV, 0x0008, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -460,7 +460,7 @@
 		return 0;
 	}
 
-	if (snac2->family != 0x000d) {
+	if (snac2->family != SNAC_FAMILY_CHATNAV) {
 		purple_debug_misc("oscar", "faim: chatnav_parse_info: received response that maps to corrupt request! (fam=%04x)\n", snac2->family);
 		return 0;
 	}
@@ -506,7 +506,7 @@
 int
 chatnav_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x000d;
+	mod->family = SNAC_FAMILY_CHATNAV;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_icbm.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Mon Jun 09 06:35:52 2008 +0000
@@ -164,7 +164,7 @@
 	ByteStream bs;
 	aim_snacid_t snacid;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (!params)
@@ -182,8 +182,8 @@
 	byte_stream_put16(&bs, params->maxrecverwarn);
 	byte_stream_put32(&bs, params->minmsginterval);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0004, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -198,10 +198,10 @@
 {
 	FlapConnection *conn;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
-	aim_genericreq_n_snacid(od, conn, 0x0004, 0x0004);
+	aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_ICBM, 0x0004);
 
 	return 0;
 }
@@ -237,7 +237,7 @@
  * Possible flags:
  *   AIM_IMFLAGS_AWAY  -- Marks the message as an autoresponse
  *   AIM_IMFLAGS_ACK   -- Requests that the server send an ack
- *                        when the message is received (of type 0x0004/0x000c)
+ *                        when the message is received (of type SNAC_FAMILY_ICBM/0x000c)
  *   AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are
  *                        online (probably ICQ only).
  *
@@ -280,7 +280,7 @@
 	int msgtlvlen;
 	static const guint8 deffeatures[] = { 0x01, 0x01, 0x01, 0x02 };
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (!args)
@@ -410,9 +410,9 @@
 	}
 
 	/* XXX - should be optional */
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1);
-
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &data);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1);
+
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &data);
 	byte_stream_destroy(&data);
 
 	/* clean out SNACs over 60sec old */
@@ -462,7 +462,7 @@
 	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (!sn || !msg || !roomname)
@@ -472,7 +472,7 @@
 
 	byte_stream_new(&bs, 1142+strlen(sn)+strlen(roomname)+strlen(msg));
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, sn, strlen(sn)+1);
 
 	/* XXX should be uncached by an unwritten 'invite accept' handler */
 	priv = g_malloc(sizeof(struct aim_invite_priv));
@@ -519,7 +519,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -539,7 +539,7 @@
 	aim_snacid_t snacid;
 	guchar cookie[8];
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))
@@ -549,7 +549,7 @@
 
 	byte_stream_new(&bs, 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);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -589,7 +589,7 @@
 	byte_stream_put16(&bs, 0x0003);
 	byte_stream_put16(&bs, 0x0000);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -620,7 +620,7 @@
 	const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* OSCAR_CAPABILITY_ICQRTF capability in string form */
 	int servdatalen;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (!args || !args->destsn || !args->rtfmsg)
@@ -632,7 +632,7 @@
 
 	byte_stream_new(&bs, 128+servdatalen);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, args->destsn);
@@ -682,7 +682,7 @@
 	byte_stream_putle32(&bs, strlen(rtfcap)+1);
 	byte_stream_putraw(&bs, (const guint8 *)rtfcap, strlen(rtfcap)+1);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -704,13 +704,13 @@
 	ByteStream hdrbs;
 
 	od = peer_conn->od;
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 118+strlen(peer_conn->sn));
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->sn);
@@ -735,7 +735,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -753,13 +753,13 @@
 	aim_snacid_t snacid;
 
 	od = peer_conn->od;
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 11+strlen(peer_conn->sn) + 4+2+8+16);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->sn);
@@ -770,7 +770,7 @@
 	byte_stream_putraw(&bs, peer_conn->cookie, 8);
 	byte_stream_putcaps(&bs, peer_conn->type);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -791,13 +791,13 @@
 	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 246+strlen(sn));
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -825,7 +825,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -844,13 +844,13 @@
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 246+strlen(sn));
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -888,7 +888,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -906,13 +906,13 @@
 	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 1014);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -971,7 +971,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -990,13 +990,13 @@
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
-	conn = flap_connection_findbygroup(od, 0x0004);
+	conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
 	if (conn == NULL)
 		return;
 
 	byte_stream_new(&bs, 1014);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -1064,7 +1064,7 @@
 	aim_tlvlist_free(inner_tlvlist);
 	aim_tlvlist_free(outer_tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -1085,14 +1085,14 @@
 	aim_snacid_t snacid;
 	guchar cookie[8];
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)) || !sn)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)) || !sn)
 		return -EINVAL;
 
 	aim_icbm_makecookie(cookie);
 
 	byte_stream_new(&bs, 8+2+1+strlen(sn) + 4+0x5e + 4);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	/* ICBM header */
 	aim_im_puticbm(&bs, cookie, 0x0002, sn);
@@ -1160,7 +1160,7 @@
 	byte_stream_put16(&bs, 0x0003);
 	byte_stream_put16(&bs, 0x0000);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1196,7 +1196,7 @@
 
 	byte_stream_new(&bs, 8+3+strlen(sn)+12+strlen(message)+1+4);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
 
 	aim_icbm_makecookie(cookie);
 
@@ -1229,7 +1229,7 @@
 	byte_stream_put16(&bs, 0x0006);
 	byte_stream_put16(&bs, 0x0000);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -2268,13 +2268,13 @@
 
 	byte_stream_new(&bs, strlen(sn)+3);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0008, 0x0000, sn, strlen(sn)+1);
 
 	byte_stream_put16(&bs, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000);
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0008, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0008, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -2321,12 +2321,12 @@
 	aim_snacid_t snacid;
 	GSList *tlvlist = NULL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	byte_stream_new(&bs, 8+2+1+strlen(sn)+6);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x000b, 0x0000, NULL, 0);
 
 	byte_stream_putraw(&bs, cookie, 8);
 
@@ -2338,7 +2338,7 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x000b, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x000b, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -2660,7 +2660,7 @@
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
 		return -EINVAL;
 
-	aim_genericreq_n(od, conn, 0x0004, 0x0010);
+	aim_genericreq_n(od, conn, SNAC_FAMILY_ICBM, 0x0010);
 
 	return 0;
 }
@@ -2686,7 +2686,7 @@
 
 	byte_stream_new(&bs, 11+strlen(sn)+2);
 
-	snacid = aim_cachesnac(od, 0x0004, 0x0014, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0014, 0x0000, NULL, 0);
 
 	/*
 	 * 8 days of light
@@ -2713,7 +2713,7 @@
 	 */
 	byte_stream_put16(&bs, type2);
 
-	flap_connection_send_snac(od, conn, 0x0004, 0x0014, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -2773,7 +2773,7 @@
 int
 msg_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0004;
+	mod->family = SNAC_FAMILY_ICBM;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_icq.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_icq.c	Mon Jun 09 06:35:52 2008 +0000
@@ -33,14 +33,14 @@
 	aim_snacid_t snacid;
 	int bslen;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 4 + 2 + 2;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -51,7 +51,7 @@
 	byte_stream_putle16(&bs, 0x003c); /* I command thee. */
 	byte_stream_putle16(&bs, snacid); /* eh. */
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -65,14 +65,14 @@
 	aim_snacid_t snacid;
 	int bslen;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 4 + 2 + 2;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -83,7 +83,7 @@
 	byte_stream_putle16(&bs, 0x003e); /* I command thee. */
 	byte_stream_putle16(&bs, snacid); /* eh. */
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -99,14 +99,14 @@
 	aim_snacid_t snacid;
 	int bslen;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2+4+2+2+2+2+2+1+1+1+1+1+1;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -126,7 +126,7 @@
 	byte_stream_putle8(&bs, 0x00);
 	byte_stream_putle8(&bs, !auth_required);
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -151,7 +151,7 @@
 	if (!passwd)
 		return -EINVAL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	passwdlen = strlen(passwd);
@@ -161,7 +161,7 @@
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -176,7 +176,7 @@
 	byte_stream_putstr(&bs, passwd);
 	byte_stream_putle8(&bs, '\0');
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -194,14 +194,14 @@
 	if (!uin || uin[0] < '0' || uin[0] > '9')
 		return -EINVAL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 4 + 2 + 2 + 2 + 4;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -214,7 +214,7 @@
 	byte_stream_putle16(&bs, 0x04b2); /* shrug. */
 	byte_stream_putle32(&bs, atoi(uin));
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -239,14 +239,14 @@
 	if (!uin || uin[0] < '0' || uin[0] > '9')
 		return -EINVAL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 4 + 2 + 2 + 2 + 4;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -259,7 +259,7 @@
 	byte_stream_putle16(&bs, 0x04ba); /* shrug. */
 	byte_stream_putle32(&bs, atoi(uin));
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -283,14 +283,14 @@
 	if (!uin || uin[0] < '0' || uin[0] > '9')
 		return -EINVAL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 4 + 2 + 2 + 2 + 4;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -303,7 +303,7 @@
 	byte_stream_putle16(&bs, 0x051f); /* shrug. */
 	byte_stream_putle32(&bs, atoi(uin));
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -321,14 +321,14 @@
 	if (!xml || !strlen(xml))
 		return -EINVAL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	bslen = 2 + 10 + 2 + strlen(xml) + 1;
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -342,7 +342,7 @@
 	byte_stream_putle16(&bs, strlen(xml) + 1);
 	byte_stream_putraw(&bs, (guint8 *)xml, strlen(xml) + 1);
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -380,7 +380,7 @@
 	struct tm *tm;
 	gchar *stripped;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 		return -EINVAL;
 
 	if (!name || !msg || !alias)
@@ -411,7 +411,7 @@
 
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	/* For simplicity, don't bother using a tlvlist */
 	byte_stream_put16(&bs, 0x0001);
@@ -436,7 +436,7 @@
 	byte_stream_putstr(&bs, xml);
 	byte_stream_put8(&bs, 0x00);
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -460,7 +460,7 @@
 
 	purple_debug_misc("oscar", "aim_icq_getstatusnote: requesting status note for %s.\n", uin);
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
 	{
 		purple_debug_misc("oscar", "aim_icq_getstatusnote: no connection.\n");
 		return -EINVAL;
@@ -469,7 +469,7 @@
 	bslen = 2 + 4 + 2 + 2 + 2 + 2 + 58 + strlen(uin);
 	byte_stream_new(&bs, 4 + bslen);
 
-	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
 
 	byte_stream_put16(&bs, 0x0001);
 	byte_stream_put16(&bs, bslen);
@@ -497,7 +497,7 @@
 	byte_stream_put16(&bs, strlen(uin));
 	byte_stream_putstr(&bs, uin);
 
-	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -541,7 +541,7 @@
 }
 
 /**
- * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet.
+ * Subtype 0x0003 - Response to SNAC_FAMILY_ICQ/0x002, contains an ICQesque packet.
  */
 static int
 icqresponse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
@@ -940,7 +940,7 @@
 int
 icq_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0015;
+	mod->family = SNAC_FAMILY_ICQ;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x047c;
--- a/libpurple/protocols/oscar/family_invite.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_invite.c	Mon Jun 09 06:35:52 2008 +0000
@@ -41,7 +41,7 @@
 int invite_modfirst(OscarData *od, aim_module_t *mod)
 {
 
-	mod->family = 0x0006;
+	mod->family = SNAC_FAMILY_INVITE;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_locate.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Mon Jun 09 06:35:52 2008 +0000
@@ -171,7 +171,7 @@
 	 {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
-	{OSCAR_CAPABILITY_GENERICUNKNOWN,
+	{OSCAR_CAPABILITY_ICHAT_SCREENSHARE,
 	 {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
@@ -943,7 +943,7 @@
 		return 0;
 	}
 
-	if ((snac2->family != 0x0002) && (snac2->type != 0x0015)) {
+	if ((snac2->family != SNAC_FAMILY_LOCATE) && (snac2->type != 0x0015)) {
 		purple_debug_misc("oscar", "faim: locate.c, error(): received response from invalid request! %d\n", snac2->family);
 		return 0;
 	}
@@ -1094,12 +1094,12 @@
 
 	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
 
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x0004, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1124,12 +1124,12 @@
 
 	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
 
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x0004, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1157,13 +1157,13 @@
 
 	byte_stream_new(&bs, 2+1+strlen(sn));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x0005, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0005, 0x0000, NULL, 0);
 
 	byte_stream_put16(&bs, infotype);
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x0005, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0005, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1274,12 +1274,12 @@
 
 	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x0009, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, NULL, 0);
 
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x0009, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1302,12 +1302,12 @@
 
 	byte_stream_new(&bs, 1+strlen(sn));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x000b, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x000b, 0x0000, NULL, 0);
 
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x000b, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x000b, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1347,12 +1347,12 @@
 
 	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
 
-	snacid = aim_cachesnac(od, 0x0002, 0x000f, 0x0000, NULL, 0);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, NULL, 0);
 
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	flap_connection_send_snac(od, conn, 0x0002, 0x000f, 0x0000, snacid, &bs);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 	return 0;
@@ -1385,8 +1385,8 @@
 	byte_stream_put8(&bs, strlen(sn));
 	byte_stream_putstr(&bs, sn);
 
-	snacid = aim_cachesnac(od, 0x0002, 0x0015, 0x0000, sn, strlen(sn)+1);
-	flap_connection_send_snac(od, conn, 0x0002, 0x0015, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, sn, strlen(sn)+1);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
--- a/libpurple/protocols/oscar/family_odir.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_odir.c	Mon Jun 09 06:35:52 2008 +0000
@@ -45,7 +45,7 @@
 	aim_snacid_t snacid;
 	GSList *tlvlist = NULL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region || !email)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region || !email)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
@@ -58,8 +58,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x000f, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -94,7 +94,7 @@
 	aim_snacid_t snacid;
 	GSList *tlvlist = NULL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
@@ -126,8 +126,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x000f, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -149,7 +149,7 @@
 	aim_snacid_t snacid;
 	GSList *tlvlist = NULL;
 
-	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
+	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
@@ -163,8 +163,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x000f, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -252,7 +252,7 @@
 int
 odir_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x000f;
+	mod->family = SNAC_FAMILY_ODIR;
 	mod->version = 0x0001;
 	mod->toolid = 0x0010;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_oservice.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_oservice.c	Mon Jun 09 06:35:52 2008 +0000
@@ -54,8 +54,8 @@
 		}
 	}
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -108,7 +108,7 @@
 	if(!conn)
 		return;
 
-	aim_genericreq_s(od, conn, 0x0001, 0x0004, &serviceid);
+	aim_genericreq_s(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, &serviceid);
 }
 
 /*
@@ -146,8 +146,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
-	flap_connection_send_snac(od, conn, 0x0001, 0x0004, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, &csi, sizeof(csi));
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -210,7 +210,7 @@
 void
 aim_srv_reqrates(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n_snacid(od, conn, 0x0001, 0x0006);
+	aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x0006);
 }
 
 /*
@@ -389,8 +389,8 @@
 		byte_stream_put16(&bs, rateclass->classid);
 	}
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x0008, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0008, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0008, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -412,8 +412,8 @@
 		byte_stream_put16(&bs, rateclass->classid);
 	}
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x0009, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0009, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0009, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -503,8 +503,8 @@
 	for (cur = conn->groups; cur != NULL; cur = cur->next)
 		byte_stream_put16(&bs, GPOINTER_TO_UINT(cur->data));
 
-	snacid = aim_cachesnac(od, 0x0001, 0x000c, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x000c, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x000c, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x000c, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -526,7 +526,7 @@
 void
 aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n_snacid(od, conn, 0x0001, 0x000e);
+	aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x000e);
 }
 
 /* Subtype 0x000f - Self User Info */
@@ -589,7 +589,7 @@
 	if(!conn)
 		return;
 
-	aim_genericreq_l(od, conn, 0x0001, 0x0011, &idletime);
+	aim_genericreq_l(od, conn, SNAC_FAMILY_OSERVICE, 0x0011, &idletime);
 }
 
 /*
@@ -698,7 +698,7 @@
 void
 aim_srv_setprivacyflags(OscarData *od, FlapConnection *conn, guint32 flags)
 {
-	aim_genericreq_l(od, conn, 0x0001, 0x0014, &flags);
+	aim_genericreq_l(od, conn, SNAC_FAMILY_OSERVICE, 0x0014, &flags);
 }
 
 /*
@@ -713,7 +713,7 @@
 void
 aim_srv_nop(OscarData *od, FlapConnection *conn)
 {
-	aim_genericreq_n(od, conn, 0x0001, 0x0016);
+	aim_genericreq_n(od, conn, SNAC_FAMILY_OSERVICE, 0x0016);
 }
 
 /*
@@ -753,8 +753,8 @@
 		}
 	}
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0017, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x0017, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0017, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0017, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -861,8 +861,8 @@
 	aim_tlvlist_write(&bs, &tlvlist);
 	aim_tlvlist_free(tlvlist);
 
-	snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x001e, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1012,8 +1012,8 @@
 
 	}
 
-	snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0);
-	flap_connection_send_snac(od, conn, 0x0001, 0x0020, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0020, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0020, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -1100,7 +1100,7 @@
 
 int service_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0001;
+	mod->family = SNAC_FAMILY_OSERVICE;
 	mod->version = 0x0003;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/family_popup.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_popup.c	Mon Jun 09 06:35:52 2008 +0000
@@ -72,7 +72,7 @@
 int
 popups_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x0008;
+	mod->family = SNAC_FAMILY_POPUP;
 	mod->version = 0x0001;
 	mod->toolid = 0x0104;
 	mod->toolversion = 0x0001;
--- a/libpurple/protocols/oscar/family_stats.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_stats.c	Mon Jun 09 06:35:52 2008 +0000
@@ -52,7 +52,7 @@
 int
 stats_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x000b;
+	mod->family = SNAC_FAMILY_STATS;
 	mod->version = 0x0001;
 	mod->toolid = 0x0104;
 	mod->toolversion = 0x0001;
--- a/libpurple/protocols/oscar/family_translate.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_translate.c	Mon Jun 09 06:35:52 2008 +0000
@@ -34,7 +34,7 @@
 int translate_modfirst(OscarData *od, aim_module_t *mod)
 {
 
-	mod->family = 0x000c;
+	mod->family = SNAC_FAMILY_TRANSLATE;
 	mod->version = 0x0001;
 	mod->toolid = 0x0104;
 	mod->toolversion = 0x0001;
--- a/libpurple/protocols/oscar/family_userlookup.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/family_userlookup.c	Mon Jun 09 06:35:52 2008 +0000
@@ -74,8 +74,8 @@
 
 	byte_stream_putstr(&bs, address);
 
-	snacid = aim_cachesnac(od, 0x000a, 0x0002, 0x0000, address, strlen(address)+1);
-	flap_connection_send_snac(od, conn, 0x000a, 0x0002, 0x0000, snacid, &bs);
+	snacid = aim_cachesnac(od, SNAC_FAMILY_USERLOOKUP, 0x0002, 0x0000, address, strlen(address)+1);
+	flap_connection_send_snac(od, conn, SNAC_FAMILY_USERLOOKUP, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 
@@ -145,7 +145,7 @@
 int
 search_modfirst(OscarData *od, aim_module_t *mod)
 {
-	mod->family = 0x000a;
+	mod->family = SNAC_FAMILY_USERLOOKUP;
 	mod->version = 0x0001;
 	mod->toolid = 0x0110;
 	mod->toolversion = 0x0629;
--- a/libpurple/protocols/oscar/oscar.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Jun 09 06:35:52 2008 +0000
@@ -707,6 +707,9 @@
 			case OSCAR_CAPABILITY_CAMERA:
 				tmp = _("Camera");
 				break;
+			case OSCAR_CAPABILITY_ICHAT_SCREENSHARE:
+				tmp = _("Screen Sharing");
+				break;
 			default:
 				tmp = NULL;
 				break;
@@ -868,8 +871,8 @@
 
 	if (b) {
 		if (purple_presence_is_online(presence)) {
-			if (aim_snvalid_icq(b->name) || !message || !(*message)) {
-				/* Append the status name for online ICQ statuses and for all buddies with no message.
+			if (aim_snvalid_icq(b->name) || is_away || !message || !(*message)) {
+				/* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message.
 				 * If the status name and the message are the same, only show one. */
 				const char *status_name = purple_status_get_name(status);
 				if (status_name && message && !strcmp(status_name, message))
@@ -1811,7 +1814,8 @@
 
 	aim_send_login(od, conn, purple_account_get_username(account),
 			purple_connection_get_password(gc), truncate_pass,
-			od->icq ? &icqinfo : &aiminfo, key);
+			od->icq ? &icqinfo : &aiminfo, key,
+			/* allow multple logins? */ purple_account_get_bool(account, "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS));
 
 	purple_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
 	ck[2] = 0x6c;
@@ -6768,6 +6772,10 @@
 		OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
 	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
 
+	option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins",
+											OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS);
+	prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+	
 	if (init)
 		return;
 	init = TRUE;
--- a/libpurple/protocols/oscar/oscar.h	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Jun 09 06:35:52 2008 +0000
@@ -353,7 +353,8 @@
 	OSCAR_CAPABILITY_ICHATAV              = 0x02000000,
 	OSCAR_CAPABILITY_LIVEVIDEO            = 0x04000000,
 	OSCAR_CAPABILITY_CAMERA               = 0x08000000,
-	OSCAR_CAPABILITY_LAST                 = 0x10000000
+	OSCAR_CAPABILITY_ICHAT_SCREENSHARE	  = 0x10000000,
+	OSCAR_CAPABILITY_LAST                 = 0x20000000
 } OscarCapability;
 
 /*
@@ -594,7 +595,7 @@
 
 void aim_clientready(OscarData *od, FlapConnection *conn);
 int aim_request_login(OscarData *od, FlapConnection *conn, const char *sn);
-int aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key);
+int aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins);
 /* 0x000b */ int aim_auth_securid_send(OscarData *od, const char *securid);
 
 void aim_cleansnacs(OscarData *, int maxage);
--- a/libpurple/protocols/oscar/oscarcommon.h	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/oscar/oscarcommon.h	Mon Jun 09 06:35:52 2008 +0000
@@ -41,6 +41,7 @@
 #define OSCAR_DEFAULT_HIDE_IP TRUE
 #define OSCAR_DEFAULT_WEB_AWARE FALSE
 #define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE
+#define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE
 
 #ifdef _WIN32
 const char *oscar_get_locale_charset(void);
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Mon Jun 09 06:35:52 2008 +0000
@@ -137,6 +137,9 @@
 		if (url_data != NULL) {
 			yd = gc->proto_data;
 			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+		} else {
+			g_free(data->who);
+			g_free(data);
 		}
 	} else if (who && send_icon_info) {
 		yahoo_send_picture_info(gc, who);
--- a/pidgin/gtkblist.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/pidgin/gtkblist.c	Mon Jun 09 06:35:52 2008 +0000
@@ -3259,7 +3259,7 @@
 
 	/* Accounts menu */
 	{ N_("/_Accounts"), NULL, NULL, 0, "<Branch>", NULL },
-	{ N_("/Accounts/Manage"), "<CTL>A", pidgin_accounts_window_show, 0, "<Item>", NULL },
+	{ N_("/Accounts/Manage Accounts"), "<CTL>A", pidgin_accounts_window_show, 0, "<Item>", NULL },
 
 	/* Tools */
 	{ N_("/_Tools"), NULL, NULL, 0, "<Branch>", NULL },
@@ -5305,7 +5305,7 @@
 	tmp = g_strdup_printf(_("<span weight='bold' size='larger'>Welcome to %s!</span>\n\n"
 
 					       "You have no accounts enabled. Enable your IM accounts from the "
-					       "<b>Accounts</b> window at <b>Accounts->Manage</b>. Once you "
+					       "<b>Accounts</b> window at <b>Accounts->Manage Accounts</b>. Once you "
 					       "enable accounts, you'll be able to sign on, set your status, "
 					       "and talk to your friends."), PIDGIN_NAME);
 	pretty = pidgin_make_pretty_arrows(tmp);
@@ -6474,6 +6474,10 @@
 		purple_blist_add_buddy(b, NULL, g, NULL);
 		purple_account_add_buddy(data->account, b);
 
+		/* Offer to merge people with the same alias. */
+		if (whoalias != NULL)
+			gtk_blist_auto_personize(g, whoalias);
+
 		/*
 		 * XXX
 		 * It really seems like it would be better if the call to
@@ -7609,7 +7613,7 @@
 	for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = g_list_delete_link(l, l)) {
 		menuitem = l->data;
 
-		if (menuitem != gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts/Manage")))
+		if (menuitem != gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts/Manage Accounts")))
 			gtk_widget_destroy(menuitem);
 	}
 
--- a/pidgin/gtkft.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/pidgin/gtkft.c	Mon Jun 09 06:35:52 2008 +0000
@@ -226,8 +226,10 @@
 			total_pct = 100 * total_bytes_xferred / total_file_size;
 		}
 
-		title = g_strdup_printf(_("File Transfers - %d%% of %d files"),
-				total_pct, num_active_xfers);
+		title = g_strdup_printf(ngettext("File Transfers - %d%% of %d file",
+						 "File Transfers - %d%% of %d files",
+						 num_active_xfers),
+					total_pct, num_active_xfers);
 		gtk_window_set_title(GTK_WINDOW(dialog->window), title);
 		g_free(title);
 	} else {
--- a/pidgin/gtkimhtml.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/pidgin/gtkimhtml.c	Mon Jun 09 06:35:52 2008 +0000
@@ -5025,9 +5025,9 @@
 			str += g_snprintf(str, sizeof(buf) - (str - buf),
 					"color: #%02x%02x%02x;",
 					color->red >> 8, color->green >> 8, color->blue >> 8);
-			gdk_color_free(color);
 			empty = FALSE;
 		}
+		gdk_color_free(color);
 
 		/* Background color */
 		g_object_get(obj, "background-set", &isset, "background-gdk", &color, NULL);
@@ -5035,9 +5035,9 @@
 			str += g_snprintf(str, sizeof(buf) - (str - buf),
 					"background: #%02x%02x%02x;",
 					color->red >> 8, color->green >> 8, color->blue >> 8);
-			gdk_color_free(color);
 			empty = FALSE;
 		}
+		gdk_color_free(color);
 
 		/* Underline */
 		g_object_get(obj, "underline-set", &isset, "underline", &ivalue, NULL);
@@ -5245,8 +5245,10 @@
 
 				if (tmp == NULL)
 					purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n");
-				else
+				else {
 					g_string_append(str, tmp->end);
+					text_tag_data_destroy(tmp);
+				}
 
 				while ((tmp = g_queue_pop_head(r))) {
 					g_string_append(str, tmp->start);
--- a/pidgin/gtksavedstatuses.c	Sat Jun 07 01:06:41 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Mon Jun 09 06:35:52 2008 +0000
@@ -59,6 +59,7 @@
 	STATUS_WINDOW_COLUMN_MESSAGE,
 	/** A hidden column containing a pointer to the editor for this saved status. */
 	STATUS_WINDOW_COLUMN_WINDOW,
+	STATUS_WINDOW_COLUMN_ICON,
 	STATUS_WINDOW_NUM_COLUMNS
 };
 
@@ -80,6 +81,7 @@
 	STATUS_EDITOR_COLUMN_STATUS_ID,
 	STATUS_EDITOR_COLUMN_STATUS_NAME,
 	STATUS_EDITOR_COLUMN_STATUS_MESSAGE,
+	STATUS_EDITOR_COLUMN_STATUS_ICON,
 	STATUS_EDITOR_NUM_COLUMNS
 };
 
@@ -392,12 +394,35 @@
     g_list_free(sel_paths);
 }
 
+static const gchar *
+get_stock_icon_from_primitive(PurpleStatusPrimitive type)
+{
+	switch (type) {
+		case PURPLE_STATUS_AVAILABLE:
+			return PIDGIN_STOCK_STATUS_AVAILABLE;
+		case PURPLE_STATUS_AWAY:
+			return PIDGIN_STOCK_STATUS_AWAY;
+		case PURPLE_STATUS_EXTENDED_AWAY:
+			return PIDGIN_STOCK_STATUS_XA;
+		case PURPLE_STATUS_INVISIBLE:
+			return PIDGIN_STOCK_STATUS_INVISIBLE;
+		case PURPLE_STATUS_OFFLINE:
+			return PIDGIN_STOCK_STATUS_OFFLINE;
+		case PURPLE_STATUS_UNAVAILABLE:
+			return PIDGIN_STOCK_STATUS_BUSY;
+		default:
+			/* this shouldn't happen */
+			return NULL;
+	}
+}
+
 static void
 add_status_to_saved_status_list(GtkListStore *model, PurpleSavedStatus *saved_status)
 {
 	GtkTreeIter iter;
 	const char *title;
 	const char *type;
+	const gchar *icon;
 	char *message;
 
 	if (purple_savedstatus_is_transient(saved_status))
@@ -406,14 +431,16 @@
 	title = purple_savedstatus_get_title(saved_status);
 	type = purple_primitive_get_name_from_type(purple_savedstatus_get_type(saved_status));
 	message = purple_markup_strip_html(purple_savedstatus_get_message(saved_status));
+	icon = get_stock_icon_from_primitive(purple_savedstatus_get_type(saved_status));
 
 	gtk_list_store_append(model, &iter);
 	gtk_list_store_set(model, &iter,
+					   STATUS_WINDOW_COLUMN_ICON, icon,
 					   STATUS_WINDOW_COLUMN_TITLE, title,
 					   STATUS_WINDOW_COLUMN_TYPE, type,
 					   STATUS_WINDOW_COLUMN_MESSAGE, message,
 					   -1);
-	free(message);
+	g_free(message);
 }
 
 static void
@@ -479,7 +506,8 @@
 									   G_TYPE_STRING,
 									   G_TYPE_STRING,
 									   G_TYPE_STRING,
-									   G_TYPE_POINTER);
+									   G_TYPE_POINTER,
+									   G_TYPE_STRING);
 
 	/* Create the treeview */
 	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
@@ -517,6 +545,10 @@
 	gtk_tree_view_column_set_sort_column_id(column,
 											STATUS_WINDOW_COLUMN_TYPE);
 	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute(column, renderer, "stock-id",
+									   STATUS_WINDOW_COLUMN_ICON);
 	renderer = gtk_cell_renderer_text_new();
 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
 	gtk_tree_view_column_add_attribute(column, renderer, "text",
@@ -717,8 +749,8 @@
 }
 
 
-static gboolean
-status_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+static void
+status_editor_destroy_cb(GtkWidget *widget, gpointer user_data)
 {
 	StatusEditor *dialog = user_data;
 
@@ -726,19 +758,13 @@
 	g_free(dialog->original_title);
 	g_object_unref(G_OBJECT(dialog->model));
 	g_free(dialog);
-
-	return FALSE;
 }
 
 static void
 status_editor_cancel_cb(GtkButton *button, gpointer user_data)
 {
 	StatusEditor *dialog = user_data;
-
-	status_editor_remove_dialog(dialog);
 	gtk_widget_destroy(dialog->window);
-	g_free(dialog->original_title);
-	g_free(dialog);
 }
 
 static void
@@ -842,20 +868,11 @@
 	g_free(message);
 	g_free(unformatted);
 
-	status_editor_remove_dialog(dialog);
-	gtk_widget_destroy(dialog->window);
-	g_free(dialog->original_title);
-
-/*
-	if (status_window != NULL)
-	  add_status_to_saved_status_list(status_window->model, saved_status);
-*/
-
 	/* If they clicked on "Save & Use" or "Use," then activate the status */
 	if (button != dialog->save_button)
 		purple_savedstatus_activate(saved_status);
 
-	g_free(dialog);
+	gtk_widget_destroy(dialog->window);
 }
 
 static void
@@ -871,6 +888,26 @@
 }
 
 static GtkWidget *
+create_stock_item(const gchar *str, const gchar *icon)
+{
+	GtkWidget *menuitem = gtk_menu_item_new();
+	GtkWidget *label = gtk_label_new_with_mnemonic(str);
+	GtkWidget *hbox = gtk_hbox_new(FALSE, 4);
+	GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
+	GtkWidget *image = gtk_image_new_from_stock(icon, icon_size);;
+
+	gtk_widget_show(label);
+	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+
+	gtk_container_add(GTK_CONTAINER(menuitem), hbox);
+
+	return menuitem;
+}
+
+static GtkWidget *
 create_status_type_menu(PurpleStatusPrimitive type)
 {
 	int i;
@@ -889,7 +926,9 @@
 			 * status types, so don't show them in the list.
 			 */
 			continue;
-		item = gtk_menu_item_new_with_label(purple_primitive_get_name_from_type(i));
+
+		item = create_stock_item(purple_primitive_get_name_from_type(i),
+					get_stock_icon_from_primitive(i));
 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
 	}
 
@@ -945,6 +984,7 @@
 						   STATUS_EDITOR_COLUMN_STATUS_ID, NULL,
 						   STATUS_EDITOR_COLUMN_STATUS_NAME, NULL,
 						   STATUS_EDITOR_COLUMN_STATUS_MESSAGE, NULL,
+						   STATUS_EDITOR_COLUMN_STATUS_ICON, NULL,
 						   -1);
 	}
 }
@@ -990,6 +1030,10 @@
 	gtk_tree_view_column_set_title(column, _("Status"));
 	gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
 	gtk_tree_view_column_set_resizable(column, TRUE);
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(column, renderer, FALSE);
+	gtk_tree_view_column_add_attribute(column, renderer, "stock-id",
+			STATUS_EDITOR_COLUMN_STATUS_ICON);
 	renderer = gtk_cell_renderer_text_new();
 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
 	gtk_tree_view_column_add_attribute(column, renderer, "text",
@@ -1016,6 +1060,7 @@
 {
 	GdkPixbuf *pixbuf;
 	const char *id = NULL, *name = NULL, *message = NULL;
+	PurpleStatusPrimitive prim = PURPLE_STATUS_UNSET;
 
 	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
 	if ((pixbuf != NULL) && !purple_account_is_connected(account))
@@ -1030,6 +1075,7 @@
 		type = purple_savedstatus_substatus_get_type(substatus);
 		id = purple_status_type_get_id(type);
 		name = purple_status_type_get_name(type);
+		prim = purple_status_type_get_primitive(type);
 		if (purple_status_type_get_attr(type, "message"))
 			message = purple_savedstatus_substatus_get_message(substatus);
 	}
@@ -1042,6 +1088,7 @@
 			STATUS_EDITOR_COLUMN_STATUS_ID, id,
 			STATUS_EDITOR_COLUMN_STATUS_NAME, name,
 			STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message,
+			STATUS_EDITOR_COLUMN_STATUS_ICON, get_stock_icon_from_primitive(prim),
 			-1);
 
 	if (pixbuf != NULL)
@@ -1133,7 +1180,7 @@
 
 	dialog->window = win = pidgin_create_dialog(_("Status"), PIDGIN_HIG_BORDER, "status", TRUE);
 
-	g_signal_connect(G_OBJECT(win), "delete_event",
+	g_signal_connect(G_OBJECT(win), "destroy",
 					 G_CALLBACK(status_editor_destroy_cb), dialog);
 
 	/* Setup the vbox */
@@ -1198,6 +1245,7 @@
 									   G_TYPE_STRING,
 									   G_TYPE_STRING,
 									   G_TYPE_STRING,
+									   G_TYPE_STRING,
 									   G_TYPE_STRING);
 
 	/* Create the treeview */
@@ -1325,25 +1373,20 @@
 	}
 }
 
-static gboolean
-substatus_editor_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+static void
+substatus_editor_destroy_cb(GtkWidget *widget, gpointer user_data)
 {
 	SubStatusEditor *dialog = user_data;
 
 	substatus_editor_remove_dialog(dialog);
 	g_free(dialog);
-
-	return FALSE;
 }
 
 static void
 substatus_editor_cancel_cb(GtkButton *button, gpointer user_data)
 {
 	SubStatusEditor *dialog = user_data;
-
-	substatus_editor_remove_dialog(dialog);
 	gtk_widget_destroy(dialog->window);
-	g_free(dialog);
 }
 
 
@@ -1356,12 +1399,11 @@
 	PurpleStatusType *type;
 	char *id = NULL;
 	char *message = NULL;
-	const char *name = NULL;
+	const char *name = NULL, *stock = NULL;
 
 	if (!gtk_combo_box_get_active_iter(dialog->box, &iter))
 	{
 		gtk_widget_destroy(dialog->window);
-		g_free(dialog);
 		return;
 	}
 
@@ -1372,6 +1414,7 @@
 	if (purple_status_type_get_attr(type, "message") != NULL)
 		message = gtk_imhtml_get_markup(GTK_IMHTML(dialog->message));
 	name = purple_status_type_get_name(type);
+	stock = get_stock_icon_from_primitive(purple_status_type_get_primitive(type));
 
 	status_editor = dialog->status_editor;
 
@@ -1383,13 +1426,13 @@
 						   STATUS_EDITOR_COLUMN_STATUS_NAME, name,
 						   STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message,
 						   STATUS_EDITOR_COLUMN_WINDOW, NULL,
+						   STATUS_EDITOR_COLUMN_STATUS_ICON, stock,
 						   -1);
 	}
 
 	gtk_widget_destroy(dialog->window);
 	g_free(id);
 	g_free(message);
-	g_free(dialog);
 }
 
 static void
@@ -1438,7 +1481,7 @@
 	dialog->window = win = pidgin_create_dialog(tmp, PIDGIN_HIG_BORDER, "substatus", TRUE);
 	g_free(tmp);
 
-	g_signal_connect(G_OBJECT(win), "delete_event",
+	g_signal_connect(G_OBJECT(win), "destroy",
 					 G_CALLBACK(substatus_editor_destroy_cb), dialog);
 
 	/* Setup the vbox */
--- a/po/lt.po	Sat Jun 07 01:06:41 2008 +0000
+++ b/po/lt.po	Mon Jun 09 06:35:52 2008 +0000
@@ -721,8 +721,11 @@
 msgstr "Pristabdyti"
 
 #, c-format
-msgid "File Transfers - %d%% of %d files"
-msgstr "Failų perdavimai – %d%% iš %d"
+msgid "File Transfers - %d%% of %d file"
+msgid_plural "File Transfers - %d%% of %d files"
+msgstr[0] "Failų perdavimai – %d%% iš %d failo"
+msgstr[1] "Failų perdavimai – %d%% iš %d failų"
+msgstr[2] "Failų perdavimai – %d%% iš %d failų"
 
 #. Create the window.
 msgid "File Transfers"
@@ -3258,8 +3261,11 @@
 msgstr "Bloga būsena"
 
 #, c-format
-msgid "Ban on %s by %s, set %ld seconds ago"
-msgstr "Vartotojui %s uždraudė prisijungti %s prieš %ld sekundžių"
+msgid "Ban on %s by %s, set %ld second ago"
+msgid_plural "Ban on %s by %s, set %ld seconds ago"
+msgstr[0] "Vartotojui %s uždraudė prisijungti %s prieš %ld sekundę"
+msgstr[1] "Vartotojui %s uždraudė prisijungti %s prieš %ld sekundes"
+msgstr[2] "Vartotojui %s uždraudė prisijungti %s prieš %ld sekundžių"
 
 #, c-format
 msgid "Ban on %s"
@@ -5439,8 +5445,11 @@
 msgstr "Prisijungiama"
 
 #, c-format
-msgid "Connection to server lost (no data received within %d seconds)"
-msgstr "Nutrūko ryšys su serveriu (negauta jokių duomenų per %d sekundžių)"
+msgid "Connection to server lost (no data received within %d second)"
+msgid_plural "Connection to server lost (no data received within %d seconds)"
+msgstr[0] "Nutrūko ryšys su serveriu (negauta jokių duomenų per %d sekundę)"
+msgstr[1] "Nutrūko ryšys su serveriu (negauta jokių duomenų per %d sekundes)"
+msgstr[2] "Nutrūko ryšys su serveriu (negauta jokių duomenų per %d sekundžių)"
 
 #. Can't write _()'d strings in array initializers. Workaround.
 msgid "New mail messages"
@@ -5538,9 +5547,18 @@
 
 #, c-format
 msgid ""
+"%d buddy was added or updated from the server (including buddies already on "
+"the server-side list)"
+msgid_plural ""
 "%d buddies were added or updated from the server (including buddies already "
 "on the server-side list)"
-msgstr ""
+msgstr[0] ""
+"%d bičiulis buvo pridėtas ar atnaujintas iš serverio (įskaitant ir "
+"bičiulius, jau esančius serverio sąraše)"
+msgstr[1] ""
+"%d bičiuliai buvo pridėti ar atnaujinti iš serverio (įskaitant ir bičiulius, "
+"jau esančius serverio sąraše)"
+msgstr[2] ""
 "%d bičiulių buvo pridėta ar atnaujinta iš serverio (įskaitant ir bičiulius, "
 "jau esančius serverio sąraše)"
 
--- a/share/ca-certs/Makefile.am	Sat Jun 07 01:06:41 2008 +0000
+++ b/share/ca-certs/Makefile.am	Mon Jun 09 06:35:52 2008 +0000
@@ -1,5 +1,4 @@
-cacertsdir =	$(datadir)/purple/ca-certs
-cacerts_DATA =	\
+CERTIFICATES = \
 		Equifax_Secure_CA.pem \
 		GTE_CyberTrust_Global_Root.pem \
 		Microsoft_Secure_Server_Authority.pem \
@@ -7,7 +6,12 @@
 		Verisign_RSA_Secure_Server_CA.pem \
 		Verisign_Class3_Primary_CA.pem
 
+if INSTALL_SSL_CERTIFICATES
+cacertsdir =	$(datadir)/purple/ca-certs
+cacerts_DATA =	$(CERTIFICATES)
+endif
+
 EXTRA_DIST =	\
 		Makefile.mingw \
-		$(cacerts_DATA)
+		$(CERTIFICATES)