diff options
Diffstat (limited to 'nick.c')
-rw-r--r-- | nick.c | 181 |
1 files changed, 101 insertions, 80 deletions
@@ -111,14 +111,15 @@ char *nick_get( bee_user_t *bu ) char *nick_gen( bee_user_t *bu ) { gboolean ok = FALSE; /* Set to true once the nick contains something unique. */ - GString *ret = g_string_new( "" ); + GString *ret = g_string_sized_new( MAX_NICK_LENGTH + 1 ); + char *rets; + irc_t *irc = (irc_t *) bu->bee->ui_data; char *fmt = set_getstr( &bu->ic->acc->set, "nick_format" ) ? : set_getstr( &bu->bee->set, "nick_format" ); while( fmt && *fmt && ret->len < MAX_NICK_LENGTH ) { char *part = NULL, chop = '\0', *asc = NULL; - int len = MAX_NICK_LENGTH; if( *fmt != '%' ) { @@ -141,13 +142,6 @@ char *nick_gen( bee_user_t *bu ) } fmt += 2; } - else if( isdigit( *fmt ) ) - { - len = 0; - /* Grab a number. */ - while( isdigit( *fmt ) ) - len = len * 10 + ( *(fmt++) - '0' ); - } else if( g_strncasecmp( fmt, "nick", 4 ) == 0 ) { part = bu->nick ? : bu->handle; @@ -196,31 +190,31 @@ char *nick_gen( bee_user_t *bu ) } } + if( !part ) + continue; + /* Credits to Josay_ in #bitlbee for this idea. //TRANSLIT should do lossy/approximate conversions, so letters with accents don't just get stripped. Note that it depends on LC_CTYPE being set to something other than C/POSIX. */ - if( part ) + if( !( irc && irc->status & IRC_UTF8_NICKS ) ) part = asc = g_convert_with_fallback( part, -1, "ASCII//TRANSLIT", "UTF-8", "", NULL, NULL, NULL ); - if( ret->len == 0 && part && isdigit( *part ) ) - g_string_append_c( ret, '_' ); - - while( part && *part && *part != chop && len > 0 ) - { - if( strchr( nick_lc_chars, *part ) || - strchr( nick_uc_chars, *part ) ) - g_string_append_c( ret, *part ); - - part ++; - len --; - } + if( part ) + g_string_append( ret, part ); g_free( asc ); } - /* This returns NULL if the nick is empty or otherwise not ok. */ - return g_string_free( ret, ret->len == 0 || !ok ); + rets = g_string_free( ret, FALSE ); + if( ok && rets && *rets ) + { + nick_strip( irc, rets ); + rets[MAX_NICK_LENGTH] = '\0'; + return rets; + } + g_free( rets ); + return NULL; } void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] ) @@ -246,24 +240,15 @@ void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] ) if( inf_protection-- == 0 ) { - int i; - - irc_rootmsg( irc, "Warning: Almost had an infinite loop in nick_get()! " - "This used to be a fatal BitlBee bug, but we tried to fix it. " - "This message should *never* appear anymore. " - "If it does, please *do* send us a bug report! " - "Please send all the following lines in your report:" ); - - irc_rootmsg( irc, "Trying to get a sane nick for handle %s", bu->handle ); - for( i = 0; i < MAX_NICK_LENGTH; i ++ ) - irc_rootmsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); - - irc_rootmsg( irc, "FAILED. Returning an insane nick now. Things might break. " - "Good luck, and please don't forget to paste the lines up here " - "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); - g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); + irc_rootmsg( irc, "Warning: Something went wrong while trying " + "to generate a nickname for contact %s on %s.", + bu->handle, bu->ic->acc->tag ); + irc_rootmsg( irc, "This might be a bug in BitlBee, or the result " + "of a faulty nick_format setting. Will use %s " + "instead.", nick ); + break; } } @@ -290,43 +275,95 @@ void nick_del( bee_user_t *bu ) void nick_strip( irc_t *irc, char *nick ) { - int i, j; + int len = 0; - for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ ) + if( irc && ( irc->status & IRC_UTF8_NICKS ) ) { - if( strchr( nick_lc_chars, nick[i] ) || - strchr( nick_uc_chars, nick[i] ) ) + gunichar c; + char *p = nick, *n, tmp[strlen(nick)+1]; + + while( p && *p ) { - nick[j] = nick[i]; - j++; + c = g_utf8_get_char_validated( p, -1 ); + n = g_utf8_find_next_char( p, NULL ); + + if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || + strchr( nick_uc_chars, c ) ) ) || + !g_unichar_isgraph( c ) ) + { + strcpy( tmp, n ); + strcpy( p, tmp ); + } + else + p = n; + } + if( p ) + len = p - nick; + } + else + { + int i; + + for( i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++ ) + { + if( strchr( nick_lc_chars, nick[i] ) || + strchr( nick_uc_chars, nick[i] ) ) + { + nick[len] = nick[i]; + len++; + } } } if( isdigit( nick[0] ) ) { char *orig; + /* First character of a nick can't be a digit, so insert an + underscore if necessary. */ orig = g_strdup( nick ); g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig ); g_free( orig ); - j ++; + len ++; } - while( j <= MAX_NICK_LENGTH ) - nick[j++] = '\0'; + while( len <= MAX_NICK_LENGTH ) + nick[len++] = '\0'; } -int nick_ok( irc_t *irc, const char *nick ) +gboolean nick_ok( irc_t *irc, const char *nick ) { const char *s; /* Empty/long nicks are not allowed, nor numbers at [0] */ if( !*nick || isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH ) - return( 0 ); + return 0; - for( s = nick; *s; s ++ ) - if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) ) - return( 0 ); + if( irc && ( irc->status & IRC_UTF8_NICKS ) ) + { + gunichar c; + const char *p = nick, *n; + + while( p && *p ) + { + c = g_utf8_get_char_validated( p, -1 ); + n = g_utf8_find_next_char( p, NULL ); + + if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || + strchr( nick_uc_chars, c ) ) ) || + !g_unichar_isgraph( c ) ) + { + return FALSE; + } + p = n; + } + } + else + { + for( s = nick; *s; s ++ ) + if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) ) + return FALSE; + } - return( 1 ); + return TRUE; } int nick_lc( irc_t *irc, char *nick ) @@ -341,38 +378,22 @@ int nick_lc( irc_t *irc, char *nick ) tab[(int)nick_lc_chars[i]] = nick_lc_chars[i]; } - for( i = 0; nick[i]; i ++ ) + if( irc && ( irc->status & IRC_UTF8_NICKS ) ) { - if( !tab[(int)nick[i]] ) - return( 0 ); - - nick[i] = tab[(int)nick[i]]; - } - - return( 1 ); -} - -int nick_uc( irc_t *irc, char *nick ) -{ - static char tab[128] = { 0 }; - int i; - - if( tab['A'] == 0 ) - for( i = 0; nick_lc_chars[i]; i ++ ) + gchar *down = g_utf8_strdown( nick, -1 ); + if( strlen( down ) > strlen( nick ) ) { - tab[(int)nick_uc_chars[i]] = nick_uc_chars[i]; - tab[(int)nick_lc_chars[i]] = nick_uc_chars[i]; + /* Well crap. Corrupt it if we have to. */ + down[strlen(nick)] = '\0'; } + strcpy( nick, down ); + g_free( down ); + } for( i = 0; nick[i]; i ++ ) - { - if( !tab[(int)nick[i]] ) - return( 0 ); - nick[i] = tab[(int)nick[i]]; - } - return( 1 ); + return nick_ok( irc, nick ); } int nick_cmp( irc_t *irc, const char *a, const char *b ) |