aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--protocols/purple/ft-direct.c239
-rw-r--r--protocols/purple/ft.c137
2 files changed, 275 insertions, 101 deletions
diff --git a/protocols/purple/ft-direct.c b/protocols/purple/ft-direct.c
new file mode 100644
index 00000000..98a16d75
--- /dev/null
+++ b/protocols/purple/ft-direct.c
@@ -0,0 +1,239 @@
+/***************************************************************************\
+* *
+* BitlBee - An IRC to IM gateway *
+* libpurple module - File transfer stuff *
+* *
+* Copyright 2009-2010 Wilmer van der Gaast <wilmer@gaast.net> *
+* *
+* 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., *
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+* *
+\***************************************************************************/
+
+/* This code tries to do direct file transfers, i.e. without caching the file
+ locally on disk first. Since libpurple can only do this since version 2.6.0
+ and even then very unreliably (and not with all IM modules), I'm canning
+ this code for now. */
+
+#include "bitlbee.h"
+
+#include <stdarg.h>
+
+#include <glib.h>
+#include <purple.h>
+
+struct prpl_xfer_data
+{
+ PurpleXfer *xfer;
+ file_transfer_t *ft;
+ gint ready_timer;
+ char *buf;
+ int buf_len;
+};
+
+static file_transfer_t *next_ft;
+
+struct im_connection *purple_ic_by_pa( PurpleAccount *pa );
+
+/* Glorious hack: We seem to have to remind at least some libpurple plugins
+ that we're ready because this info may get lost if we give it too early.
+ So just do it ten times a second. :-/ */
+static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond )
+{
+ struct prpl_xfer_data *px = data;
+
+ purple_xfer_ui_ready( px->xfer );
+
+ return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE;
+}
+
+static gboolean prpl_xfer_write_request( struct file_transfer *ft )
+{
+ struct prpl_xfer_data *px = ft->data;
+ px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px );
+ return TRUE;
+}
+
+static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len )
+{
+ struct prpl_xfer_data *px = ft->data;
+
+ px->buf = g_memdup( buffer, len );
+ px->buf_len = len;
+
+ //purple_xfer_ui_ready( px->xfer );
+ px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px );
+
+ return TRUE;
+}
+
+static void prpl_xfer_accept( struct file_transfer *ft )
+{
+ struct prpl_xfer_data *px = ft->data;
+ purple_xfer_request_accepted( px->xfer, NULL );
+ prpl_xfer_write_request( ft );
+}
+
+static void prpl_xfer_canceled( struct file_transfer *ft, char *reason )
+{
+ struct prpl_xfer_data *px = ft->data;
+ purple_xfer_request_denied( px->xfer );
+}
+
+static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond )
+{
+ PurpleXfer *xfer = data;
+ struct im_connection *ic = purple_ic_by_pa( xfer->account );
+ struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
+ PurpleBuddy *buddy;
+ const char *who;
+
+ buddy = purple_find_buddy( xfer->account, xfer->who );
+ who = buddy ? purple_buddy_get_name( buddy ) : xfer->who;
+
+ /* TODO(wilmer): After spreading some more const goodness in BitlBee,
+ remove the evil cast below. */
+ px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size );
+ px->ft->data = px;
+ px->xfer = data;
+ px->xfer->ui_data = px;
+
+ px->ft->accept = prpl_xfer_accept;
+ px->ft->canceled = prpl_xfer_canceled;
+ px->ft->write_request = prpl_xfer_write_request;
+
+ return FALSE;
+}
+
+static void prplcb_xfer_new( PurpleXfer *xfer )
+{
+ if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE )
+ {
+ /* This should suppress the stupid file dialog. */
+ purple_xfer_set_local_filename( xfer, "/tmp/wtf123" );
+
+ /* Sadly the xfer struct is still empty ATM so come back after
+ the caller is done. */
+ b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer );
+ }
+ else
+ {
+ struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
+
+ px->ft = next_ft;
+ px->ft->data = px;
+ px->xfer = xfer;
+ px->xfer->ui_data = px;
+
+ purple_xfer_set_filename( xfer, px->ft->file_name );
+ purple_xfer_set_size( xfer, px->ft->file_size );
+
+ next_ft = NULL;
+ }
+}
+
+static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )
+{
+ fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent );
+}
+
+static void prplcb_xfer_dbg( PurpleXfer *xfer )
+{
+ fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer );
+}
+
+static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size )
+{
+ struct prpl_xfer_data *px = xfer->ui_data;
+ gboolean st;
+
+ fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len );
+
+ b_event_remove( px->ready_timer );
+ px->ready_timer = 0;
+
+ st = px->ft->write( px->ft, (char*) buffer, size );
+
+ if( st && xfer->bytes_remaining == size )
+ imcb_file_finished( px->ft );
+
+ return st ? size : 0;
+}
+
+gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size )
+{
+ struct prpl_xfer_data *px = xfer->ui_data;
+
+ fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len );
+
+ if( px->buf )
+ {
+ *buffer = px->buf;
+ px->buf = NULL;
+
+ px->ft->write_request( px->ft );
+
+ return px->buf_len;
+ }
+
+ return 0;
+}
+
+PurpleXferUiOps bee_xfer_uiops =
+{
+ prplcb_xfer_new,
+ prplcb_xfer_dbg,
+ prplcb_xfer_dbg,
+ prplcb_xfer_progress,
+ prplcb_xfer_dbg,
+ prplcb_xfer_dbg,
+ prplcb_xfer_write,
+ prplcb_xfer_read,
+ prplcb_xfer_dbg,
+};
+
+static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond );
+
+void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle )
+{
+ PurpleAccount *pa = ic->proto_data;
+ struct prpl_xfer_data *px;
+
+ /* xfer_new() will pick up this variable. It's a hack but we're not
+ multi-threaded anyway. */
+ next_ft = ft;
+ serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name );
+
+ ft->write = prpl_xfer_write;
+
+ px = ft->data;
+ imcb_file_recv_start( ft );
+
+ px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px );
+}
+
+static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond )
+{
+ struct prpl_xfer_data *px = data;
+
+ if( px->ft->status & FT_STATUS_TRANSFERRING )
+ {
+ fprintf( stderr, "The ft, it is ready...\n" );
+ px->ft->write_request( px->ft );
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c
index 62a1092a..4b5a3f49 100644
--- a/protocols/purple/ft.c
+++ b/protocols/purple/ft.c
@@ -21,6 +21,11 @@
* *
\***************************************************************************/
+/* Do file transfers via disk for now, since libpurple was really designed
+ for straight-to/from disk fts and is only just learning how to pass the
+ file contents the the UI instead (2.6.0 and higher it seems, and with
+ varying levels of success). */
+
#include "bitlbee.h"
#include <stdarg.h>
@@ -41,36 +46,16 @@ static file_transfer_t *next_ft;
struct im_connection *purple_ic_by_pa( PurpleAccount *pa );
-/* Glorious hack: We seem to have to remind at least some libpurple plugins
- that we're ready because this info may get lost if we give it too early.
- So just do it ten times a second. :-/ */
-static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond )
-{
- struct prpl_xfer_data *px = data;
-
- purple_xfer_ui_ready( px->xfer );
-
- return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE;
-}
-
static gboolean prpl_xfer_write_request( struct file_transfer *ft )
{
- struct prpl_xfer_data *px = ft->data;
- px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px );
- return TRUE;
+ return FALSE;
}
static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len )
{
struct prpl_xfer_data *px = ft->data;
- px->buf = g_memdup( buffer, len );
- px->buf_len = len;
-
- //purple_xfer_ui_ready( px->xfer );
- px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px );
-
- return TRUE;
+ return FALSE;
}
static void prpl_xfer_accept( struct file_transfer *ft )
@@ -86,30 +71,7 @@ static void prpl_xfer_canceled( struct file_transfer *ft, char *reason )
purple_xfer_request_denied( px->xfer );
}
-static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond )
-{
- PurpleXfer *xfer = data;
- struct im_connection *ic = purple_ic_by_pa( xfer->account );
- struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
- PurpleBuddy *buddy;
- const char *who;
-
- buddy = purple_find_buddy( xfer->account, xfer->who );
- who = buddy ? purple_buddy_get_name( buddy ) : xfer->who;
-
- /* TODO(wilmer): After spreading some more const goodness in BitlBee,
- remove the evil cast below. */
- px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size );
- px->ft->data = px;
- px->xfer = data;
- px->xfer->ui_data = px;
-
- px->ft->accept = prpl_xfer_accept;
- px->ft->canceled = prpl_xfer_canceled;
- px->ft->write_request = prpl_xfer_write_request;
-
- return FALSE;
-}
+static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond );
static void prplcb_xfer_new( PurpleXfer *xfer )
{
@@ -124,6 +86,7 @@ static void prplcb_xfer_new( PurpleXfer *xfer )
}
else
{
+ /*
struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
px->ft = next_ft;
@@ -135,54 +98,43 @@ static void prplcb_xfer_new( PurpleXfer *xfer )
purple_xfer_set_size( xfer, px->ft->file_size );
next_ft = NULL;
+ */
}
}
-static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )
-{
- fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent );
-}
-
-static void prplcb_xfer_dbg( PurpleXfer *xfer )
-{
- fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer );
-}
-
-static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size )
+static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond )
{
- struct prpl_xfer_data *px = xfer->ui_data;
- gboolean st;
-
- fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len );
+ PurpleXfer *xfer = data;
+ struct im_connection *ic = purple_ic_by_pa( xfer->account );
+ struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 );
+ PurpleBuddy *buddy;
+ const char *who;
- b_event_remove( px->ready_timer );
- px->ready_timer = 0;
+ buddy = purple_find_buddy( xfer->account, xfer->who );
+ who = buddy ? purple_buddy_get_name( buddy ) : xfer->who;
- st = px->ft->write( px->ft, (char*) buffer, size );
+ /* TODO(wilmer): After spreading some more const goodness in BitlBee,
+ remove the evil cast below. */
+ px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size );
+ px->ft->data = px;
+ px->xfer = data;
+ px->xfer->ui_data = px;
- if( st && xfer->bytes_remaining == size )
- imcb_file_finished( px->ft );
+ px->ft->accept = prpl_xfer_accept;
+ px->ft->canceled = prpl_xfer_canceled;
+ px->ft->write_request = prpl_xfer_write_request;
- return st ? size : 0;
+ return FALSE;
}
-gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size )
+static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )
{
- struct prpl_xfer_data *px = xfer->ui_data;
-
- fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len );
+ fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent );
+}
- if( px->buf )
- {
- *buffer = px->buf;
- px->buf = NULL;
-
- px->ft->write_request( px->ft );
-
- return px->buf_len;
- }
-
- return 0;
+static void prplcb_xfer_dbg( PurpleXfer *xfer )
+{
+ fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer );
}
PurpleXferUiOps bee_xfer_uiops =
@@ -193,8 +145,8 @@ PurpleXferUiOps bee_xfer_uiops =
prplcb_xfer_progress,
prplcb_xfer_dbg,
prplcb_xfer_dbg,
- prplcb_xfer_write,
- prplcb_xfer_read,
+ NULL,
+ NULL,
prplcb_xfer_dbg,
};
@@ -214,21 +166,4 @@ void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, cha
px = ft->data;
imcb_file_recv_start( ft );
-
- px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px );
-}
-
-static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond )
-{
- struct prpl_xfer_data *px = data;
-
- if( px->ft->status & FT_STATUS_TRANSFERRING )
- {
- fprintf( stderr, "The ft, it is ready...\n" );
- px->ft->write_request( px->ft );
-
- return FALSE;
- }
-
- return TRUE;
}