📄 yahoo.c
字号:
PurpleBuddy *b; PurpleGroup *g; ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); while (l) { struct yahoo_pair *pair = l->data; l = l->next; switch (pair->key) { case 302: /* This is always 318 before a group, 319 before the first s/n in a group, 320 before any ignored s/n. * It is not sent for s/n's in a group after the first. * All ignored s/n's are listed last, so when we see a 320 we clear the group and begin marking the * s/n's as ignored. It is always followed by an identical 300 key. */ if (pair->value && !strcmp(pair->value, "320")) { /* No longer in any group; this indicates the start of the ignore list. */ g_free(grp); grp = NULL; } break; case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */ break; case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */ break; case 65: /* This is the group */ g_free(grp); grp = yahoo_string_decode(gc, pair->value, FALSE); break; case 7: /* buddy's s/n */ g_free(norm_bud); norm_bud = g_strdup(purple_normalize(account, pair->value)); if (grp) { /* This buddy is in a group */ f = yahoo_friend_find_or_new(gc, norm_bud); if (!(b = purple_find_buddy(account, norm_bud))) { if (!(g = purple_find_group(grp))) { g = purple_group_new(grp); purple_blist_add_group(g, NULL); } b = purple_buddy_new(account, norm_bud, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } yahoo_do_group_check(account, ht, norm_bud, grp); } else { /* This buddy is on the ignore list (and therefore in no group) */ purple_privacy_deny_add(account, norm_bud, 1); } break; case 241: /* another protocol user */ if (f) { f->protocol = strtol(pair->value, NULL, 10); purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); } break; /* case 242: */ /* this seems related to 241 */ /* break; */ } } g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL); g_hash_table_destroy(ht); g_free(grp); g_free(norm_bud);}static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt){ GSList *l = pkt->hash; gboolean export = FALSE; gboolean got_serv_list = FALSE; PurpleBuddy *b; PurpleGroup *g; YahooFriend *f = NULL; PurpleAccount *account = purple_connection_get_account(gc); struct yahoo_data *yd = gc->proto_data; GHashTable *ht; char **lines; char **split; char **buddies; char **tmp, **bud, *norm_bud; char *grp = NULL; if (pkt->id) yd->session_id = pkt->id; while (l) { struct yahoo_pair *pair = l->data; l = l->next; switch (pair->key) { case 87: if (!yd->tmp_serv_blist) yd->tmp_serv_blist = g_string_new(pair->value); else g_string_append(yd->tmp_serv_blist, pair->value); break; case 88: if (!yd->tmp_serv_ilist) yd->tmp_serv_ilist = g_string_new(pair->value); else g_string_append(yd->tmp_serv_ilist, pair->value); break; case 59: /* cookies, yum */ yahoo_process_cookie(yd, pair->value); break; case YAHOO_SERVICE_PRESENCE_PERM: if (!yd->tmp_serv_plist) yd->tmp_serv_plist = g_string_new(pair->value); else g_string_append(yd->tmp_serv_plist, pair->value); break; } } if (pkt->status != 0) return; if (yd->tmp_serv_blist) { ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); lines = g_strsplit(yd->tmp_serv_blist->str, "\n", -1); for (tmp = lines; *tmp; tmp++) { split = g_strsplit(*tmp, ":", 2); if (!split) continue; if (!split[0] || !split[1]) { g_strfreev(split); continue; } grp = yahoo_string_decode(gc, split[0], FALSE); buddies = g_strsplit(split[1], ",", -1); for (bud = buddies; bud && *bud; bud++) { norm_bud = g_strdup(purple_normalize(account, *bud)); f = yahoo_friend_find_or_new(gc, norm_bud); if (!(b = purple_find_buddy(account, norm_bud))) { if (!(g = purple_find_group(grp))) { g = purple_group_new(grp); purple_blist_add_group(g, NULL); } b = purple_buddy_new(account, norm_bud, NULL); purple_blist_add_buddy(b, NULL, g, NULL); export = TRUE; } yahoo_do_group_check(account, ht, norm_bud, grp); g_free(norm_bud); } g_strfreev(buddies); g_strfreev(split); g_free(grp); } g_strfreev(lines); g_string_free(yd->tmp_serv_blist, TRUE); yd->tmp_serv_blist = NULL; g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL); g_hash_table_destroy(ht); } if (yd->tmp_serv_ilist) { buddies = g_strsplit(yd->tmp_serv_ilist->str, ",", -1); for (bud = buddies; bud && *bud; bud++) { /* The server is already ignoring the user */ got_serv_list = TRUE; purple_privacy_deny_add(gc->account, *bud, 1); } g_strfreev(buddies); g_string_free(yd->tmp_serv_ilist, TRUE); yd->tmp_serv_ilist = NULL; } if (got_serv_list && ((gc->account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) && (gc->account->perm_deny != PURPLE_PRIVACY_DENY_ALL) && (gc->account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS))) { gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS; purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n", gc->account->username); } if (yd->tmp_serv_plist) { buddies = g_strsplit(yd->tmp_serv_plist->str, ",", -1); for (bud = buddies; bud && *bud; bud++) { f = yahoo_friend_find(gc, *bud); if (f) { purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n", gc->account->username, *bud); f->presence = YAHOO_PRESENCE_PERM_OFFLINE; } } g_strfreev(buddies); g_string_free(yd->tmp_serv_plist, TRUE); yd->tmp_serv_plist = NULL; }}static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt){ char *msg = NULL; char *from = NULL; char *stat = NULL; char *game = NULL; YahooFriend *f = NULL; GSList *l = pkt->hash; while (l) { struct yahoo_pair *pair = l->data; if (pair->key == 4) from = pair->value; if (pair->key == 49) msg = pair->value; if (pair->key == 13) stat = pair->value; if (pair->key == 14) game = pair->value; l = l->next; } if (!from || !msg) return; if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) && (yahoo_privacy_check(gc, from))) { if (*stat == '1') serv_got_typing(gc, from, 0, PURPLE_TYPING); else serv_got_typing_stopped(gc, from); } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { PurpleBuddy *bud = purple_find_buddy(gc->account, from); if (!bud) { purple_debug(PURPLE_DEBUG_WARNING, "yahoo", "%s is playing a game, and doesn't want " "you to know.\n", from); } f = yahoo_friend_find(gc, from); if (!f) return; /* if they're not on the list, don't bother */ yahoo_friend_set_game(f, NULL); if (*stat == '1') { yahoo_friend_set_game(f, game); if (bud) yahoo_update_status(gc, from, f); } }}struct _yahoo_im { char *from; int time; int utf8; int buddy_icon; char *msg;};static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt){ struct yahoo_data *yd = gc->proto_data; GSList *l = pkt->hash; GSList *list = NULL; struct _yahoo_im *im = NULL; const char *imv = NULL; if (pkt->status <= 1 || pkt->status == 5) { while (l != NULL) { struct yahoo_pair *pair = l->data; if (pair->key == 4) { im = g_new0(struct _yahoo_im, 1); list = g_slist_append(list, im); im->from = pair->value; im->time = time(NULL); } if (pair->key == 97) if (im) im->utf8 = strtol(pair->value, NULL, 10); if (pair->key == 15) if (im) im->time = strtol(pair->value, NULL, 10); if (pair->key == 206) if (im) im->buddy_icon = strtol(pair->value, NULL, 10); if (pair->key == 14) { if (im) im->msg = pair->value; } /* IMV key */ if (pair->key == 63) { imv = pair->value; } l = l->next; } } else if (pkt->status == 2) { purple_notify_error(gc, NULL, _("Your Yahoo! message did not get sent."), NULL); } /** TODO: It seems that this check should be per IM, not global */ /* Check for the Doodle IMV */ if (im != NULL && imv!= NULL && im->from != NULL) { g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(imv)); if (strcmp(imv, "doodle;11") == 0) { PurpleWhiteboard *wb; if (!yahoo_privacy_check(gc, im->from)) { purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from); return; } wb = purple_whiteboard_get_session(gc->account, im->from); /* If a Doodle session doesn't exist between this user */ if(wb == NULL) { wb = purple_whiteboard_create(gc->account, im->from, DOODLE_STATE_REQUESTED); yahoo_doodle_command_send_request(gc, im->from); yahoo_doodle_command_send_ready(gc, im->from); } } } for (l = list; l; l = l->next) { YahooFriend *f; char *m, *m2; im = l->data; if (!im->from || !im->msg) { g_free(im); continue; } if (!yahoo_privacy_check(gc, im->from)) { purple_debug_info("yahoo", "Message from %s dropped.\n", im->from); return; } m = yahoo_string_decode(gc, im->msg, im->utf8); /* This may actually not be necessary, but it appears * that at least at one point some clients were sending * "\r\n" as line delimiters, so we want to avoid double * lines. */ m2 = purple_strreplace(m, "\r\n", "\n"); g_free(m); m = m2; purple_util_chrreplace(m, '\r', '\n'); if (!strcmp(m, "<ding>")) { PurpleBuddy *buddy; PurpleAccount *account; PurpleConversation *c; char *username, *str; account = purple_connection_get_account(gc); c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, im->from); if ((buddy = purple_find_buddy(account, im->from)) != NULL) username = g_markup_escape_text(purple_buddy_get_alias(buddy), -1); else username = g_markup_escape_text(im->from, -1); str = g_strdup_printf(_("%s just sent you a Buzz!"), username); purple_conversation_write(c, NULL, str, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, im->time); g_free(username); g_free(str); g_free(m); g_free(im); continue; } m2 = yahoo_codes_to_html(m); g_free(m); serv_got_im(gc, im->from, m2, 0, im->time); g_free(m2); if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) { if (yahoo_friend_get_buddy_icon_need_request(f)) { yahoo_send_picture_request(gc, im->from); yahoo_friend_set_buddy_icon_need_request(f, FALSE); } } g_free(im); } g_slist_free(list);}static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt){ GSList *l = pkt->hash; char *prim, *me = NULL, *msg = NULL; while (l) { struct yahoo_pair *pair = l->data; if (pair->key == 5) me = pair->value; if (pair->key == 14) msg = pair->value; l = l->next; } if (!msg || !g_utf8_validate(msg, -1, NULL)) return; prim = g_strdup_printf(_("Yahoo! system message for %s:"), me?me:purple_connection_get_display_name(gc)); purple_notify_info(NULL, NULL, prim, msg); g_free(prim);}struct yahoo_add_request { PurpleConnection *gc; char *id; char *who; char *msg;};static voidyahoo_buddy_add_authorize_cb(struct yahoo_add_request *add_req) { g_free(add_req->id); g_free(add_req->who); g_free(add_req->msg); g_free(add_req);}static voidyahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg) { struct yahoo_packet *pkt; char *encoded_msg = NULL; struct yahoo_data *yd = add_req->gc->proto_data; if (msg) encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, "sss", 1, purple_normalize(add_req->gc->account, purple_account_get_username( purple_connection_get_account( add_req->gc))), 7, add_req->who, 14, encoded_msg ? encoded_msg : ""); yahoo_packet_send_and_free(pkt, yd); g_free(encoded_msg); g_free(add_req->id); g_free(add_req->who); g_free(add_req->msg); g_free(add_req);}static voidyahoo_buddy_add_deny_noreason_cb(struct yahoo_add_request *add_req, const char*msg){ yahoo_buddy_add_deny_cb(add_req, NULL);}static voidyahoo_buddy_add_deny_reason_cb(struct yahoo_add_request *add_req) { purple_request_input(add_req->gc, NULL, _("Authorization denied message:"), NULL, _("No reason given."), TRUE, FALSE, NULL, _("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb), _("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb), purple_connection_get_account(add_req->gc), add_req->who, NULL, add_req);}static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) { struct yahoo_add_request *add_req; char *msg = NULL; GSList *l = pkt->hash;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -