diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-06-16 10:31:40 +0200 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-06-16 10:31:40 +0200 |
commit | 6b90431eba3820aaa5535523622ba45ca65055f4 (patch) | |
tree | 434c10fe6c17b47ad16acc8ce1d97c25d66cb5cb /irc_channel.c | |
parent | e5b521d07dbe197c2dd7552f0036bdcac2116cde (diff) |
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.
Diffstat (limited to 'irc_channel.c')
-rw-r--r-- | irc_channel.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/irc_channel.c b/irc_channel.c index 54e68577..133a6de9 100644 --- a/irc_channel.c +++ b/irc_channel.c @@ -65,7 +65,7 @@ irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ) { irc_channel_t *ic = l->data; - if( g_strcasecmp( name, ic->name ) == 0 ) + if( irc_channel_name_cmp( name, ic->name ) == 0 ) return ic; } @@ -266,20 +266,59 @@ void irc_channel_printf( irc_channel_t *ic, char *format, ... ) g_free( text ); } -gboolean irc_channel_name_ok( const char *name ) +gboolean irc_channel_name_ok( const char *name_ ) { - char name_[strlen(name)+1]; + const unsigned char *name = (unsigned char*) name_; + int i; /* Check if the first character is in CTYPES (#&) */ - if( strchr( CTYPES, name[0] ) == NULL ) + if( strchr( CTYPES, name_[0] ) == NULL ) return FALSE; - /* Check the rest of the name. Just checking name + 1 doesn't work - since it will fail if the first character is a number, or if - it's a one-char channel name - both of which are legal. */ - name_[0] = '_'; - strcpy( name_ + 1, name + 1 ); - return nick_ok( name_ ); + /* RFC 1459 keeps amazing me: While only a "few" chars are allowed + in nicknames, channel names can be pretty much anything as long + as they start with # or &. I'll be a little bit more strict and + disallow all non-printable characters. */ + for( i = 1; name[i]; i ++ ) + if( name[i] <= ' ' || name[i] == ',' ) + return FALSE; + + return TRUE; +} + +int irc_channel_name_cmp( const char *a_, const char *b_ ) +{ + static unsigned char case_map[256]; + const unsigned char *a = (unsigned char*) a_, *b = (unsigned char*) b_; + int i; + + if( case_map['A'] == '\0' ) + { + for( i = 33; i < 256; i ++ ) + if( i != ',' ) + case_map[i] = i; + + for( i = 0; i < 26; i ++ ) + case_map['A'+i] = 'a' + i; + + case_map['['] = '{'; + case_map[']'] = '}'; + case_map['~'] = '`'; + case_map['\\'] = '|'; + } + + if( !irc_channel_name_ok( a_ ) || !irc_channel_name_ok( b_ ) ) + return -1; + + for( i = 0; a[i] && b[i] && case_map[a[i]] && case_map[b[i]]; i ++ ) + { + if( case_map[a[i]] == case_map[b[i]] ) + continue; + else + return case_map[a[i]] - case_map[b[i]]; + } + + return case_map[a[i]] - case_map[b[i]]; } static gint irc_channel_user_cmp( gconstpointer a_, gconstpointer b_ ) |