changeset 30800:05c634403678

Start using the real ICQ block list (SSI type 0xe) for allowing/blocking users. The deny list (SSI type 0x3) that is used in AIM is actually a "permanently invisible" list for ICQ. Also, the "vismask" parameter in aim_ssi_setpermdeny() was removed, since it wasn't being used anyway.
author ivan.komarov@soc.pidgin.im
date Fri, 18 Jun 2010 13:55:54 +0000
parents 457b9739aca9
children 3ada0cc7d2c5
files libpurple/protocols/oscar/family_feedbag.c libpurple/protocols/oscar/libicq.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h
diffstat 4 files changed, 44 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/oscar/family_feedbag.c	Thu Jun 17 11:10:27 2010 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Fri Jun 18 13:55:54 2010 +0000
@@ -781,16 +781,16 @@
  */
 int aim_ssi_adddeny(OscarData *od, const char *name)
 {
-
+	guint16 deny_entry_type = aim_ssi_getdenyentrytype(od);
 	if (!od || !name || !od->ssi.received_data)
 		return -EINVAL;
 
 	/* Make sure the master group exists */
 	if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-		aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+		aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, deny_entry_type, NULL);
 
 	/* Add that bad boy */
-	aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL);
+	aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, deny_entry_type, NULL);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
@@ -893,13 +893,14 @@
  */
 int aim_ssi_deldeny(OscarData *od, const char *name)
 {
+	guint16 deny_entry_type = aim_ssi_getdenyentrytype(od);
 	struct aim_ssi_item *del;
 
 	if (!od)
 		return -EINVAL;
 
 	/* Find the item */
-	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))
+	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, deny_entry_type)))
 		return -EINVAL;
 
 	/* Remove the item from the list */
@@ -1030,17 +1031,16 @@
  * Stores your permit/deny setting on the server, and starts using it.
  *
  * @param od The oscar odion.
- * @param permdeny Your permit/deny setting.  Can be one of the following:
+ * @param permdeny Your permit/deny setting. For ICQ accounts, it actually affects your visibility
+ *        and has nothing to do with blocking. Can be one of the following:
  *        1 - Allow all users
  *        2 - Block all users
  *        3 - Allow only the users below
  *        4 - Block only the users below
  *        5 - Allow only users on my buddy list
- * @param vismask A bitmask of the class of users to whom you want to be
- *        visible.  See the AIM_FLAG_BLEH #defines in oscar.h
  * @return Return 0 if no errors, otherwise return the error number.
  */
-int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny, guint32 vismask)
+int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny)
 {
 	struct aim_ssi_item *tmp;
 
@@ -1059,9 +1059,6 @@
 	/* Need to add the 0x00ca TLV to the TLV chain */
 	aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);
 
-	/* Need to add the 0x00cb TLV to the TLV chain */
-	aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask);
-
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
 }
@@ -1935,6 +1932,16 @@
 	return ret;
 }
 
+/*
+ * If we're on ICQ, then AIM_SSI_TYPE_DENY is used for the "permanently invisible" list.
+ * AIM_SSI_TYPE_ICQDENY is used for blocking users instead.
+ */
+guint16
+aim_ssi_getdenyentrytype(OscarData* od)
+{
+	return od->icq ? AIM_SSI_TYPE_ICQDENY : AIM_SSI_TYPE_DENY;
+}
+
 static int
 snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
--- a/libpurple/protocols/oscar/libicq.c	Thu Jun 17 11:10:27 2010 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Fri Jun 18 13:55:54 2010 +0000
@@ -63,11 +63,11 @@
 	NULL,					/* add_buddies */
 	oscar_remove_buddy,		/* remove_buddy */
 	NULL,					/* remove_buddies */
-	oscar_add_permit,		/* add_permit */
+	NULL,		/* add_permit */
 	oscar_add_deny,			/* add_deny */
-	oscar_rem_permit,		/* rem_permit */
+	NULL,		/* rem_permit */
 	oscar_rem_deny,			/* rem_deny */
-	oscar_set_permit_deny,	/* set_permit_deny */
+	NULL,	/* set_permit_deny */
 	oscar_join_chat,		/* join_chat */
 	NULL,					/* reject_chat */
 	oscar_get_chat_name,	/* get_chat_name */
--- a/libpurple/protocols/oscar/oscar.c	Thu Jun 17 11:10:27 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Jun 18 13:55:54 2010 +0000
@@ -4028,9 +4028,17 @@
 oscar_set_status_icq(PurpleAccount *account)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
-
-	/* Our permit/deny setting affects our invisibility */
-	oscar_set_permit_deny(gc);
+	OscarData *od = purple_connection_get_protocol_data(gc);
+	gboolean invisible = purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE);
+
+	/*
+	 * For ICQ the permit/deny setting controls who can see you
+	 * online. Mimicking the official client's behavior, we use PURPLE_PRIVACY_ALLOW_USERS
+	 * when our status is "invisible" and PURPLE_PRIVACY_DENY_USERS otherwise.
+	 * In the former case, we are visible only to buddies on our "permanently visible" list.
+	 * In the latter, we are invisible only to buddies on our "permanentnly invisible" list.
+	 */
+	aim_ssi_setpermdeny(od, invisible ? PURPLE_PRIVACY_ALLOW_USERS : PURPLE_PRIVACY_DENY_USERS);
 
 	/*
 	 * TODO: I guess we should probably wait and do this after we get
@@ -4284,6 +4292,7 @@
 	va_list ap;
 	guint16 fmtver, numitems;
 	guint32 timestamp;
+	guint16 deny_entry_type = aim_ssi_getdenyentrytype(od);
 
 	gc = od->gc;
 	od = purple_connection_get_protocol_data(gc);
@@ -4352,8 +4361,8 @@
 			purple_blist_remove_buddy(b);
 		}
 
-		/* Permit list */
-		if (account->permit) {
+		/* Permit list (ICQ doesn't have one) */
+		if (!od->icq && account->permit) {
 			next = account->permit;
 			while (next != NULL) {
 				cur = next;
@@ -4372,7 +4381,7 @@
 			while (next != NULL) {
 				cur = next;
 				next = next->next;
-				if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) {
+				if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) {
 					purple_debug_info("oscar",
 							"ssi: removing deny %s from local list\n", (const char *)cur->data);
 					purple_privacy_deny_remove(account, cur->data, TRUE);
@@ -4487,8 +4496,8 @@
 				g_free(gname_utf8);
 			} break;
 
-			case AIM_SSI_TYPE_PERMIT: { /* Permit buddy */
-				if (curitem->name) {
+			case AIM_SSI_TYPE_PERMIT: { /* Permit buddy (unless we're on ICQ) */
+				if (!od->icq && curitem->name) {
 					/* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */
 					GSList *list;
 					for (list=account->permit; (list && oscar_util_name_compare(curitem->name, list->data)); list=list->next);
@@ -4500,8 +4509,9 @@
 				}
 			} break;
 
+			case AIM_SSI_TYPE_ICQDENY:
 			case AIM_SSI_TYPE_DENY: { /* Deny buddy */
-				if (curitem->name) {
+				if (curitem->type == deny_entry_type && curitem->name) {
 					GSList *list;
 					for (list=account->deny; (list && oscar_util_name_compare(curitem->name, list->data)); list=list->next);
 					if (!list) {
@@ -5172,28 +5182,6 @@
 void oscar_set_permit_deny(PurpleConnection *gc) {
 	PurpleAccount *account = purple_connection_get_account(gc);
 	OscarData *od = purple_connection_get_protocol_data(gc);
-	PurplePrivacyType perm_deny;
-
-	/*
-	 * For ICQ the permit/deny setting controls who you can see you
-	 * online when you set your status to "invisible."  If we're ICQ
-	 * and we're invisible then we need to use one of
-	 * PURPLE_PRIVACY_ALLOW_USERS or PURPLE_PRIVACY_ALLOW_BUDDYLIST or
-	 * PURPLE_PRIVACY_DENY_USERS if we actually want to be invisible
-	 * to anyone.
-	 *
-	 * These three permit/deny settings correspond to:
-	 * 1. Invisible to everyone except the people on my "permit" list
-	 * 2. Invisible to everyone except the people on my buddy list
-	 * 3. Invisible only to the people on my "deny" list
-	 *
-	 * It would be nice to allow cases 2 and 3, but our UI doesn't have
-	 * a nice way to do it.  For now we just force case 1.
-	 */
-	if (od->icq && purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE))
-		perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
-	else
-		perm_deny = account->perm_deny;
 
 	if (od->ssi.received_data)
 		/*
@@ -5201,7 +5189,7 @@
 		 * values of libpurple's PurplePrivacyType and the values used
 		 * by the oscar protocol.
 		 */
-		aim_ssi_setpermdeny(od, perm_deny, 0xffffffff);
+		aim_ssi_setpermdeny(od, account->perm_deny);
 }
 
 void oscar_add_permit(PurpleConnection *gc, const char *who) {
--- a/libpurple/protocols/oscar/oscar.h	Thu Jun 17 11:10:27 2010 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Fri Jun 18 13:55:54 2010 +0000
@@ -1272,6 +1272,7 @@
 #define AIM_SSI_TYPE_DENY		0x0003
 #define AIM_SSI_TYPE_PDINFO		0x0004
 #define AIM_SSI_TYPE_PRESENCEPREFS	0x0005
+#define AIM_SSI_TYPE_ICQDENY		0x000e
 #define AIM_SSI_TYPE_ICONINFO		0x0014
 
 #define AIM_SSI_ACK_SUCCESS		0x0000
@@ -1340,12 +1341,12 @@
 int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn);
 int aim_ssi_cleanlist(OscarData *od);
 int aim_ssi_deletelist(OscarData *od);
-int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny, guint32 vismask);
+int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny);
 int aim_ssi_setpresence(OscarData *od, guint32 presence);
 int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen);
 int aim_ssi_delicon(OscarData *od);
 
-
+guint16 aim_ssi_getdenyentrytype(OscarData* od);
 
 /* 0x0015 - family_icq.c */
 #define AIM_ICQ_INFO_SIMPLE	0x001