diff -urN tiarra-20040401/ChangeLog tiarra-20040407/ChangeLog
--- tiarra-20040401/ChangeLog	2004-04-01 18:52:44.000000000 +0900
+++ tiarra-20040407/ChangeLog	2004-04-07 20:57:33.000000000 +0900
@@ -1,3 +1,33 @@
+2004-04-07  phonohawk  <phonohawk@ps.sakura.ne.jp>
+
+	* main/IrcIO/Server.pm (new):
+	$this->{channels}のキーを、小文字に変換しておく。
+	
+	大文字小文字に一貫性の無いチャンネル名をクライアントに送る、
+	EFnetやFreenet(IRC)のようなircdに接続していると、しばしば
+	Tiarraは混乱する。この問題を回避するため、チャンネル名同士の
+	比較は一旦小文字に変換した上で行うようにする。
+
+	(channel):
+	大文字小文字を無視してチャンネルを探索するように変更。
+	$server->channel($name)のようにしてChannelInfoを得ている
+	場合には、何ら変更は必要無い。
+	
+	チャンネル名 => ChannelInfoのハッシュを返す、$server->channels
+	を使っている場合は、そのキーが小文字に変換されている事に注意しなければ
+	ならない。
+
+	* main/Multicast.pm (lc, uc): 追加
+	IRC方式で大文字と小文字の変換を行う。IRC方式とは、[]\がそれぞれ{}|の
+	大文字であると定義されている方式である。
+	
+	* main/Mask.pm (compile): 追加
+	マスクからコンパイル済み正規表現を生成する部分を、独立した関数にした。
+	大量のマッチングを高速に行う場合は、Mask::の関数を何度も呼ぶ代わりに
+	マスクを一度だけコンパイルする事を考えた方が良い。
+	Mask.pm内でコンパイル済みマスクはキャッシュしているが、それでも速度は違う。
+
+
 2004-04-01  Topia  <topia@clovery.jp>
 
 	* module/Client/Cache.pm:
@@ -1537,7 +1567,7 @@
 
 	* これ以前のログは書いていません。
 
-#       Id: $Id: ChangeLog,v 1.143 2004/04/01 09:44:41 topia Exp $
-#   Author: $Author: topia $
-#     Date: $Date: 2004/04/01 09:44:41 $
-# Revision: $Revision: 1.143 $
+#       Id: $Id: ChangeLog,v 1.144 2004/04/07 11:49:58 admin Exp $
+#   Author: $Author: admin $
+#     Date: $Date: 2004/04/07 11:49:58 $
+# Revision: $Revision: 1.144 $
diff -urN tiarra-20040401/main/IrcIO/Server.pm tiarra-20040407/main/IrcIO/Server.pm
--- tiarra-20040401/main/IrcIO/Server.pm	2004-04-01 18:52:44.000000000 +0900
+++ tiarra-20040407/main/IrcIO/Server.pm	2004-04-07 20:57:33.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Server.pm,v 1.54 2004/03/07 10:34:19 topia Exp $
+# $Id: Server.pm,v 1.55 2004/04/07 11:49:57 admin Exp $
 # -----------------------------------------------------------------------------
 # IrcIO::ServerはIRCサーバーに接続し、IRCメッセージをやり取りするクラスです。
 # このクラスはサーバーからメッセージを受け取ってチャンネル情報や現在のnickなどを保持しますが、
@@ -35,7 +35,7 @@
     $obj->{receiving_exceptlist} = {}; # 同上。RPL_EXCEPTLIST
     $obj->{receiving_invitelist} = {}; # 同上、RPL_INVITELIST
 
-    $obj->{channels} = {}; # チャンネル名 => ChannelInfo
+    $obj->{channels} = {}; # 小文字チャンネル名 => ChannelInfo
     $obj->{people} = {}; # nick => PersonalInfo
 
     $obj->connect;
@@ -54,6 +54,7 @@
 }
 
 sub channels {
+    # {小文字チャンネル名 => ChannelInfo}のハッシュリファを返す。
     # @options(省略可能):
     #   'even-if-kicked-out': 既に自分が蹴り出されてゐるチャンネルも返す。この動作は高速である。
     my ($this, @options) = @_;
@@ -62,11 +63,12 @@
     }
     else {
 	# kicked-outフラグが立つてゐないチャンネルのみ返す。
-	my %result = map {
-	    ($_, $this->{channels}{$_});
-	} grep {
-	    !$this->{channels}{$_}->remarks('kicked-out');
-	} keys %{$this->{channels}};
+	my %result;
+	while (my ($name, $ch) = each %{$this->{channels}}) {
+	    if (!$ch->remark('kicked-out')) {
+		$result{$name} = $ch;
+	    }
+	}
 	\%result;
     }
 }
@@ -154,7 +156,8 @@
 }
 
 sub channel {
-    my ($this,$channel_name) = @_;
+    my $this = $_[0];
+    my $channel_name = Multicast::lc($_[1]);
     $this->{channels}->{$channel_name};
 }
 
@@ -415,7 +418,7 @@
 
 sub _receive_after_logged_in {
     my ($this,$msg) = @_;
-
+      
     $this->person($msg->nick,$msg->name,$msg->host); # nameとhostを覚えておく。
 
     if ($msg->command eq 'NICK') {
@@ -533,7 +536,7 @@
 	# チャンネル名とnickが1対1で対応
 	map {
 	    my ($ch_name,$nick) = ($ch_names[$_],$nicks[$_]);
-	    my $ch = $this->{channels}->{$ch_name};
+	    my $ch = $this->channel($ch_name);
 	    if (defined $ch) {
 		#$ch->names($nick,undef,'delete');
 		$kick->($ch,$nick);
@@ -542,7 +545,7 @@
     }
     elsif (@ch_names == 1) {
 	# 一つのチャンネルから1人以上をkick
-	my $ch = $this->{channels}->{$ch_names[0]};
+	my $ch = $this->channel($ch_names[0]);
 	if (defined $ch) {
 	    map {
 		#$ch->names($_,undef,'delete');
@@ -559,7 +562,7 @@
 	return;
     }
 
-    my $ch = $this->{channels}->{$msg->param(0)};
+    my $ch = $this->channel($msg->param(0));
     if (defined $ch) {
 	my $n_params = @{$msg->params};
 
@@ -624,14 +627,15 @@
 	m/^([^\x07]+)(?:\x07(.*))?/;
 	my ($ch_name,$mode) = ($1,(defined $2 ? $2 : ''));
 
-	my $ch = $this->{channels}->{$ch_name};
+	my $ch = $this->channel($ch_name);
 	if (defined $ch) {
 	    # 知っているチャンネル。もしkickedフラグが立っていたらクリア。
 	    $ch->remarks('kicked-out',undef,'delete');
 	}
 	else {
 	    # 知らないチャンネル。
-	    $ch = $this->{channels}->{$ch_name} = ChannelInfo->new($ch_name,$this->{network_name});
+	    $ch = ChannelInfo->new($ch_name,$this->{network_name});
+	    $this->{channels}{Multicast::lc($ch_name)} = $ch;
 	}
 	$ch->names($msg->nick,
 		   new PersonInChannel(
@@ -644,10 +648,11 @@
 sub _NJOIN {
     my ($this,$msg) = @_;
     my $ch_name = $msg->param(0);
-    my $ch = $this->{channels}->{$ch_name};
+    my $ch = $this->channel($ch_name);
     unless (defined $ch) {
 		# 知らないチャンネル。
-	$ch = $this->{channels}->{$ch_name} = ChannelInfo->new($ch_name,$this->{network_name});
+	$ch = ChannelInfo->new($ch_name,$this->{network_name});
+	$this->{channels}{Multicast::lc($ch_name)} = $ch;
     }
     map {
 	m/^([@+]*)(.+)$/;
@@ -665,11 +670,11 @@
     my ($this,$msg) = @_;
     map {
 	my $ch_name = $_;
-	my $ch = $this->{channels}->{$ch_name};
+	my $ch = $this->channel($ch_name);
 	if (defined $ch) {
 	    if ($msg->nick eq $this->{current_nick}) {
 		# PARTしたのが自分だった
-		delete $this->{channels}->{$ch_name};
+		delete $this->{channels}->{Multicast::lc($ch_name)};
 	    }
 	    else {
 		$ch->names($msg->nick,undef,'delete');
@@ -738,7 +743,7 @@
 
 sub _TOPIC {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(0)};
+    my $ch = $this->channel($msg->param(0));
     if (defined $ch) {
 	# 古いトピックを"old-topic"として註釈を付ける。
 	$msg->remark('old-topic', $ch->topic);
@@ -752,7 +757,7 @@
 
 sub _RPL_NAMREPLY {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(2)};
+    my $ch = $this->channel($msg->param(2));
     return unless defined $ch;
 
     my $receiving_namreply = $this->{receiving_namreply}->{$msg->param(2)};
@@ -844,7 +849,7 @@
 
 sub _RPL_NOTOPIC {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
     if (defined $ch) {
 	$ch->topic('');
     }
@@ -852,7 +857,7 @@
 
 sub _RPL_TOPIC {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
     if (defined $ch) {
 	$ch->topic($msg->param(2));
     }
@@ -860,7 +865,7 @@
 
 sub _RPL_TOPICWHOTIME {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
     if (defined $ch) {
 	$ch->topic_who($msg->param(2));
 	$ch->topic_time($msg->param(3));
@@ -869,7 +874,7 @@
 
 sub _RPL_INVITELIST {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
 
     my $receiving_invitelist = $this->{receiving_invitelist}->{$msg->param(1)};
     if (defined $receiving_invitelist &&
@@ -894,7 +899,7 @@
 
 sub _RPL_EXCEPTLIST {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
 
     my $receiving_exceptlist = $this->{receiving_exceptlist}->{$msg->param(1)};
     if (defined $receiving_exceptlist &&
@@ -919,7 +924,7 @@
 
 sub _RPL_BANLIST {
     my ($this,$msg) = @_;
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
 
     my $receiving_banlist = $this->{receiving_banlist}->{$msg->param(1)};
     if (defined $receiving_banlist &&
@@ -973,7 +978,7 @@
     my ($this,$msg) = @_;
     # 既知のチャンネルなら、そのチャンネルに
     # switches-are-known => 1という備考を付ける。
-    my $ch = $this->{channels}->{$msg->param(1)};
+    my $ch = $this->channel($msg->param(1));
     if (defined $ch) {
 	$ch->remarks('switches-are-known',1);
 
diff -urN tiarra-20040401/main/Mask.pm tiarra-20040407/main/Mask.pm
--- tiarra-20040401/main/Mask.pm	2004-04-01 18:52:45.000000000 +0900
+++ tiarra-20040407/main/Mask.pm	2004-04-07 20:57:34.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Mask.pm,v 1.14 2004/03/07 10:34:19 topia Exp $
+# $Id: Mask.pm,v 1.15 2004/04/07 11:49:58 admin Exp $
 # -----------------------------------------------------------------------------
 # $Clovery: tiarra/main/Mask.pm,v 1.10 2003/07/24 03:08:26 topia Exp $
 package Mask;
@@ -242,13 +242,7 @@
 	    delete $cache_table{$to_delete};
 	}
 
-	my $regex = $str;
-	$regex =~ s/(\W)/\\$1/g;
-	$regex =~ s/\\\?/\./g;
-	$regex =~ s/\\\*/\.\*/g;
-	$regex = "^$regex\$";
-	
-	my $compiled = qr/$regex/i;
+	my $compiled = compile($str);
 	push @cache_keys, $str;
 	$cache_table{$str} = $compiled;
 	
@@ -256,6 +250,28 @@
     }
 }
 
+sub compile {
+    # $mask: マスク文字列
+    # $consider_case: 真なら、大文字小文字を区別する。
+    my ($mask, $consider_case) = @_;
+
+    if (!defined $mask) {
+	return qr/(?!)/; # マッチしない正規表現
+    }
+
+    my $regex = $mask;
+    $regex =~ s/(\W)/\\$1/g;
+    $regex =~ s/\\\?/\./g;
+    $regex =~ s/\\\*/\.\*/g;
+    $regex = "^$regex\$";
+    if ($consider_case) {
+	qr/$regex/;
+    }
+    else {
+	qr/$regex/i;
+    }
+}
+
 sub _split {
     # ',' でわけられたマスクを配列にする。
     my $mask = shift;
diff -urN tiarra-20040401/main/Multicast.pm tiarra-20040407/main/Multicast.pm
--- tiarra-20040401/main/Multicast.pm	2004-04-01 18:52:45.000000000 +0900
+++ tiarra-20040407/main/Multicast.pm	2004-04-07 20:57:34.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Multicast.pm,v 1.23 2004/03/07 10:34:19 topia Exp $
+# $Id: Multicast.pm,v 1.24 2004/04/07 11:49:58 admin Exp $
 # -----------------------------------------------------------------------------
 # サーバーからクライアントにメッセージが流れるとき、このクラスはフィルタとして
 # ネットワーク名を付加します。
@@ -683,4 +683,19 @@
     }
 }
 
+sub lc {
+    # IRC方式で、大文字を小文字に変換する。
+    my $str = shift;
+    # {}|は[]\の小文字である。気違いじみている!
+    $str =~ tr/A-Z[]\\/a-z{}|/;
+    $str;
+}
+
+sub uc {
+    # IRC方式で、小文字を大文字に変換する。
+    my $str = shift;
+    $str =~ tr/a-z{}|/A-Z[]\\/;
+    $str;
+}
+
 1;
