aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordequis <dx@dxzone.com.ar>2015-01-16 16:50:25 -0300
committerdequis <dx@dxzone.com.ar>2015-01-16 16:50:25 -0300
commitfed4f766c05e44e99917909b266c99c052ed9c3e (patch)
treeca0f96eba21d6fd019b40a6f2d2af8f0d0ebecb9
parent4cff28fdfca2eaf71a13715b0fda114796091065 (diff)
Fix UTF8 nick truncation issues
When nicks exceeded the length limit, they were cut at 24 bytes and that sometimes left invalid utf8 at the end, which made the nick_ok() validation fail and often broke those nicks completely. This adds a truncate_utf8 function to cut the string at a safe place Also, the method to deduplicate nicks when there's no more place to add underscores was changed to add "_XX" at the end, where XX are two random hex chars. The previous method in those cases was increasing the value of the first character of the nick... which leads to silly and confusing results (i.e. FacebookUser -> GacebookUser)
-rw-r--r--lib/misc.c9
-rw-r--r--lib/misc.h1
-rw-r--r--nick.c12
3 files changed, 18 insertions, 4 deletions
diff --git a/lib/misc.c b/lib/misc.c
index 02b1814c..6fedb48f 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -779,3 +779,12 @@ char *get_rfc822_header( const char *text, const char *header, int len )
return NULL;
}
+
+/* Takes a string, truncates it where it's safe, returns the new length */
+int truncate_utf8( char *string, int maxlen )
+{
+ char *end;
+ g_utf8_validate( (const gchar *) string, maxlen, (const gchar **) &end );
+ *end = '\0';
+ return end - string;
+}
diff --git a/lib/misc.h b/lib/misc.h
index d8cce32b..bf587332 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -149,5 +149,6 @@ G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl );
G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
G_MODULE_EXPORT char **split_command_parts( char *command, int limit );
G_MODULE_EXPORT char *get_rfc822_header( const char *text, const char *header, int len );
+G_MODULE_EXPORT int truncate_utf8( char *string, int maxlen );
#endif
diff --git a/nick.c b/nick.c
index 63140042..2c3f9a66 100644
--- a/nick.c
+++ b/nick.c
@@ -226,7 +226,7 @@ char *nick_gen( bee_user_t *bu )
if( ok && rets && *rets )
{
nick_strip( irc, rets );
- rets[MAX_NICK_LENGTH] = '\0';
+ truncate_utf8( rets, MAX_NICK_LENGTH );
return rets;
}
g_free( rets );
@@ -251,7 +251,12 @@ void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] )
}
else
{
- nick[0] ++;
+ /* We've got no more space for underscores,
+ so truncate it and replace the last three
+ chars with a random "_XX" suffix */
+ int len = truncate_utf8( nick, MAX_NICK_LENGTH - 3 );
+ nick[len] = '_';
+ g_snprintf(nick + len + 1, 3, "%2x", rand() );
}
if( inf_protection-- == 0 )
@@ -399,8 +404,7 @@ int nick_lc( irc_t *irc, char *nick )
gchar *down = g_utf8_strdown( nick, -1 );
if( strlen( down ) > strlen( nick ) )
{
- /* Well crap. Corrupt it if we have to. */
- down[strlen(nick)] = '\0';
+ truncate_utf8( down, strlen(nick) );
}
strcpy( nick, down );
g_free( down );