📄 locate.c
字号:
/* * 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. */#define FAIM_INTERNAL#include <aim.h>#ifdef _WIN32#include "win32dep.h"#endif/* * 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 { fu32_t flag; fu8_t data[16];} aim_caps[] = { /* * These are in ascending numerical order. */ /* * Perhaps better called AIM_CAPS_SHORTCAPS */ {AIM_CAPS_ICHAT, {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_SECUREIM, {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_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 */ {AIM_CAPS_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 */ {AIM_CAPS_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 */ {AIM_CAPS_GENERICUNKNOWN, {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In iChatAV (version numbers...?) */ {AIM_CAPS_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." */ {AIM_CAPS_SMS, {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_HIPTOP, {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_TALK, {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_SENDFILE, {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_ICQ_DIRECT, {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_DIRECTIM, {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_BUDDYICON, {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_ADDINS, {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_GETFILE, {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_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. */ {AIM_CAPS_GAMES, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_GAMES2, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_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. */ {AIM_CAPS_INTEROPERATE, {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_ICQUTF8, {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, {AIM_CAPS_ICQUTF8OLD, {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}}, /* * Chat is oddball. */ {AIM_CAPS_CHAT, {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* {AIM_CAPS_ICQ2GO, {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd, 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}}, */ {AIM_CAPS_ICQRTF, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}}, /* This is added by the servers and it only shows up for ourselves... */ {AIM_CAPS_GENERICUNKNOWN, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}}, {AIM_CAPS_APINFO, {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6, 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}}, {AIM_CAPS_TRILLIANCRYPT, {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}}, {AIM_CAPS_EMPTY, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {AIM_CAPS_LAST}};/* * 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 void aim_locate_adduserinfo(aim_session_t *sess, aim_userinfo_t *userinfo) { aim_userinfo_t *cur; cur = aim_locate_finduserinfo(sess, userinfo->sn); if (cur == NULL) { cur = (aim_userinfo_t *)calloc(1, sizeof(aim_userinfo_t)); cur->sn = strdup(userinfo->sn); cur->next = sess->locate.userinfo; sess->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) { free(cur->iconcsum); cur->iconcsum = (fu8_t *)malloc(userinfo->iconcsumlen); memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen); cur->iconcsumlen = userinfo->iconcsumlen; } if (userinfo->info != NULL) { free(cur->info); free(cur->info_encoding); if (userinfo->info_len > 0) { cur->info = (char *)malloc(userinfo->info_len); memcpy(cur->info, userinfo->info, userinfo->info_len); } else cur->info = NULL; cur->info_encoding = strdup(userinfo->info_encoding); cur->info_len = userinfo->info_len; } if (userinfo->away != NULL) { free(cur->away); free(cur->away_encoding); if (userinfo->away_len > 0) { cur->away = (char *)malloc(userinfo->away_len); memcpy(cur->away, userinfo->away, userinfo->away_len); } else cur->away = NULL; cur->away_encoding = strdup(userinfo->away_encoding); cur->away_len = userinfo->away_len; }}faim_export void aim_locate_dorequest(aim_session_t *sess) { struct userinfo_node *cur = sess->locate.torequest; if (cur == NULL) return; if (sess->locate.waiting_for_response == TRUE) return; sess->locate.waiting_for_response = TRUE; aim_locate_getinfoshort(sess, cur->sn, 0x00000003); /* Move this node to the "requested" queue */ sess->locate.torequest = cur->next; cur->next = sess->locate.requested; sess->locate.requested = cur;}/** * 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 sess 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 int aim_locate_gotuserinfo(aim_session_t *sess, const char *sn) { struct userinfo_node *cur, *del; int was_explicit = TRUE; while ((sess->locate.requested != NULL) && (aim_sncmp(sn, sess->locate.requested->sn) == 0)) { del = sess->locate.requested; sess->locate.requested = del->next; was_explicit = FALSE; free(del->sn); free(del); } cur = sess->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; free(del->sn); free(del); } else cur = cur->next; } if (!was_explicit) { aim_conn_t *conn = aim_conn_findbygroup(sess, AIM_CB_FAM_LOC); aim_rxcallback_t userfunc; sess->locate.waiting_for_response = FALSE; if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_LOC, AIM_CB_LOC_REQUESTINFOTIMEOUT))) userfunc(sess, NULL); else aim_locate_dorequest(sess); } return was_explicit;}faim_internal void aim_locate_requestuserinfo(aim_session_t *sess, const char *sn) { struct userinfo_node *cur; /* Make sure we aren't already requesting info for this buddy */ cur = sess->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 *)malloc(sizeof(struct userinfo_node)); cur->sn = strdup(sn); cur->next = sess->locate.torequest; sess->locate.torequest = cur; /* Actually request some info up in this piece */ aim_locate_dorequest(sess);}faim_export aim_userinfo_t *aim_locate_finduserinfo(aim_session_t *sess, const char *sn) { aim_userinfo_t *cur = NULL; if ( sn == NULL ) return NULL; cur = sess->locate.userinfo; while (cur != NULL) { if (aim_sncmp(cur->sn, sn) == 0) return cur; cur = cur->next; } return NULL;}faim_internal fu32_t aim_locate_getcaps(aim_session_t *sess, aim_bstream_t *bs, int len){ fu32_t flags = 0; int offset; for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) { fu8_t *cap; int i, identified; cap = aimbs_getraw(bs, 0x10); for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) { if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) { flags |= aim_caps[i].flag; identified++; break; /* should only match once... */ } } if (!identified) faimdprintf(sess, 0, "unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", cap[0], cap[1], cap[2], cap[3], cap[4], cap[5], cap[6], cap[7], cap[8], cap[9], cap[10], cap[11], cap[12], cap[13], cap[14], cap[15]); free(cap); } return flags;}faim_internal fu32_t aim_locate_getcaps_short(aim_session_t *sess, aim_bstream_t *bs, int len){ fu32_t flags = 0; int offset; for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x02) { fu8_t *cap; int i, identified; cap = aimbs_getraw(bs, 0x02); for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) { if (memcmp(&aim_caps[i].data[2], cap, 0x02) == 0) { flags |= aim_caps[i].flag; identified++; break; /* should only match once... */ } } if (!identified) faimdprintf(sess, 0, "unknown short capability: {%02x%02x}\n", cap[0], cap[1]); free(cap); } return flags;}faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps){ int i; if (!bs) return -EINVAL; for (i = 0; aim_bstream_empty(bs); i++) { if (aim_caps[i].flag == AIM_CAPS_LAST) break; if (caps & aim_caps[i].flag) aimbs_putraw(bs, aim_caps[i].data, 0x10); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -