changeset 12143:cbebda5f019c

[gaim-migrate @ 14444] SF Patch #1360399 from Evan Schoenberg (evands) "I discussed this previously with Mark and he said it'd be fine. This factors out the part of the send_file function which creates a new GaimXfer into a separate prpl function, new_xfer. It's called in each of the existing send_file functions. This is needed so that another client (okay, Adium) can get a new outgoing GaimXfer from a prpl without depending upon the specific ft.c logic of send_file; previously I was adding a duplicate method to each prpl and then calling it directly." I fixed a couple small bugs in this. Otherwise, it looks good, and seems like a reasonable libgaim request. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Sat, 19 Nov 2005 00:26:12 +0000
parents 0c672be21798
children d93e6979b77a
files src/ft.h src/protocols/bonjour/bonjour.c src/protocols/gg/gg.c src/protocols/irc/dcc_send.c src/protocols/irc/irc.c src/protocols/irc/irc.h src/protocols/jabber/jabber.c src/protocols/jabber/si.c src/protocols/jabber/si.h src/protocols/msn/msn.c src/protocols/napster/napster.c src/protocols/novell/novell.c src/protocols/oscar/oscar.c src/protocols/sametime/sametime.c src/protocols/silc/ft.c src/protocols/silc/silc.c src/protocols/simple/simple.c src/protocols/toc/toc.c src/protocols/yahoo/yahoo.c src/protocols/yahoo/yahoo_filexfer.c src/protocols/yahoo/yahoo_filexfer.h src/protocols/zephyr/zephyr.c src/prpl.h
diffstat 23 files changed, 202 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/src/ft.h	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/ft.h	Sat Nov 19 00:26:12 2005 +0000
@@ -31,6 +31,7 @@
 typedef struct _GaimXfer GaimXfer;
 
 #include "account.h"
+#include "internal.h"
 
 /**
  * Types of file transfers.
--- a/src/protocols/bonjour/bonjour.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/bonjour/bonjour.c	Sat Nov 19 00:26:12 2005 +0000
@@ -396,7 +396,8 @@
 	NULL,                                                    /* roomlist_cancel */
 	NULL,                                                    /* roomlist_expand_category */
 	NULL,                                                    /* can_receive_file */
-	NULL                                                     /* send_file */
+	NULL,                                                    /* send_file */
+	NULL                                                     /* new_xfer */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/gg/gg.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/gg/gg.c	Sat Nov 19 00:26:12 2005 +0000
@@ -1837,7 +1837,8 @@
 	NULL,				/* roomlist_cancel */
 	NULL,				/* roomlist_expand_category */
 	NULL,				/* can_receive_file */
-	NULL				/* send_file */
+	NULL,				/* send_file */
+	NULL				/* new_xfer */
 };
 /* }}} */
 
--- a/src/protocols/irc/dcc_send.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/irc/dcc_send.c	Sat Nov 19 00:26:12 2005 +0000
@@ -294,30 +294,36 @@
 	g_free(tmp);
 }
 
-/**
- * Gaim calls this function when the user selects Send File from the
- * buddy menu
- * It sets up the GaimXfer struct and tells Gaim to go ahead
- */
-void irc_dccsend_send_file(GaimConnection *gc, const char *who, const char *file) {
+GaimXfer *irc_dccsend_new_xfer(GaimConnection *gc, const char *who) {
 	GaimXfer *xfer;
 	struct irc_xfer_send_data *xd;
 
 	/* Build the file transfer handle */
 	xfer = gaim_xfer_new(gaim_connection_get_account(gc), GAIM_XFER_SEND, who);
 
-
 	xd = g_new0(struct irc_xfer_send_data, 1);
 	xd->fd = -1;
 	xfer->data = xd;
 
-	 /* Setup our I/O op functions */
+	/* Setup our I/O op functions */
 	gaim_xfer_set_init_fnc(xfer, irc_dccsend_send_init);
 	gaim_xfer_set_write_fnc(xfer, irc_dccsend_send_write);
 	gaim_xfer_set_end_fnc(xfer, irc_dccsend_send_destroy);
 	gaim_xfer_set_request_denied_fnc(xfer, irc_dccsend_send_destroy);
 	gaim_xfer_set_cancel_send_fnc(xfer, irc_dccsend_send_destroy);
-	/* Now perform the request */
+
+	return xfer;
+}
+
+/**
+ * Gaim calls this function when the user selects Send File from the
+ * buddy menu
+ * It sets up the GaimXfer struct and tells Gaim to go ahead
+ */
+void irc_dccsend_send_file(GaimConnection *gc, const char *who, const char *file) {
+	GaimXfer *xfer = irc_dccsend_new_xfer(gc, who);
+
+	/* Perform the request */
 	if (file)
 		gaim_xfer_request_accepted(xfer, file);
 	else
--- a/src/protocols/irc/irc.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/irc/irc.c	Sat Nov 19 00:26:12 2005 +0000
@@ -769,7 +769,8 @@
 	irc_roomlist_cancel,	/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	NULL,					/* can_receive_file */
-	irc_dccsend_send_file	/* send_file */
+	irc_dccsend_send_file,	/* send_file */
+	irc_dccsend_new_xfer	/* new_xfer */
 };
 
 
--- a/src/protocols/irc/irc.h	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/irc/irc.h	Sat Nov 19 00:26:12 2005 +0000
@@ -25,6 +25,7 @@
 
 #include <glib.h>
 
+#include "ft.h"
 #include "roomlist.h"
 #include "sslconn.h"
 
@@ -168,6 +169,7 @@
 int irc_cmd_wallops(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
 int irc_cmd_whois(struct irc_conn *irc, const char *cmd, const char *target, const char **args);
 
+GaimXfer *irc_dccsend_new_xfer(GaimConnection *gc, const char *who);
 void irc_dccsend_send_file(GaimConnection *gc, const char *who, const char *file);
 void irc_dccsend_recv(struct irc_conn *irc, const char *from, const char *msg);
 #endif /* _GAIM_IRC_H */
--- a/src/protocols/jabber/jabber.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/jabber/jabber.c	Sat Nov 19 00:26:12 2005 +0000
@@ -1665,7 +1665,9 @@
 	jabber_roomlist_cancel,			/* roomlist_cancel */
 	NULL,							/* roomlist_expand_category */
 	NULL,							/* can_receive_file */
-	jabber_si_xfer_send				/* send_file */
+	jabber_si_xfer_send,			/* send_file */
+	jabber_si_new_xfer,				/* new_xfer */
+	NULL							/* whiteboard operations */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/jabber/si.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/jabber/si.c	Sat Nov 19 00:26:12 2005 +0000
@@ -655,7 +655,7 @@
 	}
 }
 
-void jabber_si_xfer_send(GaimConnection *gc, const char *who, const char *file)
+GaimXfer *jabber_si_new_xfer(GaimConnection *gc, const char *who)
 {
 	JabberStream *js;
 
@@ -664,9 +664,6 @@
 
 	js = gc->proto_data;
 
-	if(!gaim_find_buddy(gc->account, who) || !jabber_buddy_find(js, who, FALSE))
-		return;
-
 	xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who);
 
 	xfer->data = jsx = g_new0(JabberSIXfer, 1);
@@ -676,7 +673,23 @@
 	gaim_xfer_set_cancel_send_fnc(xfer, jabber_si_xfer_cancel_send);
 	gaim_xfer_set_end_fnc(xfer, jabber_si_xfer_end);
 
-	js->file_transfers = g_list_append(js->file_transfers, xfer);
+	js->file_transfers = g_list_append(js->file_transfers, xfer);	
+
+	return xfer;
+}
+
+void jabber_si_xfer_send(GaimConnection *gc, const char *who, const char *file)
+{
+	JabberStream *js;
+
+	GaimXfer *xfer;
+
+	js = gc->proto_data;
+
+	if(!gaim_find_buddy(gc->account, who) || !jabber_buddy_find(js, who, FALSE))
+		return;
+
+	xfer = jabber_si_new_xfer(gc, who);
 
 	if (file)
 		gaim_xfer_request_accepted(xfer, file);
--- a/src/protocols/jabber/si.h	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/jabber/si.h	Sat Nov 19 00:26:12 2005 +0000
@@ -28,6 +28,7 @@
 
 void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet);
 void jabber_si_parse(JabberStream *js, xmlnode *packet);
+GaimXfer *jabber_si_new_xfer(GaimConnection *gc, const char *who);
 void jabber_si_xfer_send(GaimConnection *gc, const char *who, const char *file);
 
 #endif /* _GAIM_JABBER_SI_H_ */
--- a/src/protocols/msn/msn.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/msn/msn.c	Sat Nov 19 00:26:12 2005 +0000
@@ -422,22 +422,30 @@
 	msn_slplink_request_ft(slplink, xfer);
 }
 
-static void
-msn_send_file(GaimConnection *gc, const char *who, const char *file)
+static GaimXfer*
+msn_new_xfer(GaimConnection *gc, const char *who)
 {
 	MsnSession *session;
 	MsnSlpLink *slplink;
 	GaimXfer *xfer;
-
+	
 	session = gc->proto_data;
-
+	
 	xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who);
+	
+	slplink = msn_session_get_slplink(session, who);
+	
+	xfer->data = slplink;
+	
+	gaim_xfer_set_init_fnc(xfer, t_msn_xfer_init);	
+	
+	return xfer;
+}
 
-	slplink = msn_session_get_slplink(session, who);
-
-	xfer->data = slplink;
-
-	gaim_xfer_set_init_fnc(xfer, t_msn_xfer_init);
+static void
+msn_send_file(GaimConnection *gc, const char *who, const char *file)
+{
+	GaimXfer *xfer = msn_new_xfer(gc, who);
 
 	if (file)
 		gaim_xfer_request_accepted(xfer, file);
@@ -1905,7 +1913,8 @@
 	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	msn_can_receive_file,	/* can_receive_file */
-	msn_send_file			/* send_file */
+	msn_send_file,			/* send_file */
+	msn_new_xfer			/* new_xfer */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/napster/napster.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/napster/napster.c	Sat Nov 19 00:26:12 2005 +0000
@@ -666,7 +666,8 @@
 	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	NULL,					/* can_receive_file */
-	NULL					/* send_file */
+	NULL,					/* send_file */
+	NULL					/* new_xfer */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/novell/novell.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/novell/novell.c	Sat Nov 19 00:26:12 2005 +0000
@@ -3507,7 +3507,8 @@
 	NULL,						/* roomlist_cancel */
 	NULL,						/* roomlist_expand_category */
 	NULL,						/* can_receive_file */
-	NULL						/* send_file */
+	NULL,						/* send_file */
+	NULL						/* new_xfer */
 };
 
 static GaimPluginInfo info = {
--- a/src/protocols/oscar/oscar.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/oscar/oscar.c	Sat Nov 19 00:26:12 2005 +0000
@@ -2646,11 +2646,8 @@
 	return can_receive;
 }
 
-/*
- * Called by the Gaim core when the user indicates that a file is to be sent to
- * a special someone.
- */
-static void oscar_send_file(GaimConnection *gc, const char *who, const char *file) {
+static GaimXfer*
+oscar_new_xfer(GaimConnection *gc, const char *who) {
 	OscarData *od;
 	GaimXfer *xfer;
 	struct aim_oft_info *oft_info;
@@ -2677,7 +2674,7 @@
 			AIM_XFER_SEND, AIM_XFER_PROXY, AIM_XFER_PROXY_STG1);
 		oft_info->proxy_info = aim_rv_proxy_createinfo(oft_info->sess, NULL, 0);
 		/* We must create a cookie before the request is sent
-		* so that it can be sent to the proxy */
+		 * so that it can be sent to the proxy */
 		aim_icbm_makecookie(oft_info->cookie);
 	} else {
 		ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1);
@@ -2699,6 +2696,16 @@
 	/* Keep track of this transfer for later */
 	od->file_transfers = g_slist_append(od->file_transfers, xfer);
 
+	return xfer;
+}
+
+/*
+ * Called by the Gaim core when the user indicates that a file is to be sent to
+ * a special someone.
+ */
+static void oscar_send_file(GaimConnection *gc, const char *who, const char *file) {
+	GaimXfer *xfer = oscar_new_xfer(gc, who);
+
 	/* Now perform the request */
 	if (file)
 		gaim_xfer_request_accepted(xfer, file);
@@ -8422,7 +8429,10 @@
 	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	oscar_can_receive_file,	/* can_receive_file */
-	oscar_send_file			/* send_file */
+	oscar_send_file,		/* send_file */
+	oscar_new_xfer,			/* new_xfer */
+	NULL,					/* whiteboard ops */
+ 	NULL					/* media ops */
 };
 
 static GaimPluginUiInfo prefs_info = {
--- a/src/protocols/sametime/sametime.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/sametime/sametime.c	Sat Nov 19 00:26:12 2005 +0000
@@ -5029,9 +5029,7 @@
 }
 
 
-static void mw_prpl_send_file(GaimConnection *gc,
-			      const char *who, const char *file) {
-
+static GaimXfer *mw_prpl_new_xfer(GaimConnect *gc, const char *who) {
   GaimAccount *acct;
   GaimXfer *xfer;
 
@@ -5041,6 +5039,14 @@
   gaim_xfer_set_init_fnc(xfer, ft_outgoing_init);
   gaim_xfer_set_cancel_send_fnc(xfer, ft_outgoing_cancel);
 
+  return xfer;
+}
+
+static void mw_prpl_send_file(GaimConnection *gc,
+			      const char *who, const char *file) {
+
+  GaimXfer *xfer = mw_prpl_new_xfer(gc, who);
+
   if(file) {
     DEBUG_INFO("file != NULL\n");
     gaim_xfer_request_accepted(xfer, file);
@@ -5109,6 +5115,7 @@
   .roomlist_expand_category  = NULL,
   .can_receive_file          = mw_prpl_can_receive_file,
   .send_file                 = mw_prpl_send_file,
+  .new_xfer                  = mw_prpl_new_xfer,
 };
 
 
--- a/src/protocols/silc/ft.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/silc/ft.c	Sat Nov 19 00:26:12 2005 +0000
@@ -347,7 +347,7 @@
 	silc_free(context);
 }
 
-void silcgaim_ftp_send_file(GaimConnection *gc, const char *name, const char *file)
+GaimXfer *silcgaim_ftp_new_xfer(GaimConnection *gc, const char *name)
 {
 	SilcGaim sg = gc->proto_data;
 	SilcClient client = sg->client;
@@ -357,47 +357,56 @@
 	SilcGaimXfer xfer;
 	char *nickname;
 
-	if (!name)
-		return;
+	g_return_val_if_fail(name != NULL, NULL);
 
 	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
+		return NULL;
 
 	/* Find client entry */
 	clients = silc_client_get_clients_local(client, conn, nickname, name,
-						&clients_count);
+											&clients_count);
 	if (!clients) {
 		silc_client_get_clients(client, conn, nickname, NULL,
-					silcgaim_ftp_send_file_resolved,
-					strdup(name));
+								silcgaim_ftp_send_file_resolved,
+								strdup(name));
 		silc_free(nickname);
-		return;
+		return NULL;
 	}
 
 	xfer = silc_calloc(1, sizeof(*xfer));
-	if (!xfer)
-		return;
+
+	g_return_val_if_fail(xfer != NULL, NULL);
+
 	xfer->sg = sg;
 	xfer->client_entry = clients[0];
 	xfer->xfer = gaim_xfer_new(xfer->sg->account, GAIM_XFER_SEND,
-				   xfer->client_entry->nickname);
+							   xfer->client_entry->nickname);
 	if (!xfer->xfer) {
 		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
 		g_free(xfer->hostname);
 		silc_free(xfer);
-		return;
+		return NULL;
 	}
 	gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_send);
 	gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_request_denied);
 	gaim_xfer_set_cancel_send_fnc(xfer->xfer, silcgaim_ftp_send_cancel);
 	xfer->xfer->data = xfer;
 
