📄 yahoo.c
字号:
while (1) { struct yahoo_packet *pkt; int pos = 0; int pktlen; if (yd->rxlen < YAHOO_PACKET_HDRLEN) return; pos += 4; /* YMSG */ pos += 2; pos += 2; pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2; gaim_debug(GAIM_DEBUG_MISC, "yahoo", "%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen); if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen)) return; yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen); pkt = yahoo_packet_new(0, 0, 0); pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2; pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4; gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Yahoo Service: 0x%02x Status: %d\n", pkt->service, pkt->status); pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4; yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen); yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen; if (yd->rxlen) { char *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen); g_free(yd->rxqueue); yd->rxqueue = tmp; } else { g_free(yd->rxqueue); yd->rxqueue = NULL; } yahoo_packet_process(gc, pkt); yahoo_packet_free(pkt); }}static void yahoo_got_connected(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; struct yahoo_data *yd; struct yahoo_packet *pkt; if (!g_list_find(gaim_connections_get_all(), gc)) { close(source); return; } if (source < 0) { gaim_connection_error(gc, _("Unable to connect.")); return; } yd = gc->proto_data; yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);}static void yahoo_got_web_connected(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; struct yahoo_data *yd; struct yahoo_packet *pkt; if (!g_list_find(gaim_connections_get_all(), gc)) { close(source); return; } if (source < 0) { gaim_connection_error(gc, _("Unable to connect.")); return; } yd = gc->proto_data; yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, 0); yahoo_packet_hash(pkt, 0, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); yahoo_packet_hash(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); yahoo_packet_hash(pkt, 6, yd->auth); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); g_free(yd->auth); gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);}static void yahoo_web_pending(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; GaimAccount *account = gaim_connection_get_account(gc); struct yahoo_data *yd = gc->proto_data; char buf[2048], *i = buf; int len; GString *s; len = read(source, buf, sizeof(buf)-1); if (len <= 0 || (strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) && strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) { gaim_connection_error(gc, _("Unable to read")); return; } s = g_string_sized_new(len); buf[sizeof(buf)-1] = '\0'; while ((i = strstr(i, "Set-Cookie: "))) { i += strlen("Set-Cookie: "); for (;*i != ';' && *i != '\0'; i++) g_string_append_c(s, *i); g_string_append(s, "; "); } yd->auth = g_string_free(s, FALSE); gaim_input_remove(gc->inpa); close(source); /* Now we have our cookies to login with. I'll go get the milk. */ if (gaim_proxy_connect(account, "wcs2.msg.dcn.yahoo.com", gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_web_connected, gc) != 0) { gaim_connection_error(gc, _("Connection problem")); return; } }static void yahoo_got_cookies(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; struct yahoo_data *yd = gc->proto_data; if (source < 0) { gaim_connection_error(gc, _("Unable to connect.")); return; } write(source, yd->auth, strlen(yd->auth)); g_free(yd->auth); gc->inpa = gaim_input_add(source, GAIM_INPUT_READ, yahoo_web_pending, gc);}static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url){ if (!strcmp(key, "passwd")) return; url = g_string_append_c(url, '&'); url = g_string_append(url, key); url = g_string_append_c(url, '='); if (!strcmp(key, ".save") || !strcmp(key, ".js")) url = g_string_append_c(url, '1'); else if (!strcmp(key, ".challenge")) url = g_string_append(url, val); else url = g_string_append(url, gaim_url_encode(val));}static GHashTable *yahoo_login_page_hash(const char *buf, size_t len){ GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); const char *c = buf; char *d; char name[64], value[64]; int count = sizeof(name)-1; while ((c < (buf + len)) && (c = strstr(c, "<input "))) { c = strstr(c, "name=\"") + strlen("name=\""); for (d = name; *c!='"' && count; c++, d++, count--) *d = *c; *d = '\0'; count = sizeof(value)-1; d = strstr(c, "value=\"") + strlen("value=\""); if (strchr(c, '>') < d) break; for (c = d, d = value; *c!='"' && count; c++, d++, count--) *d = *c; *d = '\0'; g_hash_table_insert(hash, g_strdup(name), g_strdup(value)); } return hash;}static void yahoo_login_page_cb(void *user_data, const char *buf, size_t len){ GaimConnection *gc = (GaimConnection *)user_data; GaimAccount *account = gaim_connection_get_account(gc); struct yahoo_data *yd = gc->proto_data; const char *sn = gaim_account_get_username(account); const char *pass = gaim_account_get_password(account); GHashTable *hash = yahoo_login_page_hash(buf, len); GString *url = g_string_new("GET /config/login?login="); char md5[33], *hashp = md5, *chal; int i; md5_byte_t result[16]; md5_state_t ctx; url = g_string_append(url, sn); url = g_string_append(url, "&passwd="); md5_init(&ctx); md5_append(&ctx, pass, strlen(pass)); md5_finish(&ctx, result); for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", result[i]); hashp += 2; } chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL); md5_init(&ctx); md5_append(&ctx, chal, strlen(chal)); md5_finish(&ctx, result); hashp = md5; for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", result[i]); hashp += 2; } /* md5_init(&ctx); md5_append(&ctx, md5, strlen(md5)); md5_finish(&ctx, result); hashp = md5; for (i = 0; i < 16; ++i) { g_snprintf(hashp, 3, "%02x", result[i]); hashp += 2; } */ g_free(chal); url = g_string_append(url, md5); g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url); url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n" "Host: login.yahoo.com\r\n\r\n"); g_hash_table_destroy(hash); yd->auth = g_string_free(url, FALSE); if (gaim_proxy_connect(account, "login.yahoo.com", 80, yahoo_got_cookies, gc) != 0) { gaim_connection_error(gc, _("Connection problem")); return; }}static void yahoo_server_check(GaimAccount *account){ const char *server; server = gaim_account_get_string(account, "server", YAHOO_PAGER_HOST); if (strcmp(server, "scs.yahoo.com") == 0) gaim_account_set_string(account, "server", YAHOO_PAGER_HOST);}static void yahoo_picture_check(GaimAccount *account){ GaimConnection *gc = gaim_account_get_connection(account); const char *buddyicon; buddyicon = gaim_account_get_buddy_icon(account); yahoo_set_buddy_icon(gc, buddyicon);}static void yahoo_login(GaimAccount *account) { GaimConnection *gc = gaim_account_get_connection(account); struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1); gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_NO_URLDESC; gaim_connection_update_progress(gc, _("Connecting"), 1, 2); gaim_connection_set_display_name(gc, gaim_account_get_username(account)); yd->fd = -1; yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); yd->confs = NULL; yd->conf_id = 2; yahoo_server_check(account); yahoo_picture_check(account); if (gaim_account_get_bool(account, "yahoojp", FALSE)) { yd->jp = TRUE; if (gaim_proxy_connect(account, gaim_account_get_string(account, "serverjp", YAHOOJP_PAGER_HOST), gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_connected, gc) != 0) { gaim_connection_error(gc, _("Connection problem")); return; } } else { yd->jp = FALSE; if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_connected, gc) != 0) { gaim_connection_error(gc, _("Connection problem")); return; } }}static void yahoo_close(GaimConnection *gc) { struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; GSList *l; for (l = yd->confs; l; l = l->next) { GaimConversation *conv = l->data; yahoo_conf_leave(yd, gaim_conversation_get_name(conv), gaim_connection_get_display_name(gc), gaim_conv_chat_get_users(GAIM_CONV_CHAT(conv))); } g_slist_free(yd->confs); g_hash_table_destroy(yd->friends); if (yd->chat_name) g_free(yd->chat_name); if (yd->cookie_y) g_free(yd->cookie_y); if (yd->cookie_t) g_free(yd->cookie_t); if (yd->fd >= 0) close(yd->fd); if (yd->rxqueue) g_free(yd->rxqueue); yd->rxlen = 0; if (yd->picture_url) g_free(yd->picture_url); if (yd->picture_upload_todo) yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo); if (yd->ycht) ycht_connection_close(yd->ycht); if (gc->inpa) gaim_input_remove(gc->inpa); g_free(yd);}static const char *yahoo_list_icon(GaimAccount *a, GaimBuddy *b){ return "yahoo";}static void yahoo_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne){ int i = 0; char *emblems[4] = {NULL,NULL,NULL,NULL}; GaimAccount *account; GaimConnection *gc; struct yahoo_data *yd; YahooFriend *f; if (!b || !(account = b->account) || !(gc = gaim_account_get_connection(account)) || !(yd = gc->proto_data)) return; f = yahoo_friend_find(gc, b->name); if (!f) { *se = "notauthorized"; return; } if (b->present == GAIM_BUDDY_OFFLINE) { *se = "offline"; return; } else { if (f->away) emblems[i++] = "away"; if (f->sms) emblems[i++] = "wireless"; if (yahoo_friend_get_game(f)) emblems[i++] = "game"; } *se = emblems[0]; *sw = emblems[1]; *nw = emblems[2]; *ne = emblems[3];}static char *yahoo_get_status_string(enum yahoo_status a){ switch (a) { case YAHOO_STATUS_BRB: return _("Be Right Back"); case YAHOO_STATUS_BUSY: return _("Busy"); case YAHOO_STATUS_NOTATHOME: return _("Not At Home"); case YAHOO_STATUS_NOTATDESK: return _("Not At Desk"); case YAHOO_STATUS_NOTINOFFICE: return _("Not In Office"); case YAHOO_STATUS_ONPHONE: return _("On The Phone"); case YAHOO_STATUS_ONVACATION: return _("On Vacation"); case YAHOO_STATUS_OUTTOLUNCH: return _("Out To Lunch"); case YAHOO_STATUS_STEPPEDOUT: return _("Stepped Out"); case YAHOO_STATUS_INVISIBLE: return _("Invisible"); case YAHOO_STATUS_IDLE: return _("Idle"); case YAHOO_STATUS_OFFLINE: return _("Offline"); default: return _("Online"); }}static void yahoo_initiate_conference(GaimBlistNode *node, gpointer data) { GaimBuddy *buddy; GaimConnection *gc; GHashTable *components; struct yahoo_data *yd; int id; g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); buddy = (GaimBuddy *) node; gc = gaim_account_get_connection(buddy->account); yd = gc->proto_data; id = yd->conf_id; components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_replace(components, g_strdup("room"), g_strdup_printf("%s-%d", gaim_connection_get_display_name(gc), id)); g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference...")); g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference")); yahoo_c_join(gc, components); g_hash_table_destroy(components); yahoo_c_invite(gc, id, "Join my conference...", buddy->name);}static void yahoo_game(GaimBlistNode *node, gpointer data) { GaimBuddy *buddy; GaimConnection *gc; struct yahoo_data *yd; const char *game; char *game2; char *t; char url[256]; YahooFriend *f; g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); buddy = (GaimBuddy *) node; gc = gaim_account_get_connection(buddy->account); yd = (struct yahoo_data *) gc->proto_data; f = yahoo_friend_find(gc, buddy->name); if (!f) return; game = yahoo_friend_get_game(f); if (!game) return; t = game2 = g_strdup(strstr(game, "ante?room=")); while (*t && *t != '\t') t++; *t = 0; g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2); gaim_notify_uri(gc, url); g_free(game2);}static char *yahoo_status_text(GaimBuddy *b){ YahooFriend *f = NULL; const char *msg; f = yahoo_friend_find(b->account->gc, b->name); if (!f) return g_strdup(_("Not on server list")); switch (f->status) { case YAHOO_STATUS_AVAILABLE: return NULL; case YAHOO_STATUS_IDLE: if (f->idle == -1) return g_strdup(yahoo_get_status_string(f->status)); return NULL; case YAHOO_STATUS_CUSTOM: if (!(msg = yahoo_friend_get_status_message(f))) return NULL; return g_markup_escape_text(msg, strlen(msg)); default: return g_strdup(yahoo_get_status_string(f->status)); }}char *yahoo_tooltip_text(GaimBuddy *b){ YahooFriend *f; char *escaped, *status, *ret; f = yahoo_friend_find(b->account->gc, b->name); if (!f) status = g_strdup_printf("\n%s", _("Not on server list")); else switch (f->status) { case YAHOO_STATUS_IDLE: if (f->idle == -1) { status = g_strdup(yahoo_get_status_string(f->status)); break; } return NULL; case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -