diff options
Diffstat (limited to 'irc.c')
| -rw-r--r-- | irc.c | 102 | 
1 files changed, 79 insertions, 23 deletions
| @@ -41,6 +41,35 @@ static char *passchange( set_t *set, char *value )  	return NULL;  } +static char *set_eval_charset( set_t *set, char *value ) +{ +	irc_t *irc = set->data; +	GIConv ic, oc; + +	if( g_strcasecmp( value, "none" ) == 0 ) +		value = g_strdup( "utf-8" ); + +	if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) +	{ +		return NULL; +	} +	if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) +	{ +		g_iconv_close( ic ); +		return NULL; +	} +	 +	if( irc->iconv != (GIConv) -1 ) +		g_iconv_close( irc->iconv ); +	if( irc->oconv != (GIConv) -1 ) +		g_iconv_close( irc->oconv ); +	 +	irc->iconv = ic; +	irc->oconv = oc; + +	return value; +} +  irc_t *irc_new( int fd )  {  	irc_t *irc; @@ -64,6 +93,9 @@ irc_t *irc_new( int fd )  	irc->mynick = g_strdup( ROOT_NICK );  	irc->channel = g_strdup( ROOT_CHAN ); +	irc->iconv = (GIConv) -1; +	irc->oconv = (GIConv) -1; +	  	if( global.conf->hostname )  	{  		irc->myhost = g_strdup( global.conf->hostname ); @@ -126,6 +158,9 @@ irc_t *irc_new( int fd )  	conf_loaddefaults( irc ); +	/* Evaluator sets the iconv/oconv structures. */ +	set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); +	  	return( irc );  } @@ -264,6 +299,13 @@ void irc_free(irc_t * irc)  	g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);  	g_hash_table_destroy(irc->watches); +	if( irc->iconv != (GIConv) -1 ) +		g_iconv_close( irc->iconv ); +	if( irc->oconv != (GIConv) -1 ) +		g_iconv_close( irc->oconv ); +	 +	g_free( irc->last_target ); +	  	g_free(irc);  	if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -285,7 +327,7 @@ void irc_setpass (irc_t *irc, const char *pass)  void irc_process( irc_t *irc )  { -	char **lines, *temp, **cmd, *cs; +	char **lines, *temp, **cmd;  	int i;  	if( irc->readbuffer != NULL ) @@ -294,7 +336,7 @@ void irc_process( irc_t *irc )  		for( i = 0; *lines[i] != '\0'; i ++ )  		{ -			char conv[IRC_MAX_LINE+1]; +			char *conv = NULL;  			/* [WvG] If the last line isn't empty, it's an incomplete line and we  			   should wait for the rest to come in before processing it. */ @@ -307,10 +349,14 @@ void irc_process( irc_t *irc )  				break;  			} -			if( ( cs = set_getstr( &irc->set, "charset" ) ) && g_strcasecmp( cs, "none" ) != 0 ) +			if( irc->iconv != (GIConv) -1 )  			{ -				conv[IRC_MAX_LINE] = 0; -				if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) +				gsize bytes_read, bytes_written; +				 +				conv = g_convert_with_iconv( lines[i], -1, irc->iconv, +				                             &bytes_read, &bytes_written, NULL ); +				 +				if( conv == NULL || bytes_read != strlen( lines[i] ) )  				{  					/* GLib can do strange things if things are not in the expected charset,  					   so let's be a little bit paranoid here: */ @@ -322,15 +368,18 @@ void irc_process( irc_t *irc )  						                  "that charset, or tell BitlBee which charset to "  						                  "expect by changing the charset setting. See "  						                  "`help set charset' for more information. Your " -						                  "message was ignored.", cs ); -						*conv = 0; +						                  "message was ignored.", +						                  set_getstr( &irc->set, "charset" ) ); +						 +						g_free( conv ); +						conv = NULL;  					}  					else  					{  						irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,  						           "Warning: invalid characters received at login time." ); -						strncpy( conv, lines[i], IRC_MAX_LINE ); +						conv = g_strdup( lines[i] );  						for( temp = conv; *temp; temp ++ )  							if( *temp & 0x80 )  								*temp = '?'; @@ -339,11 +388,15 @@ void irc_process( irc_t *irc )  				lines[i] = conv;  			} -			if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) -				continue; -			irc_exec( irc, cmd ); +			if( lines[i] ) +			{ +				if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) +					continue; +				irc_exec( irc, cmd ); +				g_free( cmd ); +			} -			g_free( cmd ); +			g_free( conv );  			/* Shouldn't really happen, but just in case... */  			if( !g_slist_find( irc_connection_list, irc ) ) @@ -535,32 +588,35 @@ void irc_write( irc_t *irc, char *format, ... )  	va_end( params );  	return; -  }  void irc_vawrite( irc_t *irc, char *format, va_list params )  {  	int size; -	char line[IRC_MAX_LINE+1], *cs; +	char line[IRC_MAX_LINE+1];  	/* Don't try to write anything new anymore when shutting down. */  	if( irc->status & USTATUS_SHUTDOWN )  		return; -	line[IRC_MAX_LINE] = 0; +	memset( line, 0, sizeof( line ) );  	g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); -	  	strip_newlines( line ); -	if( ( cs = set_getstr( &irc->set, "charset" ) ) && -	    g_strcasecmp( cs, "none" ) != 0 && g_strcasecmp( cs, "utf-8" ) != 0 ) +	 +	if( irc->oconv != (GIConv) -1 )  	{ -		char conv[IRC_MAX_LINE+1]; +		gsize bytes_read, bytes_written; +		char *conv; +		 +		conv = g_convert_with_iconv( line, -1, irc->oconv, +		                             &bytes_read, &bytes_written, NULL ); + +		if( bytes_read == strlen( line ) ) +			strncpy( line, conv, IRC_MAX_LINE - 2 ); -		conv[IRC_MAX_LINE] = 0; -		if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 ) -			strcpy( line, conv ); +		g_free( conv );  	} -	strcat( line, "\r\n" ); +	g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );  	if( irc->sendbuffer != NULL )  	{ | 
