soc.2009.privacy_rewrite: ea0677a6: Privacy Rewrite: Skeleton of the new UI, ...

sulabh at soc.pidgin.im sulabh at soc.pidgin.im
Sat Aug 15 05:55:35 EDT 2009


-----------------------------------------------------------------
Revision: ea0677a62b2e666d44ad1ce0cdd907f47c690e7e
Ancestor: 50b516cef5bb79fe4037fdab812e896b9660a1e1
Author: sulabh at soc.pidgin.im
Date: 2009-08-15T09:47:38
Branch: im.pidgin.soc.2009.privacy_rewrite
URL: http://d.pidgin.im/viewmtn/revision/info/ea0677a62b2e666d44ad1ce0cdd907f47c690e7e

Modified files:
        libpurple/account.c libpurple/account.h libpurple/blist.c
        libpurple/blist.h libpurple/connection.c libpurple/core.c
        libpurple/plugins/psychic.c libpurple/privacy.c
        libpurple/privacy.h libpurple/protocols/yahoo/libyahoo.c
        libpurple/protocols/yahoo/libyahoojp.c
        libpurple/protocols/yahoo/libymsg.c
        libpurple/protocols/yahoo/libymsg.h
        libpurple/protocols/yahoo/yahoo_picture.c
        libpurple/protocols/yahoo/yahoochat.c libpurple/prpl.h
        libpurple/server.c libpurple/server.h pidgin/gtkblist.c
        pidgin/gtkconv.c pidgin/gtkprivacy.c

ChangeLog: 

Privacy Rewrite: Skeleton of the new UI, and most of the changes in the core.
Changes to yahoo!, to use new UI and core.

-------------- next part --------------
============================================================
--- libpurple/account.c	2715e52a80d216af9cc215046353cc8e244e8ace
+++ libpurple/account.c	e41173f291956baa1b041d5bfdb868d505f75177
@@ -985,8 +985,6 @@ purple_account_new(const char *username,
 	account->ui_settings = g_hash_table_new_full(g_str_hash, g_str_equal,
 				g_free, (GDestroyNotify)g_hash_table_destroy);
 	account->system_log = NULL;
-	/* 0 is not a valid privacy setting */
-	account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
 
 	purple_signal_emit(purple_accounts_get_handle(), "account-created", account);
 
@@ -999,6 +997,11 @@ purple_account_new(const char *username,
 	if (prpl_info != NULL && prpl_info->status_types != NULL)
 		purple_account_set_status_types(account, prpl_info->status_types(account));
 
+	if (prpl_info != NULL)	{
+		account->privacy_spec = g_new0(PurplePrivacySpec, 1);
+		account->privacy_spec = &prpl_info->privacy_spec;
+	}
+
 	account->presence = purple_presence_new_for_account(account);
 
 	status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
============================================================
--- libpurple/account.h	07f84856640894360f119b08eb20a59165b3bd57
+++ libpurple/account.h	078442c16af0f577679b257f01ffa77c7c33d942
@@ -131,7 +131,10 @@ struct _PurpleAccount
 	PurpleProxyInfo *proxy_info;  /**< Proxy information.  This will be set   */
 								/*   to NULL when the account inherits      */
 								/*   proxy settings from global prefs.      */
-	PurplePrivacyType perm_deny;  /**< The permit/deny setting.               */
+	PurplePrivacySpec *privacy_spec;
+	NativePrivacySetting native_privacy_state;		/* Current native privacy state of protocol */
+	PurplePrivacySetting account_privacy_state;	/* Current privacy state of account */
+	gboolean privacy_list_active;			/* Marks local privacy list active or inactive */
 
 	GList *status_types;        /**< Status types.                          */
 
============================================================
--- libpurple/blist.c	1e10ec8c7c0d3b6828574d535179934c42610bb5
+++ libpurple/blist.c	197cf0a5bff78cd5c482cd818aa68f6725cfdff1
@@ -187,14 +187,10 @@ buddy_to_xmlnode(PurpleBlistNode *bnode)
 	xmlnode_insert_data(child, buddy->name, -1);
 
 	child = xmlnode_new_child(node, "privacy");
-	grandchild = xmlnode_new_child(child, "receive_message");
-	xmlnode_set_attrib(grandchild, "type", "bool");
-	buf = g_strdup_printf("%d", buddy->privacy_receive_message);
+	grandchild = xmlnode_new_child(child, "context");
+	xmlnode_set_attrib(grandchild, "type", "int");
+	buf = g_strdup_printf("%d", buddy->privacy_block_context);
 	xmlnode_insert_data(grandchild, buf, -1);
-	grandchild = xmlnode_new_child(child, "send_presence");
-	xmlnode_set_attrib(grandchild, "type", "bool");
-	buf = g_strdup_printf("%d", buddy->privacy_send_presence);
-	xmlnode_insert_data(grandchild, buf, -1);
 	grandchild = xmlnode_new_child(child, "local_only");
 	xmlnode_set_attrib(grandchild, "type", "bool");
 	buf = g_strdup_printf("%d", buddy->local_only);
@@ -318,7 +314,7 @@ accountprivacy_to_xmlnode(PurpleAccount 
 	node = xmlnode_new("account");
 	xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account));
 	xmlnode_set_attrib(node, "name", purple_account_get_username(account));
-	g_snprintf(buf, sizeof(buf), "%d", account->perm_deny);
+	g_snprintf(buf, sizeof(buf), "%d", account->account_privacy_state);
 	xmlnode_set_attrib(node, "mode", buf);
 
 	return node;
@@ -330,6 +326,7 @@ blist_to_xmlnode(void)
 	xmlnode *node, *child, *grandchild;
 	PurpleBlistNode *gnode;
 	GList *cur;
+	char *buf;
 
 	node = xmlnode_new("purple");
 	xmlnode_set_attrib(node, "version", "1.0");
@@ -349,12 +346,20 @@ blist_to_xmlnode(void)
 
 	/* Write privacy settings */
 	child = xmlnode_new_child(node, "privacy");
+
+	grandchild = xmlnode_new_child(child, "global");
+	buf = g_strdup_printf("%d", purple_privacy_obtain_global_state());
+	xmlnode_set_attrib(grandchild, "state", buf);
+
+	grandchild = xmlnode_new_child(child, "per-account");
+	child = grandchild;
 	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
 	{
 		grandchild = accountprivacy_to_xmlnode(cur->data);
 		xmlnode_insert_child(child, grandchild);
 	}
 
+	g_free(buf);
 	return node;
 }
 
@@ -456,18 +461,12 @@ parse_buddy(PurpleGroup *group, PurpleCo
 
 	if ((x = xmlnode_get_child(bnode, "privacy")))
 	{
-		if ((y = xmlnode_get_child(x, "receive_message")))
+		if ((y = xmlnode_get_child(x, "context")))
 		{
 			temp = xmlnode_get_data(y);
-			buddy->privacy_receive_message = atoi(temp);
+			buddy->privacy_block_context = atoi(temp);
 			g_free(temp);
 		}
-		if ((y = xmlnode_get_child(x, "send_presence")))
-		{
-			temp = xmlnode_get_data(y);
-			buddy->privacy_send_presence = atoi(temp);
-			g_free(temp);
-		}
 		if ((y = xmlnode_get_child(x, "local_only")))
 		{
 			temp = xmlnode_get_data(y);
@@ -590,7 +589,7 @@ purple_blist_load()
 void
 purple_blist_load()
 {
-	xmlnode *purple, *blist, *privacy;
+	xmlnode *purple, *blist, *privacy, *privacy_global, *privacy_acc;
 
 	blist_loaded = TRUE;
 
@@ -610,27 +609,42 @@ purple_blist_load()
 
 	privacy = xmlnode_get_child(purple, "privacy");
 	if (privacy) {
-		xmlnode *anode;
-		for (anode = privacy->child; anode; anode = anode->next) {
-			PurpleAccount *account;
-			int imode;
-			const char *acct_name, *proto, *mode, *protocol;
+		privacy_global = xmlnode_get_child(privacy, "global");
+		if(privacy_global)
+		{
+			const char *global_setting;
+			int i_global_setting;
 
-			acct_name = xmlnode_get_attrib(anode, "name");
-			protocol = xmlnode_get_attrib(anode, "protocol");
-			proto = xmlnode_get_attrib(anode, "proto");
-			mode = xmlnode_get_attrib(anode, "mode");
+			global_setting = xmlnode_get_attrib(privacy_global, "state");
+			i_global_setting = ( atoi(global_setting) != 0 ? atoi(global_setting) : PURPLE_PRIVACY_ALLOW_BUDDYLIST ) ;
+			purple_privacy_set_global_state(i_global_setting);
+		}
 
-			if (!acct_name || (!proto && !protocol) || !mode)
-				continue;
+		privacy_acc = xmlnode_get_child(privacy, "per-account");
+		if(privacy_acc)
+		{
+			xmlnode *anode;
+			for (anode = privacy_acc->child; anode; anode = anode->next) {
+				PurpleAccount *account;
+				int imode;
+				const char *acct_name, *proto, *mode, *protocol;
 
-			account = purple_accounts_find(acct_name, proto ? proto : protocol);
+				acct_name = xmlnode_get_attrib(anode, "name");
+				protocol = xmlnode_get_attrib(anode, "protocol");
+				proto = xmlnode_get_attrib(anode, "proto");
+				mode = xmlnode_get_attrib(anode, "mode");
 
-			if (!account)
-				continue;
+				if (!acct_name || (!proto && !protocol) || !mode)
+					continue;
 
-			imode = atoi(mode);
-			account->perm_deny = (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL);
+				account = purple_accounts_find(acct_name, proto ? proto : protocol);
+
+				if (!account)
+					continue;
+
+				imode = atoi(mode);
+				account->account_privacy_state = (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL);
+			}
 		}
 	}
 
@@ -1333,10 +1347,8 @@ PurpleBuddy *purple_buddy_new(PurpleAcco
 
 	purple_blist_node_initialize_settings((PurpleBlistNode *)buddy);
 
-	/* set new buddy's privacy settings, later: check if buddy exists in some privacy list, set settings accordingly, also 
-		check what local/server settings needed */
-	buddy->privacy_receive_message = TRUE;
-	buddy->privacy_send_presence = TRUE;
+	/* Privacy Laters: Obtain new buddy's privacy context, and local settings */
+	buddy->privacy_block_context = 0;
 	buddy->local_only = FALSE;
 
 	if (ops && ops->new_node)
============================================================
--- libpurple/blist.h	ed04ba00b79a0f21b90b4c74a94112bf823644b8
+++ libpurple/blist.h	75b1a6aa85f6448b44299a047d469d878b953f67
@@ -144,8 +144,7 @@ struct _PurpleBuddy {
 	PurpleBuddyIcon *icon;                    /**< The buddy icon. */
 	PurpleAccount *account;					/**< the account this buddy belongs to */
 	PurplePresence *presence;
-	gboolean privacy_receive_message;		/**< Are messages from this contact allowed >**/
-	gboolean privacy_send_presence;		/**< Do we send presence to this contact >**/
+	PurplePrivacyContext privacy_block_context;	/**< What do we block from this buddy >**/
 	gboolean local_only;			/**< Specifies if this contact is on any of server's lists >**/
 };
 
============================================================
--- libpurple/connection.c	cd970c06856c25a8bc6fcf84ffc4508ea43eb7a6
+++ libpurple/connection.c	eb3c5f67485ba0f1beab3e031707afac0ba08eb5
@@ -380,7 +380,7 @@ purple_connection_set_state(PurpleConnec
 
 		purple_signal_emit(purple_connections_get_handle(), "signed-on", gc);
 
-		serv_set_permit_deny(gc);
+		serv_privacy_set_state(gc);
 
 		update_keepalive(gc, TRUE);
 	}
============================================================
--- libpurple/core.c	a0ee0ae07125dacdf124e1f5ee0d122e6b7b0915
+++ libpurple/core.c	ca6b2cadb7088294a06edb1f5d6d75641c31cdc9
@@ -162,10 +162,10 @@ purple_core_init(const char *ui)
 	purple_notify_init();
 	purple_certificate_init();
 	purple_conversations_init();
+	purple_privacy_init();
 	purple_blist_init();
 	purple_log_init();
 	purple_network_init();
-	purple_privacy_init();
 	purple_pounces_init();
 	purple_proxy_init();
 	purple_dnsquery_init();
@@ -224,6 +224,7 @@ purple_core_quit(void)
 	purple_smileys_uninit();
 	purple_idle_uninit();
 	purple_pounces_uninit();
+	purple_privacy_uninit();
 	purple_blist_uninit();
 	purple_ciphers_uninit();
 	purple_notify_uninit();
============================================================
--- libpurple/plugins/psychic.c	5634b4ed4220ee9fc7a24cd903dc5600aef4b694
+++ libpurple/plugins/psychic.c	1558decbddc07ea8759b6b3f8f062f951432f5ef
@@ -48,7 +48,7 @@ buddy_typing_cb(PurpleAccount *acct, con
     return;
   }
 
-  if(FALSE == purple_privacy_check(acct, name)) {
+  if(purple_privacy_check(acct, name, PURPLE_PRIVACY_BLOCK_MESSAGE)) {
     purple_debug_info("psychic", "user %s is blocked\n", name);
     return;
   }
============================================================
--- libpurple/privacy.c	b902a489ac9b9aeda01b07b2897f0b57a4124b36
+++ libpurple/privacy.c	ae797a5834ef9516f439da80020f367d14fe8cf3
@@ -24,525 +24,452 @@
 #include "account.h"
 #include "debug.h"
 #include "privacy.h"
+#include "savedstatuses.h"
 #include "server.h"
 #include "util.h"
 
+static int privacy_handle;
+
+static PurplePrivacySetting purple_privacy_state;
+
 static PurplePrivacyUiOps *privacy_ops = NULL;
 GSList *get_account_members(PurpleAccount *account, PurplePrivacyListType type);
+static void acc_signed_on_cb(PurpleConnection *gc, void *data);
+static void acc_signed_off_cb(PurpleConnection *gc, void *data);
 
-gboolean
-purple_privacy_permit_add(PurpleAccount *account, const char *who,
-						gboolean local_only)
+void
+purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops)
 {
-	PurpleBuddy *buddy = NULL;
-	char *name = NULL;
+	privacy_ops = ops;
+}
 
-	g_return_val_if_fail(account != NULL, FALSE);
-	g_return_val_if_fail(who     != NULL, FALSE);
+PurplePrivacyUiOps *
+purple_privacy_get_ui_ops(void)
+{
+	return privacy_ops;
+}
 
-	purple_debug_info("Privacy","In purple_privacy_permit_add\n"); /* remove me laters */
+void
+purple_privacy_init(void)
+{
+	/* Set default purple privacy state to PURPLE_PRIVACY_ALLOW_BUDDYLIST */
+	purple_privacy_state = PURPLE_PRIVACY_ALLOW_BUDDYLIST;
 
-	name = g_strdup(purple_normalize(account, who));
+	/* Register the purple event callbacks. */
+	purple_signal_connect(purple_connections_get_handle(), "signed-on",
+						purple_privacy_get_handle(), PURPLE_CALLBACK(acc_signed_on_cb), NULL);
+	purple_signal_connect(purple_connections_get_handle(), "signed-off",
+						purple_privacy_get_handle(), PURPLE_CALLBACK(acc_signed_off_cb), NULL);
+}
 
-	purple_privacy_update_contact(account, name, local_only, TRUE, TRUE);
-
-	if (!local_only && purple_account_is_connected(account))
-		serv_privacy_list_add(purple_account_get_connection(account), PURPLE_PRIVACY_ALLOW_LIST, name);
-
-	if (privacy_ops != NULL && privacy_ops->permit_added != NULL)
-		privacy_ops->permit_added(account, name);
-
-	/* privacy laters: Change signals later */
-	/* This lets the UI know a buddy has had its privacy setting changed */
-	buddy = purple_find_buddy(account, name);
-	if (buddy != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", buddy);
-	}
-	g_free(name);
-	return TRUE;
+void
+purple_privacy_uninit(void)
+{
+	purple_signals_disconnect_by_handle(purple_privacy_get_handle());
+	purple_signals_unregister_by_instance(purple_privacy_get_handle());
 }
 
-gboolean
-purple_privacy_permit_remove(PurpleAccount *account, const char *who,
-						   gboolean local_only)
+gboolean purple_privacy_set_blocking_context(PurpleAccount *account, const char *who, gboolean local_only, PurplePrivacyContext context)
 {
-	/* privacy laters: privacy settings after removing from the allow list would depend upon the account type and its privacy state.
-	For now, lets assume that if you are not in buddy list and have been removed from the allow list, you are "everyone else".
-	so there needs to be no information stored about you. If you are in buddy list then it depends on account type and state */
+	PurpleBuddy *b;
+	PurpleGroup *g;
+	char *name = NULL;
 
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
- 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	purple_debug_info("Privacy","In purple_privacy_permit_remove\n"); /* remove me laters */
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-	name = g_strdup(purple_normalize(account, who));
-
-	if(!(b = purple_find_buddy(account, name)))
+	if((b = purple_find_privacy_contact(account, name)))
 	{
-		if(!(b = purple_find_privacy_contact(account, name)))
-		{
-			g_free(name);
-			return FALSE;
-		}
-		else
-			purple_blist_remove_buddy(b);	/* when in allow list,  you are in no other privacy list */
+		b->privacy_block_context = context;
+		b->local_only = local_only;
 	}
 	else
 	{
-		/* privacy laters: This now depends upon the account type and state, for now set TRUE, TRUE */
-		purple_privacy_update_contact(account, name, local_only, TRUE, TRUE);
+		if(!(g = purple_find_group(PURPLE_PRIVACY_GROUP)))
+		{
+			g = purple_group_new(PURPLE_PRIVACY_GROUP);
+			purple_blist_add_group(g, NULL);
+		}
+
+		b = purple_buddy_new(account, name, NULL);
+		b->privacy_block_context = context;
+		b->local_only = local_only;
+		purple_blist_add_buddy(b, NULL, g, NULL);
 	}
 
-	/* privacy laters: we have freed the buddy, check if some function in following statements don't require any data that we freed */
+	g_free(name);
+	return TRUE;
+}
 
-	if (!local_only && purple_account_is_connected(account))
-		serv_privacy_list_remove(purple_account_get_connection(account), PURPLE_PRIVACY_ALLOW_LIST, name);
+PurplePrivacyContext purple_privacy_get_blocking_context(PurpleAccount *account, const char *who)
+{
+	PurpleBuddy *b;
+	char *name = NULL;
 
-	if (privacy_ops != NULL && privacy_ops->permit_removed != NULL)
-		privacy_ops->permit_removed(account, name);
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	b = purple_find_buddy(account, name);
-	if (b != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", b);
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if((b = purple_find_privacy_contact(account, name)))
+		return b->privacy_block_context;
+	else
+	{
+		if((b = purple_find_privacy_contact(account, "all-others")))
+			return b->privacy_block_context;
+		else
+			return 0;
 	}
-	g_free(name);
-	return TRUE;
 }
 
-gboolean
-purple_privacy_deny_add(PurpleAccount *account, const char *who,
-					  gboolean local_only)
+gboolean purple_privacy_set_block_all(PurpleAccount *account, const char *who, gboolean local, gboolean server)
 {
-	PurpleBuddy *buddy = NULL;
-	char *name = NULL;
+	char *name;
+	PurplePrivacyContext context;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	purple_debug_info("Privacy","In purple_privacy_deny_add\n"); /* remove me laters */
+	context = PURPLE_PRIVACY_BLOCK_ALL | PURPLE_PRIVACY_BLOCK_MESSAGE | PURPLE_PRIVACY_BLOCK_PRESENCE |
+			PURPLE_PRIVACY_BLOCK_FT | PURPLE_PRIVACY_BLOCK_CONF;
 
-	name = g_strdup(purple_normalize(account, who));
-	purple_privacy_update_contact(account, name, local_only, TRUE, TRUE);
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-	if (!local_only && purple_account_is_connected(account))
-		serv_privacy_list_add(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, name);
+	if(local)
+		purple_privacy_set_blocking_context(account, name, !server, context);
 
-	if (privacy_ops != NULL && privacy_ops->deny_added != NULL)
-		privacy_ops->deny_added(account, name);
+	if(server && purple_account_is_connected(account) && 
+				purple_privacy_check_list_support(account, PURPLE_PRIVACY_BLOCK_BOTH_LIST) &&
+				(!purple_strequal(name, "all-others")) )
+		serv_privacy_list_add(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, name);
 
-	/* privacy laters: Change signals later */
-	/* This lets the UI know a buddy has had its privacy setting changed */
-	buddy = purple_find_buddy(account, name);
-	if (buddy != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", buddy);
-	}
 	g_free(name);
 	return TRUE;
 }
 
-gboolean
-purple_privacy_deny_remove(PurpleAccount *account, const char *who,
-						 gboolean local_only)
+gboolean purple_privacy_set_block_presence(PurpleAccount *account, const char *who, gboolean local, gboolean server)
 {
-	/* privacy laters: privacy settings according to account type and state */
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
+	char *name;
+	PurplePrivacyContext context;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	purple_debug_info("Privacy","In purple_privacy_deny_remove\n"); /* remove me laters */
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-	name = g_strdup(purple_normalize(account, who));
-
-	if(!(b = purple_find_buddy(account, name)))
+	if(!purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE))
 	{
-		if(!(b = purple_find_privacy_contact(account, name)))
+		if(local)
 		{
-			g_free(name);
-			return FALSE;
+			context = ( purple_privacy_get_blocking_context(account, name) | PURPLE_PRIVACY_BLOCK_PRESENCE );
+			purple_privacy_set_blocking_context(account, name, !server, context);
 		}
-		else
-		{
-			/* privacy laters: you can be (in)visible list along with block list, will figure out how laters, for now remove 
-			this contact from list */
-			purple_blist_remove_buddy(b);
-		}
-	}
-	else
-	{
-		/* privacy laters: This now depends upon the account type and state, for now set TRUE, TRUE */
-		purple_privacy_update_contact(account, name, local_only, TRUE, TRUE);
-	}
 
-	/* privacy laters: we have freed the buddy, check if some function in following statements don't require any data that we freed */
-
-	if (!local_only && purple_account_is_connected(account))
-		serv_privacy_list_remove(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, name);
-
-	if (privacy_ops != NULL && privacy_ops->deny_removed != NULL)
-		privacy_ops->deny_removed(account, name);
-
-	b = purple_find_buddy(account, name);
-	if (b != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", b);
+		if(server && purple_account_is_connected(account) && purple_privacy_check_list_support(account, PURPLE_PRIVACY_INVISIBLE_LIST) )
+			serv_privacy_list_add(purple_account_get_connection(account), PURPLE_PRIVACY_INVISIBLE_LIST, name);
 	}
+
 	g_free(name);
 	return TRUE;
 }
 
-/**
- * This makes sure your permit list contains all buddies from your
- * buddy list and ONLY buddies from your buddy list.
- */
-static gboolean 
-add_all_buddies_to_permit_list(PurpleAccount *account, gboolean local)
+gboolean purple_privacy_set_block_message(PurpleAccount *account, const char *who)
 {
-	GSList *p_list = NULL, *l_tmp = NULL;
-	PurpleBuddy *b = NULL;
+	char *name;
+	PurplePrivacyContext context;
 
 	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	p_list = purple_find_privacy_contacts(account, NULL);
-	for(l_tmp = p_list; l_tmp; l_tmp = l_tmp->next)
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if(!purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE))
 	{
-		b = l_tmp->data;
-		if(purple_find_buddy(account, b->name))
-			purple_privacy_permit_add(account, b->name, local);
-		else
-			purple_privacy_permit_remove(account, b->name, local);
+		context = ( purple_privacy_get_blocking_context(account, name) | PURPLE_PRIVACY_BLOCK_MESSAGE );
+		purple_privacy_set_blocking_context(account, name, TRUE, context);
 	}
 
-	g_slist_free(p_list);
-	return TRUE; 
+	g_free(name);
+	return TRUE;
 }
 
-/*
- * 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)
+gboolean purple_privacy_set_block_ft(PurpleAccount *account, const char *who)
 {
-	GSList *list = NULL, *l_tmp = NULL;
-	PurplePrivacyType type = account->perm_deny;
-	PurpleBuddy *b = NULL;
+	char *name;
+	PurplePrivacyContext context;
 
-	switch (account->perm_deny) {
-		case PURPLE_PRIVACY_ALLOW_ALL:
-			return;
-		case PURPLE_PRIVACY_ALLOW_USERS:
-			purple_privacy_permit_add(account, who, local);
-			break;
-		case PURPLE_PRIVACY_DENY_USERS:
-			purple_privacy_deny_remove(account, who, local);
-			break;
-		case PURPLE_PRIVACY_DENY_ALL:
-			if (!restore) {
-				/* Empty the allow-list. */
-				list = purple_find_privacy_contacts(account, NULL);
-				for(l_tmp = list; l_tmp; l_tmp=l_tmp->next)
-				{
-					b = l_tmp->data;
-					purple_privacy_permit_remove(account, b->name, local);
-				}
-			}
-			purple_privacy_permit_add(account, who, local);
-			account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
-			break;
-		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-			if (!purple_find_buddy(account, who)) {
-				add_all_buddies_to_permit_list(account, local);
-				purple_privacy_permit_add(account, who, local);
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
-			}
-			break;
-		default:
-			g_return_if_reached();
-	}
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	g_slist_free(list);
-	/* Notify the server if the privacy setting was changed */
-	if (type != account->perm_deny && purple_account_is_connected(account))
-		serv_set_permit_deny(purple_account_get_connection(account));
-}
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-/*
- * 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)
-{
-	GSList *list = NULL, *l_tmp = NULL;
-	PurpleBuddy *b = NULL;
-	PurplePrivacyType type = account->perm_deny;
-
-	switch (account->perm_deny) {
-		case PURPLE_PRIVACY_ALLOW_ALL:
-			if (!restore) {
-				/* Empty the deny-list. */
-				list = purple_find_privacy_contacts(account, NULL);
-				for(l_tmp = list; l_tmp; l_tmp=l_tmp->next)
-				{
-					b = l_tmp->data;
-					purple_privacy_deny_remove(account, b->name, local);
-				}
-			}
-			purple_privacy_deny_add(account, who, local);
-			account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
-			break;
-		case PURPLE_PRIVACY_ALLOW_USERS:
-			purple_privacy_permit_remove(account, who, local);
-			break;
-		case PURPLE_PRIVACY_DENY_USERS:
-			purple_privacy_deny_add(account, who, local);
-			break;
-		case PURPLE_PRIVACY_DENY_ALL:
-			break;
-		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-			if (purple_find_buddy(account, who)) {
-				add_all_buddies_to_permit_list(account, local);
-				purple_privacy_permit_remove(account, who, local);
-				account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
-			}
-			break;
-		default:
-			g_return_if_reached();
+	if(!purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT))
+	{
+		context = ( purple_privacy_get_blocking_context(account, name) | PURPLE_PRIVACY_BLOCK_FT );
+		purple_privacy_set_blocking_context(account, name, TRUE, context);
 	}
 
-	g_slist_free(list);
-	/* Notify the server if the privacy setting was changed */
-	if (type != account->perm_deny && purple_account_is_connected(account))
-		serv_set_permit_deny(purple_account_get_connection(account));
+	g_free(name);
+	return TRUE;
 }
 
-gboolean
-purple_privacy_check_message(PurpleAccount *account, const char *who)
+gboolean purple_privacy_set_block_conf(PurpleAccount *account, const char *who)
 {
-	/* Privacy later: When functions that set privacy will work based on account types/states, then this function will work perfectly */
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
-	gboolean receive_message;
+	char *name;
+	PurplePrivacyContext context;
 
-	b = purple_find_privacy_contact(account, who);
-	name = 	g_strdup(purple_normalize(account, who));
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	if(b)
-		receive_message = b->privacy_receive_message;
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
 	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if(!purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF))
 	{
-		/* privacy later: depends upon account type/state, for now return false */
-		receive_message = FALSE;
+		context = ( purple_privacy_get_blocking_context(account, name) | PURPLE_PRIVACY_BLOCK_CONF );
+		purple_privacy_set_blocking_context(account, name, TRUE, context);
 	}
+
 	g_free(name);
-	return receive_message;
+	return TRUE;
 }
 
-gboolean
-purple_privacy_check_presence(PurpleAccount *account, const char *who)
+gboolean purple_privacy_unset_block_message(PurpleAccount *account, const char *who)
 {
-	/* Privacy later: When functions that set privacy will work based on account types/states, then this function will work perfectly */
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
-	gboolean send_presence;
+	char *name;
 
-	b = purple_find_privacy_contact(account, who);
-	name = 	g_strdup(purple_normalize(account, who));
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	if(b)
-		send_presence = b->privacy_send_presence;
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
 	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE))
 	{
-		/* privacy later: depends upon account type/state, for now return false */
-		send_presence = FALSE;
+		if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL))
+		{
+			purple_privacy_unset_block_all(account, name, TRUE, TRUE);
+			purple_privacy_set_block_presence(account, name, TRUE, TRUE);
+			purple_privacy_set_block_ft(account, name);
+			purple_privacy_set_block_conf(account, name);
+		}
+		else
+		{
+			PurplePrivacyContext context;
+			context = purple_privacy_get_blocking_context(account, name) & (~PURPLE_PRIVACY_BLOCK_MESSAGE);
+			purple_privacy_set_blocking_context(account, name, TRUE, context);
+		}
 	}
+
 	g_free(name);
-	return send_presence;
+	return TRUE;
 }
 
-gboolean
-purple_privacy_check(PurpleAccount *account, const char *who)
+gboolean purple_privacy_unset_block_conf(PurpleAccount *account, const char *who)
 {
-	return purple_privacy_check_message(account,who);
-}
+	char *name;
 
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-void
-purple_privacy_set_ui_ops(PurplePrivacyUiOps *ops)
-{
-	privacy_ops = ops;
-}
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-PurplePrivacyUiOps *
-purple_privacy_get_ui_ops(void)
-{
-	return privacy_ops;
-}
+	if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF))
+	{
+		if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL))
+		{
+			purple_privacy_unset_block_all(account, name, TRUE, TRUE);
+			purple_privacy_set_block_presence(account, name, TRUE, TRUE);
+			purple_privacy_set_block_ft(account, name);
+			purple_privacy_set_block_message(account, name);
+		}
+		else
+		{
+			PurplePrivacyContext context;
+			context = purple_privacy_get_blocking_context(account, name) & (~PURPLE_PRIVACY_BLOCK_CONF);
+			purple_privacy_set_blocking_context(account, name, TRUE, context);
+		}
+	}
 
-void
-purple_privacy_init(void)
-{
+	g_free(name);
+	return TRUE;
 }
 
-gboolean purple_privacy_update_contact(PurpleAccount *account, const char *who, gboolean local_only, gboolean receive_message, gboolean send_presence)
+gboolean purple_privacy_unset_block_ft(PurpleAccount *account, const char *who)
 {
-	PurpleBuddy *b;
-	PurpleGroup *g;
-	char *name = NULL;
+	char *name;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	name = g_strdup(purple_normalize(account, who));
-
-	if((b = purple_find_privacy_contact(account, name)))
-	{
-		b->privacy_receive_message = receive_message;
-		b->privacy_send_presence = send_presence;
-		b->local_only = local_only;
-	}
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
 	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT))
 	{
-		if(!(g = purple_find_group(PURPLE_PRIVACY_GROUP)))
+		if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL))
 		{
-			g = purple_group_new(PURPLE_PRIVACY_GROUP);
-			purple_blist_add_group(g, NULL);
+			purple_privacy_unset_block_all(account, name, TRUE, TRUE);
+			purple_privacy_set_block_presence(account, name, TRUE, TRUE);
+			purple_privacy_set_block_conf(account, name);
+			purple_privacy_set_block_message(account, name);
 		}
-
-		b = purple_buddy_new(account, name, NULL);
-		b->privacy_receive_message = receive_message;
-		b->privacy_send_presence = send_presence;
-		b->local_only = local_only;
-		purple_blist_add_buddy(b, NULL, g, NULL);
+		else
+		{
+			PurplePrivacyContext context;
+			context = purple_privacy_get_blocking_context(account, name) & (~PURPLE_PRIVACY_BLOCK_FT);
+			purple_privacy_set_blocking_context(account, name, TRUE, context);
+		}
 	}
 
 	g_free(name);
 	return TRUE;
+}
 
-	/* put the name in list on the server 
-	if (!local_only && purple_account_is_connected(account))
-		serv_add_deny(purple_account_get_connection(account), name); */
+gboolean purple_privacy_unset_block_all(PurpleAccount *account, const char *who, gboolean local, gboolean server)
+{
+	char *name;
 
-	/* notify UI that a user was denied
-	if (privacy_ops != NULL && privacy_ops->deny_added != NULL)
-		privacy_ops->deny_added(account, name); */
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(who     != NULL, FALSE);
 
-	/* emit signal
-	buddy = purple_find_buddy(account, name);
-	if (buddy != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", buddy);
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
+
+	if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL))
+	{
+		if(local)
+			purple_privacy_set_blocking_context(account, name, !server, 0);
+
+		if(server && purple_account_is_connected(account) && 
+				purple_privacy_check_list_support(account, PURPLE_PRIVACY_BLOCK_BOTH_LIST) &&
+					(!purple_strequal(who, "all-others")) )
+			serv_privacy_list_remove(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, name);
 	}
-	return TRUE; */
+
+	g_free(name);
+	return TRUE;
 }
 
-gboolean purple_privacy_update_presence_setting(PurpleAccount *account, const char *who, gboolean send_presence)
+gboolean purple_privacy_unset_block_presence(PurpleAccount *account, const char *who, gboolean local, gboolean server)
 {
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
+	char *name;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	name = g_strdup(purple_normalize(account, who));
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-	if((b = purple_find_privacy_contact(account, name)))
+	if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE))
 	{
-		b->privacy_send_presence = send_presence;
-		g_free(name);
-		return TRUE;
-	}
-	else
-	{
-		g_free(name);
-		return FALSE;
-	}
+		if(local)
+		{
+			if(purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL))
+			{
+				purple_privacy_unset_block_all(account, name, TRUE, TRUE);
+				purple_privacy_set_block_conf(account, name);
+				purple_privacy_set_block_message(account, name);
+				purple_privacy_set_block_ft(account, name);
+			}
+			else
+			{
+				PurplePrivacyContext context;
+				
+				context = ( purple_privacy_get_blocking_context(account, who) & (~PURPLE_PRIVACY_BLOCK_PRESENCE) );
+				purple_privacy_set_blocking_context(account, name, !server, context);
+			}
+		}
 
-	/* notify UI that a user was denied
-	if (privacy_ops != NULL && privacy_ops->deny_added != NULL)
-		privacy_ops->deny_added(account, name); */
+		if(server && purple_account_is_connected(account) && 
+				purple_privacy_check_list_support(account, PURPLE_PRIVACY_INVISIBLE_LIST) &&
+					(!purple_strequal(who, "all-others")) )
+			serv_privacy_list_remove(purple_account_get_connection(account), PURPLE_PRIVACY_INVISIBLE_LIST, name);
+	}
 
-	/* emit signal
-	buddy = purple_find_buddy(account, name);
-	if (buddy != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", buddy);
-	}*/
-
+	g_free(name);
+	return TRUE;
 }
 
-gboolean purple_privacy_update_message_setting(PurpleAccount *account, const char *who, gboolean receive_message)
+gboolean purple_privacy_check(PurpleAccount *account, const char *who, PurplePrivacyContext context)
 {
-	PurpleBuddy *b = NULL;
-	char *name = NULL;
+	char *name;
+	gboolean value;
 
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(who     != NULL, FALSE);
 
-	name = g_strdup(purple_normalize(account, who));
+	if(purple_strequal(who, "all-others"))
+		name = g_strdup(who);
+	else
+		name = g_strdup(purple_normalize(account, who));
 
-	if((b = purple_find_privacy_contact(account, name)))
-	{
-		b->privacy_receive_message = receive_message;
-		g_free(name);
-		return TRUE;
-	}
+	if((purple_privacy_get_blocking_context(account, name) & context) == context)
+		value = TRUE;
 	else
-	{
-		g_free(name);
-		return FALSE;
-	}
+		value = FALSE;
 
-	/* notify UI that a user was denied
-	if (privacy_ops != NULL && privacy_ops->deny_added != NULL)
-		privacy_ops->deny_added(account, name); */
+	g_free(name);
+	return value;
+}
+	
+gboolean purple_privacy_check_list_support(PurpleAccount *account, PurplePrivacyListType type)
+{
+	return ( (account->privacy_spec->supported_privacy_lists & type) == type ? TRUE : FALSE );
+}
 
-	/* emit signal
-	buddy = purple_find_buddy(account, name);
-	if (buddy != NULL) {
-		purple_signal_emit(purple_blist_get_handle(),
-                "buddy-privacy-changed", buddy);
-	}*/
-
-}
-		
 GSList *get_account_members(PurpleAccount *account, PurplePrivacyListType type)
 {
 	GSList *account_buddies = NULL, *list = NULL, *l_tmp = NULL;
 	PurpleBuddy *b = NULL;
-	gboolean receive_message = FALSE, send_presence = FALSE;
+	PurplePrivacyContext context = 0;
 
 	switch(type)
 	{
 		case PURPLE_PRIVACY_ALLOW_LIST:
-			receive_message = TRUE;
-			send_presence = TRUE;
+			context = 0;
 			break;
 		case PURPLE_PRIVACY_BLOCK_MESSAGE_LIST:
-			receive_message = FALSE;
-			send_presence = TRUE;
+			context = PURPLE_PRIVACY_BLOCK_MESSAGE;
 			break;
 		case PURPLE_PRIVACY_BLOCK_BOTH_LIST:
-			receive_message = FALSE;
-			send_presence = FALSE;
+			context = PURPLE_PRIVACY_BLOCK_ALL;
 			break;
 		case PURPLE_PRIVACY_INVISIBLE_LIST:
-			receive_message = TRUE;
-			send_presence = FALSE;
+			context = PURPLE_PRIVACY_BLOCK_PRESENCE;
 			break;
 		case PURPLE_PRIVACY_BUDDY_LIST:
 		case PURPLE_PRIVACY_VISIBLE_LIST:
@@ -554,7 +481,7 @@ GSList *get_account_members(PurpleAccoun
 	for(l_tmp = account_buddies; l_tmp ; l_tmp=l_tmp->next)
 	{
 		b = l_tmp->data;
-		if((b->privacy_receive_message == receive_message) && (b->privacy_send_presence == send_presence))
+		if( ((b->privacy_block_context & context) == context ) && (purple_strequal(b->name, "all-others") == FALSE) )
 			list = g_slist_prepend(list, b->name);
 	}
 
@@ -606,8 +533,7 @@ gboolean purple_privacy_sync_lists(Purpl
 					purple_blist_remove_buddy(b);
 	}
 
-	/* What if there was a non-buddy contact in some privacy list(s), but now you have added it in your buddy list */
-	/* remove contact from privacy group, if now its in the buddy list */
+	/* remove contact from privacy group, if now it is in the buddy list */
 	for(l_tmp = buddy_l; l_tmp != NULL; l_tmp = l_tmp->next)
 		if((b = purple_find_buddy_in_group(account, (const char *)l_tmp->data, purple_find_group(PURPLE_PRIVACY_GROUP))))
 			purple_blist_remove_buddy(b);
@@ -617,30 +543,309 @@ gboolean purple_privacy_sync_lists(Purpl
 	and send presence from buddies in case they don't exist on any other list */
 
 	for(l_tmp = buddy_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, TRUE, TRUE);
+		purple_privacy_unset_block_all(account, l_tmp->data, TRUE, FALSE);
 
 	for(l_tmp = allow_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, TRUE, TRUE);
+		purple_privacy_unset_block_all(account, l_tmp->data, TRUE, FALSE);
 
+	/* Privacy laters: this is not correct */
 	for(l_tmp = block_msg_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, FALSE, TRUE);
+		purple_privacy_set_block_message(account, l_tmp->data);
 
 	for(l_tmp = block_both_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, FALSE, FALSE);
+		purple_privacy_set_block_all(account, l_tmp->data, TRUE, FALSE);
 
-	/* Can't determine contact's message privacy setting by its presence on visible/invisible list alone. So we process these cases in the last, 		assuming message privacy setting has already been done or assumed to be willing to receive messages */
-	/* Create contact with TRUE, TRUE state first, before updating its presence according to visible/invisible list */
 	for(l_tmp = visible_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-	{		
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, TRUE, TRUE);
-		purple_privacy_update_presence_setting(account, l_tmp->data, TRUE);
-	}
+		purple_privacy_unset_block_presence(account, l_tmp->data, TRUE, FALSE);
+
 	for(l_tmp = invisible_l ; l_tmp != NULL; l_tmp = l_tmp->next)
-	{		
-		purple_privacy_update_contact(account, l_tmp->data, FALSE, TRUE, TRUE);
-		purple_privacy_update_presence_setting(account, l_tmp->data, FALSE);
-	}
+		purple_privacy_set_block_presence(account, l_tmp->data, TRUE, FALSE);
+
 	g_slist_free(p_contacts);
 
 	return TRUE;	
 }
+
+gboolean purple_privacy_account_supports_invisible_status(PurpleAccount *account)
+{
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	if (purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_INVISIBLE))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+gboolean purple_privacy_account_status_invisible(PurpleAccount *account)
+{
+	PurpleStatus *status;
+	PurpleStatusType *status_type;
+
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	status = purple_account_get_active_status(account);
+	status_type = purple_status_get_type(status);
+	
+	if(purple_status_type_get_primitive(status_type) == PURPLE_STATUS_INVISIBLE)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+gboolean purple_privacy_set_account_status_invisible(PurpleAccount *account)
+{
+	PurpleStatusType *status_type;
+
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	/* Check whether this account supports invisible status */
+	if ( !(status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_INVISIBLE)) )
+		return FALSE;
+
+	/* Enable the status type with primitive "PURPLE_STATUS_INVISIBLE" */
+	purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
+	
+	return TRUE;
+}
+
+static gboolean test_status(PurpleSavedStatus *saved_status)
+{
+	gboolean ret = FALSE;
+	PurpleStatusPrimitive prim;
+
+	g_return_val_if_fail(saved_status != NULL, FALSE);
+
+	prim = purple_savedstatus_get_type(saved_status);
+
+	switch(prim)
+	{
+		case PURPLE_STATUS_INVISIBLE:
+		case PURPLE_STATUS_OFFLINE:
+		case PURPLE_STATUS_UNSET:
+		case PURPLE_STATUS_NUM_PRIMITIVES: /* shouldn't have this value */
+			ret = FALSE;
+			break;
+		default:
+			ret = TRUE;
+			break;
+	}
+
+	return ret;
+}
+
+/* Privacy Laters: this next function isn't perfect just yet.
+Doesn't change status window status when current status is invisible and we change it to 
+visible from the privacy UI */
+gboolean purple_privacy_set_account_status_visible(PurpleAccount *account)
+{
+	PurpleSavedStatus *saved_status;
+
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	saved_status = purple_savedstatus_get_current();
+	if( test_status(saved_status) ) {
+		purple_savedstatus_activate_for_account(saved_status, account);
+		return TRUE;
+	}
+	else	{
+		/* Our current saved status is Invisible or not Online, check default status */
+		saved_status = purple_savedstatus_get_default();
+		if( test_status(saved_status) ) {
+			purple_savedstatus_activate_for_account(saved_status, account);
+			return TRUE;
+		}
+		else	{
+			/* Both current and default saved status are Invisible or not online, we choose "available" */
+			if( (saved_status = purple_savedstatus_find_transient_by_type_and_message(PURPLE_STATUS_AVAILABLE, NULL)) )
+				purple_savedstatus_activate_for_account(saved_status, account);
+			else
+				purple_account_set_status(account, "available", TRUE, NULL);
+
+			return TRUE;
+		}
+	}
+	/* Couldn't find any suitable status */
+	return FALSE;
+}
+
+PurplePrivacySetting purple_privacy_obtain_global_state(void)
+{
+	return purple_privacy_state;
+}
+
+PurplePrivacySetting purple_privacy_obtain_account_state(PurpleAccount *account)
+{
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	return account->account_privacy_state;
+}
+
+NativePrivacySetting purple_privacy_obtain_native_state(PurpleAccount *account)
+{
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	return account->native_privacy_state;
+}
+
+void *purple_privacy_get_handle(void)
+{
+	return &privacy_handle;
+}
+
+/* Checks for the existence of "all-others" meta contact, adds it to blist if not found */
+static void set_all_others_meta_contact(PurpleAccount *account)
+{
+	PurplePrivacyContext context;
+	PurplePrivacySetting state;
+
+	if(account == NULL)
+		return;
+
+	state = purple_privacy_obtain_account_state(account);
+
+	switch (state)
+	{
+		case PURPLE_PRIVACY_ALLOW_ALL:
+			context = 0;
+			break;
+		case PURPLE_PRIVACY_BLOCK_MSG_NONBUDDY:
+			context = PURPLE_PRIVACY_BLOCK_MESSAGE;
+			break;
+		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
+		case PURPLE_PRIVACY_CUSTOM:
+			context = PURPLE_PRIVACY_BLOCK_ALL | PURPLE_PRIVACY_BLOCK_MESSAGE | PURPLE_PRIVACY_BLOCK_PRESENCE |
+						PURPLE_PRIVACY_BLOCK_FT | PURPLE_PRIVACY_BLOCK_CONF;
+			break;
+	}
+
+	purple_privacy_set_blocking_context(account, "all-others", TRUE, context);
+}
+
+static void
+acc_signed_on_cb(PurpleConnection *gc, void *data)
+{
+	PurplePrivacySetting state;
+	PurpleAccount *account = purple_connection_get_account(gc);
+
+	state = account->account_privacy_state;
+
+	if( (account->native_privacy_state == PURPLE_PRIVACY_NATIVE_DENY_USERS) &&
+			(account->account_privacy_state == PURPLE_PRIVACY_ALLOW_ALL) )
+	{
+			if(purple_privacy_state != PURPLE_PRIVACY_ALLOW_ALL)
+				state = purple_privacy_state;
+			else
+				state = PURPLE_PRIVACY_CUSTOM;
+	}
+
+	purple_privacy_set_account_state(account, state);
+}
+
+static void autoset_global_state(void)
+{
+	GList *list = NULL, *l = NULL;
+	PurpleAccount *account;
+	PurplePrivacySetting state;
+
+	state = PURPLE_PRIVACY_ALLOW_BUDDYLIST;
+	list = purple_accounts_get_all_active();
+	if(list)
+	{
+		account = list->data;
+		state = purple_privacy_obtain_account_state(account);
+	}
+	for( l = list; l != NULL; l = l->next )
+	{
+		account = l->data;
+		if( state != purple_privacy_obtain_account_state(account) ) {
+			purple_privacy_state = PURPLE_PRIVACY_CUSTOM;
+			return;
+		}
+	}
+
+	purple_privacy_state = state;
+}
+
+static void acc_signed_off_cb(PurpleConnection *gc, void *data)
+{
+	autoset_global_state();
+}
+
+static void set_list_local(PurpleAccount *account, GSList *l, gboolean local)
+{
+	PurpleBuddy *b;
+
+	while( l != NULL)
+	{
+		b = purple_find_privacy_contact(account, (char *)l->data);
+		if(b)
+			b->local_only = local;
+
+		l = l->next;
+	}
+}
+
+void purple_privacy_set_account_state(PurpleAccount *account, PurplePrivacySetting state)
+{
+	GSList *list = NULL, *l = NULL;
+
+	if(state == account->account_privacy_state)
+		return;
+
+	account->account_privacy_state = state;
+	autoset_global_state();
+
+	if(state == PURPLE_PRIVACY_ALLOW_ALL)
+	{
+		if ( (list = purple_privacy_list_get_members_by_account(account, PURPLE_PRIVACY_BLOCK_BOTH_LIST)) )
+		{
+			/* We empty deny list on the server, set local list inactive so we have the list to retrieve laters */
+			for(l = list; l != NULL; l = l->next)
+				serv_privacy_list_remove(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, (char *)l->data);
+
+			set_list_local(account, list, TRUE);
+			account->privacy_list_active = FALSE;
+		}
+		g_slist_free(list);
+		account->native_privacy_state = PURPLE_PRIVACY_NATIVE_ALLOW_ALL;
+	}
+	else
+	{
+		/* Retrieve local deny list and sync with the server : in case privacy list is inactive */
+		if( !(account->privacy_list_active) )
+		{
+			if ( (list = purple_privacy_list_get_members_by_account(account, PURPLE_PRIVACY_BLOCK_BOTH_LIST)) )
+			{
+				for(l = list; l != NULL; l = l->next)
+					serv_privacy_list_add(purple_account_get_connection(account), PURPLE_PRIVACY_BLOCK_BOTH_LIST, (char *)l->data);
+
+				account->native_privacy_state = PURPLE_PRIVACY_NATIVE_DENY_USERS;
+			}
+			else
+				account->native_privacy_state = PURPLE_PRIVACY_NATIVE_ALLOW_ALL;
+				
+			g_slist_free(list);
+			set_list_local(account, list, FALSE);		
+			account->privacy_list_active = TRUE;
+		}
+	}
+	set_all_others_meta_contact(account);
+}
+
+void purple_privacy_set_global_state(PurplePrivacySetting state)
+{
+	GList *l = NULL, *list = NULL;
+	PurpleAccount *account;
+
+	list = purple_accounts_get_all_active();
+	
+	if(state != PURPLE_PRIVACY_CUSTOM)	{
+		for( l = list; l != NULL; l = l->next )	{
+			account = l->data;
+			purple_privacy_set_account_state(account, state);
+		}
+	}
+
+	g_list_free(list);
+}
+
============================================================
--- libpurple/privacy.h	92b25c7fcd317d01588b092c9fc494eb69aa237c
+++ libpurple/privacy.h	2fd8523426bacbfbeb81565e0a2c51f869b70ce7
@@ -33,25 +33,51 @@
 /**
  * Privacy data types.
  */
-typedef enum _PurplePrivacyType
+typedef enum _PurplePrivacySetting
 {
 	PURPLE_PRIVACY_ALLOW_ALL = 1,
-	PURPLE_PRIVACY_DENY_ALL,
-	PURPLE_PRIVACY_ALLOW_USERS,
-	PURPLE_PRIVACY_DENY_USERS,
-	PURPLE_PRIVACY_ALLOW_BUDDYLIST
-} PurplePrivacyType;
+	PURPLE_PRIVACY_BLOCK_MSG_NONBUDDY,
+	PURPLE_PRIVACY_ALLOW_BUDDYLIST,
+	PURPLE_PRIVACY_CUSTOM
+} PurplePrivacySetting;
 
+typedef enum _NativePrivacySetting
+{
+	PURPLE_PRIVACY_NATIVE_ALLOW_ALL = 0x0004,
+	PURPLE_PRIVACY_NATIVE_DENY_ALL = 0x0008,	/* Both messages and presence blocked, add extra states if for a protocol only messages blocked */
+	PURPLE_PRIVACY_NATIVE_ALLOW_USERS = 0x0010,
+	PURPLE_PRIVACY_NATIVE_DENY_USERS = 0x0020,	/* Both messages and presence blocked, add extra states if for a protocol only messages blocked */
+	PURPLE_PRIVACY_NATIVE_ALLOW_BUDDYLIST = 0x0040
+} NativePrivacySetting;
+
 typedef enum _PurplePrivacyListType
 {
-	PURPLE_PRIVACY_ALLOW_LIST = 1,
-	PURPLE_PRIVACY_BLOCK_MESSAGE_LIST,
-	PURPLE_PRIVACY_BLOCK_BOTH_LIST,
-	PURPLE_PRIVACY_VISIBLE_LIST,
-	PURPLE_PRIVACY_INVISIBLE_LIST,
-	PURPLE_PRIVACY_BUDDY_LIST
+	PURPLE_PRIVACY_ALLOW_LIST = 0x0004,
+	PURPLE_PRIVACY_BLOCK_MESSAGE_LIST = 0x0008,
+	PURPLE_PRIVACY_BLOCK_BOTH_LIST = 0x0010,
+	PURPLE_PRIVACY_VISIBLE_LIST = 0x0020,
+	PURPLE_PRIVACY_INVISIBLE_LIST = 0x0040,
+	PURPLE_PRIVACY_BUDDY_LIST = 0x0080
 } PurplePrivacyListType;
 
+typedef struct _PurpleAccountPrivacySpec
+{
+	NativePrivacySetting supported_privacy_states;	/* Stores the privacy states natively supported */
+	PurplePrivacyListType supported_privacy_lists;	/* Stores the privacy lists types natively supported */
+	gboolean visible_list_transient;	/* True for Yahoo visible lists, as these are lost across sessions/status changes */
+	gboolean invisible_to_all_supported;	/* whether invisible to all status is supported */
+	gboolean can_deny_buddy;		/* can a buddy be added to the deny list - FALSE for yahoo! */
+} PurplePrivacySpec;
+
+typedef enum _PurplePrivacyContext
+{
+	PURPLE_PRIVACY_BLOCK_ALL = 0x0004,
+	PURPLE_PRIVACY_BLOCK_MESSAGE = 0x0008,
+	PURPLE_PRIVACY_BLOCK_PRESENCE = 0x0010,
+	PURPLE_PRIVACY_BLOCK_FT = 0x0020,
+	PURPLE_PRIVACY_BLOCK_CONF = 0x0040
+} PurplePrivacyContext;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -72,115 +98,8 @@ typedef struct
 	void (*_purple_reserved4)(void);
 } PurplePrivacyUiOps;
 
-/**
- * Adds a user to the account's permit list.
- *
- * @param account    The account.
- * @param name       The name of the user to add to the list.
- * @param local_only If TRUE, only the local list is updated, and not
- *                   the server.
- *
- * @return TRUE if the user was added successfully, or @c FALSE otherwise.
- */
-gboolean purple_privacy_permit_add(PurpleAccount *account, const char *name,
-								 gboolean local_only);
 
 /**
- * Removes a user from the account's permit list.
- *
- * @param account    The account.
- * @param name       The name of the user to add to the list.
- * @param local_only If TRUE, only the local list is updated, and not
- *                   the server.
- *
- * @return TRUE if the user was removed successfully, or @c FALSE otherwise.
- */
-gboolean purple_privacy_permit_remove(PurpleAccount *account, const char *name,
-									gboolean local_only);
-
-/**
- * Adds a user to the account's deny list.
- *
- * @param account    The account.
- * @param name       The name of the user to add to the list.
- * @param local_only If TRUE, only the local list is updated, and not
- *                   the server.
- *
- * @return TRUE if the user was added successfully, or @c FALSE otherwise.
- */
-gboolean purple_privacy_deny_add(PurpleAccount *account, const char *name,
-							   gboolean local_only);
-
-/**
- * Removes a user from the account's deny list.
- *
- * @param account    The account.
- * @param name       The name of the user to add to the list.
- * @param local_only If TRUE, only the local list is updated, and not
- *                   the server.
- *
- * @return TRUE if the user was removed successfully, or @c FALSE otherwise.
- */
-gboolean purple_privacy_deny_remove(PurpleAccount *account, const char *name,
-								  gboolean local_only);
-
-/**
- * Allow a user to send messages. If current privacy setting for the account is:
- *		PURPLE_PRIVACY_ALLOW_USERS:	The user is added to the allow-list.
- *		PURPLE_PRIVACY_DENY_USERS	:	The user is removed from the deny-list.
- *		PURPLE_PRIVACY_ALLOW_ALL	:	No changes made.
- *		PURPLE_PRIVACY_DENY_ALL	:	The privacy setting is changed to
- *									PURPLE_PRIVACY_ALLOW_USERS and the user
- *									is added to the allow-list.
- *		PURPLE_PRIVACY_ALLOW_BUDDYLIST: No changes made if the user is already in
- *									the buddy-list. Otherwise the setting is
- *									changed to PURPLE_PRIVACY_ALLOW_USERS, all the
- *									buddies are added to the allow-list, and the
- *									user is also added to the allow-list.
- *
- * @param account	The account.
- * @param who		The name of the user.
- * @param local		Whether the change is local-only.
- * @param restore	Should the previous allow/deny list be restored if the
- *					privacy setting is changed.
- */
-void purple_privacy_allow(PurpleAccount *account, const char *who, gboolean local,
-						gboolean restore);
-
-/**
- * Block messages from a user. If current privacy setting for the account is:
- *		PURPLE_PRIVACY_ALLOW_USERS:	The user is removed from the allow-list.
- *		PURPLE_PRIVACY_DENY_USERS	:	The user is added to the deny-list.
- *		PURPLE_PRIVACY_DENY_ALL	:	No changes made.
- *		PURPLE_PRIVACY_ALLOW_ALL	:	The privacy setting is changed to
- *									PURPLE_PRIVACY_DENY_USERS and the user is
- *									added to the deny-list.
- *		PURPLE_PRIVACY_ALLOW_BUDDYLIST: If the user is not in the buddy-list,
- *									then no changes made. Otherwise, the setting
- *									is changed to PURPLE_PRIVACY_ALLOW_USERS, all
- *									the buddies are added to the allow-list, and
- *									this user is removed from the list.
- *
- * @param account	The account.
- * @param who		The name of the user.
- * @param local		Whether the change is local-only.
- * @param restore	Should the previous allow/deny list be restored if the
- *					privacy setting is changed.
- */
-void purple_privacy_deny(PurpleAccount *account, const char *who, gboolean local,
-						gboolean restore);
-
-/**
- * Check the privacy-setting for a user.
- *
- * @param account	The account.
- * @param who		The name of the user.
- *
- * @return @c FALSE if the specified account's privacy settings block the user or @c TRUE otherwise. The meaning of "block" relates to sending of messages.
- */
-gboolean purple_privacy_check(PurpleAccount *account, const char *who);
-
-/**
  * Sets the UI operations structure for the privacy subsystem.
  *
  * @param ops The UI operations structure.
@@ -199,28 +118,53 @@ void purple_privacy_init(void);
  */
 void purple_privacy_init(void);
 
-/* privacy laters: detailed description laters */
-/* Sets the privacy settings for a contact */
-gboolean purple_privacy_update_contact(PurpleAccount *account, const char *who, gboolean local_only, gboolean receive_message, gboolean send_presence);
-
 /* Returns account specific privacy lists */
 GSList *purple_privacy_list_get_members_by_account(PurpleAccount *account, PurplePrivacyListType type);
 
-/* Sets privacy setting for receiving messages, leaves presence setting untouched */
-gboolean purple_privacy_update_message_setting(PurpleAccount *account, const char *who, gboolean receive_message);
+/* called by prpls with all the privacy lists + buddy list. Synchronizes the local master list (blist) */
+gboolean purple_privacy_sync_lists(PurpleAccount *account, GSList *buddy_l, GSList *allow_l, GSList *block_msg_l, GSList *block_both_l, GSList *visible_l, GSList *invisible_l);
 
-/* Sets privacy setting for sending presence, leaves message setting untouched */
-gboolean purple_privacy_update_presence_setting(PurpleAccount *account, const char *who, gboolean send_presence);
+/* returns TRUE if account supports "Invisible" status, otherwise FALSE */ 
+gboolean purple_privacy_account_supports_invisible_status (PurpleAccount *account);
 
-/* called by prpls with all the privacy lists + buddy list. Synchronizes the local master list (blist) */
-gboolean purple_privacy_sync_lists(PurpleAccount *account, GSList *buddy_l, GSList *allow_l, GSList *block_msg_l, GSList *block_both_l, GSList *visible_l, GSList *invisible_l);
+/* returns TRUE if account's current status is "Invisible", otherwise FALSE */ 
+gboolean purple_privacy_account_status_invisible(PurpleAccount *account);
 
-/* returns if sending presence information is allowed to the contact "who" */
-gboolean purple_privacy_check_presence(PurpleAccount *account, const char *who);
+/* Sets account's status to "Invisible", returns TRUE if successful, "FALSE" if not */ 
+gboolean purple_privacy_set_account_status_invisible(PurpleAccount *account);
 
-/* returns if receiving messages from the contact "who" is allowed */
-gboolean purple_privacy_check_message(PurpleAccount *account, const char *who);
+/* Sets account's status visible , returns TRUE if successful, "FALSE" if not */
+/* Following order is used to test for a suitable visible status:
+	* Current active saved status
+	* Default saved status
+	* Available status
+*/
+gboolean purple_privacy_set_account_status_visible(PurpleAccount *account);
 
+/* Returns the gloabl privacy state */
+PurplePrivacySetting purple_privacy_obtain_global_state(void);
+PurplePrivacySetting purple_privacy_obtain_account_state(PurpleAccount *account);
+NativePrivacySetting purple_privacy_obtain_native_state(PurpleAccount *account);
+void purple_privacy_set_account_state(PurpleAccount *account, PurplePrivacySetting state);
+void purple_privacy_set_global_state(PurplePrivacySetting state);
+void *purple_privacy_get_handle(void);
+void purple_privacy_uninit(void);
+
+gboolean purple_privacy_set_blocking_context(PurpleAccount *account, const char *who, gboolean local_only, PurplePrivacyContext context);
+PurplePrivacyContext purple_privacy_get_blocking_context(PurpleAccount *account, const char *who);
+gboolean purple_privacy_set_block_all(PurpleAccount *account, const char *who, gboolean local, gboolean server);
+gboolean purple_privacy_set_block_presence(PurpleAccount *account, const char *who, gboolean local, gboolean server);
+gboolean purple_privacy_set_block_message(PurpleAccount *account, const char *who);
+gboolean purple_privacy_set_block_ft(PurpleAccount *account, const char *who);
+gboolean purple_privacy_set_block_conf(PurpleAccount *account, const char *who);
+gboolean purple_privacy_unset_block_message(PurpleAccount *account, const char *who);
+gboolean purple_privacy_unset_block_conf(PurpleAccount *account, const char *who);
+gboolean purple_privacy_unset_block_ft(PurpleAccount *account, const char *who);
+gboolean purple_privacy_unset_block_all(PurpleAccount *account, const char *who, gboolean local, gboolean server);
+gboolean purple_privacy_unset_block_presence(PurpleAccount *account, const char *who, gboolean local, gboolean server);
+gboolean purple_privacy_check(PurpleAccount *account, const char *who, PurplePrivacyContext context);
+gboolean purple_privacy_check_list_support(PurpleAccount *account, PurplePrivacyListType type);
+
 #ifdef __cplusplus
 }
 #endif
============================================================
--- libpurple/protocols/yahoo/libyahoo.c	7d5eb47090b8ab6796f627e19547962f2037b2d7
+++ libpurple/protocols/yahoo/libyahoo.c	38e4d9ad1ac4229e85efbd2c1004d2826d95ce47
@@ -198,6 +198,11 @@ static PurplePluginProtocolInfo prpl_inf
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
 	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+	{
+		PURPLE_PRIVACY_NATIVE_ALLOW_ALL | PURPLE_PRIVACY_NATIVE_DENY_USERS,
+		PURPLE_PRIVACY_BLOCK_BOTH_LIST | PURPLE_PRIVACY_VISIBLE_LIST | PURPLE_PRIVACY_INVISIBLE_LIST | PURPLE_PRIVACY_BUDDY_LIST,
+		TRUE, TRUE, FALSE
+	},
 	yahoo_list_icon,
 	yahoo_list_emblem,
 	yahoo_status_text,
@@ -221,7 +226,7 @@ static PurplePluginProtocolInfo prpl_inf
 	NULL, /* remove_buddies */
 	yahoo_privacy_list_add, /* add to privacy lists */
 	yahoo_privacy_list_remove, /* remove from privacy lists */
-	yahoo_set_permit_deny,
+	NULL,		/* Yahoo only allows "Block the following" state, so no change of state possible */
 	yahoo_c_join,
 	NULL, /* reject chat invite */
 	yahoo_get_chat_name,
============================================================
--- libpurple/protocols/yahoo/libyahoojp.c	ca2c2228364334d3af86160259d18f6d600c06a0
+++ libpurple/protocols/yahoo/libyahoojp.c	353cb90e6732f1f1c234f6cfb0ec35e607b98e5f
@@ -94,6 +94,11 @@ static PurplePluginProtocolInfo prpl_inf
 	NULL, /* user_splits */
 	NULL, /* protocol_options */
 	{"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+	{
+		PURPLE_PRIVACY_NATIVE_ALLOW_ALL | PURPLE_PRIVACY_NATIVE_DENY_USERS,
+		PURPLE_PRIVACY_BLOCK_BOTH_LIST | PURPLE_PRIVACY_VISIBLE_LIST | PURPLE_PRIVACY_INVISIBLE_LIST | PURPLE_PRIVACY_BUDDY_LIST,
+		TRUE, TRUE, FALSE
+	},
 	yahoo_list_icon,
 	yahoo_list_emblem,
 	yahoo_status_text,
@@ -117,7 +122,7 @@ static PurplePluginProtocolInfo prpl_inf
 	NULL, /* remove_buddies */
 	yahoo_privacy_list_add, /* add to privacy lists */
 	yahoo_privacy_list_remove, /* remove from privacy lists */
-	yahoo_set_permit_deny,
+	NULL,		/* Yahoo only allows "Block the following" state, so no change of state possible */
 	yahoo_c_join,
 	NULL, /* reject chat invite */
 	yahoo_get_chat_name,
