pidgin.next.major: fc195a83: Add two hash tables to the oscar code th...
markdoliner at pidgin.im
markdoliner at pidgin.im
Sun Mar 20 16:25:49 EDT 2011
----------------------------------------------------------------------
Revision: fc195a83f896d038c367b1e92cc1bebd7e8246ab
Parent: 8a01cb2d1f94013cfd5fd2c5cc99beb98737c297
Author: markdoliner at pidgin.im
Date: 03/20/11 16:20:52
Branch: im.pidgin.pidgin.next.major
URL: http://d.pidgin.im/viewmtn/revision/info/fc195a83f896d038c367b1e92cc1bebd7e8246ab
Changelog:
Add two hash tables to the oscar code that deals with your server stored
buddy list. One hash table is indexed by a combination of group id and
buddy id. The other hash table is indexed by a combination of item type
and item name. This should reduce the number of times we iterate through
a linked list by A LOT.
This is a modified version of Oliver's patch from #4816.
Fixes #4816.
Changes against parent 8a01cb2d1f94013cfd5fd2c5cc99beb98737c297
patched ChangeLog
patched libpurple/protocols/oscar/authorization.c
patched libpurple/protocols/oscar/family_feedbag.c
patched libpurple/protocols/oscar/oscar.c
patched libpurple/protocols/oscar/oscar.h
patched libpurple/protocols/oscar/oscar_data.c
patched libpurple/protocols/oscar/userinfo.c
patched libpurple/protocols/oscar/visibility.c
-------------- next part --------------
============================================================
--- ChangeLog f677c300947728bb314d3ad027a3bf2c8422048c
+++ ChangeLog 60c5af6381e6f60909a50587f8f5248a18d473e4
@@ -1,5 +1,9 @@ Pidgin and Finch: The Pimpin' Penguin IM
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
+version 3.0.0 (??/??/????):
+ AIM and ICQ:
+ * Make buddy list management code more efficient. (Oliver) (#4816)
+
version 2.8.0 (??/??/????):
General:
* Implement simple silence suppression for voice calls, preventing wasted
============================================================
--- libpurple/protocols/oscar/oscar.c 1832433d5ba5e7cffb9ef3f207f2af3281d3d32e
+++ libpurple/protocols/oscar/oscar.c a4bf78718c7f7075f34d9a4661557f5fd2be395b
@@ -578,7 +578,7 @@ idle_reporting_pref_cb(const char *name,
gc = data;
od = purple_connection_get_protocol_data(gc);
report_idle = strcmp((const char *)value, "none") != 0;
- presence = aim_ssi_getpresence(od->ssi.local);
+ presence = aim_ssi_getpresence(&od->ssi.local);
if (report_idle)
aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
@@ -600,7 +600,7 @@ recent_buddies_pref_cb(const char *name,
gc = data;
od = purple_connection_get_protocol_data(gc);
- presence = aim_ssi_getpresence(od->ssi.local);
+ presence = aim_ssi_getpresence(&od->ssi.local);
if (value)
aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
@@ -3709,7 +3709,7 @@ oscar_add_buddy(PurpleConnection *gc, Pu
}
if (od->ssi.received_data) {
- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
+ if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
purple_debug_info("oscar",
"ssi: adding buddy %s to group %s\n", bname, gname);
aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
@@ -3721,8 +3721,8 @@ oscar_add_buddy(PurpleConnection *gc, Pu
purple_prpl_got_user_status(account, bname,
OSCAR_STATUS_ID_MOBILE, NULL);
}
- } else if (aim_ssi_waitingforauth(od->ssi.local,
- aim_ssi_itemlist_findparentname(od->ssi.local, bname),
+ } else if (aim_ssi_waitingforauth(&od->ssi.local,
+ aim_ssi_itemlist_findparentname(&od->ssi.local, bname),
bname)) {
/* Not authorized -- Re-request authorization */
oscar_auth_sendrequest(gc, bname);
@@ -3760,7 +3760,7 @@ void oscar_alias_buddy(PurpleConnection
OscarData *od = purple_connection_get_protocol_data(gc);
if (od->ssi.received_data) {
- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+ char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
if (gname) {
purple_debug_info("oscar",
"ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)");
@@ -3777,7 +3777,7 @@ void oscar_rename_group(PurpleConnection
if (od->ssi.received_data) {
const char *gname = purple_group_get_name(group);
- if (aim_ssi_itemlist_finditem(od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
+ if (aim_ssi_itemlist_finditem(&od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
GList *cur, *groups = NULL;
PurpleAccount *account = purple_connection_get_account(gc);
@@ -3928,7 +3928,7 @@ static int purple_ssi_parselist(OscarDat
gname = purple_group_get_name(g);
bname = purple_buddy_get_name(b);
- if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
+ if (aim_ssi_itemlist_exists(&od->ssi.local, bname)) {
/* If the buddy is an ICQ user then load his nickname */
const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
char *alias;
@@ -3937,7 +3937,7 @@ static int purple_ssi_parselist(OscarDat
serv_got_alias(gc, bname, servernick);
/* Store local alias on server */
- alias = aim_ssi_getalias(od->ssi.local, gname, bname);
+ alias = aim_ssi_getalias(&od->ssi.local, gname, bname);
balias = purple_buddy_get_local_buddy_alias(b);
if (!alias && balias && *balias)
aim_ssi_aliasbuddy(od, gname, bname, balias);
@@ -3960,7 +3960,7 @@ static int purple_ssi_parselist(OscarDat
while (next != NULL) {
cur = next;
next = next->next;
- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
+ if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
purple_debug_info("oscar",
"ssi: removing permit %s from local list\n", (const char *)cur->data);
purple_privacy_permit_remove(account, cur->data, TRUE);
@@ -3973,7 +3973,7 @@ static int purple_ssi_parselist(OscarDat
while (next != NULL) {
cur = next;
next = next->next;
- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) {
+ 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);
@@ -3981,7 +3981,7 @@ static int purple_ssi_parselist(OscarDat
}
/* Presence settings (idle time visibility) */
- tmp = aim_ssi_getpresence(od->ssi.local);
+ tmp = aim_ssi_getpresence(&od->ssi.local);
if (tmp != 0xFFFFFFFF) {
const char *idle_reporting_pref;
gboolean report_idle;
@@ -3999,7 +3999,7 @@ static int purple_ssi_parselist(OscarDat
/*** Begin code for adding from server list to local list ***/
- for (curitem=od->ssi.local; curitem; curitem=curitem->next) {
+ for (curitem=od->ssi.local.data; curitem; curitem=curitem->next) {
if (curitem->name && !g_utf8_validate(curitem->name, -1, NULL)) {
/* Got node with invalid UTF-8 in the name. Skip it. */
purple_debug_warning("oscar", "ssi: server list contains item of "
@@ -4013,7 +4013,7 @@ static int purple_ssi_parselist(OscarDat
struct aim_ssi_item *groupitem;
char *gname, *gname_utf8, *alias, *alias_utf8;
- groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000);
+ groupitem = aim_ssi_itemlist_find(&od->ssi.local, curitem->gid, 0x0000);
gname = groupitem ? groupitem->name : NULL;
gname_utf8 = oscar_utf8_try_convert(account, od, gname);
@@ -4023,7 +4023,7 @@ static int purple_ssi_parselist(OscarDat
purple_blist_add_group(g, NULL);
}
- alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name);
+ alias = aim_ssi_getalias_from_item(curitem);
alias_utf8 = oscar_utf8_try_convert(account, od, alias);
b = purple_find_buddy_in_group(account, curitem->name, g);
@@ -4091,7 +4091,7 @@ static int purple_ssi_parselist(OscarDat
* a part of your status and not really related to blocking.
*/
if (!od->icq && curitem->data) {
- guint8 perm_deny = aim_ssi_getpermdeny(od->ssi.local);
+ guint8 perm_deny = aim_ssi_getpermdeny(&od->ssi.local);
if (perm_deny != 0 && perm_deny != account->perm_deny)
{
purple_debug_info("oscar",
@@ -4220,10 +4220,10 @@ purple_ssi_parseaddmod(OscarData *od, Fl
if ((type != 0x0000) || (name == NULL))
return 1;
- gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+ gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL;
- alias = aim_ssi_getalias(od->ssi.local, gname, name);
+ alias = aim_ssi_getalias(&od->ssi.local, gname, name);
alias_utf8 = oscar_utf8_try_convert(account, od, alias);
g_free(alias);
@@ -4261,7 +4261,7 @@ purple_ssi_parseaddmod(OscarData *od, Fl
}
- ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
+ ssi_item = aim_ssi_itemlist_finditem(&od->ssi.local,
gname, name, AIM_SSI_TYPE_BUDDY);
if (ssi_item == NULL)
{
@@ -4634,8 +4634,8 @@ const char *oscar_list_emblem(PurpleBudd
if (purple_presence_is_online(presence) == FALSE) {
char *gname;
if ((name) && (od) && (od->ssi.received_data) &&
- (gname = aim_ssi_itemlist_findparentname(od->ssi.local, name)) &&
- (aim_ssi_waitingforauth(od->ssi.local, gname, name))) {
+ (gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name)) &&
+ (aim_ssi_waitingforauth(&od->ssi.local, gname, name))) {
return "not-authorized";
}
}
@@ -4702,8 +4702,8 @@ char *oscar_status_text(PurpleBuddy *b)
if ((od != NULL) && !purple_presence_is_online(presence))
{
const char *name = purple_buddy_get_name(b);
- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
- if (aim_ssi_waitingforauth(od->ssi.local, gname, name))
+ char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name);
+ if (aim_ssi_waitingforauth(&od->ssi.local, gname, name))
ret = g_strdup(_("Not Authorized"));
else
ret = g_strdup(_("Offline"));
@@ -4946,7 +4946,7 @@ static void oscar_buddycb_edit_comment(P
data = g_new(struct name_data, 1);
- comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name);
+ comment = aim_ssi_getcomment(&od->ssi.local, purple_group_get_name(g), name);
comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL;
data->gc = gc;
@@ -5161,8 +5161,8 @@ oscar_buddy_menu(PurpleBuddy *buddy) {
* waiting for authorization.
*/
char *gname;
- gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname);
- if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname))
+ gname = aim_ssi_itemlist_findparentname(&od->ssi.local, bname);
+ if (gname && aim_ssi_waitingforauth(&od->ssi.local, gname, bname))
{
act = purple_menu_action_new(_("Re-request Authorization"),
PURPLE_CALLBACK(oscar_auth_sendrequest_menu),
@@ -5313,7 +5313,7 @@ static void oscar_show_awaitingauth(Purp
buddy = cur->data;
bname = purple_buddy_get_name(buddy);
gname = purple_group_get_name(purple_buddy_get_group(buddy));
- if (aim_ssi_waitingforauth(od->ssi.local, gname, bname)) {
+ if (aim_ssi_waitingforauth(&od->ssi.local, gname, bname)) {
filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
}
}
============================================================
--- libpurple/protocols/oscar/family_feedbag.c ae1f1a5c598f4bc3377ff17e61d18b94eb7a52cb
+++ libpurple/protocols/oscar/family_feedbag.c 74378bf838defb8fc685afc880bb4c848d62f0bd
@@ -21,9 +21,9 @@
/*
* Family 0x0013 - Server-Side/Stored Information.
*
- * Relatively new facility that allows certain types of information, such as
- * a user's buddy list, permit/deny list, and permit/deny preferences, to be
- * stored on the server, so that they can be accessed from any client.
+ * Deals with storing certain types of information, such as a user's buddy
+ * list, permit/deny list, and permit/deny preferences, on the server, so
+ * that they can be accessed from any client.
*
* We keep 2 copies of SSI data:
* 1) An exact copy of what is stored on the AIM servers.
@@ -40,14 +40,41 @@
*
* This is entirely too complicated.
* You don't know the half of it.
- *
*/
#include "oscar.h"
+#include "oscarcommon.h"
#include "debug.h"
static int aim_ssi_addmoddel(OscarData *od);
+static void aim_ssi_item_free(struct aim_ssi_item *item)
+{
+ g_free(item->name);
+ aim_tlvlist_free(item->data);
+ g_free(item);
+}
+
+static void aim_ssi_item_set_name(struct aim_ssi_itemlist *list, struct aim_ssi_item *item, const char *name)
+{
+ gchar key[3000];
+
+ if (item->name) {
+ /* Remove old name from hash table */
+ snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name));
+ g_hash_table_remove(list->idx_all_named_items, key);
+ }
+
+ g_free(item->name);
+ item->name = g_strdup(name);
+
+ if (name) {
+ /* Add new name to hash table */
+ snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name));
+ g_hash_table_insert(list->idx_all_named_items, g_strdup(key), item);
+ }
+}
+
/**
* List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org)
* and http://iserverd.khstu.ru/oscar/ssi_item.html
@@ -112,7 +139,7 @@ static void
* @return Return a pointer to the modified item.
*/
static void
-aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
+aim_ssi_itemlist_rebuildgroup(struct aim_ssi_itemlist *list, const char *name)
{
int newlen;
struct aim_ssi_item *cur, *group;
@@ -124,11 +151,11 @@ aim_ssi_itemlist_rebuildgroup(struct aim
/* Find the length for the new additional data */
newlen = 0;
if (group->gid == 0x0000) {
- for (cur=list; cur; cur=cur->next)
+ for (cur=list->data; cur; cur=cur->next)
if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
newlen += 2;
} else {
- for (cur=list; cur; cur=cur->next)
+ for (cur=list->data; cur; cur=cur->next)
if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
newlen += 2;
}
@@ -137,14 +164,14 @@ aim_ssi_itemlist_rebuildgroup(struct aim
if (newlen > 0) {
guint8 *newdata;
- newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8));
+ newdata = g_new(guint8, newlen);
newlen = 0;
if (group->gid == 0x0000) {
- for (cur=list; cur; cur=cur->next)
+ for (cur=list->data; cur; cur=cur->next)
if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
newlen += aimutil_put16(newdata+newlen, cur->gid);
} else {
- for (cur=list; cur; cur=cur->next)
+ for (cur=list->data; cur; cur=cur->next)
if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
newlen += aimutil_put16(newdata+newlen, cur->bid);
}
@@ -166,16 +193,13 @@ aim_ssi_itemlist_rebuildgroup(struct aim
* @param data The additional data for the new item.
* @return A pointer to the newly created item.
*/
-static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
+static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_itemlist *list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
{
gboolean exists;
struct aim_ssi_item *cur, *new;
- new = g_new(struct aim_ssi_item, 1);
+ new = g_new0(struct aim_ssi_item, 1);
- /* Set the name */
- new->name = g_strdup(name);
-
/* Set the group ID# and buddy ID# */
new->gid = gid;
new->bid = bid;
@@ -184,7 +208,7 @@ static struct aim_ssi_item *aim_ssi_item
do {
new->gid += 0x0001;
exists = FALSE;
- for (cur = *list; cur != NULL; cur = cur->next)
+ for (cur = list->data; cur != NULL; cur = cur->next)
if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) {
exists = TRUE;
break;
@@ -201,7 +225,7 @@ static struct aim_ssi_item *aim_ssi_item
do {
new->bid += 0x0001;
exists = FALSE;
- for (cur = *list; cur != NULL; cur = cur->next)
+ for (cur = list->data; cur != NULL; cur = cur->next)
if (cur->bid == new->bid || cur->gid == new->bid) {
exists = TRUE;
break;
@@ -213,7 +237,7 @@ static struct aim_ssi_item *aim_ssi_item
do {
new->bid += 0x0001;
exists = FALSE;
- for (cur = *list; cur != NULL; cur = cur->next)
+ for (cur = list->data; cur != NULL; cur = cur->next)
if (cur->bid == new->bid && cur->gid == new->gid) {
exists = TRUE;
break;
@@ -225,23 +249,29 @@ static struct aim_ssi_item *aim_ssi_item
/* Set the type */
new->type = type;
+ /* Add it to the gid+bid hashtable */
+ g_hash_table_insert(list->idx_gid_bid, GINT_TO_POINTER((new->gid << 16) + new->bid), new);
+
+ /* Set the name - do this *AFTER* setting the type because type is used for the key */
+ aim_ssi_item_set_name(list, new, name);
+
/* Set the TLV list */
new->data = aim_tlvlist_copy(data);
/* Add the item to the list in the correct numerical position. Fancy, eh? */
- if (*list) {
- if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
- new->next = *list;
- *list = new;
+ if (list->data) {
+ if ((new->gid < list->data->gid) || ((new->gid == list->data->gid) && (new->bid < list->data->bid))) {
+ new->next = list->data;
+ list->data = new;
} else {
struct aim_ssi_item *prev;
- for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
+ for ((prev=list->data, cur=list->data->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
new->next = prev->next;
prev->next = new;
}
} else {
- new->next = *list;
- *list = new;
+ new->next = list->data;
+ list->data = new;
}
return new;
@@ -254,25 +284,31 @@ static struct aim_ssi_item *aim_ssi_item
* @param del A pointer to the item you want to remove from the list.
* @return Return 0 if no errors, otherwise return the error number.
*/
-static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
+static int aim_ssi_itemlist_del(struct aim_ssi_itemlist *list, struct aim_ssi_item *del)
{
- if (!(*list) || !del)
+ gchar key[3000];
+
+ if (!(list->data) || !del)
return -EINVAL;
/* Remove the item from the list */
- if (*list == del) {
- *list = (*list)->next;
+ if (list->data == del) {
+ list->data = list->data->next;
} else {
struct aim_ssi_item *cur;
- for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
+ for (cur=list->data; (cur->next && (cur->next!=del)); cur=cur->next);
if (cur->next)
cur->next = del->next;
}
+ /* Remove from the hashtables */
+ g_hash_table_remove(list->idx_gid_bid, GINT_TO_POINTER((del->gid << 16) + del->bid));
+
+ snprintf(key, sizeof(key), "%hx%s", del->type, oscar_normalize(NULL, del->name));
+ g_hash_table_remove(list->idx_all_named_items, key);
+
/* Free the removed item */
- g_free(del->name);
- aim_tlvlist_free(del->data);
- g_free(del);
+ aim_ssi_item_free(del);
return 0;
}
@@ -319,10 +355,10 @@ static int aim_ssi_itemlist_cmp(struct a
return 0;
}
-static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
+static gboolean aim_ssi_itemlist_valid(struct aim_ssi_itemlist *list, struct aim_ssi_item *item)
{
struct aim_ssi_item *cur;
- for (cur=list; cur; cur=cur->next)
+ for (cur=list->data; cur; cur=cur->next)
if (cur == item)
return TRUE;
return FALSE;
@@ -336,13 +372,10 @@ static gboolean aim_ssi_itemlist_valid(s
* @param bid The buddy ID# of the desired item.
* @return Return a pointer to the item if found, else return NULL;
*/
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid)
+struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid)
{
- struct aim_ssi_item *cur;
- for (cur=list; cur; cur=cur->next)
- if ((cur->gid == gid) && (cur->bid == bid))
- return cur;
- return NULL;
+ guint32 id_key = (gid << 16) + bid;
+ return g_hash_table_lookup(list->idx_gid_bid, GINT_TO_POINTER(id_key));
}
/**
@@ -355,37 +388,30 @@ struct aim_ssi_item *aim_ssi_itemlist_fi
* @param type The type of the desired item.
* @return Return a pointer to the item if found, else return NULL.
*/
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type)
+struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type)
{
struct aim_ssi_item *cur;
- if (!list)
+ gchar key[3000];
+
+ if (!list->data)
return NULL;
if (gn && bn) { /* For finding buddies in groups */
- for (cur=list; cur; cur=cur->next)
+ g_return_val_if_fail(type == AIM_SSI_TYPE_BUDDY, NULL);
+ for (cur=list->data; cur; cur=cur->next)
if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
struct aim_ssi_item *curg;
- for (curg=list; curg; curg=curg->next)
+ for (curg=list->data; curg; curg=curg->next)
if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(oscar_util_name_compare(curg->name, gn)))
return cur;
}
- } else if (gn) { /* For finding groups */
- for (cur=list; cur; cur=cur->next) {
- if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(oscar_util_name_compare(cur->name, gn))) {
- return cur;
- }
- }
+ } else if (gn || bn) { /* For finding groups, permits, denies and ignores */
+ snprintf(key, sizeof(key), "%hx%s", type, oscar_normalize(NULL, gn ? gn : bn));
+ return g_hash_table_lookup(list->idx_all_named_items, key);
- } else if (bn) { /* For finding permits, denies, and ignores */
- for (cur=list; cur; cur=cur->next) {
- if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
- return cur;
- }
- }
-
/* For stuff without names--permit deny setting, visibility mask, etc. */
- } else for (cur=list; cur; cur=cur->next) {
+ } else for (cur=list->data; cur; cur=cur->next) {
if ((cur->type == type) && (!cur->name))
return cur;
}
@@ -400,7 +426,7 @@ struct aim_ssi_item *aim_ssi_itemlist_fi
* @param bn The group name of the desired item.
* @return Return a pointer to the name of the item if found, else return NULL;
*/
-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn)
+struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn)
{
if (!bn)
return NULL;
@@ -414,10 +440,10 @@ struct aim_ssi_item *aim_ssi_itemlist_ex
* @param bn The buddy name of the desired item.
* @return Return a pointer to the name of the item if found, else return NULL;
*/
-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn)
+char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn)
{
struct aim_ssi_item *cur, *curg;
- if (!list || !bn)
+ if (!list->data || !bn)
return NULL;
if (!(cur = aim_ssi_itemlist_exists(list, bn)))
return NULL;
@@ -432,7 +458,7 @@ char *aim_ssi_itemlist_findparentname(st
* @param list A pointer to the current list of items.
* @return Return the current SSI permit deny setting, or 0 if no setting was found.
*/
-int aim_ssi_getpermdeny(struct aim_ssi_item *list)
+int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list)
{
struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
if (cur) {
@@ -450,7 +476,7 @@ int aim_ssi_getpermdeny(struct aim_ssi_i
* @param list A pointer to the current list of items.
* @return Return the current set of preferences.
*/
-guint32 aim_ssi_getpresence(struct aim_ssi_item *list)
+guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list)
{
struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
if (cur) {
@@ -471,17 +497,23 @@ guint32 aim_ssi_getpresence(struct aim_s
* alias, or NULL if the buddy has no alias. You should free
* this returned value!
*/
-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn)
+char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
{
- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
- if (cur) {
- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
- if (tlv && tlv->length)
- return g_strndup((const gchar *)tlv->value, tlv->length);
+ struct aim_ssi_item *item = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
+ if (item) {
+ return aim_ssi_getalias_from_item(item);
}
return NULL;
}
+char *aim_ssi_getalias_from_item(struct aim_ssi_item *item)
+{
+ aim_tlv_t *tlv = aim_tlv_gettlv(item->data, 0x0131, 1);
+ if (tlv && tlv->length)
+ return g_strndup((const gchar *)tlv->value, tlv->length);
+ return NULL;
+}
+
/**
* Locally find the comment of the given buddy.
*
@@ -492,7 +524,7 @@ char *aim_ssi_getalias(struct aim_ssi_it
* comment, or NULL if the buddy has no comment. You should free
* this returned value!
*/
-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn)
+char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
{
struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
if (cur) {
@@ -512,7 +544,7 @@ char *aim_ssi_getcomment(struct aim_ssi_
* @param bn The name of the buddy.
* @return 1 if you are waiting for authorization; 0 if you are not
*/
-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn)
+gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn)
{
struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
if (cur) {
@@ -560,8 +592,8 @@ static int aim_ssi_sync(OscarData *od)
/* Deletions */
if (!od->ssi.pending) {
- for (cur1=od->ssi.official; cur1 && (n < 15); cur1=cur1->next) {
- if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) {
+ for (cur1=od->ssi.official.data; cur1 && (n < 15); cur1=cur1->next) {
+ if (!aim_ssi_itemlist_find(&od->ssi.local, cur1->gid, cur1->bid)) {
n++;
new = g_new(struct aim_ssi_tmp, 1);
new->action = SNAC_SUBTYPE_FEEDBAG_DEL;
@@ -574,15 +606,15 @@ static int aim_ssi_sync(OscarData *od)
cur->next = new;
} else
od->ssi.pending = new;
- aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
+ aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
}
}
}
/* Additions */
if (!od->ssi.pending) {
- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
- if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) {
+ for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) {
+ if (!aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid)) {
n++;
new = g_new(struct aim_ssi_tmp, 1);
new->action = SNAC_SUBTYPE_FEEDBAG_ADD;
@@ -595,15 +627,15 @@ static int aim_ssi_sync(OscarData *od)
cur->next = new;
} else
od->ssi.pending = new;
- aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
+ aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
}
}
}
/* Modifications */
if (!od->ssi.pending) {
- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
- cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid);
+ for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) {
+ cur2 = aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid);
if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
n++;
new = g_new(struct aim_ssi_tmp, 1);
@@ -617,15 +649,15 @@ static int aim_ssi_sync(OscarData *od)
cur->next = new;
} else
od->ssi.pending = new;
- aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
+ aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
}
}
}
if (debugstr->len > 0) {
purple_debug_info("oscar", "%s", debugstr->str);
if (purple_debug_is_verbose()) {
- g_string_truncate(debugstr, 0);
- for (cur1 = od->ssi.local; cur1; cur1 = cur1->next)
+ g_string_truncate(debugstr, 0);
+ for (cur1 = od->ssi.local.data; cur1; cur1 = cur1->next)
aim_ssi_item_debug_append(debugstr, "\t", cur1);
purple_debug_misc("oscar", "Dumping item list of account %s:\n%s",
purple_connection_get_account(od->gc)->username, debugstr->str);
@@ -672,22 +704,18 @@ aim_ssi_freelist(OscarData *od)
struct aim_ssi_item *cur, *del;
struct aim_ssi_tmp *curtmp, *deltmp;
- cur = od->ssi.official;
+ cur = od->ssi.official.data;
while (cur) {
del = cur;
cur = cur->next;
- g_free(del->name);
- aim_tlvlist_free(del->data);
- g_free(del);
+ aim_ssi_item_free(del);
}
- cur = od->ssi.local;
+ cur = od->ssi.local.data;
while (cur) {
del = cur;
cur = cur->next;
- g_free(del->name);
- aim_tlvlist_free(del->data);
- g_free(del);
+ aim_ssi_item_free(del);
}
curtmp = od->ssi.pending;
@@ -698,8 +726,8 @@ aim_ssi_freelist(OscarData *od)
}
od->ssi.numitems = 0;
- od->ssi.official = NULL;
- od->ssi.local = NULL;
+ od->ssi.official.data = NULL;
+ od->ssi.local.data = NULL;
od->ssi.pending = NULL;
od->ssi.timestamp = (time_t)0;
}
@@ -725,7 +753,7 @@ int aim_ssi_cleanlist(OscarData *od)
/* DESTROY any buddies that are directly in the master group. */
/* Do the same for buddies that are in a non-existant group. */
/* This will kind of mess up if you hit the item limit, but this function isn't too critical */
- cur = od->ssi.local;
+ cur = od->ssi.local.data;
while (cur) {
next = cur->next;
if (!cur->name) {
@@ -733,8 +761,8 @@ int aim_ssi_cleanlist(OscarData *od)
aim_ssi_delbuddy(od, NULL, NULL);
else if (cur->type == AIM_SSI_TYPE_PERMIT || cur->type == AIM_SSI_TYPE_DENY || cur->type == AIM_SSI_TYPE_ICQDENY)
aim_ssi_del_from_private_list(od, NULL, cur->type);
- } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) {
- char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name);
+ } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(&od->ssi.local, cur->gid, 0x0000)))) {
+ char *alias = aim_ssi_getalias(&od->ssi.local, NULL, cur->name);
aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
aim_ssi_delbuddy(od, cur->name, NULL);
g_free(alias);
@@ -743,7 +771,7 @@ int aim_ssi_cleanlist(OscarData *od)
}
/* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
- cur = od->ssi.local;
+ cur = od->ssi.local.data;
while (cur) {
if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY))
{
@@ -784,16 +812,16 @@ int aim_ssi_addbuddy(OscarData *od, cons
return -EINVAL;
/* Find the parent */
- if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
+ if (!(parent = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
/* Find the parent's parent (the master group) */
- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+ 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);
/* Add the parent */
parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
/* Modify the parent's parent (the master group) */
- aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL);
+ aim_ssi_itemlist_rebuildgroup(&od->ssi.local, NULL);
}
/* Create a TLV list for the new buddy */
@@ -811,7 +839,7 @@ int aim_ssi_addbuddy(OscarData *od, cons
aim_tlvlist_free(data);
/* Modify the parent group */
- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+ aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
/* Sync our local list with the server list */
return aim_ssi_sync(od);
@@ -823,7 +851,7 @@ aim_ssi_add_to_private_list(OscarData *o
if (!od || !name || !od->ssi.received_data)
return -EINVAL;
- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+ 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, name, 0x0000, 0xFFFF, list_type, NULL);
@@ -838,7 +866,7 @@ aim_ssi_del_from_private_list(OscarData*
if (!od)
return -EINVAL;
- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, list_type)))
+ if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, name, list_type)))
return -EINVAL;
aim_ssi_itemlist_del(&od->ssi.local, del);
@@ -861,14 +889,14 @@ int aim_ssi_delbuddy(OscarData *od, cons
return -EINVAL;
/* Find the buddy */
- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
+ if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
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);
+ aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
/* Sync our local list with the server list */
return aim_ssi_sync(od);
@@ -890,7 +918,7 @@ int aim_ssi_delgroup(OscarData *od, cons
return -EINVAL;
/* Find the group */
- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
+ if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
return -EINVAL;
/* Don't delete the group if it's not empty */
@@ -902,7 +930,7 @@ int aim_ssi_delgroup(OscarData *od, cons
aim_ssi_itemlist_del(&od->ssi.local, del);
/* Modify the parent group */
- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+ aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group);
/* Sync our local list with the server list */
return aim_ssi_sync(od);
@@ -924,7 +952,7 @@ int aim_ssi_movebuddy(OscarData *od, con
GSList *data;
/* Find the buddy */
- buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
+ buddy = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
if (buddy == NULL)
return -EINVAL;
@@ -957,7 +985,7 @@ int aim_ssi_aliasbuddy(OscarData *od, co
if (!od || !gn || !bn)
return -EINVAL;
- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+ if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
return -EINVAL;
/* Either add or remove the 0x0131 TLV from the TLV chain */
@@ -987,7 +1015,7 @@ int aim_ssi_editcomment(OscarData *od, c
if (!od || !gn || !bn)
return -EINVAL;
- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+ if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
return -EINVAL;
/* Either add or remove the 0x0131 TLV from the TLV chain */
@@ -1015,11 +1043,10 @@ int aim_ssi_rename_group(OscarData *od,
if (!od || !oldgn || !newgn)
return -EINVAL;
- if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
+ if (!(group = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
return -EINVAL;
- g_free(group->name);
- group->name = g_strdup(newgn);
+ aim_ssi_item_set_name(&od->ssi.local, group, newgn);
/* Sync our local list with the server list */
return aim_ssi_sync(od);
@@ -1046,9 +1073,9 @@ int aim_ssi_setpermdeny(OscarData *od, g
return -EINVAL;
/* Find the PDINFO item, or add it if it does not exist */
- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
+ if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
/* Make sure the master group exists */
- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+ 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);
tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
@@ -1078,9 +1105,9 @@ int aim_ssi_seticon(OscarData *od, const
return -EINVAL;
/* Find the ICONINFO item, or add it if it does not exist */
- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
+ if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
/* Make sure the master group exists */
- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+ 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);
tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL);
@@ -1138,9 +1165,9 @@ int aim_ssi_setpresence(OscarData *od, g
return -EINVAL;
/* Find the PRESENCEPREFS item, or add it if it does not exist */
- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
+ if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
/* Make sure the master group exists */
- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+ 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);
tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
@@ -1265,7 +1292,7 @@ static int parsedata(OscarData *od, Flap
if (!(snac->flags & 0x0001)) {
/* Make a copy of the list */
struct aim_ssi_item *cur;
- for (cur=od->ssi.official; cur; cur=cur->next)
+ for (cur=od->ssi.official.data; cur; cur=cur->next)
aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
od->ssi.received_data = TRUE;
@@ -1415,18 +1442,16 @@ static int parsemod(OscarData *od, FlapC
data = NULL;
/* Replace the 2 local items with the given one */
- if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) {
+ if ((item = aim_ssi_itemlist_find(&od->ssi.local, gid, bid))) {
item->type = type;
- g_free(item->name);
- item->name = g_strdup(name);
+ aim_ssi_item_set_name(&od->ssi.local, item, name);
aim_tlvlist_free(item->data);
item->data = aim_tlvlist_copy(data);
}
- if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) {
+ if ((item = aim_ssi_itemlist_find(&od->ssi.official, gid, bid))) {
item->type = type;
- g_free(item->name);
- item->name = g_strdup(name);
+ aim_ssi_item_set_name(&od->ssi.official, item, name);
aim_tlvlist_free(item->data);
item->data = aim_tlvlist_copy(data);
}
@@ -1460,9 +1485,9 @@ static int parsedel(OscarData *od, FlapC
byte_stream_get16(bs);
byte_stream_advance(bs, byte_stream_get16(bs));
- if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid)))
+ if ((del = aim_ssi_itemlist_find(&od->ssi.local, gid, bid)))
aim_ssi_itemlist_del(&od->ssi.local, del);
- if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid)))
+ if ((del = aim_ssi_itemlist_find(&od->ssi.official, gid, bid)))
aim_ssi_itemlist_del(&od->ssi.official, del);
if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
@@ -1503,7 +1528,8 @@ static int parseack(OscarData *od, FlapC
if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
/* Remove the item from the local list */
/* Make sure cur->item is still valid memory */
- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+ /* TODO: "Still valid memory"? That's bad form. */
+ if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
cur->name = g_strdup(cur->item->name);
aim_ssi_itemlist_del(&od->ssi.local, cur->item);
}
@@ -1511,11 +1537,10 @@ static int parseack(OscarData *od, FlapC
} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
/* Replace the local item with the item from the official list */
- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+ if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
struct aim_ssi_item *cur1;
- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
- g_free(cur->item->name);
- cur->item->name = g_strdup(cur1->name);
+ if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) {
+ aim_ssi_item_set_name(&od->ssi.official, cur->item, cur1->name);
aim_tlvlist_free(cur->item->data);
cur->item->data = aim_tlvlist_copy(cur1->data);
}
@@ -1524,7 +1549,7 @@ static int parseack(OscarData *od, FlapC
} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
/* Add the item back into the local list */
- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) {
+ if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item)) {
aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
} else
cur->item = NULL;
@@ -1534,18 +1559,17 @@ static int parseack(OscarData *od, FlapC
/* Do the exact opposite */
if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
/* Add the local item to the official list */
- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+ if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
} else
cur->item = NULL;
} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
/* Replace the official item with the item from the local list */
- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+ if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) {
struct aim_ssi_item *cur1;
- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
- g_free(cur1->name);
- cur1->name = g_strdup(cur->item->name);
+ if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) {
+ aim_ssi_item_set_name(&od->ssi.official, cur1, cur->item->name);
aim_tlvlist_free(cur1->data);
cur1->data = aim_tlvlist_copy(cur->item->data);
}
@@ -1554,7 +1578,7 @@ static int parseack(OscarData *od, FlapC
} else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
/* Remove the item from the official list */
- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item))
+ if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item))
aim_ssi_itemlist_del(&od->ssi.official, cur->item);
cur->item = NULL;
}
============================================================
--- libpurple/protocols/oscar/oscar.h d6e887f2bc0553a3f5073447e4b27ec3adf887b4
+++ libpurple/protocols/oscar/oscar.h 21107927445c4a3903611fd13f3946c70d8bade1
@@ -308,9 +308,14 @@ struct _IcbmCookie
#include "peer.h"
-/*
- * AIM Session: The main client-data interface.
- *
+struct aim_ssi_itemlist {
+ struct aim_ssi_item *data;
+ GHashTable *idx_gid_bid;
+ GHashTable *idx_all_named_items;
+};
+
+/**
+ * The main client-data interface.
*/
struct _OscarData
{
@@ -387,8 +392,8 @@ struct _OscarData
struct {
gboolean received_data;
guint16 numitems;
- struct aim_ssi_item *official;
- struct aim_ssi_item *local;
+ struct aim_ssi_itemlist official;
+ struct aim_ssi_itemlist local;
struct aim_ssi_tmp *pending;
time_t timestamp;
gboolean waiting_for_ack;
@@ -916,15 +921,16 @@ struct aim_ssi_tmp
/* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, char *bn, guint8 reply, const char *msg);
/* Client functions for retrieving SSI data */
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid);
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type);
-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn);
-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn);
-int aim_ssi_getpermdeny(struct aim_ssi_item *list);
-guint32 aim_ssi_getpresence(struct aim_ssi_item *list);
-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn);
-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn);
-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn);
+struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid);
+struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type);
+struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn);
+char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn);
+int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list);
+guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list);
+char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
+char *aim_ssi_getalias_from_item(struct aim_ssi_item *item);
+char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
+gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn);
/* Client functions for changing SSI data */
int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth);
============================================================
--- libpurple/protocols/oscar/oscar_data.c 9f8e42b1a0c7a2c694546009b916fff2c1339cd6
+++ libpurple/protocols/oscar/oscar_data.c daede9f14f9f372e191a3c64ccc97870d8d59900
@@ -47,6 +47,12 @@ oscar_data_new(void)
od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
od->handlerlist = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
+ od->ssi.local.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal);
+ od->ssi.local.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ od->ssi.official.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal);
+ od->ssi.official.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
/*
* Register all the modules for this session...
*/
@@ -126,6 +132,12 @@ oscar_data_destroy(OscarData *od)
g_hash_table_destroy(od->buddyinfo);
g_hash_table_destroy(od->handlerlist);
+ g_hash_table_destroy(od->ssi.local.idx_gid_bid);
+ g_hash_table_destroy(od->ssi.local.idx_all_named_items);
+
+ g_hash_table_destroy(od->ssi.official.idx_gid_bid);
+ g_hash_table_destroy(od->ssi.official.idx_all_named_items);
+
g_free(od);
}
============================================================
--- libpurple/protocols/oscar/authorization.c 9b453d50f9c436df99b5979bf65538127ad7a61f
+++ libpurple/protocols/oscar/authorization.c 184dea2a8b1ab5f0fe9005b821a1bdbe955a36b7
@@ -51,7 +51,7 @@ oscar_auth_request(struct name_data *dat
purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n",
bname, gname);
aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
+ if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
{
aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
@@ -150,4 +150,4 @@ oscar_auth_recvrequest(PurpleConnection
purple_account_request_authorization(account, data->name, NULL, data->nick,
reason, purple_find_buddy(account, data->name) != NULL,
oscar_auth_grant, oscar_auth_dontgrant_msgprompt, data);
-}
\ No newline at end of file
+}
============================================================
--- libpurple/protocols/oscar/userinfo.c 39fdfe7ec62dd0447aa30fa1f1f671c1cc667c2f
+++ libpurple/protocols/oscar/userinfo.c 35bc296c49fbf1fb65c083a76e96a44f626ae993
@@ -263,8 +263,8 @@ oscar_user_info_append_status(PurpleConn
message = tmp;
}
- } else if (aim_ssi_waitingforauth(od->ssi.local,
- aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
+ } else if (aim_ssi_waitingforauth(&od->ssi.local,
+ aim_ssi_itemlist_findparentname(&od->ssi.local, purple_buddy_get_name(b)),
purple_buddy_get_name(b)))
{
/* Note if an offline buddy is not authorized */
@@ -356,7 +356,7 @@ oscar_user_info_append_extra_info(Purple
}
if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) {
- tmp = aim_ssi_getcomment(od->ssi.local, gname, bname);
+ tmp = aim_ssi_getcomment(&od->ssi.local, gname, bname);
if (tmp != NULL) {
char *tmp2 = g_markup_escape_text(tmp, strlen(tmp));
g_free(tmp);
@@ -543,4 +543,4 @@ oscar_user_info_display_aim(OscarData *o
purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL);
purple_notify_user_info_destroy(user_info);
-}
\ No newline at end of file
+}
============================================================
--- libpurple/protocols/oscar/visibility.c 7d7fc088fd03e15792e8d9d7bef31a92bfd09846
+++ libpurple/protocols/oscar/visibility.c a2448a731e4b17082c8355241f4cd9982f64c832
@@ -51,7 +51,7 @@ is_buddy_on_list(OscarData *od, const ch
static gboolean
is_buddy_on_list(OscarData *od, const char *bname)
{
- return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
+ return aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
}
static void
@@ -102,7 +102,7 @@ show_private_list(PurplePluginAction *ac
buddy = cur->data;
bname = purple_buddy_get_name(buddy);
- if (aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, list_type)) {
+ if (aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, list_type)) {
filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
}
}
More information about the Commits
mailing list