Ejemplo n.º 1
0
static void
send_file_cb(MsnSlpCall *slpcall)
{
	MsnSlpMessage *slpmsg;
	PurpleXfer *xfer;

	xfer = (PurpleXfer *)slpcall->xfer;
	if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED)
		return;

	purple_xfer_ref(xfer);
	purple_xfer_start(xfer, -1, NULL, 0);
	if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
		purple_xfer_unref(xfer);
		return;
	}
	purple_xfer_unref(xfer);

	slpmsg = msn_slpmsg_new(slpcall->slplink);
	slpmsg->slpcall = slpcall;
	slpmsg->flags = 0x1000030;
	slpmsg->info = "SLP FILE";
	slpmsg->size = purple_xfer_get_size(xfer);

	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
}
Ejemplo n.º 2
0
static void
send_file_cb(MsnSlpSession *slpsession)
{
	MsnSlpCall *slpcall;
	MsnSlpMessage *slpmsg;
	struct stat st;
	PurpleXfer *xfer;

	slpcall = slpsession->slpcall;
	slpmsg = msn_slpmsg_new(slpcall->slplink);
	slpmsg->slpcall = slpcall;
	slpmsg->flags = 0x1000030;
	slpmsg->slpsession = slpsession;
#ifdef MSN_DEBUG_SLP
	slpmsg->info = "SLP FILE";
#endif
	xfer = (PurpleXfer *)slpcall->xfer;
	purple_xfer_start(slpcall->xfer, 0, NULL, 0);
	slpmsg->fp = xfer->dest_fp;
	if (g_stat(purple_xfer_get_local_filename(xfer), &st) == 0)
		slpmsg->size = st.st_size;
	xfer->dest_fp = NULL; /* Disable double fclose() */

	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
}
Ejemplo n.º 3
0
MsnSlpMessage *
msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
				   const char *header, const char *branch,
				   const char *content_type, const char *content)
{
	MsnSlpLink *slplink;
	MsnSlpMessage *slpmsg;
	char *body;
	gsize body_len;
	gsize content_len;

	g_return_val_if_fail(slpcall != NULL, NULL);
	g_return_val_if_fail(header  != NULL, NULL);

	slplink = slpcall->slplink;

	/* Let's remember that "content" should end with a 0x00 */

	content_len = (content != NULL) ? strlen(content) + 1 : 0;

	body = g_strdup_printf(
		"%s\r\n"
		"To: <msnmsgr:%s>\r\n"
		"From: <msnmsgr:%s>\r\n"
		"Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
		"CSeq: %d\r\n"
		"Call-ID: {%s}\r\n"
		"Max-Forwards: 0\r\n"
		"Content-Type: %s\r\n"
		"Content-Length: %" G_GSIZE_FORMAT "\r\n"
		"\r\n",
		header,
		slplink->remote_user,
		slplink->local_user,
		branch,
		cseq,
		slpcall->id,
		content_type,
		content_len);

	body_len = strlen(body);

	if (content_len > 0)
	{
		body_len += content_len;
		body = g_realloc(body, body_len);
		g_strlcat(body, content, body_len);
	}

	slpmsg = msn_slpmsg_new(slplink);
	msn_slpmsg_set_body(slpmsg, body, body_len);

	slpmsg->sip = TRUE;
	slpmsg->slpcall = slpcall;

	g_free(body);

	return slpmsg;
}
Ejemplo n.º 4
0
MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);

	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
	slpmsg->info = "SLP FILE";
	slpmsg->size = size;

	return slpmsg;
}
Ejemplo n.º 5
0
MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
	msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
	slpmsg->info = "SLP DATA";

	msn_slpmsg_set_image(slpmsg, img);

	return slpmsg;
}
Ejemplo n.º 6
0
static MsnSlpMessage *
init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
{
	MsnSlpMessage *slpmsg;
	guint32 session_id;

	slpmsg = msn_slpmsg_new(slplink, NULL);
	slpmsg->id = msn_p2p_info_get_id(info);
	session_id = msn_p2p_info_get_session_id(info);
	slpmsg->size = msn_p2p_info_get_total_size(info);
	msn_p2p_info_init_first(slpmsg->p2p_info, info);

	if (session_id)
	{
		slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
		if (slpmsg->slpcall != NULL)
		{
			if (msn_p2p_msg_is_data(info))
			{
				PurpleXfer *xfer = slpmsg->slpcall->xfer;
				if (xfer != NULL)
				{
					slpmsg->ft = TRUE;
					slpmsg->slpcall->xfer_msg = slpmsg;

					purple_xfer_ref(xfer);
					purple_xfer_start(xfer,	-1, NULL, 0);

					if (xfer->data == NULL) {
						purple_xfer_unref(xfer);
						msn_slpmsg_destroy(slpmsg);
						g_return_val_if_reached(NULL);
					} else {
						purple_xfer_unref(xfer);
					}
				}
			}
		}
	}
	if (!slpmsg->ft && slpmsg->size)
	{
		slpmsg->buffer = g_try_malloc(slpmsg->size);
		if (slpmsg->buffer == NULL)
		{
			purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
			msn_slpmsg_destroy(slpmsg);
			return NULL;
		}
	}

	return slpmsg;
}
Ejemplo n.º 7
0
MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);

	msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
	msn_slpmsg_set_body(slpmsg, NULL, 4);
	slpmsg->info = "SLP DATA PREP";

	return slpmsg;

}
Ejemplo n.º 8
0
MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *ack_info)
{
	MsnSlpMessage *slpmsg;
	MsnP2PInfo *new_info;

	slpmsg = msn_slpmsg_new(slplink, NULL);

	new_info = slpmsg->p2p_info;
	msn_p2p_info_create_ack(ack_info, new_info);
	slpmsg->size = msn_p2p_info_get_total_size(ack_info);
	slpmsg->info = "SLP ACK";

	return slpmsg;
}
Ejemplo n.º 9
0
static MsnSlpMessage *
msn_slplink_create_ack(MsnSlpLink *slplink, MsnSlpHeader *header)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slplink);

	slpmsg->session_id = header->session_id;
	slpmsg->size       = header->total_size;
	slpmsg->flags      = 0x02;
	slpmsg->ack_id     = header->id;
	slpmsg->ack_sub_id = header->ack_id;
	slpmsg->ack_size   = header->total_size;
	slpmsg->info = "SLP ACK";

	return slpmsg;
}
Ejemplo n.º 10
0
static void
msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slplink);

	slpmsg->session_id = msg->msnslp_header.session_id;
	slpmsg->size       = msg->msnslp_header.total_size;
	slpmsg->flags      = 0x02;
	slpmsg->ack_id     = msg->msnslp_header.id;
	slpmsg->ack_sub_id = msg->msnslp_header.ack_id;
	slpmsg->ack_size   = msg->msnslp_header.total_size;
	slpmsg->info = "SLP ACK";

	msn_slplink_send_slpmsg(slplink, slpmsg);
	msn_slpmsg_destroy(slpmsg);
}
Ejemplo n.º 11
0
void
msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg)
{
	MsnSlpMessage *slpmsg;

	slpmsg = msn_slpmsg_new(slplink);

	slpmsg->session_id = msg->msnslp_header.session_id;
	slpmsg->size       = msg->msnslp_header.total_size;
	slpmsg->flags      = 0x02;
	slpmsg->ack_id     = msg->msnslp_header.id;
	slpmsg->ack_sub_id = msg->msnslp_header.ack_id;
	slpmsg->ack_size   = msg->msnslp_header.total_size;

#ifdef MSN_DEBUG_SLP
	slpmsg->info = "SLP ACK";
#endif

	msn_slplink_send_slpmsg(slplink, slpmsg);
}
Ejemplo n.º 12
0
void
msn_directconn_send_handshake(MsnDirectConn *directconn)
{
	MsnSlpLink *slplink;
	MsnSlpMessage *slpmsg;

	g_return_if_fail(directconn != NULL);

	slplink = directconn->slplink;

	slpmsg = msn_slpmsg_new(slplink);
	slpmsg->flags = 0x100;

	if (directconn->nonce != NULL)
	{
		guint32 t1;
		guint16 t2;
		guint16 t3;
		guint16 t4;
		guint64 t5;

		sscanf (directconn->nonce, "%08X-%04hX-%04hX-%04hX-%012" G_GINT64_MODIFIER "X", &t1, &t2, &t3, &t4, &t5);

		t1 = GUINT32_TO_LE(t1);
		t2 = GUINT16_TO_LE(t2);
		t3 = GUINT16_TO_LE(t3);
		t4 = GUINT16_TO_BE(t4);
		t5 = GUINT64_TO_BE(t5);

		slpmsg->ack_id     = t1;
		slpmsg->ack_sub_id = t2 | (t3 << 16);
		slpmsg->ack_size   = t4 | t5;
	}

	g_free(directconn->nonce);

	msn_slplink_send_slpmsg(slplink, slpmsg);

	directconn->acked =TRUE;
}
Ejemplo n.º 13
0
void
msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpHeader *header, const char *data, gsize len)
{
	MsnSlpMessage *slpmsg;
	guint64 offset;
	PurpleXfer *xfer = NULL;

	if (header->total_size < header->length)
	{
		purple_debug_error("msn", "This can't be good\n");
		g_return_if_reached();
	}

	offset = header->offset;

	if (offset == 0)
	{
		slpmsg = msn_slpmsg_new(slplink);
		slpmsg->id = header->id;
		slpmsg->session_id = header->session_id;
		slpmsg->size = header->total_size;
		slpmsg->flags = header->flags;

		if (slpmsg->session_id)
		{
			if (slpmsg->slpcall == NULL)
				slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);

			if (slpmsg->slpcall != NULL)
			{
				if (slpmsg->flags == 0x20 ||
				    slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
				{
					xfer = slpmsg->slpcall->xfer;
					if (xfer != NULL)
					{
						slpmsg->ft = TRUE;
						slpmsg->slpcall->xfer_msg = slpmsg;

						purple_xfer_ref(xfer);
						purple_xfer_start(xfer,	-1, NULL, 0);

						if (xfer->data == NULL) {
							purple_xfer_unref(xfer);
							msn_slpmsg_destroy(slpmsg);
							g_return_if_reached();
						} else {
							purple_xfer_unref(xfer);
						}
					}
				}
			}
		}
		if (!slpmsg->ft && slpmsg->size)
		{
			slpmsg->buffer = g_try_malloc(slpmsg->size);
			if (slpmsg->buffer == NULL)
			{
				purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
				msn_slpmsg_destroy(slpmsg);
				return;
			}
		}
	}
	else
	{
		slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id);
		if (slpmsg == NULL)
		{
			/* Probably the transfer was canceled */
			purple_debug_error("msn", "Couldn't find slpmsg\n");
			return;
		}
	}

	if (slpmsg->ft)
	{
		xfer = slpmsg->slpcall->xfer;
		slpmsg->slpcall->u.incoming_data =
				g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len);
		purple_xfer_prpl_ready(xfer);
	}
	else if (slpmsg->size && slpmsg->buffer)
	{
		if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size || slpmsg->offset != offset)
		{
			purple_debug_error("msn",
				"Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
				slpmsg->size, offset, len);
			g_return_if_reached();
		} else {
			memcpy(slpmsg->buffer + offset, data, len);
			slpmsg->offset += len;
		}
	}

	if ((slpmsg->flags == 0x20 ||
	     slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) &&
		(slpmsg->slpcall != NULL))
	{
		slpmsg->slpcall->progress = TRUE;

		if (slpmsg->slpcall->progress_cb != NULL)
		{
			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
										 len, offset);
		}
	}

#if 0
	if (slpmsg->buffer == NULL)
		return;
#endif

	if (header->offset + header->length >= header->total_size)
	{
		/* All the pieces of the slpmsg have been received */
		MsnSlpCall *slpcall;

		slpcall = msn_slp_process_msg(slplink, slpmsg);

		if (slpcall == NULL) {
			msn_slpmsg_destroy(slpmsg);
			return;
		}

		purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");

		if (/* !slpcall->wasted && */ slpmsg->flags == 0x100)
		{
#if 0
			MsnDirectConn *directconn;

			directconn = slplink->directconn;
			if (!directconn->acked)
				msn_directconn_send_handshake(directconn);
#endif
		}
		else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||
		         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||
		         slpmsg->flags == 0x1000030)
		{
			/* Release all the messages and send the ACK */

			if (slpcall->wait_for_socket) {
				/*
				 * Save ack for later because we have to send
				 * a 200 OK message to the previous direct connect
				 * invitation before ACK but the listening socket isn't
				 * created yet.
				 */
				purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");

				slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header);
			} else if (!slpcall->wasted) {
				purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");

				msn_slplink_send_ack(slplink, header);
				msn_slplink_send_queued_slpmsgs(slplink);
			}
		}

		msn_slpmsg_destroy(slpmsg);

		if (!slpcall->wait_for_socket && slpcall->wasted)
			msn_slpcall_destroy(slpcall);
	}
}
Ejemplo n.º 14
0
void
msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
{
	MsnSlpMessage *slpmsg;
	const char *data;
	gsize offset;
	gsize len;

#ifdef MSN_DEBUG_SLP
	msn_slpmsg_show(msg);
#endif

#ifdef MSN_DEBUG_SLP_FILES
	debug_msg_to_file(msg, FALSE);
#endif

	if (msg->msnslp_header.total_size < msg->msnslp_header.length)
	{
		purple_debug_error("msn", "This can't be good\n");
		g_return_if_reached();
	}

	slpmsg = NULL;
	data = msn_message_get_bin_data(msg, &len);

	/*
		OVERHEAD!
		if (msg->msnslp_header.length < msg->msnslp_header.total_size)
	 */

	offset = msg->msnslp_header.offset;

	if (offset == 0)
	{
		slpmsg = msn_slpmsg_new(slplink);
		slpmsg->id = msg->msnslp_header.id;
		slpmsg->session_id = msg->msnslp_header.session_id;
		slpmsg->size = msg->msnslp_header.total_size;
		slpmsg->flags = msg->msnslp_header.flags;

		if (slpmsg->session_id)
		{
			if (slpmsg->slpcall == NULL)
				slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);

			if (slpmsg->slpcall != NULL)
			{
				if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)
				{
					PurpleXfer *xfer;

					xfer = slpmsg->slpcall->xfer;

					if (xfer != NULL)
					{
						purple_xfer_ref(xfer);
						purple_xfer_start(xfer,	0, NULL, 0);

						if (xfer->data == NULL) {
							purple_xfer_unref(xfer);
							return;
						} else {
							purple_xfer_unref(xfer);
							slpmsg->fp = xfer->dest_fp;
							xfer->dest_fp = NULL; /* Disable double fclose() */
						}
					}
				}
			}
		}
		if (!slpmsg->fp && slpmsg->size)
		{
			slpmsg->buffer = g_try_malloc(slpmsg->size);
			if (slpmsg->buffer == NULL)
			{
				purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
				return;
			}
		}
	}
	else
	{
		slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id);
	}

	if (slpmsg == NULL)
	{
		/* Probably the transfer was canceled */
		purple_debug_error("msn", "Couldn't find slpmsg\n");
		return;
	}

	if (slpmsg->fp)
	{
		/* fseek(slpmsg->fp, offset, SEEK_SET); */
		len = fwrite(data, 1, len, slpmsg->fp);
	}
	else if (slpmsg->size)
	{
		if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size)
		{
			purple_debug_error("msn", "Oversized slpmsg\n");
			g_return_if_reached();
		}
		else
			memcpy(slpmsg->buffer + offset, data, len);
	}

	if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) &&
		(slpmsg->slpcall != NULL))
	{
		slpmsg->slpcall->progress = TRUE;

		if (slpmsg->slpcall->progress_cb != NULL)
		{
			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
										 len, offset);
		}
	}

#if 0
	if (slpmsg->buffer == NULL)
		return;
#endif

	if (msg->msnslp_header.offset + msg->msnslp_header.length
		>= msg->msnslp_header.total_size)
	{
		/* All the pieces of the slpmsg have been received */
		MsnSlpCall *slpcall;

		slpcall = msn_slp_process_msg(slplink, slpmsg);

		if (slpmsg->flags == 0x100)
		{
			MsnDirectConn *directconn;

			directconn = slplink->directconn;

			if (!directconn->acked)
				msn_directconn_send_handshake(directconn);
		}
		else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 ||
				 slpmsg->flags == 0x1000030)
		{
			/* Release all the messages and send the ACK */

			msn_slplink_send_ack(slplink, msg);
			msn_slplink_unleash(slplink);
		}

		msn_slpmsg_destroy(slpmsg);

		if (slpcall != NULL && slpcall->wasted)
			msn_slp_call_destroy(slpcall);
	}
}
Ejemplo n.º 15
0
static void
got_sessionreq(MsnSlpCall *slpcall, const char *branch,
			   const char *euf_guid, const char *context)
{
	pecan_debug ("euf_guid=[%s]", euf_guid);

	if (!strcmp(euf_guid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6"))
	{
		/* Emoticon or UserDisplay */
		char *content;
		gsize len;
		MsnSlpSession *slpsession;
		MsnSlpLink *slplink;
		MsnSlpMessage *slpmsg;
		MsnObject *obj;
		char *msnobj_data;
		PecanBuffer *image;
		int type;

		/* Send Ok */
                content = pecan_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 *)purple_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)
		{
			/* image is owned by a local object, not obj */
			image = msn_object_get_image(obj);
		}
#if PURPLE_VERSION_CHECK(2,5,0)
		else if (type == MSN_OBJECT_EMOTICON)
		{
			PurpleStoredImage *img;
			char *path;
			path = g_build_filename(purple_smileys_get_storing_dir(), msn_object_get_location(obj), NULL);
			img = purple_imgstore_new_from_file(path);
			image = pecan_buffer_new_memdup ((const gpointer) purple_imgstore_get_data (img),
							 purple_imgstore_get_size (img));
			purple_imgstore_unref(img);
			g_free(path);
		}
#endif /* PURPLE_VERSION_CHECK(2,5,0) */
		else
		{
			pecan_error ("Wrong object?");
			msn_object_destroy(obj);
			g_return_if_reached();
		}

		if (!image)
		{
                    pecan_error ("Wrong object");
                    msn_object_destroy (obj);
                    g_return_if_reached ();
		}

		msn_object_destroy(obj);

		{
			gchar *tmp;
			tmp = msn_object_to_string (obj);
			pecan_info ("object requested: %s", tmp);
			g_free (tmp);
		}

		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 PECAN_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 PECAN_DEBUG_SLP
		slpmsg->info = "SLP DATA";
#endif
		msn_slpmsg_set_image (slpmsg, image);
		msn_slplink_queue_slpmsg(slplink, slpmsg);
	}
	else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683"))
	{
		/* File Transfer */
		PurpleAccount *account;
		PurpleXfer *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 = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
							   slpcall->slplink->remote_user);
		if (xfer)
		{
			bin = (char *)purple_base64_decode(context, &bin_len);
			file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8));

			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);

			purple_xfer_set_filename(xfer, file_name);
			purple_xfer_set_size(xfer, file_size);
			purple_xfer_set_init_fnc(xfer, msn_xfer_init);
			purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
			purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);

			slpcall->xfer = xfer;
			purple_xfer_ref(slpcall->xfer);

			xfer->data = slpcall;

			purple_xfer_request(xfer);
		}
	}
}