diff options
Diffstat (limited to 'dcc.c')
| -rw-r--r-- | dcc.c | 144 | 
1 files changed, 36 insertions, 108 deletions
| @@ -60,55 +60,16 @@ unsigned int local_transfer_id=1;   */  unsigned int receivedchunks=0, receiveddata=0; -static void dcc_finish( file_transfer_t *file ); -static void dcc_close( file_transfer_t *file ); +void dcc_finish( file_transfer_t *file ); +void dcc_close( file_transfer_t *file );  gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond ); -int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr ); -gboolean dccs_recv_start( file_transfer_t *ft ); +int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr );  gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond);  gboolean dccs_recv_write_request( file_transfer_t *ft );  gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond );  gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ); -/* As defined in ft.h */ -file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *handle, char *file_name, size_t file_size ) -{ -	user_t *u = user_findhandle( ic, handle ); -	/* one could handle this more intelligent like imcb_buddy_msg. -	 * can't call it directly though cause it does some wrapping. -	 * Maybe give imcb_buddy_msg a parameter NO_WRAPPING? */ -	if (!u) return NULL; - -	return dccs_send_start( ic, u->nick, file_name, file_size ); -}; - -/* As defined in ft.h */ -void imcb_file_canceled( file_transfer_t *file, char *reason ) -{ -	if( file->canceled ) -		file->canceled( file, reason ); - -	dcc_close( file ); -} - -/* As defined in ft.h */ -gboolean imcb_file_recv_start( file_transfer_t *ft ) -{ -	return dccs_recv_start( ft ); -} - -/* As defined in ft.h */ -void imcb_file_finished( file_transfer_t *file ) -{ -	dcc_file_transfer_t *df = file->priv; - -	if( file->bytes_transferred >= file->file_size ) -		dcc_finish( file ); -	else -		df->proto_finished = TRUE; -} - -dcc_file_transfer_t *dcc_alloc_transfer( char *file_name, size_t file_size, struct im_connection *ic ) +dcc_file_transfer_t *dcc_alloc_transfer( const char *file_name, size_t file_size, struct im_connection *ic )  {  	file_transfer_t *file = g_new0( file_transfer_t, 1 );  	dcc_file_transfer_t *df = file->priv = g_new0( dcc_file_transfer_t, 1 ); @@ -116,17 +77,18 @@ dcc_file_transfer_t *dcc_alloc_transfer( char *file_name, size_t file_size, stru  	file->file_size = file_size;  	file->file_name = g_strdup( file_name );  	file->local_id = local_transfer_id++; -	df->ic = ic; +	file->ic = df->ic = ic;  	df->ft = file;  	return df;  }  /* This is where the sending magic starts... */ -file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size ) +file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size )  {  	file_transfer_t *file;  	dcc_file_transfer_t *df; +	irc_t *irc = (irc_t *) ic->bee->ui_data;  	struct sockaddr_storage saddr;  	char *errmsg;  	char host[HOST_NAME_MAX]; @@ -149,20 +111,20 @@ file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, cha  	file->status = FT_STATUS_LISTENING; -	if( !dccs_send_request( df, user_nick, &saddr ) ) +	if( !dccs_send_request( df, iu, &saddr ) )  		return NULL;  	/* watch */  	df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_send_proto, df ); -	df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, file ); +	irc->file_transfers = g_slist_prepend( irc->file_transfers, file );  	df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df );  	imcb_log( ic, "File transfer request from %s for %s (%zd kb).\n"  	              "Accept the file transfer if you'd like the file. If you don't, "  	              "issue the 'transfers reject' command.", -	              user_nick, file_name, file_size / 1024 ); +	              iu->nick, file_name, file_size / 1024 );  	return file;  } @@ -215,7 +177,7 @@ gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond )  		return dcc_abort( df , msg ": %s", strerror( errno ) );  /* Creates the "DCC SEND" line and sends it to the server */ -int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr ) +int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr )  {  	char ipaddr[INET6_ADDRSTRLEN];   	const void *netaddr; @@ -249,8 +211,7 @@ int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct soc  	cmd = g_strdup_printf( "\001DCC SEND %s %s %u %zu\001",  				df->ft->file_name, ipaddr, port, df->ft->file_size ); -	if ( !irc_msgfrom( df->ic->irc, user_nick, cmd ) ) -		return dcc_abort( df, "Couldn't send `DCC SEND' message to %s.", user_nick ); +	irc_send_msg_raw( iu, "PRIVMSG", iu->irc->user->nick, cmd );  	g_free( cmd ); @@ -495,9 +456,10 @@ gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_l  /*   * Cleans up after a transfer.   */ -static void dcc_close( file_transfer_t *file ) +void dcc_close( file_transfer_t *file )  {  	dcc_file_transfer_t *df = file->priv; +	irc_t *irc = (irc_t *) df->ic->bee->ui_data;  	if( file->free )  		file->free( file ); @@ -513,7 +475,7 @@ static void dcc_close( file_transfer_t *file )  	if( df->progress_timeout )  		b_event_remove( df->progress_timeout ); -	df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file ); +	irc->file_transfers = g_slist_remove( irc->file_transfers, file );  	g_free( df );  	g_free( file->file_name ); @@ -541,68 +503,37 @@ void dcc_finish( file_transfer_t *file )   * IP can be an unsigned int (IPV4) or something else (IPV6)   *    */ -file_transfer_t *dcc_request( struct im_connection *ic, char *line ) +file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp )  { -	char *pattern = "SEND" -		" (([^\"][^ ]*)|\"(([^\"]|\\\")*)\")" -		" (([0-9]*)|([^ ]*))" -		" ([0-9]*)" -		" ([0-9]*)\001"; -	regmatch_t pmatch[10]; -	regex_t re; +	irc_t *irc = (irc_t *) ic->bee->ui_data;  	file_transfer_t *ft;  	dcc_file_transfer_t *df; -	char errbuf[256]; -	int regerrcode, gret; - -	if( ( regerrcode = regcomp( &re, pattern, REG_EXTENDED ) ) || -	    ( regerrcode = regexec( &re, line, 10, pmatch, 0 ) ) ) { -		regerror( regerrcode,&re,errbuf,sizeof( errbuf ) ); -		imcb_log( ic,  -			  "DCC: error parsing 'DCC SEND': %s, line: %s",  -			  errbuf, line ); -		return NULL; -	} - -	if( ( pmatch[1].rm_so > 0 ) && -	    ( pmatch[5].rm_so > 0 ) && -	    ( pmatch[8].rm_so > 0 ) && -	    ( pmatch[9].rm_so > 0 ) ) +	int gret; +	size_t filesize; +	 +	if( ctcp[5] != NULL && +	    sscanf( ctcp[4], "%zd", &filesize ) == 1 && /* Just int. validation. */ +	    sscanf( ctcp[5], "%zd", &filesize ) == 1 )  	{ -		char *input = g_strdup( line );  		char *filename, *host, *port; -		size_t filesize;  		struct addrinfo hints, *rp; - -		/* "filename" or filename */ -		if ( pmatch[2].rm_so > 0 ) -		{ -			input[pmatch[2].rm_eo] = '\0'; -			filename = input + pmatch[2].rm_so; -		} else -		{ -			input[pmatch[3].rm_eo] = '\0'; -			filename = input + pmatch[3].rm_so; -		} -			 -		input[pmatch[5].rm_eo] = '\0'; - -		/* number means ipv4, something else means ipv6 */ -		if ( pmatch[6].rm_so > 0 ) +		 +		filename = ctcp[2]; +		 +		host = ctcp[3]; +		while( *host && isdigit( *host ) ) host++; /* Just digits? */ +		if( *host == '\0' )  		{ -			struct in_addr ipaddr = { .s_addr = htonl( strtoul( input + pmatch[5].rm_so, NULL, 10 ) ) }; +			struct in_addr ipaddr = { .s_addr = htonl( atoll( ctcp[3] ) ) };  			host = inet_ntoa( ipaddr );  		} else  		{  			/* Contains non-numbers, hopefully an IPV6 address */ -			host = input + pmatch[7].rm_so; +			host = ctcp[3];  		} -		input[pmatch[8].rm_eo] = '\0'; -		input[pmatch[9].rm_eo] = '\0'; - -		port = input + pmatch[8].rm_so; -		filesize = atoll( input + pmatch[9].rm_so ); +		port = ctcp[4]; +		filesize = atoll( ctcp[5] );  		memset( &hints, 0, sizeof ( struct addrinfo ) );  		hints.ai_socktype = SOCK_STREAM; @@ -610,7 +541,6 @@ file_transfer_t *dcc_request( struct im_connection *ic, char *line )  		if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) )  		{ -			g_free( input );  			imcb_log( ic, "DCC: getaddrinfo() failed with %s "  				  "when parsing incoming 'DCC SEND': "  				  "host %s, port %s",  @@ -624,15 +554,13 @@ file_transfer_t *dcc_request( struct im_connection *ic, char *line )  		memcpy( &df->saddr, rp->ai_addr, rp->ai_addrlen );  		freeaddrinfo( rp ); -		g_free( input ); -		df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, ft ); +		irc->file_transfers = g_slist_prepend( irc->file_transfers, ft );  		return ft;  	} - -	imcb_log( ic, "DCC: couldnt parse 'DCC SEND' line: %s", line ); +	else +		imcb_log( ic, "DCC: couldnt parse `DCC SEND' line" );  	return NULL;  } - | 
