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

📄 yahoo_picture.c

📁 yahoo message protocol stack
💻 C
字号:
/* * gaim * * Gaim is the legal property of its developers, whose names are too numerous * to list here.  Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include "internal.h"#include "account.h"#include "accountopt.h"#include "blist.h"#include "debug.h"#include "prpl.h"#include "proxy.h"#include "util.h"#include "yahoo.h"#include "yahoo_friend.h"#include "yahoo_picture.h"struct yahoo_fetch_picture_data {	GaimConnection *gc;	char *who;	int checksum;};void yahoo_fetch_picture_cb(void *user_data, const char *pic_data, size_t len){	struct yahoo_fetch_picture_data *d = user_data;	GaimBuddy *b;	if (GAIM_CONNECTION_IS_VALID(d->gc) && len) {		gaim_buddy_icons_set_for_user(gaim_connection_get_account(d->gc), d->who, (void *)pic_data, len);		b = gaim_find_buddy(gaim_connection_get_account(d->gc), d->who);		if (b)			gaim_blist_node_set_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY, d->checksum);	} else {		gaim_debug_error("yahoo", "Fetching buddy icon failed.\n");	}	g_free(d->who);	g_free(d);}void yahoo_process_picture(GaimConnection *gc, struct yahoo_packet *pkt){	GSList *l = pkt->hash;	char *who = NULL, *us = NULL;	gboolean got_icon_info = FALSE, send_icon_info = FALSE;	char *url = NULL;	int checksum = 0;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 1:		case 4:			who = pair->value;			break;		case 5:			us = pair->value;			break;		case 13: {				int tmp;				tmp = strtol(pair->value, NULL, 10);				if (tmp == 1) {					send_icon_info = TRUE;				} else if (tmp == 2) {					got_icon_info = TRUE;				}				break;			}		case 20:			url = pair->value;			break;		case 192:			checksum = strtol(pair->value, NULL, 10);			break;		}		l = l->next;	}	/* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */	if (who && got_icon_info && url && !strncasecmp(url, "http://", 7)) {		/* TODO: make this work p2p, try p2p before the url */		struct yahoo_fetch_picture_data *data;		GaimBuddy *b = gaim_find_buddy(gc->account, who);		if (b && (checksum == gaim_blist_node_get_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY)))			return;		data = g_new0(struct yahoo_fetch_picture_data, 1);		data->gc = gc;		data->who = g_strdup(who);		data->checksum = checksum;		gaim_url_fetch(url, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE,		               yahoo_fetch_picture_cb, data);	} else if (who && send_icon_info) {		yahoo_send_picture_info(gc, who);	}}void yahoo_process_picture_update(GaimConnection *gc, struct yahoo_packet *pkt){	GSList *l = pkt->hash;	char *who = NULL;	int icon = 0;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 4:			who = pair->value;			break;		case 5:			/* us */			break;		case 206:			icon = strtol(pair->value, NULL, 10);			break;		}		l = l->next;	}	if (who) {		if (icon == 2)			yahoo_send_picture_request(gc, who);		else if ((icon == 0) || (icon == 1)) {			GaimBuddy *b = gaim_find_buddy(gc->account, who);			YahooFriend *f;			gaim_buddy_icons_set_for_user(gc->account, who, NULL, 0);			if (b)				gaim_blist_node_remove_setting((GaimBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY);			if ((f = yahoo_friend_find(gc, who)))				yahoo_friend_set_buddy_icon_need_request(f, TRUE);			gaim_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who);		}	}}void yahoo_process_picture_checksum(GaimConnection *gc, struct yahoo_packet *pkt){	GSList *l = pkt->hash;	char *who = NULL;	int checksum = 0;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 4:			who = pair->value;			break;		case 5:			/* us */			break;		case 192:			checksum = strtol(pair->value, NULL, 10);			break;		}		l = l->next;	}	if (who) {		GaimBuddy *b = gaim_find_buddy(gc->account, who);		if (b && (checksum != gaim_blist_node_get_int((GaimBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY)))			yahoo_send_picture_request(gc, who);	}}void yahoo_process_picture_upload(GaimConnection *gc, struct yahoo_packet *pkt){	GaimAccount *account = gaim_connection_get_account(gc);	struct yahoo_data *yd = gc->proto_data;	GSList *l = pkt->hash;	char *url = NULL;	while (l) {		struct yahoo_pair *pair = l->data;		switch (pair->key) {		case 5:			/* us */			break;		case 27:			/* filename on our computer. */			break;		case 20: /* url at yahoo */			url = pair->value;		case 38: /* timestamp */			break;		}		l = l->next;	}	if (url) {		if (yd->picture_url)			g_free(yd->picture_url);		yd->picture_url = g_strdup(url);		gaim_account_set_string(account, YAHOO_PICURL_SETTING, url);		gaim_account_set_int(account, YAHOO_PICCKSUM_SETTING, yd->picture_checksum);		yahoo_send_picture_update(gc, 2);		yahoo_send_picture_checksum(gc);	}}void yahoo_send_picture_info(GaimConnection *gc, const char *who){	struct yahoo_data *yd = gc->proto_data;	struct yahoo_packet *pkt;	char *buf;	if (!yd->picture_url) {		gaim_debug_warning("yahoo", "Attempted to send picture info without a picture\n");		return;	}	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 4, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 5, who);	yahoo_packet_hash(pkt, 13, "2");	yahoo_packet_hash(pkt, 20, yd->picture_url);	buf = g_strdup_printf("%d", yd->picture_checksum);	yahoo_packet_hash(pkt, 192, buf);	yahoo_send_packet(yd, pkt);	yahoo_packet_free(pkt);	g_free(buf);}void yahoo_send_picture_request(GaimConnection *gc, const char *who){	struct yahoo_data *yd = gc->proto_data;	struct yahoo_packet *pkt;	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);	yahoo_packet_hash(pkt, 4, gaim_connection_get_display_name(gc)); /* me */	yahoo_packet_hash(pkt, 5, who); /* the other guy */	yahoo_packet_hash(pkt, 13, "1"); /* 1 = request, 2 = reply */	yahoo_send_packet(yd, pkt);	yahoo_packet_free(pkt);}void yahoo_send_picture_checksum(GaimConnection *gc){	struct yahoo_data *yd = gc->proto_data;	struct yahoo_packet *pkt;	char *cksum = g_strdup_printf("%d", yd->picture_checksum);	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0);	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 212, "1");	yahoo_packet_hash(pkt, 192, cksum);	yahoo_send_packet(yd, pkt);	yahoo_packet_free(pkt);	g_free(cksum);}void yahoo_send_picture_update_to_user(GaimConnection *gc, const char *who, int type){	struct yahoo_data *yd = gc->proto_data;	struct yahoo_packet *pkt;	char *typestr = g_strdup_printf("%d", type);	pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0);	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 5, who);	yahoo_packet_hash(pkt, 206, typestr);	yahoo_send_packet(yd, pkt);	yahoo_packet_free(pkt);	g_free(typestr);}struct yspufe {	GaimConnection *gc;	int type;};static void yahoo_send_picture_update_foreach(gpointer key, gpointer value, gpointer data){	char *who = key;	YahooFriend *f = value;	struct yspufe *d = data;	if (f->status != YAHOO_STATUS_OFFLINE)		yahoo_send_picture_update_to_user(d->gc, who, d->type);}void yahoo_send_picture_update(GaimConnection *gc, int type){	struct yahoo_data *yd = gc->proto_data;	struct yspufe data;	data.gc = gc;	data.type = type;	g_hash_table_foreach(yd->friends, yahoo_send_picture_update_foreach, &data);}void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d){	gaim_debug_misc("yahoo", "In yahoo_buddy_icon_upload_data_free()\n");	if (d->str)		g_string_free(d->str, TRUE);	if (d->filename)		g_free(d->filename);	if (d->watcher)		gaim_input_remove(d->watcher);	if (d->fd != -1)		close(d->fd);	g_free(d);}/* we could care less about the server's responce, but yahoo gets grumpy if we close before it sends it */static void yahoo_buddy_icon_upload_reading(gpointer data, gint source, GaimInputCondition condition){	struct yahoo_buddy_icon_upload_data *d = data;	GaimConnection *gc = d->gc;	char buf[1024];	if (!GAIM_CONNECTION_IS_VALID(gc)) {		yahoo_buddy_icon_upload_data_free(d);		return;	}	if (read(d->fd, buf, sizeof(buf)) <= 0)		yahoo_buddy_icon_upload_data_free(d);}static void yahoo_buddy_icon_upload_pending(gpointer data, gint source, GaimInputCondition condition){	struct yahoo_buddy_icon_upload_data *d = data;	GaimConnection *gc = d->gc;	ssize_t wrote;	if (!GAIM_CONNECTION_IS_VALID(gc)) {		yahoo_buddy_icon_upload_data_free(d);		return;	}	wrote = write(d->fd, d->str->str + d->pos, d->str->len - d->pos);	if (wrote <= 0) {		yahoo_buddy_icon_upload_data_free(d);		return;	}	d->pos += wrote;	if (d->pos >= d->str->len) {		gaim_debug_misc("yahoo", "Finished uploading buddy icon.\n");		gaim_input_remove(d->watcher);		d->watcher = gaim_input_add(d->fd, GAIM_INPUT_READ, yahoo_buddy_icon_upload_reading, d);	}}static void yahoo_buddy_icon_upload_connected(gpointer data, gint source, GaimInputCondition condition){	struct yahoo_buddy_icon_upload_data *d = data;	struct yahoo_packet *pkt;	gchar *size, *post, *buf;	int content_length;	GaimConnection *gc;	GaimAccount *account;	struct yahoo_data *yd;	if (!d)		return;	gc = d->gc;	account = gaim_connection_get_account(gc);	yd = gc->proto_data;	if (source < 0) {		gaim_debug_error("yahoo", "Buddy icon upload failed, no file desc.\n");		yahoo_buddy_icon_upload_data_free(d);		return;	}	d->fd = source;	d->watcher = gaim_input_add(d->fd, GAIM_INPUT_WRITE, yahoo_buddy_icon_upload_pending, d);	pkt = yahoo_packet_new(0xc2, YAHOO_STATUS_AVAILABLE, yd->session_id);	size = g_strdup_printf("%" G_GSIZE_FORMAT, d->str->len);	/* 1 = me, 38 = expire time(?), 0 = me, 28 = size, 27 = filename, 14 = NULL, 29 = data */	yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 38, "604800"); /* time til expire */	gaim_account_set_int(account, YAHOO_PICEXPIRE_SETTING, time(NULL) + 604800);	yahoo_packet_hash(pkt, 0, gaim_connection_get_display_name(gc));	yahoo_packet_hash(pkt, 28, size);	yahoo_packet_hash(pkt, 27, d->filename);	yahoo_packet_hash(pkt, 14, "");	content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);	buf = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t);	post = g_strdup_printf("POST /notifyft HTTP/1.0\r\n"	                       "Content-length: %" G_GSIZE_FORMAT "\r\n"	                       "Host: %s:%d\r\n"	                       "Cookie: %s\r\n"	                       "\r\n",	                       content_length + 4 + d->str->len,			       gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST),			       gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),			       buf);	write(d->fd, post, strlen(post));	yahoo_send_packet_special(d->fd, pkt, 8);	yahoo_packet_free(pkt);	write(d->fd, "29\xc0\x80", 4);	g_free(size);	g_free(post);	g_free(buf);}void yahoo_buddy_icon_upload(GaimConnection *gc, struct yahoo_buddy_icon_upload_data *d){	GaimAccount *account = gaim_connection_get_account(gc);	struct yahoo_data *yd = gc->proto_data;	if (yd->jp) {		if (gaim_proxy_connect(account, gaim_account_get_string(account, "xferjp_host",  YAHOOJP_XFER_HOST),		                       gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),		                       yahoo_buddy_icon_upload_connected, d) == -1)		{			gaim_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n");			yahoo_buddy_icon_upload_data_free(d);		}	} else {		if (gaim_proxy_connect(account, gaim_account_get_string(account, "xfer_host",  YAHOO_XFER_HOST),		                       gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),		                       yahoo_buddy_icon_upload_connected, d) == -1)		{			gaim_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n");			yahoo_buddy_icon_upload_data_free(d);		}	}}void yahoo_set_buddy_icon(GaimConnection *gc, const char *iconfile){	struct yahoo_data *yd = gc->proto_data;	GaimAccount *account = gc->account;	FILE *file;	struct stat st;	if (iconfile == NULL) {		if (yd->picture_url)			g_free(yd->picture_url);		yd->picture_url = NULL;		gaim_account_set_string(account, YAHOO_PICURL_SETTING, NULL);		gaim_account_set_int(account, YAHOO_PICCKSUM_SETTING, 0);		gaim_account_set_int(account, YAHOO_PICEXPIRE_SETTING, 0);		if (yd->logged_in)			yahoo_send_picture_update(gc, 0);		/* TODO: check if we're connected and tell everyone we ain't not one no more */	} else if (!stat(iconfile, &st)) {		file = fopen(iconfile, "rb");		if (file) {			GString *s = g_string_sized_new(st.st_size);			size_t len;			struct yahoo_buddy_icon_upload_data *d;			int oldcksum = gaim_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0);			int expire = gaim_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0);			const char *oldurl = gaim_account_get_string(account, YAHOO_PICURL_SETTING, NULL);			g_string_set_size(s, st.st_size);			len = fread(s->str, 1, st.st_size, file);			fclose(file);			g_string_set_size(s, len);			yd->picture_checksum = g_string_hash(s);			if ((yd->picture_checksum == oldcksum) && (expire > (time(NULL) + 60*60*24)) &&			    oldcksum && expire && oldurl) {				gaim_debug_misc("yahoo", "buddy icon is up to date. Not reuploading.\n");				g_string_free(s, TRUE);				if (yd->picture_url)					g_free(yd->picture_url);				yd->picture_url = g_strdup(oldurl);				return;			}			d = g_new0(struct yahoo_buddy_icon_upload_data, 1);			d->gc = gc;			d->str = s;			d->fd = -1;			d->filename = g_strdup(iconfile);			if (!yd->logged_in) {				yd->picture_upload_todo = d;				return;			}			yahoo_buddy_icon_upload(gc, d);		} else			gaim_debug_error("yahoo",				   "Can't open buddy icon file!\n");	} else		gaim_debug_error("yahoo",			   "Can't stat buddy icon file!\n");}

⌨️ 快捷键说明

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