📄 family_feedbag.c
字号:
* * @param od The oscar odion. * @param oldgn The old group name. * @param newgn The new group name. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn){ struct aim_ssi_item *group; if (!od || !oldgn || !newgn) return -EINVAL; if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) return -EINVAL; g_free(group->name); group->name = (char *)g_malloc((strlen(newgn)+1)*sizeof(char)); strcpy(group->name, newgn); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Stores your permit/deny setting on the server, and starts using it. * * @param od The oscar odion. * @param permdeny Your permit/deny setting. Can be one of the following: * 1 - Allow all users * 2 - Block all users * 3 - Allow only the users below * 4 - Block only the users below * 5 - Allow only users on my buddy list * @param vismask A bitmask of the class of users to whom you want to be * visible. See the AIM_FLAG_BLEH #defines in oscar.h * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny, guint32 vismask){ struct aim_ssi_item *tmp; if (!od || !od->ssi.received_data) 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))) { /* 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); tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL); } /* Need to add the 0x00ca TLV to the TLV chain */ aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny); /* Need to add the 0x00cb TLV to the TLV chain */ aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/** * Set buddy icon information * * @param od The oscar odion. * @param iconcsum The MD5 checksum of the icon you are using. * @param iconcsumlen Length of the MD5 checksum given above. Should be 0x10 bytes. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen){ struct aim_ssi_item *tmp; guint8 *csumdata; if (!od || !iconsum || !iconsumlen || !od->ssi.received_data) 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))) { /* 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); tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL); } /* Need to add the 0x00d5 TLV to the TLV chain */ csumdata = (guint8 *)g_malloc((iconsumlen+2)*sizeof(guint8)); aimutil_put8(&csumdata[0], 0x00); aimutil_put8(&csumdata[1], iconsumlen); memcpy(&csumdata[2], iconsum, iconsumlen); aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(guint8), csumdata); g_free(csumdata); /* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */ aim_tlvlist_replace_noval(&tmp->data, 0x0131); /* Sync our local list with the server list */ aim_ssi_sync(od); return 0;}/** * Remove a reference to a server stored buddy icon. This will make your * icon stop showing up to other people. * * Really this function just sets the icon to a dummy value. It's weird... * but I think the dummy value basically means "I don't have an icon!" * * @param od The oscar session. * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_delicon(OscarData *od){ const guint8 csumdata[] = {0x02, 0x01, 0xd2, 0x04, 0x72}; return aim_ssi_seticon(od, csumdata, 5);}/** * Stores your setting for various SSI settings. Whether you * should show up as idle or not, etc. * * @param od The oscar odion. * @param presence I think it's a bitmask, but I only know what one of the bits is: * 0x00000002 - Hide wireless? * 0x00000400 - Allow others to see your idle time * @return Return 0 if no errors, otherwise return the error number. */int aim_ssi_setpresence(OscarData *od, guint32 presence) { struct aim_ssi_item *tmp; if (!od || !od->ssi.received_data) 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))) { /* 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); tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL); } /* Need to add the x00c9 TLV to the TLV chain */ aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence); /* Sync our local list with the server list */ return aim_ssi_sync(od);}/* * Subtype 0x0002 - Request SSI Rights. */int aim_ssi_reqrights(OscarData *od){ FlapConnection *conn; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQRIGHTS); return 0;}/* * Subtype 0x0003 - SSI Rights Information. */static int parserights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0, i; aim_rxcallback_t userfunc; GSList *tlvlist; aim_tlv_t *tlv; ByteStream bstream; guint16 *maxitems; /* This SNAC is made up of a bunch of TLVs */ tlvlist = aim_tlvlist_read(bs); /* TLV 0x0004 contains the maximum number of each item */ if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) { aim_tlvlist_free(tlvlist); return 0; } byte_stream_init(&bstream, tlv->value, tlv->length); maxitems = (guint16 *)g_malloc((tlv->length/2)*sizeof(guint16)); for (i=0; i<(tlv->length/2); i++) maxitems[i] = byte_stream_get16(&bstream); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, tlv->length/2, maxitems); aim_tlvlist_free(tlvlist); g_free(maxitems); return ret;}/* * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and * revision number. * */int aim_ssi_reqdata(OscarData *od){ FlapConnection *conn; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; /* Free any current data, just in case */ aim_ssi_freelist(od); aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQDATA); return 0;}/* * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision * number. * * The data will only be sent if it is newer than the posted local * timestamp and revision. * * Note that the client should never increment the revision, only the server. * */int aim_ssi_reqifchanged(OscarData *od, time_t timestamp, guint16 numitems){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; frame = flap_frame_new(od, 0x02, 10+4+2); snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, NULL, 0); aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, snacid); byte_stream_put32(&frame->data, timestamp); byte_stream_put16(&frame->data, numitems); flap_connection_send(conn, frame); /* Free any current data, just in case */ aim_ssi_freelist(od); return 0;}/* * Subtype 0x0006 - SSI Data. */static int parsedata(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; guint8 fmtver; /* guess */ guint16 namelen, gid, bid, type; char *name; GSList *data; fmtver = byte_stream_get8(bs); /* Version of ssi data. Should be 0x00 */ od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */ /* Read in the list */ while (byte_stream_empty(bs) > 4) { /* last four bytes are timestamp */ if ((namelen = byte_stream_get16(bs))) name = byte_stream_getstr(bs, namelen); else name = NULL; gid = byte_stream_get16(bs); bid = byte_stream_get16(bs); type = byte_stream_get16(bs); data = aim_tlvlist_readlen(bs, byte_stream_get16(bs)); aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data); g_free(name); aim_tlvlist_free(data); } /* Read in the timestamp */ od->ssi.timestamp = byte_stream_get32(bs); if (!(snac->flags & 0x0001)) { /* Make a copy of the list */ struct aim_ssi_item *cur; for (cur=od->ssi.official; 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; if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, fmtver, od->ssi.numitems, od->ssi.timestamp); } return ret;}/* * Subtype 0x0007 - SSI Activate Data. * * Should be sent after receiving 13/6 or 13/f to tell the server you * are ready to begin using the list. It will promptly give you the * presence information for everyone in your list and put your permit/deny * settings into effect. * */int aim_ssi_enable(OscarData *od){ FlapConnection *conn; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, 0x0007); return 0;}/* * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s). * * Sends the SNAC to add, modify, or delete items from the server-stored * information. These 3 SNACs all have an identical structure. The only * difference is the subtype that is set for the SNAC. * */static int aim_ssi_addmoddel(OscarData *od){ FlapConnection *conn; FlapFrame *frame; aim_snacid_t snacid; int snaclen; struct aim_ssi_tmp *cur; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !od->ssi.pending || !od->ssi.pending->item) return -EINVAL; /* Calculate total SNAC size */ snaclen = 10; /* For family, subtype, flags, and SNAC ID */ for (cur=od->ssi.pending; cur; cur=cur->next) { snaclen += 10; /* For length, GID, BID, type, and length */ if (cur->item->name) snaclen += strlen(cur->item->name); if (cur->item->data) snaclen += aim_tlvlist_size(cur->item->data); } frame = flap_frame_new(od, 0x02, snaclen); snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, NULL, 0); aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, snacid); for (cur=od->ssi.pending; cur; cur=cur->next) { byte_stream_put16(&frame->data, cur->item->name ? strlen(cur->item->name) : 0); if (cur->item->name) byte_stream_putstr(&frame->data, cur->item->name); byte_stream_put16(&frame->data, cur->item->gid); byte_stream_put16(&frame->data, cur->item->bid); byte_stream_put16(&frame->data, cur->item->type); byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(cur->item->data) : 0); if (cur->item->data) aim_tlvlist_write(&frame->data, &cur->item->data); } flap_connection_send(conn, frame); return 0;}/* * Subtype 0x0008 - Incoming SSI add. * * Sent by the server, for example, when someone is added to * your "Recent Buddies" group. */static int parseadd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; char *name; guint16 len, gid, bid, type; GSList *data; while (byte_stream_empty(bs)) { if ((len = byte_stream_get16(bs))) name = byte_stream_getstr(bs, len); else name = NULL; gid = byte_stream_get16(bs); bid = byte_stream_get16(bs); type = byte_stream_get16(bs); if ((len = byte_stream_get16(bs))) data = aim_tlvlist_readlen(bs, len); else data = NULL; aim_ssi_itemlist_add(&od->ssi.local, name, gid, bid, type, data); aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data); aim_tlvlist_free(data); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, type, name); g_free(name); } return ret;}/* * Subtype 0x0009 - Incoming SSI mod. * * XXX - It would probably be good for the client to actually do something when it gets this. */static int parsemod(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; char *name; guint16 len, gid, bid, type; GSList *data; struct aim_ssi_item *item; while (byte_stream_empty(bs)) { if ((len = byte_stream_get16(bs))) name = byte_stream_getstr(bs, len); else name = NULL; gid = byte_stream_get16(bs); bid = byte_stream_get16(bs); type = byte_stream_get16(bs); if ((len = byte_stream_get16(bs))) data = aim_tlvlist_readlen(bs, len); else data = NULL; /* Replace the 2 local items with the given one */ if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) { item->type = type; g_free(item->name); if (name) { item->name = (char *)g_malloc((strlen(name)+1)*sizeof(char)); strcpy(item->name, name); } else item->name = NULL; aim_tlvlist_free(item->data); item->data = aim_tlvlist_copy(data); } if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) { item->type = type; g_free(item->name); if (name) { item->name = (char *)g_malloc((strlen(name)+1)*sizeof(char)); strcpy(item->name, name); } else item->name = NULL; aim_tlvlist_free(item->data); item->data = aim_tlvlist_copy(data); } if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame); g_free(name); aim_tlvlist_free(data); } return ret;}/* * Subtype 0x000a - Incoming SSI del. * * XXX - It would probably be good for the client to actually do something when it gets this. */static int parsedel(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs){ int ret = 0; aim_rxcallback_t userfunc; guint16 gid, bid; struct aim_ssi_item *del; while (byte_stream_empty(bs)) { byte_stream_advance(bs, byte_stream_get16(bs)); gid = byte_stream_get16(bs); bid = byte_stream_get16(bs); byte_stream_get16(bs); byte_stream_advance(bs, byte_stream_get16(bs));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -