changeset 18755:84d53c3c699d

Some changes from Matthew Goldstein and I to not automatically remove empty groups from the oscar server-stored buddy list. There's this thing called AIM WIMZI that relies on having a certain group in your buddy list so that it can add buddies to it automatically, and it wasn't working if you used Pidgin because the group didn't exist. See http://wimzi.aim.com/ Also try to fix allowing buddies to be in multiple groups.
author Mark Doliner <mark@kingant.net>
date Tue, 31 Jul 2007 06:51:29 +0000
parents 66df5d93cdf4
children 9b0fd9a4d01b
files COPYRIGHT libpurple/protocols/oscar/family_feedbag.c libpurple/protocols/oscar/libaim.c libpurple/protocols/oscar/libicq.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h libpurple/protocols/oscar/oscarcommon.h libpurple/stringref.h
diffstat 8 files changed, 61 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Jul 31 06:09:45 2007 +0000
+++ b/COPYRIGHT	Tue Jul 31 06:51:29 2007 +0000
@@ -144,6 +144,7 @@
 Gustavo Giráldez
 Richard Gobeille
 Ian Goldberg
+Matthew Goldstein
 Michael Golden
 Charlie Gordon
 Ryan C. Gordon
--- a/libpurple/protocols/oscar/family_feedbag.c	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Tue Jul 31 06:51:29 2007 +0000
@@ -695,18 +695,6 @@
 		cur = cur->next;
 	}
 
-	/* Check if there are empty groups and delete them */
-	cur = od->ssi.local;
-	while (cur) {
-		next = cur->next;
-		if (cur->type == AIM_SSI_TYPE_GROUP) {
-			aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c8, 1);
-			if (!tlv || !tlv->length)
-				aim_ssi_itemlist_del(&od->ssi.local, cur);
-		}
-		cur = next;
-	}
-
 	/* Check if the master group is empty */
 	if ((cur = aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000)) && (!cur->data))
 		aim_ssi_itemlist_del(&od->ssi.local, cur);
@@ -841,18 +829,39 @@
 	/* Modify the parent group */
 	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
 
-	/* Check if we should delete the parent group */
-	if ((del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) {
-		aim_ssi_itemlist_del(&od->ssi.local, del);
+	/* Sync our local list with the server list */
+	return aim_ssi_sync(od);
+}
+
+/**
+ * Deletes a group from the list.
+ *
+ * @param od The oscar odion.
+ * @param group The name of the group.
+ * @return Return 0 if no errors, otherwise return the error number.
+ */
+int aim_ssi_delgroup(OscarData *od, const char *group)
+{
+	struct aim_ssi_item *del;
+	aim_tlv_t *tlv;
 
-		/* Modify the parent group */
-		aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL);
+	if (!od)
+		return -EINVAL;
+
+	/* Find the group */
+	if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
+		return -EINVAL;
 
-		/* Check if we should delete the parent's parent (the master group) */
-		if ((del = aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000)) && (!del->data)) {
-			aim_ssi_itemlist_del(&od->ssi.local, del);
-		}
-	}
+	/* Don't delete the group if it's not empty */
+	tlv = aim_tlv_gettlv(del->data, 0x00c8, 1);
+	if (tlv && tlv->length > 0)
+		return -EINVAL;
+
+	/* Remove the item from the list */
+	aim_ssi_itemlist_del(&od->ssi.local, del);
+
+	/* Modify the parent group */
+	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
 
 	/* Sync our local list with the server list */
 	return aim_ssi_sync(od);
--- a/libpurple/protocols/oscar/libaim.c	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/libaim.c	Tue Jul 31 06:51:29 2007 +0000
@@ -78,7 +78,7 @@
 	oscar_convo_closed,		/* convo_closed */
 	oscar_normalize,		/* normalize */
 	oscar_set_icon,			/* set_buddy_icon */
-	NULL,					/* remove_group */
+	oscar_remove_group,		/* remove_group */
 	NULL,					/* get_cb_real_name */
 	NULL,					/* set_chat_topic */
 	NULL,					/* find_blist_chat */
--- a/libpurple/protocols/oscar/libicq.c	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Tue Jul 31 06:51:29 2007 +0000
@@ -78,7 +78,7 @@
 	oscar_convo_closed,		/* convo_closed */
 	oscar_normalize,		/* normalize */
 	oscar_set_icon,			/* set_buddy_icon */
-	NULL,					/* remove_group */
+	oscar_remove_group,		/* remove_group */
 	NULL,					/* get_cb_real_name */
 	NULL,					/* set_chat_topic */
 	NULL,					/* find_blist_chat */
--- a/libpurple/protocols/oscar/oscar.c	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Jul 31 06:51:29 2007 +0000
@@ -4709,6 +4709,11 @@
 	}
 }
 
+void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group)
+{
+	aim_ssi_delgroup(gc->proto_data, group->name);
+}
+
 static gboolean purple_ssi_rerequestdata(gpointer data) {
 	OscarData *od = data;
 
@@ -4902,29 +4907,34 @@
 
 	/* Add from server list to local list */
 	for (curitem=od->ssi.local; curitem; curitem=curitem->next) {
-		if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
+	  if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
 		switch (curitem->type) {
 			case 0x0000: { /* Buddy */
 				if (curitem->name) {
-					char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, curitem->name);
+					struct aim_ssi_item *groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000);
+					char *gname = groupitem ? groupitem->name : NULL;
 					char *gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL;
 					char *alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name);
 					char *alias_utf8;
 
+					g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans"));
+					if (g == NULL) {
+						g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+						purple_blist_add_group(g, NULL);
+					}
+
 					if (alias != NULL)
 					{
 						if (g_utf8_validate(alias, -1, NULL))
 							alias_utf8 = g_strdup(alias);
 						else
 							alias_utf8 = oscar_utf8_try_convert(account, alias);
+						g_free(alias);
 					}
 					else
 						alias_utf8 = NULL;
 
-					b = purple_find_buddy(gc->account, curitem->name);
-					/* Should gname be freed here? -- elb */
-					/* Not with the current code, but that might be cleaner -- med */
-					g_free(alias);
+					b = purple_find_buddy_in_group(gc->account, curitem->name, g);
 					if (b) {
 						/* Get server stored alias */
 						if (alias_utf8) {
@@ -4934,13 +4944,8 @@
 					} else {
 						b = purple_buddy_new(gc->account, curitem->name, alias_utf8);
 
-						if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-							g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
-							purple_blist_add_group(g, NULL);
-						}
-
 						purple_debug_info("oscar",
-								   "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
+								   "ssi: adding buddy %s to group %s to local list\n", curitem->name, g->name);
 						purple_blist_add_buddy(b, NULL, g, NULL);
 					}
 					if (!aim_sncmp(curitem->name, account->username)) {
@@ -4957,7 +4962,12 @@
 			} break;
 
 			case 0x0001: { /* Group */
-				/* Shouldn't add empty groups */
+				char *gname = curitem->name;
+				char *gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL;
+				if (gname_utf8 != NULL) {
+					g = purple_group_new(gname_utf8);
+					purple_blist_add_group(g, NULL);
+				}
 			} break;
 
 			case 0x0002: { /* Permit buddy */
--- a/libpurple/protocols/oscar/oscar.h	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Tue Jul 31 06:51:29 2007 +0000
@@ -1211,6 +1211,7 @@
 int aim_ssi_addpermit(OscarData *od, const char *name);
 int aim_ssi_adddeny(OscarData *od, const char *name);
 int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group);
+int aim_ssi_delgroup(OscarData *od, const char *group);
 int aim_ssi_delpermit(OscarData *od, const char *name);
 int aim_ssi_deldeny(OscarData *od, const char *name);
 int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn);
--- a/libpurple/protocols/oscar/oscarcommon.h	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/protocols/oscar/oscarcommon.h	Tue Jul 31 06:51:29 2007 +0000
@@ -82,6 +82,7 @@
 void oscar_convo_closed(PurpleConnection *gc, const char *who);
 const char *oscar_normalize(const PurpleAccount *account, const char *str);
 void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
+void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group);
 gboolean oscar_can_receive_file(PurpleConnection *gc, const char *who);
 void oscar_send_file(PurpleConnection *gc, const char *who, const char *file);
 PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who);
--- a/libpurple/stringref.h	Tue Jul 31 06:09:45 2007 +0000
+++ b/libpurple/stringref.h	Tue Jul 31 06:51:29 2007 +0000
@@ -1,3 +1,5 @@
+/* TODO: Can we just replace this whole thing with a GCache */
+
 /**
  * @file stringref.h Reference-counted immutable strings
  * @ingroup core