changeset 22265:7bd8ec61e687

merge of '127e166396532169c471488d7be34927a0f32b39' and 'b75a11995dcb2d3d2dc04522842a884fa0b5d06f'
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Mon, 04 Feb 2008 04:04:02 +0000
parents 99c6ed4c9cbe (diff) e808d83d797e (current diff)
children fc31c35d8024 1f3481447197
files
diffstat 42 files changed, 1395 insertions(+), 513 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Feb 04 04:00:12 2008 +0000
+++ b/ChangeLog	Mon Feb 04 04:04:02 2008 +0000
@@ -41,6 +41,9 @@
 	* The 'Grouping' plugin can be used for alternate grouping in the
 	  buddylist. The current options are 'Group Online/Offline' and 'No
 	  Group'.
+	* Added a log viewer
+	* Added the ability to block/unblock buddies - see the buddy context menu
+	  and the menu for the buddy list.
 
 version 2.3.1 (12/7/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.3.1
--- a/ChangeLog.API	Mon Feb 04 04:00:12 2008 +0000
+++ b/ChangeLog.API	Mon Feb 04 04:04:02 2008 +0000
@@ -75,6 +75,8 @@
 		  util functions finch_blist_install_manager,
 		  finch_blist_uninstall_manager, finch_blist_manager_find and
 		  finch_blist_manager_add_node.
+		* Added finch_log_show, finch_log_show_contact, finch_syslog_show,
+		  finch_log_init, finch_log_get_handle, finch_log_uninit
 
 		libgnt:
 		* Added gnt_tree_set_row_color to set the color for a row in a tree.
--- a/finch/Makefile.am	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/Makefile.am	Mon Feb 04 04:04:02 2008 +0000
@@ -25,6 +25,7 @@
 	gntft.c \
 	finch.c \
 	gntidle.c \
+	gntlog.c \
 	gntnotify.c \
 	gntplugin.c \
 	gntpounce.c \
@@ -45,6 +46,7 @@
 	gntft.h \
 	finch.h \
 	gntidle.h \
+	gntlog.h \
 	gntnotify.h \
 	gntplugin.h \
 	gntpounce.h \
--- a/finch/gntaccount.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntaccount.c	Mon Feb 04 04:04:02 2008 +0000
@@ -632,7 +632,8 @@
 	prompt = g_strdup_printf(_("Are you sure you want to delete %s?"),
 			purple_account_get_username(account));
 
-	purple_request_action(account, _("Delete Account"), prompt, NULL, 0,
+	purple_request_action(account, _("Delete Account"), prompt, NULL,
+						  PURPLE_DEFAULT_ACTION_NONE,
 						  account, NULL, NULL, account, 2,
 						  _("Delete"), really_delete_account,
 						  _("Cancel"), NULL);
--- a/finch/gntblist.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntblist.c	Mon Feb 04 04:04:02 2008 +0000
@@ -27,7 +27,9 @@
 
 #include <account.h>
 #include <blist.h>
+#include <log.h>
 #include <notify.h>
+#include <privacy.h>
 #include <request.h>
 #include <savedstatuses.h>
 #include <server.h>
@@ -43,6 +45,7 @@
 #include "gntft.h"
 #include "gntlabel.h"
 #include "gntline.h"
+#include "gntlog.h"
 #include "gntmenu.h"
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
@@ -1163,10 +1166,23 @@
 	finch_pounce_editor_show(purple_buddy_get_account(b), purple_buddy_get_name(b), NULL);
 }
 
+static void
+toggle_block_buddy(GntMenuItem *item, gpointer buddy)
+{
+	gboolean block = gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item));
+	PurpleAccount *account = purple_buddy_get_account(buddy);
+	const char *name = purple_buddy_get_name(buddy);
+
+	block ? purple_privacy_deny(account, name, FALSE, FALSE) :
+		purple_privacy_allow(account, name, FALSE, FALSE);
+}
 
 static void
 create_buddy_menu(GntMenu *menu, PurpleBuddy *buddy)
 {
+	PurpleAccount *account;
+	gboolean permitted;
+	GntMenuItem *item;
 	PurplePluginProtocolInfo *prpl_info;
 	PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 
@@ -1187,6 +1203,15 @@
 			add_custom_action(menu, _("Send File"),
 					PURPLE_CALLBACK(finch_blist_menu_send_file_cb), buddy);
 	}
+
+	account = purple_buddy_get_account(buddy);
+	permitted = purple_privacy_check(account, purple_buddy_get_name(buddy));
+
+	item = gnt_menuitem_check_new(_("Blocked"));
+	gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), !permitted);
+	gnt_menuitem_set_callback(item, toggle_block_buddy, buddy);
+	gnt_menu_add_item(menu, item);
+
 #if 0
 	add_custom_action(tree, _("View Log"),
 			PURPLE_CALLBACK(finch_blist_view_log_cb)), buddy);
@@ -1282,6 +1307,43 @@
 	g_free(prompt);
 }
 
+
+static void showlog_cb(PurpleBlistNode *node)
+{
+	PurpleLogType type;
+	PurpleAccount *account;
+	char *name = NULL;
+
+	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+		PurpleBuddy *b = (PurpleBuddy*) node;
+		type = PURPLE_LOG_IM;
+		name = g_strdup(b->name);
+		account = b->account;
+	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
+		PurpleChat *c = (PurpleChat*) node;
+		PurplePluginProtocolInfo *prpl_info = NULL;
+		type = PURPLE_LOG_CHAT;
+		account = c->account;
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
+		if (prpl_info && prpl_info->get_chat_name) {
+			name = prpl_info->get_chat_name(c->components);
+		}
+	} else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
+		finch_log_show_contact((PurpleContact *)node);
+		return;
+	} else {
+		/* This callback should not have been registered for a node
+		 * that doesn't match the type of one of the blocks above. */
+		g_return_if_reached();
+	}
+
+	if (name && account) {
+		finch_log_show(type, name, account);
+		g_free(name);
+	}
+}
+
+
 /* Xeroxed from gtkdialogs.c:purple_gtkdialogs_remove_group_cb*/
 static void
 remove_group(PurpleGroup *group)
@@ -1540,6 +1602,10 @@
 			add_custom_action(GNT_MENU(context), _("Toggle Tag"),
 					PURPLE_CALLBACK(finch_blist_toggle_tag_buddy), node);
 		}
+		if (!PURPLE_BLIST_NODE_IS_GROUP(node)) {
+			add_custom_action(GNT_MENU(context), _("View Log"),
+					PURPLE_CALLBACK(showlog_cb), node);
+		}
 	}
 
 	/* Set the position for the popup */
@@ -2493,6 +2559,61 @@
 	purple_prefs_set_string(PREF_ROOT "/sort_type", n);
 }
 
+static void
+block_select_cb(gpointer data, PurpleRequestFields *fields)
+{
+	PurpleAccount *account = purple_request_fields_get_account(fields, "account");
+	const char *name = purple_request_fields_get_string(fields,  "screenname");
+	if (account && name && *name != '\0') {
+		if (purple_request_fields_get_choice(fields, "block") == 1) {
+			purple_privacy_deny(account, name, FALSE, FALSE);
+		} else {
+			purple_privacy_allow(account, name, FALSE, FALSE);
+		}
+	}
+}
+
+static void
+block_select(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");
+	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_connections_get_all() != NULL &&
+		 purple_connections_get_all()->next != NULL));
+	purple_request_field_set_required(field, TRUE);
+	purple_request_field_group_add_field(group, field);
+
+	field = purple_request_field_choice_new("block", _("Block/Unblock"), 1);
+	purple_request_field_choice_add(field, _("Block"));
+	purple_request_field_choice_add(field, _("Unblock"));
+	purple_request_field_group_add_field(group, field);
+
+	purple_request_fields(purple_get_blist(), _("Block/Unblock"),
+						NULL,
+						_("Please enter the screen name or alias of the person "
+						  "you would like to Block/Unblock."),
+						fields,
+						_("OK"), G_CALLBACK(block_select_cb),
+						_("Cancel"), NULL,
+						NULL, NULL, NULL,
+						NULL);
+}
+
 /* send_im_select* -- Xerox */
 static void
 send_im_select_cb(gpointer data, PurpleRequestFields *fields)
@@ -2656,6 +2777,11 @@
 	gnt_menu_add_item(GNT_MENU(sub), item);
 	gnt_menuitem_set_callback(GNT_MENU_ITEM(item), send_im_select, NULL);
 
+	item = gnt_menuitem_new(_("Block/Unblock..."));
+	gnt_menuitem_set_id(GNT_MENU_ITEM(item), "block-unblock");
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(GNT_MENU_ITEM(item), block_select, NULL);
+
 	item = gnt_menuitem_new(_("Join Chat..."));
 	gnt_menuitem_set_id(GNT_MENU_ITEM(item), "join-chat");
 	gnt_menu_add_item(GNT_MENU(sub), item);
--- a/finch/gntcertmgr.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntcertmgr.c	Mon Feb 04 04:04:02 2008 +0000
@@ -234,7 +234,7 @@
 	purple_request_close_with_handle((void *)key);
 	purple_request_yes_no((void *)key, _("Confirm certificate delete"),
 			primary, NULL,
-			1,
+			0,
 			NULL, NULL, NULL,
 			g_strdup(key),
 			tls_peers_mgmt_delete_confirm_cb,
--- a/finch/gntconv.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntconv.c	Mon Feb 04 04:04:02 2008 +0000
@@ -36,6 +36,7 @@
 #include "gntblist.h"
 #include "gntconv.h"
 #include "gntdebug.h"
+#include "gntlog.h"
 #include "gntplugin.h"
 #include "gntprefs.h"
 #include "gntsound.h"
@@ -468,6 +469,44 @@
 }
 
 static void
+view_log_cb(GntMenuItem *n, gpointer ggc)
+{
+	FinchConv *fc;
+	PurpleConversation *conv;
+	PurpleLogType type;
+	const char *name;
+	PurpleAccount *account;
+	GSList *buddies;
+	GSList *cur;
+
+	fc = ggc;
+	conv = fc->active_conv;
+
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
+		type = PURPLE_LOG_IM;
+	else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
+		type = PURPLE_LOG_CHAT;
+	else
+		return;
+
+	name = purple_conversation_get_name(conv);
+	account = purple_conversation_get_account(conv);
+
+	buddies = purple_find_buddies(account, name);
+	for (cur = buddies; cur != NULL; cur = cur->next) {
+		PurpleBlistNode *node = cur->data;
+		if ((node != NULL) && ((node->prev != NULL) || (node->next != NULL))) {
+			finch_log_show_contact((PurpleContact *)node->parent);
+			g_slist_free(buddies);
+			return;
+		}
+	}
+	g_slist_free(buddies);
+
+	finch_log_show(type, name, account);
+}
+
+static void
 generate_send_to_menu(FinchConv *ggc)
 {
 	GntWidget *sub, *menu = ggc->menu;
@@ -569,6 +608,10 @@
 		generate_send_to_menu(ggc);
 	}
 
+	item = gnt_menuitem_new(_("View Log..."));
+	gnt_menu_add_item(GNT_MENU(sub), item);
+	gnt_menuitem_set_callback(item, view_log_cb, ggc);
+
 	item = gnt_menuitem_check_new(_("Enable Logging"));
 	gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item),
 			purple_conversation_is_logging(ggc->active_conv));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntlog.c	Mon Feb 04 04:04:02 2008 +0000
@@ -0,0 +1,504 @@
+/**
+ * @file gntlog.c GNT Log viewer
+ * @ingroup finch
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#include "internal.h"
+
+#include <gnt.h>
+#include <gntbox.h>
+#include <gntbutton.h>
+#include <gntentry.h>
+#include <gntlabel.h>
+#include <gnttextview.h>
+#include <gnttree.h>
+#include <gntwindow.h>
+
+#include "account.h"
+#include "debug.h"
+#include "log.h"
+#include "notify.h"
+#include "request.h"
+#include "util.h"
+
+#include "gntlog.h"
+
+static GHashTable *log_viewers = NULL;
+static void populate_log_tree(FinchLogViewer *lv);
+static FinchLogViewer *syslog_viewer = NULL;
+
+struct log_viewer_hash_t {
+	PurpleLogType type;
+	char *screenname;
+	PurpleAccount *account;
+	PurpleContact *contact;
+};
+
+static guint log_viewer_hash(gconstpointer data)
+{
+	const struct log_viewer_hash_t *viewer = data;
+
+	if (viewer->contact != NULL)
+		return g_direct_hash(viewer->contact);
+
+	return g_str_hash(viewer->screenname) +
+		g_str_hash(purple_account_get_username(viewer->account));
+}
+
+static gboolean log_viewer_equal(gconstpointer y, gconstpointer z)
+{
+	const struct log_viewer_hash_t *a, *b;
+	int ret;
+	char *normal;
+
+	a = y;
+	b = z;
+
+	if (a->contact != NULL) {
+		if (b->contact != NULL)
+			return (a->contact == b->contact);
+		else
+			return FALSE;
+	} else {
+		if (b->contact != NULL)
+			return FALSE;
+	}
+
+	normal = g_strdup(purple_normalize(a->account, a->screenname));
+	ret = (a->account == b->account) &&
+		!strcmp(normal, purple_normalize(b->account, b->screenname));
+	g_free(normal);
+
+	return ret;
+}
+
+static const char *log_get_date(PurpleLog *log)
+{
+	if (log->tm)
+		return purple_date_format_full(log->tm);
+	else
+		return purple_date_format_full(localtime(&log->time));
+}
+
+static void search_cb(GntWidget *button, FinchLogViewer *lv)
+{
+	const char *search_term = gnt_entry_get_text(GNT_ENTRY(lv->entry));
+	GList *logs;
+
+	if (!(*search_term)) {
+		/* reset the tree */
+		gnt_tree_remove_all(GNT_TREE(lv->tree));
+		g_free(lv->search);
+		lv->search = NULL;
+		populate_log_tree(lv);
+		return;
+	}
+
+	if (lv->search != NULL && !strcmp(lv->search, search_term)) {
+		return;
+	}
+
+	g_free(lv->search);
+	lv->search = g_strdup(search_term);
+
+	gnt_tree_remove_all(GNT_TREE(lv->tree));
+	gnt_text_view_clear(GNT_TEXT_VIEW(lv->text));
+
+	for (logs = lv->logs; logs != NULL; logs = logs->next) {
+		char *read = purple_log_read((PurpleLog*)logs->data, NULL);
+		if (read && *read && purple_strcasestr(read, search_term)) {
+			PurpleLog *log = logs->data;
+
+			gnt_tree_add_row_last(GNT_TREE(lv->tree),
+									log,
+									gnt_tree_create_row(GNT_TREE(lv->tree), log_get_date(log)),
+									NULL);
+		}
+		g_free(read);
+	}
+
+}
+
+static void destroy_cb(GntWidget *w, struct log_viewer_hash_t *ht) {
+	FinchLogViewer *lv = syslog_viewer;
+
+	if (ht != NULL) {
+		lv = g_hash_table_lookup(log_viewers, ht);
+		g_hash_table_remove(log_viewers, ht);
+
+		g_free(ht->screenname);
+		g_free(ht);
+	} else
+		syslog_viewer = NULL;
+
+	purple_request_close_with_handle(lv);
+
+	g_list_foreach(lv->logs, (GFunc)purple_log_free, NULL);
+	g_list_free(lv->logs);
+
+	g_free(lv->search);
+	g_free(lv);
+
+	gnt_widget_destroy(w);
+}
+
+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;
+
+	log = (PurpleLog *)new;
+
+	if (log == NULL)
+		return;
+
+	if (log->type != PURPLE_LOG_SYSTEM) {
+		char *title;
+		if (log->type == PURPLE_LOG_CHAT)
+			title = g_strdup_printf(_("Conversation in %s on %s"),
+									log->name, log_get_date(log));
+		else
+			title = g_strdup_printf(_("Conversation with %s on %s"),
+									log->name, log_get_date(log));
+
+		gnt_label_set_text(GNT_LABEL(viewer->label), title);
+		g_free(title);
+	}
+
+	read = purple_log_read(log, &flags);
+	if (flags != PURPLE_LOG_READ_NO_NEWLINE) {
+		newline = purple_strdup_withhtml(read);
+		strip = purple_markup_strip_html(newline);
+		g_free(newline);
+	} else {
+		strip = purple_markup_strip_html(read);
+	}
+	viewer->flags = flags;
+
+	purple_signal_emit(finch_log_get_handle(), "log-displaying", viewer, log);
+
+	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);
+}
+
+/* I want to make this smarter, but haven't come up with a cool algorithm to do so, yet.
+ * I want the tree to be divided into groups like "Today," "Yesterday," "Last week,"
+ * "August," "2002," etc. based on how many conversation took place in each subdivision.
+ *
+ * For now, I'll just make it a flat list.
+ */
+static void populate_log_tree(FinchLogViewer *lv)
+     /* Logs are made from trees in real life.
+        This is a tree made from logs */
+{
+	const char *pmonth;
+	char *month = NULL;
+	char prev_top_month[30] = "";
+	GList *logs = lv->logs;
+
+	while (logs != NULL) {
+		PurpleLog *log = logs->data;
+
+		pmonth = purple_utf8_strftime(_("%B %Y"),
+		                           log->tm ? log->tm : localtime(&log->time));
+
+		if (strcmp(pmonth, prev_top_month) != 0) {
+			month = g_strdup(pmonth);
+			/* top level */
+			gnt_tree_add_row_last(GNT_TREE(lv->tree),
+									month,
+									gnt_tree_create_row(GNT_TREE(lv->tree), month),
+									NULL);
+			gnt_tree_set_expanded(GNT_TREE(lv->tree), month, FALSE);
+
+			strncpy(prev_top_month, month, sizeof(prev_top_month));
+		}
+
+		/* sub */
+		gnt_tree_add_row_last(GNT_TREE(lv->tree),
+								log,
+								gnt_tree_create_row(GNT_TREE(lv->tree), log_get_date(log)),
+								month);
+
+		logs = logs->next;
+	}
+}
+
+static FinchLogViewer *display_log_viewer(struct log_viewer_hash_t *ht, GList *logs,
+						const char *title, int log_size)
+{
+	FinchLogViewer *lv;
+	char *text;
+	GntWidget *vbox, *hbox;
+	GntWidget *size_label;
+
+	if (logs == NULL)
+	{
+		/* No logs were found. */
+		const char *log_preferences = NULL;
+
+		if (ht == NULL) {
+			if (!purple_prefs_get_bool("/purple/logging/log_system"))
+				log_preferences = _("System events will only be logged if the \"Log all status changes to system log\" preference is enabled.");
+		} else {
+			if (ht->type == PURPLE_LOG_IM) {
+				if (!purple_prefs_get_bool("/purple/logging/log_ims"))
+					log_preferences = _("Instant messages will only be logged if the \"Log all instant messages\" preference is enabled.");
+			} else if (ht->type == PURPLE_LOG_CHAT) {
+				if (!purple_prefs_get_bool("/purple/logging/log_chats"))
+					log_preferences = _("Chats will only be logged if the \"Log all chats\" preference is enabled.");
+			}
+			g_free(ht->screenname);
+			g_free(ht);
+		}
+
+		purple_notify_info(NULL, title, _("No logs were found"), log_preferences);
+		return NULL;
+	}
+
+	lv = g_new0(FinchLogViewer, 1);
+	lv->logs = logs;
+
+	if (ht != NULL)
+		g_hash_table_insert(log_viewers, ht, lv);
+
+	/* Window ***********/
+	lv->window = gnt_vwindow_new(FALSE);
+	gnt_box_set_title(GNT_BOX(lv->window), title);
+	gnt_box_set_toplevel(GNT_BOX(lv->window), TRUE);
+	gnt_box_set_pad(GNT_BOX(lv->window), 0);
+	g_signal_connect(G_OBJECT(lv->window), "destroy", G_CALLBACK(destroy_cb), ht);
+
+	vbox = gnt_vbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(lv->window), vbox);
+
+	/* Label ************/
+	text = g_strdup_printf("%s", title);
+	lv->label = gnt_label_new(text);
+	g_free(text);
+	gnt_box_add_widget(GNT_BOX(vbox), lv->label);
+
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(vbox), hbox);
+	/* List *************/
+	lv->tree = gnt_tree_new();
+	gnt_widget_set_size(lv->tree, 30, 0);
+	populate_log_tree(lv);
+	g_signal_connect (G_OBJECT(lv->tree), "selection-changed",
+			G_CALLBACK (log_select_cb),
+			lv);
+	gnt_box_add_widget(GNT_BOX(hbox), lv->tree);
+
+	/* Viewer ************/
+	lv->text = gnt_text_view_new();
+	gnt_box_add_widget(GNT_BOX(hbox), lv->text);
+
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(vbox), hbox);
+	/* Log size ************/
+	if (log_size) {
+		char *sz_txt = purple_str_size_to_units(log_size);
+		text = g_strdup_printf("%s %s", _("Total log size:"), sz_txt);
+		size_label = gnt_label_new(text);
+		gnt_box_add_widget(GNT_BOX(hbox), size_label);
+		g_free(sz_txt);
+		g_free(text);
+	}
+
+	/* Search box **********/
+	gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Scroll/Search: ")));
+	lv->entry = gnt_entry_new("");
+	gnt_box_add_widget(GNT_BOX(hbox), lv->entry);
+	g_signal_connect(GNT_ENTRY(lv->entry), "activate", G_CALLBACK(search_cb), lv);
+
+	gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(lv->text), lv->entry);
+	gnt_text_view_attach_pager_widget(GNT_TEXT_VIEW(lv->text), lv->entry);
+
+	gnt_widget_show(lv->window);
+
+	return lv;
+}
+
+void finch_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account) {
+	struct log_viewer_hash_t *ht;
+	FinchLogViewer *lv = NULL;
+	const char *name = screenname;
+	char *title;
+
+	g_return_if_fail(account != NULL);
+	g_return_if_fail(screenname != NULL);
+
+	ht = g_new0(struct log_viewer_hash_t, 1);
+
+	ht->type = type;
+	ht->screenname = g_strdup(screenname);
+	ht->account = account;
+
+	if (log_viewers == NULL) {
+		log_viewers = g_hash_table_new(log_viewer_hash, log_viewer_equal);
+	} else if ((lv = g_hash_table_lookup(log_viewers, ht))) {
+		gnt_window_present(lv->window);
+		g_free(ht->screenname);
+		g_free(ht);
+		return;
+	}
+
+	if (type == PURPLE_LOG_CHAT) {
+		PurpleChat *chat;
+
+		chat = purple_blist_find_chat(account, screenname);
+		if (chat != NULL)
+			name = purple_chat_get_name(chat);
+
+		title = g_strdup_printf(_("Conversations in %s"), name);
+	} else {
+		PurpleBuddy *buddy;
+
+		buddy = purple_find_buddy(account, screenname);
+		if (buddy != NULL)
+			name = purple_buddy_get_contact_alias(buddy);
+
+		title = g_strdup_printf(_("Conversations with %s"), name);
+	}
+
+	display_log_viewer(ht, purple_log_get_logs(type, screenname, account),
+			title, purple_log_get_total_size(type, screenname, account));
+
+	g_free(title);
+}
+
+void finch_log_show_contact(PurpleContact *contact) {
+	struct log_viewer_hash_t *ht;
+	PurpleBlistNode *child;
+	FinchLogViewer *lv = NULL;
+	GList *logs = NULL;
+	const char *name = NULL;
+	char *title;
+	int total_log_size = 0;
+
+	g_return_if_fail(contact != NULL);
+
+	ht = g_new0(struct log_viewer_hash_t, 1);
+	ht->type = PURPLE_LOG_IM;
+	ht->contact = contact;
+
+	if (log_viewers == NULL) {
+		log_viewers = g_hash_table_new(log_viewer_hash, log_viewer_equal);
+	} else if ((lv = g_hash_table_lookup(log_viewers, ht))) {
+		gnt_window_present(lv->window);
+		g_free(ht);
+		return;
+	}
+
+	for (child = contact->node.child ; child ; child = child->next) {
+		if (!PURPLE_BLIST_NODE_IS_BUDDY(child))
+			continue;
+
+		logs = g_list_concat(purple_log_get_logs(PURPLE_LOG_IM, ((PurpleBuddy *)child)->name,
+						((PurpleBuddy *)child)->account), logs);
+		total_log_size += purple_log_get_total_size(PURPLE_LOG_IM, ((PurpleBuddy *)child)->name, ((PurpleBuddy *)child)->account);
+	}
+	logs = g_list_sort(logs, purple_log_compare);
+
+	if (contact->alias != NULL)
+		name = contact->alias;
+	else if (contact->priority != NULL)
+		name = purple_buddy_get_contact_alias(contact->priority);
+
+	/* This will happen if the contact doesn't have an alias,
+	 * and none of the contact's buddies are online.
+	 * There is probably a better way to deal with this. */
+	if (name == NULL) {
+		if (contact->node.child != NULL && PURPLE_BLIST_NODE_IS_BUDDY(contact->node.child))
+			name = purple_buddy_get_contact_alias((PurpleBuddy *) contact->node.child);
+		if (name == NULL)
+			name = "";
+	}
+
+	title = g_strdup_printf(_("Conversations with %s"), name);
+	display_log_viewer(ht, logs, title, total_log_size);
+	g_free(title);
+}
+
+void finch_syslog_show()
+{
+	GList *accounts = NULL;
+	GList *logs = NULL;
+
+	if (syslog_viewer != NULL) {
+		gnt_window_present(syslog_viewer->window);
+		return;
+	}
+
+	for(accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
+
+		PurpleAccount *account = (PurpleAccount *)accounts->data;
+		if(purple_find_prpl(purple_account_get_protocol_id(account)) == NULL)
+			continue;
+
+		logs = g_list_concat(purple_log_get_system_logs(account), logs);
+	}
+	logs = g_list_sort(logs, purple_log_compare);
+
+	syslog_viewer = display_log_viewer(NULL, logs, _("System Log"), 0);
+}
+
+/****************************************************************************
+ * GNT LOG SUBSYSTEM *******************************************************
+ ****************************************************************************/
+
+void *
+finch_log_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
+void finch_log_init(void)
+{
+	void *handle = finch_log_get_handle();
+
+	purple_signal_register(handle, "log-displaying",
+	                     purple_marshal_VOID__POINTER_POINTER,
+	                     NULL, 2,
+	                     purple_value_new(PURPLE_TYPE_BOXED,
+	                                    "FinchLogViewer *"),
+	                     purple_value_new(PURPLE_TYPE_SUBTYPE,
+	                                    PURPLE_SUBTYPE_LOG));
+}
+
+void
+finch_log_uninit(void)
+{
+	purple_signals_unregister_by_instance(finch_log_get_handle());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntlog.h	Mon Feb 04 04:04:02 2008 +0000
@@ -0,0 +1,83 @@
+/**
+ * @file gntlog.h GNT Log viewer
+ * @ingroup finch
+ * @see @ref gntlog-signals
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef _FINCHLOG_H_
+#define _FINCHLOG_H_
+
+#include "log.h"
+#include "account.h"
+#include "gntwidget.h"
+
+typedef struct _FinchLogViewer FinchLogViewer;
+
+/**
+ * A GNT Log Viewer.  You can look at logs with it.
+ */
+struct _FinchLogViewer {
+	GList *logs;                 /**< The list of logs viewed in this viewer   */
+
+	GntWidget	*window;    /**< The viewer's window                      */
+	GntWidget	*tree;      /**< The tree representing said treestore */
+	GntWidget	*text;      /**< The text to display said logs          */
+	GntWidget	*entry;     /**< The search entry, in which search terms
+	                              *   are entered                              */
+	GntWidget	*label;
+	PurpleLogReadFlags flags;      /**< The most recently used log flags         */
+	char		*search;    /**< The string currently being searched for  */
+};
+
+
+
+void finch_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account);
+void finch_log_show_contact(PurpleContact *contact);
+
+void finch_syslog_show(void);
+
+/**************************************************************************/
+/** @name GNT Log Subsystem                                              */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Initializes the GNT log subsystem.
+ */
+void finch_log_init(void);
+
+/**
+ * Returns the GNT log subsystem handle.
+ *
+ * @return The GNT log subsystem handle.
+ */
+void *finch_log_get_handle(void);
+
+/**
+ * Uninitializes the GNT log subsystem.
+ */
+void finch_log_uninit(void);
+
+/*@}*/
+
+#endif
--- a/finch/gntpounce.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntpounce.c	Mon Feb 04 04:04:02 2008 +0000
@@ -457,7 +457,7 @@
 
 	gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE));
 	gnt_box_add_widget(GNT_BOX(window), gnt_label_new_with_format(_("Options"), GNT_TEXT_FLAG_BOLD));
-	dialog->on_away = gnt_check_box_new(_("Pounce only when my status is not available"));
+	dialog->on_away = gnt_check_box_new(_("Pounce only when my status is not Available"));
 	gnt_box_add_widget(GNT_BOX(window), dialog->on_away);
 	dialog->save_pounce = gnt_check_box_new(_("Recurring"));
 	gnt_box_add_widget(GNT_BOX(window), dialog->save_pounce);
--- a/finch/gntui.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/gntui.c	Mon Feb 04 04:04:02 2008 +0000
@@ -30,6 +30,7 @@
 #include "gntconv.h"
 #include "gntdebug.h"
 #include "gntft.h"
+#include "gntlog.h"
 #include "gntnotify.h"
 #include "gntplugin.h"
 #include "gntpounce.h"
@@ -79,6 +80,9 @@
 	/* Pounce */
 	finch_pounces_init();
 
+	/* Log */
+	finch_log_init();
+
 	/* File transfer */
 	finch_xfers_init();
 	purple_xfers_set_ui_ops(finch_xfers_get_ui_ops());
@@ -124,6 +128,8 @@
 
 	finch_pounces_uninit();
 
+	finch_log_uninit();
+
 	finch_xfers_uninit();
 	purple_xfers_set_ui_ops(NULL);
 
--- a/finch/libgnt/gnttree.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/libgnt/gnttree.c	Mon Feb 04 04:04:02 2008 +0000
@@ -684,7 +684,7 @@
 	GntTreeRow *row = tree->current;
 	int dist;
 
-	if (!row->parent || SEARCHING(tree))
+	if (!row || !row->parent || SEARCHING(tree))
 		return FALSE;
 
 	tree->current = row->parent;
--- a/finch/libgnt/gnttree.h	Mon Feb 04 04:00:12 2008 +0000
+++ b/finch/libgnt/gnttree.h	Mon Feb 04 04:04:02 2008 +0000
@@ -332,7 +332,7 @@
  * @param color  The color
  * @since 2.4.0
  */
-void gnt_tree_set_row_color(GntTree *, void *, int);
+void gnt_tree_set_row_color(GntTree *tree, void *key, int color);
 
 /**
  * Select a row.
--- a/libpurple/account.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/account.c	Mon Feb 04 04:04:02 2008 +0000
@@ -2200,9 +2200,13 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	PurplePlugin *prpl = NULL;
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info != NULL && prpl_info->add_buddy != NULL)
 		prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy));
@@ -2213,10 +2217,14 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
+	PurplePlugin *prpl = NULL;
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		
 	if (prpl_info) {
 		GList *cur, *groups = NULL;
 
@@ -2248,10 +2256,14 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
+	PurplePlugin *prpl = NULL;
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		
 	if (prpl_info && prpl_info->remove_buddy)
 		prpl_info->remove_buddy(gc, buddy, group);
 }
@@ -2261,10 +2273,14 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
+	PurplePlugin *prpl = NULL;
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+		
 	if (prpl_info) {
 		if (prpl_info->remove_buddies)
 			prpl_info->remove_buddies(gc, buddies, groups);
@@ -2285,9 +2301,13 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	PurplePlugin *prpl = NULL;
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info && prpl_info->remove_group)
 		prpl_info->remove_group(gc, group);
@@ -2299,11 +2319,15 @@
 {
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc = purple_account_get_connection(account);
-
+	PurplePlugin *prpl = NULL;
+	
 	purple_account_set_password(account, new_pw);
-
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	
+	if (gc != NULL)
+	        prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info && prpl_info->change_passwd)
 		prpl_info->change_passwd(gc, orig_pw, new_pw);
@@ -2312,16 +2336,20 @@
 gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy)
 {
 	PurpleConnection *gc;
-	PurplePluginProtocolInfo *prpl_info;
-
+	PurplePluginProtocolInfo *prpl_info = NULL;
+	PurplePlugin *prpl = NULL;
+	
 	g_return_val_if_fail(account, FALSE);
 	g_return_val_if_fail(buddy, FALSE);
 
 	gc = purple_account_get_connection(account);
 	if (gc == NULL)
 		return FALSE;
-
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	
+	prpl = purple_connection_get_prpl(gc);      
+
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (!prpl_info || !prpl_info->offline_message)
 		return FALSE;
--- a/libpurple/blist.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/blist.c	Mon Feb 04 04:04:02 2008 +0000
@@ -1087,11 +1087,18 @@
 	if(old_name && source && strcmp(source->name, old_name)) {
 		for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) {
 			PurpleAccount *account = accts->data;
+			PurpleConnection *gc = NULL;
+			PurplePlugin *prpl = NULL;
 			PurplePluginProtocolInfo *prpl_info = NULL;
 			GList *l = NULL, *buddies = NULL;
 
-			if(account->gc && account->gc->prpl)
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
+			gc = purple_account_get_connection(account);
+			
+			if(gc)
+				prpl = purple_connection_get_prpl(gc);
+
+			if(gc && prpl)
+				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 			if(!prpl_info)
 				continue;
@@ -1104,7 +1111,7 @@
 			}
 
 			if(prpl_info->rename_group) {
-				prpl_info->rename_group(account->gc, old_name, source, buddies);
+				prpl_info->rename_group(gc, old_name, source, buddies);
 			} else {
 				GList *cur, *groups = NULL;
 
--- a/libpurple/buddyicon.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/buddyicon.c	Mon Feb 04 04:04:02 2008 +0000
@@ -707,7 +707,7 @@
 		PurplePluginProtocolInfo *prpl_info;
 
 		gc = purple_account_get_connection(account);
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 		if (prpl_info && prpl_info->set_buddy_icon)
 			prpl_info->set_buddy_icon(gc, img);
--- a/libpurple/conversation.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/conversation.c	Mon Feb 04 04:04:02 2008 +0000
@@ -402,7 +402,7 @@
 	if (gc != NULL)
 	{
 		/* Still connected */
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		{
@@ -1455,7 +1455,7 @@
 	conv      = purple_conv_chat_get_conversation(chat);
 	gc        = purple_conversation_get_gc(conv);
 	account   = purple_connection_get_account(gc);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 
 	/* Don't display this if the person who wrote it is ignored. */
 	if (purple_conv_chat_is_user_ignored(chat, who))
@@ -1574,7 +1574,7 @@
 
 	gc = purple_conversation_get_gc(conv);
 	g_return_if_fail(gc != NULL);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
 
 	ul = users;
@@ -1675,7 +1675,7 @@
 
 	gc = purple_conversation_get_gc(conv);
 	g_return_if_fail(gc != NULL);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
 
 	if (!strcmp(chat->nick, purple_normalize(conv->account, old_user))) {
@@ -1793,7 +1793,7 @@
 
 	gc = purple_conversation_get_gc(conv);
 	g_return_if_fail(gc != NULL);
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
 	g_return_if_fail(prpl_info != NULL);
 
 	ops  = purple_conversation_get_ui_ops(conv);
--- a/libpurple/privacy.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/privacy.c	Mon Feb 04 04:04:02 2008 +0000
@@ -202,9 +202,12 @@
 	return TRUE;
 }
 
-/* This makes sure that only all the buddies are in the permit list. */
+/**
+ * This makes sure your permit list contains all buddies from your
+ * buddy list and ONLY buddies from your buddy list.
+ */
 static void
-add_buddies_in_permit(PurpleAccount *account, gboolean local)
+add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local)
 {
 	GSList *list;
 
@@ -227,6 +230,12 @@
 	}
 }
 
+/*
+ * TODO: All callers of this function pass in FALSE for local and
+ *       restore and I don't understand when you would ever want to
+ *       use TRUE for either of them.  I think both parameters could
+ *       safely be removed in the next major version bump.
+ */
 void
 purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local,
 						gboolean restore)
@@ -256,7 +265,7 @@
 			break;
 		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
 			if (!purple_find_buddy(account, who)) {
-				add_buddies_in_permit(account, local);
+				add_all_buddies_to_permit_list(account, local);
 				purple_privacy_permit_add(account, who, local);
 				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
 			}
@@ -266,6 +275,12 @@
 	}
 }
 
+/*
+ * TODO: All callers of this function pass in FALSE for local and
+ *       restore and I don't understand when you would ever want to
+ *       use TRUE for either of them.  I think both parameters could
+ *       safely be removed in the next major version bump.
+ */
 void
 purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local,
 					gboolean restore)
@@ -295,7 +310,7 @@
 			break;
 		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
 			if (purple_find_buddy(account, who)) {
-				add_buddies_in_permit(account, local);
+				add_all_buddies_to_permit_list(account, local);
 				purple_privacy_permit_remove(account, who, local);
 				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
 			}
--- a/libpurple/protocols/msn/msn.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Feb 04 04:04:02 2008 +0000
@@ -655,8 +655,22 @@
 	 */
 	if (full && user)
 	{
+		const char *phone;
+
 		purple_notify_user_info_add_pair(user_info, _("Blocked"),
 									   ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
+
+		phone = msn_user_get_home_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
+
+		phone = msn_user_get_work_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
+
+		phone = msn_user_get_mobile_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
 	}
 }
 
--- a/libpurple/protocols/msnp9/msn.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msnp9/msn.c	Mon Feb 04 04:04:02 2008 +0000
@@ -557,8 +557,22 @@
 	 * you, which is the important information that this is trying to convey. */
 	if (full && user)
 	{
+		const char *phone;
+
 		purple_notify_user_info_add_pair(user_info, _("Blocked"),
 									   ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
+
+		phone = msn_user_get_home_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
+
+		phone = msn_user_get_work_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
+
+		phone = msn_user_get_mobile_phone(user);
+		if (phone != NULL)
+			purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
 	}
 }
 
--- a/libpurple/protocols/msnp9/notification.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msnp9/notification.c	Mon Feb 04 04:04:02 2008 +0000
@@ -840,6 +840,38 @@
 }
 
 static void
+bpr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	const char *type, *value, *passport;
+	MsnUser *user;
+
+	passport = cmd->params[1];
+	user = msn_userlist_find_user(cmdproc->session->userlist, passport);
+
+	g_return_if_fail(user != NULL);
+
+	type     = cmd->params[2];
+	value    = cmd->params[3];
+
+	if (value)
+	{
+		if (!strcmp(type, "MOB"))
+		{
+			if (!strcmp(value, "Y"))
+				user->mobile = TRUE;
+			else if (!strcmp(value, "N"))
+				user->mobile = FALSE;
+		}
+		else if (!strcmp(type, "PHH"))
+			msn_user_set_home_phone(user, purple_url_decode(value));
+		else if (!strcmp(type, "PHW"))
+			msn_user_set_work_phone(user, purple_url_decode(value));
+		else if (!strcmp(type, "PHM"))
+			msn_user_set_mobile_phone(user, purple_url_decode(value));
+	}
+}
+
+static void
 reg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session;
@@ -1435,6 +1467,7 @@
 	msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
 	msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
 	msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
+	msn_table_add_cmd(cbs_table, NULL, "BPR", bpr_cmd);
 
 	msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
 	msn_table_add_cmd(cbs_table, NULL, "REM", rem_cmd);
--- a/libpurple/protocols/msnp9/session.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msnp9/session.c	Mon Feb 04 04:04:02 2008 +0000
@@ -397,8 +397,13 @@
 	PurpleStoredImage *img;
 	const char *passport;
 
-	if (session->logged_in)
+	if (session->logged_in) {
+		/* We are probably here because of a mid-session notification server XFR
+		 * We must send a CHG now, otherwise the servers default to invisible,
+		 * and prevent things happening, like sending IMs */
+		msn_change_status(session);
 		return;
+	}
 
 	account = session->account;
 	gc = purple_account_get_connection(account);
--- a/libpurple/protocols/msnp9/sync.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msnp9/sync.c	Mon Feb 04 04:04:02 2008 +0000
@@ -206,6 +206,8 @@
 		{
 			if (!strcmp(value, "Y"))
 				user->mobile = TRUE;
+			else if (!strcmp(value, "N"))
+				user->mobile = FALSE;
 		}
 		else if (!strcmp(type, "PHH"))
 			msn_user_set_home_phone(user, purple_url_decode(value));
--- a/libpurple/protocols/msnp9/user.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/msnp9/user.c	Mon Feb 04 04:04:02 2008 +0000
@@ -36,7 +36,8 @@
 	user->userlist = userlist;
 
 	msn_user_set_passport(user, passport);
-	msn_user_set_friendly_name(user, friendly_name);
+	if (friendly_name != NULL)
+		msn_user_set_friendly_name(user, friendly_name);
 
 	return user;
 }
--- a/libpurple/protocols/qq/login_logout.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/qq/login_logout.c	Mon Feb 04 04:04:02 2008 +0000
@@ -485,11 +485,15 @@
 			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password."));
 		break;
 	case QQ_LOGIN_REPLY_MISC_ERROR:
-		purple_connection_error_reason(gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login, check debug log"));
+			if (purple_debug_is_enabled())
+				purple_connection_error_reason(gc,
+					PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login. Check debug log."));
+			else
+				purple_connection_error_reason(gc,
+					PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login"));				
 		break;
 	case QQ_LOGIN_REPLY_OK:
-		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login replys OK, everything is fine\n");
+		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login repliess OK; everything is fine\n");
 		break;
 	case QQ_LOGIN_REPLY_REDIRECT:
 		/* the redirect has been done in _qq_process_login_reply */
--- a/libpurple/protocols/silc10/ops.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/silc10/ops.c	Mon Feb 04 04:04:02 2008 +0000
@@ -1697,27 +1697,32 @@
 		return;
 		break;
 	case SILC_CLIENT_CONN_ERROR:
-		purple_connection_error(gc, _("Error during connecting to SILC Server"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Error during connecting to SILC Server"));
 		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_KE:
-		purple_connection_error(gc, _("Key Exchange failed"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
+			_("Key Exchange failed"));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_AUTH:
-		purple_connection_error(gc, _("Authentication failed"));
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+			_("Authentication failed"));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_RESUME:
-		purple_connection_error(gc,
-				      _("Resuming detached session failed. "
-					"Press Reconnect to create new connection."));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+			_("Resuming detached session failed. "
+			  "Press Reconnect to create new connection."));
 		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
 		break;
 
 	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
-		purple_connection_error(gc, _("Connection Timeout"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Connection Timeout"));
 		break;
 	}
 
@@ -1746,7 +1751,8 @@
 
 	/* Close the connection */
 	if (!sg->detaching)
-		purple_connection_error(gc, _("Disconnected by server"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Disconnected by server"));
 	else
 		/* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
 		purple_account_disconnect(purple_connection_get_account(gc));
--- a/libpurple/protocols/silc10/silc.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/silc10/silc.c	Mon Feb 04 04:04:02 2008 +0000
@@ -158,7 +158,9 @@
 	sg = gc->proto_data;
 
 	if (source < 0) {
-		purple_connection_error(gc, _("Connection failed"));
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Connection failed"));
 		return;
 	}
 
@@ -179,7 +181,8 @@
 							  "silc.silcnet.org"),
 			  purple_account_get_int(account, "port", 706), sg);
 	if (!conn) {
-		purple_connection_error(gc, _("Cannot initialize SILC Client connection"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Cannot initialize SILC Client connection"));
 		gc->proto_data = NULL;
 		return;
 	}
@@ -264,7 +267,8 @@
 	/* Allocate SILC client */
 	client = silc_client_alloc(&ops, &params, gc, NULL);
 	if (!client) {
-		purple_connection_error(gc, _("Out of memory"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		                             _("Out of memory"));
 		return;
 	}
 
@@ -309,15 +313,15 @@
 
 	/* Init SILC client */
 	if (!silc_client_init(client)) {
-		gc->wants_to_die = TRUE;
-		purple_connection_error(gc, _("Cannot initialize SILC protocol"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		                             _("Cannot initialize SILC protocol"));
 		return;
 	}
 
 	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
 	if (!silcpurple_check_silc_dir(gc)) {
-		gc->wants_to_die = TRUE;
-		purple_connection_error(gc, _("Cannot find/access ~/.silc directory"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		                             _("Error loading SILC key pair"));
 		return;
 	}
 
@@ -332,7 +336,8 @@
 				(gc->password == NULL) ? "" : gc->password, &client->pkcs,
 				&client->public_key, &client->private_key)) {
 		g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair: %s"), g_strerror(errno));
-		purple_connection_error(gc, pkd);
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+		                             _("Could not load SILC key pair"));
 		return;
 	}
 
@@ -352,7 +357,8 @@
 			       purple_account_get_int(account, "port", 706),
 			       silcpurple_login_connected, gc) == NULL)
 	{
-		purple_connection_error(gc, _("Unable to create connection"));
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		                             _("Unable to create connection"));
 		return;
 	}
 
--- a/libpurple/protocols/simple/simple.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/simple/simple.c	Mon Feb 04 04:04:02 2008 +0000
@@ -1983,13 +1983,6 @@
 	gc->proto_data = NULL;
 }
 
-/* not needed since privacy is checked for every subscribe */
-static void dummy_add_deny(PurpleConnection *gc, const char *name) {
-}
-
-static void dummy_permit_deny(PurpleConnection *gc) {
-}
-
 static PurplePluginProtocolInfo prpl_info =
 {
 	0,
@@ -2017,11 +2010,11 @@
 	NULL,					/* add_buddies */
 	simple_remove_buddy,	/* remove_buddy */
 	NULL,					/* remove_buddies */
-	dummy_add_deny,			/* add_permit */
-	dummy_add_deny,			/* add_deny */
-	dummy_add_deny,			/* rem_permit */
-	dummy_add_deny,			/* rem_deny */
-	dummy_permit_deny,		/* set_permit_deny */
+	NULL,					/* add_permit */
+	NULL,					/* add_deny */
+	NULL,					/* rem_permit */
+	NULL,					/* rem_deny */
+	NULL,					/* set_permit_deny */
 	NULL,					/* join_chat */
 	NULL,					/* reject_chat */
 	NULL,					/* get_chat_name */
--- a/libpurple/protocols/yahoo/yahoo.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Mon Feb 04 04:04:02 2008 +0000
@@ -61,58 +61,6 @@
 #endif
 static void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);
 
-static void
-yahoo_add_permit(PurpleConnection *gc, const char *who)
-{
-	purple_debug_info("yahoo",
-			"Permitting ID %s local contact rights for account %s\n", who, gc->account);
-	purple_privacy_permit_add(gc->account,who,TRUE);
-}
-
-static void
-yahoo_rem_permit(PurpleConnection *gc, const char *who)
-{
-	purple_debug_info("yahoo",
-			"Denying ID %s local contact rights for account %s\n", who, gc->account);
-	purple_privacy_permit_remove(gc->account,who,TRUE);
-}
-
-gboolean
-yahoo_privacy_check(PurpleConnection *gc, const char *who)
-{
-	/* returns TRUE if allowed through, FALSE otherwise */
-	gboolean permitted;
-
-	permitted = purple_privacy_check(gc->account, who);
-
-	/* print some debug info */
-	if (!permitted) {
-		char *deb = NULL;
-		switch (gc->account->perm_deny)
-		{
-			case PURPLE_PRIVACY_DENY_ALL:
-				deb = "PURPLE_PRIVACY_DENY_ALL";
-			break;
-			case PURPLE_PRIVACY_DENY_USERS:
-				deb = "PURPLE_PRIVACY_DENY_USERS";
-			break;
-			case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-				deb = "PURPLE_PRIVACY_ALLOW_BUDDYLIST";
-			break;
-		}
-		if(deb)
-			purple_debug_info("yahoo",
-				"%s blocked data received from %s (%s)\n",
-				gc->account->username,who, deb);
-	} else if (gc->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) {
-		purple_debug_info("yahoo",
-			"%s allowed data received from %s (PURPLE_PRIVACY_ALLOW_USERS)\n",
-			gc->account->username,who);
-	}
-
-	return permitted;
-}
-
 static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f)
 {
 	char *status = NULL;
@@ -700,7 +648,7 @@
 		for (bud = buddies; bud && *bud; bud++) {
 			/* The server is already ignoring the user */
 			got_serv_list = TRUE;
-			purple_privacy_deny_add(gc->account, *bud, 1);
+			purple_privacy_deny_add(account, *bud, 1);
 		}
 		g_strfreev(buddies);
 
@@ -709,13 +657,13 @@
 	}
 
 	if (got_serv_list &&
-		((gc->account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
-		(gc->account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
-		(gc->account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
+		((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
+		(account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
+		(account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
 	{
-		gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+		account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
 		purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
-		      gc->account->username);
+				account->username);
 	}
 
 	if (yd->tmp_serv_plist) {
@@ -724,7 +672,7 @@
 			f = yahoo_friend_find(gc, *bud);
 			if (f) {
 				purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n",
-								 gc->account->username, *bud);
+						account->username, *bud);
 				f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
 			}
 		}
@@ -739,6 +687,7 @@
 
 static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
+	PurpleAccount *account;
 	char *msg = NULL;
 	char *from = NULL;
 	char *stat = NULL;
@@ -746,6 +695,8 @@
 	YahooFriend *f = NULL;
 	GSList *l = pkt->hash;
 
+	account = purple_connection_get_account(gc);
+
 	while (l) {
 		struct yahoo_pair *pair = l->data;
 		if (pair->key == 4)
@@ -763,13 +714,14 @@
 		return;
 
 	if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
-		&& (yahoo_privacy_check(gc, from)))  {
+		&& (purple_privacy_check(account, from)))
+	{
 		if (*stat == '1')
 			serv_got_typing(gc, from, 0, PURPLE_TYPING);
 		else
 			serv_got_typing_stopped(gc, from);
 	} else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
-		PurpleBuddy *bud = purple_find_buddy(gc->account, from);
+		PurpleBuddy *bud = purple_find_buddy(account, from);
 
 		if (!bud) {
 			purple_debug(PURPLE_DEBUG_WARNING, "yahoo",
@@ -789,7 +741,7 @@
 				yahoo_update_status(gc, from, f);
 		}
 	} else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
-                PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, gc->account);
+		PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, account);
 		char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from);
 		purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL));
 		g_free(buf);
@@ -808,13 +760,15 @@
 
 static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
+	PurpleAccount *account;
 	struct yahoo_data *yd = gc->proto_data;
 	GSList *l = pkt->hash;
 	GSList *list = NULL;
 	struct _yahoo_im *im = NULL;
-
 	const char *imv = NULL;
 
+	account = purple_connection_get_account(gc);
+
 	if (pkt->status <= 1 || pkt->status == 5) {
 		while (l != NULL) {
 			struct yahoo_pair *pair = l->data;
@@ -859,20 +813,20 @@
 		{
 			PurpleWhiteboard *wb;
 
-			if (!yahoo_privacy_check(gc, im->from)) {
+			if (!purple_privacy_check(account, im->from)) {
 				purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from);
 				return;
 			}
 
 			/* I'm not sure the following ever happens -DAA */
 
-			wb = purple_whiteboard_get_session(gc->account, im->from);
+			wb = purple_whiteboard_get_session(account, im->from);
 
 			/* If a Doodle session doesn't exist between this user */
 			if(wb == NULL)
 			{
 				doodle_session *ds;
-				wb = purple_whiteboard_create(gc->account, im->from, DOODLE_STATE_REQUESTED);
+				wb = purple_whiteboard_create(account, im->from, DOODLE_STATE_REQUESTED);
 				ds = wb->proto_data;
 				ds->imv_key = g_strdup(imv);
 
@@ -892,7 +846,7 @@
 			continue;
 		}
 
-		if (!yahoo_privacy_check(gc, im->from)) {
+		if (!purple_privacy_check(account, im->from)) {
 			purple_debug_info("yahoo", "Message from %s dropped.\n", im->from);
 			return;
 		}
@@ -908,11 +862,9 @@
 		purple_util_chrreplace(m, '\r', '\n');
 
 		if (!strcmp(m, "<ding>")) {
-			PurpleAccount *account;
 			PurpleConversation *c;
 			char *username;
 
-			account = purple_connection_get_account(gc);
 			c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->from, account);
 			if (c == NULL)
 				c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, im->from);
@@ -975,22 +927,20 @@
 };
 
 static void
-yahoo_buddy_add_authorize_cb(gpointer data) {
+yahoo_buddy_add_authorize_cb(gpointer data)
+{
 	struct yahoo_add_request *add_req = data;
-
-	if (PURPLE_CONNECTION_IS_VALID(add_req->gc)) {
-		struct yahoo_packet *pkt;
-		struct yahoo_data *yd = add_req->gc->proto_data;
-
-		pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, 0);
-		yahoo_packet_hash(pkt, "ssiii",
-						  1, add_req->id,
-						  5, add_req->who,
-						  241, add_req->protocol,
-						  13, 1,
-						  334, 0);
-		yahoo_packet_send_and_free(pkt, yd);
-	}
+	struct yahoo_packet *pkt;
+	struct yahoo_data *yd = add_req->gc->proto_data;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, 0);
+	yahoo_packet_hash(pkt, "ssiii",
+					  1, add_req->id,
+					  5, add_req->who,
+					  241, add_req->protocol,
+					  13, 1,
+					  334, 0);
+	yahoo_packet_send_and_free(pkt, yd);
 
 	g_free(add_req->id);
 	g_free(add_req->who);
@@ -998,32 +948,30 @@
 }
 
 static void
-yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg) {
-
-	if (PURPLE_CONNECTION_IS_VALID(add_req->gc)) {
-		struct yahoo_data *yd = add_req->gc->proto_data;
-		struct yahoo_packet *pkt;
-		char *encoded_msg = NULL;
-		PurpleAccount *account = purple_connection_get_account(add_req->gc);
-
-		if (msg && *msg)
-			encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL);
-
-		pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15,
-				YAHOO_STATUS_AVAILABLE, 0);
-
-		yahoo_packet_hash(pkt, "ssiiis",
-				1, purple_normalize(account, purple_account_get_username(account)),
-				5, add_req->who,
-				13, 2,
-				334, 0,
-				97, 1,
-				14, encoded_msg ? encoded_msg : "");
-
-		yahoo_packet_send_and_free(pkt, yd);
-
-		g_free(encoded_msg);
-	}
+yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
+{
+	struct yahoo_data *yd = add_req->gc->proto_data;
+	struct yahoo_packet *pkt;
+	char *encoded_msg = NULL;
+	PurpleAccount *account = purple_connection_get_account(add_req->gc);
+
+	if (msg && *msg)
+		encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL);
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15,
+			YAHOO_STATUS_AVAILABLE, 0);
+
+	yahoo_packet_hash(pkt, "ssiiis",
+			1, purple_normalize(account, purple_account_get_username(account)),
+			5, add_req->who,
+			13, 2,
+			334, 0,
+			97, 1,
+			14, encoded_msg ? encoded_msg : "");
+
+	yahoo_packet_send_and_free(pkt, yd);
+
+	g_free(encoded_msg);
 
 	g_free(add_req->id);
 	g_free(add_req->who);
@@ -1071,9 +1019,12 @@
 }
 
 static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) {
+	PurpleAccount *account;
 	GSList *l = pkt->hash;
 	const char *msg = NULL;
 
+	account = purple_connection_get_account(gc);
+
 	/* Buddy authorized/declined our addition */
 	if (pkt->status == 1) {
 		const char *who = NULL;
@@ -1143,7 +1094,8 @@
 		if (add_req->id && add_req->who) {
 			char *alias = NULL, *dec_msg = NULL;
 
-			if (!yahoo_privacy_check(gc, add_req->who)) {
+			if (!purple_privacy_check(account, add_req->who))
+			{
 				purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
 						  add_req->who);
 				yahoo_buddy_add_deny_cb(add_req, NULL);
@@ -1163,11 +1115,12 @@
 			/* DONE! this is almost exactly the same as what MSN does,
 			 * this should probably be moved to the core.
 			 */
-			 purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id,
-						    alias, dec_msg, purple_find_buddy(purple_connection_get_account(gc), add_req->who) != NULL,
-						    yahoo_buddy_add_authorize_cb,
-						    yahoo_buddy_add_deny_reason_cb,
-						    add_req);
+			 purple_account_request_authorization(account, add_req->who, add_req->id,
+					alias, dec_msg,
+					purple_find_buddy(account, add_req->who) != NULL,
+					yahoo_buddy_add_authorize_cb,
+					yahoo_buddy_add_deny_reason_cb,
+					add_req);
 			g_free(alias);
 			g_free(dec_msg);
 		} else {
@@ -1182,10 +1135,13 @@
 
 /* I don't think this happens anymore in Version 15 */
 static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) {
+	PurpleAccount *account;
 	struct yahoo_add_request *add_req;
 	char *msg = NULL;
 	GSList *l = pkt->hash;
 
+	account = purple_connection_get_account(gc);
+
 	add_req = g_new0(struct yahoo_add_request, 1);
 	add_req->gc = gc;
 
@@ -1211,7 +1167,7 @@
 	if (add_req->id && add_req->who) {
 		char *dec_msg = NULL;
 
-		if (!yahoo_privacy_check(gc, add_req->who)) {
+		if (!purple_privacy_check(account, add_req->who)) {
 			purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
 					  add_req->who);
 			yahoo_buddy_add_deny_cb(add_req, NULL);
@@ -1224,11 +1180,11 @@
 		/* DONE! this is almost exactly the same as what MSN does,
 		 * this should probably be moved to the core.
 		 */
-		 purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id,
-                                                    NULL, dec_msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL,
-						    yahoo_buddy_add_authorize_cb,
-						    yahoo_buddy_add_deny_reason_cb,
-                                                    add_req);
+		 purple_account_request_authorization(account, add_req->who, add_req->id,
+				NULL, dec_msg,
+				purple_find_buddy(account,add_req->who) != NULL,
+						yahoo_buddy_add_authorize_cb,
+						yahoo_buddy_add_deny_reason_cb, add_req);
 		g_free(dec_msg);
 	} else {
 		g_free(add_req->id);
@@ -2285,9 +2241,12 @@
 
 static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
+	PurpleAccount *account;
 	char *who = NULL, *msg = NULL, *id = NULL;
 	GSList *l = pkt->hash;
 
+	account = purple_connection_get_account(gc);
+
 	while (l) {
 		struct yahoo_pair *pair = l->data;
 
@@ -2323,9 +2282,9 @@
 		purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
 		return;
 	}
-	if (!yahoo_privacy_check(gc, who)) {
+	if (!purple_privacy_check(account, who)) {
 		purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n",
-		      gc->account->username, who);
+				purple_account_get_username(account), who);
 		return;
 	}
 	if (id) {
@@ -3873,12 +3832,10 @@
 	yahoo_packet_send_and_free(pkt, yd);
 }
 
-/* XXX - What's the deal with PurpleGroup *foo? */
-static void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *foo)
+static void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
 {
 	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
 	struct yahoo_packet *pkt;
-	PurpleGroup *g;
 	const char *group = NULL;
 	char *group2;
 	YahooFriend *f;
@@ -3886,20 +3843,17 @@
 	if (!yd->logged_in)
 		return;
 
-	if (!yahoo_privacy_check(gc, purple_buddy_get_name(buddy)))
+	if (!purple_privacy_check(purple_connection_get_account(gc),
+			purple_buddy_get_name(buddy)))
 		return;
 
 	f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
 
-	if (foo)
-		group = foo->name;
-	if (!group) {
-		g = purple_buddy_get_group(buddy);
-		if (g)
-			group = g->name;
-		else
-			group = "Buddies";
-	}
+	g = purple_buddy_get_group(buddy);
+	if (g)
+		group = g->name;
+	else
+		group = "Buddies";
 
 	group2 = yahoo_string_encode(gc, group, NULL);
 	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0);
@@ -3961,10 +3915,6 @@
 
 	if (!yd->logged_in)
 		return;
-	/* It seems to work better without this */
-
-	/* if (gc->account->perm_deny != 4)
-		return; */
 
 	if (!who || who[0] == '\0')
 		return;
@@ -3990,34 +3940,27 @@
 	yahoo_packet_send_and_free(pkt, yd);
 }
 
-static void yahoo_set_permit_deny(PurpleConnection *gc) {
-	PurpleAccount *acct;
+static void yahoo_set_permit_deny(PurpleConnection *gc)
+{
+	PurpleAccount *account;
 	GSList *deny;
 
-	acct = gc->account;
-
-	switch (acct->perm_deny) {
-		/* privacy 1 */
+	account = purple_connection_get_account(gc);
+
+	switch (account->perm_deny)
+	{
 		case PURPLE_PRIVACY_ALLOW_ALL:
-			for (deny = acct->deny;deny;deny = deny->next)
+			for (deny = account->deny; deny; deny = deny->next)
 				yahoo_rem_deny(gc, deny->data);
 			break;
-		/* privacy 3 */
-		case PURPLE_PRIVACY_ALLOW_USERS:
-			for (deny = acct->deny;deny;deny = deny->next)
-				yahoo_rem_deny(gc, deny->data);
-			break;
-		/* privacy 5 */
+
 		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-		/* privacy 4 */
+		case PURPLE_PRIVACY_ALLOW_USERS:
 		case PURPLE_PRIVACY_DENY_USERS:
-			for (deny = acct->deny;deny;deny = deny->next)
+		case PURPLE_PRIVACY_DENY_ALL:
+			for (deny = account->deny; deny; deny = deny->next)
 				yahoo_add_deny(gc, deny->data);
 			break;
-		/* privacy 2 */
-		case PURPLE_PRIVACY_DENY_ALL:
-		default:
-			break;
 	}
 }
 
@@ -4347,9 +4290,9 @@
 	NULL, /* add_buddies */
 	yahoo_remove_buddy,
 	NULL, /*remove_buddies */
-	yahoo_add_permit,
+	NULL, /* add_permit */
 	yahoo_add_deny,
-	yahoo_rem_permit,
+	NULL, /* rem_permit */
 	yahoo_rem_deny,
 	yahoo_set_permit_deny,
 	yahoo_c_join,
--- a/libpurple/protocols/yahoo/yahoo.h	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.h	Mon Feb 04 04:04:02 2008 +0000
@@ -232,15 +232,6 @@
 */
 gchar* yahoo_get_cookies(PurpleConnection *gc);
 
-/**
- * Check to see whether the sender is permitted to send
- *
- * @param gc The gc handle.
- * @param who The sender of the packet to check
-*/
-gboolean yahoo_privacy_check
-	(PurpleConnection *gc, const char *who);
-
 gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
 GList *yahoo_attention_types(PurpleAccount *account);
 
--- a/libpurple/protocols/yahoo/yahoochat.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Mon Feb 04 04:04:02 2008 +0000
@@ -114,6 +114,7 @@
 
 void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
+	PurpleAccount *account;
 	GSList *l;
 	char *room = NULL;
 	char *who = NULL;
@@ -124,6 +125,8 @@
 	if (pkt->status == 2)
 		return; /* XXX */
 
+	account = purple_connection_get_account(gc);
+
 	members = g_string_sized_new(512);
 
 	for (l = pkt->hash; l; l = l->next) {
@@ -159,8 +162,9 @@
 		return;
 	}
 
-	if (!yahoo_privacy_check(gc, who) ||
-			(purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
+	if (!purple_privacy_check(account, who) ||
+			(purple_account_get_bool(account, "ignore_invites", FALSE)))
+	{
 		purple_debug_info("yahoo",
 		    "Invite to conference %s from %s has been dropped.\n", room, who);
 		g_free(room);
@@ -203,7 +207,8 @@
 			break;
 		}
 	}
-	if (!yahoo_privacy_check(gc, who)) {
+	if (!purple_privacy_check(purple_connection_get_account(gc), who))
+	{
 		g_free(room);
 		g_free(msg);
 		return;
@@ -664,11 +669,14 @@
 
 void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt)
 {
+	PurpleAccount *account;
 	GSList *l;
 	char *room = NULL;
 	char *msg = NULL;
 	char *who = NULL;
 
+	account = purple_connection_get_account(gc);
+
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
 
@@ -696,8 +704,9 @@
 	if (room && who) {
 		GHashTable *components;
 
-		if (!yahoo_privacy_check(gc, who) ||
-				(purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) {
+		if (!purple_privacy_check(account, who) ||
+				(purple_account_get_bool(account, "ignore_invites", FALSE)))
+		{
 			purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
 			g_free(room);
 			g_free(msg);
--- a/libpurple/protocols/zephyr/zephyr.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Mon Feb 04 04:04:02 2008 +0000
@@ -858,52 +858,8 @@
 			
 			if (!g_ascii_strcasecmp(notice.z_opcode,"PING"))
 				serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
-			else {
-				/* Based on the values of
-				   account->permit_deny,
-				   account->permit, account>deny , and
-				   the buddylist */
-
-				GSList* l;
-				gboolean in_deny;
-
-				switch (gc->account->perm_deny) {
-				case PURPLE_PRIVACY_ALLOW_ALL: 
-					in_deny = 0; break;
-				case PURPLE_PRIVACY_DENY_ALL: 
-					in_deny = 1; break;
-				case PURPLE_PRIVACY_ALLOW_USERS: /* See if stripped_sender is in gc->account->permit and allow appropriately */
-					in_deny = 1;
-					for(l=gc->account->permit;l!=NULL;l=l->next) {
-						if (!purple_utf8_strcasecmp(stripped_sender, purple_normalize(gc->account, (char *)l->data))) {
-							in_deny=0;
-							break;
-						} 
-					}
-					break;
-				case PURPLE_PRIVACY_DENY_USERS: /* See if stripped_sender is in gc->account->deny and deny if so */ 
-					in_deny = 0;
-					for(l=gc->account->deny;l!=NULL;l=l->next) {
-						if (!purple_utf8_strcasecmp(stripped_sender, purple_normalize(gc->account, (char *)l->data))) {
-							in_deny=1;
-							break;
-						} 
-					}
-					break;
-				case PURPLE_PRIVACY_ALLOW_BUDDYLIST: 
-					in_deny = 1;
-					if (purple_find_buddy(gc->account,stripped_sender)!=NULL) {
-						in_deny = 0;
-					}
-					break;
-				default: 
-					in_deny=0; break;
-				}
-				
-				if (!in_deny) {
-					serv_got_im(gc, stripped_sender, buf3, flags, time(NULL));
-				}
-			}
+			else
+				serv_got_im(gc, stripped_sender, buf3, flags, time(NULL));
 
 			g_free(stripped_sender);
 		} else {
@@ -2272,6 +2228,26 @@
 	return buf;
 }
 
+static const char *zephyr_normalize(const PurpleAccount *account, const char *who)
+{
+	static char buf[BUF_LEN];
+	PurpleConnection *gc;
+	char *tmp;
+
+	gc = purple_account_get_connection(account);
+	tmp = local_zephyr_normalize(gc->proto_data, who);
+
+	if (strlen(tmp) >= sizeof(buf)) {
+		g_free(tmp);
+		return NULL;
+	}
+
+	strcpy(buf, tmp);
+	g_free(tmp);
+
+	return buf;
+}
+
 static void zephyr_zloc(PurpleConnection *gc, const char *who)
 {
 	ZAsyncLocateData_t ald;
@@ -2782,36 +2758,6 @@
 }
 
 
-static void
-zephyr_add_deny(PurpleConnection *gc, const char *who)
-{
-	purple_privacy_deny_add(gc->account,who,1);
-}
-
-static void
-zephyr_remove_deny(PurpleConnection *gc, const char *who)
-{
-	purple_privacy_deny_remove(gc->account,who,1);
-}
-
-static void
-zephyr_add_permit(PurpleConnection *gc, const char *who)
-{
-	purple_privacy_permit_add(gc->account,who,1);
-}
-
-static void
-zephyr_remove_permit(PurpleConnection *gc, const char *who)
-{
-	purple_privacy_permit_remove(gc->account,who,1);
-}
-
-static void
-zephyr_set_permit_deny(PurpleConnection *gc)
-{
-	/* This doesn't have to do anything, since really, we can just check account->perm_deny when deciding whether to di */
-	return;
-}
 static int zephyr_resubscribe(PurpleConnection *gc)
 {
 	/* Resubscribe to the in-memory list of subscriptions and also
@@ -2920,11 +2866,11 @@
 	NULL,					/* add_buddies */
 	NULL,					/* remove_buddy */
 	NULL,					/* remove_buddies */
-	zephyr_add_permit,		/* add_permit */
-	zephyr_add_deny,		/* add_deny */
-	zephyr_remove_permit,	/* remove_permit */
-	zephyr_remove_deny,		/* remove_deny */
-	zephyr_set_permit_deny,	/* set_permit_deny */
+	NULL,					/* add_permit */
+	NULL,					/* add_deny */
+	NULL,					/* remove_permit */
+	NULL,					/* remove_deny */
+	NULL,					/* set_permit_deny */
 	zephyr_join_chat,		/* join_chat */
 	NULL,					/* reject_chat -- No chat invites*/
 	zephyr_get_chat_name,	/* get_chat_name */
@@ -2941,7 +2887,7 @@
 	NULL,					/* rename_group */
 	NULL,					/* buddy_free */
 	NULL,					/* convo_closed */
-	NULL,					/* normalize */
+	zephyr_normalize,		/* normalize */
 	NULL,					/* XXX set_buddy_icon */
 	NULL,					/* remove_group */
 	NULL,					/* XXX get_cb_real_name */
--- a/libpurple/roomlist.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/roomlist.c	Mon Feb 04 04:04:02 2008 +0000
@@ -169,20 +169,25 @@
 
 PurpleRoomlist *purple_roomlist_get_list(PurpleConnection *gc)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	g_return_val_if_fail(gc != NULL, NULL);
 
-	if (gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->roomlist_get_list)
+	if(prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->roomlist_get_list)
 		return prpl_info->roomlist_get_list(gc);
+
 	return NULL;
 }
 
 void purple_roomlist_cancel_get_list(PurpleRoomlist *list)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc;
 
@@ -192,15 +197,19 @@
 
 	g_return_if_fail(gc != NULL);
 
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->roomlist_cancel)
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->roomlist_cancel)
 		prpl_info->roomlist_cancel(list);
 }
 
 void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConnection *gc;
 
@@ -211,10 +220,13 @@
 	gc = purple_account_get_connection(list->account);
 	g_return_if_fail(gc != NULL);
 
-	if (gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->roomlist_expand_category)
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->roomlist_expand_category)
 		prpl_info->roomlist_expand_category(list, category);
 }
 
--- a/libpurple/server.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/server.c	Mon Feb 04 04:04:02 2008 +0000
@@ -44,12 +44,16 @@
 unsigned int
 serv_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->send_typing)
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->send_typing)
 		return prpl_info->send_typing(gc, name, state);
 
 	return 0;
@@ -117,24 +121,28 @@
 int serv_send_im(PurpleConnection *gc, const char *name, const char *message,
 				 PurpleMessageFlags flags)
 {
-	PurpleConversation *conv;
-	PurpleAccount *account;
-	PurplePresence *presence;
-	PurplePluginProtocolInfo *prpl_info;
+	PurpleConversation *conv = NULL;
+	PurpleAccount *account = NULL;
+	PurplePresence *presence = NULL;
+	PurplePlugin *prpl = NULL;
+	PurplePluginProtocolInfo *prpl_info = NULL;
 	int val = -EINVAL;
-	const gchar *auto_reply_pref;
+	const gchar *auto_reply_pref = NULL;
 
 	g_return_val_if_fail(gc != NULL, val);
-	g_return_val_if_fail(gc->prpl != NULL, val);
+
+	prpl = purple_connection_get_prpl(gc);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	g_return_val_if_fail(prpl != NULL, val);
+
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	account  = purple_connection_get_account(gc);
 	presence = purple_account_get_presence(account);
 
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
+	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account);
 
-	if (prpl_info && prpl_info->send_im)
+	if(prpl_info && prpl_info->send_im)
 		val = prpl_info->send_im(gc, name, message, flags);
 
 	/*
@@ -142,7 +150,7 @@
 	 * this only reset lar->sent if we're away AND idle?
 	 */
 	auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply");
-	if ((gc->flags & PURPLE_CONNECTION_AUTO_RESP) &&
+	if((gc->flags & PURPLE_CONNECTION_AUTO_RESP) &&
 			flags & PURPLE_MESSAGE_AUTO_RESP &&
 			!purple_presence_is_available(presence) &&
 			strcmp(auto_reply_pref, "never")) {
@@ -152,7 +160,7 @@
 		lar->sent = time(NULL);
 	}
 
-	if (conv && purple_conv_im_get_send_typed_timeout(PURPLE_CONV_IM(conv)))
+	if(conv && purple_conv_im_get_send_typed_timeout(PURPLE_CONV_IM(conv)))
 		purple_conv_im_stop_send_typed_timeout(PURPLE_CONV_IM(conv));
 
 	return val;
@@ -160,28 +168,36 @@
 
 void serv_get_info(PurpleConnection *gc, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+	
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-	if (gc && prpl_info && prpl_info->get_info)
+	if(gc && prpl_info && prpl_info->get_info)
 		prpl_info->get_info(gc, name);
 }
 
 void serv_set_info(PurpleConnection *gc, const char *info)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
-	PurpleAccount *account;
+	PurpleAccount *account = NULL;;
 
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+	
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-	if (prpl_info && prpl_info->set_info) {
+	if(prpl_info && prpl_info->set_info) {
 
 		account = purple_connection_get_account(gc);
 
-		if (purple_signal_emit_return_1(purple_accounts_get_handle(),
+		if(purple_signal_emit_return_1(purple_accounts_get_handle(),
 									  "account-setting-info", account, info))
 			return;
 
@@ -197,30 +213,45 @@
  */
 void serv_alias_buddy(PurpleBuddy *b)
 {
+	PurpleAccount *account = NULL;
+	PurpleConnection *gc = NULL;
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (b != NULL && b->account->gc && b->account->gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(b->account->gc->prpl);
+	if(b)
+		account = purple_buddy_get_account(b);
+
+	if(account)
+		gc = purple_account_get_connection(account);
 
-	if (b && prpl_info && prpl_info->alias_buddy) {
-		prpl_info->alias_buddy(b->account->gc, b->name, b->alias);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(b && prpl_info && prpl_info->alias_buddy) {
+		prpl_info->alias_buddy(gc, b->name, b->alias);
 	}
 }
 
 void
 serv_got_alias(PurpleConnection *gc, const char *who, const char *alias)
 {
-	PurpleAccount *account = purple_connection_get_account(gc);
-	GSList *buddies = purple_find_buddies(account, who);
+	PurpleAccount *account;
+	GSList *buddies;
 	PurpleBuddy *b;
 	PurpleConversation *conv;
 
+	account = purple_connection_get_account(gc);
+	buddies = purple_find_buddies(account, who);
+
 	while (buddies != NULL)
 	{
 		b = buddies->data;
 		buddies = g_slist_delete_link(buddies, buddies);
 
-		if ((b->server_alias == NULL && alias == NULL) ||
+		if((b->server_alias == NULL && alias == NULL) ||
 		    (b->server_alias && alias && !strcmp(b->server_alias, alias)))
 		{
 			continue;
@@ -229,7 +260,7 @@
 		purple_blist_server_alias_buddy(b, alias);
 
 		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, account);
-		if (conv != NULL && alias != NULL && strcmp(alias, who))
+		if(conv != NULL && alias != NULL && strcmp(alias, who))
 		{
 			char *tmp = g_strdup_printf(_("%s is now known as %s.\n"),
 										who, alias);
@@ -296,8 +327,8 @@
 	else
 		alias = who;
 
-	if (attn && attn->outgoing_description) {
-		description = g_strdup_printf(attn->outgoing_description, alias);
+	if (attn && purple_attention_type_get_outgoing_desc(attn)) {
+		description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias);
 	} else {
 		description = g_strdup_printf(_("Requesting %s's attention..."), alias);
 	}
@@ -341,8 +372,8 @@
 	else
 		alias = who;
 
-	if (attn && attn->incoming_description) {
-		description = g_strdup_printf(attn->incoming_description, alias);
+	if (attn && purple_attention_type_get_incoming_desc(attn)) {
+		description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias);
 	} else {
 		description = g_strdup_printf(_("%s has requested your attention!"), alias);
 	}
@@ -367,72 +398,101 @@
  */
 void serv_move_buddy(PurpleBuddy *b, PurpleGroup *og, PurpleGroup *ng)
 {
+	PurpleAccount *account = NULL;
+	PurpleConnection *gc = NULL;
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	g_return_if_fail(b != NULL);
 	g_return_if_fail(og != NULL);
 	g_return_if_fail(ng != NULL);
 
-	if (b->account->gc != NULL && b->account->gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(b->account->gc->prpl);
+	account = purple_buddy_get_account(b);
+	gc = purple_account_get_connection(account);
+
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (b->account->gc && og && ng) {
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(gc && og && ng) {
 		if (prpl_info && prpl_info->group_buddy) {
-			prpl_info->group_buddy(b->account->gc, b->name, og->name, ng->name);
+			prpl_info->group_buddy(gc, b->name, og->name, ng->name);
 		}
 	}
 }
 
-void serv_add_permit(PurpleConnection *g, const char *name)
+void serv_add_permit(PurpleConnection *gc, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->add_permit)
-		prpl_info->add_permit(g, name);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->add_permit)
+		prpl_info->add_permit(gc, name);
 }
 
-void serv_add_deny(PurpleConnection *g, const char *name)
+void serv_add_deny(PurpleConnection *gc, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->add_deny)
-		prpl_info->add_deny(g, name);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->add_deny)
+		prpl_info->add_deny(gc, name);
 }
 
-void serv_rem_permit(PurpleConnection *g, const char *name)
+void serv_rem_permit(PurpleConnection *gc, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->rem_permit)
-		prpl_info->rem_permit(g, name);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->rem_permit)
+		prpl_info->rem_permit(gc, name);
 }
 
-void serv_rem_deny(PurpleConnection *g, const char *name)
+void serv_rem_deny(PurpleConnection *gc, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->rem_deny)
-		prpl_info->rem_deny(g, name);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->rem_deny)
+		prpl_info->rem_deny(gc, name);
 }
 
-void serv_set_permit_deny(PurpleConnection *g)
+void serv_set_permit_deny(PurpleConnection *gc)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	/*
 	 * this is called when either you import a buddy list, and make lots
@@ -440,52 +500,64 @@
 	 * in the prefs. In either case you should probably be resetting and
 	 * resending the permit/deny info when you get this.
 	 */
-	if (prpl_info && prpl_info->set_permit_deny)
-		prpl_info->set_permit_deny(g);
+	if(prpl_info && prpl_info->set_permit_deny)
+		prpl_info->set_permit_deny(gc);
 }
 
-void serv_join_chat(PurpleConnection *g, GHashTable *data)
+void serv_join_chat(PurpleConnection *gc, GHashTable *data)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->join_chat)
-		prpl_info->join_chat(g, data);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->join_chat)
+		prpl_info->join_chat(gc, data);
 }
 
 
-void serv_reject_chat(PurpleConnection *g, GHashTable *data)
+void serv_reject_chat(PurpleConnection *gc, GHashTable *data)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->reject_chat)
-		prpl_info->reject_chat(g, data);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->reject_chat)
+		prpl_info->reject_chat(gc, data);
 }
 
