diff -urN tiarra-20040418/ChangeLog tiarra-20040508/ChangeLog
--- tiarra-20040418/ChangeLog	2004-04-18 16:45:56.000000000 +0900
+++ tiarra-20040508/ChangeLog	2004-05-08 17:15:56.000000000 +0900
@@ -1,3 +1,40 @@
+2004-05-08  Topia  <topia@clovery.jp>
+
+	* HACKING:
+	  - typo を修正した。
+	  - IrcIO::Server->remark に isupport と uid を追加した。
+	  - ChannelInfo->remark に creation-time を追加した。
+
+	* main/Multicast.pm:
+	  - $server_sent, $client_sent: RPL_CREATIONTIME へ対応した。
+	  - $client_sent: admin コマンドを追加した。
+
+	* main/NumericReply.pm:
+	  - RPL_BOUNCE を RPL_REDIR に変更。 RPL_BOUNCE はエイリアスとして
+	    そのまま残すようにした。
+	  - RPL_CREATIONTIME を追加した。
+	  - RPL_TOPICWHOTIME を RPL_TOPIC_WHO_TIME に変更した。
+	    RPL_TOPICWHOTIME はエイリアスとしてそのまま残すようにした。
+	  - irc2.11 なものをいくつか追加した。
+	    + RPL_HELLO(020)
+	    + RPL_YOURID(042)
+	    + RPL_SAVENICK(043)
+	    + RPL_REOPLIST(344)
+	    + RPL_ENDOFREOPLIST(345)
+
+	* main/IrcIO/Server.pm:
+	  - RPL_{CREATIONTIME,ISUPPORT,YOURID} に対応した。
+	(_receive_while_logging_in):
+	  - RPL_HELLO 対策を追加した。
+	(modify_nick):
+	  - 第二引数で nicklen を指定できるようにした。
+	(_set_to_next_nick):
+	  - ISUPPORT に NICKLEN が含まれていれば、それを使うようにした。
+
+	* module/Client/Cache.pm:
+	(_send_mode_cache):
+	  - creation-time が存在すれば、それも返すようにした。
+
 2004-04-18  Topia  <topia@clovery.jp>
 
 	* HACKING:
@@ -1586,7 +1623,7 @@
 
 	* これ以前のログは書いていません。
 
-#       Id: $Id: ChangeLog,v 1.146 2004/04/18 07:44:46 topia Exp $
+#       Id: $Id: ChangeLog,v 1.147 2004/05/08 08:11:30 topia Exp $
 #   Author: $Author: topia $
-#     Date: $Date: 2004/04/18 07:44:46 $
-# Revision: $Revision: 1.146 $
+#     Date: $Date: 2004/05/08 08:11:30 $
+# Revision: $Revision: 1.147 $
diff -urN tiarra-20040418/HACKING tiarra-20040508/HACKING
--- tiarra-20040418/HACKING	2004-04-18 16:45:56.000000000 +0900
+++ tiarra-20040508/HACKING	2004-05-08 17:15:56.000000000 +0900
@@ -49,7 +49,7 @@
   - BulletinBoard(main/BulletinBoard.pm)
     ここで紹介する関数は、全て BulletinBoard->shared->function(...) と呼んで下さい。
     + set($key, $value)		掲示板に $key という名前で値 $value をセットします。
-    				$value を __PACKAGE__."/key" という名前にすれば
+    				$key を __PACKAGE__."/key" という名前にすれば
 				被りにくいと思います。
     + get($key)			$key でセットした値を得ます。
     + keys			BulletinBoard が保持しているテーブルを返します。
@@ -66,6 +66,12 @@
     + 情報取得系
       * server_hops		自分のつながっている server と、あるサーバの hop 数の対応を
 				(情報が得られたときに)記録しています。
+      * isupport		RPL_ISUPPORT が送ってくる情報を記録しています。
+				RPL_ISUPPORT の詳細は http://www.irc.org/tech_docs/005.html 等を
+				参照してください。
+				対応していないサーバでは remark は存在しません。
+      * uid			RPL_YOURID が送ってくる情報を記録しています。
+				対応していないサーバでは remark は存在しません。
   - IRCMessage
     + 情報取得系
       * affected-channels	NICK や QUIT などの全チャンネルに波及するメッセージのときに
@@ -84,5 +90,6 @@
       * kicked-out		そのチャンネルから蹴り出されている(すでにそのチャンネルに
 				いない)かどうか。
       * switches-are-known	チャンネルモードを取得済みかどうか。
+      * creation-time		RPL_CREATIONTIME が返した値。
   - PersonInChannel
   - PersonalInfo
diff -urN tiarra-20040418/main/IrcIO/Server.pm tiarra-20040508/main/IrcIO/Server.pm
--- tiarra-20040418/main/IrcIO/Server.pm	2004-04-18 16:45:57.000000000 +0900
+++ tiarra-20040508/main/IrcIO/Server.pm	2004-05-08 17:15:57.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Server.pm,v 1.55 2004/04/07 11:49:57 admin Exp $
+# $Id: Server.pm,v 1.56 2004/05/08 08:11:31 topia Exp $
 # -----------------------------------------------------------------------------
 # IrcIO::ServerはIRCサーバーに接続し、IRCメッセージをやり取りするクラスです。
 # このクラスはサーバーからメッセージを受け取ってチャンネル情報や現在のnickなどを保持しますが、
@@ -402,6 +402,10 @@
 	$this->_set_to_next_nick($first_msg->param(1));
 	return; # 何も返さない→クライアントにはこの結果を知らせない。
     }
+    elsif ($reply eq RPL_HELLO) {
+	# RPL_HELLO (irc2.11.x)
+	return; # 何もしない
+    }
     else {
 	# それ以外。手の打ちようがないのでconnectionごと切断してしまう。
 	# 但し、ニューメリックリプライでもERRORでもなければ無視する。
@@ -501,8 +505,9 @@
 	    foreach (
 		map("RPL_$_",
 		    qw(CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME
-		       WHOREPLY NAMREPLY ENDOFNAMES
-		       WHOISUSER WHOISSERVER AWAY ENDOFWHOIS),
+		       CREATIONTIME WHOREPLY NAMREPLY ENDOFNAMES
+		       WHOISUSER WHOISSERVER AWAY ENDOFWHOIS
+		       ISUPPORT YOURID),
 		    map({("${_}LIST", "ENDOF${_}LIST");}
 			    qw(INVITE EXCEPT BAN)),
 		   )) {
@@ -872,6 +877,14 @@
     }
 }
 
+sub _RPL_CREATIONTIME {
+    my ($this,$msg) = @_;
+    my $ch = $this->channel($msg->param(1));
+    if (defined $ch) {
+	$ch->remark('creation-time', $msg->param(2));
+    }
+}
+
 sub _RPL_INVITELIST {
     my ($this,$msg) = @_;
     my $ch = $this->channel($msg->param(1));
@@ -997,10 +1010,49 @@
 		       Params => \@args));
 }
 
+sub _RPL_ISUPPORT {
+    # 歴史的な理由で、 RPL_ISUPPORT(005) は
+    # RPL_BOUNCE(005) として使われていることがある。
+    my ($this,$msg) = @_;
+    if ($msg->n_params >= 2 && # nick + [params] + 'are supported by this server'
+	    $msg->param($msg->n_params - 1) =~ /supported/i) {
+	my $isupport = $this->remark('isupport');
+	foreach my $param ((@{$msg->params})[1...($msg->n_params - 2)]) {
+	    my ($negate, $key, $value) = $param =~ /^(-)?([[:alnum:]]+)(?:=(.+))?$/;
+	    if (!defined $negate) {
+		# empty value
+		$value = '' unless defined $value;
+		$isupport->{$key} = $value;
+	    } elsif (!defined $value) {
+		# negate a previously specified parameter
+		delete $isupport->{$key};
+	    } else {
+		# inconsistency param
+		carp("inconsistency RPL_ISUPPORT param: $param");
+	    }
+	}
+	$this->remark('isupport', $isupport);
+    }
+}
+
+sub _RPL_YOURID {
+    my ($this,$msg) = @_;
+
+    $this->remark('uid', $msg->param(1));
+}
+
 sub _set_to_next_nick {
     my ($this,$failed_nick) = @_;
     # failed_nickの次のnickを試します。nick重複でログインに失敗した時に使います。
-    my $next_nick = modify_nick($failed_nick);
+    my $nicklen = do {
+	if (defined $this->remark('isupport') &&
+		defined $this->remark('isupport')->{NICKLEN}) {
+	    $this->remark('isupport')->{NICKLEN};
+	} else {
+	    9;
+	}
+    };
+    my $next_nick = modify_nick($failed_nick, $nicklen);
 
     my $msg_for_user = "Nick $failed_nick was already in use in the ".$this->network_name.". Trying ".$next_nick."...";
     $this->send_message(
@@ -1017,26 +1069,31 @@
 
 sub modify_nick {
     my $nick = shift;
-    if ($nick =~ /(\d+)$/) {
+    my $nicklen = shift || 9;
+
+    if ($nick =~ /^(.*\D)?(\d+)$/) {
 	# 最後の数文字が数字だったら、それをインクリメント
-	my $base = $`;
-	my $next_num = $1 + 1;
-	if (length($base . $next_num) <= 9) {
-	    # 9文字以内に収まるのでこれで試す。
+	my $base = $1;
+	my $next_num = $2 + 1;
+	if (($next_num - 1) eq $next_num) {
+	    # 桁あふれしているので数字部分を全部消す。
+	    $nick = $base;
+	} elsif (length($base . $next_num) <= $nicklen) {
+	    # $nicklen 文字以内に収まるのでこれで試す。
 	    $nick = $base . $next_num;
 	}
 	else {
-	    # 収まらないので9文字に縮める。
-	    $nick = substr($base,0,9 - length($next_num)) . $next_num;
+	    # 収まらないので $nicklen 文字に縮める。
+	    $nick = substr($base,0,$nicklen - length($next_num)) . $next_num;
 	}
     }
-    elsif ($nick =~ /_$/ && length($nick) >= 9) {
+    elsif ($nick =~ /_$/ && length($nick) >= $nicklen) {
 	# 最後の文字が_で、それ以上_を付けられない場合、それを0に。
 	$nick =~ s/_$/0/;
     }
     else {
 	# 最後に_を付ける。
-	if (length($nick) >= 9) {
+	if (length($nick) >= $nicklen) {
 	    $nick =~ s/.$/_/;
 	}
 	else {
diff -urN tiarra-20040418/main/Multicast.pm tiarra-20040508/main/Multicast.pm
--- tiarra-20040418/main/Multicast.pm	2004-04-18 16:45:57.000000000 +0900
+++ tiarra-20040508/main/Multicast.pm	2004-05-08 17:15:57.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Multicast.pm,v 1.24 2004/04/07 11:49:58 admin Exp $
+# $Id: Multicast.pm,v 1.25 2004/05/08 08:11:31 topia Exp $
 # -----------------------------------------------------------------------------
 # サーバーからクライアントにメッセージが流れるとき、このクラスはフィルタとして
 # ネットワーク名を付加します。
@@ -356,7 +356,8 @@
 	} ((map {"RPL_$_"}
 		((map { ("$_", "ENDOF$_"); } qw(INVITELIST EXCEPTLIST BANLIST)),
 		 (map {"ENDOF$_"} qw(WHO NAMES)),
-		 qw(LIST CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME))),
+		 qw(LIST CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME),
+		 qw(CREATIONTIME))),
 	   qw(ERR_TOOMANYCHANNELS ERR_NOTONCHANNEL ERR_NOSUCHCHANNEL))},
     do {
 	no strict 'refs';
@@ -395,7 +396,7 @@
     'SERVLIST' => \&_MODE_from_client, # これも良く分からない。MODEと同じに。
     'SERVSET' => \&_MODE_from_client, # これも。
     'SQUERY' => \&_MODE_from_client, # これも
-    'STATS' => \&_MODE_from_client,
+    'STATS' => \&_MODE_from_client, # サーバ名はうしろにつくのでこれはよくないかも
     'SUMMON' => \&_MODE_from_client,
     'TIME' => \&_MODE_from_client,
     'TOPIC' => \&_MODE_from_client,
@@ -405,6 +406,7 @@
     'USERHOST' => \&_ISON_from_client,
     'USERS' => \&_MODE_from_client,
     'VERSION' => \&_MODE_from_client,
+    'ADMIN' => \&_MODE_from_client,
     'WHO' => \&_WHOIS_from_client,
     'WHOIS' => \&_WHOIS_from_client,
     'WHOWAS' => \&_WHOIS_from_client,
@@ -430,7 +432,7 @@
 		((map { ("$_", "ENDOF$_"); } qw(INVITELIST EXCEPTLIST BANLIST)),
 		 (map {"ENDOF$_"} qw(WHO NAMES)),
 		 qw(LIST CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME),
-		 qw(INVITING UNIQOPIS WHOREPLY))),
+		 qw(CREATIONTIME INVITING UNIQOPIS WHOREPLY))),
 	   qw(ERR_TOOMANYCHANNELS ERR_NOTONCHANNEL ERR_NOSUCHCHANNEL))},
     do {
 	no strict 'refs';
diff -urN tiarra-20040418/main/NumericReply.pm tiarra-20040508/main/NumericReply.pm
--- tiarra-20040418/main/NumericReply.pm	2004-04-18 16:45:57.000000000 +0900
+++ tiarra-20040508/main/NumericReply.pm	2004-05-08 17:15:57.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: NumericReply.pm,v 1.2 2004/02/14 11:48:19 topia Exp $
+# $Id: NumericReply.pm,v 1.3 2004/05/08 08:11:31 topia Exp $
 # -----------------------------------------------------------------------------
 # このファイルでは、各ニューメリックリプライに対するシンボルを定義し、exportします。
 # -----------------------------------------------------------------------------
@@ -21,12 +21,21 @@
 	 RPL_CREATED          003
 	 RPL_MYINFO           004
 	 RPL_ISUPPORT         005
+
+	 # irc2.11.x or +hemp
 	 RPL_BOUNCE           010
+	 RPL_REDIR            010
+
 	 RPL_MAP              015
 	 RPL_MAPMORE          016
 	 RPL_MAPEND           017
 	 RPL_MAPSTART         018
 
+	 # irc2.11.x
+	 RPL_HELLO            020
+	 RPL_YOURID           042
+	 RPL_SAVENICK         043
+
 
 	 RPL_NONE             300
 	 RPL_AWAY             301
@@ -56,13 +65,20 @@
 	 RPL_CHANNELMODEIS    324
 	 RPL_UNIQOPIS         325
 
+	 RPL_CREATIONTIME     329
+
 	 RPL_NOTOPIC          331
 	 RPL_TOPIC            332
 	 RPL_TOPICWHOTIME     333
+	 RPL_TOPIC_WHO_TIME   333
 
 	 RPL_INVITING         341
 	 RPL_SUMMONING        342
 
+	 # irc2.11
+	 RPL_REOPLIST         344
+	 RPL_ENDOFREOPLIST    345
+
 	 RPL_INVITELIST       346
 	 RPL_ENDOFINVITELIST  347
 
diff -urN tiarra-20040418/module/Client/Cache.pm tiarra-20040508/module/Client/Cache.pm
--- tiarra-20040418/module/Client/Cache.pm	2004-04-18 16:45:57.000000000 +0900
+++ tiarra-20040508/module/Client/Cache.pm	2004-05-08 17:15:57.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Cache.pm,v 1.9 2004/04/18 07:44:47 topia Exp $
+# $Id: Cache.pm,v 1.10 2004/05/08 08:11:31 topia Exp $
 # -----------------------------------------------------------------------------
 # copyright (C) 2003-2004 Topia <topia@clovery.jp>. all rights reserved.
 package Client::Cache;
@@ -255,6 +255,22 @@
 	    },
 	   )
        );
+    if (defined $ch->remark('creation-time')) {
+	$sendto->send_message(
+	    IRCMessage->new(
+		Prefix => RunLoop->shared_loop->sysmsg_prefix('system'),
+		Command => RPL_CREATIONTIME,
+		Params => [
+		    RunLoop->shared_loop->current_nick,
+		    $ch_name,
+		    $ch->remark('creation-time'),
+		   ],
+		Remarks => {
+		    'fill-prefix-when-sending-to-client' => 1,
+		},
+	       )
+	   );
+    }
 }
 
 1;
