changeset 29675:ea0494a3a299

propagate from branch 'im.pidgin.pidgin' (head 81bb2e1582a2222b36e57c29ccb573dac27f2a44) to branch 'im.pidgin.cpw.attention_ui' (head 6d0c340ea0021535d623146846cc275b0b6aa5ea)
author Marcus Lundblad <ml@update.uu.se>
date Sat, 28 Mar 2009 16:59:30 +0000
parents 9407348dc714 (current diff) c422c7b1bde7 (diff)
children ae24e54a5014
files libpurple/protocols/jabber/si.c libpurple/protocols/toc/Makefile.am libpurple/protocols/toc/Makefile.mingw libpurple/protocols/toc/PROTOCOL libpurple/protocols/toc/toc.c
diffstat 59 files changed, 572 insertions(+), 3487 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Mar 16 21:45:24 2009 +0000
+++ b/COPYRIGHT	Sat Mar 28 16:59:30 2009 +0000
@@ -8,6 +8,7 @@
 Dave Ahlswede
 Manuel Amador
 Matt Amato
+Josef Andrysek
 Geoffrey Antos
 Daniel Atallah
 Paul Aurich
--- a/ChangeLog	Mon Mar 16 21:45:24 2009 +0000
+++ b/ChangeLog	Sat Mar 28 16:59:30 2009 +0000
@@ -4,10 +4,15 @@
 	General:
 	* Theme support in libpurple thanks to Justin Rodriguez's summer of code
 	  project.  With some minor additions and clean ups from Paul Aurich.
+	* It should no longer be possible to end up with duplicates of buddies
+	  in a group on the buddy list.
+	* Removed the unmaintained and unneeded toc protocol plugin.
+	* Fixed NTLM authentication on big-endian systems.
 
 	XMPP:
-	* Add support for in-band bytestreams (XEP-0047).
-	* Add support for attention (XEP-0224).
+	* Add support for in-band bytestreams for file transfers (XEP-0047).
+	* Add support for sending attentions (equivalent to "buzz" and "nudge")
+	  using the command /buzz (XEP-0224).
 
 	Pidgin:
 	* Added -f command line option to tell Pidgin to ignore NetworkManager
@@ -21,6 +26,8 @@
 	* Created a unified Buddy Pounce notification window for all pounces
 	  where "Pop up a notification" is selected, which avoids having a
 	  new dialog box every time a pounce is triggered. (Jorge Villaseñor) 
+	* The New Account dialog is now broken into three tabs.  Proxy
+	  configuration has been moved from the Advanced tab to the new tab.
 
 version 2.5.5 (03/01/2009):
 	libpurple:
--- a/ChangeLog.API	Mon Mar 16 21:45:24 2009 +0000
+++ b/ChangeLog.API	Sat Mar 28 16:59:30 2009 +0000
@@ -30,10 +30,10 @@
 
 		Changed:
 		* xmlnode_remove_attrib now removes all attributes with the
-		same name.  Previously, it would remove the first one found,
-		which was completely non-deterministic.  If you want to remove
-		the attribute with no namespace, then use NULL with
-		xmlnode_remove_with_namespace.
+		  same name.  Previously, it would remove the first one found,
+		  which was completely non-deterministic.  If you want to remove
+		  the attribute with no namespace, then use NULL with
+		  xmlnode_remove_with_namespace.
 
 		Deprecated:
 		* purple_buddy_get_local_alias
--- a/configure.ac	Mon Mar 16 21:45:24 2009 +0000
+++ b/configure.ac	Sat Mar 28 16:59:30 2009 +0000
@@ -1048,7 +1048,6 @@
 		silc)		static_silc=yes ;;
 		silc10)		static_silc=yes ;;
 		simple)		static_simple=yes ;;
-		toc)		static_toc=yes ;;
 		yahoo)		static_yahoo=yes ;;
 		zephyr)		static_zephyr=yes ;;
 		*)			echo "Invalid static protocol $i!!" ; exit ;;
@@ -1066,7 +1065,6 @@
 AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes")
 AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$have_silc" = "xyes")
 AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes")
-AM_CONDITIONAL(STATIC_TOC, test "x$static_toc" = "xyes")
 AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
 AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes")
 AC_SUBST(STATIC_LINK_LIBS)
@@ -1112,7 +1110,6 @@
 		silc)		dynamic_silc=yes ;;
 		silc10)		dynamic_silc=yes ;;
 		simple)		dynamic_simple=yes ;;
-		toc)		dynamic_toc=yes ;;
 		yahoo)		dynamic_yahoo=yes ;;
 		zephyr)		dynamic_zephyr=yes ;;
 		*)			echo "Invalid dynamic protocol $i!!" ; exit ;;
@@ -2450,7 +2447,6 @@
 		   libpurple/protocols/silc/Makefile
 		   libpurple/protocols/silc10/Makefile
 		   libpurple/protocols/simple/Makefile
-		   libpurple/protocols/toc/Makefile
 		   libpurple/protocols/yahoo/Makefile
 		   libpurple/protocols/zephyr/Makefile
 		   libpurple/tests/Makefile
--- a/doc/account-signals.dox	Mon Mar 16 21:45:24 2009 +0000
+++ b/doc/account-signals.dox	Sat Mar 28 16:59:30 2009 +0000
@@ -109,7 +109,7 @@
 
  @signaldef account-authorization-requested
   @signalproto
-void (*account_authorization_requested)(PurpleAccount *account, const char *user);
+int (*account_authorization_requested)(PurpleAccount *account, const char *user);
   @endsignalproto
   @signaldesc
    Emitted when a user requests authorization.
--- a/finch/gntblist.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/finch/gntblist.c	Sat Mar 28 16:59:30 2009 +0000
@@ -643,10 +643,14 @@
 		purple_blist_add_group(grp, NULL);
 	}
 
-	/* XXX: Ask if there's already the same buddy in the same group (#4553) */
-
-	buddy = purple_buddy_new(account, username, alias);
-	purple_blist_add_buddy(buddy, NULL, grp, NULL);
+	/* XXX: Ask to merge if there's already a buddy with the same alias in the same group (#4553) */
+
+	if ((buddy = purple_find_buddy_in_group(account, username, grp)) == NULL)
+	{
+		buddy = purple_buddy_new(account, username, alias);
+		purple_blist_add_buddy(buddy, NULL, grp, NULL);
+	}
+
 	purple_account_add_buddy(account, buddy);
 }
 
--- a/finch/gntlog.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/finch/gntlog.c	Sat Mar 28 16:59:30 2009 +0000
@@ -66,7 +66,7 @@
 			g_str_hash(purple_account_get_username(viewer->account));
 	}
 
-	return (guint)viewer;
+	return g_direct_hash(viewer);
 }
 
 static gboolean log_viewer_equal(gconstpointer y, gconstpointer z)
--- a/finch/gntplugin.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/finch/gntplugin.c	Sat Mar 28 16:59:30 2009 +0000
@@ -484,10 +484,10 @@
 				char *value = NULL;
 				switch(type) {
 					case PURPLE_PREF_BOOLEAN:
-						value = g_strdup_printf("%d", (int)list->next->data);
+						value = g_strdup_printf("%d", GPOINTER_TO_INT(list->next->data));
 						break;
 					case PURPLE_PREF_INT:
-						value = g_strdup_printf("%d", (int)list->next->data);
+						value = g_strdup_printf("%d", GPOINTER_TO_INT(list->next->data));
 						break;
 					case PURPLE_PREF_STRING:
 						value = g_strdup(list->next->data);
--- a/finch/gntroomlist.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/finch/gntroomlist.c	Sat Mar 28 16:59:30 2009 +0000
@@ -190,7 +190,7 @@
 				label = g_strdup(iter->data ? "True" : "False");
 				break;
 			case PURPLE_ROOMLIST_FIELD_INT:
-				label = g_strdup_printf("%d", (int)iter->data);
+				label = g_strdup_printf("%d", GPOINTER_TO_INT(iter->data));
 				break;
 			case PURPLE_ROOMLIST_FIELD_STRING:
 				label = g_strdup(iter->data);
--- a/libpurple/blist.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/blist.h	Sat Mar 28 16:59:30 2009 +0000
@@ -595,7 +595,7 @@
  * @param contact The optional contact to place the buddy in.
  * @param group   The group to add the new buddy to.
  * @param node    The insertion point.  Pass in NULL to add the node as
- *                the last child in the given group.
+ *                the first child in the given group.
  */
 void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node);
 
--- a/libpurple/circbuffer.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/circbuffer.c	Sat Mar 28 16:59:30 2009 +0000
@@ -68,7 +68,8 @@
 
 	/* If the fill pointer is wrapped to before the remove
 	 * pointer, we need to shift the data */
-	if (in_offset < out_offset) {
+	if (in_offset < out_offset
+			|| (in_offset == out_offset && buf->bufused > 0)) {
 		int shift_n = MIN(buf->buflen - start_buflen,
 			in_offset);
 		memcpy(buf->buffer + start_buflen, buf->buffer,
--- a/libpurple/desktopitem.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/desktopitem.c	Sat Mar 28 16:59:30 2009 +0000
@@ -823,7 +823,11 @@
 	}
 }
 
-/* fallback to find something suitable for C locale */
+/**
+ * Fallback to find something suitable for C locale.
+ *
+ * @return A newly allocated string which should be g_freed by the caller.
+ */
 static char *
 try_english_key (PurpleDesktopItem *item, const char *key)
 {
--- a/libpurple/dnssrv.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/dnssrv.c	Sat Mar 28 16:59:30 2009 +0000
@@ -175,9 +175,11 @@
 
 end:
 	size = g_list_length(ret);
+	/* TODO: Check return value */
 	write(out, &size, sizeof(int));
 	while (ret != NULL)
 	{
+		/* TODO: Check return value */
 		write(out, ret->data, sizeof(PurpleSrvResponse));
 		g_free(ret->data);
 		ret = g_list_remove(ret, ret->data);
--- a/libpurple/ntlm.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/ntlm.c	Sat Mar 28 16:59:30 2009 +0000
@@ -41,12 +41,12 @@
 	guint32 type;            /* 0x00000001 */
 	guint32 flags;           /* 0x0000b203 */
 
-	short   dom_len1;        /* domain string length */
-	short   dom_len2;        /* domain string length */
+	guint16 dom_len1;        /* domain string length */
+	guint16 dom_len2;        /* domain string length */
 	guint32 dom_off;         /* domain string offset */
 
-	short   host_len1;       /* host string length */
-	short   host_len2;       /* host string length */
+	guint16 host_len1;       /* host string length */
+	guint16 host_len2;       /* host string length */
 	guint32 host_off;        /* host string offset (always 0x00000020) */
 
 #if 0
@@ -59,47 +59,47 @@
 	guint8  protocol[8];     /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
 	guint32 type;            /* 0x00000002 */
 
-	short   msg_len1;        /* target name length */
-	short   msg_len2;        /* target name length */
-	guint32 msg_off;         /* target name offset (always 0x00000048) */
+	guint32 zero;
+	guint16 msg_len1;        /* target name length */
+	guint16 msg_len2;        /* target name length */
 
 	guint32 flags;           /* 0x00008201 */
 
 	guint8  nonce[8];        /* nonce */
-	guint8 context[8];
+	guint8  context[8];
 };
 
 struct type3_message {
 	guint8  protocol[8];     /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
 	guint32 type;            /* 0x00000003 */
 
-	short   lm_resp_len1;    /* LanManager response length (always 0x18)*/
-	short   lm_resp_len2;    /* LanManager response length (always 0x18)*/
+	guint16 lm_resp_len1;    /* LanManager response length (always 0x18)*/
+	guint16 lm_resp_len2;    /* LanManager response length (always 0x18)*/
 	guint32 lm_resp_off;     /* LanManager response offset */
 
-	short   nt_resp_len1;    /* NT response length (always 0x18) */
-	short   nt_resp_len2;    /* NT response length (always 0x18) */
+	guint16 nt_resp_len1;    /* NT response length (always 0x18) */
+	guint16 nt_resp_len2;    /* NT response length (always 0x18) */
 	guint32 nt_resp_off;     /* NT response offset */
 
-	short   dom_len1;        /* domain string length */
-	short   dom_len2;        /* domain string length */
+	guint16 dom_len1;        /* domain string length */
+	guint16 dom_len2;        /* domain string length */
 	guint32 dom_off;         /* domain string offset (always 0x00000040) */
 
-	short   user_len1;       /* username string length */
-	short   user_len2;       /* username string length */
+	guint16 user_len1;       /* username string length */
+	guint16 user_len2;       /* username string length */
 	guint32 user_off;        /* username string offset */
 
-	short   host_len1;       /* host string length */
-	short   host_len2;       /* host string length */
+	guint16 host_len1;       /* host string length */
+	guint16 host_len2;       /* host string length */
 	guint32 host_off;        /* host string offset */
 
-	short   sess_len1;
-	short	sess_len2;
+	guint16 sess_len1;
+	guint16 sess_len2;
 	guint32 sess_off;         /* message length */
 
 	guint32 flags;            /* 0x00008201 */
 	/* guint32 flags2; */     /* unknown, used in windows messenger */
-	/* guint32  flags3; */
+	/* guint32 flags3; */
 
 #if 0
 	guint8  dom[*];          /* domain string (unicode UTF-16LE) */
@@ -110,7 +110,6 @@
 #endif
 };
 
-/* TODO: Will this work on both little-endian and big-endian machines? */
 gchar *
 purple_ntlm_gen_type1(const gchar *hostname, const gchar *domain)
 {
@@ -132,12 +131,12 @@
 	tmsg->protocol[5] = 'S';
 	tmsg->protocol[6] = 'P';
 	tmsg->protocol[7] = '\0';
-	tmsg->type      = 0x00000001;
-	tmsg->flags     = 0x0000b203;
-	tmsg->dom_len1  = tmsg->dom_len2 = domainlen;
-	tmsg->dom_off   = sizeof(struct type1_message) + hostnamelen;
-	tmsg->host_len1 = tmsg->host_len2 = hostnamelen;
-	tmsg->host_off  = sizeof(struct type1_message);
+	tmsg->type      = GUINT32_TO_LE(0x00000001);
+	tmsg->flags     = GUINT32_TO_LE(0x0000b203);
+	tmsg->dom_len1  = tmsg->dom_len2 = GUINT16_TO_LE(domainlen);
+	tmsg->dom_off   = GUINT32_TO_LE(sizeof(struct type1_message) + hostnamelen);
+	tmsg->host_len1 = tmsg->host_len2 = GUINT16_TO_LE(hostnamelen);
+	tmsg->host_off  = GUINT32_TO_LE(sizeof(struct type1_message));
 	memcpy(msg + tmsg->host_off, hostname, hostnamelen);
 	memcpy(msg + tmsg->dom_off, domain, domainlen);
 
@@ -157,7 +156,7 @@
 	tmsg = (struct type2_message*)purple_base64_decode(type2, &retlen);
 	memcpy(nonce, tmsg->nonce, 8);
 	if (flags != NULL)
-		*flags = tmsg->flags;
+		*flags = GUINT16_FROM_LE(tmsg->flags);
 	g_free(tmsg);
 
 	return nonce;
@@ -268,27 +267,27 @@
 	tmsg->protocol[4] = 'S';
 	tmsg->protocol[5] = 'S';
 	tmsg->protocol[6] = 'P';
-	tmsg->type = 0x00000003;
-	tmsg->lm_resp_len1 = tmsg->lm_resp_len2 = 0x18;
-	tmsg->lm_resp_off = sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen;
-	tmsg->nt_resp_len1 = tmsg->nt_resp_len2 = 0x18;
-	tmsg->nt_resp_off = sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen + 0x18;
+	tmsg->type = GUINT32_TO_LE(0x00000003);
+	tmsg->lm_resp_len1 = tmsg->lm_resp_len2 = GUINT16_TO_LE(0x18);
+	tmsg->lm_resp_off = GUINT32_TO_LE(sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen);
+	tmsg->nt_resp_len1 = tmsg->nt_resp_len2 = GUINT16_TO_LE(0x18);
+	tmsg->nt_resp_off = GUINT32_TO_LE(sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen + 0x18);
 
-	tmsg->dom_len1 = tmsg->dom_len2 = domainlen;
-	tmsg->dom_off = sizeof(struct type3_message);
+	tmsg->dom_len1 = tmsg->dom_len2 = GUINT16_TO_LE(domainlen);
+	tmsg->dom_off = GUINT32_TO_LE(sizeof(struct type3_message));
 
-	tmsg->user_len1 = tmsg->user_len2 = usernamelen;
-	tmsg->user_off = sizeof(struct type3_message) + domainlen;
+	tmsg->user_len1 = tmsg->user_len2 = GUINT16_TO_LE(usernamelen);
+	tmsg->user_off = GUINT32_TO_LE(sizeof(struct type3_message) + domainlen);
 
-	tmsg->host_len1 = tmsg->host_len2 = hostnamelen;
-	tmsg->host_off = sizeof(struct type3_message) + domainlen + usernamelen;
+	tmsg->host_len1 = tmsg->host_len2 = GUINT16_TO_LE(hostnamelen);
+	tmsg->host_off = GUINT32_TO_LE(sizeof(struct type3_message) + domainlen + usernamelen);
 
 	if(flags) {
-		tmsg->sess_off = sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen + 0x18 + 0x18;
-		tmsg->sess_len1 = tmsg->sess_len2 = 0x0010;
+		tmsg->sess_off = GUINT32_TO_LE(sizeof(struct type3_message) + domainlen + usernamelen + hostnamelen + 0x18 + 0x18);
+		tmsg->sess_len1 = tmsg->sess_len2 = GUINT16_TO_LE(0x0010);
 	}
 
-	tmsg->flags = 0x00008201;
+	tmsg->flags = GUINT32_TO_LE(0x00008201);
 
 	tmp = (char *)tmsg + sizeof(struct type3_message);
 
@@ -361,7 +360,7 @@
 
 	/* LCS Stuff */
 	if (flags) {
-		tmsg->flags = 0x409082d4;
+		tmsg->flags = GUINT32_TO_LE(0x409082d4);
 		gensesskey(sesskey, NULL);
 		memcpy(tmp, sesskey, 0x10);
 	}
--- a/libpurple/plugins/mono/loader/debug-glue.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/plugins/mono/loader/debug-glue.c	Sat Mar 28 16:59:30 2009 +0000
@@ -9,7 +9,7 @@
 	ccat = mono_string_to_utf8(cat);
 	cstr = mono_string_to_utf8(str);
 	
-	purple_debug(type, ccat, cstr);
+	purple_debug(type, ccat, "%s", cstr);
 	
 	g_free(ccat);
 	g_free(cstr);
--- a/libpurple/plugins/mono/loader/mono.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/plugins/mono/loader/mono.c	Sat Mar 28 16:59:30 2009 +0000
@@ -39,18 +39,18 @@
 
 	if (!assm) {
 		return FALSE;
-	} 
+	}
 
 	purple_debug(PURPLE_DEBUG_INFO, "mono", "Probing plugin\n");
 
 	if (ml_is_api_dll(mono_assembly_get_image(assm))) {
-		purple_debug(PURPLE_DEBUG_INFO, "mono", "Found our PurpleAPI.dll\n");
+		purple_debug_info("mono", "Found our PurpleAPI.dll\n");
+		mono_assembly_close(assm);
 		return FALSE;
 	}
 
-	info = g_new0(PurplePluginInfo, 1);
 	mplug = g_new0(PurpleMonoPlugin, 1);
-	
+
 	mplug->signal_data = NULL;
 
 	mplug->assm = assm;
@@ -58,12 +58,16 @@
 	mplug->klass = ml_find_plugin_class(mono_assembly_get_image(mplug->assm));
 	if (!mplug->klass) {
 		purple_debug(PURPLE_DEBUG_ERROR, "mono", "no plugin class in \'%s\'\n", file);
+		mono_assembly_close(assm);
+		g_free(mplug);
 		return FALSE;
 	}
 
 	mplug->obj = mono_object_new(ml_get_domain(), mplug->klass);
 	if (!mplug->obj) {
 		purple_debug(PURPLE_DEBUG_ERROR, "mono", "obj not valid\n");
+		mono_assembly_close(assm);
+		g_free(mplug);
 		return FALSE;
 	}
 
@@ -85,14 +89,17 @@
 
 	if (!(found_load && found_unload && found_destroy)) {
 		purple_debug(PURPLE_DEBUG_ERROR, "mono", "did not find the required methods\n");
+		mono_assembly_close(assm);
+		g_free(mplug);
 		return FALSE;
 	}
-	
+
 	plugin_info = ml_get_info_prop(mplug->obj);
 
 	/* now that the methods are filled out we can populate
 	   the info struct with all the needed info */
 
+	info = g_new0(PurplePluginInfo, 1);
 	info->id = ml_get_prop_string(plugin_info, "Id");
 	info->name = ml_get_prop_string(plugin_info, "Name");
 	info->version = ml_get_prop_string(plugin_info, "Version");
@@ -109,7 +116,7 @@
 	/* this plugin depends on us; duh */
 	info->dependencies = g_list_append(info->dependencies, MONO_PLUGIN_ID);
 	mplug->plugin = plugin;
-				
+
 	plugin->info = info;
 	info->extra_info = mplug;
 
@@ -238,7 +245,7 @@
 static void init_plugin(PurplePlugin *plugin)
 {
 	ml_init();
-	
+
 	loader_info.exts = g_list_append(loader_info.exts, "dll");
 }
 
--- a/libpurple/protocols/Makefile.am	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/Makefile.am	Sat Mar 28 16:59:30 2009 +0000
@@ -1,5 +1,5 @@
 EXTRA_DIST = Makefile.mingw
 
-DIST_SUBDIRS = bonjour gg irc jabber msn msnp9 myspace novell null oscar qq sametime silc silc10 toc simple yahoo zephyr
+DIST_SUBDIRS = bonjour gg irc jabber msn msnp9 myspace novell null oscar qq sametime silc silc10 simple yahoo zephyr
 
 SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/bonjour/mdns_win32.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Sat Mar 28 16:59:30 2009 +0000
@@ -169,14 +169,17 @@
 	gboolean delete_buddy = FALSE;
 	PurpleBuddy *pb = NULL;
 
+	if ((pb = purple_find_buddy(args->account, args->res_data->name))) {
+		if (pb->proto_data != args->bb) {
+			purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.",
+				args->res_data->name);
+			goto cleanup;
+		}
 	/* Make sure that the BonjourBuddy associated with this request is still around */
-	if (g_slist_find(pending_buddies, args->bb) == NULL)
+	} else if (g_slist_find(pending_buddies, args->bb) == NULL) {
+		purple_debug_error("bonjour", "host resolution - complete, but buddy no longer pending.\n");
 		goto cleanup;
-
-	if ((pb = purple_find_buddy(args->account, args->bb->name)))
-		if (pb->proto_data != args->bb)
-			purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record. "
-				"This is going to be ugly!.\n", args->bb->name);
+	}
 
 	if (!hosts || !hosts->data) {
 		purple_debug_error("bonjour", "host resolution - callback error.\n");
--- a/libpurple/protocols/irc/irc.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/irc/irc.c	Sat Mar 28 16:59:30 2009 +0000
@@ -565,7 +565,7 @@
 	struct irc_conn *irc = (struct irc_conn *)gc->proto_data;
 	struct irc_buddy *ib = g_new0(struct irc_buddy, 1);
 	ib->name = g_strdup(purple_buddy_get_name(buddy));
-	g_hash_table_insert(irc->buddies, ib->name, ib);
+	g_hash_table_replace(irc->buddies, ib->name, ib);
 
 	/* if the timer isn't set, this is during signon, so we don't want to flood
 	 * ourself off with ISON's, so we don't, but after that we want to know when
--- a/libpurple/protocols/jabber/buddy.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Sat Mar 28 16:59:30 2009 +0000
@@ -301,36 +301,32 @@
 
 struct vcard_template {
 	char *label;			/* label text pointer */
-	char *text;			/* entry text pointer */
-	int  visible;			/* should entry field be "visible?" */
-	int  editable;			/* should entry field be editable? */
 	char *tag;			/* tag text */
 	char *ptag;			/* parent tag "path" text */
-	char *url;			/* vCard display format if URL */
 } const vcard_template_data[] = {
-	{N_("Full Name"),          NULL, TRUE, TRUE, "FN",        NULL,  NULL},
-	{N_("Family Name"),        NULL, TRUE, TRUE, "FAMILY",    "N",   NULL},
-	{N_("Given Name"),         NULL, TRUE, TRUE, "GIVEN",     "N",   NULL},
-	{N_("Nickname"),           NULL, TRUE, TRUE, "NICKNAME",  NULL,  NULL},
-	{N_("URL"),                NULL, TRUE, TRUE, "URL",       NULL,  "<A HREF=\"%s\">%s</A>"},
-	{N_("Street Address"),     NULL, TRUE, TRUE, "STREET",    "ADR", NULL},
-	{N_("Extended Address"),   NULL, TRUE, TRUE, "EXTADD",    "ADR", NULL},
-	{N_("Locality"),           NULL, TRUE, TRUE, "LOCALITY",  "ADR", NULL},
-	{N_("Region"),             NULL, TRUE, TRUE, "REGION",    "ADR", NULL},
-	{N_("Postal Code"),        NULL, TRUE, TRUE, "PCODE",     "ADR", NULL},
-	{N_("Country"),            NULL, TRUE, TRUE, "CTRY",      "ADR", NULL},
-	{N_("Telephone"),          NULL, TRUE, TRUE, "NUMBER",    "TEL",  NULL},
-	{N_("Email"),             NULL, TRUE, TRUE, "USERID",    "EMAIL",  "<A HREF=\"mailto:%s\">%s</A>"},
-	{N_("Organization Name"),  NULL, TRUE, TRUE, "ORGNAME",   "ORG", NULL},
-	{N_("Organization Unit"),  NULL, TRUE, TRUE, "ORGUNIT",   "ORG", NULL},
-	{N_("Title"),              NULL, TRUE, TRUE, "TITLE",     NULL,  NULL},
-	{N_("Role"),               NULL, TRUE, TRUE, "ROLE",      NULL,  NULL},
-	{N_("Birthday"),           NULL, TRUE, TRUE, "BDAY",      NULL,  NULL},
-	{N_("Description"),        NULL, TRUE, TRUE, "DESC",      NULL,  NULL},
-	{"", NULL, TRUE, TRUE, "N",     NULL, NULL},
-	{"", NULL, TRUE, TRUE, "ADR",   NULL, NULL},
-	{"", NULL, TRUE, TRUE, "ORG",   NULL, NULL},
-	{NULL, NULL, 0, 0, NULL, NULL, NULL}
+	{N_("Full Name"),          "FN",        NULL},
+	{N_("Family Name"),        "FAMILY",    "N"},
+	{N_("Given Name"),         "GIVEN",     "N"},
+	{N_("Nickname"),           "NICKNAME",  NULL},
+	{N_("URL"),                "URL",       NULL},
+	{N_("Street Address"),     "STREET",    "ADR"},
+	{N_("Extended Address"),   "EXTADD",    "ADR"},
+	{N_("Locality"),           "LOCALITY",  "ADR"},
+	{N_("Region"),             "REGION",    "ADR"},
+	{N_("Postal Code"),        "PCODE",     "ADR"},
+	{N_("Country"),            "CTRY",      "ADR"},
+	{N_("Telephone"),          "NUMBER",    "TEL"},
+	{N_("Email"),              "USERID",    "EMAIL"},
+	{N_("Organization Name"),  "ORGNAME",   "ORG"},
+	{N_("Organization Unit"),  "ORGUNIT",   "ORG"},
+	{N_("Title"),              "TITLE",     NULL},
+	{N_("Role"),               "ROLE",      NULL},
+	{N_("Birthday"),           "BDAY",      NULL},
+	{N_("Description"),        "DESC",      NULL},
+	{"",                       "N",         NULL},
+	{"",                       "ADR",       NULL},
+	{"",                       "ORG",       NULL},
+	{NULL,                     NULL,        NULL}
 };
 
 /*
--- a/libpurple/protocols/jabber/si.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/jabber/si.c	Sat Mar 28 16:59:30 2009 +0000
@@ -1662,23 +1662,22 @@
 	jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));
 
 	xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from);
-	if (xfer)
-	{
-		xfer->data = jsx;
+	g_return_if_fail(xfer != NULL);
+
+	xfer->data = jsx;
 
-		purple_xfer_set_filename(xfer, filename);
-		if(filesize > 0)
-			purple_xfer_set_size(xfer, filesize);
+	purple_xfer_set_filename(xfer, filename);
+	if(filesize > 0)
+		purple_xfer_set_size(xfer, filesize);
 
-		purple_xfer_set_init_fnc(xfer, jabber_si_xfer_init);
-		purple_xfer_set_request_denied_fnc(xfer, jabber_si_xfer_request_denied);
-		purple_xfer_set_cancel_recv_fnc(xfer, jabber_si_xfer_cancel_recv);
-		purple_xfer_set_end_fnc(xfer, jabber_si_xfer_end);
+	purple_xfer_set_init_fnc(xfer, jabber_si_xfer_init);
+	purple_xfer_set_request_denied_fnc(xfer, jabber_si_xfer_request_denied);
+	purple_xfer_set_cancel_recv_fnc(xfer, jabber_si_xfer_cancel_recv);
+	purple_xfer_set_end_fnc(xfer, jabber_si_xfer_end);
 
-		js->file_transfers = g_list_append(js->file_transfers, xfer);
+	js->file_transfers = g_list_append(js->file_transfers, xfer);
 
-		purple_xfer_request(xfer);
-	}
+	purple_xfer_request(xfer);
 }
 
 void
--- a/libpurple/protocols/jabber/xdata.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/jabber/xdata.c	Sat Mar 28 16:59:30 2009 +0000
@@ -153,11 +153,12 @@
 	}
 	g_free(data);
 
-	if (hasActions) {
+	if (hasActions)
 		cb(js, result, actionhandle, user_data);
-		g_free(actionhandle);
-	} else
+	else
 		((jabber_x_data_cb)cb)(js, result, user_data);
+
+	g_free(actionhandle);
 }
 
 static void jabber_x_data_cancel_cb(struct jabber_x_data_data *data, PurpleRequestFields *fields) {
--- a/libpurple/protocols/msn/cmdproc.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/cmdproc.c	Sat Mar 28 16:59:30 2009 +0000
@@ -117,8 +117,10 @@
 
 	servconn = cmdproc->servconn;
 
-	if (!servconn->connected)
+	if (!servconn->connected) {
+		/* TODO: Need to free trans */
 		return;
+	}
 
 	msn_history_add(cmdproc->history, trans);
 
--- a/libpurple/protocols/msn/contact.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/contact.c	Sat Mar 28 16:59:30 2009 +0000
@@ -1482,8 +1482,6 @@
 			  const gchar *passport, const MsnListId list)
 {
 	gchar *body = NULL, *member = NULL;
-	const char *type = "PassportMember";
-	gchar *federate = NULL;
 	MsnSoapPartnerScenario partner_scenario;
 	MsnUser *user;
 
@@ -1501,23 +1499,28 @@
 	msn_callback_state_set_who(state, passport);
 
 	user = msn_userlist_find_user(session->userlist, passport);
-	if (user && user->networkid != MSN_NETWORK_PASSPORT) {
-		type = "EmailMember";
-		federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML,
-		                           user->networkid);
-	}
 	
 	if (list == MSN_LIST_PL) {
 		partner_scenario = MSN_PS_CONTACT_API;
-		member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-		                         type, user->membership_id[MSN_LIST_PL],
-		                         federate ? federate : "");
+		if (user && user->networkid != MSN_NETWORK_PASSPORT)
+			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+			                         "EmailMember", "Email",
+			                         user->membership_id[MSN_LIST_PL]);
+		else
+			member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+			                         "PassportMember", "Passport",
+			                         user->membership_id[MSN_LIST_PL]);
 	} else {
 		/* list == MSN_LIST_AL || list == MSN_LIST_BL */
 		partner_scenario = MSN_PS_BLOCK_UNBLOCK;
-		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-		                         type, passport,
-		                         federate ? federate : "");
+		if (user && user->networkid != MSN_NETWORK_PASSPORT)
+			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+			                         "EmailMember", "Email",
+			                         "Email", passport, "Email");
+		else
+			member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+			                         "PassportMember", "Passport",
+			                         "PassportName", passport, "PassportName");
 	}
 
 	body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE,
@@ -1530,7 +1533,6 @@
 	state->cb = msn_del_contact_from_list_read_cb;
 	msn_contact_request(state);
 
-	g_free(federate);
 	g_free(member);
 	g_free(body);
 }
@@ -1578,8 +1580,6 @@
 			const gchar *passport, const MsnListId list)
 {
 	gchar *body = NULL, *member = NULL;
-	const char *type = "PassportMember";
-	gchar *federate = NULL;
 	MsnSoapPartnerScenario partner_scenario;
 	MsnUser *user;
 
@@ -1596,15 +1596,16 @@
 	msn_callback_state_set_who(state, passport);
 
 	user = msn_userlist_find_user(session->userlist, passport);
-	if (user && user->networkid != MSN_NETWORK_PASSPORT) {
-		type = "EmailMember";
-		federate = g_strdup_printf(MSN_MEMBER_FEDERATED_ANNOTATION_XML,
-		                           user->networkid);
-	}
 
 	partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
-	member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-	                         type, state->who, federate ? federate : "");
+	if (user && user->networkid != MSN_NETWORK_PASSPORT)
+		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+		                         "EmailMember", "Email",
+		                         "Email", state->who, "Email");
+	else
+		member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+		                         "PassportMember", "Passport",
+		                         "PassportName", state->who, "PassportName");
 
 	body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE,
 		MsnSoapPartnerScenarioText[partner_scenario],
@@ -1616,7 +1617,6 @@
 	state->cb = msn_add_contact_to_list_read_cb;
 	msn_contact_request(state);
 
-	g_free(federate);
 	g_free(member);
 	g_free(body);
 }
--- a/libpurple/protocols/msn/contact.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/contact.h	Sat Mar 28 16:59:30 2009 +0000
@@ -397,28 +397,18 @@
 
 #define MSN_MEMBER_PASSPORT_XML	\
 	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>Passport</Type>"\
+		"<Type>%s</Type>"\
 		"<State>Accepted</State>"\
-		"<PassportName>%s</PassportName>"\
-		"%s"\
+		"<%s>%s</%s>"\
 	"</Member>"
 
 #define MSN_MEMBER_MEMBERSHIPID_XML	\
 	"<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-		"<Type>Passport</Type>"\
+		"<Type>%s</Type>"\
 		"<MembershipId>%u</MembershipId>"\
 		"<State>Accepted</State>"\
-		"%s"\
 	"</Member>"
 
-#define MSN_MEMBER_FEDERATED_ANNOTATION_XML \
-	"<Annotations>"\
-		"<Annotation>"\
-			"<Name>MSN.IM.BuddyType</Name>"\
-			"<Value>%02d:</Value>"\
-		"</Annotation>"\
-	"</Annotations>"
-
 /* first delete contact from allow list */
 
 #define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--- a/libpurple/protocols/msn/notification.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/notification.c	Sat Mar 28 16:59:30 2009 +0000
@@ -630,7 +630,7 @@
 
 	} else {
 		purple_debug_error("msn",
-		                   "Got FQY update for unkwown user %s on network %d.\n",
+		                   "Got FQY update for unknown user %s on network %d.\n",
 		                   passport, network);
 	}
 }
@@ -686,6 +686,9 @@
 			if (++adl_count % 150 == 0) {
 				payload = xmlnode_to_str(adl_node, &payload_len);
 
+				/* ADL's are returned all-together */
+				session->adl_fqy++;
+
 				msn_notification_post_adl(session->notification->cmdproc,
 					payload, payload_len);
 
@@ -697,6 +700,9 @@
 				xmlnode_set_attrib(adl_node, "l", "1");
 			}
 		} else {
+			/* FQY's are returned one-at-a-time */
+			session->adl_fqy++;
+
 			msn_add_contact_xml(session, fqy_node, user->passport,
 				0, user->networkid);
 
@@ -718,6 +724,9 @@
 	if (adl_count == 0 || adl_count % 150 != 0) {
 		payload = xmlnode_to_str(adl_node, &payload_len);
 
+		/* ADL's are returned all-together */
+		session->adl_fqy++;
+
 		msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
 
 		g_free(payload);
@@ -804,7 +813,8 @@
 
 	if (!strcmp(cmd->params[1], "OK")) {
 		/* ADL ack */
-		msn_session_finish_login(session);
+		if (--session->adl_fqy == 0)
+			msn_session_finish_login(session);
 	} else {
 		cmdproc->last_cmd->payload_cb = adl_cmd_parse;
 		cmd->payload_len = atoi(cmd->params[1]);
@@ -1609,7 +1619,7 @@
 
 	if ( (root = xmlnode_from_str(cmd->payload, cmd->payload_len)) == NULL)
 	{
-		purple_debug_error("msn", "Unable to parse GCF payload into a XML tree");
+		purple_debug_error("msn", "Unable to parse GCF payload into a XML tree\n");
 		return;
 	}
 
@@ -1682,7 +1692,7 @@
 	user = msn_userlist_find_user(session->userlist, passport);
 	if (user == NULL) {
 		char *str = g_strndup(payload, len);
-		purple_debug_info("msn", "unknown user %s, payload is %s",
+		purple_debug_info("msn", "unknown user %s, payload is %s\n",
 			passport, str);
 		g_free(str);
 		return;
--- a/libpurple/protocols/msn/oim.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/oim.c	Sat Mar 28 16:59:30 2009 +0000
@@ -174,7 +174,7 @@
 		gchar *faultcode_str = xmlnode_get_data(faultcode);
 
 		if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
-			purple_debug_warning("msn", "OIM Request Error, Updating token now.");
+			purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
 			msn_nexus_update_token(data->oim->session->nexus,
 				data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
 				(GSourceFunc)msn_oim_request_helper, data);
@@ -183,7 +183,7 @@
 
 		} else if (faultcode_str && g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
 			if (xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL) {
-				purple_debug_warning("msn", "OIM Request Error, Updating token now.");
+				purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
 				msn_nexus_update_token(data->oim->session->nexus,
 					data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
 					(GSourceFunc)msn_oim_request_helper, data);
--- a/libpurple/protocols/msn/session.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/session.h	Sat Mar 28 16:59:30 2009 +0000
@@ -90,6 +90,7 @@
 
 	gboolean connected;
 	gboolean logged_in; /**< A temporal flag to ignore local buddy list adds. */
+	int      adl_fqy; /**< A count of ADL/FQY so status is only changed once. */
 	gboolean destroying; /**< A flag that states if the session is being destroyed. */
 	gboolean http_method;
 
--- a/libpurple/protocols/msn/state.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/state.c	Sat Mar 28 16:59:30 2009 +0000
@@ -169,7 +169,7 @@
 	}
 	currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
 	if (currentmediaNode == NULL) {
-		purple_debug_info("msn", "No CurrentMedia Node");
+		purple_debug_info("msn", "No CurrentMedia Node\n");
 		xmlnode_free(payloadNode);
 		return NULL;
 	}
@@ -195,7 +195,7 @@
 	}
 	psmNode = xmlnode_get_child(payloadNode, "PSM");
 	if (psmNode == NULL) {
-		purple_debug_info("msn", "No PSM status Node");
+		purple_debug_info("msn", "No PSM status Node\n");
 		xmlnode_free(payloadNode);
 		return NULL;
 	}
--- a/libpurple/protocols/msn/switchboard.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Sat Mar 28 16:59:30 2009 +0000
@@ -590,7 +590,7 @@
 	payload = msn_message_gen_payload(msg, &payload_len);
 
 #ifdef MSN_DEBUG_SB
-	purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}", payload_len);
+	purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len);
 	msn_message_show_readable(msg, "SB SEND", FALSE);
 #endif
 
--- a/libpurple/protocols/msn/userlist.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/msn/userlist.c	Sat Mar 28 16:59:30 2009 +0000
@@ -858,7 +858,7 @@
 	}
 
 	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!", who);
+		purple_debug_error("msn", "User %s not found!\n", who);
 		return FALSE;
 	}
 
@@ -887,7 +887,7 @@
 	}
 
 	if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-		purple_debug_error("msn", "User %s not found!", who);
+		purple_debug_error("msn", "User %s not found!\n", who);
 		return FALSE;
 	}
 
--- a/libpurple/protocols/myspace/myspace.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Sat Mar 28 16:59:30 2009 +0000
@@ -388,7 +388,7 @@
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	account = purple_buddy_get_account(buddy);
 	gc = purple_account_get_connection(account);
@@ -436,7 +436,7 @@
 	g_return_if_fail(buddy != NULL);
 	g_return_if_fail(user_info != NULL);
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
 		MsimSession *session;
@@ -1053,7 +1053,7 @@
 	g_free(display_name);
 
 	/* 3. Update buddy information */
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	user->id = uid;
 	/* Keep track of the user ID across sessions */
@@ -1377,7 +1377,7 @@
 		buddy = purple_buddy_new(session->account, username, NULL);
 		purple_blist_add_buddy(buddy, NULL, NULL, NULL);
 
-		user = msim_get_user_from_buddy(buddy);
+		user = msim_get_user_from_buddy(buddy, TRUE);
 		user->id = msim_msg_get_integer(msg, "f");
 
 		/* Keep track of the user ID across sessions */
@@ -2641,6 +2641,9 @@
 	name = purple_buddy_get_name(buddy);
 	gname = group ? purple_group_get_name(group) : NULL;
 
+	if (msim_get_user_from_buddy(buddy, FALSE) != NULL)
+		return;
+
 	purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n",
 			name, gname ? gname : "(no group)");
 
--- a/libpurple/protocols/myspace/user.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/myspace/user.c	Sat Mar 28 16:59:30 2009 +0000
@@ -41,10 +41,10 @@
 }
 
 /**
- * Get the MsimUser from a PurpleBuddy, creating it if needed.
+ * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
  */
 MsimUser *
-msim_get_user_from_buddy(PurpleBuddy *buddy)
+msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
 {
 	MsimUser *user;
 
@@ -52,7 +52,8 @@
 		return NULL;
 	}
 
-	if (!(user = purple_buddy_get_protocol_data(buddy))) {
+	user = purple_buddy_get_protocol_data(buddy);
+	if (create && !user) {
 		/* No MsimUser for this buddy; make one. */
 
 		user = g_new0(MsimUser, 1);
@@ -94,7 +95,7 @@
 		return NULL;
 	}
 
-	user = msim_get_user_from_buddy(buddy);
+	user = msim_get_user_from_buddy(buddy, TRUE);
 
 	return user;
 }
--- a/libpurple/protocols/myspace/user.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/myspace/user.h	Sat Mar 28 16:59:30 2009 +0000
@@ -46,7 +46,7 @@
  * initiated from a user lookup. */
 typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, const MsimMessage *userinfo, gpointer data);
 
-MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy);
+MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create);
 void msim_user_free(MsimUser *user);
 MsimUser *msim_find_user(MsimSession *session, const gchar *username);
 void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
--- a/libpurple/protocols/novell/nmmessage.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/novell/nmmessage.c	Sat Mar 28 16:59:30 2009 +0000
@@ -24,7 +24,6 @@
 {
 	NMConference *conference;
 	char *text;
-	gpointer data;
 	guint32 ref_count;
 };
 
--- a/libpurple/protocols/novell/novell.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/novell/novell.c	Sat Mar 28 16:59:30 2009 +0000
@@ -2547,7 +2547,7 @@
 	if (gc == NULL || buddy == NULL || group == NULL)
 		return;
 
-	user = (NMUser *) gc->proto_data;
+	user = (NMUser *) purple_connection_get_protocol_data(gc);
 	if (user == NULL)
 		return;
 
@@ -2557,6 +2557,10 @@
 	if (!user->clist_synched)
 		return;
 
+	/* Don't re-add a buddy that is already on our contact list */
+	if (nm_find_user_record(user, purple_buddy_get_name(buddy)) != NULL)
+		return;
+
 	contact = nm_create_contact();
 	nm_contact_set_dn(contact, purple_buddy_get_name(buddy));
 
--- a/libpurple/protocols/oscar/oscar.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Sat Mar 28 16:59:30 2009 +0000
@@ -870,11 +870,11 @@
 		if (itmsurl) {
 			tmp = g_strdup_printf("<a href=\"%s\">%s</a>",
 								  itmsurl, message);
-			g_free(itmsurl);
 			g_free(message);
 			message = tmp;
 		}
 	}
+	g_free(itmsurl);
 
 	if (is_away && message) {
 		tmp = purple_str_sub_away_formatters(message, purple_account_get_username(account));
@@ -4917,17 +4917,24 @@
 		return;
 	}
 
-	if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))) {
-		purple_debug_info("oscar",
-				   "ssi: adding buddy %s to group %s\n", bname, gname);
-		aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
-
-		/* Mobile users should always be online */
-		if (bname[0] == '+') {
-			purple_prpl_got_user_status(account,
-					bname, OSCAR_STATUS_ID_AVAILABLE, NULL);
-			purple_prpl_got_user_status(account,
-					bname, OSCAR_STATUS_ID_MOBILE, NULL);
+	if (od->ssi.received_data) {
+		if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
+			purple_debug_info("oscar",
+					   "ssi: adding buddy %s to group %s\n", bname, gname);
+			aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+
+			/* Mobile users should always be online */
+			if (bname[0] == '+') {
+				purple_prpl_got_user_status(account, bname,
+						OSCAR_STATUS_ID_AVAILABLE, NULL);
+				purple_prpl_got_user_status(account, bname,
+						OSCAR_STATUS_ID_MOBILE, NULL);
+			}
+		} else if (aim_ssi_waitingforauth(od->ssi.local,
+		                                  aim_ssi_itemlist_findparentname(od->ssi.local, bname),
+		                                  bname)) {
+			/* Not authorized -- Re-request authorization */
+			purple_auth_sendrequest(gc, bname);
 		}
 	}
 
--- a/libpurple/protocols/qq/buddy_list.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/qq/buddy_list.c	Sat Mar 28 16:59:30 2009 +0000
@@ -47,7 +47,6 @@
 #define QQ_GET_ONLINE_BUDDY_03          0x03	/* unknown function */
 
 typedef struct _qq_buddy_online {
-	qq_buddy_status bs;
 	guint16 unknown1;
 	guint8 ext_flag;
 	guint8 comm_flag;
--- a/libpurple/protocols/silc/buddy.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/silc/buddy.c	Sat Mar 28 16:59:30 2009 +0000
@@ -1397,7 +1397,12 @@
 
 void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	silcpurple_add_buddy_i(gc, buddy, FALSE);
+	/* Don't add if the buddy is already on the list.
+	 *
+	 * SILC doesn't have groups, so we also don't need to do anything
+	 * for a move. */
+	if (purple_buddy_get_protocol_data(buddy) == NULL)
+		silcpurple_add_buddy_i(gc, buddy, FALSE);
 }
 
 void silcpurple_send_buddylist(PurpleConnection *gc)
--- a/libpurple/protocols/silc10/buddy.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Sat Mar 28 16:59:30 2009 +0000
@@ -1390,7 +1390,12 @@
 
 void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
-	silcpurple_add_buddy_i(gc, buddy, FALSE);
+	/* Don't add if the buddy is already on the list.
+	 *
+	 * SILC doesn't have groups, so we don't need to do anything
+	 * for a move. */
+	if (purple_buddy_get_protocol_data(buddy) == NULL)
+		silcpurple_add_buddy_i(gc, buddy, FALSE);
 }
 
 void silcpurple_send_buddylist(PurpleConnection *gc)