============================================================
--- libpurple/protocols/yahoo/libymsg.c	d6f5013b1021c351bf4fc61ab9c238ce15129760
+++ libpurple/protocols/yahoo/libymsg.c	3b42e8e0275941d06bec1ee723071ba1a07e17b9
@@ -585,6 +585,15 @@ static void yahoo_process_list_15(Purple
 
 	g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
 
+	/* Provide the privacy subsystem with the lists on the server*/ 
+	purple_privacy_sync_lists(account, buddy_list, NULL, NULL, block_both_list, NULL, invisible_list);
+	purple_debug_info("yahoo","Privacy Lists synchronized\n");
+	/* Set native privacy state */
+	if(block_both_list != NULL)
+		account->native_privacy_state = PURPLE_PRIVACY_NATIVE_DENY_USERS;
+	else
+		account->native_privacy_state = PURPLE_PRIVACY_NATIVE_ALLOW_ALL;
+
 	/* Now that we have processed the buddy list, we can say yahoo has connected */
 	purple_connection_set_display_name(gc, purple_normalize(account, purple_account_get_username(account)));
 	purple_connection_set_state(gc, PURPLE_CONNECTED);
@@ -596,10 +605,6 @@ static void yahoo_process_list_15(Purple
 	yahoo_set_status(account, purple_account_get_active_status(account));
 	purple_debug_info("yahoo","Authentication: Connection established\n");
 
-	/* Provide the privacy subsystem with the lists on the server*/ 
-	purple_privacy_sync_lists(account, buddy_list, NULL, NULL, block_both_list, NULL, invisible_list);
-	purple_debug_info("yahoo","Privacy Lists synchronized\n");
-
 	g_slist_free(buddy_list);
 	g_slist_free(block_both_list);
 	g_slist_free(invisible_list);
@@ -717,7 +722,7 @@ static void yahoo_process_list(PurpleCon
 		for (bud = buddies; bud && *bud; bud++) {
 			/* The server is already ignoring the user */
 			got_serv_list = TRUE;
-			purple_privacy_deny_add(account, *bud, 1);
+			purple_privacy_set_block_all(account, *bud, TRUE, FALSE);
 		}
 		g_strfreev(buddies);
 
@@ -725,15 +730,6 @@ static void yahoo_process_list(PurpleCon
 		yd->tmp_serv_ilist = NULL;
 	}
 
-	if (got_serv_list &&
-		((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
-		(account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
-		(account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
-	{
-		account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
-		purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
-				account->username);
-	}
 
 	if (yd->tmp_serv_plist) {
 		buddies = g_strsplit(yd->tmp_serv_plist->str, ",", -1);
@@ -799,8 +795,7 @@ static void yahoo_process_notify(PurpleC
 		return;
 	}
 
-	if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
-		&& (purple_privacy_check(account, from)))
+	if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")))
 	{
 		if(msn) {
 			char *msn_from = g_strconcat("msn/", from, NULL);
@@ -997,7 +992,7 @@ static void yahoo_process_message(Purple
 		{
 			PurpleWhiteboard *wb;
 
-			if (!purple_privacy_check(account, im->from)) {
+			if (purple_privacy_check(account, im->from, PURPLE_PRIVACY_BLOCK_ALL)) {
 				purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from);
 				return;
 			}
@@ -1033,11 +1028,6 @@ static void yahoo_process_message(Purple
 			continue;
 		}
 
-		if (!purple_privacy_check(account, im->from)) {
-			purple_debug_info("yahoo", "Message from %s dropped.\n", im->from);
-			return;
-		}
-
 		/*
 		 * TODO: Is there anything else we should check when determining whether
 		 *       we should send an acknowledgement?
@@ -1336,7 +1326,7 @@ static void yahoo_buddy_auth_req_15(Purp
 		if (add_req->id && add_req->who) {
 			char *alias = NULL, *dec_msg = NULL;
 
-			if (!purple_privacy_check(account, add_req->who))
+			if (purple_privacy_check(account, add_req->who, PURPLE_PRIVACY_BLOCK_ALL))
 			{
 				purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
 						  add_req->who);
@@ -1409,7 +1399,7 @@ static void yahoo_buddy_added_us(PurpleC
 	if (add_req->id && add_req->who) {
 		char *dec_msg = NULL;
 
-		if (!purple_privacy_check(account, add_req->who)) {
+		if (purple_privacy_check(account, add_req->who, PURPLE_PRIVACY_BLOCK_ALL)) {
 			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);
@@ -1970,8 +1960,7 @@ static void keep_buddy(PurpleBuddy *b)
 
 static void keep_buddy(PurpleBuddy *b)
 {
-	purple_privacy_deny_remove(purple_buddy_get_account(b),
-			purple_buddy_get_name(b), 1);
+	purple_privacy_unset_block_all(purple_buddy_get_account(b), purple_buddy_get_name(b), TRUE, FALSE);
 }
 
 static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt) {
@@ -2771,7 +2760,7 @@ static void yahoo_process_audible(Purple
 		purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
 		return;
 	}
-	if (!purple_privacy_check(account, who)) {
+	if (purple_privacy_check(account, who, PURPLE_PRIVACY_BLOCK_ALL)) {
 		purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n",
 				purple_account_get_username(account), who);
 		return;
@@ -4626,7 +4615,7 @@ void yahoo_add_buddy(PurpleConnection *g
 		return;
 
 	bname = purple_buddy_get_name(buddy);
-	if (!purple_privacy_check(purple_connection_get_account(gc), bname))
+	if (purple_privacy_check(purple_connection_get_account(gc), bname, PURPLE_PRIVACY_BLOCK_ALL))
 		return;
 
 	f = yahoo_friend_find(gc, bname);
@@ -4756,6 +4745,46 @@ static void yahoo_rem_deny(PurpleConnect
 	yahoo_packet_send_and_free(pkt, yd);
 }
 
+/* set = TRUE for setting perm invisible, FALSE to unset perm invisible */
+static void set_perm_invisible(PurpleConnection *gc, const char *who, gboolean set)
+{	
+	struct yahoo_data *yd = gc->proto_data;
+	struct yahoo_packet *pkt = NULL;
+	gboolean msn;
+	const char *temp = NULL;
+	int val_31;
+
+	if (!yd->logged_in)
+		return;
+
+	msn = !g_strncasecmp(who, "msn/", 4);
+
+	if(msn)
+		temp = who+4;
+	else
+		temp = who;
+
+	pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_SESSION, YAHOO_STATUS_AVAILABLE, yd->session_id);
+
+	val_31 = (set ? 1 : 2);
+
+	if(msn)
+		yahoo_packet_hash(pkt, "sissssiss",
+					1, purple_connection_get_display_name(gc),
+					31, val_31, 13, "1",
+					302, "319", 300, "319",
+					7, temp, 241, 2,
+					301, "319", 303, "319");
+	else
+		yahoo_packet_hash(pkt, "sissssss",
+					1, purple_connection_get_display_name(gc),
+					31, val_31, 13, "1",
+					302, "319", 300, "319",
+					7, temp, 301, "319", 303, "319");
+
+	yahoo_packet_send_and_free(pkt, yd);
+}
+
 void yahoo_privacy_list_add(PurpleConnection *gc, PurplePrivacyListType list_type, const char *who)
 {
 	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
@@ -4781,8 +4810,7 @@ void yahoo_privacy_list_add(PurpleConnec
 			yahoo_friend_update_presence(gc, who, YAHOO_PRESENCE_ONLINE);
 			break;
 		case PURPLE_PRIVACY_INVISIBLE_LIST:
-			/* Privacy laters: check */
-			yahoo_friend_update_presence(gc, who, YAHOO_PRESENCE_PERM_OFFLINE);
+			set_perm_invisible(gc, who, TRUE);
 			break;
 	}
 	return;
@@ -4813,39 +4841,12 @@ void yahoo_privacy_list_remove(PurpleCon
 			yahoo_friend_update_presence(gc, who, YAHOO_PRESENCE_PERM_OFFLINE);
 			break;
 		case PURPLE_PRIVACY_INVISIBLE_LIST:
-			/* Privacy laters */
-			yahoo_friend_update_presence(gc, who, YAHOO_PRESENCE_ONLINE);
+			set_perm_invisible(gc, who, FALSE);
 			break;
 	}
 	return;
 }
 
-void yahoo_set_permit_deny(PurpleConnection *gc)
-{
-	PurpleAccount *account;
-	GSList *deny = NULL, *l = NULL;
-
-	account = purple_connection_get_account(gc);
-	deny = purple_privacy_list_get_members_by_account(account, PURPLE_PRIVACY_BLOCK_BOTH_LIST);
-
-	switch (account->perm_deny)
-	{
-		case PURPLE_PRIVACY_ALLOW_ALL:
-			for (l = deny; l; l = l->next)
-				yahoo_rem_deny(gc, l->data);
-			break;
-
-		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-		case PURPLE_PRIVACY_ALLOW_USERS:
-		case PURPLE_PRIVACY_DENY_USERS:
-		case PURPLE_PRIVACY_DENY_ALL:
-			for (l = deny; l; l = l->next)
-				yahoo_add_deny(gc, l->data);
-			break;
-	}
-	g_slist_free(deny);
-}
-
 void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
 				   const char *old_group, const char *new_group)
 {
============================================================
--- libpurple/protocols/yahoo/libymsg.h	92bfed9fe4c186b0d0dfaf728b3f499545764424
+++ libpurple/protocols/yahoo/libymsg.h	e308e4ef47ffc3d7139bb4c39083307b5b70cda1
@@ -313,7 +313,6 @@ void yahoo_privacy_list_remove(PurpleCon
 void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
 void yahoo_privacy_list_add(PurpleConnection *gc, PurplePrivacyListType list_type, const char *who);
 void yahoo_privacy_list_remove(PurpleConnection *gc, PurplePrivacyListType list_type, const char *who);
-void yahoo_set_permit_deny(PurpleConnection *gc);
 void yahoo_keepalive(PurpleConnection *gc);
 void yahoo_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group);
 void yahoo_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
============================================================
--- libpurple/protocols/yahoo/yahoo_picture.c	4edc0fb63a3a5e3461e078e63135888c8b17dabe
+++ libpurple/protocols/yahoo/yahoo_picture.c	fc174ad891be7831a407e343b43a0f7288b7808a
@@ -113,7 +113,7 @@ void yahoo_process_picture(PurpleConnect
 	if (!who)
 		return;
 
-	if (!purple_privacy_check(purple_connection_get_account(gc), who)) {
+	if (purple_privacy_check(purple_connection_get_account(gc), who, PURPLE_PRIVACY_BLOCK_ALL)) {
 		purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who);
 		return;
 	}
============================================================
--- libpurple/protocols/yahoo/yahoochat.c	d06d3bdd5cdbc2cfd5c2094976470e306981326f
+++ libpurple/protocols/yahoo/yahoochat.c	3645a4e914893a73f24aca037ca3a615a92728cc
@@ -162,17 +162,6 @@ void yahoo_process_conference_invite(Pur
 		return;
 	}
 
-	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);
-		g_free(msg);
-		g_string_free(members, TRUE);
-		return;
-	}
-
 	components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 	g_hash_table_replace(components, g_strdup("room"), room);
 	if (msg)
@@ -207,12 +196,6 @@ void yahoo_process_conference_decline(Pu
 			break;
 		}
 	}
-	if (!purple_privacy_check(purple_connection_get_account(gc), who))
-	{
-		g_free(room);
-		g_free(msg);
-		return;
-	}
 
 	if (who && room) {
 		/* make sure we're in the room before we process a decline message for it */
@@ -707,8 +690,7 @@ void yahoo_process_chat_addinvite(Purple
 	if (room && who) {
 		GHashTable *components;
 
-		if (!purple_privacy_check(account, who) ||
-				(purple_account_get_bool(account, "ignore_invites", FALSE)))
+		if (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);
============================================================
--- libpurple/prpl.h	3a11c5a9da26c3c23f56353dd0f6d6cbcf62d1f8
+++ libpurple/prpl.h	2a1dc722ba40c5e251e274d8339ce810796b1437
@@ -212,6 +212,7 @@ struct _PurplePluginProtocolInfo
 	GList *protocol_options; /**< A GList of PurpleAccountOption    */
 
 	PurpleBuddyIconSpec icon_spec; /**< The icon spec. */
+	PurplePrivacySpec privacy_spec;
 
 	/**
 	 * Returns the base icon name for the given buddy and account.
@@ -312,7 +313,7 @@ struct _PurplePluginProtocolInfo
 	void (*remove_buddies)(PurpleConnection *, GList *buddies, GList *groups);
 	void (*privacy_list_add)(PurpleConnection *, PurplePrivacyListType list_type, const char *name);
 	void (*privacy_list_remove)(PurpleConnection *, PurplePrivacyListType list_type, const char *name);
-	void (*set_permit_deny)(PurpleConnection *);
+	void (*privacy_set_state)(PurpleConnection *);
 	void (*join_chat)(PurpleConnection *, GHashTable *components);
 	void (*reject_chat)(PurpleConnection *, GHashTable *components);
 	char *(*get_chat_name)(GHashTable *components);
============================================================
--- libpurple/server.c	c7a028a6f930d1a92a6f714fcf41c30cfb7ce73f
+++ libpurple/server.c	5957af004443dfdf9a161c5905e322dd036ebda8
@@ -216,7 +216,7 @@ void serv_alias_buddy(PurpleBuddy *b)
 	PurpleConnection *gc = NULL;
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
-
+purple_debug_info("yahoo","in serv_alias_buddy\n");
 	if(b)
 		account = purple_buddy_get_account(b);
 
@@ -230,6 +230,7 @@ void serv_alias_buddy(PurpleBuddy *b)
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 	if(b && prpl_info && prpl_info->alias_buddy) {
+purple_debug_info("yahoo","in serv_alias_buddy: calling yahoo's prpl fucntion\n");
 		prpl_info->alias_buddy(gc, purple_buddy_get_name(b), purple_buddy_get_local_buddy_alias(b));
 	}
 }
@@ -336,7 +337,10 @@ serv_got_attention(PurpleConnection *gc,
 void
 serv_got_attention(PurpleConnection *gc, const char *who, guint type_code)
 {
-	purple_prpl_got_attention(gc, who, type_code);
+	if(purple_privacy_check(purple_connection_get_account(gc), who, PURPLE_PRIVACY_BLOCK_MESSAGE))
+		purple_debug_info("server","Privacy: Dropped attention from %s\n", who);
+	else
+		purple_prpl_got_attention(gc, who, type_code);
 }
 
 
@@ -406,7 +410,7 @@ void serv_privacy_list_remove(PurpleConn
 		prpl_info->privacy_list_remove(gc, list_type, name);
 }
 
-void serv_set_permit_deny(PurpleConnection *gc)
+void serv_privacy_set_state(PurpleConnection *gc)
 {
 	PurplePlugin *prpl = NULL;
 	PurplePluginProtocolInfo *prpl_info = NULL;
@@ -417,14 +421,8 @@ void serv_set_permit_deny(PurpleConnecti
 	if(prpl)
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-	/*
-	 * this is called when either you import a buddy list, and make lots
-	 * of changes that way, or when the user toggles the permit/deny mode
-	 * 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(gc);
+	if(prpl_info && prpl_info->privacy_set_state)
+		prpl_info->privacy_set_state(gc);
 }
 
 void serv_join_chat(PurpleConnection *gc, GHashTable *data)
@@ -562,13 +560,10 @@ void serv_got_im(PurpleConnection *gc, c
 	 */
 	flags |= PURPLE_MESSAGE_RECV;
 
-	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)) {
-			purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
-					account, who, msg, flags, (unsigned int)mtime);
-			return;
-		}
+	if(purple_privacy_check(purple_connection_get_account(gc), who, PURPLE_PRIVACY_BLOCK_MESSAGE))
+	{
+		purple_debug_info("server","Privacy: Dropped message from %s\n", who);
+		return ;
 	}
 
 	/*
@@ -693,6 +688,12 @@ void serv_got_typing(PurpleConnection *g
 	PurpleConversation *conv;
 	PurpleConvIm *im = NULL;
 
+	if(purple_privacy_check(purple_connection_get_account(gc), name, PURPLE_PRIVACY_BLOCK_MESSAGE))
+	{
+		purple_debug_info("server","Privacy: Dropped typing.. from %s\n", name);
+		return ;
+	}
+
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
 	if (conv != NULL) {
 		im = PURPLE_CONV_IM(conv);
@@ -725,6 +726,9 @@ void serv_got_typing_stopped(PurpleConne
 	PurpleConversation *conv;
 	PurpleConvIm *im;
 
+	if(purple_privacy_check(purple_connection_get_account(gc), name, PURPLE_PRIVACY_BLOCK_MESSAGE))
+		return ;
+
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account);
 	if (conv != NULL)
 	{
@@ -780,13 +784,11 @@ void serv_got_chat_invite(PurpleConnecti
 	int plugin_return;
 
 	account = purple_connection_get_account(gc);
-	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)) {
-			purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
-					account, who, name, message, data);
-			return;
-		}
+
+	if(purple_privacy_check(purple_connection_get_account(gc), who, PURPLE_PRIVACY_BLOCK_CONF))
+	{
+		purple_debug_info("server","Privacy: Dropped chat invite to room %s from %s\n", name, who);
+		return ;
 	}
 
 	cid = g_new0(struct chat_invite_data, 1);
============================================================
--- libpurple/server.h	fa39833fc949b4c69cfc1a448577d9de6ebf9e65
+++ libpurple/server.h	aaab969ed4ef4eff5296a7a13247069e12e592ca
@@ -93,7 +93,7 @@ void serv_privacy_list_remove(PurpleConn
 
 void serv_privacy_list_add(PurpleConnection *, PurplePrivacyListType list_type, const char *name);
 void serv_privacy_list_remove(PurpleConnection *, PurplePrivacyListType list_type, const char *name);
-void serv_set_permit_deny(PurpleConnection *);
+void serv_privacy_set_state(PurpleConnection *);
 void serv_chat_invite(PurpleConnection *, int, const char *, const char *);
 void serv_chat_leave(PurpleConnection *, int);
 void serv_chat_whisper(PurpleConnection *, int, const char *, const char *);
============================================================
--- pidgin/gtkblist.c	f706621cd719e61ee9f1d8ff0080135a29508a73
+++ pidgin/gtkblist.c	860155592d0085d8eb44f8737ddbe09f0a5d5472
@@ -1416,14 +1416,14 @@ toggle_privacy(GtkWidget *widget, Purple
 	account = purple_buddy_get_account(buddy);
 	name = purple_buddy_get_name(buddy);
 
-	permitted = purple_privacy_check(account, name);
+	permitted = !purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL);
 
 	/* XXX: Perhaps ask whether to restore the previous lists where appropirate? */
 
 	if (permitted)
-		purple_privacy_deny(account, name, FALSE, FALSE);
+		purple_privacy_set_block_all(account, name, TRUE, TRUE);
 	else
-		purple_privacy_allow(account, name, FALSE, FALSE);
+		purple_privacy_unset_block_all(account, name, TRUE, TRUE);
 
 	pidgin_blist_update(purple_get_blist(), node);
 }
@@ -1435,7 +1435,7 @@ void pidgin_append_blist_node_privacy_me
 	gboolean permitted;
 
 	account = purple_buddy_get_account(buddy);
-	permitted = purple_privacy_check(account, purple_buddy_get_name(buddy));
+	permitted = !purple_privacy_check(account, purple_buddy_get_name(buddy), PURPLE_PRIVACY_BLOCK_ALL);
 
 	pidgin_new_item_from_stock(menu, permitted ? _("_Block") : _("Un_block"),
 						permitted ? PIDGIN_STOCK_TOOLBAR_BLOCK : PIDGIN_STOCK_TOOLBAR_UNBLOCK, G_CALLBACK(toggle_privacy),
@@ -3826,7 +3826,7 @@ pidgin_blist_get_emblem(PurpleBlistNode 
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 
-	if (!purple_privacy_check(buddy->account, purple_buddy_get_name(buddy))) {
+	if (purple_privacy_check(buddy->account, purple_buddy_get_name(buddy), PURPLE_PRIVACY_BLOCK_ALL)) {
 		path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL);
 		return _pidgin_blist_get_cached_emblem(path);
 	}
============================================================
--- pidgin/gtkconv.c	f6508421e7282993dd2e543bf571bc3c428e602f
+++ pidgin/gtkconv.c	9e306d16695e5f28576a2836e58ad01a31f0f819
@@ -6402,7 +6402,7 @@ gray_stuff_out(PidginConversation *gtkco
 		gtk_widget_show(win->menu.get_info);
 		gtk_widget_hide(win->menu.invite);
 		gtk_widget_show(win->menu.alias);
- 		if (purple_privacy_check(account, purple_conversation_get_name(conv))) {
+ 		if (!purple_privacy_check(account, purple_conversation_get_name(conv), PURPLE_PRIVACY_BLOCK_ALL)) {
  			gtk_widget_hide(win->menu.unblock);
  			gtk_widget_show(win->menu.block);
  		} else {
============================================================
--- pidgin/gtkprivacy.c	da09153a53a01c4dcb19733faa1345d852031076
+++ pidgin/gtkprivacy.c	7093b04eeca3bf7e1b963026b423b4aec6c692d4
@@ -39,29 +39,44 @@ typedef struct
 typedef struct
 {
 	GtkWidget *win;
-
 	GtkWidget *type_menu;
-
-	GtkWidget *add_button;
-	GtkWidget *remove_button;
-	GtkWidget *removeall_button;
 	GtkWidget *close_button;
+	GtkWidget *vbox_pas;
+	GtkWidget *sw_contacts;
+	GtkWidget *add_contact_button;
 
-	GtkWidget *button_box;
-	GtkWidget *allow_widget;
-	GtkWidget *block_widget;
+	GtkListStore *model_presence;
+	GtkListStore *model_contacts;
 
-	GtkListStore *allow_store;
-	GtkListStore *block_store;
+	gboolean show_sw_contacts;
+	PurpleAccount *account;
 
-	GtkWidget *allow_list;
-	GtkWidget *block_list;
+} PidginPrivacyDialog;
 
-	gboolean in_allow_list;
+enum
+{
+	PRESENCE_COLUMN_ICON,
+	PRESENCE_COLUMN_USERNAME,
+	PRESENCE_COLUMN_INV_NONBUD,
+	PRESENCE_COLUMN_INV_ALL,
+	PRESENCE_COLUMN_PROTOCOL,
+	PRESENCE_COLUMN_DATA,
+	PRESENCE_NUM_COLUMNS
+};
 
-	PurpleAccount *account;
+enum
+{
+	CONTACTS_COLUMN_BUDDYNAME,
+	CONTACTS_COLUMN_BLOCK_ALL,
+	CONTACTS_COLUMN_INVISIBLE,
+	CONTACTS_COLUMN_BLOCK_CHAT,
+	CONTACTS_COLUMN_BLOCK_FT,
+	CONTACTS_COLUMN_BLOCK_CONF,
+	CONTACTS_COLUMN_DATA,
+	CONTACTS_NUM_COLUMNS
+};
 
-} PidginPrivacyDialog;
+static void show_contacts(PidginPrivacyDialog *dialog);
 
 typedef struct
 {
@@ -78,266 +93,494 @@ static struct
 
 } const menu_entries[] =
 {
-	{ N_("Allow all users to contact me"),         PURPLE_PRIVACY_ALLOW_ALL },
-	{ N_("Allow only the users on my buddy list"), PURPLE_PRIVACY_ALLOW_BUDDYLIST },
-	{ N_("Allow only the users below"),            PURPLE_PRIVACY_ALLOW_USERS },
-	{ N_("Block all users"),                       PURPLE_PRIVACY_DENY_ALL },
-	{ N_("Block only the users below"),            PURPLE_PRIVACY_DENY_USERS }
+	{ N_("Allow all users to contact me"), PURPLE_PRIVACY_ALLOW_ALL },
+	{ N_("Block messages from users not in buddly list"), PURPLE_PRIVACY_BLOCK_MSG_NONBUDDY },
+	{ N_("Block all users not in buddy list"), PURPLE_PRIVACY_ALLOW_BUDDYLIST },
+	{ N_("Per contact settings"), PURPLE_PRIVACY_CUSTOM }
 };
 
 static const size_t menu_entry_count = sizeof(menu_entries) / sizeof(*menu_entries);
 
 static PidginPrivacyDialog *privacy_dialog = NULL;
 
+static gint
+destroy_cb(GtkWidget *w, GdkEvent *event, PidginPrivacyDialog *dialog)
+{
+	pidgin_privacy_dialog_hide();
+
+	return 0;
+}
+
 static void
-rebuild_allow_list(PidginPrivacyDialog *dialog)
+select_account_cb(GtkWidget *dropdown, PurpleAccount *account,
+				  PidginPrivacyDialog *dialog)
 {
-	GSList *l = NULL, *list = NULL;
-	GtkTreeIter iter;
+	int i;
 
-	gtk_list_store_clear(dialog->allow_store);
-	list = purple_privacy_list_get_members_by_account(dialog->account, PURPLE_PRIVACY_ALLOW_LIST);
+	dialog->account = account;
+	gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), 0);
 
-	for (l = list; l != NULL; l = l->next) {
-		gtk_list_store_append(dialog->allow_store, &iter);
-		gtk_list_store_set(dialog->allow_store, &iter, 0, (char *)l->data, -1);
+	for (i = 0; i < menu_entry_count; i++) {
+		if( (menu_entries[i].num == purple_privacy_obtain_account_state(account)) ) {
+			gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), i);
+			break;
+		}
 	}
-	g_slist_free(list);
 }
 
 static void
-rebuild_block_list(PidginPrivacyDialog *dialog)
+type_changed_cb(GtkOptionMenu *optmenu, PidginPrivacyDialog *dialog)
 {
-	GSList *l = NULL, *list = NULL;
-	GtkTreeIter iter;
+	int new_type = menu_entries[gtk_option_menu_get_history(optmenu)].num;
 
-	gtk_list_store_clear(dialog->block_store);
-	list = purple_privacy_list_get_members_by_account(dialog->account, PURPLE_PRIVACY_BLOCK_BOTH_LIST);
+	purple_privacy_set_account_state(dialog->account, new_type);
 
-	for (l = list; l != NULL; l = l->next) {
-		gtk_list_store_append(dialog->block_store, &iter);
-		gtk_list_store_set(dialog->block_store, &iter, 0, (char *)l->data, -1);
+	if(new_type == PURPLE_PRIVACY_CUSTOM) {
+		if(dialog->show_sw_contacts == FALSE)
+			show_contacts(dialog);
 	}
-	g_slist_free(list);
+	else {
+		if(dialog->show_sw_contacts == TRUE) {
+			/* destroy model_contacts */
+			gtk_widget_hide(dialog->sw_contacts);
+			gtk_widget_hide(dialog->add_contact_button);
+			dialog->show_sw_contacts = FALSE;
+		}
+	}
 }
 
 static void
-user_selected_cb(GtkTreeSelection *sel, PidginPrivacyDialog *dialog)
+close_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
 {
-	gtk_widget_set_sensitive(dialog->remove_button, TRUE);
+	gtk_widget_destroy(dialog->win);
+
+	pidgin_privacy_dialog_hide();
 }
 
-static GtkWidget *
-build_list(PidginPrivacyDialog *dialog, GtkListStore *model,
-		   GtkWidget **ret_treeview)
+static void toggle_button_cb(GtkWidget *widget, gpointer data)
 {
-	GtkWidget *sw;
-	GtkWidget *treeview;
-	GtkCellRenderer *rend;
-	GtkTreeViewColumn *column;
-	GtkTreeSelection *sel;
+	PidginPrivacyDialog *dialog = data;
+	PurplePrivacySetting privacy_type = (PurplePrivacySetting) g_object_get_data(G_OBJECT(widget), "choice_id"); 
+	if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+	{
+		if(privacy_type == PURPLE_PRIVACY_CUSTOM)
+			gtk_widget_show(dialog->vbox_pas);
+	}
+	else
+	{
+		if(privacy_type == PURPLE_PRIVACY_CUSTOM)
+			gtk_widget_hide(dialog->vbox_pas);
+	}
+}
 
-	sw = gtk_scrolled_window_new(NULL, NULL);
-	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
-					GTK_POLICY_AUTOMATIC,
-					GTK_POLICY_AUTOMATIC);
-	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
+static void show_offline_nonbud_cb(GtkWidget *widget, gpointer data)
+{
+}
 
-	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
-	*ret_treeview = treeview;
+static void show_offline_all_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
+{
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_presence);
+	GtkTreeIter iter;
+	gboolean state;
+	gboolean new_state = FALSE;
 
-	rend = gtk_cell_renderer_text_new();
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+					   PRESENCE_COLUMN_DATA, &account,
+					   PRESENCE_COLUMN_INV_ALL, &state,
+					   -1);
 
-	column = gtk_tree_view_column_new_with_attributes(NULL, rend,
-													  "text", 0,
-													  NULL);
-	gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), TRUE);
+	state = !state;
+	if(state) {
+		if(purple_privacy_account_supports_invisible_status(account))
+			new_state = purple_privacy_set_account_status_invisible(account);
+	}
+	else
+		new_state = !( purple_privacy_set_account_status_visible(account) );
+
+	gtk_list_store_set(dialog->model_presence, &iter,
+						PRESENCE_COLUMN_INV_ALL, new_state,
+						-1);
+}
+
+static void
+add_columns_show_offline(GtkWidget *treeview, PidginPrivacyDialog *dialog)
+{
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+
+	/* Username column */
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_title(column, _("Username"));
+	gtk_tree_view_column_set_resizable(column, TRUE);
 	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
-	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
-	gtk_container_add(GTK_CONTAINER(sw), treeview);
 
-	gtk_widget_show(treeview);
+	/* Username */
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute(column, renderer, "text", PRESENCE_COLUMN_USERNAME);
 
-	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
+	/* Protocol column */
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_title(column, _("Protocol"));
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	g_signal_connect(G_OBJECT(sel), "changed",
-					 G_CALLBACK(user_selected_cb), dialog);
+	/* Icon */
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(column, renderer, FALSE);
+	gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", PRESENCE_COLUMN_ICON);
 
-	gtk_widget_set_size_request(sw, -1, 200);
+	/* Protocol */
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute(column, renderer, "text", PRESENCE_COLUMN_PROTOCOL);
 
-	return sw;
+	/* Show Offline to non-buddies */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(show_offline_nonbud_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Invisible to Non-Buddies"), renderer, "active", PRESENCE_COLUMN_INV_NONBUD, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+	/* Show Offline to everyone */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(show_offline_all_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Invisible to Everyone"), renderer, "active", PRESENCE_COLUMN_INV_ALL, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 }
 
-static GtkWidget *
-build_allow_list(PidginPrivacyDialog *dialog)
+static void populate_accounts_list(PidginPrivacyDialog *dialog)
 {
-	GtkWidget *widget;
-	GtkWidget *list;
+/* Privacy laters: this is trouble, it doesnt change the list when an account signs off or signs in */
+	GList *l;
+	GtkTreeIter iter;
+	PurpleAccount *account;
+	GdkPixbuf *pixbuf;
 
-	dialog->allow_store = gtk_list_store_new(1, G_TYPE_STRING);
+	gtk_list_store_clear(dialog->model_presence);
 
-	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->allow_store), 0, GTK_SORT_ASCENDING);
+	for (l = purple_accounts_get_all_active(); l != NULL; l = g_list_delete_link(l,l)) {
+		account = l->data;
+		gtk_list_store_append(dialog->model_presence, &iter);
+		pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
 
-	widget = build_list(dialog, dialog->allow_store, &list);
+		gtk_list_store_set(dialog->model_presence, &iter,
+			PRESENCE_COLUMN_ICON, pixbuf,
+			PRESENCE_COLUMN_USERNAME, purple_account_get_username(account),
+			PRESENCE_COLUMN_INV_NONBUD, TRUE,	/* replace with invisiblity check */
+			PRESENCE_COLUMN_INV_ALL, purple_privacy_account_status_invisible(account),
+			PRESENCE_COLUMN_PROTOCOL, purple_account_get_protocol_name(account),
+			PRESENCE_COLUMN_DATA, account,
+			-1);
 
-	dialog->allow_list = list;
+		if (pixbuf != NULL)
+			g_object_unref(G_OBJECT(pixbuf));
+	}
+}
 
-	rebuild_allow_list(dialog);
+static void contacts_block_all_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
+{
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_contacts);
+	GtkTreeIter iter;
+	gboolean state;
+	char *name;
 
-	return widget;
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+				CONTACTS_COLUMN_DATA, &account,
+				CONTACTS_COLUMN_BLOCK_ALL, &state,
+				CONTACTS_COLUMN_BUDDYNAME, &name,
+				-1);
+
+	state = !state;
+	if(state)
+		purple_privacy_set_block_all(account, name, TRUE, TRUE);
+	else
+		purple_privacy_unset_block_all(account, name, TRUE, TRUE);
+
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF),
+				-1);
 }
 
-static GtkWidget *
-build_block_list(PidginPrivacyDialog *dialog)
+static void contacts_invisible_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
 {
-	GtkWidget *widget;
-	GtkWidget *list;
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_contacts);
+	GtkTreeIter iter;
+	gboolean state;
+	char *name;
 
-	dialog->block_store = gtk_list_store_new(1, G_TYPE_STRING);
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+				CONTACTS_COLUMN_DATA, &account,
+				CONTACTS_COLUMN_INVISIBLE, &state,
+				CONTACTS_COLUMN_BUDDYNAME, &name,
+				-1);
 
-	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->block_store), 0, GTK_SORT_ASCENDING);
+	state = !state;
+	if(state)
+		purple_privacy_set_block_presence(account, name, TRUE, TRUE);
+	else
+		purple_privacy_unset_block_presence(account, name, TRUE, TRUE);
 
-	widget = build_list(dialog, dialog->block_store, &list);
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF),
+				-1);
+}
 
-	dialog->block_list = list;
+static void contacts_block_chat_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
+{
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_contacts);
+	GtkTreeIter iter;
+	gboolean state;
+	char *name;
 
-	rebuild_block_list(dialog);
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+				CONTACTS_COLUMN_DATA, &account,
+				CONTACTS_COLUMN_BLOCK_CHAT, &state,
+				CONTACTS_COLUMN_BUDDYNAME, &name,
+				-1);
 
-	return widget;
+	state = !state;
+	if(state)
+		purple_privacy_set_block_message(account, name);
+	else
+		purple_privacy_unset_block_message(account, name);
+
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF),
+				-1);
 }
 
-static gint
-destroy_cb(GtkWidget *w, GdkEvent *event, PidginPrivacyDialog *dialog)
+static void contacts_block_ft_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
 {
-	pidgin_privacy_dialog_hide();
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_contacts);
+	GtkTreeIter iter;
+	gboolean state;
+	char *name;
 
-	return 0;
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+				CONTACTS_COLUMN_DATA, &account,
+				CONTACTS_COLUMN_BLOCK_FT, &state,
+				CONTACTS_COLUMN_BUDDYNAME, &name,
+				-1);
+
+	state = !state;
+	if(state)
+		purple_privacy_set_block_ft(account, name);
+	else
+		purple_privacy_unset_block_ft(account, name);
+
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF),
+				-1);
 }
 
-static void
-select_account_cb(GtkWidget *dropdown, PurpleAccount *account,
-				  PidginPrivacyDialog *dialog)
+static void contacts_block_conf_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
 {
-	int i;
+	PidginPrivacyDialog *dialog = (PidginPrivacyDialog *)data;
+	PurpleAccount *account;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model_contacts);
+	GtkTreeIter iter;
+	gboolean state;
+	char *name;
 
-	dialog->account = account;
+	gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+	gtk_tree_model_get(model, &iter,
+				CONTACTS_COLUMN_DATA, &account,
+				CONTACTS_COLUMN_BLOCK_CONF, &state,
+				CONTACTS_COLUMN_BUDDYNAME, &name,
+				-1);
 
-	for (i = 0; i < menu_entry_count; i++) {
-		if (menu_entries[i].num == account->perm_deny) {
-			gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), i);
-			break;
-		}
-	}
+	state = !state;
+	if(state)
+		purple_privacy_set_block_conf(account, name);
+	else
+		purple_privacy_unset_block_conf(account, name);
 
-	rebuild_allow_list(dialog);
-	rebuild_block_list(dialog);
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, name, PURPLE_PRIVACY_BLOCK_CONF),
+				-1);
 }
 
-/*
- * TODO: Setting the permit/deny setting needs to go through privacy.c
- *       Even better: the privacy API needs to not suck.
- */
-static void
-type_changed_cb(GtkOptionMenu *optmenu, PidginPrivacyDialog *dialog)
+static void populate_contacts_list(PidginPrivacyDialog *dialog)
 {
-	int new_type = menu_entries[gtk_option_menu_get_history(optmenu)].num;
+	GSList *l;
+	GtkTreeIter iter;
+	PurpleAccount *account = dialog->account;
+	PurpleBuddy *c;
 
-	dialog->account->perm_deny = new_type;
-	serv_set_permit_deny(purple_account_get_connection(dialog->account));
+	gtk_list_store_clear(dialog->model_contacts);
 
-	gtk_widget_hide(dialog->allow_widget);
-	gtk_widget_hide(dialog->block_widget);
-	gtk_widget_hide_all(dialog->button_box);
+	/* add "All Others" meta contact */
+	gtk_list_store_append(dialog->model_contacts, &iter);
+	gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BUDDYNAME, "All Others",
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, "all-others", PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, "all-others", PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, "all-others", PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, "all-others", PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, "all-others", PURPLE_PRIVACY_BLOCK_CONF),
+				CONTACTS_COLUMN_DATA, account,
+				-1);
 
-	if (new_type == PURPLE_PRIVACY_ALLOW_USERS) {
-		gtk_widget_show(dialog->allow_widget);
-		gtk_widget_show_all(dialog->button_box);
-		dialog->in_allow_list = TRUE;
+	/* Add the contacts now */	
+	for (l = purple_find_privacy_contacts(account, NULL); l != NULL; l = g_slist_delete_link(l,l))
+	{
+		c = l->data;
+		if(purple_strequal(c->name, "all-others") == FALSE)
+		{
+			gtk_list_store_append(dialog->model_contacts, &iter);
+			gtk_list_store_set(dialog->model_contacts, &iter,
+				CONTACTS_COLUMN_BUDDYNAME, purple_buddy_get_name(c),
+				CONTACTS_COLUMN_BLOCK_ALL, purple_privacy_check(account, purple_buddy_get_name(c), PURPLE_PRIVACY_BLOCK_ALL),
+				CONTACTS_COLUMN_INVISIBLE, purple_privacy_check(account, purple_buddy_get_name(c), PURPLE_PRIVACY_BLOCK_PRESENCE),
+				CONTACTS_COLUMN_BLOCK_CHAT, purple_privacy_check(account, purple_buddy_get_name(c), PURPLE_PRIVACY_BLOCK_MESSAGE),
+				CONTACTS_COLUMN_BLOCK_FT, purple_privacy_check(account, purple_buddy_get_name(c), PURPLE_PRIVACY_BLOCK_FT),
+				CONTACTS_COLUMN_BLOCK_CONF, purple_privacy_check(account, purple_buddy_get_name(c), PURPLE_PRIVACY_BLOCK_CONF),
+				CONTACTS_COLUMN_DATA, account,
+				-1);
+		}
 	}
-	else if (new_type == PURPLE_PRIVACY_DENY_USERS) {
-		gtk_widget_show(dialog->block_widget);
-		gtk_widget_show_all(dialog->button_box);
-		dialog->in_allow_list = FALSE;
-	}
-
-	gtk_widget_show_all(dialog->close_button);
-	gtk_widget_show(dialog->button_box);
-
-	purple_blist_schedule_save();
-	pidgin_blist_refresh(purple_get_blist());
 }
 
 static void
-add_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
+add_columns_contacts(GtkWidget *treeview, PidginPrivacyDialog *dialog)
 {
-	if (dialog->in_allow_list)
-		pidgin_request_add_permit(dialog->account, NULL);
-	else
-		pidgin_request_add_block(dialog->account, NULL);
-}
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
 
