diff options
-rw-r--r-- | protocols/purple/Makefile | 2 | ||||
-rw-r--r-- | protocols/purple/ft.c | 234 | ||||
-rw-r--r-- | protocols/purple/purple.c | 199 |
3 files changed, 237 insertions, 198 deletions
diff --git a/protocols/purple/Makefile b/protocols/purple/Makefile index 15460529..403db799 100644 --- a/protocols/purple/Makefile +++ b/protocols/purple/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = purple.o +objects = ft.o purple.o CFLAGS += -Wall $(PURPLE_CFLAGS) LFLAGS += -r diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c new file mode 100644 index 00000000..62a1092a --- /dev/null +++ b/protocols/purple/ft.c @@ -0,0 +1,234 @@ +/***************************************************************************\ +* * +* 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. * +* * +\***************************************************************************/ + +#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/purple.c b/protocols/purple/purple.c index edd10219..b01fb991 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -36,7 +36,7 @@ GSList *purple_connections; libpurple in daemon mode anyway. */ static irc_t *local_irc; -static struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) +struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) { GSList *i; @@ -826,202 +826,7 @@ static PurpleNotifyUiOps bee_notify_uiops = prplcb_notify_email, }; - -struct prpl_xfer_data -{ - PurpleXfer *xfer; - file_transfer_t *ft; - gint ready_timer; - char *buf; - int buf_len; -}; - -static file_transfer_t *next_ft; - -/* 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 gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) -{ - struct prpl_xfer_data *px = xfer->ui_data; - gboolean st; - - 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; -} - -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_dbg( PurpleXfer *xfer ) -{ - fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); -} - -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; -} - -static PurpleXferUiOps bee_xfer_uiops = -{ - prplcb_xfer_new, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - prplcb_xfer_dbg, - 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; -} +extern PurpleXferUiOps bee_xfer_uiops; static void purple_ui_init() { |