Changeset 6b90431 for irc_channel.c


Ignore:
Timestamp:
2010-06-16T08:31:40Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
7cd2e8a
Parents:
e5b521d
Message:

More correct handling of channel names (according to RFC 1459). Pretty
much any 8-bit character is allowed in there - while nicknames are very
restricted.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • irc_channel.c

    re5b521d r6b90431  
    6666                irc_channel_t *ic = l->data;
    6767               
    68                 if( g_strcasecmp( name, ic->name ) == 0 )
     68                if( irc_channel_name_cmp( name, ic->name ) == 0 )
    6969                        return ic;
    7070        }
     
    267267}
    268268
    269 gboolean irc_channel_name_ok( const char *name )
    270 {
    271         char name_[strlen(name)+1];
     269gboolean irc_channel_name_ok( const char *name_ )
     270{
     271        const unsigned char *name = (unsigned char*) name_;
     272        int i;
    272273       
    273274        /* Check if the first character is in CTYPES (#&) */
    274         if( strchr( CTYPES, name[0] ) == NULL )
     275        if( strchr( CTYPES, name_[0] ) == NULL )
    275276                return FALSE;
    276277       
    277         /* Check the rest of the name. Just checking name + 1 doesn't work
    278            since it will fail if the first character is a number, or if
    279            it's a one-char channel name - both of which are legal. */
    280         name_[0] = '_';
    281         strcpy( name_ + 1, name + 1 );
    282         return nick_ok( name_ );
     278        /* RFC 1459 keeps amazing me: While only a "few" chars are allowed
     279           in nicknames, channel names can be pretty much anything as long
     280           as they start with # or &. I'll be a little bit more strict and
     281           disallow all non-printable characters. */
     282        for( i = 1; name[i]; i ++ )
     283                if( name[i] <= ' ' || name[i] == ',' )
     284                        return FALSE;
     285       
     286        return TRUE;
     287}
     288
     289int irc_channel_name_cmp( const char *a_, const char *b_ )
     290{
     291        static unsigned char case_map[256];
     292        const unsigned char *a = (unsigned char*) a_, *b = (unsigned char*) b_;
     293        int i;
     294       
     295        if( case_map['A'] == '\0' )
     296        {
     297                for( i = 33; i < 256; i ++ )
     298                        if( i != ',' )
     299                                case_map[i] = i;
     300               
     301                for( i = 0; i < 26; i ++ )
     302                        case_map['A'+i] = 'a' + i;
     303               
     304                case_map['['] = '{';
     305                case_map[']'] = '}';
     306                case_map['~'] = '`';
     307                case_map['\\'] = '|';
     308        }
     309       
     310        if( !irc_channel_name_ok( a_ ) || !irc_channel_name_ok( b_ ) )
     311                return -1;
     312       
     313        for( i = 0; a[i] && b[i] && case_map[a[i]] && case_map[b[i]]; i ++ )
     314        {
     315                if( case_map[a[i]] == case_map[b[i]] )
     316                        continue;
     317                else
     318                        return case_map[a[i]] - case_map[b[i]];
     319        }
     320       
     321        return case_map[a[i]] - case_map[b[i]];
    283322}
    284323
Note: See TracChangeset for help on using the changeset viewer.