📄 yahoo.c
字号:
/* * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include "internal.h"#include "account.h"#include "accountopt.h"#include "blist.h"#include "cipher.h"#include "cmds.h"#include "core.h"#include "debug.h"#include "notify.h"#include "privacy.h"#include "prpl.h"#include "proxy.h"#include "request.h"#include "server.h"#include "util.h"#include "version.h"#include "yahoo.h"#include "yahoochat.h"#include "yahoo_auth.h"#include "yahoo_crypt.h"#include "yahoo_doodle.h"#include "yahoo_filexfer.h"#include "yahoo_friend.h"#include "yahoo_packet.h"#include "yahoo_picture.h"#include "ycht.h"/* #define YAHOO_DEBUG *//* #define TRY_WEBMESSENGER_LOGIN 0 */static void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *, PurpleGroup *);#ifdef TRY_WEBMESSENGER_LOGINstatic void yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message);#endifstatic void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);static voidyahoo_add_permit(PurpleConnection *gc, const char *who){ purple_debug_info("yahoo", "Permitting ID %s local contact rights for account %s\n", who, gc->account); purple_privacy_permit_add(gc->account,who,TRUE);}static voidyahoo_rem_permit(PurpleConnection *gc, const char *who){ purple_debug_info("yahoo", "Denying ID %s local contact rights for account %s\n", who, gc->account); purple_privacy_permit_remove(gc->account,who,TRUE);}gbooleanyahoo_privacy_check(PurpleConnection *gc, const char *who){ /* returns TRUE if allowed through, FALSE otherwise */ gboolean permitted; permitted = purple_privacy_check(gc->account, who); /* print some debug info */ if (!permitted) { char *deb = NULL; switch (gc->account->perm_deny) { case PURPLE_PRIVACY_DENY_ALL: deb = "PURPLE_PRIVACY_DENY_ALL"; break; case PURPLE_PRIVACY_DENY_USERS: deb = "PURPLE_PRIVACY_DENY_USERS"; break; case PURPLE_PRIVACY_ALLOW_BUDDYLIST: deb = "PURPLE_PRIVACY_ALLOW_BUDDYLIST"; break; } if(deb) purple_debug_info("yahoo", "%s blocked data received from %s (%s)\n", gc->account->username,who, deb); } else if (gc->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) { purple_debug_info("yahoo", "%s allowed data received from %s (PURPLE_PRIVACY_ALLOW_USERS)\n", gc->account->username,who); } return permitted;}static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f){ char *status = NULL; if (!gc || !name || !f || !purple_find_buddy(purple_connection_get_account(gc), name)) return; if (f->status == YAHOO_STATUS_OFFLINE) { return; } switch (f->status) { case YAHOO_STATUS_AVAILABLE: status = YAHOO_STATUS_TYPE_AVAILABLE; break; case YAHOO_STATUS_BRB: status = YAHOO_STATUS_TYPE_BRB; break; case YAHOO_STATUS_BUSY: status = YAHOO_STATUS_TYPE_BUSY; break; case YAHOO_STATUS_NOTATHOME: status = YAHOO_STATUS_TYPE_NOTATHOME; break; case YAHOO_STATUS_NOTATDESK: status = YAHOO_STATUS_TYPE_NOTATDESK; break; case YAHOO_STATUS_NOTINOFFICE: status = YAHOO_STATUS_TYPE_NOTINOFFICE; break; case YAHOO_STATUS_ONPHONE: status = YAHOO_STATUS_TYPE_ONPHONE; break; case YAHOO_STATUS_ONVACATION: status = YAHOO_STATUS_TYPE_ONVACATION; break; case YAHOO_STATUS_OUTTOLUNCH: status = YAHOO_STATUS_TYPE_OUTTOLUNCH; break; case YAHOO_STATUS_STEPPEDOUT: status = YAHOO_STATUS_TYPE_STEPPEDOUT; break; case YAHOO_STATUS_INVISIBLE: /* this should never happen? */ status = YAHOO_STATUS_TYPE_INVISIBLE; break; case YAHOO_STATUS_CUSTOM: case YAHOO_STATUS_IDLE: if (!f->away) status = YAHOO_STATUS_TYPE_AVAILABLE; else status = YAHOO_STATUS_TYPE_AWAY; break; default: purple_debug_warning("yahoo", "Warning, unknown status %d\n", f->status); break; } if (status) { if (f->status == YAHOO_STATUS_CUSTOM) purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message", yahoo_friend_get_status_message(f), NULL); else purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL); } if (f->idle != 0) purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle); else purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0); if (f->sms) purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL); else purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);}static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt){ PurpleAccount *account = purple_connection_get_account(gc); struct yahoo_data *yd = gc->proto_data; GSList *l = pkt->hash; YahooFriend *f = NULL; char *name = NULL; if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { gc->wants_to_die = TRUE; purple_connection_error(gc, _("You have signed on from another location.")); return; } while (l) { struct yahoo_pair *pair = l->data; switch (pair->key) { case 0: /* we won't actually do anything with this */ break; case 1: /* we don't get the full buddy list here. */ if (!yd->logged_in) { purple_connection_set_display_name(gc, pair->value); purple_connection_set_state(gc, PURPLE_CONNECTED); yd->logged_in = TRUE; if (yd->picture_upload_todo) { yahoo_buddy_icon_upload(gc, yd->picture_upload_todo); yd->picture_upload_todo = NULL; } yahoo_set_status(account, purple_account_get_active_status(account)); /* this requests the list. i have a feeling that this is very evil * * scs.yahoo.com sends you the list before this packet without it being * requested * * do_import(gc, NULL); * newpkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_OFFLINE, 0); * yahoo_packet_send_and_free(newpkt, yd); */ } break; case 8: /* how many online buddies we have */ break; case 7: /* the current buddy */ if (name && f) /* update the previous buddy before changing the variables */ yahoo_update_status(gc, name, f); name = pair->value; if (name && g_utf8_validate(name, -1, NULL)) f = yahoo_friend_find_or_new(gc, name); else { f = NULL; name = NULL; } break; case 10: /* state */ if (!f) break; f->status = strtol(pair->value, NULL, 10); if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT)) f->away = 1; else f->away = 0; if (f->status == YAHOO_STATUS_IDLE) { /* Idle may have already been set in a more precise way in case 137 */ if (f->idle == 0) f->idle = time(NULL); } else f->idle = 0; if (f->status != YAHOO_STATUS_CUSTOM) yahoo_friend_set_status_message(f, NULL); f->sms = 0; break; case 19: /* custom message */ if (f) yahoo_friend_set_status_message(f, yahoo_string_decode(gc, pair->value, FALSE)); break; case 11: /* this is the buddy's session id */ break; case 17: /* in chat? */ break; case 47: /* is custom status away or not? 2=idle*/ if (!f) break; /* I have no idea what it means when this is * set when someone's available, but it doesn't * mean idle. */ if (f->status == YAHOO_STATUS_AVAILABLE) break; f->away = strtol(pair->value, NULL, 10); if (f->away == 2) { /* Idle may have already been set in a more precise way in case 137 */ if (f->idle == 0) f->idle = time(NULL); } break; case 138: /* either we're not idle, or we are but won't say how long */ if (!f) break; if (f->idle) f->idle = -1; break; case 137: /* usually idle time in seconds, sometimes login time */ if (!f) break; if (f->status != YAHOO_STATUS_AVAILABLE) f->idle = time(NULL) - strtol(pair->value, NULL, 10); break; case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ if (strtol(pair->value, NULL, 10) == 0) { if (f) f->status = YAHOO_STATUS_OFFLINE; if (name) { purple_prpl_got_user_status(account, name, "offline", NULL); purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE); } break; } break; case 60: /* SMS */ if (f) { f->sms = strtol(pair->value, NULL, 10); yahoo_update_status(gc, name, f); } break; case 197: /* Avatars */ { guchar *decoded; char *tmp; gsize len; if (pair->value) { decoded = purple_base64_decode(pair->value, &len); if (len) { tmp = purple_str_binary_to_ascii(decoded, len); purple_debug_info("yahoo", "Got key 197, value = %s\n", tmp); g_free(tmp); } g_free(decoded); } break; } case 192: /* Pictures, aka Buddy Icons, checksum */ { /* FIXME: Please, if you know this protocol, * FIXME: fix up the strtol() stuff if possible. */ int cksum = strtol(pair->value, NULL, 10); const char *locksum = NULL; PurpleBuddy *b; if (!name) break; b = purple_find_buddy(gc->account, name); if (!cksum || (cksum == -1)) { if (f) yahoo_friend_set_buddy_icon_need_request(f, TRUE); purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL); break; } if (!f) break; yahoo_friend_set_buddy_icon_need_request(f, FALSE); if (b) { locksum = purple_buddy_icons_get_checksum_for_user(b); if (!locksum || (cksum != strtol(locksum, NULL, 10))) yahoo_send_picture_request(gc, name); } break; } case 16: /* Custom error message */ { char *tmp = yahoo_string_decode(gc, pair->value, TRUE); purple_notify_error(gc, NULL, tmp, NULL); g_free(tmp); } break; default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", "Unknown status key %d\n", pair->key); break; } l = l->next; } if (name && f) /* update the last buddy */ yahoo_update_status(gc, name, f);}static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group){ PurpleBuddy *b; PurpleGroup *g; GSList *list, *i; gboolean onlist = 0; char *oname = NULL; char **oname_p = &oname; GSList **list_p = &list; if (!g_hash_table_lookup_extended(ht, purple_normalize(account, name), (gpointer *) oname_p, (gpointer *) list_p)) list = purple_find_buddies(account, name); else g_hash_table_steal(ht, name); for (i = list; i; i = i->next) { b = i->data; g = purple_buddy_get_group(b); if (!purple_utf8_strcasecmp(group, g->name)) { purple_debug(PURPLE_DEBUG_MISC, "yahoo", "Oh good, %s is in the right group (%s).\n", name, group); list = g_slist_delete_link(list, i); onlist = 1; break; } } if (!onlist) { purple_debug(PURPLE_DEBUG_MISC, "yahoo", "Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group); if (!(g = purple_find_group(group))) { g = purple_group_new(group); purple_blist_add_group(g, NULL); } b = purple_buddy_new(account, name, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } if (list) { if (!oname) oname = g_strdup(purple_normalize(account, name)); g_hash_table_insert(ht, oname, list); } else if (oname) g_free(oname);}static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data){ char *name = key; GSList *list = value, *i; PurpleBuddy *b; PurpleGroup *g; for (i = list; i; i = i->next) { b = i->data; g = purple_buddy_get_group(b); purple_debug(PURPLE_DEBUG_MISC, "yahoo", "Deleting Buddy %s from group %s.\n", name, g->name); purple_blist_remove_buddy(b); }}static char *_getcookie(char *rawcookie){ char *cookie = NULL; char *tmpcookie; char *cookieend; if (strlen(rawcookie) < 2) return NULL; tmpcookie = g_strdup(rawcookie+2); cookieend = strchr(tmpcookie, ';'); if (cookieend) *cookieend = '\0'; cookie = g_strdup(tmpcookie); g_free(tmpcookie); return cookie;}static void yahoo_process_cookie(struct yahoo_data *yd, char *c){ if (c[0] == 'Y') { if (yd->cookie_y) g_free(yd->cookie_y); yd->cookie_y = _getcookie(c); } else if (c[0] == 'T') { if (yd->cookie_t) g_free(yd->cookie_t); yd->cookie_t = _getcookie(c); }}static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt){ GSList *l = pkt->hash; PurpleAccount *account = purple_connection_get_account(gc); GHashTable *ht; char *grp = NULL; char *norm_bud = NULL; YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */ /* But what if you had no friends? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -