aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dcc.c72
-rw-r--r--dcc.h2
-rw-r--r--irc_im.c19
-rw-r--r--lib/misc.c5
4 files changed, 43 insertions, 55 deletions
diff --git a/dcc.c b/dcc.c
index e97b822f..f17f52aa 100644
--- a/dcc.c
+++ b/dcc.c
@@ -503,69 +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 )
{
irc_t *irc = (irc_t *) ic->bee->ui_data;
- char *pattern = "SEND"
- " (([^\"][^ ]*)|\"(([^\"]|\\\")*)\")"
- " (([0-9]*)|([^ ]*))"
- " ([0-9]*)"
- " ([0-9]*)\001";
- regmatch_t pmatch[10];
- regex_t re;
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;
@@ -573,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",
@@ -587,14 +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 );
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;
}
diff --git a/dcc.h b/dcc.h
index c0cf6ccc..f3e7aa98 100644
--- a/dcc.h
+++ b/dcc.h
@@ -97,7 +97,7 @@ typedef struct dcc_file_transfer {
file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size );
void dcc_canceled( file_transfer_t *file, char *reason );
gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size );
-file_transfer_t *dcc_request( struct im_connection *ic, char *line );
+file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp );
void dcc_finish( file_transfer_t *file );
void dcc_close( file_transfer_t *file );
gboolean dccs_recv_start( file_transfer_t *ft );
diff --git a/irc_im.c b/irc_im.c
index ccf0d55c..85828eb1 100644
--- a/irc_im.c
+++ b/irc_im.c
@@ -210,6 +210,25 @@ static gboolean bee_irc_user_privmsg( irc_user_t *iu, const char *msg )
return FALSE;
}
+static gboolean bee_irc_user_ctcp( irc_user_t *iu, char *const *ctcp )
+{
+ if( ctcp[1] && g_strcasecmp( ctcp[0], "DCC" ) == 0
+ && g_strcasecmp( ctcp[1], "SEND" ) == 0 )
+ {
+ if( iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->transfer_request )
+ {
+ file_transfer_t *ft = dcc_request( iu->bu->ic, ctcp );
+ if ( ft )
+ iu->bu->ic->acc->prpl->transfer_request( iu->bu->ic, ft, iu->bu->handle );
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static const struct irc_user_funcs irc_user_im_funcs = {
bee_irc_user_privmsg,
+ bee_irc_user_ctcp,
};
diff --git a/lib/misc.c b/lib/misc.c
index 2901704a..fa5bb9a4 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -654,7 +654,10 @@ char **split_command_parts( char *command )
{
q = *s = 0;
}
- cmd[k] = NULL;
+
+ /* Full zero-padding for easier argc checking. */
+ while( k <= IRC_MAX_ARGS )
+ cmd[k++] = NULL;
return cmd;
}