-static void
-remove_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
-{
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	GtkTreeSelection *sel;
-	char *name;
+	/* Buddyname column */
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_title(column, _("Buddy"));
+	gtk_tree_view_column_set_resizable(column, TRUE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	if (dialog->in_allow_list && dialog->allow_store == NULL)
-		return;
+	/* Buddyname */
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute(column, renderer, "text", CONTACTS_COLUMN_BUDDYNAME);
 
-	if (!dialog->in_allow_list && dialog->block_store == NULL)
-		return;
+	/* Block All */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(contacts_block_all_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Block All"), renderer, "active", CONTACTS_COLUMN_BLOCK_ALL, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	if (dialog->in_allow_list) {
-		model = GTK_TREE_MODEL(dialog->allow_store);
-		sel   = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->allow_list));
-	}
-	else {
-		model = GTK_TREE_MODEL(dialog->block_store);
-		sel   = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->block_list));
-	}
+	/* Invisible */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(contacts_invisible_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Invisible"), renderer, "active", CONTACTS_COLUMN_INVISIBLE, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	if (gtk_tree_selection_get_selected(sel, NULL, &iter))
-		gtk_tree_model_get(model, &iter, 0, &name, -1);
-	else
-		return;
+	/* Block Chat */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(contacts_block_chat_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Block Chat"), renderer, "active", CONTACTS_COLUMN_BLOCK_CHAT, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	if (dialog->in_allow_list)
-		purple_privacy_permit_remove(dialog->account, name, FALSE);
-	else
-		purple_privacy_deny_remove(dialog->account, name, FALSE);
+	/* Block FT */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(contacts_block_ft_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Block File Transfer"), renderer, "active", CONTACTS_COLUMN_BLOCK_FT, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 
-	g_free(name);
+	/* Block CONF */
+	renderer = gtk_cell_renderer_toggle_new();
+	g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(contacts_block_conf_cb), dialog); /* privacy laters: connect signal */
+	column = gtk_tree_view_column_new_with_attributes(_("Block Conference"), renderer, "active", CONTACTS_COLUMN_BLOCK_CONF, NULL);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
 }
 
-static void
-removeall_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
+/* Callback to add a contact */
+static void add_contact_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
 {
-	GSList *l = NULL, *list = NULL;
-	if (dialog->in_allow_list)
-		l = list = purple_privacy_list_get_members_by_account(dialog->account, PURPLE_PRIVACY_ALLOW_LIST);
-	else
-		l = list = purple_privacy_list_get_members_by_account(dialog->account, PURPLE_PRIVACY_BLOCK_BOTH_LIST);
-	while (l) {
-		char *user;
-		user = l->data;
-		l = l->next;
-		if (dialog->in_allow_list)
-			purple_privacy_permit_remove(dialog->account, user, FALSE);
-		else
-			purple_privacy_deny_remove(dialog->account, user, FALSE);
-	}
-	g_slist_free(list);
 }
 
-static void
-close_cb(GtkWidget *button, PidginPrivacyDialog *dialog)
+/* Create scroll box - Contacts and add contact button */
+static void show_contacts(PidginPrivacyDialog *dialog)
 {
-	gtk_widget_destroy(dialog->win);
+	GtkWidget *treeview;
+	GtkWidget *align;
 
-	pidgin_privacy_dialog_hide();
+	dialog->sw_contacts = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dialog->sw_contacts), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(dialog->sw_contacts), GTK_SHADOW_IN);
+	gtk_box_pack_start(GTK_BOX(dialog->vbox_pas), dialog->sw_contacts, TRUE, TRUE, 0);
+	gtk_widget_show(dialog->sw_contacts);
+
+	/* Add items to the scroll box - Contacts */
+	dialog->model_contacts = gtk_list_store_new(CONTACTS_NUM_COLUMNS,
+					G_TYPE_STRING,		/* CONTACTS_COLUMN_BUDDYNAME */
+					G_TYPE_BOOLEAN,		/* CONTACTS_COLUMN_BLOCK_ALL */
+					G_TYPE_BOOLEAN,		/* CONTACTS_COLUMN_INVISIBLE */
+					G_TYPE_BOOLEAN,		/* CONTACTS_COLUMN_BLOCK_CHAT */
+					G_TYPE_BOOLEAN,		/* CONTACTS_COLUMN_BLOCK_FT */
+					G_TYPE_BOOLEAN,		/* CONTACTS_COLUMN_BLOCK_CONF */
+					G_TYPE_POINTER		/* CONTACTS_COLUMN_DATA */
+					);
+
+	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model_contacts));
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
+	gtk_widget_set_size_request(treeview, -1, 150);
+	gtk_container_add(GTK_CONTAINER(dialog->sw_contacts), treeview);
+
+	add_columns_contacts(treeview, dialog);
+	gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview));
+	populate_contacts_list(dialog);
+
+	gtk_widget_show_all(treeview);
+	gtk_widget_show_all(treeview);
+
+	/* Add contact button */
+	align = gtk_alignment_new(1,1,0,0);
+	gtk_box_pack_start(GTK_BOX(dialog->vbox_pas), align, FALSE, FALSE, 0);
+	dialog->add_contact_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+	g_signal_connect(G_OBJECT(dialog->add_contact_button), "clicked", G_CALLBACK(add_contact_cb), dialog);
+	gtk_container_add(GTK_CONTAINER(align), dialog->add_contact_button);
+	gtk_widget_show(dialog->add_contact_button);
+	gtk_widget_show(align);
+
+	dialog->show_sw_contacts = TRUE;
 }
 
 static PidginPrivacyDialog *
@@ -345,100 +588,148 @@ privacy_dialog_new(void)
 {
 	PidginPrivacyDialog *dialog;
 	GtkWidget *vbox;
-	GtkWidget *button;
+	GtkWidget *label;
+	GtkWidget *radio = NULL;
+	GtkWidget *vbox_radio;
+	GtkWidget *presence_expander;
+	GtkWidget *vbox_presence_expander;
+	GtkWidget *sw_presence;
+	GtkWidget *treeview_presence;
 	GtkWidget *dropdown;
-	GtkWidget *label;
 	GtkWidget *menu;
 	int selected = 0;
 	int i;
+	PurplePrivacySetting state_global;
 
+	GtkWidget *button;
+
 	dialog = g_new0(PidginPrivacyDialog, 1);
 
-	dialog->win = pidgin_create_dialog(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", TRUE);
+	dialog->win = pidgin_create_dialog(_("Privacy"), PIDGIN_HIG_BORDER , "privacy", TRUE);
 
-	g_signal_connect(G_OBJECT(dialog->win), "delete_event",
-					 G_CALLBACK(destroy_cb), dialog);
+	g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(destroy_cb), dialog);
 
 	/* Main vbox */
 	vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog->win), FALSE, PIDGIN_HIG_BORDER);
 
 	/* Description label */
-	label = gtk_label_new(
-		_("Changes to privacy settings take effect immediately."));
+	label = gtk_label_new(_("Changes to privacy settings take effect immediately."));
 
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_widget_show(label);
 
+	/* Radio buttons */
+	vbox_radio = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_box_pack_start(GTK_BOX(vbox), vbox_radio, FALSE, FALSE, 0);
+	state_global = purple_privacy_obtain_global_state();
+
+	radio = gtk_radio_button_new_with_label(NULL, _("Allow all users"));
+	gtk_box_pack_start(GTK_BOX(vbox_radio), radio, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(radio), "toggled", G_CALLBACK(toggle_button_cb), (gpointer) dialog);
+	g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(PURPLE_PRIVACY_ALLOW_ALL));
+	if(state_global == PURPLE_PRIVACY_ALLOW_ALL)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+	gtk_widget_show(radio);
+
+	radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Block messages from the users not in the buddy list"));
+	gtk_box_pack_start(GTK_BOX(vbox_radio), radio, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(radio), "toggled", G_CALLBACK(toggle_button_cb), (gpointer) dialog);
+	g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(PURPLE_PRIVACY_BLOCK_MSG_NONBUDDY));
+	if(state_global == PURPLE_PRIVACY_BLOCK_MSG_NONBUDDY)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+	gtk_widget_show(radio);
+
+	radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Block users not in the buddy list"));
+	gtk_box_pack_start(GTK_BOX(vbox_radio), radio, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(radio), "toggled", G_CALLBACK(toggle_button_cb), (gpointer) dialog);
+	g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(PURPLE_PRIVACY_ALLOW_BUDDYLIST));
+	if(state_global == PURPLE_PRIVACY_ALLOW_BUDDYLIST)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+	gtk_widget_show(radio);
+
+	radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Per account settings"));
+	gtk_box_pack_start(GTK_BOX(vbox_radio), radio, FALSE, FALSE, 0);
+	g_signal_connect(G_OBJECT(radio), "toggled", G_CALLBACK(toggle_button_cb), (gpointer) dialog);
+	g_object_set_data(G_OBJECT(radio), "choice_id", GINT_TO_POINTER(PURPLE_PRIVACY_CUSTOM));
+	if(state_global == PURPLE_PRIVACY_CUSTOM)
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
+	gtk_widget_show(radio);
+
+	/* Prepare box for widgets under "Per account settings (pas) */
+	dialog->vbox_pas = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE/2);
+	gtk_box_pack_start(GTK_BOX(vbox_radio), dialog->vbox_pas, FALSE, FALSE, 0);
+
+	gtk_widget_show(vbox_radio);
+
+	/* Prepare widgets under PAS */
 	/* Accounts drop-down */
-	dropdown = pidgin_account_option_menu_new(NULL, FALSE,
-												G_CALLBACK(select_account_cb), NULL, dialog);
-	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Set privacy for:"), NULL, dropdown, TRUE, NULL);
+	dropdown = pidgin_account_option_menu_new(NULL, FALSE, G_CALLBACK(select_account_cb), NULL, dialog);
+	pidgin_add_widget_to_vbox(GTK_BOX(dialog->vbox_pas), _("Set privacy for:"), NULL, dropdown, TRUE, NULL);
 	dialog->account = pidgin_account_option_menu_get_selected(dropdown);
 
-	/* Add the drop-down list with the allow/block types. */
+	/* Privacy State drop down */
 	dialog->type_menu = gtk_option_menu_new();
-	gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0);
-	gtk_widget_show(dialog->type_menu);
+	pidgin_add_widget_to_vbox(GTK_BOX(dialog->vbox_pas), _("Privacy State: "), NULL, dialog->type_menu, TRUE, NULL);
+	menu = gtk_menu_new();
 
-	/* Build the menu for that. */
-	menu = gtk_menu_new();
+	if(state_global == PURPLE_PRIVACY_CUSTOM)
+		gtk_widget_show(dialog->vbox_pas);
 
 	for (i = 0; i < menu_entry_count; i++) {
 		pidgin_new_item(menu, _(menu_entries[i].text));
-
-		if (menu_entries[i].num == dialog->account->perm_deny)
+		if ( (menu_entries[i].num == purple_privacy_obtain_account_state(dialog->account)) )
 			selected = i;
 	}
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(dialog->type_menu), menu);
 	gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), selected);
+	g_signal_connect(G_OBJECT(dialog->type_menu), "changed", G_CALLBACK(type_changed_cb), dialog);
 
-	g_signal_connect(G_OBJECT(dialog->type_menu), "changed",
-					 G_CALLBACK(type_changed_cb), dialog);
+	/* If custom options selected: Construct and show contacts scroll window, add contact button */
+	dialog->show_sw_contacts = FALSE;	/* Currently we are not showing contacts scroll window */
+	if( menu_entries[selected].num == PURPLE_PRIVACY_CUSTOM )
+		type_changed_cb(GTK_OPTION_MENU(dialog->type_menu), dialog);
 
-	/* Build the treeview for the allow list. */
-	dialog->allow_widget = build_allow_list(dialog);
-	gtk_box_pack_start(GTK_BOX(vbox), dialog->allow_widget, TRUE, TRUE, 0);
+	/* Expander for Presence */
+	presence_expander = gtk_expander_new(_("Presence Settings"));
+	gtk_box_pack_start(GTK_BOX(vbox), presence_expander, FALSE, FALSE, 0);
+	gtk_widget_show(presence_expander);
+	vbox_presence_expander = gtk_vbox_new(FALSE, 20);
+	gtk_container_add(GTK_CONTAINER(presence_expander), vbox_presence_expander);
+	gtk_widget_show(presence_expander);
+	
+	/* Create scroll box for Presence Settings */
+	sw_presence = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw_presence), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw_presence), GTK_SHADOW_IN);
+	gtk_box_pack_start(GTK_BOX(vbox_presence_expander), sw_presence, TRUE, TRUE, 0);
+	gtk_widget_show(sw_presence);
+	gtk_widget_show(vbox_presence_expander);
 
-	/* Build the treeview for the block list. */
-	dialog->block_widget = build_block_list(dialog);
-	gtk_box_pack_start(GTK_BOX(vbox), dialog->block_widget, TRUE, TRUE, 0);
+	/* Add items to the scroll box - (SOPNL)*/
+	dialog->model_presence = gtk_list_store_new(PRESENCE_NUM_COLUMNS,
+					GDK_TYPE_PIXBUF,   /* PRESENCE_COLUMN_ICON */
+					G_TYPE_STRING,     /* PRESENCE_COLUMN_USERNAME */
+					G_TYPE_BOOLEAN,    /* PRESENCE_COLUMN_INV_NONBUD */
+					G_TYPE_BOOLEAN,    /* PRESENCE_COLUMN_INV_ALL */
+					G_TYPE_STRING,     /* PRESENCE_COLUMN_PROTOCOL */
+					G_TYPE_POINTER     /* PRESENCE_COLUMN_DATA */
+					);
+	treeview_presence = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model_presence));
+	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview_presence), TRUE);
+	gtk_widget_set_size_request(treeview_presence, -1, 150);
+	gtk_container_add(GTK_CONTAINER(sw_presence), treeview_presence);
 
-	/* Add the button box for Add, Remove, Remove All */
-	dialog->button_box = pidgin_dialog_get_action_area(GTK_DIALOG(dialog->win));
+	add_columns_show_offline(treeview_presence, dialog);
+	gtk_tree_view_columns_autosize(GTK_TREE_VIEW(treeview_presence));
+	populate_accounts_list(dialog);
+	gtk_widget_show_all(treeview_presence);
 
-	/* Add button */
-	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_ADD, G_CALLBACK(add_cb), dialog);
-	dialog->add_button = button;
-
-	/* 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);
-
-	/* 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);
 	dialog->close_button = button;
 
-	type_changed_cb(GTK_OPTION_MENU(dialog->type_menu), dialog);
-#if 0
-	if (dialog->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) {
-		gtk_widget_show(dialog->allow_widget);
-		gtk_widget_show(dialog->button_box);
-		dialog->in_allow_list = TRUE;
-	}
-	else if (dialog->account->perm_deny == PURPLE_PRIVACY_DENY_USERS) {
-		gtk_widget_show(dialog->block_widget);
-		gtk_widget_show(dialog->button_box);
-		dialog->in_allow_list = FALSE;
-	}
-#endif
 	return dialog;
 }
 
@@ -460,8 +751,7 @@ pidgin_privacy_dialog_hide(void)
 	if (privacy_dialog == NULL)
 		return;
 
-	g_object_unref(G_OBJECT(privacy_dialog->allow_store));
-	g_object_unref(G_OBJECT(privacy_dialog->block_store));
+	/* privacy laters: un ref stores, free data */
 	g_free(privacy_dialog);
 	privacy_dialog = NULL;
 }
@@ -473,24 +763,16 @@ destroy_request_data(PidginPrivacyReques
 	g_free(data);
 }
 
-static void
-confirm_permit_block_cb(PidginPrivacyRequestData *data, int option)
+/* privacy laters: remove laters */
+
+static void confirm_permit_block_cb(PidginPrivacyRequestData *data, int option)
 {
-	if (data->block)
-		purple_privacy_deny(data->account, data->name, FALSE, FALSE);
-	else
-		purple_privacy_allow(data->account, data->name, FALSE, FALSE);
-
-	destroy_request_data(data);
 }
 
-static void
-add_permit_block_cb(PidginPrivacyRequestData *data, const char *name)
+static void add_permit_block_cb(PidginPrivacyRequestData *data, const char *name)
 {
-	data->name = g_strdup(name);
-
-	confirm_permit_block_cb(data, 0);
 }
+/* privacy laters */
 
 void
 pidgin_request_add_permit(PurpleAccount *account, const char *name)
@@ -576,15 +858,15 @@ pidgin_permit_added_removed(PurpleAccoun
 static void
 pidgin_permit_added_removed(PurpleAccount *account, const char *name)
 {
-	if (privacy_dialog != NULL)
-		rebuild_allow_list(privacy_dialog);
+	/*if (privacy_dialog != NULL)
+		rebuild_allow_list(privacy_dialog); */
 }
 
 static void
 pidgin_deny_added_removed(PurpleAccount *account, const char *name)
 {
-	if (privacy_dialog != NULL)
-		rebuild_block_list(privacy_dialog);
+	/*if (privacy_dialog != NULL)
+		rebuild_block_list(privacy_dialog); */
 }
 
 static PurplePrivacyUiOps privacy_ops =


More information about the Commits mailing list