-void serv_chat_invite(PurpleConnection *g, int id, const char *message, const char *name)
+void serv_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 	PurpleConversation *conv;
 	char *buffy = message && *message ? g_strdup(message) : NULL;
 
-	conv = purple_find_chat(g, id);
+	conv = purple_find_chat(gc, id);
 
-	if (conv == NULL)
+	if(conv == NULL)
 		return;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user",
 					 conv, name, &buffy);
 
 	if (prpl_info && prpl_info->chat_invite)
-		prpl_info->chat_invite(g, id, buffy, name);
+		prpl_info->chat_invite(gc, id, buffy, name);
 
 	purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user",
 					 conv, name, buffy);
@@ -499,37 +571,47 @@
  * to leave a chat without destroying the conversation.
  */
 
-void serv_chat_leave(PurpleConnection *g, int id)
+void serv_chat_leave(PurpleConnection *gc, int id)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->chat_leave)
-		prpl_info->chat_leave(g, id);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->chat_leave)
+		prpl_info->chat_leave(gc, id);
 }
 
-void serv_chat_whisper(PurpleConnection *g, int id, const char *who, const char *message)
+void serv_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (g != NULL && g->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(g->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->chat_whisper)
-		prpl_info->chat_whisper(g, id, who, message);
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->chat_whisper)
+		prpl_info->chat_whisper(gc, id, who, message);
 }
 
 int serv_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
 {
 	int val = -EINVAL;
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	prpl = purple_connection_get_prpl(gc);
 
-	if (prpl_info && prpl_info->chat_send)
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if(prpl_info && prpl_info->chat_send)
 		val = prpl_info->chat_send(gc, id, message, flags);
 
 	return val;
@@ -552,7 +634,7 @@
 
 	account  = purple_connection_get_account(gc);
 
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->set_permit_deny == NULL) {
+	if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->set_permit_deny == NULL) {
 		/* protocol does not support privacy, handle it ourselves */
 		if (!purple_privacy_check(account, who))
 			return;
@@ -772,7 +854,7 @@
 	int plugin_return;
 
 	account = purple_connection_get_account(gc);
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->set_permit_deny == NULL) {
+	if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->set_permit_deny == NULL) {
 		/* protocol does not support privacy, handle it ourselves */
 		if (!purple_privacy_check(account, who))
 			return;
@@ -920,10 +1002,14 @@
 
 void serv_send_file(PurpleConnection *gc, const char *who, const char *file)
 {
+	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	if (gc != NULL && gc->prpl != NULL)
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if(gc)
+		prpl = purple_connection_get_prpl(gc);
+
+	if(prpl)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if (prpl_info && prpl_info->send_file) {
 		if (!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, who)) {
--- a/libpurple/status.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/status.c	Mon Feb 04 04:04:02 2008 +0000
@@ -1310,7 +1310,8 @@
 	else if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_ACCOUNT)
 	{
 		PurpleAccount *account;
-		PurpleConnection *gc;
+		PurpleConnection *gc = NULL;
+		PurplePlugin *prpl = NULL;
 		PurplePluginProtocolInfo *prpl_info = NULL;
 
 		account = purple_presence_get_account(presence);
@@ -1339,9 +1340,11 @@
 
 		gc = purple_account_get_connection(account);
 
-		if (gc != NULL && PURPLE_CONNECTION_IS_CONNECTED(gc) &&
-				gc->prpl != NULL)
-			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		if(gc)
+			prpl = purple_connection_get_prpl(gc);
+
+		if(PURPLE_CONNECTION_IS_CONNECTED(gc) && prpl != NULL)
+			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		if (prpl_info && prpl_info->set_idle)
 			prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0));
--- a/libpurple/whiteboard.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/libpurple/whiteboard.c	Mon Feb 04 04:04:02 2008 +0000
@@ -59,7 +59,8 @@
 	wb->state   = state;
 	wb->who     = g_strdup(who);
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(
+				purple_account_get_connection(account)));
 	purple_whiteboard_set_prpl_ops(wb, prpl_info->whiteboard_prpl_ops);
 
 	/* Start up protocol specifics */
--- a/pidgin/gtkaccount.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/pidgin/gtkaccount.c	Mon Feb 04 04:04:02 2008 +0000
@@ -1833,7 +1833,8 @@
 							  purple_account_get_username(account));
 
 		purple_request_close_with_handle(account);
-		purple_request_action(account, NULL, buf, NULL, 0,
+		purple_request_action(account, NULL, buf, NULL,
+							PURPLE_DEFAULT_ACTION_NONE,
 							account, NULL, NULL,
 							account, 2,
 							_("Delete"), delete_account_cb,
--- a/pidgin/gtkcertmgr.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/pidgin/gtkcertmgr.c	Mon Feb 04 04:04:02 2008 +0000
@@ -84,10 +84,10 @@
 	GtkTreeView *listview = tpm_dat->listview;
 	PurpleCertificatePool *tls_peers;
 	GList *idlist, *l;
-	
+
 	GtkListStore *store = GTK_LIST_STORE(
 		gtk_tree_view_get_model(GTK_TREE_VIEW(listview)));
-	
+
 	/* First, delete everything in the list */
 	gtk_list_store_clear(store);
 
@@ -199,7 +199,7 @@
 				     NULL, NULL, NULL, /* No account/who/conv*/
 				     crt    /* Pass cert instance to callback*/
 				     );
-		
+
 		g_free(default_hostname);
 	} else {
 		/* Errors! Oh no! */
@@ -235,7 +235,7 @@
 	PurpleCertificate *crt = (PurpleCertificate *) data;
 
 	g_assert(filename);
-	
+
 	if (!purple_certificate_export(filename, crt)) {
 		/* Errors! Oh no! */
 		/* TODO: Perhaps find a way to be specific about what just
@@ -260,7 +260,7 @@
 	/* Pressing cancel just frees the duplicated certificate */
 	purple_certificate_destroy(crt);
 }
-	
+
 static void
 tls_peers_mgmt_export_cb(GtkWidget *button, gpointer data)
 {
@@ -293,7 +293,6 @@
 	}
 	g_free(id);
 
-	
 	/* TODO: inform user that it will be a PEM? */
 	purple_request_file(tpm_dat,
 			    _("PEM X.509 Certificate Export"),
@@ -327,10 +326,10 @@
 	/* Now retrieve the certificate */
 	crt = purple_certificate_pool_retrieve(tpm_dat->tls_peers, id);
 	g_return_if_fail(crt);
-	
+
 	/* Fire the notification */
 	purple_certificate_display_x509(crt);
-	
+
 	g_free(id);
 	purple_certificate_destroy(crt);
 }
@@ -350,7 +349,7 @@
 
 	g_free(id);
 }
-	
+
 static void
 tls_peers_mgmt_delete_cb(GtkWidget *button, gpointer data)
 {
@@ -370,17 +369,17 @@
 		/* Prompt to confirm deletion */
 		primary = g_strdup_printf(
 			_("Really delete certificate for %s?"), id );
-		
+
 		purple_request_yes_no(tpm_dat, _("Confirm certificate delete"),
 				      primary, NULL, /* Can this be NULL? */
-				      1, /* NO is default action */
+				      0, /* "yes" is the default action */
 				      NULL, NULL, NULL,
 				      id, /* id ownership passed to callback */
 				      tls_peers_mgmt_delete_confirm_cb,
 				      tls_peers_mgmt_delete_confirm_cb );
-		
+
 		g_free(primary);
-				      
+
 	} else {
 		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
 				     "Delete clicked with no selection?\n");
@@ -393,6 +392,7 @@
 {
 	GtkWidget *bbox;
 	GtkListStore *store;
+	GtkWidget *sw;
 
 	/* This block of variables will end up in tpm_dat */
 	GtkTreeView *listview;
@@ -406,10 +406,12 @@
 
 	/* Create a struct to store context information about this window */
 	tpm_dat = g_new0(tls_peers_mgmt_data, 1);
-	
+
 	tpm_dat->mgmt_widget = mgmt_widget =
 		gtk_hbox_new(FALSE, /* Non-homogeneous */
-			     PIDGIN_HIG_BORDER);
+			     PIDGIN_HIG_BOX_SPACE);
+	gtk_container_set_border_width(GTK_CONTAINER(mgmt_widget),
+		PIDGIN_HIG_BOX_SPACE);
 	gtk_widget_show(mgmt_widget);
 
 	/* Ensure that everything gets cleaned up when the dialog box
@@ -417,13 +419,23 @@
 	g_signal_connect(G_OBJECT(mgmt_widget), "destroy",
 			 G_CALLBACK(tls_peers_mgmt_destroy), NULL);
 
+	/* Scrolled window */
+	sw = gtk_scrolled_window_new(NULL,NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+			GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
+	gtk_box_pack_start(GTK_BOX(mgmt_widget), GTK_WIDGET(sw),
+			TRUE, TRUE, /* Take up lots of space */
+			0);
+	gtk_widget_show(GTK_WIDGET(sw));
+
 	/* List view */
 	store = gtk_list_store_new(TPM_N_COLUMNS, G_TYPE_STRING);
-	
+
 	tpm_dat->listview = listview =
 		GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
 	g_object_unref(G_OBJECT(store));
-	
+
 	{
 		GtkCellRenderer *renderer;
 		GtkTreeViewColumn *column;
@@ -440,11 +452,11 @@
 		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
 				TPM_HOSTNAME_COLUMN, GTK_SORT_ASCENDING);
 	}
-	
+
 	/* Get the treeview selector into the struct */
 	tpm_dat->listselect = select =
 		gtk_tree_view_get_selection(GTK_TREE_VIEW(listview));
-	
+
 	/* Force the selection mode */
 	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
 
@@ -452,20 +464,18 @@
 	   something is selected */
 	g_signal_connect(G_OBJECT(select), "changed",
 			 G_CALLBACK(tls_peers_mgmt_select_chg_cb), NULL);
-	
-	gtk_box_pack_start(GTK_BOX(mgmt_widget), GTK_WIDGET(listview),
-			   TRUE, TRUE, /* Take up lots of space */
-			   0); /* TODO: this padding is wrong */
+
+	gtk_container_add(GTK_CONTAINER(sw), GTK_WIDGET(listview));
 	gtk_widget_show(GTK_WIDGET(listview));
 
 	/* Fill the list for the first time */
 	tls_peers_mgmt_repopulate_list();
-	
+
 	/* Right-hand side controls box */
 	bbox = gtk_vbutton_box_new();
 	gtk_box_pack_end(GTK_BOX(mgmt_widget), bbox,
 			 FALSE, FALSE, /* Do not take up space */
-			 0); /* TODO: this padding is probably wrong */
+			 0);
 	gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE);
 	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
 	gtk_widget_show(bbox);
@@ -513,7 +523,7 @@
 
 	/* Bind us to the tls_peers pool */
 	tpm_dat->tls_peers = purple_certificate_find_pool("x509", "tls_peers");
-	
+
 	/**** libpurple signals ****/
 	/* Respond to certificate add/remove by just reloading everything */
 	purple_signal_connect(tpm_dat->tls_peers, "certificate-stored",
@@ -522,7 +532,7 @@
 	purple_signal_connect(tpm_dat->tls_peers, "certificate-deleted",
 			      tpm_dat, PURPLE_CALLBACK(tls_peers_mgmt_mod_cb),
 			      NULL);
-	
+
 	return mgmt_widget;
 }
 
@@ -571,7 +581,7 @@
 		      poollist = poollist->next ) {
 			PurpleCertificatePool *pool = poollist->data;
 			GList *l;
-			
+
 			purple_debug_info("gtkcertmgr",
 					  "Pool %s found for scheme %s -"
 					  "Enumerating certificates:\n",
@@ -588,7 +598,7 @@
 		} /* poollist */
 	}
 
-	
+
 	/* If the manager is already open, bring it to the front */
 	if (certmgr_dialog != NULL) {
 		gtk_window_present(GTK_WINDOW(certmgr_dialog->window));
@@ -607,7 +617,7 @@
 	g_signal_connect(G_OBJECT(win), "delete_event",
 			 G_CALLBACK(certmgr_close_cb), dlg);
 
-	
+
 	/* TODO: Retrieve the user-set window size and use it */
 	gtk_window_set_default_size(GTK_WINDOW(win), 400, 400);
 
--- a/pidgin/gtklog.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/pidgin/gtklog.c	Mon Feb 04 04:04:02 2008 +0000
@@ -242,8 +242,8 @@
 {
 	if (!purple_log_delete((PurpleLog *)data[2]))
 	{
-		purple_notify_error(NULL, NULL, "Log Deletion Failed",
-		                  "Check permissions and try again.");
+		purple_notify_error(NULL, NULL, _("Log Deletion Failed"),
+		                  _("Check permissions and try again."));
 	}
 	else
 	{
@@ -321,7 +321,7 @@
 	data2[0] = lv->treestore;
 	data2[1] = data[3]; /* iter */
 	data2[2] = log;
-	purple_request_action(lv, NULL, "Delete Log?", tmp, 0,
+	purple_request_action(lv, NULL, _("Delete Log?"), tmp, 0,
 						NULL, NULL, NULL,
 						data2, 2,
 						_("Delete"), delete_log_cb,
@@ -332,7 +332,7 @@
 static void log_show_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer *data)
 {
 	GtkWidget *menu = gtk_menu_new();
-	GtkWidget *menuitem = gtk_menu_item_new_with_label("Delete Log...");
+	GtkWidget *menuitem = gtk_menu_item_new_with_label(_("Delete Log..."));
 
 	if (!purple_log_is_deletable((PurpleLog *)data[1]))
 		gtk_widget_set_sensitive(menuitem, FALSE);
--- a/pidgin/gtkprivacy.c	Mon Feb 04 04:00:12 2008 +0000
+++ b/pidgin/gtkprivacy.c	Mon Feb 04 04:04:02 2008 +0000
@@ -44,7 +44,7 @@
 
 	GtkWidget *add_button;
 	GtkWidget *remove_button;
-	GtkWidget *clear_button;
+	GtkWidget *removeall_button;
 	GtkWidget *close_button;
 
 	GtkWidget *button_box;
@@ -117,23 +117,6 @@
 	}
 }
 
-static const char *
-find_permit_block_by_name(GSList *list, const char *name)
-{
-	const char *temp_name;
-	GSList *l;
-
-	for (l = list; l != NULL; l = l->next) {
-		temp_name = (const char *)l->data;
-
-		/* Should this use purple_normalize()? */
-		if (!purple_utf8_strcasecmp(name, temp_name))
-			return temp_name;
-	}
-
-	return NULL;
-}
-
 static void
 user_selected_cb(GtkTreeSelection *sel, PidginPrivacyDialog *dialog)
 {
@@ -317,19 +300,16 @@
 	else
 		return;
 
-	if (dialog->in_allow_list) {
-		if (find_permit_block_by_name(dialog->account->permit, name))
-			purple_privacy_permit_remove(dialog->account, name, FALSE);
-	}
-	else {
-		if (find_permit_block_by_name(dialog->account->deny, name))
-			purple_privacy_deny_remove(dialog->account, name, FALSE);
-	}
+	if (dialog->in_allow_list)
+		purple_privacy_permit_remove(dialog->account, name, FALSE);
+	else
+		purple_privacy_deny_remove(dialog->account, name, FALSE);
+
 	g_free(name);
 }
 
 static void
-clear_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
+removeall_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
 {
 	GSList *l;
 	if (dialog->in_allow_list)
@@ -420,7 +400,7 @@
 	dialog->block_widget = build_block_list(dialog);
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->block_widget, TRUE, TRUE, 0);
 
-	/* Add the button box for Add, Remove, Clear */
+	/* Add the button box for Add, Remove, Remove All */
 	dialog->button_box = pidgin_dialog_get_action_area(GTK_DIALOG(dialog->win));
 
 	/* Add button */
@@ -430,11 +410,12 @@
 	/* Remove button */
 	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_REMOVE, G_CALLBACK(remove_cb), dialog);
 	dialog->remove_button = button;
+	/* TODO: This button should be sensitive/invisitive more cleverly */
 	gtk_widget_set_sensitive(button, FALSE);
 
-	/* Clear button */
-	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_CLEAR, G_CALLBACK(clear_cb), dialog);
-	dialog->clear_button = button;
+	/* Remove All button */
+	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), _("Remove Al_l"), G_CALLBACK(removeall_cb), dialog);
+	dialog->removeall_button = button;
 
 	/* Close button */
 	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_CLOSE, G_CALLBACK(close_cb), dialog);
--- a/pidgin/pidgintooltip.h	Mon Feb 04 04:00:12 2008 +0000
+++ b/pidgin/pidgintooltip.h	Mon Feb 04 04:04:02 2008 +0000
@@ -88,7 +88,7 @@
  * @since 2.4.0
  */
 gboolean pidgin_tooltip_setup_for_widget(GtkWidget *widget, gpointer userdata,
-		PidginTooltipCreate create_tooltip, PidginTooltipPaint paint_tooltip);
+		PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb);
 
 /**
  * Destroy the tooltip.
--- a/po/POTFILES.in	Mon Feb 04 04:00:12 2008 +0000
+++ b/po/POTFILES.in	Mon Feb 04 04:04:02 2008 +0000
@@ -7,6 +7,7 @@
 finch/gntconv.c
 finch/gntdebug.c
 finch/gntft.c
+finch/gntlog.c
 finch/gntnotify.c
 finch/gntplugin.c
 finch/gntpounce.c