Changeset 1a2c1c0 for nick.c


Ignore:
Timestamp:
2013-06-16T12:42:39Z (11 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
2f9027c
Parents:
ab19567 (diff), 5cb9461 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging utf8-nicks branch. This adds a utf8_nicks setting which removes the
ASCII restriction on contact nicknames. Use at your own risk!

File:
1 edited

Legend:

Unmodified
Added
Removed
  • nick.c

    rab19567 r1a2c1c0  
    5151{
    5252        char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 );
     53        irc_t *irc = (irc_t *) acc->bee->ui_data;
    5354       
    5455        store_handle = clean_handle( handle );
    5556        store_nick[MAX_NICK_LENGTH] = '\0';
    5657        strncpy( store_nick, nick, MAX_NICK_LENGTH );
    57         nick_strip( store_nick );
     58        nick_strip( irc, store_nick );
    5859       
    5960        g_hash_table_replace( acc->nicks, store_handle, store_nick );
     
    6970        static char nick[MAX_NICK_LENGTH+1];
    7071        char *store_handle, *found_nick;
     72        irc_t *irc = (irc_t *) bu->bee->ui_data;
    7173       
    7274        memset( nick, 0, MAX_NICK_LENGTH + 1 );
     
    9496                                *(s++) = 0;
    9597               
    96                 nick_strip( nick );
     98                nick_strip( irc, nick );
    9799                if( set_getbool( &bu->bee->set, "lcnicks" ) )
    98                         nick_lc( nick );
     100                        nick_lc( irc, nick );
    99101        }
    100102        g_free( store_handle );
     
    110112{
    111113        gboolean ok = FALSE; /* Set to true once the nick contains something unique. */
    112         GString *ret = g_string_new( "" );
     114        GString *ret = g_string_sized_new( MAX_NICK_LENGTH + 1 );
     115        char *rets;
     116        irc_t *irc = (irc_t *) bu->bee->ui_data;
    113117        char *fmt = set_getstr( &bu->ic->acc->set, "nick_format" ) ? :
    114118                    set_getstr( &bu->bee->set, "nick_format" );
     
    117121        {
    118122                char *part = NULL, chop = '\0', *asc = NULL;
    119                 int len = MAX_NICK_LENGTH;
    120123               
    121124                if( *fmt != '%' )
     
    140143                                fmt += 2;
    141144                        }
    142                         else if( isdigit( *fmt ) )
    143                         {
    144                                 len = 0;
    145                                 /* Grab a number. */
    146                                 while( isdigit( *fmt ) )
    147                                         len = len * 10 + ( *(fmt++) - '0' );
    148                         }
    149145                        else if( g_strncasecmp( fmt, "nick", 4 ) == 0 )
    150146                        {
     
    195191                }
    196192               
     193                if( !part )
     194                        continue;
     195               
    197196                /* Credits to Josay_ in #bitlbee for this idea. //TRANSLIT
    198197                   should do lossy/approximate conversions, so letters with
    199198                   accents don't just get stripped. Note that it depends on
    200199                   LC_CTYPE being set to something other than C/POSIX. */
    201                 if( part )
     200                if( !( irc && irc->status & IRC_UTF8_NICKS ) )
    202201                        part = asc = g_convert_with_fallback( part, -1, "ASCII//TRANSLIT",
    203202                                                              "UTF-8", "", NULL, NULL, NULL );
    204203               
    205                 if( ret->len == 0 && part && isdigit( *part ) )
    206                         g_string_append_c( ret, '_' );
    207                
    208                 while( part && *part && *part != chop && len > 0 )
    209                 {
    210                         if( strchr( nick_lc_chars, *part ) ||
    211                             strchr( nick_uc_chars, *part ) )
    212                                 g_string_append_c( ret, *part );
    213                        
    214                         part ++;
    215                         len --;
    216                 }
     204                if( part )
     205                        g_string_append( ret, part );
    217206                g_free( asc );
    218207        }
    219208       
    220         /* This returns NULL if the nick is empty or otherwise not ok. */
    221         return g_string_free( ret, ret->len == 0 || !ok );
     209        rets = g_string_free( ret, FALSE );
     210        if( ok && rets && *rets )
     211        {
     212                nick_strip( irc, rets );
     213                rets[MAX_NICK_LENGTH] = '\0';
     214                return rets;
     215        }
     216        g_free( rets );
     217        return NULL;
    222218}
    223219
     
    230226        /* Now, find out if the nick is already in use at the moment, and make
    231227           subtle changes to make it unique. */
    232         while( !nick_ok( nick ) ||
     228        while( !nick_ok( irc, nick ) ||
    233229               ( ( iu = irc_user_by_name( irc, nick ) ) && iu->bu != bu ) )
    234230        {
     
    245241                if( inf_protection-- == 0 )
    246242                {
    247                         int i;
     243                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
    248244                       
    249                         irc_rootmsg( irc, "Warning: Almost had an infinite loop in nick_get()! "
    250                                           "This used to be a fatal BitlBee bug, but we tried to fix it. "
    251                                           "This message should *never* appear anymore. "
    252                                           "If it does, please *do* send us a bug report! "
    253                                           "Please send all the following lines in your report:" );
    254                        
    255                         irc_rootmsg( irc, "Trying to get a sane nick for handle %s", bu->handle );
    256                         for( i = 0; i < MAX_NICK_LENGTH; i ++ )
    257                                 irc_rootmsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] );
    258                        
    259                         irc_rootmsg( irc, "FAILED. Returning an insane nick now. Things might break. "
    260                                           "Good luck, and please don't forget to paste the lines up here "
    261                                           "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
    262                        
    263                         g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
     245                        irc_rootmsg( irc, "Warning: Something went wrong while trying "
     246                                          "to generate a nickname for contact %s on %s.",
     247                                          bu->handle, bu->ic->acc->tag );
     248                        irc_rootmsg( irc, "This might be a bug in BitlBee, or the result "
     249                                          "of a faulty nick_format setting. Will use %s "
     250                                          "instead.", nick );
    264251                       
    265252                        break;
     
    287274
    288275
    289 void nick_strip( char *nick )
    290 {
    291         int i, j;
    292        
    293         for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ )
    294         {
    295                 if( strchr( nick_lc_chars, nick[i] ) ||
    296                     strchr( nick_uc_chars, nick[i] ) )
    297                 {
    298                         nick[j] = nick[i];
    299                         j++;
     276void nick_strip( irc_t *irc, char *nick )
     277{
     278        int len = 0;
     279       
     280        if( irc && ( irc->status & IRC_UTF8_NICKS ) )
     281        {
     282                gunichar c;
     283                char *p = nick, *n, tmp[strlen(nick)+1];
     284               
     285                while( p && *p )
     286                {
     287                        c = g_utf8_get_char_validated( p, -1 );
     288                        n = g_utf8_find_next_char( p, NULL );
     289                       
     290                        if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) ||
     291                                             strchr( nick_uc_chars, c ) ) ) ||
     292                            !g_unichar_isgraph( c ) )
     293                        {
     294                                strcpy( tmp, n );
     295                                strcpy( p, tmp );
     296                        }
     297                        else
     298                                p = n;
     299                }
     300                if( p )
     301                        len = p - nick;
     302        }
     303        else
     304        {
     305                int i;
     306               
     307                for( i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++ )
     308                {
     309                        if( strchr( nick_lc_chars, nick[i] ) ||
     310                            strchr( nick_uc_chars, nick[i] ) )
     311                        {
     312                                nick[len] = nick[i];
     313                                len++;
     314                        }
    300315                }
    301316        }
     
    304319                char *orig;
    305320               
     321                /* First character of a nick can't be a digit, so insert an
     322                   underscore if necessary. */
    306323                orig = g_strdup( nick );
    307324                g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig );
    308325                g_free( orig );
    309                 j ++;
    310         }
    311         while( j <= MAX_NICK_LENGTH )
    312                 nick[j++] = '\0';
    313 }
    314 
    315 int nick_ok( const char *nick )
     326                len ++;
     327        }
     328        while( len <= MAX_NICK_LENGTH )
     329                nick[len++] = '\0';
     330}
     331
     332gboolean nick_ok( irc_t *irc, const char *nick )
    316333{
    317334        const char *s;
     
    319336        /* Empty/long nicks are not allowed, nor numbers at [0] */
    320337        if( !*nick || isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH )
    321                 return( 0 );
    322        
    323         for( s = nick; *s; s ++ )
    324                 if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) )
    325                         return( 0 );
    326        
    327         return( 1 );
    328 }
    329 
    330 int nick_lc( char *nick )
     338                return 0;
     339       
     340        if( irc && ( irc->status & IRC_UTF8_NICKS ) )
     341        {
     342                gunichar c;
     343                const char *p = nick, *n;
     344               
     345                while( p && *p )
     346                {
     347                        c = g_utf8_get_char_validated( p, -1 );
     348                        n = g_utf8_find_next_char( p, NULL );
     349                       
     350                        if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) ||
     351                                             strchr( nick_uc_chars, c ) ) ) ||
     352                            !g_unichar_isgraph( c ) )
     353                        {
     354                                return FALSE;
     355                        }
     356                        p = n;
     357                }
     358        }
     359        else
     360        {
     361                for( s = nick; *s; s ++ )
     362                        if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) )
     363                                return FALSE;
     364        }
     365       
     366        return TRUE;
     367}
     368
     369int nick_lc( irc_t *irc, char *nick )
    331370{
    332371        static char tab[128] = { 0 };
     
    340379                }
    341380       
     381        if( irc && ( irc->status & IRC_UTF8_NICKS ) )
     382        {
     383                gchar *down = g_utf8_strdown( nick, -1 );
     384                if( strlen( down ) > strlen( nick ) )
     385                {
     386                        /* Well crap. Corrupt it if we have to. */
     387                        down[strlen(nick)] = '\0';
     388                }
     389                strcpy( nick, down );
     390                g_free( down );
     391        }
     392       
    342393        for( i = 0; nick[i]; i ++ )
    343         {
    344                 if( !tab[(int)nick[i]] )
    345                         return( 0 );
    346                
    347                 nick[i] = tab[(int)nick[i]];
    348         }
    349        
    350         return( 1 );
    351 }
    352 
    353 int nick_uc( char *nick )
    354 {
    355         static char tab[128] = { 0 };
    356         int i;
    357        
    358         if( tab['A'] == 0 )
    359                 for( i = 0; nick_lc_chars[i]; i ++ )
    360                 {
    361                         tab[(int)nick_uc_chars[i]] = nick_uc_chars[i];
    362                         tab[(int)nick_lc_chars[i]] = nick_uc_chars[i];
    363                 }
    364        
    365         for( i = 0; nick[i]; i ++ )
    366         {
    367                 if( !tab[(int)nick[i]] )
    368                         return( 0 );
    369                
    370                 nick[i] = tab[(int)nick[i]];
    371         }
    372        
    373         return( 1 );
    374 }
    375 
    376 int nick_cmp( const char *a, const char *b )
     394                if( nick[i] < 0x7f )
     395                        nick[i] = tab[(int)nick[i]];
     396       
     397        return nick_ok( irc, nick );
     398}
     399
     400int nick_cmp( irc_t *irc, const char *a, const char *b )
    377401{
    378402        char aa[1024] = "", bb[1024] = "";
     
    380404        strncpy( aa, a, sizeof( aa ) - 1 );
    381405        strncpy( bb, b, sizeof( bb ) - 1 );
    382         if( nick_lc( aa ) && nick_lc( bb ) )
     406        if( nick_lc( irc, aa ) && nick_lc( irc, bb ) )
    383407        {
    384408                return( strcmp( aa, bb ) );
     
    389413        }
    390414}
    391 
    392 char *nick_dup( const char *nick )
    393 {
    394         return g_strndup( nick, MAX_NICK_LENGTH );
    395 }
Note: See TracChangeset for help on using the changeset viewer.