📄 ssi.c
字号:
free(group->name); group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char)); strcpy(group->name, newgn); /* Sync our local list with the server list */ aim_ssi_sync(sess); return 0;}/** * Stores your permit/deny setting on the server, and starts using it. * * @param sess The oscar session. * @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 aim.h * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask){ struct aim_ssi_item *tmp; if (!sess) return -EINVAL; /* Find the PDINFO item, or add it if it does not exist */ if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) tmp = aim_ssi_itemlist_add(&sess->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 */ aim_ssi_sync(sess); return 0;}/** * Set buddy icon information * * @param sess The oscar session. * @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. */faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen){ struct aim_ssi_item *tmp; fu8_t *csumdata; if (!sess || !iconsum || !iconsumlen) return -EINVAL; /* Find the ICONINFO item, or add it if it does not exist */ if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL); } /* Need to add the 0x00d5 TLV to the TLV chain */ if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t)))) return -ENOMEM; csumdata[0] = 0x00; csumdata[1] = 0x10; memcpy(&csumdata[2], iconsum, iconsumlen); aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata); 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(sess); return 0;}/** * Remove a reference to a server stored buddy icon. This will make your * icon stop showing up to other people. * * @param sess The oscar session. * @return Return 0 if no errors, otherwise return the error number. */faim_export int aim_ssi_delicon(aim_session_t *sess){ struct aim_ssi_item *tmp; if (!sess) return -EINVAL; /* Find the ICONINFO item and delete it if it exists*/ if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) aim_ssi_itemlist_del(&sess->ssi.local, tmp); /* Sync our local list with the server list */ aim_ssi_sync(sess); return 0;}/** * Stores your setting for various SSI settings. Whether you * should show up as idle or not, etc. * * @param sess The oscar session. * @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. */faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) { struct aim_ssi_item *tmp; if (!sess) return -EINVAL; /* Find the PRESENCEPREFS item, or add it if it does not exist */ if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) tmp = aim_ssi_itemlist_add(&sess->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 */ aim_ssi_sync(sess); return 0;}/* * Subtype 0x0002 - Request SSI Rights. */faim_export int aim_ssi_reqrights(aim_session_t *sess){ aim_conn_t *conn; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL; return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);}/* * Subtype 0x0003 - SSI Rights Information. */static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0, i; aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist; aim_tlv_t *tlv; aim_bstream_t bstream; fu16_t *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; } aim_bstream_init(&bstream, tlv->value, tlv->length); if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) { aim_tlvlist_free(&tlvlist); return 0; } for (i=0; i<(tlv->length/2); i++) maxitems[i] = aimbs_get16(&bstream); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, tlv->length/2, maxitems); aim_tlvlist_free(&tlvlist); free(maxitems); return ret;}/* * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and * revision number. * */faim_export int aim_ssi_reqdata(aim_session_t *sess){ aim_conn_t *conn; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL; /* Free any current data, just in case */ aim_ssi_freelist(sess); return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);}/* * 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. * */faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2))) return -ENOMEM; snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0); aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid); aimbs_put32(&fr->data, timestamp); aimbs_put16(&fr->data, numitems); aim_tx_enqueue(sess, fr); /* Free any current data, just in case */ aim_ssi_freelist(sess); return 0;}/* * Subtype 0x0006 - SSI Data. */static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; fu8_t fmtver; /* guess */ fu16_t namelen, gid, bid, type; char *name; aim_tlvlist_t *data; fmtver = aimbs_get8(bs); /* Version of ssi data. Should be 0x00 */ sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */ /* Read in the list */ while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */ if ((namelen = aimbs_get16(bs))) name = aimbs_getstr(bs, namelen); else name = NULL; gid = aimbs_get16(bs); bid = aimbs_get16(bs); type = aimbs_get16(bs); data = aim_tlvlist_readlen(bs, aimbs_get16(bs)); aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); free(name); aim_tlvlist_free(&data); } /* Read in the timestamp */ sess->ssi.timestamp = aimbs_get32(bs); if (!(snac->flags & 0x0001)) { /* Make a copy of the list */ struct aim_ssi_item *cur; for (cur=sess->ssi.official; cur; cur=cur->next) aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data); sess->ssi.received_data = 1; if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->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. * */faim_export int aim_ssi_enable(aim_session_t *sess){ aim_conn_t *conn; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL; return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);}/* * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s). * * Sends the SNAC to add, modify, or delete an item 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. * */faim_export int aim_ssi_addmoddel(aim_session_t *sess){ aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; int snaclen; struct aim_ssi_tmp *cur; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item) return -EINVAL; /* Calculate total SNAC size */ snaclen = 10; /* For family, subtype, flags, and SNAC ID */ for (cur=sess->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); } if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) return -ENOMEM; snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0); aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid); for (cur=sess->ssi.pending; cur; cur=cur->next) { aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0); if (cur->item->name) aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name)); aimbs_put16(&fr->data, cur->item->gid); aimbs_put16(&fr->data, cur->item->bid); aimbs_put16(&fr->data, cur->item->type); aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0); if (cur->item->data) aim_tlvlist_write(&fr->data, &cur->item->data); } aim_tx_enqueue(sess, fr); 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(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; char *name; fu16_t len, gid, bid, type; aim_tlvlist_t *data; while (aim_bstream_empty(bs)) { if ((len = aimbs_get16(bs))) name = aimbs_getstr(bs, len); else name = NULL; gid = aimbs_get16(bs); bid = aimbs_get16(bs); type = aimbs_get16(bs); if ((len = aimbs_get16(bs))) data = aim_tlvlist_readlen(bs, len); else data = NULL; aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data); aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); aim_tlvlist_free(&data); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, type, name); 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(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; char *name; fu16_t len, gid, bid, type; aim_tlvlist_t *data; struct aim_ssi_item *item; while (aim_bstream_empty(bs)) { if ((len = aimbs_get16(bs))) name = aimbs_getstr(bs, len); else name = NULL; gid = aimbs_get16(bs); bid = aimbs_get16(bs); type = aimbs_get16(bs); if ((len = aimbs_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(sess->ssi.local, gid, bid))) { item->type = type; free(item->name); if (name) { item->name = (char *)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(sess->ssi.official, gid, bid))) { item->type = type; free(item->name); if (name) { item->name = (char *)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(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx); 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(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; fu16_t gid, bid; struct aim_ssi_item *del; while (aim_bstream_empty(bs)) { aim_bstream_advance(bs, aimbs_get16(bs)); gid = aimbs_get16(bs); bid = aimbs_get16(bs); aimbs_get16(bs); aim_bstream_advance(bs, aimbs_get16(bs)); if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) aim_ssi_itemlist_del(&sess->ssi.local, del); if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) aim_ssi_itemlist_del(&sess->ssi.official, del); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -