📄 yahoo.c
字号:
shaUpdate(&ctx2, crypt_hash_xor2, 64); shaUpdate(&ctx2, digest1, 20); shaFinal(&ctx2, digest2); /* * Now that we have digest2, use it to fetch characters from an alphabet to construct * our first authentication response. */ for (x = 0; x < 20; x += 2) { unsigned int val = 0; unsigned int lookup = 0; char byte[6]; memset(&byte, 0, 6); /* First two bytes of digest stuffed together. */ val = digest2[x]; val <<= 8; val += digest2[x+1]; lookup = (val >> 0x0b); lookup &= 0x1f; if (lookup >= strlen(alphabet1)) break; sprintf(byte, "%c", alphabet1[lookup]); strcat(resp_96, byte); strcat(resp_96, "="); lookup = (val >> 0x06); lookup &= 0x1f; if (lookup >= strlen(alphabet2)) break; sprintf(byte, "%c", alphabet2[lookup]); strcat(resp_96, byte); lookup = (val >> 0x01); lookup &= 0x1f; if (lookup >= strlen(alphabet2)) break; sprintf(byte, "%c", alphabet2[lookup]); strcat(resp_96, byte); lookup = (val & 0x01); if (lookup >= strlen(delimit_lookup)) break; sprintf(byte, "%c", delimit_lookup[lookup]); strcat(resp_96, byte); } pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pack, 0, name); yahoo_packet_hash(pack, 6, resp_6); yahoo_packet_hash(pack, 96, resp_96); yahoo_packet_hash(pack, 1, name); yahoo_packet_hash(pack, 135, "6,0,0,1710"); if (yd->picture_checksum) { char *cksum = g_strdup_printf("%d", yd->picture_checksum); yahoo_packet_hash(pack, 192, cksum); g_free(cksum); } yahoo_send_packet(yd, pack); yahoo_packet_free(pack); g_free(password_hash); g_free(crypt_hash);}static void yahoo_process_auth(GaimConnection *gc, struct yahoo_packet *pkt){ char *seed = NULL; char *sn = NULL; GSList *l = pkt->hash; int m = 0; gchar *buf; while (l) { struct yahoo_pair *pair = l->data; if (pair->key == 94) seed = pair->value; if (pair->key == 1) sn = pair->value; if (pair->key == 13) m = atoi(pair->value); l = l->next; } if (seed) { switch (m) { case 0: yahoo_process_auth_old(gc, seed); break; case 1: yahoo_process_auth_new(gc, seed); break; default: buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized " "authentication method. This version of Gaim will likely not be able " "to successfully sign on to Yahoo. Check %s for updates."), GAIM_WEBSITE); gaim_notify_error(gc, "", _("Failed Yahoo! Authentication"), buf); g_free(buf); yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */ } }}static void ignore_buddy(GaimBuddy *buddy) { GaimGroup *group; GaimConversation *conv; GaimAccount *account; gchar *name; if (!buddy) return; group = gaim_find_buddys_group(buddy); name = g_strdup(buddy->name); account = buddy->account; gaim_debug(GAIM_DEBUG_INFO, "blist", "Removing '%s' from buddy list.\n", buddy->name); serv_remove_buddy(account->gc, buddy, group); gaim_blist_remove_buddy(buddy); serv_add_deny(account->gc, name); conv = gaim_find_conversation_with_account(name, account); if (conv != NULL) gaim_conversation_update(conv, GAIM_CONV_UPDATE_REMOVE); g_free(name);}static void keep_buddy(GaimBuddy *b) { gaim_privacy_deny_remove(b->account, b->name, 1);}static void yahoo_process_ignore(GaimConnection *gc, struct yahoo_packet *pkt) { GaimBuddy *b; GSList *l; gchar *who = NULL; gchar *sn = NULL; gchar buf[BUF_LONG]; gint ignore = 0; gint status = 0; for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; switch (pair->key) { case 0: who = pair->value; break; case 1: sn = pair->value; break; case 13: ignore = strtol(pair->value, NULL, 10); break; case 66: status = strtol(pair->value, NULL, 10); break; default: break; } } switch (status) { case 12: b = gaim_find_buddy(gc->account, who); g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the " "user is on your buddy list. Clicking \"Yes\" " "will remove and ignore the buddy."), who); gaim_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0, b, G_CALLBACK(ignore_buddy), G_CALLBACK(keep_buddy)); break; case 2: case 3: case 0: default: break; }}static void yahoo_process_authresp(GaimConnection *gc, struct yahoo_packet *pkt){ struct yahoo_data *yd = gc->proto_data; GSList *l = pkt->hash; int err = 0; char *msg; char *url = NULL; char *fullmsg; while (l) { struct yahoo_pair *pair = l->data; if (pair->key == 66) err = strtol(pair->value, NULL, 10); if (pair->key == 20) url = pair->value; l = l->next; } switch (err) { case 3: msg = g_strdup(_("Invalid username.")); break; case 13: if (!yd->wm) { yd->wm = TRUE; if (yd->fd >= 0) close(yd->fd); if (gc->inpa) gaim_input_remove(gc->inpa); gaim_url_fetch(WEBMESSENGER_URL, TRUE, "Gaim/" VERSION, FALSE, yahoo_login_page_cb, gc); gaim_notify_warning(gc, NULL, _("Normal authentication failed!"), _("The normal authentication method has failed. " "This means either your password is incorrect, " "or Yahoo!'s authentication scheme has changed. " "Gaim will now attempt to log in using Web " "Messenger authentication, which will result " "in reduced functionality and features.")); return; } msg = g_strdup(_("Incorrect password.")); break; case 14: msg = g_strdup(_("Your account is locked, please log in to the Yahoo! website.")); break; default: msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err); } if (url) fullmsg = g_strdup_printf("%s\n%s", msg, url); else fullmsg = g_strdup(msg); gc->wants_to_die = TRUE; gaim_connection_error(gc, fullmsg); g_free(msg); g_free(fullmsg);}static void yahoo_process_addbuddy(GaimConnection *gc, struct yahoo_packet *pkt){ int err = 0; char *who = NULL; char *group = NULL; char *decoded_group; char *buf; YahooFriend *f; GSList *l = pkt->hash; while (l) { struct yahoo_pair *pair = l->data; switch (pair->key) { case 66: err = strtol(pair->value, NULL, 10); break; case 7: who = pair->value; break; case 65: group = pair->value; break; } l = l->next; } if (!who) return; if (!group) group = ""; if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ f = yahoo_friend_find_or_new(gc, who); yahoo_update_status(gc, who, f); return; } decoded_group = yahoo_string_decode(gc, group, FALSE); buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), who, decoded_group, gaim_connection_get_display_name(gc)); if (!gaim_conv_present_error(who, gaim_connection_get_account(gc), buf)) gaim_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); g_free(buf); g_free(decoded_group);}static void yahoo_process_p2p(GaimConnection *gc, struct yahoo_packet *pkt){ GSList *l = pkt->hash; char *who = NULL; char *base64 = NULL; char *decoded; int len; while (l) { struct yahoo_pair *pair = l->data; switch (pair->key) { case 5: /* our identity */ break; case 4: who = pair->value; break; case 1: /* who again, the master identity this time? */ break; case 12: base64 = pair->value; /* so, this is an ip address. in base64. decoded it's in ascii. after strtol, it's in reversed byte order. Who thought this up?*/ break; /* TODO: figure these out yahoo: Key: 61 Value: 0 yahoo: Key: 2 Value: yahoo: Key: 13 Value: 0 yahoo: Key: 49 Value: PEERTOPEER yahoo: Key: 140 Value: 1 yahoo: Key: 11 Value: -1786225828 */ } l = l->next; } if (base64) { guint32 ip; char *tmp2; YahooFriend *f; gaim_base64_decode(base64, &decoded, &len); if (len) { char *tmp = gaim_str_binary_to_ascii(decoded, len); gaim_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); g_free(tmp); } tmp2 = g_strndup(decoded, len); /* so its \0 terminated...*/ ip = strtol(tmp2, NULL, 10); g_free(tmp2); g_free(decoded); tmp2 = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); f = yahoo_friend_find(gc, who); if (f) yahoo_friend_set_ip(f, tmp2); g_free(tmp2); }}static void yahoo_process_audible(GaimConnection *gc, struct yahoo_packet *pkt){ char *who = NULL, *msg = NULL; GSList *l = pkt->hash; while (l) { struct yahoo_pair *pair = l->data; switch (pair->key) { case 4: who = pair->value; break; case 5: /* us */ break; case 230: /* the audible, in foo.bar.baz format */ break; case 231: /* the text of the audible */ msg = pair->value; break; case 232: /* weird number (md5 hash?), like 8ebab9094156135f5dcbaccbeee662a5c5fd1420 */ break; } l = l->next; } if (!who || !msg) return; if (!g_utf8_validate(msg, -1, NULL)) { gaim_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n"); return; } serv_got_im(gc, who, msg, 0, time(NULL));}static void yahoo_packet_process(GaimConnection *gc, struct yahoo_packet *pkt){ switch (pkt->service) { case YAHOO_SERVICE_LOGON: case YAHOO_SERVICE_LOGOFF: case YAHOO_SERVICE_ISAWAY: case YAHOO_SERVICE_ISBACK: case YAHOO_SERVICE_GAMELOGON: case YAHOO_SERVICE_GAMELOGOFF: case YAHOO_SERVICE_CHATLOGON: case YAHOO_SERVICE_CHATLOGOFF: case YAHOO_SERVICE_YAHOO6_STATUS_UPDATE: yahoo_process_status(gc, pkt); break; case YAHOO_SERVICE_NOTIFY: yahoo_process_notify(gc, pkt); break; case YAHOO_SERVICE_MESSAGE: case YAHOO_SERVICE_GAMEMSG: case YAHOO_SERVICE_CHATMSG: yahoo_process_message(gc, pkt); break; case YAHOO_SERVICE_SYSMESSAGE: yahoo_process_sysmessage(gc, pkt); break; case YAHOO_SERVICE_NEWMAIL: yahoo_process_mail(gc, pkt); break; case YAHOO_SERVICE_NEWCONTACT: yahoo_process_contact(gc, pkt); break; case YAHOO_SERVICE_AUTHRESP: yahoo_process_authresp(gc, pkt); break; case YAHOO_SERVICE_LIST: yahoo_process_list(gc, pkt); break; case YAHOO_SERVICE_AUTH: yahoo_process_auth(gc, pkt); break; case YAHOO_SERVICE_ADDBUDDY: yahoo_process_addbuddy(gc, pkt); break; case YAHOO_SERVICE_IGNORECONTACT: yahoo_process_ignore(gc, pkt); break; case YAHOO_SERVICE_CONFINVITE: case YAHOO_SERVICE_CONFADDINVITE: yahoo_process_conference_invite(gc, pkt); break; case YAHOO_SERVICE_CONFDECLINE: yahoo_process_conference_decline(gc, pkt); break; case YAHOO_SERVICE_CONFLOGON: yahoo_process_conference_logon(gc, pkt); break; case YAHOO_SERVICE_CONFLOGOFF: yahoo_process_conference_logoff(gc, pkt); break; case YAHOO_SERVICE_CONFMSG: yahoo_process_conference_message(gc, pkt); break; case YAHOO_SERVICE_CHATONLINE: yahoo_process_chat_online(gc, pkt); break; case YAHOO_SERVICE_CHATLOGOUT: yahoo_process_chat_logout(gc, pkt); break; case YAHOO_SERVICE_CHATGOTO: yahoo_process_chat_goto(gc, pkt); break; case YAHOO_SERVICE_CHATJOIN: yahoo_process_chat_join(gc, pkt); break; case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */ case YAHOO_SERVICE_CHATEXIT: yahoo_process_chat_exit(gc, pkt); break; case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */ case YAHOO_SERVICE_CHATADDINVITE: yahoo_process_chat_addinvite(gc, pkt); break; case YAHOO_SERVICE_COMMENT: yahoo_process_chat_message(gc, pkt); break; case YAHOO_SERVICE_P2PFILEXFER: case YAHOO_SERVICE_FILETRANSFER: yahoo_process_filetransfer(gc, pkt); break; case YAHOO_SERVICE_PEEPTOPEER: yahoo_process_p2p(gc, pkt); break; case YAHOO_SERVICE_PICTURE: yahoo_process_picture(gc, pkt); break; case YAHOO_SERVICE_PICTURE_UPDATE: yahoo_process_picture_update(gc, pkt); break; case YAHOO_SERVICE_PICTURE_CHECKSUM: yahoo_process_picture_checksum(gc, pkt); break; case YAHOO_SERVICE_PICTURE_UPLOAD: yahoo_process_picture_upload(gc, pkt); break; case YAHOO_SERVICE_AUDIBLE: yahoo_process_audible(gc, pkt); default: gaim_debug(GAIM_DEBUG_ERROR, "yahoo", "Unhandled service 0x%02x\n", pkt->service); break; }}static void yahoo_pending(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; struct yahoo_data *yd = gc->proto_data; char buf[1024]; int len; len = read(yd->fd, buf, sizeof(buf)); if (len <= 0) { gaim_connection_error(gc, _("Unable to read")); return; } yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen); memcpy(yd->rxqueue + yd->rxlen, buf, len); yd->rxlen += len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -