diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/purple/ft.c | 113 | 
1 files changed, 93 insertions, 20 deletions
| diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index 8cfa60dd..ab637a94 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -37,8 +37,9 @@ struct prpl_xfer_data  {  	PurpleXfer *xfer;  	file_transfer_t *ft; +	struct im_connection *ic;  	int fd; -	char *fn; +	char *fn, *orig_fn, *handle;  	gboolean ui_wants_data;  }; @@ -82,20 +83,16 @@ static void prplcb_xfer_new( PurpleXfer *xfer )  	}  	else  	{ -		/* -		struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); +		struct file_transfer *ft = next_ft; +		struct prpl_xfer_data *px = ft->data; -		px->fd = -1; -		px->ft = next_ft; -		px->ft->data = px; +		xfer->ui_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 ); +		purple_xfer_set_filename( xfer, px->orig_fn ); +		purple_xfer_set_local_filename( xfer, px->fn );  		next_ft = NULL; -		*/  	}  } @@ -179,6 +176,8 @@ static void prplcb_xfer_destroy( PurpleXfer *xfer )  	struct prpl_xfer_data *px = xfer->ui_data;  	g_free( px->fn ); +	g_free( px->orig_fn ); +	g_free( px->handle );  	if( px->fd >= 0 )  		close( px->fd );  	g_free( px ); @@ -188,6 +187,20 @@ static void prplcb_xfer_progress( PurpleXfer *xfer, double percent )  {  	struct prpl_xfer_data *px = xfer->ui_data; +	if( px == NULL ) +		return; +	 +	if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) +	{ +		if( *px->fn ) +		{ +			//unlink( px->fn ); +			*px->fn = '\0'; +		} +		 +		return; +	} +	  	if( px->fd == -1 && percent > 0 )  	{  		/* Weeeeeeeee, we're getting data! That means the file exists @@ -215,6 +228,16 @@ static void prplcb_xfer_cancel_remote( PurpleXfer *xfer )  	imcb_file_canceled( px->ft, "Canceled by remote end" );  } +static void prplcb_xfer_add( PurpleXfer *xfer ) +{ +	if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) +	{ +		struct prpl_xfer_data *px = xfer->ui_data; +		 +		purple_xfer_set_filename( xfer, px->orig_fn ); +	} +} +  static void prplcb_xfer_dbg( PurpleXfer *xfer )  {  	fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); @@ -222,27 +245,77 @@ static void prplcb_xfer_dbg( PurpleXfer *xfer )  /* Sending files (UI->IM): */ -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ); +static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ); + +void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle )  { -	return FALSE; +	struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); +	 +	ft->data = px; +	px->ft = ft; +	px->fn = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); +	px->fd = mkstemp( px->fn ); +	 +	px->ic = ic; +	px->handle = g_strdup( handle ); +	px->orig_fn = g_strdup( ft->file_name ); +	 +	imcb_log( ic, "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..." ); +	 +	b_timeout_add( 0, purple_transfer_request_cb, ft );  } -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +static void purple_transfer_forward( struct file_transfer *ft )  { -	PurpleAccount *pa = ic->proto_data; -	struct prpl_xfer_data *px; +	struct prpl_xfer_data *px = ft->data; +	PurpleAccount *pa = px->ic->proto_data;  	/* 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 ); +	serv_send_file( purple_account_get_connection( pa ), px->handle, px->fn ); +} + +static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ) +{ +	file_transfer_t *ft = data; +	 +	if( ft->write == NULL ) +	{ +		ft->write = prpl_xfer_write; +		imcb_file_recv_start( ft ); +	} -	ft->write = prpl_xfer_write; +	ft->write_request( ft ); -	px = ft->data; -	imcb_file_recv_start( ft ); +	return FALSE;  } +static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +{ +	struct prpl_xfer_data *px = ft->data; +	 +	if( write( px->fd, buffer, len ) != len ) +	{ +		imcb_file_canceled( ft, "Error while writing temporary file" ); +		return FALSE; +	} +	 +	if( lseek( px->fd, 0, SEEK_CUR ) >= ft->file_size ) +	{ +		close( px->fd ); +		px->fd = -1; +		 +		purple_transfer_forward( ft ); +		imcb_file_finished( ft ); +		px->ft = NULL; +	} +	else +		b_timeout_add( 0, purple_transfer_request_cb, ft ); +	 +	return TRUE; +} @@ -250,7 +323,7 @@ PurpleXferUiOps bee_xfer_uiops =  {  	prplcb_xfer_new,  	prplcb_xfer_destroy, -	prplcb_xfer_dbg, +	prplcb_xfer_add,  	prplcb_xfer_progress,  	prplcb_xfer_dbg,  	prplcb_xfer_cancel_remote, | 
