Changeset 6b90431


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.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • irc.h

    re5b521d r6b90431  
    231231void irc_channel_printf( irc_channel_t *ic, char *format, ... );
    232232gboolean irc_channel_name_ok( const char *name );
     233int irc_channel_name_cmp( const char *a_, const char *b_ );
    233234void irc_channel_update_ops( irc_channel_t *ic, char *value );
    234235char *set_eval_irc_channel_ops( struct set *set, char *value );
  • 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
  • irc_commands.c

    re5b521d r6b90431  
    314314                irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
    315315        }
    316 
    317 
    318 #if 0
    319         else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    320         {
    321         }
    322         else
    323         {
    324                 if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    325                 {
    326                         unsigned int i;
    327                         char *t = set_getstr( &irc->set, "default_target" );
    328                        
    329                         if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
    330                                 cmd[1] = irc->last_target;
    331                         else if( g_strcasecmp( t, "root" ) == 0 )
    332                                 cmd[1] = irc->mynick;
    333                        
    334                         for( i = 0; i < strlen( cmd[2] ); i ++ )
    335                         {
    336                                 if( cmd[2][i] == ' ' ) break;
    337                                 if( cmd[2][i] == ':' || cmd[2][i] == ',' )
    338                                 {
    339                                         cmd[1] = cmd[2];
    340                                         cmd[2] += i;
    341                                         *cmd[2] = 0;
    342                                         while( *(++cmd[2]) == ' ' );
    343                                         break;
    344                                 }
    345                         }
    346                        
    347                         irc->is_private = 0;
    348                        
    349                         if( cmd[1] != irc->last_target )
    350                         {
    351                                 g_free( irc->last_target );
    352                                 irc->last_target = g_strdup( cmd[1] );
    353                         }
    354                 }
    355                 else
    356                 {
    357                         irc->is_private = 1;
    358                 }
    359                 irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
    360         }
    361 #endif
    362316}
    363317
Note: See TracChangeset for help on using the changeset viewer.