--- a/libpurple/protocols/toc/Makefile.am	Mon Mar 16 21:45:24 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-EXTRA_DIST = \
-	PROTOCOL \
-	Makefile.mingw
-
-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
-
-TOCSOURCES = toc.c
-
-AM_CFLAGS = $(st)
-
-libtoc_la_LDFLAGS = -module -avoid-version
-
-if STATIC_TOC
-
-st = -DPURPLE_STATIC_PRPL
-noinst_LTLIBRARIES = libtoc.la
-libtoc_la_SOURCES  = $(TOCSOURCES)
-libtoc_la_CFLAGS   = $(AM_CFLAGS)
-
-else
-
-st =
-pkg_LTLIBRARIES   = libtoc.la
-libtoc_la_SOURCES = $(TOCSOURCES)
-
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/libpurple \
-	-I$(top_builddir)/libpurple \
-	$(GLIB_CFLAGS) \
-	$(DEBUG_CFLAGS)
--- a/libpurple/protocols/toc/Makefile.mingw	Mon Mar 16 21:45:24 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-#
-# Makefile.mingw
-#
-# Description: Makefile for win32 (mingw) version of libtoc
-#
-
-PIDGIN_TREE_TOP := ../../..
-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
-
-TARGET = libtoc
-TYPE = PLUGIN
-
-# Static or Plugin...
-ifeq ($(TYPE),STATIC)
-  DEFINES += -DSTATIC
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
-else
-ifeq ($(TYPE),PLUGIN)
-  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
-endif
-endif
-
-##
-## INCLUDE PATHS
-##
-INCLUDE_PATHS +=	-I$(TOC_ROOT) \
-			-I$(GTK_TOP)/include \
-			-I$(GTK_TOP)/include/glib-2.0 \
-			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(LIBPIDGIN_TREE_TOP) \
-			-I$(LIBPIDGIN_TREE_TOP)/win32 \
-			-I$(PIDGIN_TREE_TOP)
-
-LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(LIBPIDGIN_TREE_TOP)
-
-##
-##  SOURCES, OBJECTS
-##
-C_SRC =			toc.c
-
-OBJECTS = $(C_SRC:%.c=%.o)
-
-##
-## LIBRARIES
-##
-LIBS =	\
-			-lglib-2.0 \
-			-lws2_32 \
-			-lintl \
-			-lpurple
-
-include $(PIDGIN_COMMON_RULES)
-
-##
-## TARGET DEFINITIONS
-##
-
-.PHONY: all install clean
-
-all: $(TARGET).dll
-
-install: all $(DLL_INSTALL_DIR)
-	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-
-$(OBJECTS): $(PURPLE_CONFIG_H)
-
-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
-
-##
-## CLEAN RULES
-##
-clean:
-	rm -f $(OBJECTS)
-	rm -f $(TARGET).dll
-
-include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/protocols/toc/PROTOCOL	Mon Mar 16 21:45:24 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,499 +0,0 @@
-# Copyright (c) 1998-9 America Online, Inc. All Rights Reserved.
-#
-#   This program is free software; you can redistribute it and/or
-#   modify it under the terms of the GNU General Public License
-#   as published by the Free Software Foundation; either version 2
-#   of the License, or (at your option) any later version.
-#
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License
-#   along with this program; if not, write to the Free Software
-#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301, USA.
-
-# Note from Jim Duchek, former libpurple maintainer -- this may not be
-# the latest version of this document, I provide it as a service.
-# Download a copy of TiK (http://www.aim.aol.com/tik/) for the latest
-# version of this doc.
-
-# Note from Eric Warmenhoven, random guy -- this appears to be the last
-# published version of the protocol, and AOL has stopped hosting the TiK
-# program. TiK is still being maintained and is hosted on sourceforge.net;
-# this appears to be the same version of the protocol they're using.
-
-Version: TOC1.0
-
-This document describes the protocol between TOC and TOC clients.
-The protocol is built on TCP.  Framing is done by SFLAP,
-described at the bottom of this document.  Inside each
-SFLAP frame is a TOC command.
-
-The TOC protocol is ASCII based, and special attention
-must be placed argument separation.  The separator and 
-the rules of separation are different for messages inbound 
-to TOC and outbound to the client.  The rules of separation
-are described in sections below.
-
-The TOC server is built mainly to service the TIC and TiK clients.  Since
-the TIC client is a Java applet, and downloadable, TOC will NOT support
-multiple TOC protocol versions at the same time.   Therefore, TiK
-users will be forced to upgrade if the protocol version changes.  
-TOC sends down the protocol version it expects the client
-to speak and understand.  Note, the protocol version is a string.
-
-Important Notes
-===============
-* TOC will drop the connection if a command exceeds the maximum
-  length, which is currently 2048 bytes.  So the client needs to 
-  spend special attention to im, chat, and config message lengths.
-  There is an 8k length maximum from TOC to the client.
-
-* No commands should be sent to TOC (besides toc_signon) before 
-  a SIGN_ON is received.  If you do send a command before SIGN_ON
-  the command will be ignored, and in some case the connection
-  will be dropped.
-
-* Initial permit/deny items should be sent after receiving SIGN_ON 
-  but before sending toc_init_done, otherwise the user will flash
-  on peoples buddylist who the user has denied.  You will probably
-  want to send the toc_add_buddies at this time also.
-
-* After TOC sends the PAUSE message to a client, all messages sent 
-  to TOC will be ignored, and in some cases the connection will 
-  be dropped.  Another SIGN_ON message will be sent to the client 
-  when it is online again.  The buddy list and permit/deny items must 
-  be sent again, followed by the toc_init_done.  In most cases the 
-  SIGN_ON message will be sent between 1-2 seconds after the 
-  PAUSE message.  Therefore a client could choose to ignore the 
-  PAUSE message and hope nothing bad happens.
-
-
-Client -> TOC
-==============
-The commands and the arguments are usually separated by whitespaces.  Arguments
-with whitespace characters should be enclosed in quotes.  Dollar signs, 
-curly brackets, square brackets, parentheses, quotes, and backslashes 
-must all be backslashed whether in quotes or not.  It is usually 
-a good idea just to use quotes no matter what.  All user names from clients 
-to TOC should be normalized (spaces removed and lowercased), and therefore
-are the one exception to the always use quotes rule.
-
-When sending commands to the server you will not get a response
-back confirming that the command format was correct or not!  However
-in some cases if the command format was incorrect the connection
-will be dropped.
-
-
-RoastingString="Tic/Toc"
-
-toc_signon <authorizer host> <authorizer port> <User Name> <Password> 
-           <language> <version>
-    The password needs to be roasted with the Roasting String if
-    coming over a FLAP connection, CP connections don't use
-    roasted passwords.  The language specified will be used
-    when generating web pages, such as the get info pages.
-    Currently the only supported language is "english".
-    If the language sent isn't found, the default "english"
-    language will be used.  The version string will be used
-    for the client identity, and must be less then 50
-    characters.
-
-    Passwords are roasted when sent to the host.  This is done so they 
-    aren't sent in "clear text" over the wire, although they are still 
-    trivial to decode.  Roasting is performed by first xoring each byte 
-    in the password with the equivalent modulo byte in the roasting 
-    string.  The result is then converted to ascii hex, and prepended 
-    with "0x".  So for example the password "password" roasts to 
-    "0x2408105c23001130"
-
-toc_init_done
-    Tells TOC that we are ready to go online.  TOC clients should first 
-    send TOC the buddy list and any permit/deny lists.  However toc_init_done
-    must be called within 30 seconds after toc_signon, or the connection
-    will be dropped.  Remember, it can't be called until after the SIGN_ON
-    message is received.  Calling this before or multiple times after a
-    SIGN_ON will cause the connection to be dropped.
-
-toc_send_im <Destination User> <Message> [auto]
-    Send a message to a remote user.  Remember to quote and encode the 
-    message.  If the optional string "auto" is the last argument, then the 
-    auto response flag will be turned on for the im. 
-
-toc_add_buddy <Buddy User 1> [<Buddy User2> [<Buddy User 3> [...]]]
-    Add buddies to your buddy list.  This does not change your
-    saved config.
-
-toc_remove_buddy <Buddy User 1> [<Buddy User2> [<Buddy User 3> [...]]]
-    Remove buddies from your buddy list.  This does not change your
-    saved config.
-
-toc_set_config <Config Info>
-    Set the config information for this user.  The config information
-    is line oriented with the first character being the item type,
-    followed by a space, with the rest of the line being the item
-    value.  Only letters, numbers, and spaces should be used.  Remember
-    you will have to enclose the entire config in quotes.
-
-    Item Types:
-    g - Buddy Group (All Buddies until the next g or the end of config 
-		     are in this group.)
-    b - A Buddy 
-    p - Person on permit list
-    d - Person on deny list
-    m - Permit/Deny Mode.  Possible values are
-	1 - Permit All
-	2 - Deny All
-	3 - Permit Some
-	4 - Deny Some
-
-toc_evil <User> <norm|anon>
-    Evil/Warn someone else.  The 2nd argument is either the string
-    "norm" for a normal warning, or "anon" for an anonymous 
-    warning.  You can only evil people who have recently sent you
-    ims.  The higher someones evil level, the slower they can
-    send message.
-
-toc_add_permit [ <User 1> [<User 2> [...]]]
-    ADD the following people to your permit mode.  If
-    you are in deny mode it will switch you to permit
-    mode first.  With no arguments and in deny mode
-    this will switch you to permit none. If already
-    in permit mode, no arguments does nothing
-    and your permit list remains the same.
-
-toc_add_deny [ <User 1> [<User 2> [...]]]
-    ADD the following people to your deny mode. If
-    you are in permit mode it will switch you to
-    deny mode first.  With no arguments and in permit
-    mode, this will switch you to deny none. If
-    already in deny mode, no arguments does nothing
-    and your deny list remains unchanged.
-
-toc_chat_join <Exchange> <Chat Room Name>
-    Join a chat room in the given exchange.  Exchange is
-    an integer that represents a group of chat rooms.
-    Different exchanges have different properties.  For
-    example some exchanges might have room replication (ie
-    a room never fills up, there are just multiple
-    instances.) and some exchanges might have navigational
-    information, and some exchanges might have ...  Currently
-    exchange should always be 4, however this may
-    change in the future.  You will either
-    receive an ERROR if the room couldn't be joined
-    or a CHAT_JOIN message.  The Chat Room Name
-    is case insensitive and consecutive spaces
-    are removed.
-
-toc_chat_send <Chat Room ID> <Message>
-    Send a message in a chat room using the chat room
-    id from CHAT_JOIN.  Since reflection is always on in
-    TOC, you do not need to add the message to your chat UI,
-    since you will get a CHAT_IN with the message.  
-    Remember to quote and encode the message.
-
-toc_chat_whisper <Chat Room ID> <dst_user> <Message>
-    Send a message in a chat room using the chat room
-    id from CHAT_JOIN.  This message is directed at
-    only one person.  (Currently you DO need to add this to
-    your UI.)  Remember to quote and encode the message.  
-    Chat whispering is different from IMs since it is linked
-    to a chat room, and should usually be displayed in the chat
-    room UI.
-
-toc_chat_evil <Chat Room ID> <User> <norm|anon>
-    Evil/Warn someone else inside a chat room.  The 3rd argument is either 
-    the string "norm" for a normal warning, or "anon" for an anonymous 
-    warning.  Currently chat evil is not turned on in the chat complex.
-
-toc_chat_invite <Chat Room ID> <Invite Msg> <buddy1> [<buddy2> [<buddy3> [...]]]
-    Once you are inside a chat room you can invite other people into
-    that room.  Remember to quote and encode the invite message.
-
-toc_chat_leave <Chat Room ID>
-    Leave the chat room.
-
-toc_chat_accept <Chat Room ID>
-    Accept a CHAT_INVITE message from TOC.  The server will send a
-    CHAT_JOIN in response.
-
-toc_get_info <username>
-    Gets a user's info a GOTO_URL or ERROR message will be sent back to the 
-    client.
-
-toc_set_info <info information>
-    Set the LOCATE user information.  This is basic HTML.
-    Remember to encode the info.
-
-toc_set_away [<away message>]
-    if the away message is present, then the unavailable
-    status flag is set for the user.  If the away message
-    is not present, then the unavailable status flag is
-    unset.  The away message is basic HTML, remember to
-    encode the information.
-
-toc_get_dir <username>
-    Gets a user's dir info a GOTO_URL or ERROR message will be sent back to the 
-    client.
-
-toc_set_dir <info information>
-    Set the DIR user information.  This is a colon separated fields as in:
-    "first name":"middle name":"last name":"maiden name":"city":"state":"country":"email":"allow web searches"
-    Should return a DIR_STATUS msg.  Having anything in the "allow web searches"
-    field allows people to use web-searches to find your directory info.
-    Otherwise, they'd have to use the client.  
-
-toc_dir_search <info information>
-    Perform a search of the Oscar Directory, using colon separated fields as in:
-    "first name":"middle name":"last name":"maiden name":"city":"state":"country":"email"
-    Returns either a GOTO_URL or ERROR msg.  
-
-toc_set_idle <idle secs>
-    Set idle information. If <idle secs> is 0 then the user isn't idle at all.
-    If <idle secs> is greater then 0 then the user has already been idle
-    for <idle secs> number of seconds.  The server will automatically
-    keep incrementing this number, so do not repeatedly call with new
-    idle times.
-
-toc_set_caps [ <Capability 1> [<Capability 2> [...]]]
-    Set my capabilities.  All capabilities that we support need to
-    be sent at the same time.  Capabilities are represented by
-    UUIDs.  
-
-toc_rvous_propose  - Not Implemented Yet
-
-toc_rvous_accept <nick> <cookie> <service> <tlvlist>
-    Accept a rendezvous proposal from the user <nick>.
-    <cookie> is the cookie from the RVOUS_PROPOSE
-    message.  <service> is the UUID the proposal was
-    for. <tlvlist> contains a list of tlv tags followed by
-    base64 encoded values.
-
-toc_rvous_cancel <nick> <cookie> <service> <tlvlist>
-    Cancel a rendezvous proposal from the user <nick>.
-    <cookie> is the cookie from the RVOUS_PROPOSE
-    message.  <service> is the UUID the proposal was
-    for. <tlvlist> contains a list of tlv tags followed by
-    base64 encoded values.
-
-toc_format_nickname <new_format>
-    Reformat a user's nickname.  An ADMIN_NICK_STATUS or ERROR message will 
-    be sent back to the client.
-
-toc_change_passwd <existing_passwd new_passwd>
-    Change a user's password.  An ADMIN_PASSWD_STATUS or ERROR message will 
-    be sent back to the client.
-
-
-TOC -> Client
-==============
-All user names from TOC to client are NOT normalized, and are
-sent as they should be displayed.  String are NOT encoded, instead
-we use colons as separators.  So that you can have colons inside
-of messages, everything after the colon before :<Message> should
-be considered part of the message (ie don't just "split" on colons,
-instead split with a max number of results.)
-
-
-SIGN_ON:<Client Version Supported>
-   This is sent after a successful toc_signon command is sent to TOC.
-   If the command was unsuccessful either the FLAP connection will
-   be dropped or you will receive a ERROR message.
-
-CONFIG:<config>
-   A user's config. Config can be empty in which case the host was not able to
-   retrieve it, or a config didn't exist for the user.  See toc_set_config
-   above for the format.
-
-NICK:<Nickname>
-   Tells you your correct nickname (ie how it should be capitalized and
-   spacing)
-
-IM_IN:<Source User>:<Auto Response T/F?>:<Message>
-   Receive an IM from some one.  Everything after the third colon is
-   the incoming message, including other colons.
-
-UPDATE_BUDDY:<Buddy User>:<Online? T/F>:<Evil Amount>:<Signon Time>:<IdleTime>:<UC>
-   This one command handles arrival/depart/updates.  Evil Amount is
-   a percentage, Signon Time is UNIX epoc, idle time is in minutes, UC (User Class)
-   is a two/three character string.
-   uc[0]:
-   ' '  - Ignore
-   'A'  - On AOL
-   uc[1]
-   ' '  - Ignore
-   'A'  - Oscar Admin
-   'U'  - Oscar Unconfirmed
-   'O'  - Oscar Normal
-   uc[2] 
-   '\0' - Ignore
-   ' '  - Ignore
-   'U'  - The user has set their unavailable flag.
-
-
-
-ERROR:<Error Code>:Var args
-   * General Errors *
-   901   - $1 not currently available
-   902   - Warning of $1 not currently available
-   903   - A message has been dropped, you are exceeding
-	   the server speed limit
-
-   * Admin Errors  *
-   911   - Error validating input
-   912   - Invalid account
-   913   - Error encountered while processing request
-   914   - Service unavailable
-
-   * Chat Errors  *
-   950   - Chat in $1 is unavailable.
-
-   * IM & Info Errors *
-   960   - You are sending message too fast to $1
-   961   - You missed an im from $1 because it was too big.
-   962   - You missed an im from $1 because it was sent too fast.
-
-   * Dir Errors *
-   970   - Failure
-   971   - Too many matches
-   972   - Need more qualifiers
-   973   - Dir service temporarily unavailable
-   974   - Email lookup restricted
-   975   - Keyword Ignored
-   976   - No Keywords
-   977   - Language not supported
-   978   - Country not supported
-   979   - Failure unknown $1
-
-   * Auth errors *
-   980   - Incorrect nickname or password.
-   981   - The service is temporarily unavailable.
-   982   - Your warning level is currently too high to sign on.
-   983   - You have been connecting and
-	   disconnecting too frequently.  Wait 10 minutes and try again.
-	   If you continue to try, you will need to wait even longer.
-   989   - An unknown signon error has occurred $1
-
-
-EVILED:<new evil>:<name of eviler, blank if anonymous>
-   The user was just eviled.
-
-CHAT_JOIN:<Chat Room Id>:<Chat Room Name>
-   We were able to join this chat room.  The Chat Room Id is
-   internal to TOC.
-
-CHAT_IN:<Chat Room Id>:<Source User>:<Whisper? T/F>:<Message>
-   A chat message was sent in a chat room.
-
-CHAT_UPDATE_BUDDY:<Chat Room Id>:<Inside? T/F>:<User 1>:<User 2>...
-   This one command handles arrival/departs from a chat room.  The
-   very first message of this type for each chat room contains the
-   users already in the room.
-
-CHAT_INVITE:<Chat Room Name>:<Chat Room Id>:<Invite Sender>:<Message>
-   We are being invited to a chat room.
-
-CHAT_LEFT:<Chat Room Id>
-   Tells tic connection to chat room has been dropped
-
-GOTO_URL:<Window Name>:<Url>
-   Goto a URL.  Window Name is the suggested internal name of the window
-   to use.  (Java supports this.) 
-
-DIR_STATUS:<Return Code>:<Optional args>
-   <Return Code> is always 0 for success status.
-
-ADMIN_NICK_STATUS:<Return Code>:<Optional args>
-   <Return Code> is always 0 for success status.
-
-ADMIN_PASSWD_STATUS:<Return Code>:<Optional args>
-   <Return Code> is always 0 for success status.
-   
-
-PAUSE
-   Tells TIC to pause so we can do migration
-
-RVOUS_PROPOSE:<user>:<uuid>:<cookie>:<seq>:<rip>:<pip>:<vip>:<port>
-              [:tlv tag1:tlv value1[:tlv tag2:tlv value2[:...]]]
-   Another user has proposed that we rendezvous with them to
-   perform the service specified by <uuid>.  They want us
-   to connect to them, we have their rendezvous ip, their 
-   proposer_ip, and their verified_ip. The tlv values are 
-   base64 encoded.
-
-Typical Signon Process
-======================
-Except for the section marked optional this is an sequential
-process.  Each line MUST occur before the following line.
-
-* Client connects to TOC
-* Client sends "FLAPON\r\n\r\n"
-* TOC sends Client FLAP SIGNON
-* Client sends TOC FLAP SIGNON
-* Client sends TOC "toc_signon" message
-* if login fails TOC drops client's connection
-  else TOC sends client SIGN_ON reply
-* if Client doesn't support version it drops the connection
-
-[BEGIN OPTIONAL]
-    * TOC sends Client CONFIG
-    * Client sends TOC permit/deny stuff
-    * Client sends TOC toc_add_buddy message
-[END OPTIONAL]
-
-* Client sends TOC toc_init_done message
-
-
-SFLAP Documentation
-===================
-SFLAP is pretty much a FLAP connection except the DATA frame payload is a null
-terminated string when traveling from client to host, it is NOT null
-terminated when traveling from host to client.  The FLAP Header is binary 
-data, and is in network byte order.  The data portion is at offset 6, after the
-header.  The sequence number is sequential in each direction.  So
-packets from the server to client have one sequence number, while
-the packets from the client to server have an independent
-increasing number.
-
-FLAP Header (6 bytes)
------------
-Offset   Size  Type
-0        1     ASTERISK (literal ASCII '*')
-1        1     Frame Type
-2        2     Sequence Number
-4        2     Data Length
-
-
-Valid Frame Type Values
------------------------
-1   SIGNON
-2   DATA
-3   ERROR     (Not used by TOC)
-4   SIGNOFF   (Not used by TOC)
-5   KEEP_ALIVE
-
-
-TOC SIGNON FRAME TYPE
----------------------
-Sequence Number contains the initial sequence number used in each direction.
-Data Length contains the payload length, with the payload described
-below.  The payload area is NOT null terminated.
-
-Host To Client:
-    4 byte FLAP version (1)
-
-Client To Host:  
-    4 byte FLAP version (1)
-    2 byte TLV Tag (1)
-    2 byte Normalized User Name Length
-    N byte Normalized User Name  (NOT null terminated)
-
-    
-TOC DATA FRAME TYPE
--------------------
-Sequence Number contains the next sequence number.
-Data Length is the length of the payload, including the null termination
-from client to host.
-
--- a/libpurple/protocols/toc/toc.c	Mon Mar 16 21:45:24 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2340 +0,0 @@
-/*
- * purple
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-#include "internal.h"
-
-#include "account.h"
-#include "accountopt.h"
-#include "conversation.h"
-#include "debug.h"
-#include "notify.h"
-#include "privacy.h"
-#include "proxy.h"
-#include "prpl.h"
-#include "request.h"
-#include "util.h"
-#include "version.h"
-
-static PurplePlugin *my_protocol = NULL;
-
-#define REVISION "penguin"
-
-#define TYPE_SIGNON    1
-#define TYPE_DATA      2
-#define TYPE_ERROR     3
-#define TYPE_SIGNOFF   4
-#define TYPE_KEEPALIVE 5
-
-#define FLAPON "FLAPON\r\n\r\n"
-#define ROAST "Tic/Toc"
-
-#define TOC_HOST "toc.oscar.aol.com"
-#define TOC_PORT 9898
-#define AUTH_HOST "login.oscar.aol.com"
-#define AUTH_PORT 5190
-#define LANGUAGE "english"
-
-#define STATE_OFFLINE 0
-#define STATE_FLAPON 1
-#define STATE_SIGNON_REQUEST 2
-#define STATE_ONLINE 3
-#define STATE_PAUSE 4
-
-#define VOICE_UID     "09461341-4C7F-11D1-8222-444553540000"
-#define FILE_SEND_UID "09461343-4C7F-11D1-8222-444553540000"
-#define IMAGE_UID     "09461345-4C7F-11D1-8222-444553540000"
-#define B_ICON_UID    "09461346-4C7F-11D1-8222-444553540000"
-#define STOCKS_UID    "09461347-4C7F-11D1-8222-444553540000"
-#define FILE_GET_UID  "09461348-4C7F-11D1-8222-444553540000"
-#define GAMES_UID     "0946134a-4C7F-11D1-8222-444553540000"
-
-#define UC_UNAVAILABLE	0x01
-#define UC_AOL			0x02
-#define UC_ADMIN		0x04
-#define UC_UNCONFIRMED	0x08
-#define UC_NORMAL		0x10
-#define UC_WIRELESS		0x20
-
-struct ft_request {
-	PurpleConnection *gc;
-	char *user;
-	char UID[2048];
-	char *cookie;
-	char *ip;
-	int port;
-	char *message;
-	char *filename;
-	int files;
-	int size;
-};
-
-struct buddy_icon {
-	guint32 hash;
-	guint32 len;
-	time_t time;
-	void *data;
-};
-
-struct toc_data {
-	int toc_fd;
-	char toc_ip[20];
-	int seqno;
-	int state;
-};
-
-struct sflap_hdr {
-	unsigned char ast;
-	unsigned char type;
-	unsigned short seqno;
-	unsigned short len;
-};
-
-struct signon {
-	unsigned int ver;
-	unsigned short tag;
-	unsigned short namelen;
-	char username[80];
-};
-
-/* constants to identify proto_opts */
-#define USEROPT_AUTH      0
-#define USEROPT_AUTHPORT  1
-
-#define TOC_CONNECT_STEPS 3
-
-static void toc_login_callback(gpointer, gint, const gchar *);
-static void toc_callback(gpointer, gint, PurpleInputCondition);
-
-/* ok. this function used to take username/password, and return 0 on success.
- * now, it takes username/password, and returns NULL on error or a new purple_connection
- * on success. */
-static void toc_login(PurpleAccount *account)
-{
-	PurpleConnection *gc;
-	struct toc_data *tdt;
-	char buf[80];
-
-	gc = purple_account_get_connection(account);
-	gc->proto_data = tdt = g_new0(struct toc_data, 1);
-	gc->flags |= PURPLE_CONNECTION_HTML;
-	gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
-
-	g_snprintf(buf, sizeof buf, _("Looking up %s"),
-			purple_account_get_string(account, "server", TOC_HOST));
-	purple_connection_update_progress(gc, buf, 0, TOC_CONNECT_STEPS);
-
-	purple_debug(PURPLE_DEBUG_INFO, "toc", "Client connects to TOC\n");
-	if (purple_proxy_connect(gc, account,
-				purple_account_get_string(account, "server", TOC_HOST),
-				purple_account_get_int(account, "port", TOC_PORT),
-				toc_login_callback, gc) != 0 || !account->gc) {
-		g_snprintf(buf, sizeof(buf), _("Connect to %s failed"),
-				purple_account_get_string(account, "server", TOC_HOST));
-		purple_connection_error(gc, buf);
-		return;
-	}
-}
-
-static void toc_login_callback(gpointer data, gint source, const gchar *error_message)
-{
-	PurpleConnection *gc = data;
-	struct toc_data *tdt;
-	char buf[80];
-	struct sockaddr_in name;
-	socklen_t namelen;
-
-	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
-		if (source >= 0)
-			close(source);
-		return;
-	}
-
-	tdt = gc->proto_data;
-
-	if (source == -1) {
-		/* we didn't successfully connect. tdt->toc_fd is valid here */
-		purple_connection_error(gc, _("Unable to connect."));
-		return;
-	}
-	tdt->toc_fd = source;
-
-	/*
-	 * Copy the IP that we're connected to.  We need this because "GOTO_URL"'s 
-	 * should open on the exact server we're connected to.  toc.oscar.aol.com 
-	 * doesn't work because that hostname resolves to multiple IP addresses.
-	 */
-	if (getpeername(tdt->toc_fd, (struct sockaddr *)&name, &namelen) == 0)
-		strncpy(tdt->toc_ip, inet_ntoa(name.sin_addr), sizeof(tdt->toc_ip));
-	else
-		strncpy(tdt->toc_ip, purple_account_get_string(gc->account, "server", TOC_HOST), sizeof(tdt->toc_ip));
-
-	purple_debug(PURPLE_DEBUG_INFO, "toc",
-			   "Client sends \"FLAPON\\r\\n\\r\\n\"\n");
-	if (write(tdt->toc_fd, FLAPON, strlen(FLAPON)) < 0) {
-		purple_connection_error(gc, _("Disconnected."));
-		return;
-	}
-	tdt->state = STATE_FLAPON;
-
-	/* i know a lot of people like to look at purple to see how TOC works. so i'll comment
-	 * on what this does. it's really simple. when there's data ready to be read from the
-	 * toc_fd file descriptor, toc_callback is called, with gc passed as its data arg. */
-	gc->inpa = purple_input_add(tdt->toc_fd, PURPLE_INPUT_READ, toc_callback, gc);
-
-	g_snprintf(buf, sizeof(buf), _("Signon: %s"), purple_account_get_username(gc->account));
-	purple_connection_update_progress(gc, buf, 1, TOC_CONNECT_STEPS);
-}
-
-static void toc_close(PurpleConnection *gc)
-{
-	if (gc->inpa > 0)
-		purple_input_remove(gc->inpa);
-	gc->inpa = 0;
-	close(((struct toc_data *)gc->proto_data)->toc_fd);
-	g_free(gc->proto_data);
-}
-
-static void toc_build_config(PurpleAccount *account, char *s, int len, gboolean show)
-{
-	PurpleBlistNode *gnode, *cnode, *bnode;
-	PurpleGroup *g;
-	PurpleBuddy *b;
-	GSList *plist = account->permit;
-	GSList *dlist = account->deny;
-
-	int pos = 0;
-
-	if (!account->perm_deny)
-		account->perm_deny = 1;
-
-	pos += g_snprintf(&s[pos], len - pos, "m %d\n", account->perm_deny);
-	for(gnode = purple_get_blist()->root; gnode && len > pos; gnode = gnode->next) {
-		g = (PurpleGroup *)gnode;
-		if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
-			continue;
-		if(purple_group_on_account(g, account)) {
-			pos += g_snprintf(&s[pos], len - pos, "g %s\n", g->name);
-			for(cnode = gnode->child; cnode; cnode = cnode->next) {
-				if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
-					continue;
-				for(bnode = gnode->child; bnode && len > pos; bnode = bnode->next) {
-					b = (PurpleBuddy *)bnode;
-					if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-						continue;
-					if(b->account == account) {
-						pos += g_snprintf(&s[pos], len - pos, "b %s%s%s\n",
-								b->name,
-								(show && b->alias) ? ":" : "",
-								(show && b->alias) ? b->alias : "");
-					}
-				}
-			}
-		}
-	}
-
-	while (len > pos && plist) {
-		pos += g_snprintf(&s[pos], len - pos, "p %s\n", (char *)plist->data);
-		plist = plist->next;
-	}
-
-	while (len > pos && dlist) {
-		pos += g_snprintf(&s[pos], len - pos, "d %s\n", (char *)dlist->data);
-		dlist = dlist->next;
-	}
-}
-
-static char *
-escape_message(const char *msg)
-{
-	char *ret;
-	int i, j;
-
-	if (!msg)
-		return NULL;
-
-	/* Calculate the length after escaping */
-	for (i=0, j=0; msg[i]; i++)
-		switch (msg[i]) {
-			case '$':
-			case '[':
-			case ']':
-			case '(':
-			case ')':
-				j++;
-			default:
-				j++;
-		}
-
-	/* Allocate a string */
-	ret = (char *)g_malloc((j+1) * sizeof(char));
-
-	/* Copy the string */
-	for (i=0, j=0; msg[i]; i++)
-		switch (msg[i]) {
-			case '$':
-			case '[':
-			case ']':
-			case '(':
-			case ')':
-				ret[j++] = '\\';
-			default:
-				ret[j++] = msg[i];
-			}
-	ret[j] = '\0';
-
-	return ret;
-}
-
-/*
- * Duplicates the input string, replacing each \n with a <BR>, and 
- * escaping a few other characters.
- */
-static char *
-escape_text(const char *msg)
-{
-	char *ret;
-	int i, j;
-
-	if (!msg)
-		return NULL;
-
-	/* Calculate the length after escaping */
-	for (i=0, j=0; msg[i]; i++)
-		switch (msg[i]) {
-			case '\n':
-				j += 4;
-				break;
-			case '{':
-			case '}':
-			case '\\':
-			case '"':
-				j += 1;
-			default:
-				j += 1;
-		}
-
-	/* Allocate a string */
-	ret = (char *)malloc((j+1) * sizeof(char));
-
-	/* Copy the string */
-	for (i=0, j=0; msg[i]; i++)
-		switch (msg[i]) {
-			case '\n':
-				ret[j++] = '<';
-				ret[j++] = 'B';
-				ret[j++] = 'R';
-				ret[j++] = '>';
-				break;
-			case '{':
-			case '}':
-			case '\\':
-			case '"':
-				ret[j++] = '\\';
-			default:
-				ret[j++] = msg[i];
-		}
-	ret[j] = '\0';
-
-	return ret;
-}
-
-static int sflap_send(PurpleConnection *gc, const char *buf, int olen, int type)
-{
-	struct toc_data *tdt = (struct toc_data *)gc->proto_data;
-	int len;
-	int slen = 0;
-	int ret;
-	struct sflap_hdr hdr;
-	char *escaped, *obuf;
-
-	if (tdt->state == STATE_PAUSE)
-		/* TOC has given us the PAUSE message; sending could cause a disconnect
-		 * so we just return here like everything went through fine */
-		return 0;
-
-	if (olen < 0) {
-		escaped = escape_message(buf);
-		len = strlen(escaped);
-	} else {
-		escaped = g_memdup(buf, olen);
-		len = olen;
-	}
-
-	/*
-	 * One _last_ 2048 check here!  This shouldn't ever
-	 * get hit though, hopefully.  If it gets hit on an IM
-	 * It'll lose the last " and the message won't go through,
-	 * but this'll stop a segfault.
-	 */
-	if (len > MSG_LEN) {
-		purple_debug(PURPLE_DEBUG_WARNING, "toc", "message too long, truncating\n");
-		escaped[MSG_LEN - 1] = '\0';
-		len = MSG_LEN;
-	}
-
-	if (olen < 0)
-		purple_debug(PURPLE_DEBUG_INFO, "toc", "C: %s\n", escaped);
-
-	hdr.ast = '*';
-	hdr.type = type;
-	hdr.seqno = htons(tdt->seqno++ & 0xffff);
-	hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1));
-
-	obuf = (char *)malloc((sizeof(hdr)+len+1) * sizeof(char));
-	memcpy(obuf, &hdr, sizeof(hdr));
-	slen += sizeof(hdr);
-
-	memcpy(&obuf[slen], escaped, len);
-	slen += len;
-
-	if (type != TYPE_SIGNON) {
-		obuf[slen] = '\0';
-		slen += 1;
-	}
-
-	ret = write(tdt->toc_fd, obuf, slen);
-	free(obuf);
-	g_free(escaped);
-
-	return ret;
-}
-
-static int toc_send_raw(PurpleConnection *gc, const char *buf, int len)
-{
-	return sflap_send(gc, buf, len, 2);
-}
-
-static int wait_reply(PurpleConnection *gc, char *buffer, size_t buflen)
-{
-	struct toc_data *tdt = (struct toc_data *)gc->proto_data;
-	struct sflap_hdr *hdr;
-	int ret;
-
-	if (read(tdt->toc_fd, buffer, sizeof(struct sflap_hdr)) < 0) {
-		purple_debug(PURPLE_DEBUG_ERROR, "toc", "Couldn't read flap header\n");
-		return -1;
-	}
-
-	hdr = (struct sflap_hdr *)buffer;
-
-	if (buflen < ntohs(hdr->len)) {
-		/* fake like there's a read error */
-		purple_debug(PURPLE_DEBUG_ERROR, "toc",
-				   "buffer too small (have %" G_GSIZE_FORMAT ", need %d)\n",
-				   buflen, ntohs(hdr->len));
-		return -1;
-	}
-
-	if (ntohs(hdr->len) > 0) {
-		int count = 0;
-		ret = 0;
-		do {
-			count += ret;
-			ret = read(tdt->toc_fd,
-				   buffer + sizeof(struct sflap_hdr) + count, ntohs(hdr->len) - count);
-		} while (count + ret < ntohs(hdr->len) && ret > 0);
-		buffer[sizeof(struct sflap_hdr) + count + ret] = '\0';
-		return ret;
-	} else
-		return 0;
-}
-
-static unsigned char *roast_password(const char *pass)
-{
-	/* Trivial "encryption" */
-	static unsigned char rp[256];
-	static char *roast = ROAST;
-	int pos = 2;
-	int x;
-	strcpy(rp, "0x");
-	for (x = 0; (x < 150) && pass[x]; x++)
-		pos += sprintf(&rp[pos], "%02x", pass[x] ^ roast[x % strlen(roast)]);
-	rp[pos] = '\0';
-	return rp;
-}
-
-static void toc_got_info(void *data, const char *url_text, size_t len)
-{
-	if (!url_text)
-		return;
-
-	purple_notify_formatted(data, NULL, _("Buddy Information"), NULL,
-						  url_text, NULL, NULL);
-}
-
-static char *show_error_message()
-{
-	int no = atoi(strtok(NULL, ":"));
-	char *w = strtok(NULL, ":");
-	static char buf[256];
-
-	switch(no) {
-		case 69:
-			g_snprintf(buf, sizeof(buf), _("Unable to write file %s."), w);
-			break;
-		case 169:
-			g_snprintf(buf, sizeof(buf), _("Unable to read file %s."), w);
-			break;
-		case 269:
-			g_snprintf(buf, sizeof(buf), _("Message too long, last %s bytes truncated."), w);
-			break;
-		case 901:
-			g_snprintf(buf, sizeof(buf), _("%s not currently logged in."), w);
-			break;
-		case 902:
-			g_snprintf(buf, sizeof(buf), _("Warning of %s not allowed."), w);
-			break;
-		case 903:
-			g_snprintf(buf, sizeof(buf), _("A message has been dropped, you are exceeding the server speed limit."));
-			break;
-		case 950:
-			g_snprintf(buf, sizeof(buf), _("Chat in %s is not available."), w);
-			break;
-		case 960:
-			g_snprintf(buf, sizeof(buf), _("You are sending messages too fast to %s."), w);
-			break;
-		case 961:
-			g_snprintf(buf, sizeof(buf), _("You missed an IM from %s because it was too big."), w);
-			break;
-		case 962:
-			g_snprintf(buf, sizeof(buf), _("You missed an IM from %s because it was sent too fast."), w);
-			break;
-		case 970:
-			g_snprintf(buf, sizeof(buf), _("Failure."));
-			break;
-		case 971:
-			g_snprintf(buf, sizeof(buf), _("Too many matches."));
-			break;
-		case 972:
-			g_snprintf(buf, sizeof(buf), _("Need more qualifiers."));
-			break;
-		case 973:
-			g_snprintf(buf, sizeof(buf), _("Dir service temporarily unavailable."));
-			break;
-		case 974:
-			g_snprintf(buf, sizeof(buf), _("Email lookup restricted."));
-			break;
-		case 975:
-			g_snprintf(buf, sizeof(buf), _("Keyword ignored."));
-			break;
-		case 976:
-			g_snprintf(buf, sizeof(buf), _("No keywords."));
-			break;
-		case 977:
-			g_snprintf(buf, sizeof(buf), _("User has no directory information."));
-			/* g_snprintf(buf, sizeof(buf), _("Language not supported.")); */
-			break;
-		case 978:
-			g_snprintf(buf, sizeof(buf), _("Country not supported."));
-			break;
-		case 979:
-			g_snprintf(buf, sizeof(buf), _("Failure unknown: %s."), w);
-			break;
-		case 980:
-			g_snprintf(buf, sizeof(buf), _("Incorrect username or password."));
-			break;
-		case 981:
-			g_snprintf(buf, sizeof(buf), _("The service is temporarily unavailable."));
-			break;
-		case 982:
-			g_snprintf(buf, sizeof(buf), _("Your warning level is currently too high to log in."));
-			break;
-		case 983:
-			g_snprintf(buf, sizeof(buf), _("You have been connecting and disconnecting too frequently.  Wait ten minutes and try again.  If you continue to try, you will need to wait even longer."));
-			break;
-			g_snprintf(buf, sizeof(buf), _("An unknown signon error has occurred: %s."), w);
-			break;
-		default:
-			g_snprintf(buf, sizeof(buf), _("An unknown error, %d, has occurred.  Info: %s"), no, w);
-	}
-
- return buf;
-}
-
-static void
-parse_toc_buddy_list(PurpleAccount *account, char *config)
-{
-	char *c;
-	char current[256];
-	GList *buddies = NULL;
-
-	if (config == NULL)
-		return;
-
-	/* skip "CONFIG:" (if it exists) */
-	c = strncmp(config + 6 /* sizeof(struct sflap_hdr) */ , "CONFIG:", strlen("CONFIG:")) ?
-		strtok(config, "\n") :
-		strtok(config + 6 /* sizeof(struct sflap_hdr) */  + strlen("CONFIG:"), "\n");
-	do {
-		if (c == NULL)
-			break;
-		if (*c == 'g') {
-			char *utf8 = NULL;
-			utf8 = purple_utf8_try_convert(c + 2);
-			if (utf8 == NULL) {
-				g_strlcpy(current, _("Invalid Groupname"), sizeof(current));
-			} else {
-				g_strlcpy(current, utf8, sizeof(current));
-				g_free(utf8);
-			}
-			if (!purple_find_group(current)) {
-				PurpleGroup *g = purple_group_new(current);
-				purple_blist_add_group(g, NULL);
-			}
-		} else if (*c == 'b') { /*&& !purple_find_buddy(user, c + 2)) {*/
-			char nm[80], sw[388], *a, *utf8 = NULL;
-
-			if ((a = strchr(c + 2, ':')) != NULL) {
-				*a++ = '\0';		/* nul the : */
-			}
-
-			g_strlcpy(nm, c + 2, sizeof(nm));
-			if (a) {
-				utf8 = purple_utf8_try_convert(a);
-				if (utf8 == NULL) {
-					purple_debug(PURPLE_DEBUG_ERROR, "toc blist",
-							   "Failed to convert alias for "
-							   "'%s' to UTF-8\n", nm);
-					}
-			}
-			if (utf8 == NULL) {
-				sw[0] = '\0';
-			} else {
-				/* This can leave a partial sequence at the end,
-				 * but who cares? */
-				g_strlcpy(sw, utf8, sizeof(sw));
-				g_free(utf8);
-			}
-
-			if (!purple_find_buddy(account, nm)) {
-				PurpleBuddy *b = purple_buddy_new(account, nm, sw);
-				PurpleGroup *g = purple_find_group(current);
-				purple_blist_add_buddy(b, NULL, g, NULL);
-				buddies = g_list_append(buddies, b);
-			}
-		} else if (*c == 'p') {
-			purple_privacy_permit_add(account, c + 2, TRUE);
-		} else if (*c == 'd') {
-			purple_privacy_deny_add(account, c + 2, TRUE);
-		} else if (!strncmp("toc", c, 3)) {
-			sscanf(c + strlen(c) - 1, "%d", &account->perm_deny);
-			purple_debug(PURPLE_DEBUG_MISC, "toc blist",
-					   "permdeny: %d\n", account->perm_deny);
-			if (account->perm_deny == 0)
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
-		} else if (*c == 'm') {
-			sscanf(c + 2, "%d", &account->perm_deny);
-			purple_debug(PURPLE_DEBUG_MISC, "toc blist",
-					   "permdeny: %d\n", account->perm_deny);
-			if (account->perm_deny == 0)
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
-		}
-	} while ((c = strtok(NULL, "\n")));
-
-	if (account->gc) {
-		if (buddies != NULL) {
-			purple_account_add_buddies(account, buddies);
-			g_list_free(buddies);
-		}
-		serv_set_permit_deny(account->gc);
-	}
-	g_list_free(buddies);
-}
-
-static void toc_callback(gpointer data, gint source, PurpleInputCondition condition)
-{
-	PurpleConnection *gc = (PurpleConnection *)data;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	struct toc_data *tdt = (struct toc_data *)gc->proto_data;
-	struct sflap_hdr *hdr;
-	struct signon so;
-	char buf[8 * 1024], *c;
-	char snd[BUF_LEN * 2];
-	const char *username = purple_account_get_username(account);
-	char *password;
-	PurpleBuddy *buddy;
-
-	/* there's data waiting to be read, so read it. */
-	if (wait_reply(gc, buf, 8 * 1024) <= 0) {
-		purple_connection_error(gc, _("Connection Closed"));
-		return;
-	}
-
-	if (tdt->state == STATE_FLAPON) {
-		hdr = (struct sflap_hdr *)buf;
-		if (hdr->type != TYPE_SIGNON)
-			purple_debug(PURPLE_DEBUG_ERROR, "toc", "hdr->type != TYPE_SIGNON\n");
-		else
-			purple_debug(PURPLE_DEBUG_INFO, "toc",
-					   "TOC sends Client FLAP SIGNON\n");
-		tdt->seqno = ntohs(hdr->seqno);
-		tdt->state = STATE_SIGNON_REQUEST;
-
-		purple_debug(PURPLE_DEBUG_INFO, "toc", "Client sends TOC FLAP SIGNON\n");
-		g_snprintf(so.username, sizeof(so.username), "%s", username);
-		so.ver = htonl(1);
-		so.tag = htons(1);
-		so.namelen = htons(strlen(so.username));
-		if (sflap_send(gc, (char *)&so, ntohs(so.namelen) + 8, TYPE_SIGNON) < 0) {
-			purple_connection_error(gc, _("Disconnected."));
-			return;
-		}
-
-		purple_debug(PURPLE_DEBUG_INFO, "toc",
-				   "Client sends TOC \"toc_signon\" message\n");
-		/* i hate icq. */
-		if (username[0] >= '0' && username[0] <= '9')
-			password = g_strndup(purple_connection_get_password(gc), 8);
-		else
-			password = g_strdup(purple_connection_get_password(gc));
-		g_snprintf(snd, sizeof snd, "toc_signon %s %d  %s %s %s \"%s\"",
-			   AUTH_HOST, AUTH_PORT, purple_normalize(account, username),
-			   roast_password(password), LANGUAGE, REVISION);
-		g_free(password);
-		if (sflap_send(gc, snd, -1, TYPE_DATA) < 0) {
-			purple_connection_error(gc, _("Disconnected."));
-			return;
-		}
-
-		purple_connection_update_progress(gc, _("Waiting for reply..."), 2, TOC_CONNECT_STEPS);
-		return;
-	}
-
-	if (tdt->state == STATE_SIGNON_REQUEST) {
-		purple_debug(PURPLE_DEBUG_INFO, "toc", "TOC sends client SIGN_ON reply\n");
-		if (g_ascii_strncasecmp(buf + sizeof(struct sflap_hdr), "SIGN_ON", strlen("SIGN_ON"))) {
-			purple_debug(PURPLE_DEBUG_ERROR, "toc",
-					   "Didn't get SIGN_ON! buf was: %s\n",
-				     buf + sizeof(struct sflap_hdr));
-			if (!g_ascii_strncasecmp(buf + sizeof(struct sflap_hdr), "ERROR", 5)) {
-				strtok(buf + sizeof(struct sflap_hdr), ":");
-				purple_connection_error(gc, show_error_message());
-			} else
-				purple_connection_error(gc, _("Authentication failed"));
-			return;
-		}
-		/* we're supposed to check that it's really TOC v1 here but we know it is ;) */
-		purple_debug(PURPLE_DEBUG_INFO, "toc",
-				   "TOC version: %s\n", buf + sizeof(struct sflap_hdr) + 8);
-
-		/* we used to check for the CONFIG here, but we'll wait until we've sent our
-		 * version of the config and then the toc_init_done message. we'll come back to
-		 * the callback in a better state if we get CONFIG anyway */
-
-		tdt->state = STATE_ONLINE;
-
-		purple_connection_set_state(gc, PURPLE_CONNECTED);
-
-		/*
-		 * Add me to my buddy list so that we know the time when
-		 * the server thinks I signed on.
-		 */
-		buddy = purple_buddy_new(account, username, NULL);
-		/* XXX - Pick a group to add to */
-		/* purple_blist_add(buddy, NULL, g, NULL); */
-		purple_account_add_buddy(gc, buddy);
-
-		/* Client sends TOC toc_init_done message */
-		purple_debug(PURPLE_DEBUG_INFO, "toc",
-				   "Client sends TOC toc_init_done message\n");
-		g_snprintf(snd, sizeof snd, "toc_init_done");
-		sflap_send(gc, snd, -1, TYPE_DATA);
-
-		/*
-		g_snprintf(snd, sizeof snd, "toc_set_caps %s %s %s",
-				FILE_SEND_UID, FILE_GET_UID, B_ICON_UID);
-		*/
-		g_snprintf(snd, sizeof snd, "toc_set_caps %s %s", FILE_SEND_UID, FILE_GET_UID);
-		sflap_send(gc, snd, -1, TYPE_DATA);
-
-		return;
-	}
-
-	purple_debug(PURPLE_DEBUG_INFO, "toc", "S: %s\n",
-			   buf + sizeof(struct sflap_hdr));
-
-	c = strtok(buf + sizeof(struct sflap_hdr), ":");	/* Ditch the first part */
-
-	if (!g_ascii_strcasecmp(c, "SIGN_ON")) {
-		/* we should only get here after a PAUSE */
-		if (tdt->state != STATE_PAUSE)
-			purple_debug(PURPLE_DEBUG_ERROR, "toc",
-					   "got SIGN_ON but not PAUSE!\n");
-		else {
-			tdt->state = STATE_ONLINE;
-			g_snprintf(snd, sizeof snd, "toc_signon %s %d %s %s %s \"%s\"",
-				   AUTH_HOST, AUTH_PORT,
-				   purple_normalize(account, purple_account_get_username(account)),
-				   roast_password(purple_connection_get_password(gc)),
-				   LANGUAGE, REVISION);
-			if (sflap_send(gc, snd, -1, TYPE_DATA) < 0) {
-				purple_connection_error(gc, _("Disconnected."));
-				return;
-			}
-			g_snprintf(snd, sizeof snd, "toc_init_done");
-			sflap_send(gc, snd, -1, TYPE_DATA);
-			purple_notify_info(gc, NULL,
-							 _("TOC has come back from its pause. You may "
-							   "now send messages again."), NULL);
-		}
-	} else if (!g_ascii_strcasecmp(c, "CONFIG")) {
-		c = strtok(NULL, ":");
-		parse_toc_buddy_list(account, c);
-	} else if (!g_ascii_strcasecmp(c, "NICK")) {
-		/* ignore NICK so that things get imported/exported properly
-		c = strtok(NULL, ":");
-		g_snprintf(gc->username, sizeof(gc->username), "%s", c);
-		*/
-	} else if (!g_ascii_strcasecmp(c, "IM_IN")) {
-		char *away, *message;
-		int a = 0;
-
-		c = strtok(NULL, ":");
-		away = strtok(NULL, ":");
-
-		message = away;
-		while (*message && (*message != ':'))
-			message++;
-		message++;
-
-		a = (away && (*away == 'T')) ? PURPLE_MESSAGE_AUTO_RESP : 0;
-
-		serv_got_im(gc, c, message, a, time(NULL));
-	} else if (!g_ascii_strcasecmp(c, "UPDATE_BUDDY")) {
-		char *l, *uc, *tmp;
-		gboolean logged_in;
-		int evil, idle, type = 0;
-		time_t signon, time_idle;
-
-		c = strtok(NULL, ":");	/* name */
-		l = strtok(NULL, ":");	/* online */
-		sscanf(strtok(NULL, ":"), "%d", &evil);
-		sscanf(strtok(NULL, ":"), "%ld", &signon);
-		sscanf(strtok(NULL, ":"), "%d", &idle);
-		uc = strtok(NULL, ":");
-
-		logged_in = (l && (*l == 'T')) ? TRUE : FALSE;
-
-		if (uc[0] == 'A')
-			type |= UC_AOL;
-		switch (uc[1]) {
-		case 'A':
-			type |= UC_ADMIN;
-			break;
-		case 'U':
-			type |= UC_UNCONFIRMED;
-			break;
-		case 'O':
-			type |= UC_NORMAL;
-			break;
-		case 'C':
-			type |= UC_WIRELESS;
-			break;
-		default:
-			break;
-		}
-		if (uc[2] == 'U')
-			type |= UC_UNAVAILABLE;
-
-		if (idle) {
-			time(&time_idle);
-			time_idle -= idle * 60;
-		} else
-			time_idle = 0;
-
-		/*
-		 * If we have info for ourselves then set our display name, warning
-		 * level and official time of login.
-		 */
-		tmp = g_strdup(purple_normalize(account, purple_account_get_username(gc->account)));
-		if (!strcmp(tmp, purple_normalize(account, c))) {
-			purple_connection_set_display_name(gc, c);
-			/* XXX - What should the second parameter be here? */
-			/*			purple_prpl_got_account_warning_level(account, NULL, evil);*/
-			purple_prpl_got_account_login_time(account, signon);
-		}
-		g_free(tmp);
-
-		purple_prpl_got_user_status(account, c, (logged_in ? "online" : "offline"), NULL);
-		purple_prpl_got_user_login_time(account, c, signon);
-		if (time_idle > 0)
-			purple_prpl_got_user_idle(account, c, TRUE, time_idle);
-		else
-			purple_prpl_got_user_idle(account, c, FALSE, 0);
-	} else if (!g_ascii_strcasecmp(c, "ERROR")) {
-		purple_notify_error(gc, NULL, show_error_message(), NULL);
-	} else if (!g_ascii_strcasecmp(c, "EVILED")) {
-		int lev;
-		char *name;
-
-		sscanf(strtok(NULL, ":"), "%d", &lev);
-		name = strtok(NULL, ":");
-
-		/*	purple_prpl_got_account_warning_level(account, name, lev); */
-	} else if (!g_ascii_strcasecmp(c, "CHAT_JOIN")) {
-		char *name;
-		int id;
-
-		sscanf(strtok(NULL, ":"), "%d", &id);
-		name = strtok(NULL, ":");
-
-		serv_got_joined_chat(gc, id, name);
-	} else if (!g_ascii_strcasecmp(c, "CHAT_IN")) {
-		int id;
-		PurpleMessageFlags flags;
-		char *m, *who, *whisper;
-
-		sscanf(strtok(NULL, ":"), "%d", &id);
-		who = strtok(NULL, ":");
-		whisper = strtok(NULL, ":");
-		m = whisper;
-		while (*m && (*m != ':'))
-			m++;
-		m++;
-
-		flags = (whisper && (*whisper == 'T')) ? PURPLE_MESSAGE_WHISPER : 0;
-
-		serv_got_chat_in(gc, id, who, flags, m, time((time_t)NULL));
-	} else if (!g_ascii_strcasecmp(c, "CHAT_UPDATE_BUDDY")) {
-		int id;
-		char *in, *buddy;
-		GSList *bcs = gc->buddy_chats;
-		PurpleConversation *b = NULL;
-		PurpleConvChat *chat;
-
-		sscanf(strtok(NULL, ":"), "%d", &id);
-		in = strtok(NULL, ":");
-
-		chat = PURPLE_CONV_CHAT(b);
-
-		while (bcs) {
-			b = (PurpleConversation *)bcs->data;
-			if (id == purple_conv_chat_get_id(chat))
-				break;
-			bcs = bcs->next;
-			b = NULL;
-		}
-
-		if (!b)
-			return;
-
-		if (in && (*in == 'T'))
-			while ((buddy = strtok(NULL, ":")) != NULL)
-				purple_conv_chat_add_user(chat, buddy, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-		else
-			while ((buddy = strtok(NULL, ":")) != NULL)
-				purple_conv_chat_remove_user(chat, buddy, NULL);
-	} else if (!g_ascii_strcasecmp(c, "CHAT_INVITE")) {
-		char *name, *who, *message;
-		int id;
-		GHashTable *components = g_hash_table_new_full(g_str_hash, g_str_equal,
-				g_free, g_free);
-
-		name = strtok(NULL, ":");
-		sscanf(strtok(NULL, ":"), "%d", &id);
-		who = strtok(NULL, ":");
-		message = strtok(NULL, ":");
-
-		g_hash_table_replace(components, g_strdup("id"), g_strdup_printf("%d", id));
-
-		serv_got_chat_invite(gc, name, who, message, components);
-	} else if (!g_ascii_strcasecmp(c, "CHAT_LEFT")) {
-		GSList *bcs = gc->buddy_chats;
-		PurpleConversation *b = NULL;
-		int id;
-
-		sscanf(strtok(NULL, ":"), "%d", &id);
-
-		while (bcs) {
-			b = (PurpleConversation *)bcs->data;
-			if (id == purple_conv_chat_get_id(PURPLE_CONV_CHAT(b)))
-				break;
-			b = NULL;
-			bcs = bcs->next;
-		}
-
-		if (!b)
-			return;
-
-		if (b->window) {
-			char error_buf[BUF_LONG];
-			purple_conversation_set_account(b, NULL);
-			g_snprintf(error_buf, sizeof error_buf, _("You have been disconnected"
-								  " from chat room %s."), b->name);
-			purple_notify_error(gc, NULL, error_buf, NULL);
-		} else
-			serv_got_chat_left(gc, id);
-	} else if (!g_ascii_strcasecmp(c, "GOTO_URL")) {
-		char *name, *url, tmp[256];
-
-		name = strtok(NULL, ":");
-		url = strtok(NULL, ":");
-
-		g_snprintf(tmp, sizeof(tmp), "http://%s:%d/%s", tdt->toc_ip,
-				purple_account_get_int(gc->account, "port", TOC_PORT),
-				url);
-		purple_url_fetch(tmp, FALSE, NULL, FALSE, toc_got_info, gc);
-	} else if (!g_ascii_strcasecmp(c, "DIR_STATUS")) {
-	} else if (!g_ascii_strcasecmp(c, "ADMIN_NICK_STATUS")) {
-	} else if (!g_ascii_strcasecmp(c, "ADMIN_PASSWD_STATUS")) {
-		purple_notify_info(gc, NULL, _("Password Change Successful"), NULL);
-	} else if (!g_ascii_strcasecmp(c, "PAUSE")) {
-		tdt->state = STATE_PAUSE;
-	} else if (!g_ascii_strcasecmp(c, "RVOUS_PROPOSE")) {
-#if 0
-		char *user, *uuid, *cookie;
-		int seq;
-		char *rip, *pip, *vip, *trillian = NULL;
-		int port;
-		
-		user = strtok(NULL, ":");
-		uuid = strtok(NULL, ":");
-		cookie = strtok(NULL, ":");
-		sscanf(strtok(NULL, ":"), "%d", &seq);
-		rip = strtok(NULL, ":");
-		pip = strtok(NULL, ":");
-		vip = strtok(NULL, ":");
-		sscanf(strtok(NULL, ":"), "%d", &port);
-
-		if (!strcmp(uuid, FILE_SEND_UID)) {
-			/* they want us to get a file */
-			int unk[4], i;
-			char *messages[4], *tmp, *name;
-			int subtype, files, totalsize = 0;
-			struct ft_request *ft;
-
-			for (i = 0; i < 4; i++) {
-				trillian = strtok(NULL, ":");
-				sscanf(trillian, "%d", &unk[i]);
-				if (unk[i] == 10001)
-					break;
-				/* Trillian likes to send an empty token as a message, rather than
-				   no message at all. */
-				if (*(trillian + strlen(trillian) +1) != ':')
-					frombase64(strtok(NULL, ":"), &messages[i], NULL);
-			}
-			   
-			frombase64(strtok(NULL, ":"), &tmp, NULL);
-
-			subtype = tmp[1];
-			files = tmp[3];
-
-			totalsize |= (tmp[4] << 24) & 0xff000000;
-			totalsize |= (tmp[5] << 16) & 0x00ff0000;
-			totalsize |= (tmp[6] << 8) & 0x0000ff00;
-			totalsize |= (tmp[7] << 0) & 0x000000ff;
-
-			if (!totalsize) {
-				g_free(tmp);
-				for (i--; i >= 0; i--)
-					g_free(messages[i]);
-				return;
-			}
-
-			name = tmp + 8;
-
-			ft = g_new0(struct ft_request, 1);
-			ft->cookie = g_strdup(cookie);
-			ft->ip = g_strdup(pip);
-			ft->port = port;
-			if (i)
-				ft->message = g_strdup(messages[0]);
-			else
-				ft->message = NULL;
-			ft->filename = g_strdup(name);
-			ft->user = g_strdup(user);
-			ft->size = totalsize;
-			ft->files = files;
-			g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_SEND_UID);
-			ft->gc = gc;
-
-			g_free(tmp);
-			for (i--; i >= 0; i--)
-				g_free(messages[i]);
-
-			purple_debug(PURPLE_DEBUG_MISC, "toc",
-					   "English translation of RVOUS_PROPOSE: %s requests "
-					   "Send File (i.e. send a file to you); %s:%d "
-					   "(verified_ip:port), %d files at total size of "
-					   "%d bytes.\n", user, vip, port, files, totalsize);
-			accept_file_dialog(ft);
-		} else if (!strcmp(uuid, FILE_GET_UID)) {
-			/* they want us to send a file */
-			int unk[4], i;
-			char *messages[4], *tmp;
-			struct ft_request *ft;
-
-			for (i = 0; i < 4; i++) {
-				sscanf(strtok(NULL, ":"), "%d", unk + i);
-				if (unk[i] == 10001)
-					break;
-				/* Trillian likes to send an empty token as a message, rather than
-				   no message at all. */
-				if (*(trillian + strlen(trillian) +1) != ':')
-					frombase64(strtok(NULL, ":"), &messages[i], NULL);
-			}
-			frombase64(strtok(NULL, ":"), &tmp, NULL);
-
-			ft = g_new0(struct ft_request, 1);
-			ft->cookie = g_strdup(cookie);
-			ft->ip = g_strdup(pip);
-			ft->port = port;
-			if (i)
-				ft->message = g_strdup(messages[0]);
-			else
-				ft->message = NULL;
-			ft->user = g_strdup(user);
-			g_snprintf(ft->UID, sizeof(ft->UID), "%s", FILE_GET_UID);
-			ft->gc = gc;
-
-			g_free(tmp);
-			for (i--; i >= 0; i--)
-				g_free(messages[i]);
-
-			accept_file_dialog(ft);
-		} else if (!strcmp(uuid, VOICE_UID)) {
-			/* oh goody. voice over ip. fun stuff. */
-		} else if (!strcmp(uuid, B_ICON_UID)) {
-			int unk[4], i;
-			char *messages[4];
-			struct buddy_icon *icon;
-
-			for (i = 0; i < 4; i++) {
-				sscanf(strtok(NULL, ":"), "%d", unk + i);
-				if (unk[i] == 10001)
-					break;
-				frombase64(strtok(NULL, ":"), &messages[i], NULL);
-			}
-			frombase64(strtok(NULL, ":"), (char **)&icon, NULL);
-
-			purple_debug(PURPLE_DEBUG_MISC, "toc",
-			           "received icon of length %d\n", icon->len);
-			g_free(icon);
-			for (i--; i >= 0; i--)
-				g_free(messages[i]);
-		} else if (!strcmp(uuid, IMAGE_UID)) {
-			/* aka Direct IM */
-		} else {
-			purple_debug(PURPLE_DEBUG_ERROR, "toc",
-					   "Don't know what to do with RVOUS UUID %s\n", uuid);
-			/* do we have to do anything here? i think it just times out */
-		}
-#endif
-	} else {
-		purple_debug(PURPLE_DEBUG_ERROR, "toc",
-				   "don't know what to do with %s\n", c);
-	}
-}
-
-static int toc_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags flags)
-{
-	char *buf1, *buf2;
-
-#if 1
-	/* This is the old, non-i18n way */
-	buf1 = escape_text(message);
-	if (strlen(buf1) + 52 > MSG_LEN) {
-		g_free(buf1);
-		return -E2BIG;
-	}
-	buf2 = g_strdup_printf("toc_send_im %s \"%s\"%s", purple_normalize(gc->account, name), buf1,
-						   ((flags & PURPLE_MESSAGE_AUTO_RESP) ? " auto" : ""));
-	g_free(buf1);
-#else
-	/* This doesn't work yet.  See the comments below for details */
-	buf1 = purple_strreplace(message, "\"", "\\\"");
-
-	/*
-	 * We still need to determine what encoding should be used and send the 
-	 * message in that encoding.  This should be done the same as in 
-	 * oscar_encoding_check() in oscar.c.  There is no encoding flag sent 
-	 * along with the message--the TOC to OSCAR proxy server must just 
-	 * use a lil' algorithm to determine what the actual encoding is.
-	 *
-	 * After that, you need to convert buf1 to that encoding, and keep track 
-	 * of the length of the resulting string.  Then you need to make sure 
-	 * that length is passed to sflap_send().
-	 */
-
-	if (strlen(buf1) + 52 > MSG_LEN) {
-		g_free(buf1);
-		return -E2BIG;
-	}
-
-	buf2 = g_strdup_printf("toc2_send_im_enc %s F U en \"%s\" %s", purple_normalize(gc->account, name), buf1, 
-						   ((flags & PURPLE_MESSAGE_AUTO_RESP) ? "auto" : ""));
-	g_free(buf1);
-#endif
-
-	sflap_send(gc, buf2, -1, TYPE_DATA);
-	g_free(buf2);
-
-	return 1;
-}
-
-static void toc_set_config(PurpleConnection *gc)
-{
-	char *buf = g_malloc(MSG_LEN), snd[BUF_LEN * 2];
-	toc_build_config(gc->account, buf, MSG_LEN - strlen("toc_set_config \\{\\}"), FALSE);
-	g_snprintf(snd, MSG_LEN, "toc_set_config {%s}", buf);
-	sflap_send(gc, snd, -1, TYPE_DATA);
-	g_free(buf);
-}
-
-static void toc_get_info(PurpleConnection *gc, const char *name)
-{
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, MSG_LEN, "toc_get_info %s", purple_normalize(gc->account, name));
-	sflap_send(gc, buf, -1, TYPE_DATA);
-}
-
-/* Should be implemented as an Account Action? */
-static void toc_get_dir(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	char buf[BUF_LEN * 2];
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(buddy->account);
-
-	g_snprintf(buf, MSG_LEN, "toc_get_dir %s",
-			purple_normalize(buddy->account, buddy->name));
-	sflap_send(gc, buf, -1, TYPE_DATA);
-}
-
-#if 0
-/* Should be implemented as an Account Action */
-static void toc_set_dir(PurpleConnection *g, const char *first, const char *middle, const char *last,
-			const char *maiden, const char *city, const char *state, const char *country, int web)
-{
-	char *buf3, buf2[BUF_LEN * 4], buf[BUF_LEN];
-	g_snprintf(buf2, sizeof(buf2), "%s:%s:%s:%s:%s:%s:%s:%s", first,
-		   middle, last, maiden, city, state, country, (web == 1) ? "Y" : "");
-	buf3 = escape_text(buf2);
-	g_snprintf(buf, sizeof(buf), "toc_set_dir %s", buf3);
-	g_free(buf3);
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-#endif
-
-#if 0
-/* Should be implemented as an Account Action */
-static void toc_dir_search(PurpleConnection *g, const char *first, const char *middle, const char *last,
-			   const char *maiden, const char *city, const char *state, const char *country, const char *email)
-{
-	char buf[BUF_LONG];
-	g_snprintf(buf, sizeof(buf) / 2, "toc_dir_search %s:%s:%s:%s:%s:%s:%s:%s", first, middle,
-		   last, maiden, city, state, country, email);
-	purple_debug(PURPLE_DEBUG_INFO, "toc",
-			   "Searching for: %s,%s,%s,%s,%s,%s,%s\n",
-			   first, middle, last, maiden,
-		     city, state, country);
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-#endif
-
-static void toc_set_status(PurpleAccount *account, PurpleStatus *status)
-{
-#if 0 /* do we care about TOC any more? */
-	char buf[BUF_LEN * 2];
-	if (gc->away) {
-		g_free(gc->away);
-		gc->away = NULL;
-	}
-	if (message) {
-		char *tmp;
-		gc->away = g_strdup(message);
-		tmp = escape_text(message);
-		g_snprintf(buf, MSG_LEN, "toc_set_away \"%s\"", tmp);
-		g_free(tmp);
-	} else
-		g_snprintf(buf, MSG_LEN, "toc_set_away \"\"");
-	sflap_send(g, buf, -1, TYPE_DATA);
-#endif
-}
-
-static void toc_set_info(PurpleConnection *g, const char *info)
-{
-	char buf[BUF_LEN * 2], *buf2;
-	buf2 = escape_text(info);
-	g_snprintf(buf, sizeof(buf), "toc_set_info \"%s\n\"", buf2);
-	g_free(buf2);
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-
-static void toc_change_passwd(PurpleConnection *g, const char *orig, const char *new)
-{
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, BUF_LONG, "toc_change_passwd %s %s", orig, new);
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-
-static void
-toc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, sizeof(buf), "toc_add_buddy %s", purple_normalize(gc->account, buddy->name));
-	sflap_send(gc, buf, -1, TYPE_DATA);
-	toc_set_config(gc);
-}
-
-static void toc_add_buddies(PurpleConnection *gc, GList *buddies, GList *groups)
-{
-	char buf[BUF_LEN * 2];
-	int n;
-	GList *cur;
-
-	n = g_snprintf(buf, sizeof(buf), "toc_add_buddy");
-	for (cur = buddies; cur != NULL; cur = cur->next) {
-		PurpleBuddy *buddy = cur->data;
-
-		if (strlen(purple_normalize(gc->account, buddy->name)) + n + 32 > MSG_LEN) {
-			sflap_send(gc, buf, -1, TYPE_DATA);
-			n = g_snprintf(buf, sizeof(buf), "toc_add_buddy");
-		}
-		n += g_snprintf(buf + n, sizeof(buf) - n, " %s", purple_normalize(gc->account, buddy->name));
-	}
-	sflap_send(gc, buf, -1, TYPE_DATA);
-}
-
-static void toc_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
-{
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, sizeof(buf), "toc_remove_buddy %s", purple_normalize(gc->account, buddy->name));
-	sflap_send(gc, buf, -1, TYPE_DATA);
-	toc_set_config(gc);
-}
-
-static void toc_remove_buddies(PurpleConnection *gc, GList *buddies, GList *groups)
-{
-	char buf[BUF_LEN * 2];
-	int n;
-	GList *cur;
-
-	n = g_snprintf(buf, sizeof(buf), "toc_remove_buddy");
-	for (cur = buddies; cur != NULL; cur = cur->next) {
-		PurpleBuddy *buddy = cur->data;
-
-		if (strlen(purple_normalize(gc->account, buddy->name)) + n + 32 > MSG_LEN) {
-			sflap_send(gc, buf, -1, TYPE_DATA);
-			n = g_snprintf(buf, sizeof(buf), "toc_remove_buddy");
-		}
-		n += g_snprintf(buf + n, sizeof(buf) - n, " %s", purple_normalize(gc->account, buddy->name));
-	}
-	sflap_send(gc, buf, -1, TYPE_DATA);
-	toc_set_config(gc);
-}
-
-static void toc_set_idle(PurpleConnection *g, int time)
-{
-	char buf[BUF_LEN * 2];
-	g_snprintf(buf, sizeof(buf), "toc_set_idle %d", time);
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-
-static void toc_warn(PurpleConnection *g, const char *name, int anon)
-{
-	char send[BUF_LEN * 2];
-	g_snprintf(send, 255, "toc_evil %s %s", name, ((anon) ? "anon" : "norm"));
-	sflap_send(g, send, -1, TYPE_DATA);
-}
-
-static GList *toc_chat_info(PurpleConnection *gc)
-{
-	GList *m = NULL;
-	struct proto_chat_entry *pce;
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Group:");
-	pce->identifier = "room";
-	m = g_list_append(m, pce);
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Exchange:");
-	pce->identifier = "exchange";
-	pce->is_int = TRUE;
-	pce->min = 4;
-	pce->max = 20;
-	m = g_list_append(m, pce);
-
-	return m;
-}
-
-GHashTable *toc_chat_info_defaults(PurpleConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "room", g_strdup(chat_name));
-
-	return defaults;
-}
-
-static void toc_join_chat(PurpleConnection *g, GHashTable *data)
-{
-	char buf[BUF_LONG];
-	char *name, *exchange;
-	char *id;
-
-	name = g_hash_table_lookup(data, "room");
-	exchange = g_hash_table_lookup(data, "exchange");
-	id = g_hash_table_lookup(data, "id");
-
-	if (id) {
-		g_snprintf(buf, 255, "toc_chat_accept %d", atoi(id));
-	} else {
-		g_snprintf(buf, sizeof(buf) / 2, "toc_chat_join %d \"%s\"", atoi(exchange), name);
-	}
-
-	sflap_send(g, buf, -1, TYPE_DATA);
-}
-
-static void toc_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
-{
-	char buf[BUF_LONG];
-	g_snprintf(buf, sizeof(buf) / 2, "toc_chat_invite %d \"%s\" %s", id,
-			message ? message : "", purple_normalize(gc->account, name));
-	sflap_send(gc, buf, -1, TYPE_DATA);
-}
-
-static void toc_chat_leave(PurpleConnection *g, int id)
-{
-	GSList *bcs = g->buddy_chats;
-	PurpleConversation *b = NULL;
-	char buf[BUF_LEN * 2];
-
-	while (bcs) {
-		b = (PurpleConversation *)bcs->data;
-		if (id == purple_conv_chat_get_id(PURPLE_CONV_CHAT(b)))
-			break;
-		b = NULL;
-		bcs = bcs->next;
-	}
-
-	if (!b)
-		return;		/* can this happen? */
-
-	if (purple_conversation_get_account(b) == NULL) {
-		/* TOC already kicked us out of this room */
-		serv_got_chat_left(g, id);
-	}
-	else {
-		g_snprintf(buf, 255, "toc_chat_leave %d", id);
-		sflap_send(g, buf, -1, TYPE_DATA);
-	}
-}
-
-static void toc_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message)
-{
-	char *buf1, *buf2;
-	buf1 = escape_text(message);
-	buf2 = g_strdup_printf("toc_chat_whisper %d %s \"%s\"", id, purple_normalize(gc->account, who), buf1);
-	g_free(buf1);
-	sflap_send(gc, buf2, -1, TYPE_DATA);
-	g_free(buf2);
-}
-
-static int toc_chat_send(PurpleConnection *g, int id, const char *message, PurpleMessageFlags flags)
-{
-	char *buf1, *buf2;
-	buf1 = escape_text(message);
-	if (strlen(buf1) > 2000) {
-		g_free(buf1);
-		return -E2BIG;
-	}
-	buf2 = g_strdup_printf("toc_chat_send %d \"%s\"", id, buf1);
-	g_free(buf1);
-	sflap_send(g, buf2, -1, TYPE_DATA);
-	g_free(buf2);
-	return 0;
-}
-
-static void toc_keepalive(PurpleConnection *gc)
-{
-	sflap_send(gc, "", 0, TYPE_KEEPALIVE);
-}
-
-static const char *
-toc_normalize(const PurpleAccount *account, const char *str)
-{
-	static char buf[BUF_LEN];
-	char *tmp1, *tmp2;
-	int i, j;
-
-	g_return_val_if_fail(str != NULL, NULL);
-
-	strncpy(buf, str, BUF_LEN);
-	for (i=0, j=0; buf[j]; i++, j++)
-	{
-		while (buf[j] == ' ')
-			j++;
-		buf[i] = buf[j];
-	}
-	buf[i] = '\0';
-
-	tmp1 = g_utf8_strdown(buf, -1);
-	tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
-	g_snprintf(buf, sizeof(buf), "%s", tmp2);
-	g_free(tmp2);
-	g_free(tmp1);
-
-	return buf;
-}
-
-static const char *toc_list_icon(PurpleAccount *a, PurpleBuddy *b)
-{
-	if (!b || (b && b->name && b->name[0] == '+')) {
-		if (a != NULL && isdigit(*purple_account_get_username(a)))
-			return "icq";
-		else
-			return "aim";
-	}
-
-	if (b && b->name && isdigit(b->name[0]))
-		return "icq";
-	return "aim";
-}
-
-static const char* toc_list_emblem(PurpleBuddy *b)
-{
-	if (b->uc & UC_AOL)
-		return "aol";
-	if (b->uc & UC_ADMIN)
-		return "admin";
-	if (b->uc & UC_WIRELESS)
-		return "mobile";
-	return NULL	
-}
-
-static GList *toc_blist_node_menu(PurpleBlistNode *node)
-{
-	GList *m = NULL;
-	PurpleMenuAction *act;
-
-	if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		act = purple_menu_action_new(_("Get Dir Info"),
-		                           toc_get_dir, NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-static void toc_add_permit(PurpleConnection *gc, const char *who)
-{
-	char buf2[BUF_LEN * 2];
-	if (gc->account->perm_deny != 3)
-		return;
-	g_snprintf(buf2, sizeof(buf2), "toc_add_permit %s", purple_normalize(gc->account, who));
-	sflap_send(gc, buf2, -1, TYPE_DATA);
-	toc_set_config(gc);
-}
-
-static void toc_add_deny(PurpleConnection *gc, const char *who)
-{
-	char buf2[BUF_LEN * 2];
-	if (gc->account->perm_deny != 4)
-		return;
-	g_snprintf(buf2, sizeof(buf2), "toc_add_deny %s", purple_normalize(gc->account, who));
-	sflap_send(gc, buf2, -1, TYPE_DATA);
-	toc_set_config(gc);
-}
-
-static void toc_set_permit_deny(PurpleConnection *gc)
-{
-	char buf2[BUF_LEN * 2];
-	GSList *list;
-	int at;
-
-	switch (gc->account->perm_deny) {
-	case 1:
-		/* permit all, deny none. to get here reliably we need to have been in permit
-		 * mode, and send an empty toc_add_deny message, which will switch us to deny none */
-		g_snprintf(buf2, sizeof(buf2), "toc_add_permit ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		g_snprintf(buf2, sizeof(buf2), "toc_add_deny ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		break;
-	case 2:
-		/* deny all, permit none. to get here reliably we need to have been in deny
-		 * mode, and send an empty toc_add_permit message, which will switch us to permit none */
-		g_snprintf(buf2, sizeof(buf2), "toc_add_deny ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		g_snprintf(buf2, sizeof(buf2), "toc_add_permit ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		break;
-	case 3:
-		/* permit some. we want to switch to deny mode first, then send the toc_add_permit
-		 * message, which will clear and set our permit list. toc sucks. */
-		g_snprintf(buf2, sizeof(buf2), "toc_add_deny ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-
-		at = g_snprintf(buf2, sizeof(buf2), "toc_add_permit ");
-		list = gc->account->permit;
-		while (list) {
-			at += g_snprintf(buf2 + at, sizeof(buf2) - at, "%s ", purple_normalize(gc->account, list->data));
-			if (at > MSG_LEN + 32) {	/* from out my ass comes greatness */
-				sflap_send(gc, buf2, -1, TYPE_DATA);
-				at = g_snprintf(buf2, sizeof(buf2), "toc_add_permit ");
-			}
-			list = list->next;
-		}
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		break;
-	case 4:
-		/* deny some. we want to switch to permit mode first, then send the toc_add_deny
-		 * message, which will clear and set our deny list. toc sucks. */
-		g_snprintf(buf2, sizeof(buf2), "toc_add_permit ");
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-
-		at = g_snprintf(buf2, sizeof(buf2), "toc_add_deny ");
-		list = gc->account->deny;
-		while (list) {
-			at += g_snprintf(buf2 + at, sizeof(buf2) - at, "%s ", purple_normalize(gc->account, list->data));
-			if (at > MSG_LEN + 32) {	/* from out my ass comes greatness */
-				sflap_send(gc, buf2, -1, TYPE_DATA);
-				at = g_snprintf(buf2, sizeof(buf2), "toc_add_deny ");
-			}
-			list = list->next;
-		}
-		sflap_send(gc, buf2, -1, TYPE_DATA);
-		break;
-	default:
-		break;
-	}
-	toc_set_config(gc);
-}
-
-static void toc_rem_permit(PurpleConnection *gc, const char *who)
-{
-	if (gc->account->perm_deny != 3)
-		return;
-	toc_set_permit_deny(gc);
-}
-
-static void toc_rem_deny(PurpleConnection *gc, const char *who)
-{
-	if (gc->account->perm_deny != 4)
-		return;
-	toc_set_permit_deny(gc);
-}
-
-static GList *toc_away_states(PurpleAccount *account)
-{
-#if 0 /* do we care about TOC any more? */
-	return g_list_append(NULL, PURPLE_AWAY_CUSTOM);
-#else
-	return NULL;
-#endif
-}
-
-static void
-show_set_info(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	purple_account_request_change_user_info(purple_connection_get_account(gc));
-}
-
-static void
-change_pass(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	purple_account_request_change_password(purple_connection_get_account(gc));
-}
-
-static GList *toc_actions(PurplePlugin *plugin, gpointer context)
-{
-	GList *m = NULL;
-	PurplePluginAction *act;
-
-	act = purple_plugin_action_new(_("Set User Info"),
-			show_set_info);
-	m = g_list_append(m, act);
-
-#if 0
-	act = purple_plugin_action_new(_("Set Dir Info"),
-			show_set_dir);
-	m = g_list_append(m, act);
-#endif
-
-	act = purple_plugin_action_new(_("Change Password"),
-			change_pass);
-	m = g_list_append(m, act);
-
-	return m;
-}
-
-#if 0
-/*********
- * RVOUS ACTIONS
- ********/
-
-struct file_header {
-	char  magic[4];		/* 0 */
-	short hdrlen;		/* 4 */
-	short hdrtype;		/* 6 */
-	char  bcookie[8];	/* 8 */
-	short encrypt;		/* 16 */
-	short compress;		/* 18 */
-	short totfiles;		/* 20 */
-	short filesleft;	/* 22 */
-	short totparts;		/* 24 */
-	short partsleft;	/* 26 */
-	long  totsize;		/* 28 */
-	long  size;		/* 32 */
-	long  modtime;		/* 36 */
-	long  checksum;		/* 40 */
-	long  rfrcsum;		/* 44 */
-	long  rfsize;		/* 48 */
-	long  cretime;		/* 52 */
-	long  rfcsum;		/* 56 */
-	long  nrecvd;		/* 60 */
-	long  recvcsum;		/* 64 */
-	char  idstring[32];	/* 68 */
-	char  flags;		/* 100 */
-	char  lnameoffset;	/* 101 */
-	char  lsizeoffset;	/* 102 */
-	char  dummy[69];	/* 103 */
-	char  macfileinfo[16];	/* 172 */
-	short nencode;		/* 188 */
-	short nlanguage;	/* 190 */
-	char  name[64];		/* 192 */
-				/* 256 */
-};
-
-struct file_transfer {
-	struct file_header hdr;
-
-	PurpleConnection *gc;
-
-	char *user;
-	char *cookie;
-	char *ip;
-	int port;
-	long size;
-	struct stat st;
-
-	GtkWidget *window;
-	int files;
-	char *filename;
-	FILE *file;
-	int recvsize;
-
-	gint inpa;
-};
-
-static void debug_header(struct file_transfer *ft) {
-	struct file_header *f = (struct file_header *)ft;
-	purple_debug(PURPLE_DEBUG_MISC, "toc", "FT HEADER:\n"
-			"\t%s %d 0x%04x\n"
-			"\t%s %d %d\n"
-			"\t%d %d %d %d %d %d\n"
-			"\t%d %d %d %d %d %d %d %d\n"
-			"\t%s\n"
-			"\t0x%02x, 0x%02x, 0x%02x\n"
-			"\t%s %s\n"
-			"\t%d %d\n"
-			"\t%s\n",
-			f->magic, ntohs(f->hdrlen), f->hdrtype,
-			f->bcookie, ntohs(f->encrypt), ntohs(f->compress),
-			ntohs(f->totfiles), ntohs(f->filesleft), ntohs(f->totparts),
-				ntohs(f->partsleft), ntohl(f->totsize), ntohl(f->size),
-			ntohl(f->modtime), ntohl(f->checksum), ntohl(f->rfrcsum), ntohl(f->rfsize),
-				ntohl(f->cretime), ntohl(f->rfcsum), ntohl(f->nrecvd),
-				ntohl(f->recvcsum),
-			f->idstring,
-			f->flags, f->lnameoffset, f->lsizeoffset,
-			f->dummy, f->macfileinfo,
-			ntohs(f->nencode), ntohs(f->nlanguage),
-			f->name);
-}
-
-static void toc_send_file_callback(gpointer data, gint source, PurpleInputCondition cond)
-{
-	char buf[BUF_LONG];
-	int rt, i;
-
-	struct file_transfer *ft = data;
-
-	if (ft->hdr.hdrtype != 0x202) {
-		char *buf;
-		frombase64(ft->cookie, &buf, NULL);
-
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-
-		ft->hdr.hdrtype = 0x202;
-		memcpy(ft->hdr.bcookie, buf, 8);
-		g_free(buf);
-		ft->hdr.encrypt = 0; ft->hdr.compress = 0;
-		debug_header(ft);
-		write(source, ft, 256);
-
-		if (ft->files == 1) {
-			ft->file = g_fopen(ft->filename, "w");
-			if (!ft->file) {
-				buf = g_strdup_printf(_("Could not open %s for writing!"), ft->filename);
-				purple_notify_error(ft->gc, NULL, buf, g_strerror(errno));
-				g_free(buf);
-				purple_input_remove(ft->inpa);
-				close(source);
-				g_free(ft->filename);
-				g_free(ft->user);
-				g_free(ft->ip);
-				g_free(ft->cookie);
-				g_free(ft);
-			}
-		} else {
-			buf = g_strdup_printf("%s/%s", ft->filename, ft->hdr.name);
-			ft->file = g_fopen(buf, "w");
-			g_free(buf);
-			if (!ft->file) {
-				buf = g_strdup_printf("Could not open %s/%s for writing!", ft->filename,
-						ft->hdr.name);
-				purple_notify_error(ft->gc, NULL, buf, g_strerror(errno));
-				g_free(buf);
-				purple_input_remove(ft->inpa);
-				close(source);
-				g_free(ft->filename);
-				g_free(ft->user);
-				g_free(ft->ip);
-				g_free(ft->cookie);
-				g_free(ft);
-			}
-		}
-
-		return;
-	}
-
-	rt = read(source, buf, MIN(ntohl(ft->hdr.size) - ft->recvsize, 1024));
-	if (rt < 0) {
-		purple_notify_error(ft->gc, NULL,
-						  _("File transfer failed; other side probably "
-							"canceled."), NULL);
-		purple_input_remove(ft->inpa);
-		close(source);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft->cookie);
-		if (ft->file)
-			fclose(ft->file);
-		g_free(ft);
-		return;
-	}
-	ft->recvsize += rt;
-	for (i = 0; i < rt; i++)
-		fprintf(ft->file, "%c", buf[i]);
-
-	if (ft->recvsize == ntohl(ft->hdr.size)) {
-		ft->hdr.hdrtype = htons(0x0204);
-		ft->hdr.filesleft = htons(ntohs(ft->hdr.filesleft) - 1);
-		ft->hdr.partsleft = htons(ntohs(ft->hdr.partsleft) - 1);
-		ft->hdr.recvcsum = ft->hdr.checksum; /* uh... */
-		ft->hdr.nrecvd = htons(ntohs(ft->hdr.nrecvd) + 1);
-		ft->hdr.flags = 0;
-		write(source, ft, 256);
-		debug_header(ft);
-		ft->recvsize = 0;
-		fclose(ft->file);
-		if (ft->hdr.filesleft == 0) {
-			purple_input_remove(ft->inpa);
-			close(source);
-			g_free(ft->filename);
-			g_free(ft->user);
-			g_free(ft->ip);
-			g_free(ft->cookie);
-			g_free(ft);
-		}
-	}
-}
-
-static void toc_send_file_connect(gpointer data, gint src, PurpleInputCondition cond)
-{
-	struct file_transfer *ft = data;
-
-	if (src == -1) {
-		purple_notify_error(ft->gc, NULL,
-						  _("Could not connect for transfer."), NULL);
-		g_free(ft->filename);
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-		return;
-	}
-
-	ft->inpa = purple_input_add(src, PURPLE_INPUT_READ, toc_send_file_callback, ft);
-}
-
-static void toc_send_file(gpointer a, struct file_transfer *old_ft)
-{
-	struct file_transfer *ft;
-	const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window));
-	PurpleAccount *account;
-	char buf[BUF_LEN * 2];
-
-	if (purple_gtk_check_if_dir(dirname, GTK_FILE_SELECTION(old_ft->window)))
-		return;
-	ft = g_new0(struct file_transfer, 1);
-	if (old_ft->files == 1)
-		ft->filename = g_strdup(dirname);
-	else
-		ft->filename = g_path_get_dirname(dirname);
-	ft->cookie = g_strdup(old_ft->cookie);
-	ft->user = g_strdup(old_ft->user);
-	ft->ip = g_strdup(old_ft->ip);
-	ft->files = old_ft->files;
-	ft->port = old_ft->port;
-	ft->gc = old_ft->gc;
-	account = ft->gc->account;
-	gtk_widget_destroy(old_ft->window);
-
-	g_snprintf(buf, sizeof(buf), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_SEND_UID);
-	sflap_send(ft->gc, buf, -1, TYPE_DATA);
-
-	if (purple_proxy_connect(ft->gc, account, ft->ip, ft->port, toc_send_file_connect, ft) != 0) {
-		purple_notify_error(ft->gc, NULL,
-						  _("Could not connect for transfer."), NULL);
-		g_free(ft->filename);
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-		return;
-	}
-}
-
-static void toc_get_file_callback(gpointer data, gint source, PurpleInputCondition cond)
-{
-	char buf[BUF_LONG];
-
-	struct file_transfer *ft = data;
-
-	if (cond & PURPLE_INPUT_WRITE) {
-		int remain = MIN(ntohl(ft->hdr.totsize) - ft->recvsize, 1024);
-		int i;
-		for (i = 0; i < remain; i++)
-			fscanf(ft->file, "%c", &buf[i]);
-		write(source, buf, remain);
-		ft->recvsize += remain;
-		if (ft->recvsize == ntohl(ft->hdr.totsize)) {
-			purple_input_remove(ft->inpa);
-			ft->inpa = purple_input_add(source, PURPLE_INPUT_READ,
-						 toc_get_file_callback, ft);
-		}
-		return;
-	}
-
-	if (ft->hdr.hdrtype == htons(0x1108)) {
-		struct tm *fortime;
-		struct stat st;
-		char *basename;
-
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-
-		g_stat(ft->filename, &st);
-		fortime = localtime(&st.st_mtime);
-		basename = g_path_get_basename(ft->filename);
-		g_snprintf(buf, sizeof(buf), "%2d/%2d/%4d %2d:%2d %8ld %s\r\n",
-				fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900,
-				fortime->tm_hour + 1, fortime->tm_min + 1, (long)st.st_size,
-				basename);
-		write(source, buf, ntohl(ft->hdr.size));
-		g_free(basename);
-		return;
-	}
-
-	if (ft->hdr.hdrtype == htons(0x1209)) {
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-		return;
-	}
-
-	if (ft->hdr.hdrtype == htons(0x120b)) {
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-
-		if (ft->hdr.hdrtype != htons(0x120c)) {
-			g_snprintf(buf, sizeof(buf), "%s decided to cancel the transfer", ft->user);
-			purple_notify_error(ft->gc, NULL, buf, NULL);
-			purple_input_remove(ft->inpa);
-			close(source);
-			g_free(ft->filename);
-			g_free(ft->user);
-			g_free(ft->ip);
-			g_free(ft->cookie);
-			if (ft->file)
-				fclose(ft->file);
-			g_free(ft);
-			return;
-		}
-
-		ft->hdr.hdrtype = 0x0101;
-		ft->hdr.totfiles = htons(1); ft->hdr.filesleft = htons(1);
-		ft->hdr.flags = 0x20;
-		write(source, ft, 256);
-		return;
-	}
-
-	if (ft->hdr.hdrtype == 0x0101) {
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-
-		purple_input_remove(ft->inpa);
-		ft->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
-					 toc_get_file_callback, ft);
-		return;
-	}
-
-	if (ft->hdr.hdrtype == 0x0202) {
-		read(source, ft, 8);
-		read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8));
-		debug_header(ft);
-
-		purple_input_remove(ft->inpa);
-		close(source);
-		g_free(ft->filename);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft->cookie);
-		if (ft->file)
-			fclose(ft->file);
-		g_free(ft);
-		return;
-	}
-}
-
-static void toc_get_file_connect(gpointer data, gint src, PurpleInputCondition cond)
-{
-	struct file_transfer *ft = data;
-	struct file_header *hdr;
-	char *buf;
-	char *basename;
-
-	if (src == -1) {
-		purple_notify_error(ft->gc, NULL,
-						  _("Could not connect for transfer."), NULL);
-		fclose(ft->file);
-		g_free(ft->filename);
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-		return;
-	}
-
-	hdr = (struct file_header *)ft;
-	hdr->magic[0] = 'O'; hdr->magic[1] = 'F'; hdr->magic[2] = 'T'; hdr->magic[3] = '2';
-	hdr->hdrlen = htons(256);
-	hdr->hdrtype = htons(0x1108);
-	rombase64(ft->cookie, &buf, NULL);
-	g_snprintf(hdr->bcookie, 8, "%s", buf);
-	g_free(buf);
-	hdr->totfiles = htons(1); hdr->filesleft = htons(1);
-	hdr->totparts = htons(1); hdr->partsleft = htons(1);
-	hdr->totsize = htonl((long)ft->st.st_size); /* combined size of all files */
-	/* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */
-	basename = g_path_get_basename(ft->filename);
-	hdr->size = htonl(28 + strlen(basename)); /* size of listing.txt */
-	g_free(basename);
-	hdr->modtime = htonl(ft->st.st_mtime);
-	hdr->checksum = htonl(0x89f70000); /* uh... */
-	g_snprintf(hdr->idstring, 32, "OFT_Windows ICBMFT V1.1 32");
-	hdr->flags = 0x02;
-	hdr->lnameoffset = 0x1A;
-	hdr->lsizeoffset = 0x10;
-	g_snprintf(hdr->name, 64, "listing.txt");
-	if (write(src, hdr, 256) < 0) {
-		purple_notify_error(ft->gc, NULL,
-						  _("Could not write file header.  The file will "
-							"not be transferred."), NULL);
-		fclose(ft->file);
-		g_free(ft->filename);
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-		return;
-	}
-
-	ft->inpa = purple_input_add(src, PURPLE_INPUT_READ, toc_get_file_callback, ft);
-}
-
-static void toc_get_file(gpointer a, struct file_transfer *old_ft)
-{
-	struct file_transfer *ft;
-	const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window));
-	PurpleAccount *account;
-	char *buf, buf2[BUF_LEN * 2];
-
-	if (purple_gtk_check_if_dir(dirname, GTK_FILE_SELECTION(old_ft->window)))
-		return;
-	ft = g_new0(struct file_transfer, 1);
-	ft->filename = g_strdup(dirname);
-	ft->file = g_fopen(ft->filename, "r");
-	if (!ft->file) {
-		buf = g_strdup_printf("Unable to open %s for transfer.", ft->filename);
-		purple_notify_error(ft->gc, NULL, buf, NULL);
-		g_free(buf);
-		g_free(ft->filename);
-		g_free(ft);
-		return;
-	}
-	if (g_stat(dirname, &ft->st)) {
-		buf = g_strdup_printf("Unable to examine %s.", dirname);
-		purple_notify_error(ft->gc, NULL, buf, NULL);
-		g_free(buf);
-		g_free(ft->filename);
-		g_free(ft);
-		return;
-	}
-	ft->cookie = g_strdup(old_ft->cookie);
-	ft->user = g_strdup(old_ft->user);
-	ft->ip = g_strdup(old_ft->ip);
-	ft->port = old_ft->port;
-	ft->gc = old_ft->gc;
-	account = ft->gc->account;
-	gtk_widget_destroy(old_ft->window);
-
-	g_snprintf(buf2, sizeof(buf2), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_GET_UID);
-	sflap_send(ft->gc, buf2, -1, TYPE_DATA);
-
-	if (purple_proxy_connect(ft->gc, account, ft->ip, ft->port, toc_get_file_connect, ft) < 0) {
-		purple_notify_error(ft->gc, NULL,
-						  _("Could not connect for transfer."), NULL);
-		fclose(ft->file);
-		g_free(ft->filename);
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-		return;
-	}
-}
-
-static void cancel_callback(gpointer a, struct file_transfer *ft) {
-	gtk_widget_destroy(ft->window);
-	if (a == ft->window) {
-		g_free(ft->cookie);
-		g_free(ft->user);
-		g_free(ft->ip);
-		g_free(ft);
-	}
-}
-
-static void toc_reject_ft(struct ft_request *ft) {
-	g_free(ft->user);
-	g_free(ft->filename);
-	g_free(ft->ip);
-	g_free(ft->cookie);
-	if (ft->message)
-		g_free(ft->message);
-	g_free(ft);
-}
-
-
-static void toc_accept_ft(struct ft_request *fr) {
-	if(g_list_find(purple_connections_get_all(), fr->gc)) {
-		GtkWidget *window;
-		char buf[BUF_LEN];
-
-		struct file_transfer *ft = g_new0(struct file_transfer, 1);
-		ft->gc = fr->gc;
-		ft->user = g_strdup(fr->user);
-		ft->cookie = g_strdup(fr->cookie);
-		ft->ip = g_strdup(fr->ip);
-		ft->port = fr->port;
-		ft->files = fr->files;
-
-		ft->window = window = gtk_file_selection_new(_("Save As..."));
-		g_snprintf(buf, sizeof(buf), "%s/%s", purple_home_dir(), fr->filename ? fr->filename : "");
-		gtk_file_selection_set_filename(GTK_FILE_SELECTION(window), buf);
-		g_signal_connect(G_OBJECT(window), "destroy",
-				G_CALLBACK(cancel_callback), ft);
-		g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button),
-				"clicked", G_CALLBACK(cancel_callback), ft);
-
-		if (!strcmp(fr->UID, FILE_SEND_UID))
-			g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button),
-					"clicked", G_CALLBACK(toc_send_file), ft);
-		else
-			g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button),
-					"clicked", G_CALLBACK(toc_get_file), ft);
-
-		gtk_widget_show(window);
-	}
-
-	toc_reject_ft(fr);
-}
-
-static void accept_file_dialog(struct ft_request *ft) {
-	char buf[BUF_LONG];
-	if (!strcmp(ft->UID, FILE_SEND_UID)) {
-		/* holy crap. who the fuck would transfer gigabytes through AIM?! */
-		static char *sizes[4] = { "bytes", "KB", "MB", "GB" };
-		float size = ft->size;
-		int index = 0;
-		while ((index < 4) && (size > 1024)) {
-			size /= 1024;
-			index++;
-		}
-		g_snprintf(buf, sizeof(buf), 
-				dngettext(PACKAGE, 
-				"%s requests %s to accept %d file: %s (%.2f %s)%s%s",
-				"%s requests %s to accept %d files: %s (%.2f %s)%s%s",
-				ft->files),
-				ft->user, purple_account_get_username(ft->gc->account), ft->files,
-				ft->filename, size, sizes[index], (ft->message) ? "\n" : "",
-				(ft->message) ? ft->message : "");
-	} else {
-		g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"), ft->user);
-	}
-
-	purple_request_accept_cancel(ft->gc, NULL, buf, NULL, 
-							   PURPLE_DEFAULT_ACTION_NONE, ft,
-							   G_CALLBACK(toc_accept_ft),
-							   G_CALLBACK(toc_reject_ft));
-}
-#endif
-
-static PurplePluginProtocolInfo prpl_info =
-{
-	0,
-	NULL,					/* user_splits */
-	NULL,					/* protocol_options */
-	NO_BUDDY_ICONS,			/* icon_spec */
-	toc_list_icon,			/* list_icon */
-	toc_list_emblem,		/* list_emblems */
-	NULL,					/* status_text */
-	NULL,					/* tooltip_text */
-	toc_away_states,		/* away_states */
-	toc_blist_node_menu,	/* blist_node_menu */
-	toc_chat_info,			/* chat_info */
-	toc_chat_info_defaults,	/* chat_info_defaults */
-	toc_login,				/* login */
-	toc_close,				/* close */
-	toc_send_im,			/* send_im */
-	toc_set_info,			/* set_info */
-	NULL,					/* send_typing */
-	toc_get_info,			/* get_info */
-	toc_set_status,			/* set_away */
-	toc_set_idle,			/* set_idle */
-	toc_change_passwd,		/* change_passwd */
-	toc_add_buddy,			/* add_buddy */
-	toc_add_buddies,		/* add_buddies */
-	toc_remove_buddy,		/* remove_buddy */
-	toc_remove_buddies,		/* remove_buddies */
-	toc_add_permit,			/* add_permit */
-	toc_add_deny,			/* add_deny */
-	toc_rem_permit,			/* rem_permit */
-	toc_rem_deny,			/* rem_deny */
-	toc_set_permit_deny,	/* set_permit_deny */
-	toc_join_chat,			/* join_chat */
-	NULL,					/* reject_chat */
-	NULL,				/* get_chat_name */
-	toc_chat_invite,		/* chat_invite */
-	toc_chat_leave,			/* chat_leave */
-	toc_chat_whisper,		/* chat_whisper */
-	toc_chat_send,			/* chat_send */
-	toc_keepalive,			/* keepalive */
-	NULL,					/* register_user */
-	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
-	NULL,					/* alias_buddy */
-	NULL,					/* group_buddy */
-	NULL,					/* rename_group */
-	NULL,					/* buddy_free */
-	NULL,					/* convo_closed */
-	toc_normalize,			/* normalize */
-	NULL,					/* set_buddy_icon */
-	NULL,					/* remove_group */
-	NULL,					/* get_cb_real_name */
-	NULL,					/* set_chat_topic */
-	NULL,					/* find_blist_chat */
-	NULL,					/* roomlist_get_list */
-	NULL,					/* roomlist_cancel */
-	NULL,					/* roomlist_expand_category */
-	NULL,					/* can_receive_file */
-	NULL,					/* send_file */
-	NULL,					/* new_xfer */
-	NULL,					/* offline_message */
-	NULL,					/* whiteboard_prpl_ops */
-	toc_send_raw,				/* send_raw */
-};
-
-static PurplePluginInfo info =
-{
-	PURPLE_PLUGIN_MAGIC,
-	PURPLE_MAJOR_VERSION,
-	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
-
-	"prpl-toc",                                       /**< id             */
-	"TOC",                                            /**< name           */
-	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("TOC Protocol Plugin"),
-	                                                  /**  description    */
-	N_("TOC Protocol Plugin"),
-	NULL,                                             /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
-
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,
-	toc_actions
-};
-
-static void
-init_plugin(PurplePlugin *plugin)
-{
-	PurpleAccountOption *option;
-
-	option = purple_account_option_string_new(_("Server"), "server", TOC_HOST);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	option = purple_account_option_int_new(_("Port"), "port", TOC_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-											   option);
-
-	my_protocol = plugin;
-}
-
-PURPLE_INIT_PLUGIN(toc, init_plugin, info);
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Sat Mar 28 16:59:30 2009 +0000
@@ -201,6 +201,8 @@
 		}
 		pos += 2;
 
