changeset 23129:ac567757d236

propagate from branch 'im.pidgin.pidgin' (head 6be4a11c3e1bf403bbb6e1a7a754e4b99e7d9a44) to branch 'im.pidgin.pidgin.custom_smiley' (head fb801dc3cb44bc81a383a9e0a44ba099a3e99d1e)
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 07 May 2008 03:32:43 +0000
parents 4409f8a0d7aa (diff) a3b4a9061552 (current diff)
children 9c0a47402f7a
files ChangeLog.API libpurple/protocols/msn/msn.c libpurple/protocols/msn/slp.c pidgin/gtkaccount.c pidgin/gtkblist.c pidgin/gtkconv.c pidgin/gtkimhtml.c pidgin/gtkimhtmltoolbar.c
diffstat 94 files changed, 1186 insertions(+), 630 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Apr 28 07:43:50 2008 +0000
+++ b/COPYRIGHT	Wed May 07 03:32:43 2008 +0000
@@ -263,6 +263,7 @@
 John Moody
 Tim Mooney
 Sergio Moretto
+Andrei Mozzhuhin
 Christian Muise
 Richard Nelson
 Dennis Nezic
--- a/ChangeLog	Mon Apr 28 07:43:50 2008 +0000
+++ b/ChangeLog	Wed May 07 03:32:43 2008 +0000
@@ -7,6 +7,10 @@
 	* IRC now displays ban lists in-channel for joined channels.
 	* Fixed a bug where the list of loaded plugins would get removed when
 	  switching between different operating systems.
+	* Fix reception of IRC PART without a part message on Undernet
+	  (fixes a problem with litter in the channel user list).
+	* IRC no longer crashes on /list on servers which erroneously omit
+	  RPL_LISTSTART.
 
 	Pidgin:
 	* The typing notification in the conversation history can be disabled or
@@ -14,8 +18,20 @@
 	* Added a plugin (not built by default) which adds a Send button back
 	  to the conversation window. People without physical keyboards have a
 	  hard time with the lack of the button.
-	* Clicking on the buddyicon in the conversation window toggles the size of
-	  the icon between small and large.
+	* Clicking on the buddyicon in the conversation window toggles the
+	  size of the icon between small and large.
+	* The settings of a chat (e.g. Handle in an XMPP chat, or Exchange in
+	  an AIM chat) can be edited from its context menu in the buddy list.
+	* Add a "Present conversation window" preference to the Message
+	  Notification plugin, the "Raise conversation window" option does not
+	  unminimize windows or draw attention to them when they are on other
+	  workspaces the "Present" option should.
+	* Add a preference to set Escape as the keyboard shortcut for closing
+	  the conversation window.
+	* Add an option in the context menu to disable smileys in the selected
+	  text in the conversation history/log viewer. This should help people who
+	  regularly paste code in conversations.
+	* Add a preference to choose the minimum size of the text input.
 
 	General:
 	* The configure script now dies on more absent dependencies.  The
@@ -28,6 +44,9 @@
 	* The Contact Availability Prediction plugin must now be explicitly
 	  enabled.  Use the --enable-cap argument to configure to enable it.
 
+	Finch:
+	* New default binding ctrl+x to open context menus.
+
 version 2.4.1 (03/31/2008):
 	http://developer.pidgin.im/query?status=closed&milestone=2.4.1
 
--- a/autogen.sh	Mon Apr 28 07:43:50 2008 +0000
+++ b/autogen.sh	Wed May 07 03:32:43 2008 +0000
@@ -79,17 +79,23 @@
 	CMD=$1
 	shift
 
+	OUTPUT=`mktemp autogen-XXXX`
+
 	printf "%s" "running ${CMD} ${@}... "
-	OUTPUT=`${CMD} ${@} 2>&1`
+	${CMD} ${@} >${OUTPUT} 2>&1
+
 	if [ $? != 0 ] ; then
 		echo "failed."
-		echo ${OUTPUT}
+		cat ${OUTPUT}
+		rm -f ${OUTPUT}
 		exit 1
 	else
 		echo "done."
-		if [ x"${OUTPUT}" != x"" ] ; then
-			echo ${OUTPUT}
+		if [ `stat --printf="%s" ${OUTPUT}` -ge 0 ] ; then
+			cat ${OUTPUT}
 		fi
+
+		rm -f ${OUTPUT}
 	fi
 }
 
--- a/doc/finch.1.in	Mon Apr 28 07:43:50 2008 +0000
+++ b/doc/finch.1.in	Wed May 07 03:32:43 2008 +0000
@@ -111,9 +111,12 @@
 .B Alt \+ Shift \+ Tab
 Jump to the previous URGENT (highlighted) window.
 .TP
-.B Ctrl \+ o
+.B Ctrl \+ o \fR or \fB F10
 Bring up the menu (if there is one) for a window.
 .TP
+.B F11
+Popup the context menu (if there is one) for the selected widget.
+.TP
 .B Alt \+ /
 Show a list of available key-bindings for the current widget in focus.
 .TP
--- a/finch/gntaccount.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntaccount.c	Wed May 07 03:32:43 2008 +0000
@@ -122,7 +122,7 @@
 	if (value == NULL || *value == '\0')
 	{
 		purple_notify_error(NULL, _("Error"), _("Account was not added"),
-				_("Screenname of an account must be non-empty."));
+				_("Username of an account must be non-empty."));
 		return;
 	}
 	
@@ -526,7 +526,7 @@
 	gnt_box_add_widget(GNT_BOX(window), hbox);
 
 	dialog->screenname = entry = gnt_entry_new(NULL);
-	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Screen name:")));
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Username:")));
 	gnt_box_add_widget(GNT_BOX(hbox), entry);
 
 	/* User splits */
--- a/finch/gntblist.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntblist.c	Wed May 07 03:32:43 2008 +0000
@@ -380,6 +380,27 @@
 		fnode = FINCH_GET_DATA(node);
 		if (fnode && fnode->signed_timer)
 			flag |= GNT_TEXT_FLAG_BLINK;
+	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
+		/* If the node is collapsed, then check to see if any of the priority buddies of
+		 * any of the contacts within this group recently signed on/off, and set the blink
+		 * flag appropriately. */
+		/* XXX: Refs #5444 */
+		/* XXX: there's no way I can ask if the node is expanded or not? *sigh*
+		 * API addition would be necessary */
+#if 0
+		if (!gnt_tree_get_expanded(GNT_TREE(ggblist->tree), node)) {
+			for (node = purple_blist_node_get_first_child(node); node;
+					node = purple_blist_node_get_sibling_next(node)) {
+				PurpleBlistNode *pnode;
+				pnode = purple_contact_get_priority_buddy((PurpleContact*)node);
+				fnode = FINCH_GET_DATA(node);
+				if (fnode && fnode->signed_timer) {
+					flag |= GNT_TEXT_FLAG_BLINK;
+					break;
+				}
+			}
+		}
+#endif
 	}
 
 	return flag;
@@ -560,7 +581,7 @@
 	PurpleBuddy *buddy;
 
 	if (!username)
-		error = _("You must provide a screename for the buddy.");
+		error = _("You must provide a username for the buddy.");
 	else if (!group)
 		error = _("You must provide a group.");
 	else if (!account)
@@ -598,7 +619,7 @@
 
 	purple_request_fields_add_group(fields, group);
 
-	field = purple_request_field_string_new("screenname", _("Screen Name"), username, FALSE);
+	field = purple_request_field_string_new("screenname", _("Username"), username, FALSE);
 	purple_request_field_group_add_field(group, field);
 
 	field = purple_request_field_string_new("alias", _("Alias (optional)"), alias, FALSE);
@@ -623,6 +644,32 @@
 }
 
 static void
+join_chat(PurpleChat *chat)
+{
+	PurpleAccount *account = purple_chat_get_account(chat);
+	const char *name;
+	PurpleConversation *conv;
+	const char *alias;
+
+	/* This hack here is to work around the fact that there's no good way of
+	 * getting the actual name of a chat. I don't understand why we return
+	 * the alias for a chat when all we want is the name. */
+	alias = chat->alias;
+	chat->alias = NULL;
+	name = purple_chat_get_name(chat);
+	conv = purple_find_conversation_with_account(
+			PURPLE_CONV_TYPE_CHAT, name, account);
+	chat->alias = (char *)alias;
+
+	if (!conv || purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))) {
+		serv_join_chat(purple_account_get_connection(account),
+				purple_chat_get_components(chat));
+	} else if (conv) {
+		purple_conversation_present(conv);
+	}
+}
+
+static void
 add_chat_cb(void *data, PurpleRequestFields *allfields)
 {
 	PurpleAccount *account;
@@ -661,8 +708,9 @@
 		purple_blist_add_chat(chat, grp, NULL);
 		purple_blist_alias_chat(chat, alias);
 		purple_blist_node_set_bool((PurpleBlistNode*)chat, "gnt-autojoin", autojoin);
-		if (autojoin)
-			serv_join_chat(purple_account_get_connection(purple_chat_get_account(chat)), purple_chat_get_components(chat));
+		if (autojoin) {
+			join_chat(chat);
+		}
 	}
 }
 
@@ -689,6 +737,7 @@
 
 	field = purple_request_field_string_new("group", _("Group"), grp ? purple_group_get_name(grp) : NULL, FALSE);
 	purple_request_field_group_add_field(group, field);
+	purple_request_field_set_type_hint(field, "group");
 
 	field = purple_request_field_bool_new("autojoin", _("Auto-join"), FALSE);
 	purple_request_field_group_add_field(group, field);
@@ -923,7 +972,7 @@
 
 	if (!node)
 		return;
-	
+
 	if (PURPLE_BLIST_NODE_IS_CONTACT(node))
 		node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)node);
 
@@ -946,8 +995,7 @@
 	}
 	else if (PURPLE_BLIST_NODE_IS_CHAT(node))
 	{
-		PurpleChat *chat = (PurpleChat*)node;
-		serv_join_chat(purple_account_get_connection(purple_chat_get_account(chat)), purple_chat_get_components(chat));
+		join_chat((PurpleChat*)node);
 	}
 }
 
@@ -1034,7 +1082,11 @@
 			else
 				val = g_strdup(purple_request_field_string_get_value(field));
 
-			g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val);  /* val should not be free'd */
+			if (!val) {
+				g_hash_table_remove(purple_chat_get_components(chat), id);
+			} else {
+				g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val);  /* val should not be free'd */
+			}
 		}
 	}
 }
@@ -1065,8 +1117,13 @@
 		} else {
 			field = purple_request_field_string_new(pce->identifier, pce->label,
 					g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier), FALSE);
+			if (pce->secret)
+				purple_request_field_string_set_masked(field, TRUE);
 		}
 
+		if (pce->required)
+			purple_request_field_set_required(field, TRUE);
+
 		purple_request_field_group_add_field(group, field);
 		g_free(pce);
 	}
@@ -2597,7 +2654,7 @@
 
 	purple_request_fields(purple_get_blist(), _("Block/Unblock"),
 						NULL,
-						_("Please enter the screen name or alias of the person "
+						_("Please enter the username or alias of the person "
 						  "you would like to Block/Unblock."),
 						fields,
 						_("OK"), G_CALLBACK(block_select_cb),
@@ -2648,7 +2705,7 @@
 
 	purple_request_fields(purple_get_blist(), _("New Instant Message"),
 						NULL,
-						_("Please enter the screen name or alias of the person "
+						_("Please enter the username or alias of the person "
 						  "you would like to IM."),
 						fields,
 						_("OK"), G_CALLBACK(send_im_select_cb),
@@ -2722,6 +2779,68 @@
 }
 
 static void
+view_log_select_cb(gpointer data, PurpleRequestFields *fields)
+{
+	PurpleAccount *account;
+	const char *name;
+	PurpleBuddy *buddy;
+	PurpleContact *contact;
+
+	account = purple_request_fields_get_account(fields, "account");
+	name = purple_request_fields_get_string(fields,  "screenname");
+
+	buddy = purple_find_buddy(account, name);
+	if (buddy) {
+		contact = purple_buddy_get_contact(buddy);
+	} else {
+		contact = NULL;
+	}
+
+	if (contact) {
+		finch_log_show_contact(contact);
+	} else {
+		finch_log_show(PURPLE_LOG_IM, name, account);
+	}
+}
+
+static void
+view_log_cb(GntMenuItem *item, gpointer n)
+{
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *group;
+	PurpleRequestField *field;
+
+	fields = purple_request_fields_new();
+
+	group = purple_request_field_group_new(NULL);
+	purple_request_fields_add_group(fields, group);
+
+	field = purple_request_field_string_new("screenname", _("Name"), NULL, FALSE);
+	purple_request_field_set_type_hint(field, "screenname-all");
+	purple_request_field_set_required(field, TRUE);
+	purple_request_field_group_add_field(group, field);
+
+	field = purple_request_field_account_new("account", _("Account"), NULL);
+	purple_request_field_set_type_hint(field, "account");
+	purple_request_field_set_visible(field,
+		(purple_accounts_get_all() != NULL &&
+		 purple_accounts_get_all()->next != NULL));
+	purple_request_field_set_required(field, TRUE);
+	purple_request_field_group_add_field(group, field);
+	purple_request_field_account_set_show_all(field, TRUE);
+
+	purple_request_fields(purple_get_blist(), _("View Log"),
+						NULL,
+						_("Please enter the username or alias of the person "
+						  "whose log you would like to view."),
+						fields,
+						_("OK"), G_CALLBACK(view_log_select_cb),
+						_("Cancel"), NULL,
+						NULL, NULL, NULL,
+						NULL);
+}
+
+static void
 menu_add_buddy_cb(GntMenuItem *item, gpointer null)
 {
 	purple_blist_request_add_buddy(NULL, NULL, NULL, NULL);
@@ -2781,6 +2900,11 @@
 	gnt_menu_add_item(GNT_MENU(sub), item);
 	gnt_menuitem_set_callback(GNT_MENU_ITEM(item), join_chat_select, NULL);
 
+	item = gnt_menuitem_new(_("View Log..."));
+	gnt_menuitem_set_id(GNT_MENU_ITEM(item), "view-log");
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENU_ITEM(item), view_log_cb, NULL);
+
 	item = gnt_menuitem_new(_("Show"));
 	gnt_menu_add_item(GNT_MENU(sub), item);
 	subsub = gnt_menu_new(GNT_MENU_POPUP);
--- a/finch/gntlog.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntlog.c	Wed May 07 03:32:43 2008 +0000
@@ -139,7 +139,8 @@
 
 }
 
-static void destroy_cb(GntWidget *w, struct log_viewer_hash_t *ht) {
+static void destroy_cb(GntWidget *w, struct log_viewer_hash_t *ht)
+{
 	FinchLogViewer *lv = syslog_viewer;
 
 	if (ht != NULL) {
@@ -162,12 +163,12 @@
 	gnt_widget_destroy(w);
 }
 
-static void log_select_cb(GntWidget *w, gpointer old, gpointer new, FinchLogViewer *viewer) {
+static void log_select_cb(GntWidget *w, gpointer old, gpointer new, FinchLogViewer *viewer)
+{
 	GntTree *tree = GNT_TREE(w);
 	PurpleLog *log = NULL;
 	PurpleLogReadFlags flags;
 	char *read = NULL, *strip, *newline;
-	int h;
 
 	if (!viewer->search && !gnt_tree_get_parent_key(tree, new))
 		return;
@@ -204,8 +205,6 @@
 
 	gnt_text_view_clear(GNT_TEXT_VIEW(viewer->text));
 	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(viewer->text), strip, GNT_TEXT_FLAG_NORMAL);
-	gnt_widget_get_size(viewer->text, NULL, &h);
-	gnt_text_view_scroll(GNT_TEXT_VIEW(viewer->text), h - 2);
 	g_free(read);
 	g_free(strip);
 }
@@ -321,6 +320,7 @@
 	/* Viewer ************/
 	lv->text = gnt_text_view_new();
 	gnt_box_add_widget(GNT_BOX(hbox), lv->text);
+	gnt_text_view_set_flag(GNT_TEXT_VIEW(lv->text), GNT_TEXT_VIEW_TOP_ALIGN);
 
 	hbox = gnt_hbox_new(FALSE);
 	gnt_box_add_widget(GNT_BOX(vbox), hbox);
--- a/finch/gntnotify.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntnotify.c	Wed May 07 03:32:43 2008 +0000
@@ -29,6 +29,7 @@
 #include <gntlabel.h>
 #include <gnttree.h>
 #include <gntutils.h>
+#include <gntwindow.h>
 
 #include "finch.h"
 
@@ -66,8 +67,7 @@
 			break;
 	}
 
-	window = gnt_box_new(FALSE, TRUE);
-	gnt_box_set_toplevel(GNT_BOX(window), TRUE);
+	window = gnt_window_box_new(FALSE, TRUE);
 	gnt_box_set_title(GNT_BOX(window), title);
 	gnt_box_set_fill(GNT_BOX(window), FALSE);
 	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
@@ -420,6 +420,12 @@
 	return tree;
 }
 
+static void *
+finch_notify_uri(const char *url)
+{
+	return finch_notify_message(PURPLE_NOTIFY_URI, _("URI"), url, NULL);
+}
+
 static PurpleNotifyUiOps ops = 
 {
 	finch_notify_message,
@@ -429,7 +435,7 @@
 	finch_notify_searchresults,
 	finch_notify_sr_new_rows,
 	finch_notify_userinfo,
-	NULL,                     /* notify_uri is of low-priority to me. --sadrul */
+	finch_notify_uri,
 	finch_close_notify,       /* The rest of the notify-uiops return a GntWidget.
                                      These widgets should be destroyed from here. */
 	NULL,
--- a/finch/gntrequest.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntrequest.c	Wed May 07 03:32:43 2008 +0000
@@ -98,11 +98,14 @@
  * cb: the callback
  * data: data for the callback
  * (text, primary-callback) pairs, ended by a NULL
+ *
+ * The cancellation callback should be the last callback sent.
  */
 static GntWidget *
 setup_button_box(GntWidget *win, gpointer userdata, gpointer cb, gpointer data, ...)
 {
-	GntWidget *box, *button;
+	GntWidget *box;
+	GntWidget *button = NULL;
 	va_list list;
 	const char *text;
 	gpointer callback;
@@ -122,6 +125,9 @@
 		g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(cb), data);
 	}
 
+	if (button)
+		g_object_set_data(G_OBJECT(button), "cancellation-function", GINT_TO_POINTER(TRUE));
+
 	va_end(list);
 	return box;
 }
@@ -295,13 +301,12 @@
 	 * updating the fields at the end like here, it updates the appropriate field
 	 * instantly whenever a change is made. That allows it to make sure the
 	 * 'required' fields are entered before the user can hit OK. It's not the case
-	 * here, althought it can be done. I am not honouring the 'required' fields
-	 * for the moment. */
+	 * here, althought it can be done. */
 	for (list = purple_request_fields_get_groups(fields); list; list = list->next)
 	{
 		PurpleRequestFieldGroup *group = list->data;
 		GList *fields = purple_request_field_group_get_fields(group);
-		
+
 		for (; fields ; fields = fields->next)
 		{
 			PurpleRequestField *field = fields->data;
@@ -368,6 +373,16 @@
 		}
 	}
 
+	purple_notify_close_with_handle(button);
+
+	if (!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
+			!purple_request_fields_all_required_filled(fields)) {
+		purple_notify_error(button, _("Error"),
+				_("You must fill all the required fields."),
+				_("The required fields are underlined."));
+		return;
+	}
+
 	if (callback)
 		callback(data, fields);
 
@@ -587,7 +602,11 @@
 
 			if (type != PURPLE_REQUEST_FIELD_BOOLEAN && label)
 			{
-				GntWidget *l = gnt_label_new(label);
+				GntWidget *l;
+				if (purple_request_field_is_required(field))
+					l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE);
+				else
+					l = gnt_label_new(label);
 				gnt_widget_set_size(l, 0, 1);
 				gnt_box_add_widget(GNT_BOX(hbox), l);
 			}
@@ -641,7 +660,7 @@
 	}
 
 	g_object_set_data(G_OBJECT(window), "fields", allfields);
-	
+
 	return window;
 }
 
--- a/finch/gntsound.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/gntsound.c	Wed May 07 03:32:43 2008 +0000
@@ -103,7 +103,7 @@
 	{PURPLE_SOUND_CHAT_YOU_SAY, N_("You talk in chat"), "send_chat_msg", "send.wav", NULL},
 	{PURPLE_SOUND_CHAT_SAY,     N_("Others talk in chat"), "chat_msg_recv", "receive.wav", NULL},
 	{PURPLE_SOUND_POUNCE_DEFAULT, NULL, "pounce_default", "alert.wav", NULL},
-	{PURPLE_SOUND_CHAT_NICK,    N_("Someone says your screen name in chat"), "nick_said", "alert.wav", NULL}
+	{PURPLE_SOUND_CHAT_NICK,    N_("Someone says your username in chat"), "nick_said", "alert.wav", NULL}
 };
 
 const char *
--- a/finch/libgnt/gntwidget.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/libgnt/gntwidget.c	Wed May 07 03:32:43 2008 +0000
@@ -257,6 +257,7 @@
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu,
 				GNT_KEY_POPUP, NULL);
 	gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_F11, NULL);
+	gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_CTRL_X, NULL);
 
 	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 	GNTDEBUG;
--- a/finch/libgnt/gntwm.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/libgnt/gntwm.c	Wed May 07 03:32:43 2008 +0000
@@ -101,7 +101,9 @@
 static gboolean idle_update;
 static GList *act = NULL; /* list of WS with unseen activitiy */
 static gboolean ignore_keys = FALSE;
+#ifdef USE_PYTHON
 static gboolean started_python = FALSE;
+#endif
 
 static GList *
 g_list_bring_to_front(GList *list, gpointer data)
@@ -1516,7 +1518,7 @@
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-window", help_for_window,
 				"\033" "|", NULL);
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-start", ignore_keys_start,
-				GNT_KEY_CTRL_G, NULL);
+				NULL, NULL);
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-end", ignore_keys_end,
 				"\033" GNT_KEY_CTRL_G, NULL);
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next-urgent", window_next_urgent,
--- a/finch/libgnt/gntws.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/finch/libgnt/gntws.c	Wed May 07 03:32:43 2008 +0000
@@ -13,7 +13,8 @@
 	GntNode *node = g_hash_table_lookup(nodes, widget);
 	if (GNT_IS_WINDOW(widget))
 		gnt_window_workspace_hiding(GNT_WINDOW(widget));
-	hide_panel(node->panel);
+	if (node)
+		hide_panel(node->panel);
 }
 
 static void
--- a/libpurple/conversation.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/conversation.c	Wed May 07 03:32:43 2008 +0000
@@ -813,14 +813,27 @@
 
 	g_return_val_if_fail(name != NULL, NULL);
 
+	switch (type) {
+		case PURPLE_CONV_TYPE_IM:
+			cnv = purple_get_ims();
+			break;
+		case PURPLE_CONV_TYPE_CHAT:
+			cnv = purple_get_chats();
+			break;
+		case PURPLE_CONV_TYPE_ANY:
+			cnv = purple_get_conversations();
+			break;
+		default:
+			g_return_val_if_reached(NULL);
+	}
+
 	name1 = g_strdup(purple_normalize(account, name));
 
-	for (cnv = purple_get_conversations(); cnv != NULL; cnv = cnv->next) {
+	for (; cnv != NULL; cnv = cnv->next) {
 		c = (PurpleConversation *)cnv->data;
 		name2 = purple_normalize(account, purple_conversation_get_name(c));
 
-		if (((type == PURPLE_CONV_TYPE_ANY) || (type == purple_conversation_get_type(c))) &&
-				(account == purple_conversation_get_account(c)) &&
+		if ((account == purple_conversation_get_account(c)) &&
 				!purple_utf8_strcasecmp(name1, name2)) {
 
 			break;
--- a/libpurple/idle.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/idle.c	Wed May 07 03:32:43 2008 +0000
@@ -252,7 +252,7 @@
 	PurpleAccount *account;
 
 	account = purple_connection_get_account(gc);
-	set_account_unidle(account);
+	idled_accts = g_list_remove(idled_accts, account);
 }
 
 static void
--- a/libpurple/log.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/log.c	Wed May 07 03:32:43 2008 +0000
@@ -667,6 +667,18 @@
 purple_log_uninit(void)
 {
 	purple_signals_unregister_by_instance(purple_log_get_handle());
+
+	purple_log_logger_remove(html_logger);
+	purple_log_logger_free(html_logger);
+	html_logger = NULL;
+
+	purple_log_logger_remove(txt_logger);
+	purple_log_logger_free(txt_logger);
+	txt_logger = NULL;
+
+	purple_log_logger_remove(old_logger);
+	purple_log_logger_free(old_logger);
+	old_logger = NULL;
 }
 
 /****************************************************************************
--- a/libpurple/notify.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/notify.c	Wed May 07 03:32:43 2008 +0000
@@ -66,35 +66,27 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_message != NULL) {
-		PurpleNotifyInfo *info;
+		void *ui_handle = ops->notify_message(type, title, primary,
+											  secondary);
+		if (ui_handle != NULL) {
 
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_MESSAGE;
-		info->handle    = handle;
-		info->ui_handle = ops->notify_message(type, title, primary,
-											  secondary);
-		info->cb = cb;
-		info->cb_user_data = user_data;
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_MESSAGE;
+			info->handle = handle;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
 
-		if (info->ui_handle != NULL) {
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
-
-			return NULL;
 		}
 
-	} else {
-		if (cb != NULL)
-			cb(user_data);
 	}
 
+	if (cb != NULL)
+		cb(user_data);
+
 	return NULL;
 }
 
@@ -108,36 +100,30 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_email != NULL) {
-		PurpleNotifyInfo *info;
-
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_EMAIL;
-		info->handle    = handle;
+		void *ui_handle;
 
 		purple_signal_emit(purple_notify_get_handle(), "displaying-email-notification",
-							subject, from, to, url);
+						   subject, from, to, url);
+
+		ui_handle = ops->notify_email(handle, subject, from, to, url);
+
+		if (ui_handle != NULL) {
 
-		info->ui_handle = ops->notify_email(handle, subject, from, to, url);
-		info->cb = cb;
-		info->cb_user_data = user_data;
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_EMAIL;
+			info->handle = handle;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
 
-		if (info->ui_handle != NULL) {
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
+		}
+	}
 
-			return NULL;
-		}
-	} else {
-		if (cb != NULL)
-			cb(user_data);
-	}
+	if (cb != NULL)
+		cb(user_data);
 
 	return NULL;
 }
@@ -162,39 +148,32 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_emails != NULL) {
-		PurpleNotifyInfo *info;
-
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_EMAILS;
-		info->handle    = handle;
+		void *ui_handle;
 
 		purple_signal_emit(purple_notify_get_handle(), "displaying-emails-notification",
 							subjects, froms, tos, urls, count);
 
-		info->ui_handle = ops->notify_emails(handle, count, detailed, subjects,
+		ui_handle = ops->notify_emails(handle, count, detailed, subjects,
 											 froms, tos, urls);
-		info->cb = cb;
-		info->cb_user_data = user_data;
 
-		if (info->ui_handle != NULL) {
+		if (ui_handle != NULL) {
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_EMAILS;
+			info->handle = handle;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
+
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
-
-			return NULL;
 		}
 
-	} else {
-		if (cb != NULL)
-			cb(user_data);
 	}
 
+	if (cb != NULL)
+		cb(user_data);
+
 	return NULL;
 }
 
@@ -210,34 +189,25 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_formatted != NULL) {
-		PurpleNotifyInfo *info;
+		void *ui_handle = ops->notify_formatted(title, primary, secondary, text);
+
+		if (ui_handle != NULL) {
 
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_FORMATTED;
-		info->handle    = handle;
-		info->ui_handle = ops->notify_formatted(title, primary, secondary, text);
-		info->cb = cb;
-		info->cb_user_data = user_data;
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_FORMATTED;
+			info->handle = handle;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
 
-		if (info->ui_handle != NULL) {
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
-
-			return NULL;
 		}
-
-	} else {
-		if (cb != NULL)
-			cb(user_data);
 	}
 
+	if (cb != NULL)
+		cb(user_data);
 	return NULL;
 }
 
@@ -252,34 +222,25 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_searchresults != NULL) {
-		PurpleNotifyInfo *info;
+		void *ui_handle = ops->notify_searchresults(gc, title, primary,
+													secondary, results, user_data);
+		if (ui_handle != NULL) {
 
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_SEARCHRESULTS;
-		info->handle    = gc;
-		info->ui_handle = ops->notify_searchresults(gc, title, primary,
-													secondary, results, user_data);
-		info->cb = cb;
-		info->cb_user_data = user_data;
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type      = PURPLE_NOTIFY_SEARCHRESULTS;
+			info->handle    = gc;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
 
-		if (info->ui_handle != NULL) {
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
+		}
+	}
 
-			return NULL;
-		}
-
-	} else {
-		if (cb != NULL)
-			cb(user_data);
-	}
+	if (cb != NULL)
+		cb(user_data);
 
 	return NULL;
 }
@@ -449,37 +410,30 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_userinfo != NULL) {
-		PurpleNotifyInfo *info;
-
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_USERINFO;
-		info->handle    = gc;
+		void *ui_handle;
 
 		purple_signal_emit(purple_notify_get_handle(), "displaying-userinfo",
 						 purple_connection_get_account(gc), who, user_info);
 
-		info->ui_handle = ops->notify_userinfo(gc, who, user_info);
-		info->cb = cb;
-		info->cb_user_data = user_data;
+		ui_handle = ops->notify_userinfo(gc, who, user_info);
+
+		if (ui_handle != NULL) {
 
-		if (info->ui_handle != NULL) {
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_USERINFO;
+			info->handle = gc;
+			info->ui_handle = ui_handle;
+			info->cb = cb;
+			info->cb_user_data = user_data;
+
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			if (info->cb != NULL)
-				info->cb(info->cb_user_data);
-
-			g_free(info);
+		}
+	}
 
-			return NULL;
-		}
-
-	} else {
-		if (cb != NULL)
-			cb(user_data);
-	}
+	if (cb != NULL)
+		cb(user_data);
 
 	return NULL;
 }
@@ -705,22 +659,19 @@
 	ops = purple_notify_get_ui_ops();
 
 	if (ops != NULL && ops->notify_uri != NULL) {
-		PurpleNotifyInfo *info;
+
+		void *ui_handle = ops->notify_uri(uri);
+
+		if (ui_handle != NULL) {
 
-		info            = g_new0(PurpleNotifyInfo, 1);
-		info->type      = PURPLE_NOTIFY_URI;
-		info->handle    = handle;
-		info->ui_handle = ops->notify_uri(uri);
+			PurpleNotifyInfo *info = g_new0(PurpleNotifyInfo, 1);
+			info->type = PURPLE_NOTIFY_URI;
+			info->handle = handle;
+			info->ui_handle = ui_handle;
 
-		if (info->ui_handle != NULL) {
 			handles = g_list_append(handles, info);
 
 			return info->ui_handle;
-
-		} else {
-			g_free(info);
-
-			return NULL;
 		}
 	}
 
--- a/libpurple/plugins/log_reader.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/plugins/log_reader.c	Wed May 07 03:32:43 2008 +0000
@@ -2789,14 +2789,34 @@
 	g_return_val_if_fail(plugin != NULL, FALSE);
 
 	purple_log_logger_remove(adium_logger);
+	purple_log_logger_free(adium_logger);
+	adium_logger = NULL;
+
 #if 0
 	purple_log_logger_remove(fire_logger);
+	purple_log_logger_free(fire_logger);
+	fire_logger = NULL;
+
 	purple_log_logger_remove(messenger_plus_logger);
+	purple_log_logger_free(messenger_plus_logger);
+	messenger_plus_logger = NULL;
 #endif
+
 	purple_log_logger_remove(msn_logger);
+	purple_log_logger_free(msn_logger);
+	msn_logger = NULL;
+
 	purple_log_logger_remove(trillian_logger);
+	purple_log_logger_free(trillian_logger);
+	trillian_logger = NULL;
+
 	purple_log_logger_remove(qip_logger);
+	purple_log_logger_free(qip_logger);
+	qip_logger = NULL;
+
 	purple_log_logger_remove(amsn_logger);
+	purple_log_logger_free(amsn_logger);
+	amsn_logger = NULL;
 
 	return TRUE;
 }
--- a/libpurple/plugins/newline.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/plugins/newline.c	Wed May 07 03:32:43 2008 +0000
@@ -102,11 +102,11 @@
 
 	"core-plugin_pack-newline",						/**< id				*/
 	N_("New Line"),									/**< name			*/
-	DISPLAY_VERSION,									/**< version		*/
+	DISPLAY_VERSION,								/**< version		*/
 	N_("Prepends a newline to displayed message."),	/**< summary		*/
 	N_("Prepends a newline to messages so that the "
 	   "rest of the message appears below the "
-	   "screen name in the conversation window."),	/**< description	*/
+	   "username in the conversation window."),		/**< description	*/
 	"Stu Tomlinson <stu@nosnilmot.com>",			/**< author			*/
 	PURPLE_WEBSITE,									/**< homepage		*/
 
--- a/libpurple/protocols/irc/msgs.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/irc/msgs.c	Wed May 07 03:32:43 2008 +0000
@@ -422,6 +422,11 @@
 		if (!args[0] || !args[1] || !args[2] || !args[3])
 			return;
 
+		if (!purple_roomlist_get_in_progress(irc->roomlist)) {
+			purple_debug_warning("irc", "Buggy server didn't send RPL_LISTSTART.\n");
+			purple_roomlist_set_in_progress(irc->roomlist, TRUE);
+		}
+
 		room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, args[1], NULL);
 		purple_roomlist_room_add_field(irc->roomlist, room, args[1]);
 		purple_roomlist_room_add_field(irc->roomlist, room, GINT_TO_POINTER(strtol(args[2], NULL, 10)));
@@ -1015,14 +1020,18 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(irc->account);
 	PurpleConversation *convo;
-	char *nick, *msg;
+	char *nick, *msg, *channel;
 
 	if (!args || !args[0] || !gc)
 		return;
 
-	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], irc->account);
+	/* Undernet likes to :-quote the channel name, for no good reason
+         * that I can see.  This catches that. */
+	channel = (args[0][0] == ':') ? &args[0][1] : args[0];
+
+	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, channel, irc->account);
 	if (!convo) {
-		purple_debug(PURPLE_DEBUG_INFO, "irc", "Got a PART on %s, which doesn't exist -- probably closed\n", args[0]);
+		purple_debug(PURPLE_DEBUG_INFO, "irc", "Got a PART on %s, which doesn't exist -- probably closed\n", channel);
 		return;
 	}
 
@@ -1033,7 +1042,7 @@
                                       (args[1] && *args[1]) ? ": " : "",
 									  (escaped && *escaped) ? escaped : "");
 		g_free(escaped);
-		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), args[0], msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
+		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
 		g_free(msg);
 		serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
 	} else {
--- a/libpurple/protocols/jabber/auth.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/auth.c	Wed May 07 03:32:43 2008 +0000
@@ -54,6 +54,11 @@
 				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
 				_("Server requires TLS/SSL for login.  No TLS/SSL support found."));
 			return TRUE;
+		} else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE)) {
+			purple_connection_error_reason (js->gc,
+				 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+				_("You require encryption, but no TLS/SSL support found."));
+			return TRUE;
 		}
 	}
 
@@ -377,6 +382,10 @@
 					if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
 						g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech));
 					}
+					/* Remove space which separated this mech from the next */
+					if (strlen(js->sasl_mechs->str) > 0 && ((js->sasl_mechs->str)[0] == ' ')) {
+						g_string_erase(js->sasl_mechs, 0, 1);	
+					}
 					again = TRUE;
 				}
 
@@ -1107,12 +1116,18 @@
 			if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
 				g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech));
 			}
+			/* Remove space which separated this mech from the next */
+			if (strlen(js->sasl_mechs->str) > 0 && ((js->sasl_mechs->str)[0] == ' ')) {
+				g_string_erase(js->sasl_mechs, 0, 1);	
+			}			
 		}
-
-		sasl_dispose(&js->sasl);
-
-		jabber_auth_start_cyrus(js);
-		return;
+		if (strlen(js->sasl_mechs->str)) {
+			/* If we have remaining mechs to try, do so */
+			sasl_dispose(&js->sasl);
+			
+			jabber_auth_start_cyrus(js);
+			return;
+		}
 	}
 #endif
 	msg = jabber_parse_error(js, packet, &reason);
--- a/libpurple/protocols/jabber/buddy.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Wed May 07 03:32:43 2008 +0000
@@ -56,8 +56,7 @@
 {
 	g_return_if_fail(jb != NULL);
 
-	if(jb->error_msg)
-		g_free(jb->error_msg);
+	g_free(jb->error_msg);
 	while(jb->resources)
 		jabber_buddy_resource_free(jb->resources->data);
 
@@ -155,12 +154,8 @@
 	}
 	jbr->priority = priority;
 	jbr->state = state;
-	if(jbr->status)
-		g_free(jbr->status);
-	if (status)
-		jbr->status = g_markup_escape_text(status, -1);
-	else
-		jbr->status = NULL;
+	g_free(jbr->status);
+	jbr->status = status != NULL ? g_markup_escape_text(status, -1) : NULL;
 
 	return jbr;
 }
@@ -502,6 +497,11 @@
 	if(((JabberStream*)gc->proto_data)->pep) {
 		/* XEP-0084: User Avatars */
 		if(img) {
+			/*
+			 * TODO: This is pretty gross.  The Jabber PRPL really shouldn't
+			 *       do voodoo to try to determine the image type, height
+			 *       and width.
+			 */
 			/* A PNG header, including the IHDR, but nothing else */
 			const struct {
 				guchar signature[8]; /* must be hex 89 50 4E 47 0D 0A 1A 0A */
--- a/libpurple/protocols/jabber/chat.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/chat.c	Wed May 07 03:32:43 2008 +0000
@@ -238,6 +238,8 @@
 		char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle);
 		purple_notify_error(gc, _("Invalid Room Handle"),
 				_("Invalid Room Handle"), buf);
+		g_free(buf);
+		return;
 	}
 
 	if(jabber_chat_find(js, room, server))
--- a/libpurple/protocols/jabber/presence.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/presence.c	Wed May 07 03:32:43 2008 +0000
@@ -369,17 +369,29 @@
 
 typedef struct _JabberPresenceCapabilities {
 	JabberStream *js;
-	JabberBuddyResource *jbr;
+	JabberBuddy *jb;
 	char *from;
 } JabberPresenceCapabilities;
 
 static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, gpointer user_data) {
 	JabberPresenceCapabilities *userdata = user_data;
+	JabberID *jid;
+	JabberBuddyResource *jbr;
 	GList *iter;
 
-	if(userdata->jbr->caps)
-		jabber_caps_free_clientinfo(userdata->jbr->caps);
-	userdata->jbr->caps = info;
+	jid = jabber_id_new(userdata->from);
+	jbr = jabber_buddy_find_resource(userdata->jb, jid->resource);
+	jabber_id_free(jid);
+
+	if(!jbr) {
+		g_free(userdata->from);
+		g_free(userdata);
+		return;
+	}
+
+	if(jbr->caps)
+		jabber_caps_free_clientinfo(jbr->caps);
+	jbr->caps = info;
 
 	if (info) {
 		for(iter = info->features; iter; iter = g_list_next(iter)) {
@@ -741,7 +753,7 @@
 				if(node && ver) {
 					JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1);
 					userdata->js = js;
-					userdata->jbr = jbr;
+					userdata->jb = jb;
 					userdata->from = g_strdup(from);
 					jabber_caps_get_info(js, from, node, ver, ext, jabber_presence_set_capabilities, userdata);
 				}
--- a/libpurple/protocols/jabber/roster.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/roster.c	Wed May 07 03:32:43 2008 +0000
@@ -329,11 +329,20 @@
 
 	jb = jabber_buddy_find(js, buddy->name, FALSE);
 
+	/*
+	 * For some reason if we're waiting for our subscription request
+	 * to be approved and we try to add the buddy to another group
+	 * then we remove the buddy from the old group.  I don't understand
+	 * the rationale for this, can someone please explain it?  It seems
+	 * like we should pass NULL as the groups parameter to
+	 * jabber_roster_update().
+	 */
 	if(!jb || !(jb->subscription & JABBER_SUB_TO)) {
 		groups = g_slist_append(groups, group->name);
 	}
 
 	jabber_roster_update(js, who, groups);
+	g_slist_free(groups);
 
 	my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
 	if(!strcmp(who, my_bare_jid)) {
--- a/libpurple/protocols/jabber/usermood.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Wed May 07 03:32:43 2008 +0000
@@ -147,7 +147,7 @@
 
 static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) {
 	JabberStream *js;
-	int max_mood_idx;
+	const int max_mood_idx = sizeof(moodstrings) / sizeof(moodstrings[0]) - 1;
 	int selected_mood = purple_request_fields_get_choice(fields, "mood");
 
 	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
@@ -157,9 +157,6 @@
 
 	js = gc->proto_data;
 
-	/* This is ugly, but protects us from unexpected values. */
-	for (max_mood_idx = 0; moodstrings[max_mood_idx]; max_mood_idx++);
-
 	if (selected_mood < 0 || selected_mood >= max_mood_idx) {
 		purple_debug_error("jabber", "Invalid mood index (%d) selected.\n", selected_mood);
 		return;
--- a/libpurple/protocols/msn/command.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/command.c	Wed May 07 03:32:43 2008 +0000
@@ -121,7 +121,7 @@
 	/* khc: Huh! */
 	/*add payload Length checking*/
 	msn_set_payload_len(cmd);
-	purple_debug_info("MSNP14","get payload len:%d\n",cmd->payload_len);
+	purple_debug_info("MSNP14","get payload len:%" G_GSIZE_FORMAT "\n", cmd->payload_len);
 
 	msn_command_ref(cmd);
 
--- a/libpurple/protocols/msn/contact.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/contact.c	Wed May 07 03:32:43 2008 +0000
@@ -100,56 +100,46 @@
 void
 msn_callback_state_set_who(MsnCallbackState *state, const gchar *who)
 {
-	gchar *nval;
 	g_return_if_fail(state != NULL);
 
-	nval = g_strdup(who);
 	g_free(state->who);
-	state->who = nval;
+	state->who = g_strdup(who);
 }
 
 void
 msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
 {
-	gchar *nval;
 	g_return_if_fail(state != NULL);
 
-	nval = g_strdup(uid);
 	g_free(state->uid);
-	state->uid = nval;
+	state->uid = g_strdup(uid);
 }
 
 void
 msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
 {
-	gchar *nval;
 	g_return_if_fail(state != NULL);
 
-	nval = g_strdup(old_group_name);
 	g_free(state->old_group_name);
-	state->old_group_name = nval;
+	state->old_group_name = g_strdup(old_group_name);
 }
 
 void
 msn_callback_state_set_new_group_name(MsnCallbackState *state, const gchar *new_group_name)
 {
-	gchar *nval;
 	g_return_if_fail(state != NULL);
 
-	nval = g_strdup(new_group_name);
 	g_free(state->new_group_name);
-	state->new_group_name = nval;
+	state->new_group_name = g_strdup(new_group_name);
 }
 
 void
 msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid)
 {
-	gchar *nval;
 	g_return_if_fail(state != NULL);
 
-	nval = g_strdup(guid);
 	g_free(state->guid);
-	state->guid = nval;
+	state->guid = g_strdup(guid);
 }
 
 
@@ -495,12 +485,13 @@
 					xmlnode *messenger_enabled;
 					char *is_messenger_enabled = NULL;
 
+					g_free(mobile_number);
 					mobile_number = xmlnode_get_data(number);
 
 					if (mobile_number &&
-						(messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled")) 
-						&& (is_messenger_enabled = xmlnode_get_data(messenger_enabled)) 
-						&& !strcmp(is_messenger_enabled, "true"))
+							(messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled")) 
+							&& (is_messenger_enabled = xmlnode_get_data(messenger_enabled)) 
+							&& !strcmp(is_messenger_enabled, "true"))
 						mobile = TRUE;
 
 					g_free(is_messenger_enabled);
@@ -538,6 +529,7 @@
 		g_free(Name);
 		g_free(uid);
 		g_free(type);
+		g_free(mobile_number);
 		passport = Name = uid = type = mobile_number = NULL;
 		mobile = FALSE;
 
@@ -659,6 +651,7 @@
 	g_free(Name);
 	g_free(uid);
 	g_free(type);
+	g_free(mobile_number);
 }
 
 static gboolean
@@ -691,6 +684,7 @@
 				g_free(errorcode);
 				return TRUE;
 			}
+			g_free(errorcode);
 		}
 
 		return FALSE;
--- a/libpurple/protocols/msn/dialog.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/dialog.c	Wed May 07 03:32:43 2008 +0000
@@ -112,7 +112,7 @@
 
 	data        = g_new0(MsnAddRemData, 1);
 	data->who   = g_strdup(passport);
-	data->group = group_name != NULL ? g_strdup(group_name) : NULL;
+	data->group = g_strdup(group_name);
 	data->gc    = gc;
 
 	msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
--- a/libpurple/protocols/msn/error.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/error.c	Wed May 07 03:32:43 2008 +0000
@@ -56,7 +56,7 @@
 			g_snprintf(msg, sizeof(msg), _("Already logged in"));
 			break;
 		case 208:
-			g_snprintf(msg, sizeof(msg), _("Invalid screen name"));
+			g_snprintf(msg, sizeof(msg), _("Invalid username"));
 			break;
 		case 209:
 			g_snprintf(msg, sizeof(msg), _("Invalid friendly name"));
--- a/libpurple/protocols/msn/msn.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/msn.c	Wed May 07 03:32:43 2008 +0000
@@ -247,7 +247,7 @@
 	MsnUser *user;
 	char *payload = NULL;
 	const char *mobile_number = NULL;
-	size_t payload_len;
+	gsize payload_len;
 
 	session = gc->proto_data;
 	cmdproc = session->notification->cmdproc;
@@ -262,13 +262,13 @@
 		mobile_number[0] == '+') {
 		/* if msn_user_get_mobile_phone() has a + in front, it's a number
 		   that from the buddy's contact card */
-		trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %d",
+		trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %" G_GSIZE_FORMAT,
 			mobile_number, payload_len);
 	} else {
 		/* otherwise we send to whatever phone number the buddy registered
 		   with msn */
-		trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %d", who,
-			payload_len);
+		trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %" G_GSIZE_FORMAT,
+			who, payload_len);
 	}
 
 	msn_transaction_set_payload(trans, payload, payload_len);
@@ -2188,7 +2188,7 @@
 
 static void
 msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-		const gchar *url_text, size_t len, const gchar *error_message)
+		const gchar *url_text, gsize len, const gchar *error_message)
 {
 	MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data;
 	int id = -1;
@@ -2230,7 +2230,7 @@
 		else
 		{
 			char buf[1024];
-			purple_debug_info("msn", "%s is %d bytes\n", photo_url_text, len);
+			purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len);
 			id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
 			g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id);
 			purple_notify_user_info_prepend_pair(user_info, NULL, buf);
--- a/libpurple/protocols/msn/nexus.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/nexus.c	Wed May 07 03:32:43 2008 +0000
@@ -52,6 +52,7 @@
 	if (nexus->challenge_data != NULL)
 		g_hash_table_destroy(nexus->challenge_data);
 
+	g_free(nexus->challenge_data_str);
 	g_free(nexus);
 }
 
@@ -101,13 +102,10 @@
 			msn_twn_p = g_hash_table_lookup(nexus->challenge_data, "p");
 
 			/*setup the t and p parameter for session*/
-			if (session->passport_info.t != NULL){
-				g_free(session->passport_info.t);
-			}
+			g_free(session->passport_info.t);
 			session->passport_info.t = g_strdup(msn_twn_t);
 
-			if (session->passport_info.p != NULL)
-				g_free(session->passport_info.p);
+			g_free(session->passport_info.p);
 			session->passport_info.p = g_strdup(msn_twn_p);
 
 			cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p);
@@ -133,7 +131,8 @@
 	MsnSession *session = nexus->session;
 	char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf;
 	char *fs0,*fs;
-	char *username, *password;
+	const char *username;
+	char *password;
 	char *tail;
 #ifdef NEXUS_LOGIN_TWN
 	char *challenge_str;
@@ -147,7 +146,7 @@
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
 
 	/*prepare the Windows Live ID authentication token*/
-	username = g_strdup(purple_account_get_username(session->account));
+	username = purple_account_get_username(session->account);
 	password = g_strndup(purple_connection_get_password(session->account->gc), 16);
 
 	lc =	(char *)g_hash_table_lookup(nexus->challenge_data, "lc");
@@ -170,7 +169,6 @@
 	if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){
 		purple_debug_error("MSN Nexus","WLM Authenticate Key Error!\n");
 		msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed"));
-		g_free(username);
 		g_free(password);
 		msn_nexus_destroy(nexus);
 		session->nexus = NULL;
--- a/libpurple/protocols/msn/notification.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/notification.c	Wed May 07 03:32:43 2008 +0000
@@ -414,7 +414,9 @@
 	{
 		g_return_if_fail(cmd->payload_cb != NULL);
 
-		purple_debug_info("MSNP14","MSG payload:{%.*s}\n",cmd->payload_len, cmd->payload);
+#if 0 /* glib on win32 doesn't correctly support precision modifiers for a string */
+		purple_debug_info("MSNP14", "MSG payload:{%.*s}\n", cmd->payload_len, cmd->payload);
+#endif
 		cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
 	}
 }
@@ -432,10 +434,12 @@
 	cmdproc = session->notification->cmdproc;
 	g_return_if_fail(msg     != NULL);
 	payload = msn_message_gen_payload(msg, &payload_len);
-	purple_debug_info("MSNP14","send UUM,payload{%s},strlen:%d,len:%d\n",
-		payload,strlen(payload),payload_len);
+	purple_debug_info("MSNP14",
+		"send UUM, payload{%s}, strlen:%" G_GSIZE_FORMAT ", len:%" G_GSIZE_FORMAT "\n",
+		payload, strlen(payload), payload_len);
 	type = msg->type;
-	trans = msn_transaction_new(cmdproc, "UUM","%s 32 %d %d",msg->remote_user,type,payload_len);
+	trans = msn_transaction_new(cmdproc, "UUM", "%s 32 %d %" G_GSIZE_FORMAT,
+		msg->remote_user, type, payload_len);
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
@@ -449,7 +453,7 @@
 	const char *passport;
 	const char *content_type;
 
-	purple_debug_info("MSNP14","Process UBM payload:%.*s\n", len, payload);
+	purple_debug_info("MSNP14","Process UBM payload:%.*s\n", (guint)len, payload);
 	msg = msn_message_new_from_cmd(cmdproc->session, cmd);
 
 	msn_message_parse_payload(msg, payload, len,MSG_LINE_DEM,MSG_BODY_DEM);
@@ -530,7 +534,7 @@
 	}else{
 		g_return_if_fail(cmd->payload_cb != NULL);
 
-		purple_debug_info("MSNP14","UBM payload:{%.*s}\n", cmd->payload_len, cmd->payload);
+		purple_debug_info("MSNP14", "UBM payload:{%.*s}\n", (guint)(cmd->payload_len), cmd->payload);
 		ubm_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
 	}
 }
@@ -645,8 +649,8 @@
 {
 	MsnTransaction *trans;
 	purple_debug_info("MSN Notification","Sending ADL with payload: %s\n", payload);
-	trans = msn_transaction_new(cmdproc, "ADL","%d", strlen(payload));
-	msn_transaction_set_payload(trans, payload, strlen(payload));
+	trans = msn_transaction_new(cmdproc, "ADL","%" G_GSIZE_FORMAT, payload_len);
+	msn_transaction_set_payload(trans, payload, payload_len);
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
@@ -729,7 +733,7 @@
 	domain = tokens[1];
 
 	payload = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>", domain, email);
-	trans = msn_transaction_new(cmdproc, "FQY","%d", strlen(payload));
+	trans = msn_transaction_new(cmdproc, "FQY","%" G_GSIZE_FORMAT, strlen(payload));
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
 
@@ -1703,6 +1707,9 @@
 		msn_user_set_currentmedia(user, &media);
 	else
 		msn_user_set_currentmedia(user, NULL);
+	g_free(media.title);
+	g_free(media.album);
+	g_free(media.artist);
 	g_free(str);
 
 	msn_user_update(user);
@@ -2070,7 +2077,7 @@
 	xmlnode_free(rml_node);
 
 	purple_debug_info("MSN Notification","Send RML with payload:\n%s\n", payload);
-	trans = msn_transaction_new(cmdproc, "RML","%d", strlen(payload));
+	trans = msn_transaction_new(cmdproc, "RML","%" G_GSIZE_FORMAT, strlen(payload));
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
 	g_free(payload);
--- a/libpurple/protocols/msn/oim.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/oim.c	Wed May 07 03:32:43 2008 +0000
@@ -58,7 +58,7 @@
 
 	oim = g_new0(MsnOim, 1);
 	oim->session = session;
-	oim->oim_list	= NULL;
+	oim->oim_list = NULL;
 	oim->run_id = rand_guid();
 	oim->challenge = NULL;
 	oim->send_queue = g_queue_new();
@@ -71,16 +71,18 @@
 msn_oim_destroy(MsnOim *oim)
 {
 	MsnOimSendReq *request;
-	
-	purple_debug_info("OIM","destroy the OIM \n");
+
+	purple_debug_info("OIM", "destroy the OIM %p\n", oim);
 	g_free(oim->run_id);
 	g_free(oim->challenge);
-	
+
 	while((request = g_queue_pop_head(oim->send_queue)) != NULL){
 		msn_oim_free_send_req(request);
 	}
+
 	g_queue_free(oim->send_queue);
-	
+	g_list_free(oim->oim_list);
+
 	g_free(oim);
 }
 
@@ -91,7 +93,7 @@
 	MsnOimSendReq *request;
 	
 	request = g_new0(MsnOimSendReq, 1);
-	request->from_member	=g_strdup(from_member);
+	request->from_member	= g_strdup(from_member);
 	request->friendname		= g_strdup(friendname);
 	request->to_member		= g_strdup(to_member);
 	request->oim_msg		= g_strdup(msg);
@@ -170,7 +172,6 @@
 								msg->oim_msg);
 							g_queue_push_head(oim->send_queue, msg);
 							msn_oim_send_msg(oim);
-							return;
 						} else {
 							purple_debug_info("msnoim",
 								"can't find lock key for OIM: %s\n",
@@ -191,9 +192,10 @@
 						purple_debug_info("MSNP14","resending OIM: %s\n", msg->oim_msg);
 						g_queue_push_head(oim->send_queue, msg);
 						msn_oim_send_msg(oim);
-						return;
 					}
 				}
+
+				g_free(faultcode_str);
 			}
 		}
 	}
@@ -472,7 +474,7 @@
 	xmlnode *iu_node;
 	MsnSession *session = oim->session;
 
-	purple_debug_info("MSNP14:OIM", "%s", xmlmsg);
+	purple_debug_info("MSNP14:OIM", "%s\n", xmlmsg);
 
 	node = xmlnode_from_str(xmlmsg, -1);
 	if (strcmp(node->name, "MD") != 0) {
--- a/libpurple/protocols/msn/page.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/page.c	Wed May 07 03:32:43 2008 +0000
@@ -39,14 +39,9 @@
 {
 	g_return_if_fail(page != NULL);
 
-	if (page->body != NULL)
-		g_free(page->body);
-
-	if (page->from_location != NULL)
-		g_free(page->from_location);
-
-	if (page->from_phone != NULL)
-		g_free(page->from_phone);
+	g_free(page->body);
+	g_free(page->from_location);
+	g_free(page->from_phone);
 
 	g_free(page);
 }
--- a/libpurple/protocols/msn/slp.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/slp.c	Wed May 07 03:32:43 2008 +0000
@@ -371,6 +371,7 @@
 			g_free(bin);
 
 			purple_xfer_set_filename(xfer, file_name);
+			g_free(file_name);
 			purple_xfer_set_size(xfer, file_size);
 			purple_xfer_set_init_fnc(xfer, msn_xfer_init);
 			purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
--- a/libpurple/protocols/msn/slpcall.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/slpcall.c	Wed May 07 03:32:43 2008 +0000
@@ -71,14 +71,9 @@
 	if (slpcall->timer)
 		purple_timeout_remove(slpcall->timer);
 
-	if (slpcall->id != NULL)
-		g_free(slpcall->id);
-
-	if (slpcall->branch != NULL)
-		g_free(slpcall->branch);
-
-	if (slpcall->data_info != NULL)
-		g_free(slpcall->data_info);
+	g_free(slpcall->id);
+	g_free(slpcall->branch);
+	g_free(slpcall->data_info);
 
 	for (e = slpcall->slplink->slp_msgs; e != NULL; )
 	{
--- a/libpurple/protocols/msn/slplink.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/slplink.c	Wed May 07 03:32:43 2008 +0000
@@ -101,11 +101,8 @@
 
 	session = slplink->session;
 
-	if (slplink->local_user != NULL)
-		g_free(slplink->local_user);
-
-	if (slplink->remote_user != NULL)
-		g_free(slplink->remote_user);
+	g_free(slplink->local_user);
+	g_free(slplink->remote_user);
 
 #if 0
 	if (slplink->directconn != NULL)
@@ -598,7 +595,9 @@
 	{
 		if ((offset + len) > slpmsg->size)
 		{
-			purple_debug_error("msn", "Oversized slpmsg - msgsize=%lld offset=%d len=%d\n", slpmsg->size, offset, len);
+			purple_debug_error("msn",
+				"Oversized slpmsg - msgsize=%lld offset=%" G_GSIZE_FORMAT " len=%" G_GSIZE_FORMAT "\n",
+				slpmsg->size, offset, len);
 			g_return_if_reached();
 		}
 		else
--- a/libpurple/protocols/msn/slpmsg.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/slpmsg.c	Wed May 07 03:32:43 2008 +0000
@@ -95,6 +95,7 @@
 		msg->nak_cb = NULL;
 		msg->ack_data = NULL;
 	}
+	g_list_free(slpmsg->msgs);
 
 	slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
 
--- a/libpurple/protocols/msn/soap.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/soap.c	Wed May 07 03:32:43 2008 +0000
@@ -273,7 +273,7 @@
 			case EAGAIN: return len;
 
 			default : purple_debug_error("MSN SOAP", "Read error!"
-						"read len: %d, error = %s\n",
+						"read len: %" G_GSSIZE_FORMAT ", error = %s\n",
 						len, g_strerror(errno));
 				  purple_input_remove(soapconn->input_handler);
 				  //soapconn->input_handler = 0;
@@ -293,7 +293,9 @@
 			soapconn->read_buf[soapconn->read_len] = '\0';
 		}
 		else {
-			purple_debug_error("MSN SOAP", "Failure re-allocating %d bytes of memory!\n", soapconn->read_len + len + 1);
+			purple_debug_error("MSN SOAP",
+				"Failure re-allocating %" G_GSIZE_FORMAT " bytes of memory!\n",
+				soapconn->read_len + len + 1);
 			exit(EXIT_FAILURE);
 		}
 			
@@ -301,7 +303,9 @@
 
 #if defined(MSN_SOAP_DEBUG)
 	if (len > 0)
-		purple_debug_info("MSN SOAP","Read %d bytes from SOAP server:\n%s\n", len, soapconn->read_buf + soapconn->read_len - len);
+		purple_debug_info("MSN SOAP",
+			"Read %" G_GSIZE_FORMAT " bytes from SOAP server:\n%s\n", len,
+			soapconn->read_buf + soapconn->read_len - len);
 #endif
 
 	return len;
@@ -523,7 +527,9 @@
 		soapconn->body_len	= atoi(body_len);
 		g_free(body_len);
 #ifdef MSN_SOAP_DEBUG
-		purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
+		purple_debug_misc("MSN SOAP",
+			"SOAP bytes read so far: %" G_GSIZE_FORMAT ", Content-Length: %d\n",
+			soapconn->read_len, soapconn->body_len);
 #endif
 		soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
 		if ( soapconn->need_to_read > 0 ) {
--- a/libpurple/protocols/msn/soap2.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/soap2.c	Wed May 07 03:32:43 2008 +0000
@@ -261,7 +261,7 @@
 static void
 msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
 {
-    MsnSoapConnection *conn = data;
+	MsnSoapConnection *conn = data;
 	int count = 0, cnt;
 	char buf[8192];
 	char *linebreak;
@@ -382,7 +382,7 @@
 	}
 
 	if (!handled && conn->headers_done) {
-		if (conn->buf->len - conn->handled_len >= 
+		if (conn->buf->len - conn->handled_len >=
 			conn->body_len) {
 			xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
 
@@ -394,8 +394,11 @@
 				conn->message = NULL;
 				message->xml = node;
 
-				if (!msn_soap_handle_body(conn, message))
+				if (!msn_soap_handle_body(conn, message)) {
+					msn_soap_message_destroy(message);
 					return;
+				}
+				msn_soap_message_destroy(message);
 			}
 
 			msn_soap_connection_handle_next(conn);
@@ -508,7 +511,7 @@
 
 			g_free(authstr);
 			g_free(body);
-		}		
+		}
 	}
 
 	return FALSE;
@@ -643,12 +646,12 @@
 }
 
 void
-msn_soap_message_add_header(MsnSoapMessage *req,
+msn_soap_message_add_header(MsnSoapMessage *message,
 		const char *name, const char *value)
 {
 	char *header = g_strdup_printf("%s: %s\r\n", name, value);
 
-	req->headers = g_slist_prepend(req->headers, header);
+	message->headers = g_slist_prepend(message->headers, header);
 }
 
 static void
--- a/libpurple/protocols/msn/state.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/state.c	Wed May 07 03:32:43 2008 +0000
@@ -87,7 +87,8 @@
 msn_parse_currentmedia(const char *cmedia, CurrentMedia *media)
 {
 	char **cmedia_array;
-	int strings;
+	int strings = 0;
+	gboolean parsed = FALSE;
 
 	if ((cmedia == NULL) || (*cmedia == '\0')) {
 		purple_debug_info("msn", "No currentmedia string\n");
@@ -108,31 +109,39 @@
 	 * 6: Album
 	 * 7: ?
 	 */
-	strings = 0;
+#if GLIB_CHECK_VERSION(2,6,0)
+	strings  = g_strv_length(cmedia_array);
+#else
 	while (cmedia_array[++strings] != NULL);
+#endif
+
+	if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
+		parsed = TRUE;
 
-	if (strings < 4)
-		return FALSE;
-	if (strcmp(cmedia_array[2], "1"))
-		return FALSE;
+		g_free(media->title);
+		if (strings == 4) {
+			media->title = g_strdup(cmedia_array[3]);
+		} else {
+			media->title = g_strdup(cmedia_array[4]);
+		}
 
-	if (strings == 4) {
-		media->title = g_strdup(cmedia_array[3]);
-	} else {
-		media->title = g_strdup(cmedia_array[4]);
+		g_free(media->artist);
+		if (strings > 5)
+			media->artist = g_strdup(cmedia_array[5]);
+		else
+			media->artist = NULL;
+
+		g_free(media->album);
+		if (strings > 6)
+			media->album = g_strdup(cmedia_array[6]);
+		else
+			media->album = NULL;
+
 	}
 
-	if (strings > 5)
-		media->artist = g_strdup(cmedia_array[5]);
-	else
-		media->artist = NULL;
+	g_strfreev(cmedia_array);
 
-	if (strings > 6)
-		media->album = g_strdup(cmedia_array[6]);
-	else
-		media->album = NULL;
-
-	return TRUE;
+	return parsed;
 }
 
 /* get the CurrentMedia info from the XML string */
@@ -241,7 +250,7 @@
 
 	payload = session->psm;
 	purple_debug_misc("MSNP14","Sending UUX command with payload: %s\n",payload);
-	trans = msn_transaction_new(cmdproc, "UUX", "%d", strlen(payload));
+	trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, strlen(payload));
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
 
--- a/libpurple/protocols/msn/switchboard.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Wed May 07 03:32:43 2008 +0000
@@ -544,7 +544,7 @@
 	msn_message_show_readable(msg, "SB SEND", FALSE);
 #endif
 
-	trans = msn_transaction_new(cmdproc, "MSG", "%c %d",
+	trans = msn_transaction_new(cmdproc, "MSG", "%c %" G_GSIZE_FORMAT,
 								msn_message_get_flag(msg), payload_len);
 
 	/* Data for callbacks */
--- a/libpurple/protocols/msn/sync.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/sync.c	Wed May 07 03:32:43 2008 +0000
@@ -156,16 +156,13 @@
 
 		for (c = tokens; *c != NULL; c++)
 		{
-			char *id;
-
-			id = *c;
-			group_ids = g_slist_append(group_ids, g_strdup(id));
+			group_ids = g_slist_append(group_ids, *c);
 		}
 
-		g_strfreev(tokens);
 
 		msn_got_lst_user(session, user, list_op, group_ids);
 
+		g_strfreev(tokens);
 		g_slist_free(group_ids);
 	}
 	else
--- a/libpurple/protocols/msn/userlist.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msn/userlist.c	Wed May 07 03:32:43 2008 +0000
@@ -349,8 +349,7 @@
 		GSList *c;
 		for (c = group_ids; c != NULL; c = g_slist_next(c))
 		{
-			char *group_id;
-			group_id = c->data;
+			char *group_id = c->data;
 			msn_user_add_group_id(user, group_id);
 		}
 
@@ -714,7 +713,7 @@
 		char *str = g_strdup_printf(_("Unable to add \"%s\"."), who);
 		
 		purple_notify_error(NULL, NULL, str,
-				  _("The screen name specified is invalid."));
+				  _("The username specified is invalid."));
 		g_free(str);
 
 		return;
--- a/libpurple/protocols/msnp9/error.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msnp9/error.c	Wed May 07 03:32:43 2008 +0000
@@ -56,7 +56,7 @@
 			g_snprintf(msg, sizeof(msg), _("Already logged in"));
 			break;
 		case 208:
-			g_snprintf(msg, sizeof(msg), _("Invalid screen name"));
+			g_snprintf(msg, sizeof(msg), _("Invalid username"));
 			break;
 		case 209:
 			g_snprintf(msg, sizeof(msg), _("Invalid friendly name"));
--- a/libpurple/protocols/msnp9/userlist.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/msnp9/userlist.c	Wed May 07 03:32:43 2008 +0000
@@ -652,7 +652,7 @@
 		{
 			char *str = g_strdup_printf(_("Unable to add \"%s\"."), who);
 			purple_notify_error(NULL, NULL, str,
-							  _("The screen name specified is invalid."));
+							  _("The username specified is invalid."));
 			g_free(str);
 		}
 
--- a/libpurple/protocols/novell/nmuser.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/novell/nmuser.c	Wed May 07 03:32:43 2008 +0000
@@ -1919,10 +1919,10 @@
 
 		case NMERR_AUTHENTICATION_FAILED:
 		case NMERR_CREDENTIALS_MISSING:
-			return _("Incorrect screen name or password");
+			return _("Incorrect username or password");
 
 		case NMERR_HOST_NOT_FOUND:
-			return _("Could not recognize the host of the screen name you entered");
+			return _("Could not recognize the host of the username you entered");
 
 		case NMERR_ACCESS_DENIED:
 			return _("Your account has been disabled because too many incorrect passwords were entered");
@@ -1935,7 +1935,7 @@
 			return _("You have reached your limit for the number of contacts allowed");
 
 		case NMERR_OBJECT_NOT_FOUND:
-			return _("You have entered an incorrect screen name");
+			return _("You have entered an incorrect username");
 
 		case NMERR_DIRECTORY_UPDATE:
 			return _("An error occurred while updating the directory");
--- a/libpurple/protocols/oscar/family_admin.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_admin.c	Wed May 07 03:32:43 2008 +0000
@@ -28,16 +28,15 @@
 
 #include "oscar.h"
 
-/*
+/**
  * Subtype 0x0002 - Request a bit of account info.
  *
  * Info should be one of the following:
  * 0x0001 - Screen name formatting
  * 0x0011 - Email address
  * 0x0013 - Unknown
- *
  */
-int
+void
 aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info)
 {
 	ByteStream bs;
@@ -48,22 +47,19 @@
 	byte_stream_put16(&bs, info);
 	byte_stream_put16(&bs, 0x0000);
 
-	snacid = aim_cachesnac(od, 0x0007, 0x0002, 0x0000, NULL, 0);	
-	flap_connection_send_snac(od, conn, 0x0007, 0x0002, 0x0000, snacid, &bs);	
+	snacid = aim_cachesnac(od, 0x0007, 0x0002, 0x0000, NULL, 0);
+	flap_connection_send_snac(od, conn, 0x0007, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-
-	return 0;
 }
 
-/*
+/**
  * Subtypes 0x0003 and 0x0005 - Parse account info.
  *
  * Called in reply to both an information request (subtype 0x0002) and
  * an information change (subtype 0x0004).
- *
  */
-static int
+static void
 infochange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
@@ -112,19 +108,12 @@
 	g_free(sn);
 	g_free(url);
 	g_free(email);
-
-	return 1;
 }
 
-/*
+/**
  * Subtype 0x0004 - Set screenname formatting.
- *
  */
-/*
- * Subtype 0x0004 - Set screenname formatting.
- *
- */
-int
+void
 aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick)
 {
 	ByteStream bs;
@@ -142,15 +131,12 @@
 	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-
-	return 0;
 }
 
-/*
+/**
  * Subtype 0x0004 - Change password.
- *
  */
-int
+void
 aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw)
 {
 	ByteStream bs;
@@ -171,14 +157,13 @@
 	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
 
-	return 0;
+	byte_stream_destroy(&bs);
 }
 
-/*
+/**
  * Subtype 0x0004 - Change email address.
- *
  */
-int
+void
 aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail)
 {
 	ByteStream bs;
@@ -196,8 +181,6 @@
 	flap_connection_send_snac(od, conn, 0x0007, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-
-	return 0;
 }
 
 /*
@@ -214,9 +197,8 @@
 	aim_genericreq_n(od, conn, 0x0007, 0x0006);
 }
 
-/*
+/**
  * Subtype 0x0007 - Account confirmation request acknowledgement.
- *
  */
 static int
 accountconfirm(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
@@ -242,9 +224,10 @@
 static int
 snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
-	if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005))
-		return infochange(od, conn, mod, frame, snac, bs);
-	else if (snac->subtype == 0x0007)
+	if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) {
+		infochange(od, conn, mod, frame, snac, bs);
+		return 1;
+	} else if (snac->subtype == 0x0007)
 		return accountconfirm(od, conn, mod, frame, snac, bs);
 
 	return 0;
--- a/libpurple/protocols/oscar/family_bart.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_bart.c	Wed May 07 03:32:43 2008 +0000
@@ -57,9 +57,9 @@
 
 	snacid = aim_cachesnac(od, 0x0010, 0x0002, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0010, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_chat.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_chat.c	Wed May 07 03:32:43 2008 +0000
@@ -435,7 +435,7 @@
 	flap_connection_send_snac(od, conn, 0x000e, 0x0005, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_feedbag.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Wed May 07 03:32:43 2008 +0000
@@ -1690,7 +1690,7 @@
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !sn)
 		return -EINVAL;
 
-	byte_stream_new(&bs, 1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2);
+	byte_stream_new(&bs, 1+strlen(sn) + 2+(msg ? strlen(msg)+1 : 0) + 2);
 
 	/* Screen name */
 	byte_stream_put8(&bs, strlen(sn));
@@ -1764,7 +1764,7 @@
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !sn)
 		return -EINVAL;
 
-	byte_stream_new(&bs, 1+strlen(sn) + 2+(msg ? (strlen(msg)+1) : 0) + 2);
+	byte_stream_new(&bs, 1+strlen(sn) + 2+(msg ? strlen(msg)+1 : 0) + 2);
 
 	/* Screen name */
 	byte_stream_put8(&bs, strlen(sn));
@@ -1864,7 +1864,7 @@
 	flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_icbm.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Wed May 07 03:32:43 2008 +0000
@@ -184,9 +184,9 @@
 
 	snacid = aim_cachesnac(od, 0x0004, 0x0002, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0004, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -520,7 +520,7 @@
 	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
 
 	return 0;
@@ -592,7 +592,7 @@
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -685,7 +685,7 @@
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -728,7 +728,7 @@
 	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
 
 	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-	g_free(hdrbs.data);
+	byte_stream_destroy(&hdrbs);
 
 	aim_tlvlist_write(&bs, &outer_tlvlist);
 
@@ -772,7 +772,7 @@
 
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
 
-	byte_stream_destroy(&bs);	
+	byte_stream_destroy(&bs);
 }
 
 /**
@@ -945,20 +945,20 @@
 
 	if (filename != NULL)
 	{
-		ByteStream bs;
+		ByteStream inner_bs;
 
 		/* Begin TLV t(2711) */
-		byte_stream_new(&bs, 2+2+4+strlen(filename)+1);
-		byte_stream_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001);
-		byte_stream_put16(&bs, numfiles);
-		byte_stream_put32(&bs, size);
+		byte_stream_new(&inner_bs, 2+2+4+strlen(filename)+1);
+		byte_stream_put16(&inner_bs, (numfiles > 1) ? 0x0002 : 0x0001);
+		byte_stream_put16(&inner_bs, numfiles);
+		byte_stream_put32(&inner_bs, size);
 
 		/* Filename - NULL terminated, for some odd reason */
-		byte_stream_putstr(&bs, filename);
-		byte_stream_put8(&bs, 0x00);
-
-		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data);
-		byte_stream_destroy(&bs);
+		byte_stream_putstr(&inner_bs, filename);
+		byte_stream_put8(&inner_bs, 0x00);
+
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, inner_bs.len, inner_bs.data);
+		byte_stream_destroy(&inner_bs);
 		/* End TLV t(2711) */
 	}
 
@@ -1163,7 +1163,7 @@
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -1232,7 +1232,7 @@
 	flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -2339,7 +2339,7 @@
 	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send_snac(od, conn, 0x0004, 0x000b, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
 
 	return 0;
@@ -2716,7 +2716,7 @@
 	flap_connection_send_snac(od, conn, 0x0004, 0x0014, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_icq.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_icq.c	Wed May 07 03:32:43 2008 +0000
@@ -260,9 +260,9 @@
 	byte_stream_putle32(&bs, atoi(uin));
 
 	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
-	
+
 	/* Keep track of this request and the ICQ number and request ID */
 	info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
 	info->reqid = snacid;
@@ -343,9 +343,9 @@
 	byte_stream_putraw(&bs, (guint8 *)xml, strlen(xml) + 1);
 
 	flap_connection_send_snac(od, conn, 0x0015, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 #endif
--- a/libpurple/protocols/oscar/family_locate.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Wed May 07 03:32:43 2008 +0000
@@ -1353,7 +1353,7 @@
 	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send_snac(od, conn, 0x0002, 0x000f, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
 	return 0;
 }
--- a/libpurple/protocols/oscar/family_odir.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_odir.c	Wed May 07 03:32:43 2008 +0000
@@ -130,7 +130,7 @@
 	flap_connection_send_snac(od, conn, 0x000f, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -165,9 +165,9 @@
 
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x000f, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_oservice.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_oservice.c	Wed May 07 03:32:43 2008 +0000
@@ -56,7 +56,7 @@
 
 	snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0001, 0x0002, 0x0000, snacid, &bs);
-	
+
 	byte_stream_destroy(&bs);
 }
 
@@ -150,7 +150,7 @@
 	flap_connection_send_snac(od, conn, 0x0001, 0x0004, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -392,7 +392,7 @@
 	snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0001, 0x0008, 0x0000, snacid, &bs);
 
-	byte_stream_destroy(&bs);	
+	byte_stream_destroy(&bs);
 }
 
 /* Subtype 0x0009 - Delete Rate Parameter */
@@ -415,7 +415,7 @@
 	snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0);
 	flap_connection_send_snac(od, conn, 0x0001, 0x0009, 0x0000, snacid, &bs);
 
-	byte_stream_destroy(&bs);	
+	byte_stream_destroy(&bs);
 }
 
 /* Subtype 0x000a - Rate Change */
@@ -865,7 +865,7 @@
 	flap_connection_send_snac(od, conn, 0x0001, 0x001e, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
@@ -1016,7 +1016,7 @@
 	flap_connection_send_snac(od, conn, 0x0001, 0x0020, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/family_userlookup.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/family_userlookup.c	Wed May 07 03:32:43 2008 +0000
@@ -78,7 +78,7 @@
 	flap_connection_send_snac(od, conn, 0x000a, 0x0002, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
-	
+
 	return 0;
 }
 
--- a/libpurple/protocols/oscar/flap_connection.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Wed May 07 03:32:43 2008 +0000
@@ -115,7 +115,7 @@
 	conn = data;
 	gettimeofday(&now, NULL);
 
-	purple_debug_info("oscar", "Attempting to send %i queued SNACs for %p\n", g_queue_get_length(conn->queued_snacs), conn);
+	purple_debug_info("oscar", "Attempting to send %u queued SNACs for %p\n", g_queue_get_length(conn->queued_snacs), conn);
 	while (!g_queue_is_empty(conn->queued_snacs))
 	{
 		QueuedSnac *queued_snac;
@@ -201,7 +201,7 @@
 			rateclass->last.tv_usec = now.tv_usec;
 		}
 	} else {
-		purple_debug_warning("oscar", "No rate class found for family %u subtype %u\n", family, subtype);
+		purple_debug_warning("oscar", "No rate class found for family %hu subtype %hu\n", family, subtype);
 	}
 
 	if (enqueue)
--- a/libpurple/protocols/oscar/misc.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/misc.c	Wed May 07 03:32:43 2008 +0000
@@ -39,7 +39,6 @@
 void
 aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
 {
-	FlapFrame *frame;
 	aim_snacid_t snacid = 0x00000000;
 
 	flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, NULL);
@@ -48,7 +47,6 @@
 void
 aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
 {
-	FlapFrame *frame;
 	aim_snacid_t snacid;
 
 	snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0);
@@ -74,7 +72,7 @@
 
 	byte_stream_put32(&bs, *longdata);
 
-	flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, NULL);
+	flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
@@ -97,7 +95,7 @@
 
 	byte_stream_put16(&bs, *shortdata);
 
-	flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, NULL);
+	flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, &bs);
 
 	byte_stream_destroy(&bs);
 }
--- a/libpurple/protocols/oscar/oscar.h	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Wed May 07 03:32:43 2008 +0000
@@ -1350,11 +1350,11 @@
 
 /* 0x0017 - family_auth.c */
 void aim_sendcookie(OscarData *, FlapConnection *, const guint16 length, const guint8 *);
-int aim_admin_changepasswd(OscarData *, FlapConnection *, const char *newpw, const char *curpw);
+void aim_admin_changepasswd(OscarData *, FlapConnection *, const char *newpw, const char *curpw);
 void aim_admin_reqconfirm(OscarData *od, FlapConnection *conn);
-int aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info);
-int aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail);
-int aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick);
+void aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info);
+void aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail);
+void aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick);
 
 
 
--- a/libpurple/protocols/oscar/util.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/oscar/util.c	Wed May 07 03:32:43 2008 +0000
@@ -156,7 +156,7 @@
 		return FALSE;
 
 	for (i = 0; sn[i] != '\0'; i++) {
-		if (!isalnum(sn[i]) && (sn[i] != ' ') && (sn[i] != '.'))
+		if (!isalnum(sn[i]) && (sn[i] != ' '))
 			return FALSE;
 	}
 
--- a/libpurple/protocols/sametime/sametime.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Wed May 07 03:32:43 2008 +0000
@@ -1233,6 +1233,7 @@
   }
 
   mwSametimeList_free(stlist);
+  mwGetBuffer_free(b);
 }
 
 
--- a/libpurple/protocols/silc/buddy.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/buddy.c	Wed May 07 03:32:43 2008 +0000
@@ -52,13 +52,13 @@
 			   _("User %s is not present in the network"), r->nick);
 		purple_notify_error(gc, _("Key Agreement"),
 				  _("Cannot perform the key agreement"), tmp);
-		silc_free(r->nick);
+		g_free(r->nick);
 		silc_free(r);
 		return;
 	}
 
 	silcpurple_buddy_keyagr_do(gc, r->nick, FALSE);
-	silc_free(r->nick);
+	g_free(r->nick);
 	silc_free(r);
 }
 
@@ -276,7 +276,7 @@
 	}
 
  out:
-	silc_free(a->hostname);
+	g_free(a->hostname);
 	silc_free(a);
 }
 
@@ -309,7 +309,7 @@
 	a->conn = conn;
 	a->client_id = client_entry->id;
 	if (hostname)
-		a->hostname = strdup(hostname);
+		a->hostname = g_strdup(hostname);
 	a->port = port;
 
 	purple_request_action(client->application, _("Key Agreement Request"), tmp,
@@ -416,7 +416,7 @@
 	}
 
 	silcpurple_buddy_privkey(client->application, context);
-	silc_free(context);
+	g_free(context);
 }
 
 static void
@@ -544,7 +544,7 @@
 	}
 
 	silcpurple_buddy_getkey(client->application, context);
-	silc_free(context);
+	g_free(context);
 }
 
 static void
--- a/libpurple/protocols/silc/chat.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/chat.c	Wed May 07 03:32:43 2008 +0000
@@ -92,7 +92,7 @@
 {
 	SilcPurple sg = gc->proto_data;
 	const char *chname;
-	char *buf, tmp[256], *tmp2;
+	char tmp[256], *tmp2;
 	GString *s;
 	SilcChannelEntry channel;
 	SilcHashTableList htl;
@@ -173,9 +173,8 @@
 		}
 	}
 
-	buf = g_string_free(s, FALSE);
-	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);
-	g_free(buf);
+	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, s->str, NULL, NULL);
+	g_string_free(s, TRUE);
 }
 
 
@@ -671,7 +670,7 @@
 
 typedef struct {
 	SilcPurple sg;
-	const char *channel;
+	char *channel;
 } *SilcPurpleChatInput;
 
 static void
@@ -689,17 +688,20 @@
 
 	if (!limit || !(*limit) || *limit == '0') {
 		if (limit && ulimit == channel->user_limit) {
+			g_free(s->channel);
 			silc_free(s);
 			return;
 		}
 		silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
 					 s->channel, "-l", NULL);
 
+		g_free(s->channel);
 		silc_free(s);
 		return;
 	}
 
 	if (ulimit == channel->user_limit) {
+		g_free(s->channel);
 		silc_free(s);
 		return;
 	}
@@ -708,6 +710,7 @@
 	silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
 				 s->channel, "+l", limit, NULL);
 
+	g_free(s->channel);
 	silc_free(s);
 }
 
@@ -720,7 +723,7 @@
 
 	SilcPurpleChatInput s;
 	SilcChannelEntry channel;
-	const char *ch;
+	char *ch;
 	char tmp[32];
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
--- a/libpurple/protocols/silc/ft.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/ft.c	Wed May 07 03:32:43 2008 +0000
@@ -424,12 +424,12 @@
 			   (const char *)context);
 		purple_notify_error(gc, _("Secure File Transfer"),
 				  _("Cannot send file"), tmp);
-		silc_free(context);
+		g_free(context);
 		return;
 	}
 
 	silcpurple_ftp_send_file(client->application, (const char *)context, NULL);
-	silc_free(context);
+	g_free(context);
 }
 
 PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name)
@@ -447,7 +447,7 @@
 	if (!clients) {
 		silc_client_get_clients(client, conn, name, NULL,
 					silcpurple_ftp_send_file_resolved,
-					strdup(name));
+					g_strdup(name));
 		return NULL;
 	}
 	silc_dlist_start(clients);
--- a/libpurple/protocols/silc/ops.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/ops.c	Wed May 07 03:32:43 2008 +0000
@@ -462,7 +462,7 @@
 			client_entry = va_arg(va, SilcClientEntry);
 
 			components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-			g_hash_table_insert(components, strdup("channel"), strdup(name));
+			g_hash_table_insert(components, g_strdup("channel"), g_strdup(name));
 			serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components);
 		}
 		break;
@@ -484,7 +484,7 @@
 		g_snprintf(buf, sizeof(buf), "%s@%s",
 			   client_entry->username, client_entry->hostname);
 		purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo),
-					  g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE);
+					  client_entry->nickname, buf, PURPLE_CBFLAGS_NONE, TRUE);
 
 		break;
 
@@ -974,7 +974,6 @@
 {
 	SilcAttributePayload attr;
 	SilcAttribute attribute;
-	char *buf;
 	GString *s;
 	SilcVCardStruct vcard;
 	int i;
@@ -1064,10 +1063,9 @@
 		}
 	}
 
-	buf = g_string_free(s, FALSE);
 	purple_notify_info(NULL, _("User Information"), _("User Information"),
-			 buf);
-	g_free(buf);
+			 s->str);
+	g_string_free(s, TRUE);
 }
 #endif
 
@@ -1133,7 +1131,7 @@
 			    f |= PURPLE_CBFLAGS_FOUNDER;
 			  if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
 			    f |= PURPLE_CBFLAGS_OP;
-			  users = g_list_append(users, g_strdup(chu->client->nickname));
+			  users = g_list_append(users, chu->client->nickname);
 			  flags = g_list_append(flags, GINT_TO_POINTER(f));
 
 			  if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
--- a/libpurple/protocols/silc/pk.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/pk.c	Wed May 07 03:32:43 2008 +0000
@@ -56,9 +56,9 @@
 					  SILC_PKCS_FILE_BASE64);
 	}
 
-	silc_free(verify->filename);
-	silc_free(verify->entity);
-	silc_free(verify->entity_name);
+	g_free(verify->filename);
+	g_free(verify->entity);
+	g_free(verify->entity_name);
 	silc_free(verify->fingerprint);
 	silc_free(verify->babbleprint);
 	silc_pkcs_public_key_free(verify->public_key);
@@ -211,10 +211,10 @@
 		return;
 	verify->client = client;
 	verify->conn = conn;
-	verify->filename = strdup(ipf);
-	verify->entity = strdup(entity);
+	verify->filename = g_strdup(ipf);
+	verify->entity = g_strdup(entity);
 	verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
-			       (name ? strdup(name) : strdup(hostname))
+			       (name ? g_strdup(name) : g_strdup(hostname))
 			       : NULL);
 	verify->public_key = silc_pkcs_public_key_copy(public_key);
 	verify->completion = completion;
@@ -262,9 +262,9 @@
 		/* Local copy matched */
 		if (completion)
 			completion(TRUE, context);
-		silc_free(verify->filename);
-		silc_free(verify->entity);
-		silc_free(verify->entity_name);
+		g_free(verify->filename);
+		g_free(verify->entity);
+		g_free(verify->entity_name);
 		silc_free(verify->fingerprint);
 		silc_free(verify->babbleprint);
 		silc_pkcs_public_key_free(verify->public_key);
--- a/libpurple/protocols/silc/silc.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/silc.c	Wed May 07 03:32:43 2008 +0000
@@ -575,7 +575,7 @@
 
 	username = (char *)purple_account_get_username(account);
 	up = g_strsplit(username, "@", 2);
-	username = strdup(up[0]);
+	username = g_strdup(up[0]);
 	g_strfreev(up);
 
 	if (!purple_account_get_user_info(account)) {
@@ -619,12 +619,12 @@
 		                             _("Cannot initialize SILC protocol"));
 		gc->proto_data = NULL;
 		silc_free(sg);
-		free(hostname);
-		free(username);
+		silc_free(hostname);
+		g_free(username);
 		return;
 	}
-	free(hostname);
-	free(username);
+	silc_free(hostname);
+	g_free(username);
 
 	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
 	if (!silcpurple_check_silc_dir(gc)) {
@@ -2111,6 +2111,15 @@
 	NULL
 };
 
+#if 0
+static SilcBool silcpurple_debug_cb(char *file, char *function, int line,
+		char *message, void *context)
+{
+	purple_debug_info("SILC", "%s:%d:%s - %s\n", file ? file : "(null)", line, function ? function : "(null)", message ? message : "(null)");
+	return TRUE;
+}
+#endif
+
 static void
 init_plugin(PurplePlugin *plugin)
 {
@@ -2189,6 +2198,8 @@
 #if 0
 silc_log_debug(TRUE);
 silc_log_set_debug_string("*client*");
+silc_log_quick(TRUE);
+silc_log_set_debug_callbacks(silcpurple_debug_cb, NULL, NULL, NULL);
 #endif
 
 }
--- a/libpurple/protocols/silc/util.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc/util.c	Wed May 07 03:32:43 2008 +0000
@@ -338,7 +338,6 @@
 	unsigned char *pk;
 	SilcUInt32 pk_len, key_len = 0;
 	GString *s;
-	char *buf;
 
 	/* We support showing only SILC public keys for now */
 	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
@@ -380,14 +379,12 @@
 	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
 	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
 
-	buf = g_string_free(s, FALSE);
-
 	purple_request_action(sg->gc, _("Public Key Information"),
 			      _("Public Key Information"),
-			      buf, 0, purple_connection_get_account(sg->gc),
+			      s->str, 0, purple_connection_get_account(sg->gc),
 			      NULL, NULL, context, 1, _("Close"), callback);
 
-	g_free(buf);
+	g_string_free(s, TRUE);
 	silc_free(fingerprint);
 	silc_free(babbleprint);
 	silc_free(pk);
@@ -545,8 +542,7 @@
 			g_string_append_printf(s, "[%s] ", _("Anxious"));
 	}
 	if (strlen(s->str)) {
-		*moodstr = s->str;
-		g_string_free(s, FALSE);
+		*moodstr = g_string_free(s, FALSE);
 		g_strchomp(*moodstr);
 	} else
 		g_string_free(s, TRUE);
@@ -575,8 +571,7 @@
 			g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
 	}
 	if (strlen(s->str)) {
-		*contactstr = s->str;
-		g_string_free(s, FALSE);
+		*contactstr = g_string_free(s, FALSE);
 		g_strchomp(*contactstr);
 	} else
 		g_string_free(s, TRUE);
@@ -604,10 +599,9 @@
 				device.model ? device.model : "",
 				device.language ? device.language : "");
 	}
-	if (strlen(s->str)) {
-		*devicestr = s->str;
-		g_string_free(s, FALSE);
-	} else
+	if (strlen(s->str))
+		*devicestr = g_string_free(s, FALSE);
+	else
 		g_string_free(s, TRUE);
 
 	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
@@ -635,15 +629,15 @@
 	if (!ct)
 		return NULL;
 	else if (!g_ascii_strcasecmp(".png", ct))
-		return strdup("image/png");
+		return g_strdup("image/png");
 	else if (!g_ascii_strcasecmp(".jpg", ct))
-		return strdup("image/jpeg");
+		return g_strdup("image/jpeg");
 	else if (!g_ascii_strcasecmp(".jpeg", ct))
-		return strdup("image/jpeg");
+		return g_strdup("image/jpeg");
 	else if (!g_ascii_strcasecmp(".gif", ct))
-		return strdup("image/gif");
+		return g_strdup("image/gif");
 	else if (!g_ascii_strcasecmp(".tiff", ct))
-		return strdup("image/tiff");
+		return g_strdup("image/tiff");
 
 	return NULL;
 }
@@ -705,7 +699,7 @@
 				continue;
 			}
 			silc_mime_add_field(p, "Content-Type", type);
-			silc_free(type);
+			g_free(type);
 
 			/* Add content transfer encoding */
 			silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");
--- a/libpurple/protocols/silc10/chat.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/silc10/chat.c	Wed May 07 03:32:43 2008 +0000
@@ -651,7 +651,7 @@
 
 typedef struct {
 	SilcPurple sg;
-	const char *channel;
+	char *channel;
 } *SilcPurpleChatInput;
 
 static void
@@ -700,7 +700,7 @@
 
 	SilcPurpleChatInput s;
 	SilcChannelEntry channel;
-	const char *ch;
+	char *ch;
 	char tmp[32];
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
--- a/libpurple/protocols/simple/simple.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/simple/simple.c	Wed May 07 03:32:43 2008 +0000
@@ -1890,7 +1890,7 @@
 	if (strpbrk(username, " \t\v\r\n") != NULL) {
 		purple_connection_error_reason(gc,
 			PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-			_("SIP screen names may not contain whitespaces or @ symbols"));
+			_("SIP usernames may not contain whitespaces or @ symbols"));
 		return;
 	}
 
--- a/libpurple/protocols/toc/toc.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/toc/toc.c	Wed May 07 03:32:43 2008 +0000
@@ -546,7 +546,7 @@
 			g_snprintf(buf, sizeof(buf), _("Failure unknown: %s."), w);
 			break;
 		case 980:
-			g_snprintf(buf, sizeof(buf), _("Incorrect screen name or password."));
+			g_snprintf(buf, sizeof(buf), _("Incorrect username or password."));
 			break;
 		case 981:
 			g_snprintf(buf, sizeof(buf), _("The service is temporarily unavailable."));
--- a/libpurple/protocols/yahoo/yahoo.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Wed May 07 03:32:43 2008 +0000
@@ -2124,7 +2124,7 @@
 
 	switch (err) {
 	case 3:
-		msg = g_strdup(_("Invalid screen name."));
+		msg = g_strdup(_("Invalid username."));
 		reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
 		break;
 	case 13:
@@ -3483,9 +3483,12 @@
 {
 	PurpleConnection *gc = user_data;
 	gboolean set_cookie = FALSE;
-	char *url;
+	gchar *url;
+	struct yahoo_data *yd = gc->proto_data;
 
 	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
+	
+	yd->url_datas = g_slist_remove(yd->url_datas, url_data);
 
 	if (error_message != NULL)
 		purple_debug_error("yahoo", "Requesting mail login token failed: %s\n", error_message);
@@ -3500,7 +3503,6 @@
 	}
 
 	if (!set_cookie) {
-		struct yahoo_data *yd = gc->proto_data;
 		purple_debug_error("yahoo", "No mail login token; forwarding to login screen.\n");
 		url = g_strdup(yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
 	}
@@ -3541,7 +3543,9 @@
 
 	g_free(request);
 
-	if (url_data == NULL) {
+	if (url_data != NULL)
+		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+	else {
 		const char *yahoo_mail_url = (yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
 		purple_debug_error("yahoo",
 				   "Unable to request mail login token; forwarding to login screen.");
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_aliases.c	Wed May 07 03:32:43 2008 +0000
@@ -32,6 +32,7 @@
 #include "version.h"
 #include "yahoo.h"
 #include "yahoo_aliases.h"
+#include "yahoo_friend.h"
 #include "yahoo_packet.h"
 
 /* I hate hardcoding this stuff, but Yahoo never sends us anything to use.  Someone in the know may be able to tweak this URL */
@@ -68,8 +69,10 @@
 		purple_debug_info("yahoo", "No Aliases to process.%s%s\n",
 						  error_message ? " Error:" : "", error_message ? error_message : "");
 	} else {
-		const char *yid, *full_name, *nick_name, *alias, *id, *fn, *ln, *nn;
-		PurpleBuddy *b = NULL;
+		gchar *full_name, *nick_name, *alias;
+		const char *yid, *id, *fn, *ln, *nn;
+		YahooFriend *f;
+		PurpleBuddy *b;
 		xmlnode *item, *contacts;
 
 		/* Put our web response into a xmlnode for easy management */
@@ -92,7 +95,9 @@
 				nn = xmlnode_get_attrib(item,"nn");
 				id = xmlnode_get_attrib(item,"id");
 
-		                /* Yahoo stores first and last names separately, lets put them together into a full name */
+				full_name = nick_name = alias = NULL;
+
+				/* Yahoo stores first and last names separately, lets put them together into a full name */
 				if (yd->jp)
 					full_name = g_strstrip(g_strdup_printf("%s %s", (ln != NULL ? ln : "") , (fn != NULL ? fn : "")));
 				else
@@ -103,22 +108,14 @@
 					alias = nick_name;   /* If we have a nickname from Yahoo, let's use it */
 				else if (strlen(full_name) != 0)
 					alias = full_name;  /* If no Yahoo nickname, we can use the full_name created above */
-				else
-					alias = NULL;  /* No nickname, first name or last name, then you get no alias !!  */
 
 				/*  Find the local buddy that matches */
+				f = yahoo_friend_find(cb->gc, yid);
 				b = purple_find_buddy(cb->gc->account, yid);
 
 				/*  If we don't find a matching buddy, ignore the alias !!  */
-				if (b != NULL) {
-					/* Create an object that we can attach to the buddies proto_data pointer */
-					struct YahooUser *yu;
-					yu = g_new0(struct YahooUser, 1);
-					yu->id = g_strdup(id);
-					yu->firstname = g_strdup(fn);
-					yu->lastname = g_strdup(ln);
-					yu->nickname = g_strdup(nn);
-					b->proto_data=yu;
+				if (f != NULL && b != NULL) {
+					yahoo_friend_set_alias_id(f, id);
 
 					/* Finally, if we received an alias, we better update the buddy list */
 					if (alias != NULL) {
@@ -132,6 +129,9 @@
 				} else {
 					purple_debug_info("yahoo", "Bizarre, received alias for %s, but they are not on your list...\n", yid);
 				}
+
+				g_free(full_name);
+				g_free(nick_name);
 			}
 		}
 		xmlnode_free(contacts);
@@ -232,14 +232,13 @@
 yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias)
 {
 	struct yahoo_data *yd;
-	struct YahooUser *yu;
 	char *content, *url, *request, *webpage, *webaddress, *strtmp;
 	char *escaped_alias, *alias_jp, *converted_alias_jp;
 	int inttmp;
 	struct callback_data *cb;
-	PurpleBuddy *buddy;
 	PurpleUtilFetchUrlData *url_data;
 	gboolean use_whole_url = FALSE;
+	YahooFriend *f;
 
 	/* use whole URL if using HTTP Proxy */
 	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
@@ -249,20 +248,19 @@
 	g_return_if_fail(who != NULL);
 	g_return_if_fail(gc != NULL);
 
-	purple_debug_info("yahoo", "Sending '%s' as new alias for user '%s'.\n",alias, who);
+	purple_debug_info("yahoo", "Sending '%s' as new alias for user '%s'.\n", alias, who);
 
-	buddy = purple_find_buddy(gc->account, who);
-	if (buddy == NULL || buddy->proto_data == NULL) {
+	f = yahoo_friend_find(gc, who);
+	if (f == NULL) {
 		purple_debug_info("yahoo", "Missing proto_data (get_yahoo_aliases must have failed), bailing out\n");
 		return;
 	}
 
 	yd = gc->proto_data;
-	yu = buddy->proto_data;
 
 	/* Using callback_data so I have access to gc in the callback function */
 	cb = g_new0(struct callback_data, 1);
-	cb->id = g_strdup(yu->id);
+	cb->id = g_strdup(yahoo_friend_get_alias_id(f));
 	cb->gc = gc;
 
 	/*  Build all the info to make the web request */
@@ -274,7 +272,7 @@
 		converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
 		content = g_strdup_printf("<ab k=\"%s\" cc=\"1\">\n"
 		                          "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-		                          gc->account->username, who, yu->id, converted_alias_jp);
+		                          gc->account->username, who, yahoo_friend_get_alias_id(f), converted_alias_jp);
 		free(converted_alias_jp);
 		g_free(alias_jp);
 	}
@@ -282,7 +280,7 @@
 		escaped_alias = g_markup_escape_text(alias, strlen(alias));
 		content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"1\">\n"
 		                          "<ct e=\"1\"  yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-		                          gc->account->username, who, yu->id, escaped_alias);
+		                          gc->account->username, who, yahoo_friend_get_alias_id(f), escaped_alias);
 		g_free(escaped_alias);
 	}
 
--- a/libpurple/protocols/yahoo/yahoo_aliases.h	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_aliases.h	Wed May 07 03:32:43 2008 +0000
@@ -33,18 +33,6 @@
 #include "yahoo.h"
 #include "yahoo_packet.h"
 
-
-/**
- * The additional protocol specific info attached to each buddy.  We need
- * to store the unique numeric id number to allow us to push alias changes.
- */
-struct YahooUser
-{
-    const char *id;             /* The yahoo accountid for this buddy (not YahooID but numeric value) */
-    char *firstname;            /* Storing this information for no real reason, just because */
-    char *lastname;             /* Storing this information for no real reason, just because */
-    char *nickname;             /* Storing this information for no real reason, just because */
-};
-
 void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
 void yahoo_fetch_aliases(PurpleConnection *gc);
+
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Wed May 07 03:32:43 2008 +0000
@@ -998,6 +998,7 @@
 	url = g_strdup_printf("%ld.%ld.%ld.%ld", d, c, b, a);
 	if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) {
 		purple_xfer_cancel_remote(xfer);
+		g_free(url);
 		return;
 	}
 	g_free(url);
--- a/libpurple/protocols/yahoo/yahoo_friend.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_friend.c	Wed May 07 03:32:43 2008 +0000
@@ -76,8 +76,7 @@
 
 void yahoo_friend_set_ip(YahooFriend *f, const char *ip)
 {
-	if (f->ip)
-		g_free(f->ip);
+	g_free(f->ip);
 	f->ip = g_strdup(ip);
 }
 
@@ -88,8 +87,7 @@
 
 void yahoo_friend_set_game(YahooFriend *f, const char *game)
 {
-	if (f->game)
-		g_free(f->game);
+	g_free(f->game);
 
 	if (game)
 		f->game = g_strdup(game);
@@ -104,8 +102,7 @@
 
 void yahoo_friend_set_status_message(YahooFriend *f, char *msg)
 {
-	if (f->msg)
-		g_free(f->msg);
+	g_free(f->msg);
 
 	f->msg = msg;
 }
@@ -125,15 +122,24 @@
 	return !f->bicon_sent_request;
 }
 
+void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id)
+{
+	g_free(f->alias_id);
+	f->alias_id = g_strdup(alias_id);
+}
+
+const char *yahoo_friend_get_alias_id(YahooFriend *f)
+{
+	return f->alias_id;
+}
+
 void yahoo_friend_free(gpointer p)
 {
 	YahooFriend *f = p;
-	if (f->msg)
-		g_free(f->msg);
-	if (f->game)
-		g_free(f->game);
-	if (f->ip)
-		g_free(f->ip);
+	g_free(f->msg);
+	g_free(f->game);
+	g_free(f->ip);
+	g_free(f->alias_id);
 	g_free(f);
 }
 
--- a/libpurple/protocols/yahoo/yahoo_friend.h	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_friend.h	Wed May 07 03:32:43 2008 +0000
@@ -39,16 +39,17 @@
  */
 typedef struct _YahooFriend {
 	enum yahoo_status status;
-	char *msg;
-	char *game;
+	gchar *msg;
+	gchar *game;
 	int idle;
 	int away;
 	gboolean sms;
-	char *ip;
+	gchar *ip;
 	gboolean bicon_sent_request;
 	YahooPresenceVisibility presence;
 	int protocol; /* 1=LCS, 2=MSN*/
 	long int version_id;
+	gchar *alias_id;
 } YahooFriend;
 
 YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
@@ -63,6 +64,9 @@
 void yahoo_friend_set_status_message(YahooFriend *f, char *msg);
 const char *yahoo_friend_get_status_message(YahooFriend *f);
 
+void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id);
+const char *yahoo_friend_get_alias_id(YahooFriend *f);
+
 void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs);
 gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f);
 
--- a/libpurple/prpl.h	Mon Apr 28 07:43:50 2008 +0000
+++ b/libpurple/prpl.h	Wed May 07 03:32:43 2008 +0000
@@ -186,7 +186,7 @@
  * A protocol plugin information structure.
  *
  * Every protocol plugin initializes this structure. It is the gateway
- * between purple and the protocol plugin.  Many of this callbacks can be
+ * between purple and the protocol plugin.  Many of these callbacks can be
  * NULL.  If a callback must be implemented, it has a comment indicating so.
  */
 struct _PurplePluginProtocolInfo
--- a/pidgin/gtkaccount.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkaccount.c	Wed May 07 03:32:43 2008 +0000
@@ -401,7 +401,7 @@
 	g_object_set(G_OBJECT(dialog->screenname_entry), "truncate-multiline", TRUE, NULL);
 #endif
 
-	add_pref_box(dialog, vbox, _("Screen _name:"), dialog->screenname_entry);
+	add_pref_box(dialog, vbox, _("_Username:"), dialog->screenname_entry);
 
 	g_signal_connect(G_OBJECT(dialog->screenname_entry), "changed",
 					 G_CALLBACK(screenname_changed_cb), dialog);
@@ -489,10 +489,6 @@
 	dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"),
 										  dialog->password_entry);
 
-	/* Alias */
-	dialog->alias_entry = gtk_entry_new();
-	add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry);
-
 	/* Remember Password */
 	dialog->remember_pass_check =
 		gtk_check_button_new_with_mnemonic(_("Remember pass_word"));
@@ -508,10 +504,6 @@
 			gtk_entry_set_text(GTK_ENTRY(dialog->password_entry),
 							   purple_account_get_password(dialog->account));
 
-		if (purple_account_get_alias(dialog->account))
-			gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry),
-							   purple_account_get_alias(dialog->account));
-
 		gtk_toggle_button_set_active(
 				GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
 				purple_account_get_remember_password(dialog->account));
@@ -564,6 +556,10 @@
 	gtk_container_add(GTK_CONTAINER(frame), vbox);
 	gtk_widget_show(vbox);
 
+	/* Alias */
+	dialog->alias_entry = gtk_entry_new();
+	add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry);
+
 	/* New mail notifications */
 	dialog->new_mail_check =
 		gtk_check_button_new_with_mnemonic(_("New _mail notifications"));
@@ -628,6 +624,10 @@
 		gpointer data = NULL;
 		size_t len = 0;
 
+		if (purple_account_get_alias(dialog->account))
+			gtk_entry_set_text(GTK_ENTRY(dialog->alias_entry),
+							   purple_account_get_alias(dialog->account));
+
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check),
 					     purple_account_get_check_mail(dialog->account));
 
@@ -647,6 +647,7 @@
 		set_dialog_icon(dialog, NULL, 0, NULL);
 	}
 
+#if 0
 	if (!dialog->prpl_info ||
 			(!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) &&
 			 (dialog->prpl_info->icon_spec.format ==  NULL))) {
@@ -654,6 +655,7 @@
 		/* Nothing to see :( aww. */
 		gtk_widget_hide(dialog->user_frame);
 	}
+#endif
 }
 
 static void
@@ -1904,7 +1906,7 @@
 
 	/* Screen Name column */
 	column = gtk_tree_view_column_new();
-	gtk_tree_view_column_set_title(column, _("Screen Name"));
+	gtk_tree_view_column_set_title(column, _("Username"));
 	gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
 	gtk_tree_view_column_set_resizable(column, TRUE);
 
