📄 family_feedbag.c
字号:
* additions, then modifications. Also, both the official and the local * list should be in ascending numerical order for the group ID#s and the * buddy ID#s, which makes things more efficient. I think. */ /* 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)) { n++; new = (struct aim_ssi_tmp *)g_malloc(sizeof(struct aim_ssi_tmp)); new->action = SNAC_SUBTYPE_FEEDBAG_ADD; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; if (od->ssi.pending) { for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else od->ssi.pending = new; } } } /* 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)) { n++; new = (struct aim_ssi_tmp *)g_malloc(sizeof(struct aim_ssi_tmp)); new->action = SNAC_SUBTYPE_FEEDBAG_DEL; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; if (od->ssi.pending) { for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else od->ssi.pending = new; } } } /* 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); if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) { n++; new = (struct aim_ssi_tmp *)g_malloc(sizeof(struct aim_ssi_tmp)); new->action = SNAC_SUBTYPE_FEEDBAG_MOD; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; if (od->ssi.pending) { for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else od->ssi.pending = new; } } } /* We're out of stuff to do, so tell the AIM servers we're done and exit */ if (!od->ssi.pending) { if (od->ssi.in_transaction) { aim_ssi_modend(od); od->ssi.in_transaction = FALSE; } return 0; } /* If this is the first in a series of add/mod/del * requests then send the "begin transaction" message. */ if (!od->ssi.in_transaction) { aim_ssi_modbegin(od); od->ssi.in_transaction = TRUE; } /* Make sure we don't send anything else between now * and when we receive the ack for the following operation */ od->ssi.waiting_for_ack = TRUE; /* Now go mail off our data and wait 4 to 6 weeks */ return aim_ssi_addmoddel(od);;}/** * Free all SSI data. * * This doesn't remove it from the server, that's different. * * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */static voidaim_ssi_freelist(OscarData *od){ struct aim_ssi_item *cur, *del; struct aim_ssi_tmp *curtmp, *deltmp; cur = od->ssi.official; while (cur) { del = cur; cur = cur->next; g_free(del->name); aim_tlvlist_free(del->data); g_free(del); } cur = od->ssi.local; while (cur) { del = cur; cur = cur->next; g_free(del->name); aim_tlvlist_free(del->data); g_free(del); } curtmp = od->ssi.pending; while (curtmp) { deltmp = curtmp; curtmp = curtmp->next; g_free(deltmp); } od->ssi.numitems = 0; od->ssi.official = NULL; od->ssi.local = NULL; od->ssi.pending = NULL; od->ssi.timestamp = (time_t)0;}/** * This "cleans" the ssi list. It does the following: * 1) Makes sure all buddies, permits, and denies have names. * 2) Makes sure that all buddies are in a group that exist. * 3) Deletes any empty groups * * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_cleanlist(OscarData *od){ struct aim_ssi_item *cur, *next; if (!od) return -EINVAL; /* Delete any buddies, permits, or denies with empty names. */ /* If there are any buddies directly in the master group, add them to a real group. */ /* 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; while (cur) { next = cur->next; if (!cur->name) { if (cur->type == AIM_SSI_TYPE_BUDDY) aim_ssi_delbuddy(od, NULL, NULL); else if (cur->type == AIM_SSI_TYPE_PERMIT) aim_ssi_delpermit(od, NULL); else if (cur->type == AIM_SSI_TYPE_DENY) aim_ssi_deldeny(od, NULL); } 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); } cur = next; } /* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */ cur = od->ssi.local; while (cur) { if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY)) { struct aim_ssi_item *cur2, *next2; cur2 = cur->next; while (cur2) { next2 = cur2->next; if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!aim_sncmp(cur->name, cur2->name))) { aim_ssi_itemlist_del(&od->ssi.local, cur2); } cur2 = next2; } } 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); /* If we've made any changes then sync our list with the server's */ return aim_ssi_sync(od);}/** * Add a buddy to the list. * * @param od The oscar odion. * @param name The name of the item. * @param group The group of the item. * @param data A TLV list to use as the additional data for this item. * @param alias The alias/nickname of the item, or NULL. * @param comment The buddy comment for the item, or NULL. * @param smsnum The locally assigned SMS number, or NULL. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *data, const char *alias, const char *comment, const char *smsnum, gboolean needauth){ struct aim_ssi_item *parent; if (!od || !name || !group) return -EINVAL; /* Find the parent */ 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) 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); } /* Create a TLV list for the new buddy */ if (needauth) aim_tlvlist_add_noval(&data, 0x0066); if (alias != NULL) aim_tlvlist_add_str(&data, 0x0131, alias); if (smsnum != NULL) aim_tlvlist_add_str(&data, 0x013a, smsnum); if (comment != NULL) aim_tlvlist_add_str(&data, 0x013c, comment); /* Add that bad boy */ aim_ssi_itemlist_add(&od->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data); aim_tlvlist_free(data); /* 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);}/** * Add a permit buddy to the list. * * @param od The oscar odion. * @param name The name of the item.. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_addpermit(OscarData *od, const char *name){ 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); /* Add that bad boy */ aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Add a deny buddy to the list. * * @param od The oscar odion. * @param name The name of the item.. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_adddeny(OscarData *od, const char *name){ 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); /* Add that bad boy */ aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Deletes a buddy from the list. * * @param od The oscar odion. * @param name The name of the item, or NULL. * @param group The group of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group){ struct aim_ssi_item *del; if (!od) return -EINVAL; /* Find the 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); /* 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); /* Modify the parent group */ aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL); /* 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); } } /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Deletes a permit buddy from the list. * * @param od The oscar odion. * @param name The name of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_delpermit(OscarData *od, const char *name){ 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_PERMIT))) return -EINVAL; /* Remove the item from the list */ aim_ssi_itemlist_del(&od->ssi.local, del); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Deletes a deny buddy from the list. * * @param od The oscar odion. * @param name The name of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_deldeny(OscarData *od, const char *name){ 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))) return -EINVAL; /* Remove the item from the list */ aim_ssi_itemlist_del(&od->ssi.local, del); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Move a buddy from one group to another group. This basically just deletes the * buddy and re-adds it. * * @param od The oscar odion. * @param oldgn The group that the buddy is currently in. * @param newgn The group that the buddy should be moved in to. * @param sn The name of the buddy to be moved. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn){ struct aim_ssi_item *buddy; GSList *data; /* Find the buddy */ buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, sn, AIM_SSI_TYPE_BUDDY); if (buddy == NULL) return -EINVAL; /* Make a copy of the buddy's TLV list */ data = aim_tlvlist_copy(buddy->data); /* Delete the old item */ aim_ssi_delbuddy(od, sn, oldgn); /* Add the new item using the EXACT SAME TLV list */ aim_ssi_addbuddy(od, sn, newgn, data, NULL, NULL, NULL, FALSE); return 0;}/** * Change the alias stored on the server for a given buddy. * * @param od The oscar odion. * @param gn The group that the buddy is currently in. * @param sn The screen name of the buddy. * @param alias The new alias for the buddy, or NULL if you want to remove * a buddy's comment. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *sn, const char *alias){ struct aim_ssi_item *tmp; if (!od || !gn || !sn) return -EINVAL; if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ if ((alias != NULL) && (strlen(alias) > 0)) aim_tlvlist_replace_str(&tmp->data, 0x0131, alias); else aim_tlvlist_remove(&tmp->data, 0x0131); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Change the comment stored on the server for a given buddy. * * @param od The oscar odion. * @param gn The group that the buddy is currently in. * @param sn The screen name of the buddy. * @param alias The new comment for the buddy, or NULL if you want to remove * a buddy's comment. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_editcomment(OscarData *od, const char *gn, const char *sn, const char *comment){ struct aim_ssi_item *tmp; if (!od || !gn || !sn) return -EINVAL; if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ if ((comment != NULL) && (strlen(comment) > 0)) aim_tlvlist_replace_str(&tmp->data, 0x013c, comment); else aim_tlvlist_remove(&tmp->data, 0x013c); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Rename a group.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -