Exemplo n.º 1
0
PurpleBuddyIcon *
purple_buddy_icon_unref(PurpleBuddyIcon *icon)
{
	if (icon == NULL)
		return NULL;

	g_return_val_if_fail(icon->ref_count > 0, NULL);

	icon->ref_count--;

	if (icon->ref_count == 0)
	{
		GHashTable *icon_cache = g_hash_table_lookup(account_cache, purple_buddy_icon_get_account(icon));

		if (icon_cache != NULL)
			g_hash_table_remove(icon_cache, purple_buddy_icon_get_username(icon));

		g_free(icon->username);
		g_free(icon->checksum);
		purple_imgstore_unref(icon->img);

		PURPLE_DBUS_UNREGISTER_POINTER(icon);
		g_slice_free(PurpleBuddyIcon, icon);

		return NULL;
	}

	return icon;
}
Exemplo n.º 2
0
PurpleStoredImage *
purple_buddy_icons_set_account_icon(PurpleAccount *account,
                                    guchar *icon_data, size_t icon_len)
{
	PurpleStoredImage *old_img;
	PurpleStoredImage *img = NULL;
	char *old_icon;

	if (icon_data != NULL && icon_len > 0)
	{
		img = purple_buddy_icon_data_new(icon_data, icon_len, NULL);
	}

	old_icon = g_strdup(purple_account_get_string(account, "buddy_icon", NULL));
	if (img && purple_buddy_icons_is_caching())
	{
		const char *filename = purple_imgstore_get_filename(img);
		purple_account_set_string(account, "buddy_icon", filename);
		purple_account_set_int(account, "buddy_icon_timestamp", time(NULL));
		ref_filename(filename);
	}
	else
	{
		purple_account_set_string(account, "buddy_icon", NULL);
		purple_account_set_int(account, "buddy_icon_timestamp", 0);
	}
	unref_filename(old_icon);

	old_img = g_hash_table_lookup(pointer_icon_cache, account);

	if (img)
		g_hash_table_insert(pointer_icon_cache, account, img);
	else
		g_hash_table_remove(pointer_icon_cache, account);

	if (purple_account_is_connected(account))
	{
		PurpleConnection *gc;
		PurplePluginProtocolInfo *prpl_info;

		gc = purple_account_get_connection(account);
		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));

		if (prpl_info && prpl_info->set_buddy_icon)
			prpl_info->set_buddy_icon(gc, img);
	}

	if (old_img)
		purple_imgstore_unref(old_img);
	else if (old_icon)
	{
		/* The old icon may not have been loaded into memory.  In that
		 * case, we'll need to uncache the filename.  The filenames
		 * are ref-counted, so this is safe. */
		purple_buddy_icon_data_uncache_file(old_icon);
	}
	g_free(old_icon);

	return img;
}
Exemplo n.º 3
0
void
purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data,
                           size_t len, const char *checksum)
{
	PurpleStoredImage *old_img;

	g_return_if_fail(icon != NULL);

	old_img = icon->img;
	icon->img = NULL;

	if (data != NULL)
	{
		if (len > 0)
			icon->img = purple_buddy_icon_data_new(data, len, NULL);
		else
			g_free(data);
	}

	g_free(icon->checksum);
	icon->checksum = g_strdup(checksum);

	purple_buddy_icon_update(icon);

	purple_imgstore_unref(old_img);
}
Exemplo n.º 4
0
void
msn_session_finish_login(MsnSession *session)
{
	PurpleAccount *account;
	PurpleConnection *gc;
	PurpleStoredImage *img;

	if (!session->logged_in) {
		account = session->account;
		gc = purple_account_get_connection(account);

		img = purple_buddy_icons_find_account_icon(session->account);
		/* TODO: Do we really want to call this if img is NULL? */
		msn_user_set_buddy_icon(session->user, img);
		if (img != NULL)
			purple_imgstore_unref(img);

		session->logged_in = TRUE;
		purple_connection_set_state(gc, PURPLE_CONNECTED);

		/* Sync users */
		msn_session_sync_users(session);
	}

	/* TODO: Send this when updating status instead? */
	msn_notification_send_uux_endpointdata(session);
	msn_notification_send_uux_private_endpointdata(session);

	msn_change_status(session);
}
Exemplo n.º 5
0
static void
purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data,
				size_t smiley_data_len)
{
	PurpleStoredImage *old_img, *new_img;
	const char *old_filename = NULL;
	const char *new_filename = NULL;

	g_return_if_fail(smiley     != NULL);
	g_return_if_fail(smiley_data != NULL);
	g_return_if_fail(smiley_data_len > 0);

	old_img = smiley->img;

	new_img = purple_smiley_data_new(smiley_data, smiley_data_len);

	g_object_set(G_OBJECT(smiley), PROP_IMGSTORE_S, new_img, NULL);

	/* If the old and new image files have different names we need
	 * to unstore old image file. */
	if (!old_img)
		return;

	old_filename = purple_imgstore_get_filename(old_img);
	new_filename = purple_imgstore_get_filename(smiley->img);

	if (g_ascii_strcasecmp(old_filename, new_filename))
		purple_smiley_data_unstore(old_filename);
	purple_imgstore_unref(old_img);
}
Exemplo n.º 6
0
void purple_imgstore_unref_by_id(int id)
{
	PurpleStoredImage *img = purple_imgstore_find_by_id(id);

	g_return_if_fail(img != NULL);

	purple_imgstore_unref(img);
}
Exemplo n.º 7
0
void
msn_object_set_image(MsnObject *obj, PurpleStoredImage *img)
{
	g_return_if_fail(obj != NULL);
	g_return_if_fail(img != NULL);

	/* obj->local = TRUE; */

	purple_imgstore_unref(obj->img);
	obj->img = purple_imgstore_ref(img);
}
Exemplo n.º 8
0
void
msn_slpmsg_destroy(MsnSlpMessage *slpmsg)
{
	MsnSlpLink *slplink;
	GList *cur;

	g_return_if_fail(slpmsg != NULL);

#ifdef MSN_DEBUG_SLPMSG
	purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg);
#endif

	slplink = slpmsg->slplink;

	if (slpmsg->fp != NULL)
		fclose(slpmsg->fp);

	purple_imgstore_unref(slpmsg->img);

	/* We don't want to free the data of the PurpleStoredImage,
	 * but to avoid code duplication, it's sharing buffer. */
	if (slpmsg->img == NULL)
		g_free(slpmsg->buffer);

#ifdef MSN_DEBUG_SLP
	/*
	if (slpmsg->info != NULL)
		g_free(slpmsg->info);
	*/
#endif

	for (cur = slpmsg->msgs; cur != NULL; cur = cur->next)
	{
		/* Something is pointing to this slpmsg, so we should remove that
		 * pointer to prevent a crash. */
		/* Ex: a user goes offline and after that we receive an ACK */

		MsnMessage *msg = cur->data;

#ifdef MSN_DEBUG_SLPMSG
		purple_debug_info("msn", "Unlink slpmsg callbacks.\n");
#endif

		msg->ack_cb = NULL;
		msg->nak_cb = NULL;
		msg->ack_data = NULL;
	}
	g_list_free(slpmsg->msgs);

	slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);

	g_free(slpmsg);
}
Exemplo n.º 9
0
void
msn_object_destroy(MsnObject *obj)
{
	g_return_if_fail(obj != NULL);

	g_free(obj->creator);
	g_free(obj->location);
	g_free(obj->friendly);
	g_free(obj->sha1d);
	g_free(obj->sha1c);

	purple_imgstore_unref(obj->img);

	if (obj->local)
		local_objs = g_list_remove(local_objs, obj);

	g_free(obj);
}
Exemplo n.º 10
0
void
msn_session_finish_login (MsnSession *session)
{
    PurpleAccount *account;
    PurpleStoredImage *img;

    if (session->logged_in)
        return;

    account = msn_session_get_user_data (session);

#ifdef HAVE_LIBPURPLE
    sync_users (session);
#endif

    img = purple_buddy_icons_find_account_icon (account);

    {
        struct pn_buffer *image;
        if (img)
            image = pn_buffer_new_memdup ((const gpointer) purple_imgstore_get_data (img),
                                             purple_imgstore_get_size (img));
        else
            image = NULL;
        pn_contact_set_buddy_icon (session->user, image);
    }

    purple_imgstore_unref (img);

    session->logged_in = TRUE;

    /** @todo move this to msn.c */
    pn_update_status (session);
    pn_update_personal_message (session);
    pn_timeout_tune_status (session);

    {
        PurpleConnection *connection;
        connection = purple_account_get_connection (account);
        purple_connection_set_state (connection, PURPLE_CONNECTED);
    }

    pn_contactlist_check_pending (session->contactlist);
}
Exemplo n.º 11
0
void
msn_session_finish_login(MsnSession *session)
{
	PurpleAccount *account;
	PurpleConnection *gc;
	PurpleStoredImage *img;
	const char *passport;

	if (session->logged_in) {
		/* We are probably here because of a mid-session notification server XFR
		 * We must send a CHG now, otherwise the servers default to invisible,
		 * and prevent things happening, like sending IMs */
		msn_change_status(session);
		return;
	}

	account = session->account;
	gc = purple_account_get_connection(account);

	img = purple_buddy_icons_find_account_icon(session->account);
	msn_user_set_buddy_icon(session->user, img);
	purple_imgstore_unref(img);

	session->logged_in = TRUE;

	msn_change_status(session);

	purple_connection_set_state(gc, PURPLE_CONNECTED);

	/* Sync users */
	msn_session_sync_users(session);
	/* It seems that some accounts that haven't accessed hotmail for a while
	 * and @msn.com accounts don't automatically get the initial email
	 * notification so we always request it on login
	 */

	passport = purple_normalize(account, purple_account_get_username(account));

	if ((strstr(passport, "@hotmail.") != NULL) ||
		(strstr(passport, "@msn.com") != NULL))
	{
		msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
	}
}
Exemplo n.º 12
0
void UploadPortrait(gpointer data, gint source, const gchar * error_message)
{
	struct fetion_account_data *sip = data;
	PurpleStoredImage *img = sip->icon;
	gchar *head;
	gchar *buf;
	gint head_len;
	gint ret, lenth, writed;
	gconstpointer img_data = purple_imgstore_get_data(img);
	size_t size = purple_imgstore_get_size(img);

	head = g_strdup_printf("POST /%s/setportrait.aspx HTTP/1.1\r\n"
			       "User-Agent: IIC2.0/PC 3.3.0370\r\n"
			       "Content-Type: image/jpeg\r\n"
			       "Host: %s\r\n"
			       "Cookie: ssic=%s\r\n"
			       "Content-Length: %d\r\n\r\n",
			       sip->UploadPrefix,
			       sip->UploadServer, sip->ssic, size);
	purple_debug_info("fetion:", "UploadPortrait:head[%s][%d]\n", head,
			  size);
	head_len = strlen(head);
	buf = g_malloc(head_len + size);
	memcpy(buf, head, head_len);
	memcpy(buf + head_len, img_data, size);
	lenth = size + strlen(head);
	writed = 0;
	ret = write(source, buf, lenth);
	if (ret < 0 && errno == EAGAIN)
		ret = 0;
	g_return_if_fail(ret >= 0);
	if (ret < lenth) {
		purple_circ_buffer_append(sip->icon_buf, buf + ret,
					  lenth - ret);
		sip->icon_handler =
		    purple_input_add(source, PURPLE_INPUT_WRITE,
				     (PurpleInputFunction) UploadPortrait_cb,
				     sip);

	}
	g_free(head);
	sip->icon = NULL;
	purple_imgstore_unref(img);
}
Exemplo n.º 13
0
void bonjour_dns_sd_update_buddy_icon(BonjourDnsSd *data) {
	PurpleStoredImage *img;

	if ((img = purple_buddy_icons_find_account_icon(data->account))) {
		gconstpointer avatar_data;
		gsize avatar_len;

		avatar_data = purple_imgstore_get_data(img);
		avatar_len = purple_imgstore_get_size(img);

		if (_mdns_set_buddy_icon_data(data, avatar_data, avatar_len)) {
			/* The filename is a SHA-1 hash of the data (conveniently what we need) */
			const char *p, *filename = purple_imgstore_get_filename(img);

			g_free(data->phsh);
			data->phsh = NULL;

			/* Get rid of the extension */
			p = strchr(filename, '.');
			if (p)
				data->phsh = g_strndup(filename, p - filename);
			else
				purple_debug_error("bonjour", "account buddy icon returned unexpected filename (%s)"
								"; unable to extract hash. Clearing buddy icon\n", filename);

			/* Update our TXT record */
			publish_presence(data, PUBLISH_UPDATE);
		}

		purple_imgstore_unref(img);
	} else {
		/* We need to do this regardless of whether data->phsh is set so that we
		 * cancel any icons that are currently in the process of being set */
		_mdns_set_buddy_icon_data(data, NULL, 0);
		if (data->phsh != NULL) {
			/* Clear the buddy icon */
			g_free(data->phsh);
			data->phsh = NULL;
			/* Update our TXT record */
			publish_presence(data, PUBLISH_UPDATE);
		}
	}
}
Exemplo n.º 14
0
static void
purple_smiley_finalize(GObject *obj)
{
	PurpleSmiley *smiley = PURPLE_SMILEY(obj);

	if (g_hash_table_lookup(smiley_shortcut_index, smiley->shortcut)) {
		g_hash_table_remove(smiley_shortcut_index, smiley->shortcut);
		g_hash_table_remove(smiley_checksum_index, smiley->checksum);
	}

	g_free(smiley->shortcut);
	g_free(smiley->checksum);
	if (smiley->img)
		purple_smiley_data_unstore(purple_imgstore_get_filename(smiley->img));
	purple_imgstore_unref(smiley->img);

	PURPLE_DBUS_UNREGISTER_POINTER(smiley);

	purple_smileys_save();
}
Exemplo n.º 15
0
void
msn_slpmsg_destroy(MsnSlpMessage *slpmsg)
{
	MsnSlpLink *slplink;
	GList *cur;

	g_return_if_fail(slpmsg != NULL);

	if (purple_debug_is_verbose())
		purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg);

	slplink = slpmsg->slplink;

	purple_imgstore_unref(slpmsg->img);

	/* We don't want to free the data of the PurpleStoredImage,
	 * but to avoid code duplication, it's sharing buffer. */
	if (slpmsg->img == NULL)
		g_free(slpmsg->buffer);

	for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur))
	{
		/* Something is pointing to this slpmsg, so we should remove that
		 * pointer to prevent a crash. */
		/* Ex: a user goes offline and after that we receive an ACK */

		MsnSlpMessagePart *part = cur->data;

		part->ack_cb = NULL;
		part->nak_cb = NULL;
		part->ack_data = NULL;
		msn_slpmsgpart_unref(part);
	}

	slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);

	msn_p2p_info_free(slpmsg->p2p_info);

	g_free(slpmsg);
}
Exemplo n.º 16
0
void
msn_session_finish_login(MsnSession *session)
{
	PurpleAccount *account;
	PurpleConnection *gc;
	PurpleStoredImage *img;
	const char *passport;

	if (session->logged_in)
		return;

	account = session->account;
	gc = purple_account_get_connection(account);

	img = purple_buddy_icons_find_account_icon(session->account);
	msn_user_set_buddy_icon(session->user, img);
	purple_imgstore_unref(img);

	session->logged_in = TRUE;

	msn_change_status(session);

	purple_connection_set_state(gc, PURPLE_CONNECTED);

	/* Sync users */
	msn_session_sync_users(session);
	/* It seems that some accounts that haven't accessed hotmail for a while
	 * and @msn.com accounts don't automatically get the initial email
	 * notification so we always request it on login
	 */

	passport = purple_normalize(account, purple_account_get_username(account));

	if ((strstr(passport, "@hotmail.") != NULL) ||
		(strstr(passport, "@msn.com") != NULL))
	{
		msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
	}
}
Exemplo n.º 17
0
static void
purple_smiley_set_property(GObject *object, guint param_id, const GValue *value,
		GParamSpec *spec)
{
	PurpleSmiley *smiley = PURPLE_SMILEY(object);
	PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);

	switch (param_id) {
		case PROP_SHORTCUT:
			{
				const char *shortcut = g_value_get_string(value);
				purple_smiley_set_shortcut(smiley, shortcut);
			}
			break;
		case PROP_IMGSTORE:
			{
				PurpleStoredImage *img = g_value_get_pointer(value);

				purple_imgstore_unref(priv->img);
				g_free(priv->checksum);

				priv->img = img;
				if (img) {
					priv->checksum = g_compute_checksum_for_data(
							G_CHECKSUM_SHA1,
							purple_imgstore_get_data(img),
							purple_imgstore_get_size(img));
					purple_smiley_data_store(img);
				} else {
					priv->checksum = NULL;
				}
			}
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
			break;
	}
}
Exemplo n.º 18
0
static void
purple_smiley_set_property(GObject *object, guint param_id, const GValue *value,
		GParamSpec *spec)
{
	PurpleSmiley *smiley = PURPLE_SMILEY(object);
	switch (param_id) {
		case PROP_SHORTCUT:
			{
				const char *shortcut = g_value_get_string(value);
				purple_smiley_set_shortcut(smiley, shortcut);
			}
			break;
		case PROP_IMGSTORE:
			{
				PurpleStoredImage *img = g_value_get_pointer(value);

				purple_imgstore_unref(smiley->img);
				g_free(smiley->checksum);

				smiley->img = img;
				if (img) {
					smiley->checksum = purple_util_get_image_checksum(
							purple_imgstore_get_data(img),
							purple_imgstore_get_size(img));
					purple_smiley_data_store(img);
				} else {
					smiley->checksum = NULL;
				}

				g_object_notify(object, PROP_IMGSTORE_S);
			}
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
			break;
	}
}
Exemplo n.º 19
0
PurpleStoredImage *
purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
                                        guchar *icon_data, size_t icon_len)
{
	char *old_icon;
	PurpleStoredImage *old_img;
	PurpleStoredImage *img = NULL;

	g_return_val_if_fail(node != NULL, NULL);

	if (!PURPLE_BLIST_NODE_IS_CONTACT(node) &&
	    !PURPLE_BLIST_NODE_IS_CHAT(node) &&
	    !PURPLE_BLIST_NODE_IS_GROUP(node)) {
		return NULL;
	}

	old_img = g_hash_table_lookup(pointer_icon_cache, node);

	if (icon_data != NULL && icon_len > 0) {
		img = purple_buddy_icon_data_new(icon_data, icon_len, NULL);
	}

	old_icon = g_strdup(purple_blist_node_get_string(node,
	                                                 "custom_buddy_icon"));
	if (img && purple_buddy_icons_is_caching()) {
		const char *filename = purple_imgstore_get_filename(img);
		purple_blist_node_set_string(node, "custom_buddy_icon",
		                             filename);
		ref_filename(filename);
	} else {
		purple_blist_node_remove_setting(node, "custom_buddy_icon");
	}
	unref_filename(old_icon);

	if (img)
		g_hash_table_insert(pointer_icon_cache, node, img);
	else
		g_hash_table_remove(pointer_icon_cache, node);

	if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
		PurpleBlistNode *child;
		for (child = purple_blist_node_get_first_child(node);
		     child;
			 child = purple_blist_node_get_sibling_next(child))
		{
			PurpleBuddy *buddy;
			PurpleConversation *conv;

			if (!PURPLE_BLIST_NODE_IS_BUDDY(child))
				continue;

			buddy = (PurpleBuddy *)child;

			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
			if (conv)
				purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);

			/* Is this call necessary anymore? Can the buddies
			 * themselves need updating when the custom buddy
			 * icon changes? */
			purple_blist_update_node_icon((PurpleBlistNode*)buddy);
		}
	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
		PurpleConversation *conv = NULL;

		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, purple_chat_get_name((PurpleChat*)node), purple_chat_get_account((PurpleChat*)node));
		if (conv) {
			purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);
		}
	}

	purple_blist_update_node_icon(node);

	if (old_img) {
		purple_imgstore_unref(old_img);
	} else if (old_icon) {
		/* The old icon may not have been loaded into memory.  In that
		 * case, we'll need to uncache the filename.  The filenames
		 * are ref-counted, so this is safe. */
		purple_buddy_icon_data_uncache_file(old_icon);
	}
	g_free(old_icon);

	return img;
}
Exemplo n.º 20
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);
		}
	}
}