--- a/pidgin/gtkblist.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkblist.c	Wed May 07 03:32:43 2008 +0000
@@ -615,6 +615,78 @@
 	pidgin_blist_refresh(list);
 }
 
+static void
+chat_components_edit_ok(PurpleChat *chat, PurpleRequestFields *allfields)
+{
+	GList *groups, *fields;
+
+	for (groups = purple_request_fields_get_groups(allfields); groups; groups = groups->next) {
+		fields = purple_request_field_group_get_fields(groups->data);
+		for (; fields; fields = fields->next) {
+			PurpleRequestField *field = fields->data;
+			const char *id;
+			char *val;
+
+			id = purple_request_field_get_id(field);
+			if (purple_request_field_get_type(field) == PURPLE_REQUEST_FIELD_INTEGER)
+				val = g_strdup_printf("%d", purple_request_field_int_get_value(field));
+			else
+				val = g_strdup(purple_request_field_string_get_value(field));
+
+			if (!val) {
+				g_hash_table_remove(purple_chat_get_components(chat), id);
+			} else {
+				g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val);  /* val should not be free'd */
+			}
+		}
+	}
+}
+
+static void chat_components_edit(GtkWidget *w, PurpleBlistNode *node)
+{
+	PurpleRequestFields *fields = purple_request_fields_new();
+	PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
+	PurpleRequestField *field;
+	GList *parts, *iter;
+	struct proto_chat_entry *pce;
+	PurpleConnection *gc;
+	PurpleChat *chat = (PurpleChat*)node;
+
+	purple_request_fields_add_group(fields, group);
+
+	gc = purple_account_get_connection(purple_chat_get_account(chat));
+	parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc);
+
+	for (iter = parts; iter; iter = iter->next) {
+		pce = iter->data;
+		if (pce->is_int) {
+			int val;
+			const char *str = g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier);
+			if (!str || sscanf(str, "%d", &val) != 1)
+				val = pce->min;
+			field = purple_request_field_int_new(pce->identifier, pce->label, val);
+		} else {
+			field = purple_request_field_string_new(pce->identifier, pce->label,
+					g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier), FALSE);
+			if (pce->secret)
+				purple_request_field_string_set_masked(field, TRUE);
+		}
+
+		if (pce->required)
+			purple_request_field_set_required(field, TRUE);
+
+		purple_request_field_group_add_field(group, field);
+		g_free(pce);
+	}
+
+	g_list_free(parts);
+
+	purple_request_fields(NULL, _("Edit Chat"), NULL, _("Please update the necessary fields."),
+			fields, _("Save"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL,
+			NULL, NULL, NULL,
+			chat);
+}
+
 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node)
 {
 	GtkTreeIter iter;
@@ -1511,6 +1583,8 @@
 
 	pidgin_separator(menu);
 
+	pidgin_new_item_from_stock(menu, _("_Edit Settings..."), NULL,
+				 G_CALLBACK(chat_components_edit), node, 0, 0, NULL);
 	pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
 				 G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL);
 	pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
@@ -3667,13 +3741,13 @@
 			}
 			return text;
 		}
-		else
-			if (hidden_conv) {
-				char *tmp = esc;
-				esc = g_strdup_printf("<b>%s</b>", esc);
-				g_free(tmp);
-			}
-			return esc;
+		else if (hidden_conv)
+		{
+			char *tmp = esc;
+			esc = g_strdup_printf("<b>%s</b>", esc);
+			g_free(tmp);
+		}
+		return esc;
 	}
 
 	prpl = purple_find_prpl(purple_account_get_protocol_id(b->account));
@@ -6395,7 +6469,7 @@
 
 	gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 0, 2, 0, 1);
 
-	label = gtk_label_new_with_mnemonic(_("Buddy's _screen name:"));
+	label = gtk_label_new_with_mnemonic(_("Buddy's _username:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
 
--- a/pidgin/gtkconv.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkconv.c	Wed May 07 03:32:43 2008 +0000
@@ -3050,7 +3050,7 @@
 	{ N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL },
 	{ "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL },
-	{ N_("/Options/Show Ti_mestamps"), "F2", menu_timestamps_cb, 0, "<CheckItem>", NULL },
+	{ N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "<CheckItem>", NULL },
 };
 
 static const int menu_item_count =
@@ -3978,11 +3978,10 @@
 }
 
 static void
-tab_complete_process_item(int *most_matched, char *entered, char **partial, char *nick_partial,
+tab_complete_process_item(int *most_matched, char *entered, gsize entered_bytes, char **partial, char *nick_partial,
 				  GList **matches, gboolean command, char *name)
 {
-	strncpy(nick_partial, name, strlen(entered));
-	nick_partial[strlen(entered)] = '\0';
+	memcpy(nick_partial, name, entered_bytes);
 	if (purple_utf8_strcasecmp(nick_partial, entered))
 		return;
 
@@ -4027,6 +4026,7 @@
 	const char *prefix;
 	GList *matches = NULL;
 	gboolean command = FALSE;
+	gsize entered_bytes = 0;
 
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
@@ -4046,19 +4046,24 @@
 	/* if we're at the end of ": " we need to move back 2 spaces */
 	start = strlen(text) - 1;
 
-	if (strlen(text) >= 2 && !strncmp(&text[start-1], ": ", 2)) {
+	if (start >= 1 && !strncmp(&text[start-1], ": ", 2)) {
 		gtk_text_iter_backward_chars(&word_start, 2);
-		start-=2;
-	}
-
-	/* find the start of the word that we're tabbing */
-	while (start >= 0 && text[start] != ' ') {
-		gtk_text_iter_backward_char(&word_start);
-		start--;
+	}
+
+	/* find the start of the word that we're tabbing.
+	 * Using gtk_text_iter_backward_word_start won't work, because a nick can contain
+	 * characters (e.g. '.', '/' etc.) that Pango may think are word separators. */
+	while (gtk_text_iter_backward_char(&word_start)) {
+		if (gtk_text_iter_get_char(&word_start) == ' ') {
+			/* Reached the whitespace before the start of the word. Move forward once */
+			gtk_text_iter_forward_char(&word_start);
+			break;
+		}
 	}
 
 	prefix = pidgin_get_cmd_prefix();
-	if (start == -1 && (strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) {
+	if (gtk_text_iter_get_offset(&word_start) == 0 &&
+			(strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) {
 		command = TRUE;
 		gtk_text_iter_forward_chars(&word_start, strlen(prefix));
 	}
@@ -4067,13 +4072,14 @@
 
 	entered = gtk_text_buffer_get_text(gtkconv->entry_buffer, &word_start,
 									   &cursor, FALSE);
+	entered_bytes = strlen(entered);
 
 	if (!g_utf8_strlen(entered, -1)) {
 		g_free(entered);
 		return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE;
 	}
 
-	nick_partial = g_malloc(strlen(entered)+1);
+	nick_partial = g_malloc0(entered_bytes + 1);
 
 	if (command) {
 		GList *list = purple_cmd_list(conv);
@@ -4081,7 +4087,7 @@
 
 		/* Commands */
 		for (l = list; l != NULL; l = l->next) {
-			tab_complete_process_item(&most_matched, entered, &partial, nick_partial,
+			tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
 									  &matches, TRUE, l->data);
 		}
 		g_list_free(list);
@@ -4094,7 +4100,7 @@
 
 		/* Users */
 		for (; l != NULL; l = l->next) {
-			tab_complete_process_item(&most_matched, entered, &partial, nick_partial,
+			tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
 									  &matches, TRUE, ((PurpleConvChatBuddy *)l->data)->name);
 		}
 
@@ -4112,7 +4118,7 @@
 						   -1);
 
 				if (name && alias && strcmp(name, alias))
-					tab_complete_process_item(&most_matched, entered, &partial, nick_partial,
+					tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
 										  &matches, FALSE, alias);
 				g_free(name);
 				g_free(alias);
@@ -4450,7 +4456,10 @@
 	GdkRectangle oneline;
 	int height, diff;
 	int pad_top, pad_inside, pad_bottom;
-	int max_height = gtkconv->tab_cont->allocation.height / 2;
+	int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height);
+	int max_height = total_height / 2;
+	int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines");
+	int min_height;
 
 	pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
 	pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
@@ -4471,15 +4480,14 @@
 	} while (gtk_text_iter_forward_line(&iter));
 	height += lines * (oneline.height + pad_top + pad_bottom);
 
-	/* Make sure there's enough room for at least two lines. Allocate enough space to
+	/* Make sure there's enough room for at least min_lines. Allocate enough space to
 	 * prevent scrolling when the second line is a continuation of the first line, or
 	 * is the beginning of a new paragraph. */
-	height = MAX(height, 2 * (oneline.height + MAX(pad_inside, pad_top + pad_bottom)));
-
-	height = MIN(height, max_height);
+	min_height = min_lines * (oneline.height + MAX(pad_inside, pad_top + pad_bottom));
+	height = CLAMP(height, MIN(min_height, max_height), max_height);
 
 	diff = height - gtkconv->entry->allocation.height;
-	if (diff == 0 || (diff < 0 && -diff < oneline.height / 2))
+	if (ABS(diff) < oneline.height / 2)
 		return FALSE;
 
 	gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
@@ -4489,6 +4497,25 @@
 }
 
 static void
+minimum_entry_lines_pref_cb(const char *name,
+                            PurplePrefType type,
+                            gconstpointer value,
+                            gpointer data)
+{
+	GList *l = purple_get_conversations();
+	PurpleConversation *conv;
+	while (l != NULL)
+	{
+		conv = (PurpleConversation *)l->data;
+
+		if (PIDGIN_IS_PIDGIN_CONVERSATION(conv))
+			resize_imhtml_cb(PIDGIN_CONVERSATION(conv));
+
+		l = l->next;
+	}
+}
+
+static void
 setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox)
 {
 	PurpleConversation *conv = gtkconv->active_conv;
@@ -4756,6 +4783,7 @@
 
 	/* Setup the gtkimhtml widget */
 	frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
+	gtk_widget_set_size_request(gtkconv->imhtml, -1, 0);
 	if (chat) {
 		GtkWidget *hpaned;
 
@@ -7637,6 +7665,7 @@
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE);
+	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", 2);
 
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", TRUE);
@@ -7701,6 +7730,9 @@
 								conv_placement_pref_cb, NULL);
 	purple_prefs_trigger_callback(PIDGIN_PREFS_ROOT "/conversations/placement");
 
+	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines",
+		minimum_entry_lines_pref_cb, NULL);
+
 	/* IM callbacks */
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons",
 								animate_buddy_icons_pref_cb, NULL);
--- a/pidgin/gtkdialogs.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkdialogs.c	Wed May 07 03:32:43 2008 +0000
@@ -760,7 +760,7 @@
 
 	purple_request_fields(purple_get_blist(), _("New Instant Message"),
 						NULL,
-						_("Please enter the screen name or alias of the person "
+						_("Please enter the username or alias of the person "
 						  "you would like to IM."),
 						fields,
 						_("OK"), G_CALLBACK(pidgin_dialogs_im_cb),
@@ -899,7 +899,7 @@
 
 	purple_request_fields(purple_get_blist(), _("Get User Info"),
 						NULL,
-						_("Please enter the screen name or alias of the person "
+						_("Please enter the username or alias of the person "
 						  "whose info you would like to view."),
 						fields,
 						_("OK"), G_CALLBACK(pidgin_dialogs_info_cb),
@@ -991,7 +991,7 @@
 
 	purple_request_fields(purple_get_blist(), _("View User Log"),
 						NULL,
-						_("Please enter the screen name or alias of the person "
+						_("Please enter the username or alias of the person "
 						  "whose log you would like to view."),
 						fields,
 						_("OK"), G_CALLBACK(pidgin_dialogs_log_cb),
--- a/pidgin/gtkimhtml.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkimhtml.c	Wed May 07 03:32:43 2008 +0000
@@ -814,9 +814,30 @@
 	gtk_imhtml_clear_formatting(imhtml);
 }
 
+static void disable_smiley_selected(GtkMenuItem *item, GtkIMHtml *imhtml)
+{
+	GtkTextIter start, end;
+	GtkTextMark *mark;
+	char *text;
+
+	if (!gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end))
+		return;
+
+	text = gtk_imhtml_get_markup_range(imhtml, &start, &end);
+
+	mark = gtk_text_buffer_get_selection_bound(imhtml->text_buffer);
+	gtk_text_buffer_delete_selection(imhtml->text_buffer, FALSE, FALSE);
+
+	gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, mark);
+	gtk_imhtml_insert_html_at_iter(imhtml, text, GTK_IMHTML_NO_NEWLINE | GTK_IMHTML_NO_SMILEY, &start);
+
+	g_free(text);
+}
+
 static void hijack_menu_cb(GtkIMHtml *imhtml, GtkMenu *menu, gpointer data)
 {
 	GtkWidget *menuitem;
+	GtkTextIter start, end;
 
 	menuitem = gtk_menu_item_new_with_mnemonic(_("Paste as Plain _Text"));
 	gtk_widget_show(menuitem);
@@ -842,6 +863,15 @@
 	gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, 5);
 
 	g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(clear_formatting_cb), imhtml);
+
+	menuitem = gtk_menu_item_new_with_mnemonic(_("Disable _smileys in selected text"));
+	gtk_widget_show(menuitem);
+	if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) {
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(disable_smiley_selected), imhtml);
+	} else {
+		gtk_widget_set_sensitive(menuitem, FALSE);
+	}
+	gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, 6);
 }
 
 static char *
@@ -1458,10 +1488,8 @@
 
 static void gtk_imhtml_init (GtkIMHtml *imhtml)
 {
-	GtkTextIter iter;
 	imhtml->text_buffer = gtk_text_buffer_new(NULL);
 	imhtml->undo_manager = gtk_source_undo_manager_new(imhtml->text_buffer);
-	gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter);
 	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer);
 	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR);
 	gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(imhtml), 2);
--- a/pidgin/gtkimhtmltoolbar.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Wed May 07 03:32:43 2008 +0000
@@ -621,7 +621,7 @@
 	struct smiley_button_list *cur;
 	struct smiley_button_list *it, *it_last;
 
-	cur = malloc(sizeof(struct smiley_button_list));
+	cur = g_new0(struct smiley_button_list, 1);
 	it = ls;
 	it_last = ls; /* list iterators*/
 	image = gtk_image_new_from_file(filename);
@@ -771,10 +771,9 @@
 		while (unique_smileys) {
 			GtkIMHtmlSmiley *smiley = unique_smileys->data;
 			if (!smiley->hidden) {
-				fflush(stdout);
 				ls = sort_smileys(ls, toolbar, &max_line_width, smiley->file, smiley->smile);
 			}
-			unique_smileys = unique_smileys->next;
+			unique_smileys = g_slist_delete_link(unique_smileys, unique_smileys);
 		}
 		/* pack buttons of the list */
 		max_line_width = max_line_width / num_lines;
@@ -793,7 +792,7 @@
 			}
 			col++;
 			it = it->next;
-			free(it_tmp);
+			g_free(it_tmp);
 		}
 		gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, TRUE, 0);
 
--- a/pidgin/gtknotify.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtknotify.c	Wed May 07 03:32:43 2008 +0000
@@ -52,6 +52,7 @@
 	GtkWidget *label;
 	GtkTreeIter iter;
 	int count;
+	gboolean purple_has_handle;
 } PidginNotifyMailData;
 
 typedef struct
@@ -100,6 +101,8 @@
 									const char **froms, const char **tos,
 									const char **urls);
 
+static void pidgin_close_notify(PurpleNotifyType type, void *ui_handle);
+
 static void
 message_response_cb(GtkDialog *dialog, gint id, GtkWidget *widget)
 {
@@ -144,7 +147,10 @@
 				purple_notify_uri(NULL, data->url);
 
 			gtk_tree_store_remove(dialog->treemodel, &iter);
-			purple_notify_close(PURPLE_NOTIFY_EMAILS, data);
+			if (data->purple_has_handle)
+				purple_notify_close(PURPLE_NOTIFY_EMAILS, data);
+			else
+				pidgin_close_notify(PURPLE_NOTIFY_EMAILS, data);
 		}
 	}
 	gtk_widget_destroy(dialog->dialog);
@@ -465,6 +471,7 @@
 
 	if (new_n) {
 		data = g_new0(PidginNotifyMailData, 1);
+		data->purple_has_handle = TRUE;
 		gtk_tree_store_append(treemodel, &iter, NULL);
 	}
 
@@ -479,6 +486,8 @@
 	data->iter = iter;              /* XXX: Do we use this for something? */
 	data->account = account;
 	data->count = count;
+
+	/* Why is this necessary?*/
 	gtk_tree_model_get(GTK_TREE_MODEL(treemodel), &iter,
 						PIDGIN_MAIL_DATA, &data, -1);
 	if (icon)
@@ -540,6 +549,9 @@
 			g_free(from_text);
 			g_free(subject_text);
 
+			/* If we don't keep track of this, will leak "data" for each of the notifications except the last */
+			if (data)
+				data->purple_has_handle = FALSE;
 			data = pidgin_notify_add_mail(mail_dialog->treemodel, account, notification, urls ? *urls : NULL, 0, FALSE);
 			g_free(notification);
 
@@ -588,7 +600,7 @@
 	} else if (!GTK_WIDGET_HAS_FOCUS(dialog))
 		pidgin_set_urgent(GTK_WINDOW(dialog), TRUE);
 
-	return NULL;
+	return data;
 }
 
 static gboolean
@@ -807,6 +819,7 @@
 		col_types[i] = G_TYPE_STRING;
 	}
 	model = gtk_list_store_newv(col_num, col_types);
+	g_free(col_types);
 
 	/* Setup the scrolled window containing the treeview */
 	sw = gtk_scrolled_window_new(NULL, NULL);
--- a/pidgin/gtkprefs.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkprefs.c	Wed May 07 03:32:43 2008 +0000
@@ -825,6 +825,106 @@
 		gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
 }
 