+		if (pos + 1 > len) break;
+
 		/* Skip over garbage we've noticed in the mail notifications */
 		if (data[0] == '9' && data[pos] == 0x01)
 			pos++;
--- a/libpurple/prpl.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/prpl.h	Sat Mar 28 16:59:30 2009 +0000
@@ -296,6 +296,14 @@
 	void (*set_idle)(PurpleConnection *, int idletime);
 	void (*change_passwd)(PurpleConnection *, const char *old_pass,
 						  const char *new_pass);
+	/**
+	 * Add a buddy to a group on the server.
+	 *
+	 * This PRPL function may be called in situations in which the buddy is
+	 * already in the specified group. If the protocol supports
+	 * authorization and the user is not already authorized to see the
+	 * status of \a buddy, \a add_buddy should request authorization.
+	 */
 	void (*add_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
 	void (*add_buddies)(PurpleConnection *, GList *buddies, GList *groups);
 	void (*remove_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group);
--- a/libpurple/tests/test_util.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/tests/test_util.c	Sat Mar 28 16:59:30 2009 +0000
@@ -5,7 +5,7 @@
 
 START_TEST(test_util_base16_encode)
 {
-	assert_string_equal_free("68656c6c6f2c20776f726c642100", purple_base16_encode("hello, world!", 14));
+	assert_string_equal_free("68656c6c6f2c20776f726c642100", purple_base16_encode((const unsigned char *)"hello, world!", 14));
 }
 END_TEST
 
@@ -14,14 +14,14 @@
 	gsize sz = 0;
 	guchar *out = purple_base16_decode("21646c726f77202c6f6c6c656800", &sz);
 	fail_unless(sz == 14, NULL);
-	fail_unless(strcmp("!dlrow ,olleh", out) == 0, NULL);
+	fail_unless(strcmp("!dlrow ,olleh", (const char *)out) == 0, NULL);
 	g_free(out);
 }
 END_TEST
 
 START_TEST(test_util_base64_encode)
 {
-	assert_string_equal_free("Zm9ydHktdHdvAA==", purple_base64_encode("forty-two", 10));
+	assert_string_equal_free("Zm9ydHktdHdvAA==", purple_base64_encode((const unsigned char *)"forty-two", 10));
 }
 END_TEST
 
@@ -30,7 +30,7 @@
 	gsize sz;
 	guchar *out = purple_base64_decode("b3d0LXl0cm9mAA==", &sz);
 	fail_unless(sz == 10, NULL);
-	fail_unless(strcmp("owt-ytrof", out) == 0, NULL);
+	fail_unless(strcmp("owt-ytrof", (const char *)out) == 0, NULL);
 	g_free(out);
 }
 END_TEST
--- a/libpurple/util.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/libpurple/util.c	Sat Mar 28 16:59:30 2009 +0000
@@ -4044,6 +4044,13 @@
 				   &gfud->website.page, &gfud->website.user, &gfud->website.passwd);
 
 	if (purple_strcasestr(url, "https://") != NULL) {
+		if (!purple_ssl_is_supported()) {
+			purple_util_fetch_url_error(gfud,
+					_("Unable to connect to %s: Server requires TLS/SSL, but no TLS/SSL support was found."),
+					gfud->website.address);
+			return NULL;
+		}
+
 		gfud->is_ssl = TRUE;
 		gfud->ssl_connection = purple_ssl_connect(NULL,
 				gfud->website.address, gfud->website.port,
--- a/pidgin/gtkaccount.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkaccount.c	Sat Mar 28 16:59:30 2009 +0000
@@ -106,8 +106,8 @@
 	GtkSizeGroup *sg;
 	GtkWidget *window;
 
+	GtkWidget *notebook;
 	GtkWidget *top_vbox;
-	GtkWidget *bottom_vbox;
 	GtkWidget *ok_button;
 	GtkWidget *register_button;
 
@@ -157,8 +157,7 @@
  **************************************************************************/
 static void add_login_options(AccountPrefsDialog *dialog, GtkWidget *parent);
 static void add_user_options(AccountPrefsDialog *dialog, GtkWidget *parent);
-static void add_protocol_options(AccountPrefsDialog *dialog,
-								 GtkWidget *parent);
+static void add_protocol_options(AccountPrefsDialog *dialog);
 static void add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent);
 
 static GtkWidget *
@@ -237,7 +236,7 @@
 
 	add_login_options(dialog,    dialog->top_vbox);
 	add_user_options(dialog,     dialog->top_vbox);
-	add_protocol_options(dialog, dialog->bottom_vbox);
+	add_protocol_options(dialog);
 
 	gtk_widget_grab_focus(dialog->protocol_menu);
 
@@ -733,11 +732,11 @@
 }
 
 static void
-add_protocol_options(AccountPrefsDialog *dialog, GtkWidget *parent)
+add_protocol_options(AccountPrefsDialog *dialog)
 {
 	PurpleAccountOption *option;
 	PurpleAccount *account;
-	GtkWidget *frame, *vbox, *check, *entry, *combo;
+	GtkWidget *vbox, *check, *entry, *combo;
 	GList *list, *node;
 	gint i, idx, int_value;
 	GtkListStore *model;
@@ -752,14 +751,10 @@
 	ProtocolOptEntry *opt_entry;
 
 	if (dialog->protocol_frame != NULL) {
-		gtk_widget_destroy(dialog->protocol_frame);
+		gtk_notebook_remove_page (GTK_NOTEBOOK(dialog->notebook), 1);
 		dialog->protocol_frame = NULL;
 	}
 
-	if (dialog->prpl_info == NULL ||
-			dialog->prpl_info->protocol_options == NULL)
-		return;
-
 	while (dialog->protocol_opt_entries != NULL) {
 		ProtocolOptEntry *opt_entry = dialog->protocol_opt_entries->data;
 		g_free(opt_entry->setting);
@@ -767,21 +762,17 @@
 		dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries);
 	}
 
+	if (dialog->prpl_info == NULL ||
+			dialog->prpl_info->protocol_options == NULL)
+		return;
+
 	account = dialog->account;
 
