Mercurial > pidgin.yaz
diff libpurple/protocols/oscar/family_feedbag.c @ 32295:dc120ca9f523
propagate from branch 'im.pidgin.pidgin' (head bfb757dfe6b2549ab37a9b19f78f5f1f2f9df0cd)
to branch 'im.pidgin.pidgin.next.major' (head fc195a83f896d038c367b1e92cc1bebd7e8246ab)
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 21 Mar 2011 05:45:22 +0000 |
parents | 0cf50b0f7af4 8d6630912021 |
children | 142429bcb4c8 |
line wrap: on
line diff
--- a/libpurple/protocols/oscar/family_feedbag.c Mon Mar 21 00:11:19 2011 +0000 +++ b/libpurple/protocols/oscar/family_feedbag.c Mon Mar 21 05:45:22 2011 +0000 @@ -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 @@ * @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 @@ /* 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 @@ 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,15 +193,12 @@ * @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); - - /* Set the name */ - new->name = g_strdup(name); + new = g_new0(struct aim_ssi_item, 1); /* Set the group ID# and buddy ID# */ new->gid = gid; @@ -184,7 +208,7 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ * @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 @@ 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 @@ * @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 @@ * @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 (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; - } - } + } 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); /* 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 @@ * @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 @@ * @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 @@ * @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 @@ * @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 @@ * 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 @@ * 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 @@ * @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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ /* 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 @@ 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 @@ } /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ /* 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 @@ } 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; }