+
+#define CONVERSATION_CLOSE_ACCEL_PATH "<main>/Conversation/Close"
+
+/* Filled in in keyboard_shortcuts(). */
+static GtkAccelKey ctrl_w = { 0, 0, 0 };
+static GtkAccelKey escape = { 0, 0, 0 };
+
+static guint escape_closes_conversation_cb_id = 0;
+
+static gboolean
+accel_is_escape(GtkAccelKey *k)
+{
+	return (k->accel_key == escape.accel_key
+		&& k->accel_mods == escape.accel_mods);
+}
+
+/* Update the tickybox in Preferences when the keybinding for Conversation ->
+ * Close is changed via Gtk.
+ */
+static void
+conversation_close_accel_changed_cb (GtkAccelMap    *object,
+                                     gchar          *accel_path,
+                                     guint           accel_key,
+                                     GdkModifierType accel_mods,
+                                     gpointer        checkbox_)
+{
+	GtkToggleButton *checkbox = GTK_TOGGLE_BUTTON(checkbox_);
+	GtkAccelKey new = { accel_key, accel_mods, 0 };
+
+	g_signal_handler_block(checkbox, escape_closes_conversation_cb_id);
+	gtk_toggle_button_set_active(checkbox, accel_is_escape(&new));
+	g_signal_handler_unblock(checkbox, escape_closes_conversation_cb_id);
+}
+
+
+static void
+escape_closes_conversation_cb(GtkWidget *w,
+                              gpointer unused)
+{
+	gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+	gboolean changed;
+	GtkAccelKey *new_key = active ? &escape : &ctrl_w;
+
+	changed = gtk_accel_map_change_entry(CONVERSATION_CLOSE_ACCEL_PATH,
+		new_key->accel_key, new_key->accel_mods, TRUE);
+
+	/* If another path is already bound to the new accelerator,
+	 * _change_entry tries to delete that binding (because it was passed
+	 * replace=TRUE).  If that other path is locked, then _change_entry
+	 * will fail.  We don't ever lock any accelerator paths, so this case
+	 * should never arise.
+	 */
+	if(!changed)
+		purple_debug_warning("gtkprefs", "Escape accel failed to change\n");
+
+	/* TODO: create pidgin_accels_schedule_save */
+	pidgin_save_accels_cb(NULL, 0, 0, NULL, NULL);
+}
+
+
+/* Creates preferences for keyboard shortcuts that it's hard to change with the
+ * standard Gtk accelerator-changing mechanism.
+ */
+static void
+keyboard_shortcuts(GtkWidget *page)
+{
+	GtkWidget *vbox = pidgin_make_frame(page, _("Keyboard Shortcuts"));
+	GtkWidget *checkbox;
+	GtkAccelKey current = { 0, 0, 0 };
+	GtkAccelMap *map = gtk_accel_map_get();
+
+	/* Maybe it would be better just to hardcode the values?
+	 * -- resiak, 2007-04-30
+	 */
+	if (ctrl_w.accel_key == 0)
+	{
+		gtk_accelerator_parse ("<Control>w", &(ctrl_w.accel_key),
+			&(ctrl_w.accel_mods));
+		g_assert(ctrl_w.accel_key != 0);
+
+		gtk_accelerator_parse ("Escape", &(escape.accel_key),
+			&(escape.accel_mods));
+		g_assert(escape.accel_key != 0);
+	}
+
+	checkbox = gtk_check_button_new_with_mnemonic(
+		_("Cl_ose conversations with the Escape key"));
+	gtk_accel_map_lookup_entry(CONVERSATION_CLOSE_ACCEL_PATH, &current);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
+		accel_is_escape(&current));
+
+	escape_closes_conversation_cb_id = g_signal_connect(checkbox,
+		"clicked", G_CALLBACK(escape_closes_conversation_cb), NULL);
+
+	g_signal_connect(map, "changed::" CONVERSATION_CLOSE_ACCEL_PATH,
+		G_CALLBACK(conversation_close_accel_changed_cb), checkbox);
+
+	gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
+}
+
 static GtkWidget *
 interface_page(void)
 {
@@ -904,6 +1004,10 @@
 
 	g_list_free(names);
 
+
+	keyboard_shortcuts(ret);
+
+
 	gtk_widget_show_all(ret);
 	g_object_unref(sg);
 	return ret;
@@ -970,6 +1074,12 @@
 	pidgin_prefs_checkbox(_("Minimi_ze new conversation windows"), PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", vbox);
 #endif
 
+	pidgin_prefs_labeled_spin_button(vbox,
+		_("Minimum input area height in lines:"),
+		PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines",
+		1, 8, NULL);
+
+
 #if GTK_CHECK_VERSION(2,4,0)
 	vbox = pidgin_make_frame(ret, _("Font"));
 	if (purple_running_gnome())
--- a/pidgin/gtkrequest.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtkrequest.c	Wed May 07 03:32:43 2008 +0000
@@ -1120,6 +1120,16 @@
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
 	gtk_widget_show(img);
 
+	/* Cancel button */
+	button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(cancel_text), G_CALLBACK(multifield_cancel_cb), data);
+	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+
+	/* OK button */
+	button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(ok_text), G_CALLBACK(multifield_ok_cb), data);
+	data->ok_button = button;
+	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+	gtk_window_set_default(GTK_WINDOW(win), button);
+
 	/* Setup the vbox */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
 	gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
@@ -1272,6 +1282,7 @@
 				size_t col_offset = col_num * 2;
 				PurpleRequestFieldType type;
 				GtkWidget *widget = NULL;
+				const char *field_label;
 
 				label = NULL;
 				field = fl->data;
@@ -1282,17 +1293,17 @@
 				}
 
 				type = purple_request_field_get_type(field);
+				field_label = purple_request_field_get_label(field);
 
-				if (type != PURPLE_REQUEST_FIELD_BOOLEAN &&
-				    purple_request_field_get_label(field))
+				if (type != PURPLE_REQUEST_FIELD_BOOLEAN && field_label)
 				{
-					char *text;
+					char *text = NULL;
 
-					text = g_strdup_printf("%s:",
-						purple_request_field_get_label(field));
+					if (field_label[strlen(field_label) - 1] != ':')
+						text = g_strdup_printf("%s:", field_label);
 
 					label = gtk_label_new(NULL);
-					gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text);
+					gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text ? text : field_label);
 					g_free(text);
 
 					gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
@@ -1393,18 +1404,8 @@
 
 	g_object_unref(sg);
 
-	/* Cancel button */
-	button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(cancel_text), G_CALLBACK(multifield_cancel_cb), data);
-	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-
-	/* OK button */
-	button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(ok_text), G_CALLBACK(multifield_ok_cb), data);
-	data->ok_button = button;
-	GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-	gtk_window_set_default(GTK_WINDOW(win), button);
-
 	if (!purple_request_fields_all_required_filled(fields))
-		gtk_widget_set_sensitive(button, FALSE);
+		gtk_widget_set_sensitive(data->ok_button, FALSE);
 
 	pidgin_auto_parent_window(win);
 
--- a/pidgin/gtksavedstatuses.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Wed May 07 03:32:43 2008 +0000
@@ -968,7 +968,7 @@
 	/* Screen Name column */
 	column = gtk_tree_view_column_new();
 	gtk_tree_view_column_set_resizable(column, TRUE);
-	gtk_tree_view_column_set_title(column, _("Screen Name"));
+	gtk_tree_view_column_set_title(column, _("Username"));
 	gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
 	gtk_tree_view_column_set_resizable(column, TRUE);
 
--- a/pidgin/gtksound.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/gtksound.c	Wed May 07 03:32:43 2008 +0000
@@ -70,7 +70,7 @@
 	{N_("Others talk in chat"), "chat_msg_recv", "receive.wav"},
 	/* this isn't a terminator, it's the buddy pounce default sound event ;-) */
 	{NULL, "pounce_default", "alert.wav"},
-	{N_("Someone says your screen name in chat"), "nick_said", "alert.wav"}
+	{N_("Someone says your username in chat"), "nick_said", "alert.wav"}
 };
 
 static gboolean
--- a/pidgin/plugins/gevolution/new_person_dialog.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/plugins/gevolution/new_person_dialog.c	Wed May 07 03:32:43 2008 +0000
@@ -267,7 +267,7 @@
 	}
 	else
 	{
-		label = gtk_label_new(_("Please enter the buddy's screen name and "
+		label = gtk_label_new(_("Please enter the buddy's username and "
 								"account type below."));
 	}
 
@@ -291,7 +291,7 @@
 
 		/* Screen Name */
 		dialog->screenname = gtk_entry_new();
-		add_pref_box(sg, vbox, _("Screen name:"), dialog->screenname);
+		add_pref_box(sg, vbox, _("Username:"), dialog->screenname);
 
 		if (username != NULL)
 			gtk_entry_set_text(GTK_ENTRY(dialog->screenname), username);
--- a/pidgin/plugins/notify.c	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/plugins/notify.c	Wed May 07 03:32:43 2008 +0000
@@ -112,7 +112,7 @@
 
 /* notification set/unset */
 static int notify(PurpleConversation *conv, gboolean increment);
-static void notify_win(PidginWindow *purplewin);
+static void notify_win(PidginWindow *purplewin, PurpleConversation *conv);
 static void unnotify(PurpleConversation *conv, gboolean reset);
 static int unnotify_cb(GtkWidget *widget, gpointer data,
                        PurpleConversation *conv);
@@ -141,6 +141,9 @@
 /* raise function */
 static void handle_raise(PidginWindow *purplewin);
 
+/* present function */
+static void handle_present(PurpleConversation *conv);
+
 /****************************************/
 /* Begin doing stuff below this line... */
 /****************************************/
@@ -193,14 +196,14 @@
 			purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count));
 		}
 
-		notify_win(purplewin);
+		notify_win(purplewin, conv);
 	}
 
 	return 0;
 }
 
 static void
-notify_win(PidginWindow *purplewin)
+notify_win(PidginWindow *purplewin, PurpleConversation *conv)
 {
 	if (count_messages(purplewin) <= 0)
 		return;
@@ -215,6 +218,8 @@
 		handle_urgent(purplewin, TRUE);
 	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_raise"))
 		handle_raise(purplewin);
+	if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_present"))
+		handle_present(conv);
 }
 
 static void
@@ -564,6 +569,12 @@
 }
 
 static void
+handle_present(PurpleConversation *conv)
+{
+	purple_conversation_present(conv);
+}
+
+static void
 type_toggle_cb(GtkWidget *widget, gpointer data)
 {
 	gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
@@ -694,7 +705,7 @@
 	                 G_CALLBACK(type_toggle_cb), "type_chat");
 
 	ref = toggle;
-	toggle = gtk_check_button_new_with_mnemonic(_("\t_Only when someone says your screen name"));
+	toggle = gtk_check_button_new_with_mnemonic(_("\t_Only when someone says your username"));
 	gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
 	                            purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick"));
@@ -771,6 +782,14 @@
 	g_signal_connect(G_OBJECT(toggle), "toggled",
 	                 G_CALLBACK(method_toggle_cb), "method_raise");
 
+	/* Present conversation method button */
+	toggle = gtk_check_button_new_with_mnemonic(_("_Present conversation window"));
+	gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
+	                             purple_prefs_get_bool("/plugins/gtk/X11/notify/method_present"));
+	g_signal_connect(G_OBJECT(toggle), "toggled",
+	                 G_CALLBACK(method_toggle_cb), "method_present");
+
 	/*---------- "Notification Removals" ----------*/
 	frame = pidgin_make_frame(ret, _("Notification Removal"));
 	vbox = gtk_vbox_new(FALSE, 5);
@@ -945,6 +964,7 @@
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/method_count", FALSE);
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/method_count_xprop", FALSE);
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/method_raise", FALSE);
+	purple_prefs_add_bool("/plugins/gtk/X11/notify/method_present", FALSE);
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_focus", TRUE);
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_click", FALSE);
 	purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_type", TRUE);
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Mon Apr 28 07:43:50 2008 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Wed May 07 03:32:43 2008 +0000
@@ -49,6 +49,7 @@
 !include "WordFunc.nsh"
 !insertmacro VersionCompare
 !insertmacro WordFind
+!insertmacro un.WordFind
 
 ;--------------------------------
 ;Defines
@@ -549,23 +550,18 @@
 
 ;--------------------------------
 ;URI Handling
-SectionGroup /e $(URI_HANDLERS_SECTION_TITLE) SecURIHandlers
-  Section /o "aim:" SecURI_AIM
-    Push "aim"
-    Call RegisterURIHandler
-  SectionEnd
-  Section /o "msnim:" SecURI_MSNIM
-    Push "msnim"
+
+!macro URI_SECTION proto
+  Section /o "${proto}:" SecURI_${proto}
+    Push "${proto}"
     Call RegisterURIHandler
   SectionEnd
-  Section /o "myim:" SecURI_MYIM
-    Push "myim"
-    Call RegisterURIHandler
-  SectionEnd
-  Section /o "ymsgr:" SecURI_YMSGR
-    Push "ymsgr"
-    Call RegisterURIHandler
-  SectionEnd
+!macroend
+SectionGroup /e $(URI_HANDLERS_SECTION_TITLE) SecURIHandlers
+  !insertmacro URI_SECTION "aim"
+  !insertmacro URI_SECTION "msnim"
+  !insertmacro URI_SECTION "myim"
+  !insertmacro URI_SECTION "ymsgr"
 SectionGroupEnd
 
 ;--------------------------------
@@ -694,7 +690,19 @@
     ; The WinPrefs plugin may have left this behind..
     DeleteRegValue HKCU "${STARTUP_RUN_KEY}" "Pidgin"
     DeleteRegValue HKLM "${STARTUP_RUN_KEY}" "Pidgin"
-    ; Remove Language preference info (TODO: check if NSIS removes this)
+    ; Remove Language preference info
+    DeleteRegValue HKCU "${PIDGIN_REG_KEY}" "Installer Language"
+
+    ; Remove any URI handlers
+    ; I can't think of an easy way to maintain a list in a single place
+    Push "aim"
+    Call un.UnregisterURIHandler
+    Push "msnim"
+    Call un.UnregisterURIHandler
+    Push "myim"
+    Call un.UnregisterURIHandler
+    Push "ymsgr"
+    Call un.UnregisterURIHandler
 
     Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem"
     Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem"
@@ -903,12 +911,12 @@
   ReadRegStr $R3 HKCR "$R2" ""
   IfErrors default_on ;there is no current handler
 
-  ; Check if Pidgin is the current handler
-  ClearErrors
-  ReadRegStr $R3 HKCR "$R2\shell\Open\command" ""
-  IfErrors end_loop
-  ${WordFind} "$R3" "pidgin.exe" "E+1{" $R3
-  IfErrors end_loop default_on
+  Push $R2
+  Call CheckIfPidginIsCurrentURIHandler
+  Pop $R3
+
+  ; If Pidgin isn't the current handler, we don't steal it automatically
+  IntCmp $R3 0 end_loop
 
   ;We default the URI handler checkbox on
   default_on:
@@ -926,9 +934,58 @@
   Pop $R0
 FunctionEnd ;SelectURIHandlerSections
 
+; Check if Pidgin is the current handler
+; Returns a boolean on the stack
+!macro CheckIfPidginIsCurrentURIHandlerMacro UN
+Function ${UN}CheckIfPidginIsCurrentURIHandler
+  Exch $R0
+  ClearErrors
+
+  ReadRegStr $R0 HKCR "$R0\shell\Open\command" ""
+  IfErrors 0 +3
+    IntOp $R0 0 + 0
+    Goto done
+
+  !ifdef __UNINSTALL__
+  ${un.WordFind} "$R0" "pidgin.exe" "E+1{" $R0
+  !else
+  ${WordFind} "$R0" "pidgin.exe" "E+1{" $R0
+  !endif
+  IntOp $R0 0 + 1
+  IfErrors 0 +2
+    IntOp $R0 0 + 0
+
+  done:
+  Exch $R0
+FunctionEnd
+!macroend
+!insertmacro CheckIfPidginIsCurrentURIHandlerMacro ""
+!insertmacro CheckIfPidginIsCurrentURIHandlerMacro "un."
+
+; If Pidgin is the current URI handler for the specified protocol, remove it.
+Function un.UnregisterURIHandler
+  Exch $R0
+  Push $R1
+
+  Push $R0
+  Call un.CheckIfPidginIsCurrentURIHandler
+  Pop $R1
+
+  ; If Pidgin isn't the current handler, leave it as-is
+  IntCmp $R1 0 done
+
+  ;Unregister the URI handler
+  DetailPrint "Unregistering $R0 URI Handler"
+  DeleteRegKey HKCR "$R0"
+
+  done:
+  Pop $R1
+  Pop $R0
+FunctionEnd
 
 Function RegisterURIHandler
   Exch $R0
+  DetailPrint "Registering $R0 URI Handler"
   DeleteRegKey HKCR "$R0"
   WriteRegStr HKCR "$R0" "" "URL:$R0"
   WriteRegStr HKCR "$R0" "URL Protocol" ""
@@ -1198,12 +1255,14 @@
   StrCpy $SPELLCHECK_SEL ""
 
   ;Try to copy the old Gaim installer Lang Reg. key
+  ;(remove it after we're done to prevent this being done more than once)
   ClearErrors
   ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "Installer Language"
   IfErrors 0 +5
   ClearErrors
-  ReadRegStr $R0 HKCU "SOFTWARE\gaim" "Installer Language"
-  IfErrors +2
+  ReadRegStr $R0 HKCU "${OLD_GAIM_REG_KEY}" "Installer Language"
+  IfErrors +3
+  DeleteRegValue HKCU "${OLD_GAIM_REG_KEY}" "Installer Language"
   WriteRegStr HKCU "${PIDGIN_REG_KEY}" "Installer Language" "$R0"
 
   !insertmacro SetSectionFlag ${SecSpellCheck} ${SF_RO}
@@ -1321,6 +1380,7 @@
 Function un.onInit
   Call un.RunCheck
   StrCpy $name "Pidgin ${PIDGIN_VERSION}"
+;LogSet on
 
   ; Get stored language preference
   !insertmacro MUI_UNGETLANGUAGE