-	/* Build the protocol options frame. */
-	g_snprintf(buf, sizeof(buf), _("%s Options"), dialog->plugin->info->name);
-
-	frame = pidgin_make_frame(parent, buf);
-	dialog->protocol_frame =
-		gtk_widget_get_parent(gtk_widget_get_parent(frame));
-
-	gtk_box_reorder_child(GTK_BOX(parent), dialog->protocol_frame, 0);
-	gtk_widget_show(dialog->protocol_frame);
-
 	/* Main vbox */
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	dialog->protocol_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BORDER);
+	gtk_notebook_insert_page(GTK_NOTEBOOK(dialog->notebook), vbox,
+			gtk_label_new_with_mnemonic(_("_Advanced")), 1);
 	gtk_widget_show(vbox);
 
 	for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
@@ -1046,22 +1037,15 @@
 add_proxy_options(AccountPrefsDialog *dialog, GtkWidget *parent)
 {
 	PurpleProxyInfo *proxy_info;
-	GtkWidget *frame;
 	GtkWidget *vbox;
 	GtkWidget *vbox2;
 
 	if (dialog->proxy_frame != NULL)
 		gtk_widget_destroy(dialog->proxy_frame);
 
-	frame = pidgin_make_frame(parent, _("Proxy Options"));
-	dialog->proxy_frame = gtk_widget_get_parent(gtk_widget_get_parent(frame));
-
-	gtk_box_reorder_child(GTK_BOX(parent), dialog->proxy_frame, 1);
-	gtk_widget_show(dialog->proxy_frame);
-
 	/* Main vbox */
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	dialog->proxy_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_container_add(GTK_CONTAINER(parent), vbox);
 	gtk_widget_show(vbox);
 
 	/* Proxy Type drop-down. */
@@ -1496,15 +1480,15 @@
 		dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin);
 
 	dialog->window = win = pidgin_create_dialog((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"),
-		PIDGIN_HIG_BORDER, "account", FALSE);
+		PIDGIN_HIG_BOX_SPACE, "account", FALSE);
 
 	g_signal_connect(G_OBJECT(win), "delete_event",
 					 G_CALLBACK(account_win_destroy_cb), dialog);
 
 	/* Setup the vbox */
-	main_vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BORDER);
-
-	notebook = gtk_notebook_new();
+	main_vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BOX_SPACE);
+
+	dialog->notebook = notebook = gtk_notebook_new();
 	gtk_box_pack_start(GTK_BOX(main_vbox), notebook, FALSE, FALSE, 0);
 	gtk_widget_show(GTK_WIDGET(notebook));
 
@@ -1530,15 +1514,15 @@
 	if (!dialog->prpl_info || !dialog->prpl_info->register_user)
 		gtk_widget_hide(button);
 
-	/* Setup the page with 'Advanced'. */
-	dialog->bottom_vbox = dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
+	/* Setup the page with 'Advanced' (protocol options). */
+	add_protocol_options(dialog);
+
+	/* Setup the page with 'Proxy'. */
+	dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
 	gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER);
 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dbox,
-			gtk_label_new_with_mnemonic(_("_Advanced")));
+			gtk_label_new_with_mnemonic(_("_Proxy")));
 	gtk_widget_show(dbox);
-
-	/** Setup the bottom frames. */
-	add_protocol_options(dialog, dbox);
 	add_proxy_options(dialog, dbox);
 
 	/* Cancel button */
--- a/pidgin/gtkblist.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkblist.c	Sat Mar 28 16:59:30 2009 +0000
@@ -3898,7 +3898,7 @@
 	presence = purple_buddy_get_presence(b);
 
 	/* Name is all that is needed */
