src/protocols/msn/slp.c

changeset 14253
b63ebf84c42b
parent 14252
d10dda2777a9
child 14254
77edc7a6191a
--- a/src/protocols/msn/slp.c	Sat Aug 19 00:24:14 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1138 +0,0 @@
-/**
- * @file msnslp.c MSNSLP support
- *
- * 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 "msn.h"
-#include "slp.h"
-#include "slpcall.h"
-#include "slpmsg.h"
-#include "slpsession.h"
-
-#include "object.h"
-#include "user.h"
-#include "switchboard.h"
-
-/* ms to delay between sending buddy icon requests to the server. */
-#define BUDDY_ICON_DELAY 20000
-
-static void send_ok(MsnSlpCall *slpcall, const char *branch,
-					const char *type, const char *content);
-
-static void send_decline(MsnSlpCall *slpcall, const char *branch,
-						 const char *type, const char *content);
-
-void msn_request_user_display(MsnUser *user);
-
-/**************************************************************************
- * Util
- **************************************************************************/
-
-static char *
-get_token(const char *str, const char *start, const char *end)
-{
-	const char *c, *c2;
-
-	if ((c = strstr(str, start)) == NULL)
-		return NULL;
-
-	c += strlen(start);
-
-	if (end != NULL)
-	{
-		if ((c2 = strstr(c, end)) == NULL)
-			return NULL;
-
-		return g_strndup(c, c2 - c);
-	}
-	else
-	{
-		/* This has to be changed */
-		return g_strdup(c);
-	}
-
-}
-
-/**************************************************************************
- * Xfer
- **************************************************************************/
-
-static void
-msn_xfer_init(GaimXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	/* MsnSlpLink *slplink; */
-	char *content;
-
-	gaim_debug_info("msn", "xfer_init\n");
-
-	slpcall = xfer->data;
-
-	/* Send Ok */
-	content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-							  slpcall->session_id);
-
-	send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-			content);
-
-	g_free(content);
-	msn_slplink_unleash(slpcall->slplink);
-}
-
-void
-msn_xfer_cancel(GaimXfer *xfer)
-{
-	MsnSlpCall *slpcall;
-	char *content;
-
-	g_return_if_fail(xfer != NULL);
-	g_return_if_fail(xfer->data != NULL);
-
-	slpcall = xfer->data;
-
-	if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL)
-	{
-		if (slpcall->started)
-		{
-			msn_slp_call_close(slpcall);
-		}
-		else
-		{
-			content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-									slpcall->session_id);
-
-			send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-						content);
-
-			g_free(content);
-			msn_slplink_unleash(slpcall->slplink);
-
-			msn_slp_call_destroy(slpcall);
-		}
-	}
-}
-
-void
-msn_xfer_progress_cb(MsnSlpCall *slpcall, gsize total_length, gsize len, gsize offset)
-{
-	GaimXfer *xfer;
-
-	xfer = slpcall->xfer;
-
-	xfer->bytes_sent = (offset + len);
-	xfer->bytes_remaining = total_length - (offset + len);
-
-	gaim_xfer_update_progress(xfer);
-}
-
-void
-msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session)
-{
-	if ((gaim_xfer_get_status(slpcall->xfer) != GAIM_XFER_STATUS_DONE) &&
-		(gaim_xfer_get_status(slpcall->xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE) &&
-		(gaim_xfer_get_status(slpcall->xfer) != GAIM_XFER_STATUS_CANCEL_LOCAL))
-	{
-		gaim_xfer_cancel_remote(slpcall->xfer);
-	}
-}
-
-void
-msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body,
-					  gsize size)
-{
-	gaim_xfer_set_completed(slpcall->xfer, TRUE);
-}
-
-/**************************************************************************
- * SLP Control
- **************************************************************************/
-
-#if 0
-static void
-got_transresp(MsnSlpCall *slpcall, const char *nonce,
-			  const char *ips_str, int port)
-{
-	MsnDirectConn *directconn;
-	char **ip_addrs, **c;
-
-	directconn = msn_directconn_new(slpcall->slplink);
-
-	directconn->initial_call = slpcall;
-
-	/* msn_directconn_parse_nonce(directconn, nonce); */
-	directconn->nonce = g_strdup(nonce);
-
-	ip_addrs = g_strsplit(ips_str, " ", -1);
-
-	for (c = ip_addrs; *c != NULL; c++)
-	{
-		gaim_debug_info("msn", "ip_addr = %s\n", *c);
-		if (msn_directconn_connect(directconn, *c, port))
-			break;
-	}
-
-	g_strfreev(ip_addrs);
-}
-#endif
-
-static void
-send_ok(MsnSlpCall *slpcall, const char *branch,
-		const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-
-	slplink = slpcall->slplink;
-
-	/* 200 OK */
-	slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-								"MSNSLP/1.0 200 OK",
-								branch, type, content);
-
-#ifdef MSN_DEBUG_SLP
-	slpmsg->info = "SLP 200 OK";
-	slpmsg->text_body = TRUE;
-#endif
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-
-	msn_slp_call_session_init(slpcall);
-}
-
-static void
-send_decline(MsnSlpCall *slpcall, const char *branch,
-			 const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-
-	slplink = slpcall->slplink;
-
-	/* 603 Decline */
-	slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-								"MSNSLP/1.0 603 Decline",
-								branch, type, content);
-
-#ifdef MSN_DEBUG_SLP
-	slpmsg->info = "SLP 603 Decline";
-	slpmsg->text_body = TRUE;
-#endif
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-}
-
-#define MAX_FILE_NAME_LEN 0x226
-
-static void
-got_sessionreq(MsnSlpCall *slpcall, const char *branch,
-			   const char *euf_guid, const char *context)
-{
-	if (!strcmp(euf_guid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6"))
-	{
-		/* Emoticon or UserDisplay */
-		MsnSlpSession *slpsession;
-		MsnSlpLink *slplink;
-		MsnSlpMessage *slpmsg;
-		MsnObject *obj;
-		char *msnobj_data;
-		const char *file_name;
-		char *content;
-		gsize len;
-		int type;
-
-		/* Send Ok */
-		content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-								  slpcall->session_id);
-
-		send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody",
-				content);
-
-		g_free(content);
-
-		slplink = slpcall->slplink;
-
-		msnobj_data = (char *)gaim_base64_decode(context, &len);
-		obj = msn_object_new_from_string(msnobj_data);
-		type = msn_object_get_type(obj);
-		g_free(msnobj_data);
-
-		if (!(type == MSN_OBJECT_USERTILE))
-		{
-			gaim_debug_error("msn", "Wrong object?\n");
-			msn_object_destroy(obj);
-			g_return_if_reached();
-		}
-
-		file_name = msn_object_get_real_location(obj);
-
-		if (file_name == NULL)
-		{
-			gaim_debug_error("msn", "Wrong object.\n");
-			msn_object_destroy(obj);
-			g_return_if_reached();
-		}
-
-		msn_object_destroy(obj);
-
-		slpsession = msn_slplink_find_slp_session(slplink,
-												  slpcall->session_id);
-
-		/* DATA PREP */
-		slpmsg = msn_slpmsg_new(slplink);
-		slpmsg->slpcall = slpcall;
-		slpmsg->slpsession = slpsession;
-		slpmsg->session_id = slpsession->id;
-		msn_slpmsg_set_body(slpmsg, NULL, 4);
-#ifdef MSN_DEBUG_SLP
-		slpmsg->info = "SLP DATA PREP";
-#endif
-		msn_slplink_queue_slpmsg(slplink, slpmsg);
-
-		/* DATA */
-		slpmsg = msn_slpmsg_new(slplink);
-		slpmsg->slpcall = slpcall;
-		slpmsg->slpsession = slpsession;
-		slpmsg->flags = 0x20;
-#ifdef MSN_DEBUG_SLP
-		slpmsg->info = "SLP DATA";
-#endif
-		msn_slpmsg_open_file(slpmsg, file_name);
-		msn_slplink_queue_slpmsg(slplink, slpmsg);
-	}
-	else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683"))
-	{
-		/* File Transfer */
-		GaimAccount *account;
-		GaimXfer *xfer;
-		char *bin;
-		gsize bin_len;
-		guint32 file_size;
-		char *file_name;
-		gunichar2 *uni_name;
-
-		account = slpcall->slplink->session->account;
-
-		slpcall->cb = msn_xfer_completed_cb;
-		slpcall->end_cb = msn_xfer_end_cb;
-		slpcall->progress_cb = msn_xfer_progress_cb;
-		slpcall->branch = g_strdup(branch);
-
-		slpcall->pending = TRUE;
-
-		xfer = gaim_xfer_new(account, GAIM_XFER_RECEIVE,
-							 slpcall->slplink->remote_user);
-
-		bin = (char *)gaim_base64_decode(context, &bin_len);
-		file_size = GUINT32_FROM_LE(*((gsize *)bin + 2));
-
-		uni_name = (gunichar2 *)(bin + 20);
-		while(*uni_name != 0 && ((char *)uni_name - (bin + 20)) < MAX_FILE_NAME_LEN) {
-			*uni_name = GUINT16_FROM_LE(*uni_name);
-			uni_name++;
-		}
-
-		file_name = g_utf16_to_utf8((const gunichar2 *)(bin + 20), -1,
-									NULL, NULL, NULL);
-
-		g_free(bin);
-
-		gaim_xfer_set_filename(xfer, file_name);
-		gaim_xfer_set_size(xfer, file_size);
-		gaim_xfer_set_init_fnc(xfer, msn_xfer_init);
-		gaim_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
-		gaim_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
-
-		slpcall->xfer = xfer;
-		xfer->data = slpcall;
-
-		gaim_xfer_request(xfer);
-	}
-}
-
-void
-send_bye(MsnSlpCall *slpcall, const char *type)
-{
-	MsnSlpLink *slplink;
-	MsnSlpMessage *slpmsg;
-	char *header;
-
-	slplink = slpcall->slplink;
-
-	g_return_if_fail(slplink != NULL);
-
-	header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0",
-							 slplink->local_user);
-
-	slpmsg = msn_slpmsg_sip_new(slpcall, 0, header,
-								"A0D624A6-6C0C-4283-A9E0-BC97B4B46D32",
-								type,
-								"\r\n");
-	g_free(header);
-
-#ifdef MSN_DEBUG_SLP
-	slpmsg->info = "SLP BYE";
-	slpmsg->text_body = TRUE;
-#endif
-
-	msn_slplink_queue_slpmsg(slplink, slpmsg);
-}
-
-static void
-got_invite(MsnSlpCall *slpcall,
-		   const char *branch, const char *type, const char *content)
-{
-	MsnSlpLink *slplink;
-
-	slplink = slpcall->slplink;
-
-	if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-	{
-		char *euf_guid, *context;
-		char *temp;
-
-		euf_guid = get_token(content, "EUF-GUID: {", "}\r\n");
-
-		temp = get_token(content, "SessionID: ", "\r\n");
-		if (temp != NULL)
-			slpcall->session_id = atoi(temp);
-		g_free(temp);
-
-		temp = get_token(content, "AppID: ", "\r\n");
-		if (temp != NULL)
-			slpcall->app_id = atoi(temp);
-		g_free(temp);
-
-		context = get_token(content, "Context: ", "\r\n");
-
-		got_sessionreq(slpcall, branch, euf_guid, context);
-
-		g_free(context);
-		g_free(euf_guid);
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-	{
-		/* A direct connection? */
-
-		char *listening, *nonce;
-		char *content;
-
-		if (FALSE)
-		{
-#if 0
-			MsnDirectConn *directconn;
-			/* const char *ip_addr; */
-			char *ip_port;
-			int port;
-
-			/* ip_addr = gaim_prefs_get_string("/core/ft/public_ip"); */
-			ip_port = "5190";
-			listening = "true";
-			nonce = rand_guid();
-
-			directconn = msn_directconn_new(slplink);
-
-			/* msn_directconn_parse_nonce(directconn, nonce); */
-			directconn->nonce = g_strdup(nonce);
-
-			msn_directconn_listen(directconn);
-
-			port = directconn->port;
-
-			content = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: %s\r\n"
-				"Nonce: {%s}\r\n"
-				"Ipv4Internal-Addrs: 192.168.0.82\r\n"
-				"Ipv4Internal-Port: %d\r\n"
-				"\r\n",
-				listening,
-				nonce,
-				port);
-#endif
-		}
-		else
-		{
-			listening = "false";
-			nonce = g_strdup("00000000-0000-0000-0000-000000000000");
-
-			content = g_strdup_printf(
-				"Bridge: TCPv1\r\n"
-				"Listening: %s\r\n"
-				"Nonce: {%s}\r\n"
-				"\r\n",
-				listening,
-				nonce);
-		}
-
-		send_ok(slpcall, branch,
-				"application/x-msnmsgr-transrespbody", content);
-
-		g_free(content);
-		g_free(nonce);
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-	{
-#if 0
-		char *ip_addrs;
-		char *temp;
-		char *nonce;
-		int port;
-
-		nonce = get_token(content, "Nonce: {", "}\r\n");
-		ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n");
-
-		temp = get_token(content, "IPv4Internal-Port: ", "\r\n");
-		if (temp != NULL)
-			port = atoi(temp);
-		else
-			port = -1;
-		g_free(temp);
-
-		if (ip_addrs == NULL)
-			return;
-
-		if (port > 0)
-			got_transresp(slpcall, nonce, ip_addrs, port);
-
-		g_free(nonce);
-		g_free(ip_addrs);
-#endif
-	}
-}
-
-static void
-got_ok(MsnSlpCall *slpcall,
-	   const char *type, const char *content)
-{
-	g_return_if_fail(slpcall != NULL);
-	g_return_if_fail(type    != NULL);
-
-	if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-	{
-#if 0
-		if (slpcall->type == MSN_SLPCALL_DC)
-		{
-			/* First let's try a DirectConnection. */
-
-			MsnSlpLink *slplink;
-			MsnSlpMessage *slpmsg;
-			char *header;
-			char *content;
-			char *branch;
-
-			slplink = slpcall->slplink;
-
-			branch = rand_guid();
-
-			content = g_strdup_printf(
-				"Bridges: TRUDPv1 TCPv1\r\n"
-				"NetID: 0\r\n"
-				"Conn-Type: Direct-Connect\r\n"
-				"UPnPNat: false\r\n"
-				"ICF: false\r\n"
-			);
-
-			header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0",
-									 slplink->remote_user);
-
-			slpmsg = msn_slp_sipmsg_new(slpcall, 0, header, branch,
-										"application/x-msnmsgr-transreqbody",
-										content);
-
-#ifdef MSN_DEBUG_SLP
-			slpmsg->info = "SLP INVITE";
-			slpmsg->text_body = TRUE;
-#endif
-			msn_slplink_send_slpmsg(slplink, slpmsg);
-
-			g_free(header);
-			g_free(content);
-
-			g_free(branch);
-		}
-		else
-		{
-			msn_slp_call_session_init(slpcall);
-		}
-#else
-		msn_slp_call_session_init(slpcall);
-#endif
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-	{
-		/* Do we get this? */
-		gaim_debug_info("msn", "OK with transreqbody\n");
-	}
-	else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-	{
-#if 0
-		char *ip_addrs;
-		char *temp;
-		char *nonce;
-		int port;
-
-		nonce = get_token(content, "Nonce: {", "}\r\n");
-		ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n");
-
-		temp = get_token(content, "IPv4Internal-Port: ", "\r\n");
-		if (temp != NULL)
-			port = atoi(temp);
-		else
-			port = -1;
-		g_free(temp);
-
-		if (ip_addrs == NULL)
-			return;
-
-		if (port > 0)
-			got_transresp(slpcall, nonce, ip_addrs, port);
-
-		g_free(nonce);
-		g_free(ip_addrs);
-#endif
-	}
-}
-
-MsnSlpCall *
-msn_slp_sip_recv(MsnSlpLink *slplink, const char *body)
-{
-	MsnSlpCall *slpcall;
-
-	if (body == NULL)
-	{
-		gaim_debug_warning("msn", "received bogus message\n");
-		return NULL;
-	}
-
-	if (!strncmp(body, "INVITE", strlen("INVITE")))
-	{
-		char *branch;
-		char *content;
-		char *content_type;
-
-		slpcall = msn_slp_call_new(slplink);
-
-		/* From: <msnmsgr:buddy@hotmail.com> */
-#if 0
-		slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n");
-#endif
-
-		branch = get_token(body, ";branch={", "}");
-
-		slpcall->id = get_token(body, "Call-ID: {", "}");
-
-#if 0
-		long content_len = -1;
-
-		temp = get_token(body, "Content-Length: ", "\r\n");
-		if (temp != NULL)
-			content_len = atoi(temp);
-		g_free(temp);
-#endif
-		content_type = get_token(body, "Content-Type: ", "\r\n");
-
-		content = get_token(body, "\r\n\r\n", NULL);
-
-		got_invite(slpcall, branch, content_type, content);
-
-		g_free(branch);
-		g_free(content_type);
-		g_free(content);
-	}
-	else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 ")))
-	{
-		char *content;
-		char *content_type;
-		/* Make sure this is "OK" */
-		const char *status = body + strlen("MSNSLP/1.0 ");
-		char *call_id;
-
-		call_id = get_token(body, "Call-ID: {", "}");
-		slpcall = msn_slplink_find_slp_call(slplink, call_id);
-		g_free(call_id);
-
-		g_return_val_if_fail(slpcall != NULL, NULL);
-
-		if (strncmp(status, "200 OK", 6))
-		{
-			/* It's not valid. Kill this off. */
-			char temp[32];
-			const char *c;
-
-			/* Eww */
-			if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) ||
-				(c = strchr(status, '\0')))
-			{
-				size_t offset =  c - status;
-				if (offset >= sizeof(temp))
-					offset = sizeof(temp) - 1;
-
-				strncpy(temp, status, offset);
-				temp[offset] = '\0';
-			}
-
-			gaim_debug_error("msn", "Received non-OK result: %s\n", temp);
-
-			slpcall->wasted = TRUE;
-
-			/* msn_slp_call_destroy(slpcall); */
-			return slpcall;
-		}
-
-		content_type = get_token(body, "Content-Type: ", "\r\n");
-
-		content = get_token(body, "\r\n\r\n", NULL);
-
-		got_ok(slpcall, content_type, content);
-
-		g_free(content_type);
-		g_free(content);
-	}
-	else if (!strncmp(body, "BYE", strlen("BYE")))
-	{
-		char *call_id;
-
-		call_id = get_token(body, "Call-ID: {", "}");
-		slpcall = msn_slplink_find_slp_call(slplink, call_id);
-		g_free(call_id);
-
-		if (slpcall != NULL)
-			slpcall->wasted = TRUE;
-
-		/* msn_slp_call_destroy(slpcall); */
-	}
-	else
-		slpcall = NULL;
-
-	return slpcall;
-}
-
-/**************************************************************************
- * Msg Callbacks
- **************************************************************************/
-
-void
-msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-
-	session = cmdproc->servconn->session;
-	slplink = msn_session_get_slplink(session, msg->remote_user);
-
-	if (slplink->swboard == NULL)
-	{
-		/* We will need this in order to change its flags. */
-		slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
-		/* If swboard is NULL, something has probably gone wrong earlier on
-		 * I didn't want to do this, but MSN 7 is somehow causing us to crash
-		 * here, I couldn't reproduce it to debug more, and people are
-		 * reporting bugs. Hopefully this doesn't cause more crashes. Stu.
-		 */
-		if (slplink->swboard != NULL)
-			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-		else
-			gaim_debug_error("msn", "msn_p2p_msg, swboard is NULL, ouch!\n");
-	}
-
-	msn_slplink_process_msg(slplink, msg);
-}
-
-static void
-got_emoticon(MsnSlpCall *slpcall,
-			 const guchar *data, gsize size)
-{
-
-	GaimConversation *conv;
-	GaimConnection *gc;
-	const char *who;
-
-	gc = slpcall->slplink->session->account->gc;
-	who = slpcall->slplink->remote_user;
-
-	if ((conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, who, gc->account))) {
-
-		/* FIXME: it would be better if we wrote the data as we received it
-		          instead of all at once, calling write multiple times and
-		          close once at the very end
-		*/
-		gaim_conv_custom_smiley_write(conv, slpcall->data_info, data, size);
-		gaim_conv_custom_smiley_close(conv, slpcall->data_info);
-	}
-#ifdef MSN_DEBUG_UD
-	gaim_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
-#endif
-}
-
-void
-msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
-{
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnObject *obj;
-	char **tokens;
-	char *smile, *body_str;
-	const char *body, *who, *sha1c;
-	guint tok;
-	size_t body_len;
-
-	GaimConversation *conv;
-
-	session = cmdproc->servconn->session;
-
-	if (!gaim_account_get_bool(session->account, "custom_smileys", TRUE))
-		return;
-
-	body = msn_message_get_bin_data(msg, &body_len);
-	body_str = g_strndup(body, body_len);
-
-	/* MSN Messenger 7 may send more than one MSNObject in a single message...
-	 * Maybe 10 tokens is a reasonable max value. */
-	tokens = g_strsplit(body_str, "\t", 10);
-
-	g_free(body_str);
-
-	for (tok = 0; tok < 9; tok += 2) {
-		if (tokens[tok] == NULL || tokens[tok + 1] == NULL) {
-			break;
-		}
-
-		smile = tokens[tok];
-		obj = msn_object_new_from_string(gaim_url_decode(tokens[tok + 1]));
-
-		who = msn_object_get_creator(obj);
-		sha1c = msn_object_get_sha1c(obj);
-
-		slplink = msn_session_get_slplink(session, who);
-
-		conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, who,
-												   session->account);
-
-		/* If the conversation doesn't exist then this is a custom smiley
-		 * used in the first message in a MSN conversation: we need to create
-		 * the conversation now, otherwise the custom smiley won't be shown.
-		 * This happens because every GtkIMHtml has its own smiley tree: if
-		 * the conversation doesn't exist then we cannot associate the new
-		 * smiley with its GtkIMHtml widget. */
-		if (!conv) {
-			conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, session->account, who);
-		}
-
-		if (gaim_conv_custom_smiley_add(conv, smile, "sha1", sha1c, TRUE)) {
-			msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
-		}
-
-		msn_object_destroy(obj);
-		obj =   NULL;
-		who =   NULL;
-		sha1c = NULL;
-	}
-	g_strfreev(tokens);
-}
-
-static gboolean
-buddy_icon_cached(GaimConnection *gc, MsnObject *obj)
-{
-	GaimAccount *account;
-	GaimBuddy *buddy;
-	const char *old;
-	const char *new;
-
-	g_return_val_if_fail(obj != NULL, FALSE);
-
-	account = gaim_connection_get_account(gc);
-
-	buddy = gaim_find_buddy(account, msn_object_get_creator(obj));
-	if (buddy == NULL)
-		return FALSE;
-
-	old = gaim_blist_node_get_string((GaimBlistNode *)buddy, "icon_checksum");
-	new = msn_object_get_sha1c(obj);
-
-	if (new == NULL)
-		return FALSE;
-
-	/* If the old and new checksums are the same, and the file actually exists,
-	 * then return TRUE */
-	if (old != NULL && !strcmp(old, new) && (gaim_buddy_icons_find(account, gaim_buddy_get_name(buddy)) != NULL))
-		return TRUE;
-
-	return FALSE;
-}
-
-static void
-msn_release_buddy_icon_request(MsnUserList *userlist)
-{
-	MsnUser *user;
-
-	g_return_if_fail(userlist != NULL);
-
-#ifdef MSN_DEBUG_UD
-	gaim_debug_info("msn", "Releasing buddy icon request\n");
-#endif
-
-	if (userlist->buddy_icon_window > 0)
-	{
-		GQueue *queue;
-		GaimAccount *account;
-		const char *username;
-
-		queue = userlist->buddy_icon_requests;
-
-		if (g_queue_is_empty(userlist->buddy_icon_requests))
-			return;
-
-		user = g_queue_pop_head(queue);
-
-		account  = userlist->session->account;
-		username = user->passport;
-
-		userlist->buddy_icon_window--;
-		msn_request_user_display(user);
-
-#ifdef MSN_DEBUG_UD
-		gaim_debug_info("msn", "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n",
-						userlist->buddy_icon_window);
-#endif
-	}
-}
-
-/*
- * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next
- * buddy icon request if there is one.
- */
-static gboolean
-msn_release_buddy_icon_request_timeout(gpointer data)
-{
-	MsnUserList *userlist = (MsnUserList *)data;
-	
-	/* Free one window slot */
-	userlist->buddy_icon_window++;	
-	
-	/* Clear the tag for our former request timer */
-	userlist->buddy_icon_request_timer = 0;
-	
-	msn_release_buddy_icon_request(userlist);
-	
-	return FALSE;
-}
-
-void
-msn_queue_buddy_icon_request(MsnUser *user)
-{
-	GaimAccount *account;
-	MsnObject *obj;
-	GQueue *queue;
-
-	g_return_if_fail(user != NULL);
-
-	account = user->userlist->session->account;
-
-	obj = msn_user_get_object(user);
-
-	if (obj == NULL)
-	{
-		/* It seems the user has not set a msnobject */
-		GSList *sl, *list;
-
-		/* TODO: I think we need better buddy icon core functions. */
-		gaim_buddy_icons_set_for_user(account, user->passport, NULL, -1);
-
-		list = gaim_find_buddies(account, user->passport);
-
-		for (sl = list; sl != NULL; sl = sl->next)
-		{
-			GaimBuddy *buddy = (GaimBuddy *)sl->data;
-			gaim_blist_node_remove_setting((GaimBlistNode*)buddy, "icon_checksum");
-		}
-		g_slist_free(list);
-
-		return;
-	}
-
-	if (!buddy_icon_cached(account->gc, obj))
-	{
-		MsnUserList *userlist;
-
-		userlist = user->userlist;
-		queue = userlist->buddy_icon_requests;
-
-#ifdef MSN_DEBUG_UD
-		gaim_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n",
-						user->passport, userlist->buddy_icon_window);
-#endif
-
-		g_queue_push_tail(queue, user);
-
-		if (userlist->buddy_icon_window > 0)
-			msn_release_buddy_icon_request(userlist);
-	}
-}
-
-static void
-got_user_display(MsnSlpCall *slpcall,
-				 const guchar *data, gsize size)
-{
-	MsnUserList *userlist;
-	const char *info;
-	GaimAccount *account;
-	GSList *sl, *list;
-
-	g_return_if_fail(slpcall != NULL);
-
-	info = slpcall->data_info;
-#ifdef MSN_DEBUG_UD
-	gaim_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user);
-#endif
-
-	userlist = slpcall->slplink->session->userlist;
-	account = slpcall->slplink->session->account;
-
-	/* TODO: I think we need better buddy icon core functions. */
-	gaim_buddy_icons_set_for_user(account, slpcall->slplink->remote_user,
-								  (void *)data, size);
-
-	list = gaim_find_buddies(account, slpcall->slplink->remote_user);
-
-	for (sl = list; sl != NULL; sl = sl->next)
-	{
-		GaimBuddy *buddy = (GaimBuddy *)sl->data;
-		gaim_blist_node_set_string((GaimBlistNode*)buddy, "icon_checksum", info);
-	}
-	g_slist_free(list);
-
-#if 0
-	/* Free one window slot */
-	userlist->buddy_icon_window++;
-
-	gaim_debug_info("msn", "got_user_display(): buddy_icon_window++ yields =%d\n",
-					userlist->buddy_icon_window);
-
-	msn_release_buddy_icon_request(userlist);
-#endif
-}
-
-static void
-end_user_display(MsnSlpCall *slpcall, MsnSession *session)
-{
-	MsnUserList *userlist;
-
-	g_return_if_fail(session != NULL);
-
-#ifdef MSN_DEBUG_UD
-	gaim_debug_info("msn", "End User Display\n");
-#endif
-
-	userlist = session->userlist;
-
-	/* If the session is being destroyed we better stop doing anything. */
-	if (session->destroying)
-		return;
-
-	/* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate.
-	 * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will
-	 * send us an error 800 like so:
-	 *
-	 * C: NS 000: XFR 21 SB
-	 * S: NS 000: 800 21
-	 */
-	if (userlist->buddy_icon_request_timer) {
-		/* Free the window slot used by this previous request */
-		userlist->buddy_icon_window++;
-
-		/* Clear our pending timeout */
-		gaim_timeout_remove(userlist->buddy_icon_request_timer);
-	}
-
-	/* Wait BUDDY_ICON_DELAY ms before freeing our window slot and requesting the next icon. */
-	userlist->buddy_icon_request_timer = gaim_timeout_add(BUDDY_ICON_DELAY, 
-														  msn_release_buddy_icon_request_timeout, userlist);
-}
-
-void
-msn_request_user_display(MsnUser *user)
-{
-	GaimAccount *account;
-	MsnSession *session;
-	MsnSlpLink *slplink;
-	MsnObject *obj;
-	const char *info;
-
-	session = user->userlist->session;
-	account = session->account;
-
-	slplink = msn_session_get_slplink(session, user->passport);
-
-	obj = msn_user_get_object(user);
-
-	info = msn_object_get_sha1c(obj);
-
-	if (g_ascii_strcasecmp(user->passport,
-						   gaim_account_get_username(account)))
-	{
-		msn_slplink_request_object(slplink, info, got_user_display,
-								   end_user_display, obj);
-	}
-	else
-	{
-		MsnObject *my_obj = NULL;
-		gchar *data = NULL;
-		gsize len = 0;
-		GSList *sl, *list;
-
-#ifdef MSN_DEBUG_UD
-		gaim_debug_info("msn", "Requesting our own user display\n");
-#endif
-
-		my_obj = msn_user_get_object(session->user);
-
-		if (my_obj != NULL)
-		{
-			const char *filename = msn_object_get_real_location(my_obj);
-
-			if (filename != NULL)
-				g_file_get_contents(filename, &data, &len, NULL);
-		}
-
-		/* TODO: I think we need better buddy icon core functions. */
-		gaim_buddy_icons_set_for_user(account, user->passport, (void *)data, len);
-		g_free(data);
-
-		list = gaim_find_buddies(account, user->passport);
-
-		for (sl = list; sl != NULL; sl = sl->next)
-		{
-			GaimBuddy *buddy = (GaimBuddy *)sl->data;
-			gaim_blist_node_set_string((GaimBlistNode*)buddy, "icon_checksum", info);
-		}
-		g_slist_free(list);
-
-		/* Free one window slot */
-		session->userlist->buddy_icon_window++;
-
-#ifdef MSN_DEBUG_UD
-		gaim_debug_info("msn", "msn_request_user_display(): buddy_icon_window++ yields =%d\n",
-						session->userlist->buddy_icon_window);
-#endif
-
-		msn_release_buddy_icon_request(session->userlist);
-	}
-}

mercurial