diff options
| -rw-r--r-- | irc.c | 102 | ||||
| -rw-r--r-- | irc.h | 1 | ||||
| -rw-r--r-- | irc_commands.c | 3 | ||||
| -rw-r--r-- | set.c | 15 | ||||
| -rw-r--r-- | set.h | 1 | 
5 files changed, 81 insertions, 41 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 )  	{ @@ -60,6 +60,7 @@ typedef struct irc  	int pinging;  	char *sendbuffer;  	char *readbuffer; +	GIConv iconv, oconv;  	int sentbytes;  	time_t oldtime; diff --git a/irc_commands.c b/irc_commands.c index 61517614..6a47007a 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -277,8 +277,7 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd )  			if( cmd[1] != irc->last_target )  			{ -				if( irc->last_target ) -					g_free( irc->last_target ); +				g_free( irc->last_target );  				irc->last_target = g_strdup( cmd[1] );  			}  		} @@ -229,18 +229,3 @@ char *set_eval_ops( set_t *set, char *value )  	return value;  } - -char *set_eval_charset( set_t *set, char *value ) -{ -	GIConv cd; - -	if( g_strcasecmp( value, "none" ) == 0 ) -		return value; - -	cd = g_iconv_open( "UTF-8", value ); -	if( cd == (GIConv) -1 ) -		return NULL; - -	g_iconv_close( cd ); -	return value; -} @@ -96,6 +96,5 @@ char *set_eval_bool( set_t *set, char *value );  /* Some not very generic evaluators that really shouldn't be here... */  char *set_eval_to_char( set_t *set, char *value );  char *set_eval_ops( set_t *set, char *value ); -char *set_eval_charset( set_t *set, char *value );  #endif /* __SET_H__ */ | 