-	if (aliased && biglist) {
+	if (!aliased || biglist) {
 
 		/* Status Info */
 		prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
@@ -4038,7 +4038,7 @@
 	}
 
 	/* Put it all together */
-	if (aliased && biglist && (statustext || idletime)) {
+	if ((!aliased || biglist) && (statustext || idletime)) {
 		/* using <span size='smaller'> breaks the status, so it must be seperated into <small><span>*/
 		if (name_color) {
 			text = g_strdup_printf("<span font_desc='%s' foreground='%s'>%s</span>\n"
@@ -6443,7 +6443,7 @@
 		gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
 		PidginBlistNode *ui;
 		PurpleConversation *conv;
-		gboolean hidden;
+		gboolean hidden = FALSE;
 		GdkColor *bgcolor = NULL;
 		FontColorPair *pair;
 		PidginBlistTheme *theme;
@@ -6701,14 +6701,27 @@
 			whoalias = NULL;
 
 		g = NULL;
-		if ((grp != NULL) && (*grp != '\0') && ((g = purple_find_group(grp)) == NULL))
+		if ((grp != NULL) && (*grp != '\0'))
 		{
-			g = purple_group_new(grp);
-			purple_blist_add_group(g, NULL);
-		}
-
-		b = purple_buddy_new(data->account, who, whoalias);
-		purple_blist_add_buddy(b, NULL, g, NULL);
+			if ((g = purple_find_group(grp)) == NULL)
+			{
+				g = purple_group_new(grp);
+				purple_blist_add_group(g, NULL);
+			}
+
+			b = purple_find_buddy_in_group(data->account, who, g);
+		}
+		else if ((b = purple_find_buddy(data->account, who)) != NULL)
+		{
+			g = purple_buddy_get_group(b);
+		}
+
+		if (b == NULL)
+		{
+			b = purple_buddy_new(data->account, who, whoalias);
+			purple_blist_add_buddy(b, NULL, g, NULL);
+		}
+
 		purple_account_add_buddy(data->account, b);
 
 		/* Offer to merge people with the same alias. */
--- a/pidgin/gtkdialogs.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkdialogs.c	Sat Mar 28 16:59:30 2009 +0000
@@ -189,7 +189,7 @@
 	{N_("Italian"),             "it", "Claudio Satriano", "satriano@na.infn.it"},
 	{N_("Japanese"),            "ja", "Takashi Aihana", "aihana@gnome.gr.jp"},
 	{N_("Georgian"),            "ka", N_("Ubuntu Georgian Translators"), "alexander.didebulidze@stusta.mhn.de"},
-	{"Khmer",                   "km", "Khoem Sokhem", "khoemsokhem@khmeros.info"},
+	{N_("Khmer"),               "km", "Khoem Sokhem", "khoemsokhem@khmeros.info"},
 	{N_("Kannada"),             "kn", N_("Kannada Translation team"), "translation@sampada.info"},
 	{N_("Korean"),              "ko", "Sushizang", "sushizang@empal.com"},
 	{N_("Kurdish"),             "ku", "Erdal Ronahi", "erdal.ronahi@gmail.com"},
--- a/pidgin/gtkprefs.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkprefs.c	Sat Mar 28 16:59:30 2009 +0000
@@ -2385,14 +2385,12 @@
 	/* Auto-away stuff */
 	vbox = pidgin_make_frame(ret, _("Auto-away"));
 
-	button = pidgin_prefs_checkbox(_("Change status when _idle"),
-						   "/purple/away/away_when_idle", vbox);
-
 	select = pidgin_prefs_labeled_spin_button(vbox,
 			_("_Minutes before becoming idle:"), "/purple/away/mins_before_away",
 			1, 24 * 60, sg);
-	g_signal_connect(G_OBJECT(button), "clicked",
-					 G_CALLBACK(pidgin_toggle_sensitive), select);
+
+	button = pidgin_prefs_checkbox(_("Change status when _idle"),
+						   "/purple/away/away_when_idle", vbox);
 
 	/* TODO: Show something useful if we don't have any saved statuses. */
 	menu = pidgin_status_menu(purple_savedstatus_get_idleaway(), G_CALLBACK(set_idle_away));
@@ -2404,7 +2402,6 @@
 
 	if (!purple_prefs_get_bool("/purple/away/away_when_idle")) {
 		gtk_widget_set_sensitive(GTK_WIDGET(menu), FALSE);
-		gtk_widget_set_sensitive(GTK_WIDGET(select), FALSE);
 		gtk_widget_set_sensitive(GTK_WIDGET(label), FALSE);
 	}
 
--- a/pidgin/gtkroomlist.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkroomlist.c	Sat Mar 28 16:59:30 2009 +0000
@@ -64,7 +64,6 @@
 	gint num_rooms, total_rooms;
 	GtkWidget *tipwindow;
 	GdkRectangle tip_rect;
-	guint timeout;
 	PangoLayout *tip_layout;
 	PangoLayout *tip_name_layout;
 	int tip_height;
--- a/pidgin/gtkutils.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/gtkutils.c	Sat Mar 28 16:59:30 2009 +0000
@@ -2451,11 +2451,6 @@
 	dialog->callback = callback;
 	dialog->data = data;
 
-	if (dialog->icon_filesel != NULL) {
-		gtk_window_present(GTK_WINDOW(dialog->icon_filesel));
-		return NULL;
-	}
-
 	current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder");
 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
 
--- a/pidgin/plugins/gevolution/gevo-util.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/plugins/gevolution/gevo-util.c	Sat Mar 28 16:59:30 2009 +0000
@@ -41,8 +41,12 @@
 		purple_blist_add_group(group, NULL);
 	}
 
-	buddy = purple_buddy_new(account, buddy_name, alias);
-	purple_blist_add_buddy(buddy, NULL, group, NULL);
+	if ((buddy = purple_find_buddy_in_group(account, buddy_name, group)))
+	{	
+		buddy = purple_buddy_new(account, buddy_name, alias);
+		purple_blist_add_buddy(buddy, NULL, group, NULL);
+	}
+
 	purple_account_add_buddy(account, buddy);
 
 	if (conv != NULL)
--- a/pidgin/plugins/gevolution/gevolution.h	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/plugins/gevolution/gevolution.h	Sat Mar 28 16:59:30 2009 +0000
@@ -75,7 +75,7 @@
 
 	GtkWidget *win;
 	GtkWidget *accounts_menu;
-	GtkWidget *screenname;
+	GtkWidget *username;
 	GtkWidget *firstname;
 	GtkWidget *lastname;
 	GtkWidget *email;
--- a/pidgin/win32/untar.c	Mon Mar 16 21:45:24 2009 +0000
+++ b/pidgin/win32/untar.c	Sat Mar 28 16:59:30 2009 +0000
@@ -212,9 +212,11 @@
 	 * make sure the directory path exists.
 	 */
 	fpdst = createpath(dst);
-	if (!fpdst)
+	if (!fpdst) {
 		/* error message already given */
+		fclose(fpsrc);
 		return;
+	}
 
 #ifdef _POSIX_SOURCE
 # ifndef _WEAK_POSIX
--- a/po/POTFILES.in	Mon Mar 16 21:45:24 2009 +0000
+++ b/po/POTFILES.in	Sat Mar 28 16:59:30 2009 +0000
@@ -62,6 +62,7 @@
 libpurple/plugins/mono/loader/mono.c
 libpurple/plugins/newline.c
 libpurple/plugins/offlinemsg.c
+libpurple/plugins/one_time_password.c
 libpurple/plugins/perl/perl.c
 libpurple/plugins/psychic.c
 libpurple/plugins/signals-test.c
@@ -165,7 +166,6 @@
 libpurple/protocols/silc10/util.c
 libpurple/protocols/silc10/wb.c
 libpurple/protocols/simple/simple.c
-libpurple/protocols/toc/toc.c
 libpurple/protocols/yahoo/yahoo.c
 libpurple/protocols/yahoo/yahoo_doodle.c
 libpurple/protocols/yahoo/yahoo_filexfer.c
--- a/po/de.po	Mon Mar 16 21:45:24 2009 +0000
+++ b/po/de.po	Sat Mar 28 16:59:30 2009 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-02-25 17:28+0100\n"
-"PO-Revision-Date: 2009-02-25 17:28+0100\n"
+"POT-Creation-Date: 2009-03-28 16:59+0100\n"
+"PO-Revision-Date: 2009-03-28 16:53+0100\n"
 "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: German <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -2630,6 +2630,31 @@
 msgid "Do not ask. Always save in pounce."
 msgstr "Nicht nachfragen. Immer als Alarm sichern."
 
+msgid "One Time Password"
+msgstr ""
+
+#. *< type
+#. *< ui_requirement
+#. *< flags
+#. *< dependencies
+#. *< priority
+#. *< id
+msgid "One Time Password Support"
+msgstr ""
+
+#. *< name
+#. *< version
+#. *  summary
+msgid "Enforce that passwords are used only once."
+msgstr ""
+
+#. *  description
+msgid ""
+"Allows you to enforce on a per-account basis that passwords not being saved "
+"are only used in a single successful connection.\n"
+"Note: The account password must not be saved for this to work."
+msgstr ""
+
 #. *< type
 #. *< ui_requirement
 #. *< flags
@@ -4440,16 +4465,24 @@
 msgstr "Kann den Benutzer %s nicht anpingen"
 
 #, c-format
-msgid "Unable to buzz, because there is nothing known about user %s."
-msgstr "Kann nicht anklopfen, da nichts über den Benutzer %s bekannt ist."
-
-#, c-format
-msgid "Unable to buzz, because user %s might be offline."
-msgstr "Kann nicht anklopfen, da der Benutzer %s vielleicht offline ist."
-
-#, c-format
-msgid "Unable to buzz, because the user %s does not support it."
-msgstr "Kann nicht anklopfen, da der Benutzer %s dies nicht unterstützt."
+msgid "Unable to buzz, because there is nothing known about %s."
+msgstr "Kann nicht anklopfen, da nichts über %s bekannt ist."
+
+#, c-format
+msgid "Unable to buzz, because %s might be offline."
+msgstr "Kann nicht anklopfen, da %s vielleicht offline ist."
+
+#, c-format
+msgid ""
+"Unable to buzz, because %s does not support it or does not wish to receive "
+"buzzes now."
+msgstr ""
+"Kann nicht anklopfen, da %s dies nicht unterstützt oder im Moment nicht "
+"möchte."
+
+#, c-format
+msgid "Buzzing %s..."
+msgstr "%s anklopfen..."
 
 #. Yahoo only supports one attention command: the 'buzz'.
 #. This is index number YAHOO_BUZZ.
@@ -4460,10 +4493,6 @@
 msgid "%s has buzzed you!"
 msgstr "%s hat bei Ihnen angeklopft!"
 
-#, c-format
-msgid "Buzzing %s..."
-msgstr "%s anklopfen..."
-
 msgid "config:  Configure a chat room."
 msgstr "config:  Konfiguriere einen Chatraum."
 
@@ -4618,6 +4647,19 @@
 msgid "Error in chat %s"
 msgstr "Fehler im Chat %s"
 
+#, fuzzy
+msgid "An error occured on the in-band bytestream transfer\n"
+msgstr "Beim Öffnen der Datei trat ein Fehler auf."
+
+msgid "Transfer was closed."
+msgstr "Übertragung wurde geschlossen"
+
+msgid "Failed to open the file"
+msgstr "Öffnen der Datei fehlgeschlagen"
+
+msgid "Failed to open in-band bytestream"
+msgstr ""
+
 #, c-format
 msgid "Unable to send file to %s, user does not support file transfers"
 msgstr ""
@@ -6435,7 +6477,7 @@
 "sein oder mit einem Buchstaben beginnen und nur Buchstaben, Ziffern und "
 "Leerzeichen enthalten oder nur aus Ziffern bestehen."
 
-#. Unregistered screen name
+#. Unregistered username
 #. uid is not exist
 msgid "Invalid username."
 msgstr "Ungültiger Benutzername."
@@ -6451,7 +6493,7 @@
 msgid "The AOL Instant Messenger service is temporarily unavailable."
 msgstr "Der AOL-Sofortnachrichtendienst ist zur Zeit nicht erreichbar."
 
-#. screen name connecting too frequently
+#. username connecting too frequently
 #. IP address connecting too frequently
 msgid ""
 "You have been connecting and disconnecting too frequently. Wait ten minutes "
@@ -6652,7 +6694,7 @@
 msgstr[1] ""
 "Sie haben %hu Nachrichten von %s aus unbekannten Gründen nicht erhalten."
 
-#. Data is assumed to be the destination sn
+#. Data is assumed to be the destination bn
 #, c-format
 msgid "Unable to send message: %s"
 msgstr "Kann die Nachricht nicht senden: %s"
@@ -7253,6 +7295,36 @@
 msgid "Could not change buddy information."
 msgstr "Konnte Buddy-Informationen nicht bearbeiten."
 
+msgid "Mobile"
+msgstr "Mobil"
+
+msgid "Note"
+msgstr "Bemerkung"
+
+#. callback
+msgid "Buddy Memo"
+msgstr "Buddy-Notiz"
+
+msgid "Change his/her memo as you like"
+msgstr ""
+
+#, fuzzy
+msgid "_Modify"
+msgstr "Bearbeiten"
+
+#, fuzzy
+msgid "Memo Modify"
+msgstr "Bearbeiten"
+
+msgid "Server says:"
+msgstr "Server meldet:"
+
+msgid "Your request was accepted."
+msgstr "Ihre Anfrage wurde akzeptiert."
+
+msgid "Your request was rejected."
+msgstr "Ihre Anfrage wurde abgelehnt."
+
 #, c-format
 msgid "%u requires verification"
 msgstr "%u erfordert Autorisierung"
@@ -7701,7 +7773,6 @@
 "Unbekannte Antwort bei der Anmeldung (0x%02X):\n"
 "%s"
 
-#. we didn't successfully connect. tdt->toc_fd is valid here
 msgid "Unable to connect."
 msgstr "Verbindung nicht möglich."
 
@@ -8613,9 +8684,6 @@
 msgid "Unit"
 msgstr "Abteilung"
 
-msgid "Note"
-msgstr "Bemerkung"
-
 msgid "Join Chat"
 msgstr "Chat betreten"
 
@@ -9309,188 +9377,13 @@
 msgstr "Auth-Domain"
 
 #, c-format
-msgid "Looking up %s"
-msgstr "Suche nach %s"
-
-#, c-format
-msgid "Connect to %s failed"
-msgstr "Verbindung mit %s fehlgeschlagen"
-
-#, c-format
-msgid "Signon: %s"
-msgstr "Anmeldung: %s"
-
-#, c-format
-msgid "Unable to write file %s."
-msgstr "Datei %s konnte nicht geschrieben werden."
-
-#, c-format
-msgid "Unable to read file %s."
-msgstr "Datei %s konnte nicht gelesen werden."
-
-#, c-format
-msgid "Message too long, last %s bytes truncated."
-msgstr "Nachricht zu lange, letzten %s Bytes abgeschnitten."
-
-#, c-format
-msgid "%s not currently logged in."
-msgstr "%s ist zur Zeit nicht online."
-
-#, c-format
-msgid "Warning of %s not allowed."
-msgstr "Verwarnung von %s nicht erlaubt."
-
-msgid "A message has been dropped, you are exceeding the server speed limit."
-msgstr ""
-"Eine Nachricht ging verloren. Sie überschreiten die Geschwindigkeitsgrenze "
-"des Servers."
-
-#, c-format
-msgid "Chat in %s is not available."
-msgstr "Chat in %s ist nicht verfügbar."
-
-#, c-format
-msgid "You are sending messages too fast to %s."
-msgstr "Sie verschicken die Nachrichten an %s zu schnell."
-
-#, c-format
-msgid "You missed an IM from %s because it was too big."
-msgstr "Eine Nachricht von %s hat Sie nicht erreicht, da sie zu groß war."
-
-#, c-format
-msgid "You missed an IM from %s because it was sent too fast."
-msgstr ""
-"Eine Nachricht von %s hat Sie nicht erreicht, da sie zu schnell gesendet "
-"wurde."
-
-msgid "Failure."
-msgstr "Fehler."
-
-msgid "Too many matches."
-msgstr "Zu viele Übereinstimmungen."
-
-msgid "Need more qualifiers."
-msgstr "Benötige mehr Angaben."
-
-msgid "Dir service temporarily unavailable."
-msgstr "Verzeichnis-Dienst ist zur Zeit nicht verfügbar."
-
-msgid "Email lookup restricted."
-msgstr "E-Mail-Suche eingeschränkt."
-
-msgid "Keyword ignored."
-msgstr "Stichwort ignoriert."
-
-msgid "No keywords."
-msgstr "Keine Stichwörter."
-
-msgid "User has no directory information."
-msgstr "Der Benutzer hat kein Profil."
-
-msgid "Country not supported."
-msgstr "Land nicht unterstützt."
-
-#, c-format
-msgid "Failure unknown: %s."
-msgstr "Unbekannter Fehler: %s."
-
-msgid "Incorrect username or password."
-msgstr "Ungültiger Benutzername oder Passwort."
-
-msgid "The service is temporarily unavailable."
-msgstr "Der Dienst ist zur Zeit nicht verfügbar."
-
-msgid "Your warning level is currently too high to log in."
-msgstr "Ihre Warnstufe ist zur Zeit zu hoch, um sich anzumelden."
-
-msgid ""
-"You have been connecting and disconnecting too frequently.  Wait ten minutes "
-"and try again.  If you continue to try, you will need to wait even longer."
-msgstr ""
-"Sie haben Sich zu schnell an- und abgemeldet. Warten Sie 10 Minuten und "
-"versuchen Sie es erneut. Wenn Sie es weiter versuchen, werden sie noch "
-"länger warten müssen."
-
-#, c-format
-msgid "An unknown signon error has occurred: %s."
-msgstr "Unbekannter Anmeldungsfehler: %s."
-
-#, c-format
-msgid "An unknown error, %d, has occurred.  Info: %s"
-msgstr "Unbekannter Fehler '%d' aufgetreten. Info: %s"
-
-msgid "Invalid Groupname"
-msgstr "Ungültiger Gruppenname"
-
-msgid "Connection Closed"
-msgstr "Verbindung geschlossen"
-
-msgid "Waiting for reply..."
-msgstr "Warte auf Antwort..."
-
-msgid "TOC has come back from its pause. You may now send messages again."
-msgstr ""
-"TOC ist von seiner Pause zurückgekehrt. Sie können wieder Nachrichten senden."
-
-msgid "Password Change Successful"
-msgstr "Passwortänderung erfolgreich"
-
-msgid "_Group:"
-msgstr "_Gruppe:"
-
-msgid "Get Dir Info"
-msgstr "Verzeichnisinformation abrufen"
-
-msgid "Set Dir Info"
-msgstr "Verzeichnisinformation abrufen"
-
-#, c-format
-msgid "Could not open %s for writing!"
-msgstr "Kann %s nicht zum Schreiben öffnen!"
-
-msgid "File transfer failed; other side probably canceled."
-msgstr ""
-"Dateiübertragung gescheitert; die andere Seite hat die Dateiübertragung "
-"wahrscheinlich abgebrochen."
-
-msgid "Could not connect for transfer."
-msgstr "Übertragungsverbindung konnte nicht hergestellt werden."
-
-msgid "Could not write file header.  The file will not be transferred."
-msgstr ""
-"Konnte keinen Datei-Header schreiben. Die Datei wurde nicht übermittelt."
-
-msgid "Save As..."
-msgstr "Speichern unter..."
-
-#, c-format
-msgid "%s requests %s to accept %d file: %s (%.2f %s)%s%s"
-msgid_plural "%s requests %s to accept %d files: %s (%.2f %s)%s%s"
-msgstr[0] "%s bittet %s %d Datei zu akzeptieren: %s (%.2f %s)%s%s"
-msgstr[1] "%s bittet %s %d Dateien zu akzeptieren: %s (%.2f %s)%s%s"
-
-#, c-format
-msgid "%s requests you to send them a file"
-msgstr "%s bittet Sie eine Datei zu senden"
-
-#. *< type
-#. *< ui_requirement
-#. *< flags
-#. *< dependencies
-#. *< priority
-#. *< id
-#. *< name
-#. *< version
-#. *  summary
-#. *  description
-msgid "TOC Protocol Plugin"
-msgstr "TOC-Protokoll-Plugin"
-
-#, c-format
 msgid "%s has sent you a webcam invite, which is not yet supported."
 msgstr ""
 "%s hat Ihnen eine Webcam-Einladung gesendet, die noch nicht unterstützt wird."
 
+msgid "Your SMS was not delivered"
+msgstr "Ihre SMS wurde nicht ausgeliefert"
+
 msgid "Your Yahoo! message did not get sent."
 msgstr "Ihre Yahoo!-Nachricht wurde nicht verschickt."
 
@@ -10099,9 +9992,6 @@
 msgid "Extended away"
 msgstr "Abwesend (erweitert)"
 
-msgid "Mobile"
-msgstr "Mobil"
-
 msgid "Listening to music"
 msgstr "Musik hören"
 
@@ -10143,18 +10033,6 @@
 msgid "%x %X"
 msgstr "%x %X"
 
-#, c-format
-msgid "Error Reading %s"
-msgstr "Fehler beim Lesen von %s"
-
-#, c-format
-msgid ""
-"An error was encountered reading your %s.  They have not been loaded, and "
-"the old file has been renamed to %s~."
-msgstr ""
-"Beim Einlesen Ihrer %s trat ein Fehler auf.  Die Liste wurde nicht geladen "
-"und die alte Datei wurde in %s~ umbenannt."
-
 msgid "Calculating..."
 msgstr "Berechne..."
 
@@ -10230,6 +10108,14 @@
 msgstr "Verbindung zu %s nicht möglich: %s"
 
 #, c-format
+msgid ""
+"Unable to connect to %s: Server requires TLS/SSL, but no TLS/SSL support was "
+"found."
+msgstr ""
+"Verbindung zu %s fehlgeschlagen: Der Server verlangt TLS/SSL, es wurde "
+"jedoch kein TLS/SSL-Support gefunden."
+
+#, c-format
 msgid " - %s"
 msgstr " - %s"
 
@@ -10259,6 +10145,18 @@
 msgid "Address already in use."
 msgstr "Adresse wird bereits benutzt."
 
+#, c-format
+msgid "Error Reading %s"
+msgstr "Fehler beim Lesen von %s"
+
+#, c-format
+msgid ""
+"An error was encountered reading your %s.  The file has not been loaded, and "
+"the old file has been renamed to %s~."
+msgstr ""
+"Beim Einlesen Ihrer %s trat ein Fehler auf.  Die Datei wurde nicht geladen "
+"und die alte Datei wurde in %s~ umbenannt."
+
 msgid "Internet Messenger"
 msgstr "Internet-Sofortnachrichtendienst"
 
@@ -10301,10 +10199,8 @@
 msgid "Use this buddy _icon for this account:"
 msgstr "Dieses Buddy-_Icon für dieses Konto benutzen:"
 
-#. Build the protocol options frame.
-#, c-format
-msgid "%s Options"
-msgstr "%s Einstellungen"
+msgid "_Advanced"
+msgstr "E_rweitert"
 
 msgid "Use GNOME Proxy Settings"
 msgstr "Benutze GNOME-Proxy-Einstellungen"
@@ -10339,9 +10235,6 @@
 msgid "you can see the butterflies mating"
 msgstr "Sie können den Schmetterlingen beim Paaren zusehen"
 
-msgid "Proxy Options"
-msgstr "Proxy-Optionen"
-
 msgid "Proxy _type:"
 msgstr "Proxy-_Typ:"
 
@@ -10369,8 +10262,8 @@
 msgid "Create _this new account on the server"
 msgstr "Dieses _neue Konto auf dem Server anlegen"
 
-msgid "_Advanced"
-msgstr "_Erweitert"
+msgid "_Proxy"
+msgstr "Pr_oxy"
 
 # Aktiv
 msgid "Enabled"
@@ -10588,6 +10481,9 @@
 msgid "/Tools/_Certificates"
 msgstr "/Werkzeuge/_Zertifikate"
 
+msgid "/Tools/Custom Smile_ys"
+msgstr "/Werkzeuge/Benutzerdefinierte Smile_ys"
+
 msgid "/Tools/Plu_gins"
 msgstr "/Werkzeuge/Plu_gins"
 
@@ -10597,9 +10493,6 @@
 msgid "/Tools/Pr_ivacy"
 msgstr "/Werkzeuge/Pri_vatsphäre"
 
-msgid "/Tools/Smile_y"
-msgstr "/Werkzeuge/Smile_y"
-
 msgid "/Tools/_File Transfers"
 msgstr "/Werkzeuge/_Dateiübertragungen"
 
@@ -10717,8 +10610,8 @@
 msgid "By status"
 msgstr "Nach Status"
 
-msgid "By log size"
-msgstr "Nach Größe der Logs"
+msgid "By recent log activity"
+msgstr "Nach letzter Mitschnitts-Aktivität"
 
 #, c-format
 msgid "%s disconnected"
@@ -10734,6 +10627,9 @@
 msgid "Re-enable"
 msgstr "Reaktivieren"
 
+msgid "SSL FAQs"
+msgstr "SSL-FAQs"
+
 msgid "Welcome back!"
 msgstr "Willkommen zurück!"
 
@@ -10824,6 +10720,9 @@
 msgid "A_lias:"
 msgstr "A_lias:"
 
+msgid "_Group:"
+msgstr "_Gruppe:"
+
 msgid "Auto_join when account becomes online."
 msgstr "Automatisch _beitreten, wenn das Konto online geht."
 
@@ -11352,6 +11251,9 @@
 msgid "Ubuntu Georgian Translators"
 msgstr "Ubuntu-Georgisch-Übersetzer"
 
+msgid "Khmer"
+msgstr "Khmer"
+
 msgid "Kannada"
 msgstr "Kannada"
 
@@ -11825,15 +11727,6 @@
 msgid "Enable typing notification"
 msgstr "Tipp-Benachrichtigung aktivieren"
 
-msgid "_Copy Email Address"
-msgstr "Kopiere _E-Mail-Adresse"
-
-msgid "_Open Link in Browser"
-msgstr "Ö_ffne Link im Browser"
-
-msgid "_Copy Link Location"
-msgstr "_Kopiere den Link"
-
 msgid ""
 "<span size='larger' weight='bold'>Unrecognized file type</span>\n"
 "\n"
@@ -12086,6 +11979,7 @@
 "\n"
 "  -c, --config=DIR    use DIR for config files\n"
 "  -d, --debug         print debugging messages to stdout\n"
+"  -f, --force-online  force online, regardless of network status\n"
 "  -h, --help          display this help and exit\n"
 "  -m, --multiple      do not ensure single instance\n"
 "  -n, --nologin       don't automatically login\n"
@@ -12100,6 +11994,7 @@
 "\n"
 "  -c, --config=VERZ   benutze VERZ als Konfigurationsverzeichnis\n"
 "  -d, --debug         gibt Debugging-Meldungen nach stdout aus\n"
+"  -f, --force-online  online erzwingen, ungeachtet des Netzwerk-Status\n"
 "  -h, --help          zeigt diese Hilfe und beendet das Programm\n"
 "  -m, --multiple      mehrere Instanzen erlauben\n"
 "  -n, --nologin       nicht automatisch anmelden\n"
@@ -12117,6 +12012,7 @@
 "\n"
 "  -c, --config=DIR    use DIR for config files\n"
 "  -d, --debug         print debugging messages to stdout\n"
+"  -f, --force-online  force online, regardless of network status\n"
 "  -h, --help          display this help and exit\n"
 "  -m, --multiple      do not ensure single instance\n"
 "  -n, --nologin       don't automatically login\n"
@@ -12130,6 +12026,7 @@
 "\n"
 "  -c, --config=VERZ   benutze VERZ als Konfigurationsverzeichnis\n"
 "  -d, --debug         gibt Debugging-Meldungen nach stdout aus\n"
+"  -f, --force-online  online erzwingen, ungeachtet des Netzwerkstatus\n"
 "  -h, --help          zeigt diese Hilfe und beendet das Programm\n"
 "  -m, --multiple      mehrere Instanzen erlauben\n"
 "  -n, --nologin       nicht automatisch anmelden\n"
@@ -12176,12 +12073,6 @@
 msgid "Exiting because another libpurple client is already running.\n"
 msgstr "Wird geschlossen, da bereits ein anderer libpurple-Client läuft\n"
 
-msgid "Open All Messages"
-msgstr "Alle Nachrichten öffnen"
-
-msgid "<span weight=\"bold\" size=\"larger\">You have mail!</span>"
-msgstr "<span weight=\"bold\" size=\"larger\">Sie haben Post!</span>"
-
 #, c-format
 msgid "%s has %d new message."
 msgid_plural "%s has %d new messages."
@@ -12210,6 +12101,24 @@
 msgstr ""
 "Das benutzerdefinierte Browserkommando wurde ausgewählt, aber nicht gesetzt."
 
+msgid "Open All Messages"
+msgstr "Alle Nachrichten öffnen"
+
+msgid "<span weight=\"bold\" size=\"larger\">You have mail!</span>"
+msgstr "<span weight=\"bold\" size=\"larger\">Sie haben Post!</span>"
+
+msgid "New Pounces"
+msgstr "Neuer Alarm"
+
+msgid "Dismiss"
+msgstr "Verwerfen"
+
+msgid "<span weight=\"bold\" size=\"larger\">You have pounced!</span>"
+msgstr "<span weight=\"bold\" size=\"larger\">Sie haben geklopft!</span>"
+
+msgid "No message"
+msgstr "Keine Nachricht"
+
 msgid "The following plugins will be unloaded."
 msgstr "Die folgenden Plugins werden entladen."
 
@@ -12258,6 +12167,9 @@
 msgid "Select a file"
 msgstr "Wählen Sie eine Datei"
 
+msgid "Modify Buddy Pounce"
+msgstr "Buddy-Alarm bearbeiten"
+
 #. Create the "Pounce on Whom" frame.
 msgid "Pounce on Whom"
 msgstr "Bei wem alarmieren"
@@ -12328,6 +12240,49 @@
 msgid "Pounce Target"
 msgstr "Alarm-Ziel"
 
+#, fuzzy
+msgid "Started typing"
+msgstr "zu tippen beginnt"
+
+#, fuzzy
+msgid "Paused while typing"
+msgstr "beim Tippen anhält"
+
+#, fuzzy
+msgid "Signed on"
+msgstr "sich anmeldet"
+
+#, fuzzy
+msgid "Returned from being idle"
+msgstr "%s ist nicht mehr inaktiv (%s)"
+
+#, fuzzy
+msgid "Returned from being away"
+msgstr "wieder anwesend ist"
+
+#, fuzzy
+msgid "Stopped typing"
+msgstr "Tippen gestoppt"
+
+#, fuzzy
+msgid "Signed off"
+msgstr "sich abmeldet"
+
+#, fuzzy
+msgid "Became idle"
+msgstr "untätig wird"
+
+#, fuzzy
+msgid "Went away"
+msgstr "Bei Abwesenheit"
+
+#, fuzzy
+msgid "Sent a message"
+msgstr "Eine Nachricht senden"
+
+msgid "Unknown.... Please report this!"
+msgstr "Unbekannt.... Bitte berichten Sie dieses Problem!"
+
 msgid "Smiley theme failed to unpack."
 msgstr "Smiley-Thema konnte nicht entpackt werden."
 
@@ -12350,6 +12305,11 @@
 msgid "Cl_ose conversations with the Escape key"
 msgstr "_Schließe Gespräche mit der Escape-Taste"
 
+#. Buddy List Themes
+msgid "Buddy List Theme"
+msgstr "Buddy-Listen-Thema"
+
+#. System Tray
 msgid "System Tray Icon"
 msgstr "Kontrollleisten-Icon"
 
@@ -12671,12 +12631,12 @@
 msgid "Auto-away"
 msgstr "Automatisch abwesend"
 
+msgid "_Minutes before becoming idle:"
+msgstr "_Minuten, bevor auf abwesend gesetzt wird:"
+
 msgid "Change status when _idle"
 msgstr "Ändere Status, wenn _inaktiv"
 
-msgid "_Minutes before becoming idle:"
-msgstr "_Minuten, bevor auf abwesend gesetzt wird:"
-
 msgid "Change _status to:"
 msgstr "Ändere _Status zu:"
 
@@ -12833,6 +12793,12 @@
 msgid "Status for %s"
 msgstr "Status für %s"
 
+#.
+#. * TODO: We should enable/disable the add button based on
+#. *       whether the user has entered all required data.  That
+#. *       would eliminate the need for this check and provide a
+#. *       better user experience.
+#.
 msgid "Custom Smiley"
 msgstr "Benutzerdefinierter Smiley"
 
@@ -12842,16 +12808,16 @@
 msgid "Please provide a shortcut to associate with the smiley."
 msgstr "Bitte geben Sie eine Tastenkombination für den Smiley an."
 
+#, c-format
+msgid ""
+"A custom smiley for '%s' already exists.  Please use a different shortcut."
+msgstr ""
+"Für '%s' existiert bereits ein benutzerdefinierter Smiley. Bitten wählen Sie "
+"eine andere Tastenkombination."
+
 msgid "Duplicate Shortcut"
 msgstr "Doppelte Tastenkombination"
 
-msgid ""
-"A custom smiley for the selected shortcut already exists. Please specify a "
-"different shortcut."
-msgstr ""
-"Für diese Tastenkombination existiert bereits ein benutzerdefinierter "
-"Smiley. Bitten wählen Sie eine andere Tastenkombination."
-
 msgid "Please select an image for the smiley."
 msgstr "Bitte wählen Sie ein Bild für den Smiley."
 
@@ -12861,16 +12827,21 @@
 msgid "Add Smiley"
 msgstr "Smiley hinzufügen"
 
-msgid "Smiley _Image"
-msgstr "Smiley-_Bild"
-
-#. Smiley shortcut
-msgid "Smiley S_hortcut"
-msgstr "_Tastenkombination"
+msgid "_Image:"
+msgstr "_Bild:"
+
+#. Shortcut text
+#, fuzzy
+msgid "S_hortcut text:"
+msgstr "Tastenkombination"
 
 msgid "Smiley"
 msgstr "Smiley"
 
+#, fuzzy
+msgid "Shortcut Text"
+msgstr "Tastenkombination"
+
 msgid "Custom Smiley Manager"
 msgstr "Verwaltung für benutzerdefinierte Smileys"
 
@@ -12996,6 +12967,15 @@
 "Bild '%s' konnte nicht geladen werden: Grund unbekannt, vermutlich eine "
 "korrupte Bilddatei"
 
+msgid "_Open Link"
+msgstr "Ö_ffne Link"
+
+msgid "_Copy Link Location"
+msgstr "_Kopiere den Link"
+
+msgid "_Copy Email Address"
+msgstr "Kopiere _E-Mail-Adresse"
+
 msgid "Save File"
 msgstr "Datei speichern"
 
@@ -14023,6 +14003,3 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr ""
 "Dieses Plugin ist nützlich zur Fehlersuche in XMPP-Servern oder -Clients."
-
-#~ msgid "Unable to retrieve MSN Address Book"
-#~ msgstr "Konnte das MSN-Adressbuch nicht abrufen"