+	silc_free(clients);
+	silc_free(nickname);
+
+	return xfer;
+}
+
+void silcgaim_ftp_send_file(GaimConnection *gc, const char *name, const char *file)
+{
+	GaimXfer *xfer = silcgaim_ftp_new_xfer(gc, name);
+
+	g_return_if_fail(xfer != NULL);
+
 	/* Choose file to send */
 	if (file)
 		gaim_xfer_request_accepted(xfer->xfer, file);
 	else
 		gaim_xfer_request(xfer->xfer);
-
-	silc_free(clients);
-	silc_free(nickname);
 }
--- a/src/protocols/silc/silc.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/silc/silc.c	Sat Nov 19 00:26:12 2005 +0000
@@ -1557,7 +1557,9 @@
 	NULL,						/* roomlist_expand_category */
 	NULL,						/* can_receive_file */
 	silcgaim_ftp_send_file,		/* send_file */
-	&silcgaim_wb_ops,		/* whiteboard operations */
+	silcgaim_ftp_send_file,		/* send_file */
+	silcgaim_ftp_new_xfer,		/* new_xfer */
+	&silcgaim_wb_ops,			/* whiteboard operations */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/simple/simple.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/simple/simple.c	Sat Nov 19 00:26:12 2005 +0000
@@ -1334,21 +1334,21 @@
 	0,
 	NULL,					/* user_splits */
 	NULL,					/* protocol_options */
-	NO_BUDDY_ICONS,		/* icon_spec */
+	NO_BUDDY_ICONS,			/* icon_spec */
 	simple_list_icon,		/* list_icon */
-	NULL,	/* list_emblems */
+	NULL,					/* list_emblems */
 	NULL,					/* status_text */
 	NULL,					/* tooltip_text */
 	simple_status_types,	/* away_states */
 	NULL,					/* blist_node_menu */
-	NULL,	/* chat_info */
-	NULL,	/* chat_info_defaults */
-	simple_login,		/* login */
-	simple_close,		/* close */
-	simple_im_send,		/* send_im */
+	NULL,					/* chat_info */
+	NULL,					/* chat_info_defaults */
+	simple_login,			/* login */
+	simple_close,			/* close */
+	simple_im_send,			/* send_im */
 	NULL,					/* set_info */
-	simple_typing,					/* send_typing */
-	NULL,		/* get_info */
+	simple_typing,			/* send_typing */
+	NULL,					/* get_info */
 	simple_set_status,		/* set_status */
 	NULL,					/* set_idle */
 	NULL,					/* change_passwd */
@@ -1356,19 +1356,19 @@
 	NULL,					/* add_buddies */
 	simple_remove_buddy,	/* remove_buddy */
 	NULL,					/* remove_buddies */
-	dummy_add_deny,					/* add_permit */
-	dummy_add_deny,					/* add_deny */
-	dummy_add_deny,					/* rem_permit */
-	dummy_add_deny,					/* rem_deny */
-	dummy_permit_deny,					/* set_permit_deny */
-	NULL,		/* join_chat */
+	dummy_add_deny,			/* add_permit */
+	dummy_add_deny,			/* add_deny */
+	dummy_add_deny,			/* rem_permit */
+	dummy_add_deny,			/* rem_deny */
+	dummy_permit_deny,		/* set_permit_deny */
+	NULL,					/* join_chat */
 	NULL,					/* reject_chat */
-	NULL,	/* get_chat_name */
-	NULL,	/* chat_invite */
-	NULL,		/* chat_leave */
+	NULL,					/* get_chat_name */
+	NULL,					/* chat_invite */
+	NULL,					/* chat_leave */
 	NULL,					/* chat_whisper */
-	NULL,		/* chat_send */
-	simple_keep_alive,					/* keepalive */
+	NULL,					/* chat_send */
+	simple_keep_alive,		/* keepalive */
 	NULL,					/* register_user */
 	NULL,					/* get_cb_info */
 	NULL,					/* get_cb_away */
@@ -1381,13 +1381,14 @@
 	NULL,					/* set_buddy_icon */
 	NULL,					/* remove_group */
 	NULL,					/* get_cb_real_name */
-	NULL,	/* set_chat_topic */
+	NULL,					/* set_chat_topic */
 	NULL,					/* find_blist_chat */
-	NULL,	/* roomlist_get_list */
-	NULL,	/* roomlist_cancel */
+	NULL,					/* roomlist_get_list */
+	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	NULL,					/* can_receive_file */
-	NULL	/* send_file */
+	NULL,					/* send_file */
+	NULL					/* new_xfer */
 };
 
 
--- a/src/protocols/toc/toc.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/toc/toc.c	Sat Nov 19 00:26:12 2005 +0000
@@ -2295,7 +2295,8 @@
 	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	NULL,					/* can_receive_file */
-	NULL					/* send_file */
+	NULL,					/* send_file */
+	NULL					/* new_xfer */
 };
 
 static GaimPluginInfo info =
--- a/src/protocols/yahoo/yahoo.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/yahoo/yahoo.c	Sat Nov 19 00:26:12 2005 +0000
@@ -3605,6 +3605,7 @@
 	yahoo_roomlist_expand_category,
 	NULL, /* can_receive_file */
 	yahoo_send_file,
+	yahoo_new_xfer,
 	&yahoo_whiteboard_prpl_ops
 };
 
--- a/src/protocols/yahoo/yahoo_filexfer.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/yahoo/yahoo_filexfer.c	Sat Nov 19 00:26:12 2005 +0000
@@ -506,21 +506,20 @@
 	gaim_xfer_request(xfer);
 }
 
-void yahoo_send_file(GaimConnection *gc, const char *who, const char *file)
+GaimXfer *yahoo_new_xfer(GaimConnection *gc, const char *who)
 {
 	GaimXfer *xfer;
 	struct yahoo_xfer_data *xfer_data;
-
-	if (!who)
-		return;
-
+	
+	g_return_val_if_fail(who != NULL, NULL);
+	
 	xfer_data = g_new0(struct yahoo_xfer_data, 1);
 	xfer_data->gc = gc;
-
+	
 	/* Build the file transfer handle. */
 	xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who);
 	xfer->data = xfer_data;
-
+	
 	/* Setup our I/O op functions */
 	gaim_xfer_set_init_fnc(xfer,        yahoo_xfer_init);
 	gaim_xfer_set_start_fnc(xfer,       yahoo_xfer_start);
@@ -530,6 +529,15 @@
 	gaim_xfer_set_read_fnc(xfer,        yahoo_xfer_read);
 	gaim_xfer_set_write_fnc(xfer,       yahoo_xfer_write);
 
+	return xfer;
+}
+
+void yahoo_send_file(GaimConnection *gc, const char *who, const char *file)
+{
+	GaimXfer *xfer = yahoo_new_xfer(gc, who);
+
+	g_return_if_fail(xfer != NULL);
+
 	/* Now perform the request */
 	if (file)
 		gaim_xfer_request_accepted(xfer, file);
--- a/src/protocols/yahoo/yahoo_filexfer.h	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/yahoo/yahoo_filexfer.h	Sat Nov 19 00:26:12 2005 +0000
@@ -31,6 +31,14 @@
 void yahoo_process_filetransfer(GaimConnection *gc, struct yahoo_packet *pkt);
 
 /**
+ * Create a new GaimXfer
+ *
+ * @param gc The GaimConnection handle.
+ * @param who Who will we be sending it to?
+ */
+GaimXfer *yahoo_new_xfer(GaimConnection *gc, const char *who);
+
+/**
  * Send a file.
  *
  * @param gc The GaimConnection handle.
--- a/src/protocols/zephyr/zephyr.c	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/protocols/zephyr/zephyr.c	Sat Nov 19 00:26:12 2005 +0000
@@ -2772,42 +2772,42 @@
 
 static GaimPluginProtocolInfo prpl_info = {
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD,
-	NULL, /* ??? user_splits */
-	NULL,  /* ??? protocol_options */
+	NULL,					/* ??? user_splits */
+	NULL,					/* ??? protocol_options */
 	NO_BUDDY_ICONS,
 	zephyr_list_icon,
-	NULL, /* ??? list_emblems */
-	NULL, /* ??? status_text */
-	NULL, /* ??? tooltip_text */
-	zephyr_status_types, /* status_types */
-	NULL, /* ??? blist_node_menu - probably all useful actions are already handled*/
+	NULL,					/* ??? list_emblems */
+	NULL,					/* ??? status_text */
+	NULL,					/* ??? tooltip_text */
+	zephyr_status_types,	/* status_types */
+	NULL,					/* ??? blist_node_menu - probably all useful actions are already handled*/
 	zephyr_chat_info,		/* chat_info */
 	NULL,					/* chat_info_defaults */
 	zephyr_login,			/* login */
 	zephyr_close,			/* close */
 	zephyr_send_im,			/* send_im */
-	NULL,	/* XXX set info (Location?) */
-	zephyr_send_typing,  /* send_typing */
+	NULL,					/* XXX set info (Location?) */
+	zephyr_send_typing,		/* send_typing */
 	zephyr_zloc,			/* get_info */
-	zephyr_set_status, /* set_status */
-	NULL, /* ??? set idle */
-	NULL, /* change password */
+	zephyr_set_status,		/* set_status */
+	NULL,					/* ??? set idle */
+	NULL,					/* change password */
 	NULL,					/* add_buddy */
 	NULL,					/* add_buddies */
 	NULL,					/* remove_buddy */
 	NULL,					/* remove_buddies */
-	zephyr_add_permit,			/* add_permit */
-	zephyr_add_deny,			/* add_deny */
-	zephyr_remove_permit,			/* remove_permit */
-	zephyr_remove_deny,			/* remove_deny */
-	zephyr_set_permit_deny,			/* set_permit_deny */
-	zephyr_join_chat,			/* join_chat */
+	zephyr_add_permit,		/* add_permit */
+	zephyr_add_deny,		/* add_deny */
+	zephyr_remove_permit,	/* remove_permit */
+	zephyr_remove_deny,		/* remove_deny */
+	zephyr_set_permit_deny,	/* set_permit_deny */
+	zephyr_join_chat,		/* join_chat */
 	NULL,					/* reject_chat -- No chat invites*/
-	zephyr_get_chat_name,			/* get_chat_name */
+	zephyr_get_chat_name,	/* get_chat_name */
 	NULL,					/* chat_invite -- No chat invites*/
-	zephyr_chat_leave,			/* chat_leave */
+	zephyr_chat_leave,		/* chat_leave */
 	NULL,					/* chat_whisper -- No "whispering"*/
-	zephyr_chat_send,			/* chat_send */
+	zephyr_chat_send,		/* chat_send */
 	NULL,					/* keepalive -- Not necessary*/
 	NULL,					/* register_user -- Not supported*/
 	NULL,					/* XXX get_cb_info */
@@ -2821,13 +2821,14 @@
 	NULL,					/* XXX set_buddy_icon */
 	NULL,					/* remove_group */
 	NULL,					/* XXX get_cb_real_name */
-	zephyr_chat_set_topic,			/* set_chat_topic */
-	zephyr_find_blist_chat,			/* find_blist_chat */
+	zephyr_chat_set_topic,	/* set_chat_topic */
+	zephyr_find_blist_chat,	/* find_blist_chat */
 	NULL,					/* roomlist_get_list */
 	NULL,					/* roomlist_cancel */
 	NULL,					/* roomlist_expand_category */
 	NULL,					/* can_receive_file */
-	NULL					/* send_file */
+	NULL,					/* send_file */
+	NULL					/* new_xfer */
 };
 
 static GaimPluginInfo info = {
--- a/src/prpl.h	Sat Nov 19 00:16:45 2005 +0000
+++ b/src/prpl.h	Sat Nov 19 00:26:12 2005 +0000
@@ -80,6 +80,7 @@
 #define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0}
 
 #include "blist.h"
+#include "ft.h"
 #include "proxy.h"
 #include "plugin.h"
 #include "media.h"
@@ -309,7 +310,8 @@
 	/* file transfer callbacks */
 	gboolean (*can_receive_file)(GaimConnection *, const char *who);
 	void (*send_file)(GaimConnection *, const char *who, const char *filename);
-	
+	GaimXfer *(*new_xfer)(GaimConnection *, const char *who);
+
 	GaimWhiteboardPrplOps *whiteboard_prpl_ops;
 	GaimMediaPrplOps *media_prpl_ops;
 };