📄 family_locate.c
字号:
/* * Purple's oscar protocol plugin * This file is the legal property of its developers. * Please see the AUTHORS file distributed alongside this file. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* * Family 0x0002 - Locate. * * The functions here are responsible for requesting and parsing information- * gathering SNACs. Or something like that. This family contains the SNACs * for getting and setting info, away messages, directory profile thingy, etc. */#include "oscar.h"#ifdef _WIN32#include "win32dep.h"#endif/* Define to log unknown TLVs *//* #define LOG_UNKNOWN_TLV *//* * Capability blocks. * * These are CLSIDs. They should actually be of the form: * * {0x0946134b, 0x4c7f, 0x11d1, * {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}}, * * But, eh. */static const struct { guint32 flag; guint8 data[16];} aim_caps[] = { /* * These are in ascending numerical order. */ /* * Perhaps better called OSCAR_CAPABILITY_SHORTCAPS */ {OSCAR_CAPABILITY_ICHAT, {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_SECUREIM, {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_VIDEO, {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* "Live Video" support in Windows AIM 5.5.3501 and newer */ {OSCAR_CAPABILITY_LIVEVIDEO, {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* "Camera" support in Windows AIM 5.5.3501 and newer */ {OSCAR_CAPABILITY_CAMERA, {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In Windows AIM 5.5.3501 and newer */ {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In iChatAV (version numbers...?) */ {OSCAR_CAPABILITY_ICHATAV, {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}}, /* * Not really sure about this one. In an email from * 26 Sep 2003, Matthew Sachs suggested that, "this * is probably the capability for the SMS features." */ {OSCAR_CAPABILITY_SMS, {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_HIPTOP, {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_TALK, {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_SENDFILE, {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_ICQ_DIRECT, {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_DIRECTIM, {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_BUDDYICON, {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_ADDINS, {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_GETFILE, {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_ICQSERVERRELAY, {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* * Indeed, there are two of these. The former appears to be correct, * but in some versions of winaim, the second one is set. Either they * forgot to fix endianness, or they made a typo. It really doesn't * matter which. */ {OSCAR_CAPABILITY_GAMES, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_GAMES2, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_SENDBUDDYLIST, {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* * Setting this lets AIM users receive messages from ICQ users, and ICQ * users receive messages from AIM users. It also lets ICQ users show * up in buddy lists for AIM users, and AIM users show up in buddy lists * for ICQ users. And ICQ privacy/invisibility acts like AIM privacy, * in that if you add a user to your deny list, you will not be able to * see them as online (previous you could still see them, but they * couldn't see you. */ {OSCAR_CAPABILITY_INTEROPERATE, {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_UNICODE, {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {OSCAR_CAPABILITY_UNICODEOLD, {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}}, /* {OSCAR_CAPABILITY_ICQ2GO, {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd, 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}}, */ /* * Chat is oddball. */ {OSCAR_CAPABILITY_CHAT, {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* This is added by the servers and it only shows up for ourselves... */ {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}}, {OSCAR_CAPABILITY_ICQRTF, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}}, {OSCAR_CAPABILITY_APINFO, {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6, 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}}, {OSCAR_CAPABILITY_TRILLIANCRYPT, {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}}, {OSCAR_CAPABILITY_EMPTY, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {OSCAR_CAPABILITY_LAST, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},};/* * Add the userinfo to our linked list. If we already have userinfo * for this buddy, then just overwrite parts of the old data. * * @param userinfo Contains the new information for the buddy. */static voidaim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo){ aim_userinfo_t *cur; FlapConnection *conn; aim_rxcallback_t userfunc; cur = aim_locate_finduserinfo(od, userinfo->sn); if (cur == NULL) { cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1); cur->sn = g_strdup(userinfo->sn); cur->next = od->locate.userinfo; od->locate.userinfo = cur; } cur->warnlevel = userinfo->warnlevel; cur->idletime = userinfo->idletime; if (userinfo->flags != 0) cur->flags = userinfo->flags; if (userinfo->createtime != 0) cur->createtime = userinfo->createtime; if (userinfo->membersince != 0) cur->membersince = userinfo->membersince; if (userinfo->onlinesince != 0) cur->onlinesince = userinfo->onlinesince; if (userinfo->sessionlen != 0) cur->sessionlen = userinfo->sessionlen; if (userinfo->capabilities != 0) cur->capabilities = userinfo->capabilities; cur->present |= userinfo->present; if (userinfo->iconcsumlen > 0) { g_free(cur->iconcsum); cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen); memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen); cur->iconcsumlen = userinfo->iconcsumlen; } if (userinfo->info != NULL) { g_free(cur->info); g_free(cur->info_encoding); if (userinfo->info_len > 0) { cur->info = (char *)g_malloc(userinfo->info_len); memcpy(cur->info, userinfo->info, userinfo->info_len); } else cur->info = NULL; cur->info_encoding = g_strdup(userinfo->info_encoding); cur->info_len = userinfo->info_len; } if (userinfo->status != NULL) { g_free(cur->status); g_free(cur->status_encoding); if (userinfo->status_len > 0) { cur->status = (char *)g_malloc(userinfo->status_len); memcpy(cur->status, userinfo->status, userinfo->status_len); } else cur->status = NULL; if (userinfo->status_encoding != NULL) cur->status_encoding = g_strdup(userinfo->status_encoding); else cur->status_encoding = NULL; cur->status_len = userinfo->status_len; } if (userinfo->itmsurl != NULL) { g_free(cur->itmsurl); g_free(cur->itmsurl_encoding); if (userinfo->itmsurl_len > 0) { cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len); memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len); } else cur->itmsurl = NULL; if (userinfo->itmsurl_encoding != NULL) cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding); else cur->itmsurl_encoding = NULL; cur->itmsurl_len = userinfo->itmsurl_len; } if (userinfo->away != NULL) { g_free(cur->away); g_free(cur->away_encoding); if (userinfo->away_len > 0) { cur->away = (char *)g_malloc(userinfo->away_len); memcpy(cur->away, userinfo->away, userinfo->away_len); } else cur->away = NULL; cur->away_encoding = g_strdup(userinfo->away_encoding); cur->away_len = userinfo->away_len; } else if (!(userinfo->flags & AIM_FLAG_AWAY)) { /* * We don't have an away message specified in this user_info block. * If the user is not away, clear any cached away message now. */ if (cur->away) { g_free(cur->away); cur->away = NULL; } if (cur->away_encoding) { g_free(cur->away_encoding); cur->away_encoding = NULL; } cur->away_len = 0; } /* * This callback can be used by a client if they want to know whenever * info for a buddy is updated. For example, if a client shows away * messages in its buddy list, then it would need to know if a user's * away message changes. */ conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE); if ((userfunc = aim_callhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK))) userfunc(od, conn, NULL, cur);}voidaim_locate_dorequest(OscarData *od){ struct userinfo_node *cur = od->locate.torequest; if (od->locate.waiting_for_response == TRUE) return; od->locate.waiting_for_response = TRUE; aim_locate_getinfoshort(od, cur->sn, 0x00000003); /* Move this node to the "requested" queue */ od->locate.torequest = cur->next; cur->next = od->locate.requested; od->locate.requested = cur;}static gbooleanpurple_reqinfo_timeout_cb(void *data){ OscarData *od; od = data; if (od->locate.torequest == NULL) { od->getinfotimer = 0; return FALSE; } aim_locate_dorequest(od); return TRUE;}/** * Remove this screen name from our queue. If this info was requested * by our info request queue, then pop the next element off of the queue. * * @param od The aim session. * @param sn Screen name of the info we just received. * @return True if the request was explicit (client requested the info), * false if the request was implicit (libfaim request the info). */static intaim_locate_gotuserinfo(OscarData *od, FlapConnection *conn, const char *sn){ struct userinfo_node *cur, *del; int was_explicit = TRUE; while ((od->locate.requested != NULL) && (aim_sncmp(sn, od->locate.requested->sn) == 0)) { del = od->locate.requested; od->locate.requested = del->next; was_explicit = FALSE; g_free(del->sn); g_free(del); } cur = od->locate.requested; while ((cur != NULL) && (cur->next != NULL)) { if (aim_sncmp(sn, cur->next->sn) == 0) { del = cur->next; cur->next = del->next; was_explicit = FALSE; g_free(del->sn); g_free(del); } else cur = cur->next; } if (!was_explicit) { od->locate.waiting_for_response = FALSE; /* * Wait a little while then call aim_locate_dorequest(od). * This keeps us from hitting the rate limit due to * requesting away messages and info too quickly. */ if (od->getinfotimer == 0) od->getinfotimer = purple_timeout_add(500, purple_reqinfo_timeout_cb, od); } return was_explicit;}voidaim_locate_requestuserinfo(OscarData *od, const char *sn){ struct userinfo_node *cur; /* Make sure we aren't already requesting info for this buddy */ cur = od->locate.torequest; while (cur != NULL) { if (aim_sncmp(sn, cur->sn) == 0) return; cur = cur->next; } /* Add a new node to our request queue */ cur = (struct userinfo_node *)g_malloc(sizeof(struct userinfo_node)); cur->sn = g_strdup(sn); cur->next = od->locate.torequest; od->locate.torequest = cur; /* Actually request some info up in this piece */ aim_locate_dorequest(od);}aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *sn) { aim_userinfo_t *cur = NULL; if (sn == NULL) return NULL; cur = od->locate.userinfo; while (cur != NULL) { if (aim_sncmp(cur->sn, sn) == 0) return cur; cur = cur->next; } return NULL;}guint32aim_locate_getcaps(OscarData *od, ByteStream *bs, int len){ guint32 flags = 0; int offset; for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) { guint8 *cap; int i, identified; cap = byte_stream_getraw(bs, 0x10); for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) { if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) { flags |= aim_caps[i].flag; identified++; break; /* should only match once... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -