Initial attempt at removing the magic around PurpleProtocolXferInterface

Thu, 31 Aug 2017 22:40:50 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Thu, 31 Aug 2017 22:40:50 -0500
changeset 38827
3573c82d32d8
parent 38648
9ff9acf9fa14
child 38828
a7190db83539

Initial attempt at removing the magic around PurpleProtocolXferInterface

finch/gntblist.c file | annotate | diff | comparison | revisions
finch/gntconv.c file | annotate | diff | comparison | revisions
libpurple/protocol.c file | annotate | diff | comparison | revisions
libpurple/protocol.h file | annotate | diff | comparison | revisions
libpurple/protocols/bonjour/bonjour.c file | annotate | diff | comparison | revisions
libpurple/protocols/irc/irc.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/jabber.c file | annotate | diff | comparison | revisions
libpurple/protocols/oscar/oscar.c file | annotate | diff | comparison | revisions
libpurple/protocols/sametime/sametime.c file | annotate | diff | comparison | revisions
libpurple/server.c file | annotate | diff | comparison | revisions
libpurple/xfer.c file | annotate | diff | comparison | revisions
libpurple/xfer.h file | annotate | diff | comparison | revisions
pidgin/gtkblist.c file | annotate | diff | comparison | revisions
pidgin/gtkconv.c file | annotate | diff | comparison | revisions
pidgin/gtkutils.c file | annotate | diff | comparison | revisions
--- a/finch/gntblist.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/finch/gntblist.c	Thu Aug 31 22:40:50 2017 -0500
@@ -1279,12 +1279,16 @@
 	add_custom_action(menu, _("Add Buddy Pounce"),
 			PURPLE_CALLBACK(finch_blist_pounce_node_cb), buddy);
 
-	if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send))
+	if (PURPLE_IS_PROTOCOL_XFER(protocol))
 	{
-		if (!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-			purple_protocol_xfer_iface_can_receive(protocol, gc, purple_buddy_get_name(buddy)))
+		if (purple_protocol_xfer_can_receive(
+			PURPLE_PROTOCOL_XFER(protocol),
+			gc,
+			purple_buddy_get_name(buddy))
+		) {
 			add_custom_action(menu, _("Send File"),
 					PURPLE_CALLBACK(finch_blist_menu_send_file_cb), buddy);
+		}
 	}
 
 	account = purple_buddy_get_account(buddy);
--- a/finch/gntconv.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/finch/gntconv.c	Thu Aug 31 22:40:50 2017 -0500
@@ -719,10 +719,13 @@
 		gnt_menu_add_item(GNT_MENU(sub), item);
 		gnt_menuitem_set_callback(item, add_pounce_cb, ggc);
 
-		if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send) &&
-				(!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-					purple_protocol_xfer_iface_can_receive(protocol, gc,
-					purple_conversation_get_name(ggc->active_conv)))) {
+		if (PURPLE_IS_PROTOCOL_XFER(protocol) && 
+			purple_protocol_xfer_can_receive(
+				PURPLE_PROTOCOL_XFER(protocol),
+				gc,
+				purple_conversation_get_name(ggc->active_conv)
+			)
+		) {
 			item = gnt_menuitem_new(_("Send File"));
 			gnt_menu_add_item(GNT_MENU(sub), item);
 			gnt_menuitem_set_callback(item, send_file_cb, ggc);
--- a/libpurple/protocol.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocol.c	Thu Aug 31 22:40:50 2017 -0500
@@ -800,63 +800,6 @@
 #undef DEFINE_PROTOCOL_FUNC
 
 /**************************************************************************
- * Protocol Xfer Interface API
- **************************************************************************/
-#define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \
-	PurpleProtocolXferIface *xfer_iface = \
-		PURPLE_PROTOCOL_GET_XFER_IFACE(protocol); \
-	if (xfer_iface && xfer_iface->funcname) \
-		xfer_iface->funcname(__VA_ARGS__);
-
-#define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \
-	PurpleProtocolXferIface *xfer_iface = \
-		PURPLE_PROTOCOL_GET_XFER_IFACE(protocol); \
-	if (xfer_iface && xfer_iface->funcname) \
-		return xfer_iface->funcname(__VA_ARGS__); \
-	else \
-		return defaultreturn;
-
-GType
-purple_protocol_xfer_iface_get_type(void)
-{
-	static GType type = 0;
-
-	if (G_UNLIKELY(type == 0)) {
-		static const GTypeInfo info = {
-			.class_size = sizeof(PurpleProtocolXferIface),
-		};
-
-		type = g_type_register_static(G_TYPE_INTERFACE,
-				"PurpleProtocolXferIface", &info, 0);
-	}
-	return type;
-}
-
-gboolean
-purple_protocol_xfer_iface_can_receive(PurpleProtocol *protocol,
-		PurpleConnection *gc, const char *who)
-{
-	DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, FALSE, can_receive, gc, who);
-}
-
-void
-purple_protocol_xfer_iface_send(PurpleProtocol *protocol, PurpleConnection *gc,
-		const char *who, const char *filename)
-{
-	DEFINE_PROTOCOL_FUNC(protocol, send, gc, who, filename);
-}
-
-PurpleXfer *
-purple_protocol_xfer_iface_new_xfer(PurpleProtocol *protocol,
-		PurpleConnection *gc, const char *who)
-{
-	DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, NULL, new_xfer, gc, who);
-}
-
-#undef DEFINE_PROTOCOL_FUNC_WITH_RETURN
-#undef DEFINE_PROTOCOL_FUNC
-
-/**************************************************************************
  * Protocol Roomlist Interface API
  **************************************************************************/
 #define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \
--- a/libpurple/protocol.h	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocol.h	Thu Aug 31 22:40:50 2017 -0500
@@ -556,35 +556,6 @@
 #define PURPLE_PROTOCOL_GET_PRIVACY_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE, \
                                                 PurpleProtocolPrivacyIface))
 
-#define PURPLE_TYPE_PROTOCOL_XFER_IFACE     (purple_protocol_xfer_iface_get_type())
-
-typedef struct _PurpleProtocolXferIface PurpleProtocolXferIface;
-
-/**
- * PurpleProtocolXferIface:
- *
- * The protocol file transfer interface.
- *
- * This interface provides file transfer callbacks for the protocol.
- */
-struct _PurpleProtocolXferIface
-{
-	/*< private >*/
-	GTypeInterface parent_iface;
-
-	/*< public >*/
-	gboolean (*can_receive)(PurpleConnection *, const char *who);
-
-	void (*send)(PurpleConnection *, const char *who,
-					  const char *filename);
-
-	PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who);
-};
-
-#define PURPLE_PROTOCOL_HAS_XFER_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PROTOCOL_XFER_IFACE))
-#define PURPLE_PROTOCOL_GET_XFER_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), PURPLE_TYPE_PROTOCOL_XFER_IFACE, \
-                                             PurpleProtocolXferIface))
-
 #define PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE     (purple_protocol_roomlist_iface_get_type())
 
 typedef struct _PurpleProtocolRoomlistIface PurpleProtocolRoomlistIface;
@@ -1084,26 +1055,6 @@
 		PurpleConnection *);
 
 /**************************************************************************/
-/* Protocol Xfer Interface API                                            */
-/**************************************************************************/
-
-/**
- * purple_protocol_xfer_iface_get_type:
- *
- * Returns: The #GType for the protocol xfer interface.
- */
-GType purple_protocol_xfer_iface_get_type(void);
-
-gboolean purple_protocol_xfer_iface_can_receive(PurpleProtocol *,
-		PurpleConnection *, const char *who);
-
-void purple_protocol_xfer_iface_send(PurpleProtocol *, PurpleConnection *,
-		const char *who, const char *filename);
-
-PurpleXfer *purple_protocol_xfer_iface_new_xfer(PurpleProtocol *,
-		PurpleConnection *, const char *who);
-
-/**************************************************************************/
 /* Protocol Roomlist Interface API                                        */
 /**************************************************************************/
 
--- a/libpurple/protocols/bonjour/bonjour.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocols/bonjour/bonjour.c	Thu Aug 31 22:40:50 2017 -0500
@@ -699,7 +699,7 @@
 }
 
 static void
-bonjour_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface)
+bonjour_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
 {
 	xfer_iface->can_receive = bonjour_can_receive_file;
 	xfer_iface->send        = bonjour_send_file;
@@ -718,7 +718,7 @@
 	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_IM_IFACE,
 	                                  bonjour_protocol_im_iface_init)
 
-	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE,
+	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
 	                                  bonjour_protocol_xfer_iface_init)
 );
 
--- a/libpurple/protocols/irc/irc.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocols/irc/irc.c	Thu Aug 31 22:40:50 2017 -0500
@@ -916,7 +916,7 @@
 }
 
 static void
-irc_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface)
+irc_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
 {
 	xfer_iface->send     = irc_dccsend_send_file;
 	xfer_iface->new_xfer = irc_dccsend_new_xfer;
@@ -940,7 +940,7 @@
 	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE,
 	                                  irc_protocol_roomlist_iface_init)
 
-	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE,
+	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
 	                                  irc_protocol_xfer_iface_init)
 );
 
--- a/libpurple/protocols/jabber/jabber.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocols/jabber/jabber.c	Thu Aug 31 22:40:50 2017 -0500
@@ -4263,7 +4263,7 @@
 }
 
 static void
-jabber_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface)
+jabber_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
 {
 	xfer_iface->can_receive = jabber_can_receive_file;
 	xfer_iface->send        = jabber_si_xfer_send;
@@ -4297,7 +4297,7 @@
 	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_MEDIA_IFACE,
 	                                  jabber_protocol_media_iface_init)
 
-	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE,
+	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
 	                                  jabber_protocol_xfer_iface_init)
 );
 
--- a/libpurple/protocols/oscar/oscar.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocols/oscar/oscar.c	Thu Aug 31 22:40:50 2017 -0500
@@ -5760,7 +5760,7 @@
 }
 
 static void
-oscar_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface)
+oscar_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
 {
 	xfer_iface->can_receive = oscar_can_receive_file;
 	xfer_iface->send        = oscar_send_file;
@@ -5785,7 +5785,7 @@
 	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE,
 	                                  oscar_protocol_privacy_iface_init)
 
-	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE,
+	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
 	                                  oscar_protocol_xfer_iface_init)
 );
 
--- a/libpurple/protocols/sametime/sametime.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/protocols/sametime/sametime.c	Thu Aug 31 22:40:50 2017 -0500
@@ -5701,7 +5701,7 @@
 
 
 static void
-mw_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface)
+mw_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
 {
   xfer_iface->can_receive = mw_protocol_can_receive_file;
   xfer_iface->send        = mw_protocol_send_file;
@@ -5727,7 +5727,7 @@
   PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE,
                                     mw_protocol_privacy_iface_init)
 
-  PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE,
+  PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
                                     mw_protocol_xfer_iface_init)
 );
 
--- a/libpurple/server.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/server.c	Thu Aug 31 22:40:50 2017 -0500
@@ -894,9 +894,11 @@
 	if (gc) {
 		protocol = purple_connection_get_protocol(gc);
 
-		if (!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-				purple_protocol_xfer_iface_can_receive(protocol, gc, who))
-
-			purple_protocol_xfer_iface_send(protocol, gc, who, file);
+		if(PURPLE_IS_PROTOCOL_XFER(protocol)) {
+			PurpleProtocolXferInterface *iface = PURPLE_PROTOCOL_XFER_GET_IFACE(protocol);
+			if(purple_protocol_xfer_can_receive(iface, gc, who)) {
+				purple_protocol_xfer_send(iface, gc, who, file);
+			}
+		}
 	}
 }
--- a/libpurple/xfer.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/xfer.c	Thu Aug 31 22:40:50 2017 -0500
@@ -2477,3 +2477,50 @@
 
 	return type;
 }
+
+/**************************************************************************
+ * PurpleXferProtocolInterface
+ **************************************************************************/
+G_DEFINE_INTERFACE(PurpleProtocolXfer, purple_protocol_xfer, G_TYPE_INVALID);
+
+static void
+purple_protocol_xfer_default_init(PurpleProtocolXferInterface *face) {
+}
+
+gboolean
+purple_protocol_xfer_can_receive(PurpleProtocolXferInterface *iface,
+                                 PurpleConnection *connection,
+                                 const gchar *who
+) {
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL_XFER(iface), FALSE);
+	g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE);
+	g_return_val_if_fail(who, FALSE);
+
+	return iface->can_receive(connection, who);
+}
+
+void
+purple_protocol_xfer_send(PurpleProtocolXferInterface *iface,
+                          PurpleConnection *connection,
+                          const gchar *who,
+                          const gchar *filename
+) {
+	g_return_if_fail(PURPLE_IS_PROTOCOL_XFER(iface));
+	g_return_if_fail(PURPLE_IS_CONNECTION(connection));
+	g_return_if_fail(who);
+	g_return_if_fail(filename);
+
+	iface->send(connection, who, filename);
+}
+
+PurpleXfer *
+purple_protocol_xfer_new_xfer(PurpleProtocolXferInterface *iface,
+                              PurpleConnection *connection,
+                              const gchar *who
+) {
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL_XFER(iface), FALSE);
+	g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE);
+	g_return_val_if_fail(who, FALSE);
+
+	return iface->new_xfer(connection, who);
+}
--- a/libpurple/xfer.h	Wed Aug 30 20:33:01 2017 -0300
+++ b/libpurple/xfer.h	Thu Aug 31 22:40:50 2017 -0500
@@ -38,6 +38,11 @@
 
 #define PURPLE_TYPE_XFER_UI_OPS      (purple_xfer_ui_ops_get_type())
 
+#define PURPLE_TYPE_PROTOCOL_XFER           (purple_protocol_xfer_get_type())
+#define PURPLE_PROTOCOL_XFER(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PROTOCOL_XFER, PurpleProtocolXferInterface))
+#define PURPLE_IS_PROTOCOL_XFER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PROTOCOL_XFER))
+#define PURPLE_PROTOCOL_XFER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), PURPLE_TYPE_PROTOCOL_XFER, PurpleProtocolXferInterface))
+
 /**************************************************************************/
 /** Data Structures                                                       */
 /**************************************************************************/
@@ -46,10 +51,13 @@
 
 typedef struct _PurpleXferUiOps PurpleXferUiOps;
 
+typedef struct _PurpleProtocolXferInterface PurpleProtocolXferInterface;
+
 #include <glib.h>
 #include <stdio.h>
 
 #include "account.h"
+#include "connection.h"
 
 /**
  * PurpleXferType:
@@ -182,6 +190,27 @@
 	void (*_purple_reserved4)(void);
 };
 
+/**
+ * PurpleProtocolXferIface:
+ *
+ * The protocol file transfer interface.
+ *
+ * This interface provides file transfer callbacks for the protocol.
+ */
+struct _PurpleProtocolXferInterface
+{
+	/*< private >*/
+	GTypeInterface parent_iface;
+
+	/*< public >*/
+	gboolean (*can_receive)(PurpleConnection *, const char *who);
+
+	void (*send)(PurpleConnection *, const char *who,
+					  const char *filename);
+
+	PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who);
+};
+
 G_BEGIN_DECLS
 
 /**************************************************************************/
@@ -946,6 +975,52 @@
  */
 PurpleXferUiOps *purple_xfers_get_ui_ops(void);
 
+/******************************************************************************
+ * Protocol Interface
+ *****************************************************************************/
+
+/**
+ * purple_protocol_xfer_get_type:
+ *
+ * Returns: The #GType for the protocol xfer interface.
+ */
+GType purple_protocol_xfer_get_type(void);
+
+/**
+ * purple_protocol_xfer_can_receive:
+ * @iface: The #PurpleProtocolXferIface instance
+ * @connection: The #PurpleConnection that we're checking
+ * @who: The user that we want to set a file transfer to.
+ *
+ * Checks whether or not we can transfer a file to @who.
+ *
+ * Returns: TRUE on success, FALSE otherwise.
+ */
+gboolean purple_protocol_xfer_can_receive(PurpleProtocolXferInterface *iface, PurpleConnection *connection, const gchar *who);
+
+/**
+ * purple_protocol_xfer_send:
+ * @iface: The #PurpleProtocolXferInterface instance
+ * @connection: The #PurpleConnection that we're checking
+ * @who: The user that we want to set a file transfer to.
+ * @filename: The name of the file to send.
+ *
+ * Sends @filename to @who.
+ */
+void purple_protocol_xfer_send(PurpleProtocolXferInterface *iface, PurpleConnection *connection, const gchar *who, const gchar *filename);
+
+/**
+ * purple_protocol_xfer_send:
+ * @iface: The #PurpleProtocolXferInterface instance
+ * @connection: The #PurpleConnection that we're checking
+ * @who: The user that we want to set a file transfer to.
+ *
+ * Creates a new #PurpleXfer to @who.
+ *
+ * Returns: A new #PurpleXfer instance.
+ */
+PurpleXfer *purple_protocol_xfer_new_xfer(PurpleProtocolXferInterface *iface, PurpleConnection *connection, const gchar *who);
+
 G_END_DECLS
 
 #endif /* _PURPLE_XFER_H_ */
--- a/pidgin/gtkblist.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/pidgin/gtkblist.c	Thu Aug 31 22:40:50 2017 -0500
@@ -1523,11 +1523,11 @@
 
 #endif
 
-	if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send)) {
-		if (!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-			purple_protocol_xfer_iface_can_receive(protocol,
-			purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)))
-		{
+	if (protocol && PURPLE_IS_PROTOCOL_XFER(protocol)) {
+		if (purple_protocol_xfer_can_receive(
+			PURPLE_PROTOCOL_XFER(protocol),
+			purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)
+		)) {
 			pidgin_new_menu_item(menu, _("_Send File..."),
                                         PIDGIN_STOCK_TOOLBAR_SEND_FILE,
                                         G_CALLBACK(gtk_blist_menu_send_file_cb),
--- a/pidgin/gtkconv.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/pidgin/gtkconv.c	Thu Aug 31 22:40:50 2017 -0500
@@ -1679,7 +1679,7 @@
 			g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free);
 
 
-		if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send))
+		if (protocol && PURPLE_IS_PROTOCOL_XFER(protocol))
 		{
 			gboolean can_receive_file = TRUE;
 
@@ -1693,9 +1693,11 @@
 				gchar *real_who = NULL;
 				real_who = purple_protocol_chat_iface_get_user_real_name(protocol, gc,
 					purple_chat_conversation_get_id(chat), who);
-				if (!(!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-						purple_protocol_xfer_iface_can_receive(protocol, gc, real_who ? real_who : who)))
+
+				if (!purple_protocol_xfer_can_receive(protocol, gc, real_who ? real_who : who)) {
 					can_receive_file = FALSE;
+				}
+
 				g_free(real_who);
 			}
 
@@ -7424,12 +7426,18 @@
 
 		if (PURPLE_IS_IM_CONVERSATION(conv))
 		{
+			gboolean can_send_file = FALSE;
+			const gchar *name = purple_conversation_get_name(conv);
+
+			if (PURPLE_IS_PROTOCOL_XFER(protocol) &&
+			    purple_protocol_xfer_can_receive(PURPLE_PROTOCOL_XFER(protocol), gc, name)
+			) {
+				can_send_file = TRUE;
+			}
+
 			gtk_action_set_sensitive(win->menu->add, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, add_buddy)));
 			gtk_action_set_sensitive(win->menu->remove, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER_IFACE, remove_buddy)));
-			gtk_action_set_sensitive(win->menu->send_file,
-									 (PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send) &&
-									 (!PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive) ||
-									  purple_protocol_xfer_iface_can_receive(protocol, gc, purple_conversation_get_name(conv)))));
+			gtk_action_set_sensitive(win->menu->send_file, can_send_file);
 			gtk_action_set_sensitive(win->menu->get_attention, (PURPLE_PROTOCOL_IMPLEMENTS(protocol, ATTENTION_IFACE, send)));
 			gtk_action_set_sensitive(win->menu->alias,
 									 (account != NULL) &&
--- a/pidgin/gtkutils.c	Wed Aug 30 20:33:01 2017 -0300
+++ b/pidgin/gtkutils.c	Thu Aug 31 22:40:50 2017 -0500
@@ -1439,10 +1439,15 @@
 	if (!(purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_NO_IMAGES))
 		im = TRUE;
 
-	if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, can_receive))
-		ft = purple_protocol_xfer_iface_can_receive(protocol, gc, who);
-	else if (protocol && PURPLE_PROTOCOL_IMPLEMENTS(protocol, XFER_IFACE, send))
-		ft = TRUE;
+	if (protocol && PURPLE_IS_PROTOCOL_XFER(protocol)) {
+		PurpleProtocolXferInterface *iface = PURPLE_PROTOCOL_XFER(protocol);
+
+		if(iface->can_receive) {
+			ft = purple_protocol_xfer_can_receive(protocol, gc, who);
+		} else {
+			ft = (iface->send) ? TRUE : FALSE;
+		}
+	}
 
 	if (im && ft) {
 		purple_request_choice(NULL, NULL,

mercurial