⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yahoo.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	add_req = g_new0(struct yahoo_add_request, 1);	add_req->gc = gc;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 1:			add_req->id = g_strdup(pair->value);			break;		case 3:			add_req->who = g_strdup(pair->value);			break;		case 15: /* time, for when they add us and we're offline */			break;		case 14:			msg = pair->value;			break;		}		l = l->next;	}	if (add_req->id) {		if (msg)			add_req->msg = yahoo_string_decode(gc, msg, FALSE);		/* DONE! this is almost exactly the same as what MSN does,		 * this should probably be moved to the core.		 */		 purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id,                                                    NULL, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL,						    G_CALLBACK(yahoo_buddy_add_authorize_cb), 						    G_CALLBACK(yahoo_buddy_add_deny_reason_cb),                                                    add_req);	} else {		g_free(add_req->id);		g_free(add_req->who);		/*g_free(add_req->msg);*/		g_free(add_req);	}}static void yahoo_buddy_denied_our_add(PurpleConnection *gc, struct yahoo_packet *pkt){	char *who = NULL;	char *msg = NULL;	GSList *l = pkt->hash;	GString *buf = NULL;	struct yahoo_data *yd = gc->proto_data;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 3:			who = pair->value;			break;		case 14:			msg = pair->value;			break;		}		l = l->next;	}	if (who) {		char *msg2;		buf = g_string_sized_new(0);		if (!msg) {			g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list."), who);		} else {			msg2 = yahoo_string_decode(gc, msg, FALSE);			g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2);			g_free(msg2);		}		purple_notify_info(gc, NULL, _("Add buddy rejected"), buf->str);		g_string_free(buf, TRUE);		g_hash_table_remove(yd->friends, who);		purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */		/* TODO: Shouldn't we remove the buddy from our local list? */	}}static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt){	switch (pkt->status) {	case 1:		yahoo_process_status(gc, pkt);		return;	case 3:		yahoo_buddy_added_us(gc, pkt);		break;	case 7:		yahoo_buddy_denied_our_add(gc, pkt);		break;	default:		break;	}}#define OUT_CHARSET "utf-8"static char *yahoo_decode(const char *text){	char *converted = NULL;	char *n, *new;	const char *end, *p;	int i, k;	n = new = g_malloc(strlen (text) + 1);	end = text + strlen(text);	for (p = text; p < end; p++, n++) {		if (*p == '\\') {			if (p[1] >= '0' && p[1] <= '7') {				p += 1;				for (i = 0, k = 0; k < 3; k += 1) {					char c = p[k];					if (c < '0' || c > '7') break;					i *= 8;					i += c - '0';				}				*n = i;				p += k - 1;			} else { /* bug 959248 */				/* If we see a \ not followed by an octal number,				 * it means that it is actually a \\ with one \				 * already eaten by some unknown function.				 * This is arguably broken.				 *				 * I think wing is wrong here, there is no function				 * called that I see that could have done it. I guess				 * it is just really sending single \'s. That's yahoo				 * for you.				 */				*n = *p;			}		}		else			*n = *p;	}	*n = '\0';	if (strstr(text, "\033$B"))		converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);	if (!converted)		converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);	g_free(new);	return converted;}static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt){	PurpleAccount *account = purple_connection_get_account(gc);	struct yahoo_data *yd = gc->proto_data;	char *who = NULL;	char *email = NULL;	char *subj = NULL;	char *yahoo_mail_url = (yd->jp? YAHOOJP_MAIL_URL: YAHOO_MAIL_URL);	int count = 0;	GSList *l = pkt->hash;	if (!purple_account_get_check_mail(account))		return;	while (l) {		struct yahoo_pair *pair = l->data;		if (pair->key == 9)			count = strtol(pair->value, NULL, 10);		else if (pair->key == 43)			who = pair->value;		else if (pair->key == 42)			email = pair->value;		else if (pair->key == 18)			subj = pair->value;		l = l->next;	}	if (who && subj && email && *email) {		char *dec_who = yahoo_decode(who);		char *dec_subj = yahoo_decode(subj);		char *from = g_strdup_printf("%s (%s)", dec_who, email);		purple_notify_email(gc, dec_subj, from, purple_account_get_username(account),						  yahoo_mail_url, NULL, NULL);		g_free(dec_who);		g_free(dec_subj);		g_free(from);	} else if (count > 0) {		const char *to = purple_account_get_username(account);		const char *url = yahoo_mail_url;		purple_notify_emails(gc, count, FALSE, NULL, NULL, &to, &url,						   NULL, NULL);	}}/* This is the y64 alphabet... it's like base64, but has a . and a _ */static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";/* This is taken from Sylpheed by Hiroyuki Yamamoto.  We have our own tobase64 function * in util.c, but it has a bug I don't feel like finding right now ;) */static void to_y64(char *out, const unsigned char *in, gsize inlen)     /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */{	for (; inlen >= 3; inlen -= 3)		{			*out++ = base64digits[in[0] >> 2];			*out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];			*out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];			*out++ = base64digits[in[2] & 0x3f];			in += 3;		}	if (inlen > 0)		{			unsigned char fragment;			*out++ = base64digits[in[0] >> 2];			fragment = (in[0] << 4) & 0x30;			if (inlen > 1)				fragment |= in[1] >> 4;			*out++ = base64digits[fragment];			*out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];			*out++ = '-';		}	*out = '\0';}static void yahoo_process_auth_old(PurpleConnection *gc, const char *seed){	struct yahoo_packet *pack;	PurpleAccount *account = purple_connection_get_account(gc);	const char *name = purple_normalize(account, purple_account_get_username(account));	const char *pass = purple_connection_get_password(gc);	struct yahoo_data *yd = gc->proto_data;	/* So, Yahoo has stopped supporting its older clients in India, and undoubtedly	 * will soon do so in the rest of the world.	 *	 * The new clients use this authentication method.  I warn you in advance, it's	 * bizarre, convoluted, inordinately complicated.  It's also no more secure than	 * crypt() was.  The only purpose this scheme could serve is to prevent third	 * party clients from connecting to their servers.	 *	 * Sorry, Yahoo.	 */	PurpleCipher *cipher;	PurpleCipherContext *context;	guchar digest[16];	char *crypt_result;	char password_hash[25];	char crypt_hash[25];	char *hash_string_p = g_malloc(50 + strlen(name));	char *hash_string_c = g_malloc(50 + strlen(name));	char checksum;	int sv;	char result6[25];	char result96[25];	sv = seed[15];	sv = sv % 8;	cipher = purple_ciphers_find_cipher("md5");	context = purple_cipher_context_new(cipher, NULL);	purple_cipher_context_append(context, (const guchar *)pass, strlen(pass));	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);	to_y64(password_hash, digest, 16);	crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$");	purple_cipher_context_reset(context, NULL);	purple_cipher_context_append(context, (const guchar *)crypt_result, strlen(crypt_result));	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);	to_y64(crypt_hash, digest, 16);	switch (sv) {	case 1:	case 6:		checksum = seed[seed[9] % 16];		g_snprintf(hash_string_p, strlen(name) + 50,			   "%c%s%s%s", checksum, name, seed, password_hash);		g_snprintf(hash_string_c, strlen(name) + 50,			   "%c%s%s%s", checksum, name, seed, crypt_hash);		break;	case 2:	case 7:		checksum = seed[seed[15] % 16];		g_snprintf(hash_string_p, strlen(name) + 50,			   "%c%s%s%s", checksum, seed, password_hash, name);		g_snprintf(hash_string_c, strlen(name) + 50,			   "%c%s%s%s", checksum, seed, crypt_hash, name);		break;	case 3:		checksum = seed[seed[1] % 16];		g_snprintf(hash_string_p, strlen(name) + 50,			   "%c%s%s%s", checksum, name, password_hash, seed);		g_snprintf(hash_string_c, strlen(name) + 50,			   "%c%s%s%s", checksum, name, crypt_hash, seed);		break;	case 4:		checksum = seed[seed[3] % 16];		g_snprintf(hash_string_p, strlen(name) + 50,			   "%c%s%s%s", checksum, password_hash, seed, name);		g_snprintf(hash_string_c, strlen(name) + 50,			   "%c%s%s%s", checksum, crypt_hash, seed, name);		break;	case 0:	case 5:		checksum = seed[seed[7] % 16];			g_snprintf(hash_string_p, strlen(name) + 50,                                   "%c%s%s%s", checksum, password_hash, name, seed);                        g_snprintf(hash_string_c, strlen(name) + 50,				   "%c%s%s%s", checksum, crypt_hash, name, seed);			break;	}	purple_cipher_context_reset(context, NULL);	purple_cipher_context_append(context, (const guchar *)hash_string_p, strlen(hash_string_p));	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);	to_y64(result6, digest, 16);	purple_cipher_context_reset(context, NULL);	purple_cipher_context_append(context, (const guchar *)hash_string_c, strlen(hash_string_c));	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);	purple_cipher_context_destroy(context);	to_y64(result96, digest, 16);	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,	YAHOO_STATUS_AVAILABLE, 0);	yahoo_packet_hash(pack, "ssss", 0, name, 6, result6, 96, result96, 1, name);	yahoo_packet_send_and_free(pack, yd);	g_free(hash_string_p);	g_free(hash_string_c);}/* I'm dishing out some uber-mad props to Cerulean Studios for cracking this * and sending the fix!  Thanks guys. */static void yahoo_process_auth_new(PurpleConnection *gc, const char *seed){	struct yahoo_packet *pack = NULL;	PurpleAccount *account = purple_connection_get_account(gc);	const char *name = purple_normalize(account, purple_account_get_username(account));	const char *pass = purple_connection_get_password(gc);	char *enc_pass;	struct yahoo_data *yd = gc->proto_data;	PurpleCipher			*md5_cipher;	PurpleCipherContext	*md5_ctx;	guchar				md5_digest[16];	PurpleCipher			*sha1_cipher;	PurpleCipherContext	*sha1_ctx1;	PurpleCipherContext	*sha1_ctx2;	char				*alphabet1			= "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";	char				*alphabet2			= "F0E1D2C3B4A59687abcdefghijklmnop";	char				*challenge_lookup	= "qzec2tb3um1olpar8whx4dfgijknsvy5";	char				*operand_lookup		= "+|&%/*^-";	char				*delimit_lookup		= ",;";	char				*password_hash		= (char *)g_malloc(25);	char				*crypt_hash		= (char *)g_malloc(25);	char				*crypt_result		= NULL;	unsigned char		pass_hash_xor1[64];	unsigned char		pass_hash_xor2[64];	unsigned char		crypt_hash_xor1[64];	unsigned char		crypt_hash_xor2[64];	char				resp_6[100];	char				resp_96[100];	unsigned char		digest1[20];	unsigned char		digest2[20];	unsigned char		comparison_src[20];	unsigned char		magic_key_char[4];	const char			*magic_ptr;	unsigned int		magic[64];	unsigned int		magic_work = 0;	unsigned int		magic_4 = 0;	int					x;	int					y;	int					cnt = 0;	int					magic_cnt = 0;	int					magic_len;	memset(password_hash, 0, 25);	memset(crypt_hash, 0, 25);	memset(&pass_hash_xor1, 0, 64);	memset(&pass_hash_xor2, 0, 64);	memset(&crypt_hash_xor1, 0, 64);	memset(&crypt_hash_xor2, 0, 64);	memset(&digest1, 0, 20);	memset(&digest2, 0, 20);	memset(&magic, 0, 64);	memset(&resp_6, 0, 100);	memset(&resp_96, 0, 100);	memset(&magic_key_char, 0, 4);	memset(&comparison_src, 0, 20);	md5_cipher = purple_ciphers_find_cipher("md5");	md5_ctx = purple_cipher_context_new(md5_cipher, NULL);	sha1_cipher = purple_ciphers_find_cipher("sha1");	sha1_ctx1 = purple_cipher_context_new(sha1_cipher, NULL);	sha1_ctx2 = purple_cipher_context_new(sha1_cipher, NULL);	/*	 * Magic: Phase 1.  Generate what seems to be a 30 byte value (could change if base64	 * ends up differently?  I don't remember and I'm tired, so use a 64 byte buffer.	 */	magic_ptr = seed;	while (*magic_ptr != (int)NULL) {		char   *loc;		/* Ignore parentheses. */		if (*magic_ptr == '(' || *magic_ptr == ')') {			magic_ptr++;			continue;		}		/* Characters and digits verify against the challenge lookup. */		if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {			loc = strchr(challenge_lookup, *magic_ptr);			if (!loc) {			  /* SME XXX Error - disconnect here */			}			/* Get offset into lookup table and shl 3. */			magic_work = loc - challenge_lookup;			magic_work <<= 3;			magic_ptr++;			continue;		} else {			unsigned int	local_store;			loc = strchr(operand_lookup, *magic_ptr);			if (!loc) {				/* SME XXX Disconnect */			}			local_store = loc - operand_lookup;			/* Oops; how did this happen? */			if (magic_cnt >= 64)				break;			magic[magic_cnt++] = magic_work | local_store;			magic_ptr++;			continue;		}			}	magic_len = magic_cnt;	magic_cnt = 0;	/* Magic: Phase 2.  Take generated magic value and sprinkle fairy	 * dust on the values.	 */	for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) {		unsigned char	byte1;		unsigned char	byte2;		/* Bad.  Abort. */		if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len))			break;		byte1 = magic[magic_cnt];		byte2 = magic[magic_cnt+1];		byte1 *= 0xcd;		byte1 ^= byte2;		magic[magic_cnt+1] = byte1;			}	/*	 * Magic: Phase 3.  This computes 20 bytes.  The first 4 bytes are used as our magic	 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -