Index: dcc.c
===================================================================
--- dcc.c	(revision 24b8bbb2616d685006a279e46a4bd2e8e7cf6694)
+++ dcc.c	(revision 89c11e735164b7212d27bb64ff1a00ac50b9c746)
@@ -504,67 +504,35 @@
  * 
  */
-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 ) )
-	{
-		char *input = g_strdup( line );
+	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 *filename, *host, *port;
-		size_t filesize;
 		struct addrinfo hints, *rp;
-
-		/* "filename" or filename */
-		if ( pmatch[2].rm_so > 0 )
+		
+		filename = ctcp[2];
+		
+		host = ctcp[3];
+		while( *host && isdigit( *host ) ) host++; /* Just digits? */
+		if( *host == '\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 )
-		{
-			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 ) );
@@ -574,5 +542,4 @@
 		if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) )
 		{
-			g_free( input );
 			imcb_log( ic, "DCC: getaddrinfo() failed with %s "
 				  "when parsing incoming 'DCC SEND': "
@@ -588,5 +555,4 @@
 
 		freeaddrinfo( rp );
-		g_free( input );
 
 		irc->file_transfers = g_slist_prepend( irc->file_transfers, ft );
@@ -594,6 +560,6 @@
 		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;
Index: dcc.h
===================================================================
--- dcc.h	(revision 24b8bbb2616d685006a279e46a4bd2e8e7cf6694)
+++ dcc.h	(revision 89c11e735164b7212d27bb64ff1a00ac50b9c746)
@@ -98,5 +98,5 @@
 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 );
Index: irc_im.c
===================================================================
--- irc_im.c	(revision 24b8bbb2616d685006a279e46a4bd2e8e7cf6694)
+++ irc_im.c	(revision 89c11e735164b7212d27bb64ff1a00ac50b9c746)
@@ -211,5 +211,24 @@
 }
 
+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,
 };
Index: lib/misc.c
===================================================================
--- lib/misc.c	(revision 24b8bbb2616d685006a279e46a4bd2e8e7cf6694)
+++ lib/misc.c	(revision 89c11e735164b7212d27bb64ff1a00ac50b9c746)
@@ -655,5 +655,8 @@
 			q = *s = 0;
 		}
-	cmd[k] = NULL;
+	
+	/* Full zero-padding for easier argc checking. */
+	while( k <= IRC_MAX_ARGS )
+		cmd[k++] = NULL;
 	
 	return cmd;
