📄 yahoo.c
字号:
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, purple_connection_get_display_name(gc)); if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf)) purple_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); g_free(buf); g_free(decoded_group);}static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt){ GSList *l = pkt->hash; char *who = NULL; char *base64 = NULL; guchar *decoded; gsize 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; decoded = purple_base64_decode(base64, &len); if (len) { char *tmp = purple_str_binary_to_ascii(decoded, len); purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp); g_free(tmp); } tmp2 = g_strndup((const gchar *)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(PurpleConnection *gc, struct yahoo_packet *pkt){ char *who = NULL, *msg = NULL, *id = 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.locale.bar.baz format eg: base.tw.smiley.smiley43 */ id = pair->value; 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 (!msg) msg = id; if (!who || !msg) return; if (!g_utf8_validate(msg, -1, NULL)) { purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n"); return; } if (!yahoo_privacy_check(gc, who)) { purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n", gc->account->username, who); return; } if (id) { /* "http://us.dl1.yimg.com/download.yahoo.com/dl/aud/"+locale+"/"+id+".swf" */ char **audible_locale = g_strsplit(id, ".", 0); char *buf = g_strdup_printf(_("[ Audible %s/%s/%s.swf ] %s"), YAHOO_AUDIBLE_URL, audible_locale[1], id, msg); g_strfreev(audible_locale); serv_got_im(gc, who, buf, 0, time(NULL)); g_free(buf); } else serv_got_im(gc, who, msg, 0, time(NULL));}static void yahoo_packet_process(PurpleConnection *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_Y6_STATUS_UPDATE: case YAHOO_SERVICE_STATUS_15: 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_LIST_15: yahoo_process_list_15(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_PRESENCE_PERM: case YAHOO_SERVICE_PRESENCE_SESSION: yahoo_process_presence(gc, pkt); break; case YAHOO_SERVICE_P2PFILEXFER: /* This case had no break and continued; thus keeping it this way.*/ yahoo_process_p2pfilexfer(gc, pkt); case YAHOO_SERVICE_FILETRANSFER: yahoo_process_filetransfer(gc, pkt); break; case YAHOO_SERVICE_PEERTOPEER: 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_AVATAR_UPDATE: yahoo_process_avatar_update(gc, pkt); break; case YAHOO_SERVICE_AUDIBLE: yahoo_process_audible(gc, pkt); break; default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", "Unhandled service 0x%02x\n", pkt->service); break; }}static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond){ PurpleConnection *gc = data; struct yahoo_data *yd = gc->proto_data; char buf[1024]; int len; len = read(yd->fd, buf, sizeof(buf)); if (len < 0) { gchar *tmp; if (errno == EAGAIN) /* No worries */ return; tmp = g_strdup_printf(_("Lost connection with server:\n%s"), strerror(errno)); purple_connection_error(gc, tmp); g_free(tmp); return; } else if (len == 0) { purple_connection_error(gc, _("Server closed the connection.")); return; } yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen); memcpy(yd->rxqueue + yd->rxlen, buf, len); yd->rxlen += len; while (1) { struct yahoo_packet *pkt; int pos = 0; int pktlen; if (yd->rxlen < YAHOO_PACKET_HDRLEN) return; if (strncmp((char *)yd->rxqueue, "YMSG", MIN(4, yd->rxlen)) != 0) { /* HEY! This isn't even a YMSG packet. What * are you trying to pull? */ guchar *start; purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n"); start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1); if (start) { g_memmove(yd->rxqueue, start, yd->rxlen - (start - yd->rxqueue)); yd->rxlen -= start - yd->rxqueue; continue; } else { g_free(yd->rxqueue); yd->rxqueue = NULL; yd->rxlen = 0; return; } } pos += 4; /* YMSG */ pos += 2; pos += 2; pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2; purple_debug(PURPLE_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; purple_debug(PURPLE_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) { guchar *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, const gchar *error_message){ PurpleConnection *gc = data; struct yahoo_data *yd; struct yahoo_packet *pkt; if (!PURPLE_CONNECTION_IS_VALID(gc)) { close(source); return; } if (source < 0) { gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), error_message); purple_connection_error(gc, tmp); g_free(tmp); return; } yd = gc->proto_data; yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, 0); yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc)))); yahoo_packet_send_and_free(pkt, yd); gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);}#ifdef TRY_WEBMESSENGER_LOGINstatic void yahoo_got_web_connected(gpointer data, gint source, const gchar *error_message){ PurpleConnection *gc = data; struct yahoo_data *yd; struct yahoo_packet *pkt; if (!PURPLE_CONNECTION_IS_VALID(gc)) { close(source); return; } if (source < 0) { gchar *tmp; tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), error_message); purple_connection_error(gc, tmp); g_free(tmp); return; } yd = gc->proto_data; yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, 0); yahoo_packet_hash(pkt, "sss", 0, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))), 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))), 6, yd->auth); yahoo_packet_send_and_free(pkt, yd); g_free(yd->auth); gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);}static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond){ PurpleConnection *gc = data; PurpleAccount *account = purple_connection_get_account(gc); struct yahoo_data *yd = gc->proto_data; char bufread[2048], *i = bufread, *buf = bufread; int len; GString *s; len = read(source, bufread, sizeof(bufread) - 1); if (len < 0) { gchar *tmp; if (errno == EAGAIN) /* No worries */ return; tmp = g_strdup_printf(_("Lost connection with server:\n%s"), strerror(errno)); purple_connection_error(gc, tmp); g_free(tmp); return; } else if (len == 0) { purple_connection_error(gc, _("Server closed the connection.")); return; } if (yd->rxlen > 0 || !g_strstr_len(buf, len, "\r\n\r\n")) { yd->rxqueue = g_realloc(yd->rxqueue, yd->rxlen + len + 1); memcpy(yd->rxqueue + yd->rxlen, buf, len); yd->rxlen += len; i = buf = (char *)yd->rxqueue; len = yd->rxlen; } buf[len] = '\0'; if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) && strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) { purple_connection_error(gc, _("Received unexpected HTTP response from server.")); return; } s = g_string_sized_new(len); 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); purple_input_remove(gc->inpa); close(source); g_free(yd->rxqueue); yd->rxqueue = NULL; yd->rxlen = 0; /* Now we have our cookies to logi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -