diff -urN tiarra-20040215/ChangeLog tiarra-20040223/ChangeLog
--- tiarra-20040215/ChangeLog	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/ChangeLog	2004-02-23 11:47:36.000000000 +0900
@@ -1,3 +1,167 @@
+2004-02-23  Topia  <topia@clovery.jp>
+
+	* makedoc:
+	  - sample.conf を出力するようにした。
+	  - 全体にわたってモジュール名のソートを行うようにした。
+	  - block 構文への暫定対応。
+	  - #key:value という *コメント* をきちんと認識していなかったのを fix
+	  - グループ名に説明が定義されていなかったときに警告を出すようにした。
+
+	* tiarra:
+	  - --enable-debug 時にも、 couldn't connect 関連のメッセージなら
+	    スタックトレースを省略するようにした。
+
+	* sample.conf:
+	  - TiarraDoc を使用するようになった。
+
+	* doc/module-toc.html, doc/module/*.html:
+	  - regen.
+
+	* doc-src/conf-main.tdoc:
+	  - general/omit-sysmsg-prefix-when-possible 削除。
+	  - general/sysmsg-prefix-use-masks ブロック追加。
+	  - 書かれていなかった networks/multi-server-mode の解説を
+	    sample.conf から持ってきて追加。
+	  - typo したままだった networks/channel-network-separator の
+	    コメントを sample.conf に従って修正。
+	  - ircnet/host を irc.nara.wide.ad.jp に変更。
+	    いまは停止しているのだが、復活を願うということで。
+
+	* doc-src/module-group.tdoc:
+	  - Channel の最後が typo していたのを修正。
+	  - Client, CTCP, Debug を追加。
+	    とはいえ Debug はまだ cvs repo. には存在していないが…。
+
+	* doc-src/sample.conf.in:
+	  - RCS Tag 'Id' を追加。
+
+	* main/Configuration.pm:
+	  - general/omit-sysmsg-prefix-when-possible のデフォルト値を消して、
+	    general/sysmsg-prefix-use-masks のデフォルトブロックを追加。
+	(_complete_table_with_defaults):
+	  - _complete_{table,block}_with_defaults に分割。
+	(_complete_table_with_defaults):
+	  - Block を使った実装に変更。
+	  - Configuration::Block->table の追加が必須。
+	(_complete_block_with_defaults):
+	  - block(hash_ref) と array_ref のデフォルト値に対応。
+
+	* main/ModuleManager.pm:
+	(update_modules):
+	  - %loaded_mods に古いモジュールが無かった場合は無視するようにした。
+	(_unload):
+	  - デバッグモード時でも、同じモジュールからの 11 以上の export は表示しない。
+
+	* main/Multicast.pm:
+	  - $server_sent, $client_sent: NumericReply 化。
+	    ERR_TOOMANYCHANNELS と RPL_WHOISCHANNELS を追加。
+	(_NJOIN_from_server, _RPL_NAMREPLY):
+	  - /[@+]/ が変数展開されているようなので /[\@+]/ に変更。
+	(_WHOIS_from_client):
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	(_{attach,detach}_RPL_WHOISCHANNELS):
+	  - 追加。 WHOIS で表示されるチャンネル名に network をつける。
+
+	* main/RunLoop.pm:
+	  - sysmsg_prefix を追加。
+	(_action_one_message, _action_message_for_each, notify_msg):
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+
+	* main/TiarraDoc.pm:
+	(_makeconf):
+	  - block への暫定対応。
+
+	* main/Configuration/Block.pm:
+	  - ->table を追加。
+	(eval_code):
+	  - original の typo を修正。
+
+	* main/IrcIO/Client.pm:
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	(inform_joinning_channels):
+	  - 暫定的に networks/fixed-channels ブロックに channel の mask を
+	    書くことで、送信順を指定できるようにしたが、 conf エントリ名が
+	    気に入らないため、名前が決まるまでは sample.conf に
+	    書かないことにする。
+
+	* main/IrcIO/Server.pm:
+	  - ->server_hostname を追加。 RPL_WELCOME(001) で送られてきた
+	    サーバ名を保持する。
+	  - サーバで nick 変更が起こったときに、以前の nick も表示するようにした。
+
+	* module/Auto/Reply.pm:
+	  - 返答時に mask をチェックするようにした。
+
+	* module/Channel/Freeze.pm:
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	  - 不要になった use Configuration; を削除。
+
+	* module/Client/Cache.pm:
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	  - WHO キャッシュ送信時において、 Multicast::global_to_local を
+	    使って nick を変換していなかった bug を修正。
+	  - 不要になった use Configuration; を削除。
+
+	* module/Client/Eval.pm:
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	  - 無用な remark('fill-prefix-when-sending-to-client') をなくした。
+
+	* module/Log/Recent.pm:
+	  - no-recent-logs クライアントオプションを追加。
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	  - 不要になった use Configuration; を削除。
+
+	* module/System/Pong.pm:
+	  - NumericReply 化。 ERR_NOORIGIN を返せるようにした。
+	  - PING もここで破棄するようにした。
+	(message_arrived):
+	  - $sender->server_hostname を使用して正確なホスト名に返す。
+
+	* module/System/Raw.pm:
+	  - RunLoop->shared_loop->sysmsg_prefix を使用するようにした。
+	  - NumericReply 化。 NOTICE の代わりに ERR_NEEDMOREPARAMS を返す。
+	  - 不要になった use Configuration; を削除。
+
+	* module/User/Ignore.pm:
+	  - sample conf の mask に例示用ドメインを使用するようにした。
+
+	* module/Auto/Alias.pm, module/Auto/Answer.pm,
+	module/Auto/ChannelWithoutOper.pm, module/Auto/Joined.pm,
+	module/Auto/MesMail.pm, module/Auto/Oper.pm,
+	module/Auto/Random.pm, module/Auto/Reply.pm,
+	module/Auto/Response.pm, module/CTCP/*.pm,
+	module/Channel/*.pm, module/Channel/Join/Invite.pm,
+	module/Channel/Join/Kicked.pm, module/Channel/Mode/*.pm,
+	module/Channel/Mode/Oper/Grant.pm, module/Log/Recent.pm,
+	module/System/Macro.pm, module/System/Pong.pm,
+	module/System/Raw.pm, module/System/RemoteControl.pm,
+	module/System/Shutdown.pm, module/User/Filter.pm,
+	module/User/ServerOper.pm, module/User/Vanish.pm,
+	module/User/Away/Client.pm, module/User/Away/Nick.pm,
+	module/User/Nick/Detached.pm:
+	  - TiarraDoc 化。 sample.conf から取ってきて一部まずいところは
+	    変更している。
+
+2004-02-21  phonohawk  <phonohawk@ps.sakura.ne.jp>
+
+	* module/Channel/Freeze.pm:
+	freezeコマンドの引数は、これまでは完全なチャンネル名であったが、
+	これはマスクに変更。その時にJOINしている全てのチャンネルの中から
+	マスクに一致した全てのチャンネルを凍結する。
+
+	* sample.conf, doc-src/conf-main.tdoc:
+	設定 general/omit-sysmsg-prefix-when-possible 追加。
+	これが1である時、sysmsg-prefixはチャンネルに対してのメッセージ
+	でなければ省略する。デフォルトは1。
+
+	* main/Configuration.pm:
+	general/omit-sysmsg-prefix-when-possible のデフォルト値を追加。
+
+	* main/Multicast.pm, main/RunLoop.pm,
+	  main/IrcIO/Client.pm, module/Channel/Freeze.pm,
+	  main/Log/Recent.pm, module/System/Raw.pm:
+	omit-sysmsg-prefix-when-possibleを反映。
+
 2004-02-15  Topia  <topia@clovery.jp>
 
 	* module/Client/Cache.pm:
@@ -1234,7 +1398,7 @@
 
 	* これ以前のログは書いていません。
 
-#       Id: $Id: ChangeLog,v 1.129 2004/02/15 00:19:31 topia Exp $
+#       Id: $Id: ChangeLog,v 1.131 2004/02/23 02:46:17 topia Exp $
 #   Author: $Author: topia $
-#     Date: $Date: 2004/02/15 00:19:31 $
-# Revision: $Revision: 1.129 $
+#     Date: $Date: 2004/02/23 02:46:17 $
+# Revision: $Revision: 1.131 $
diff -urN tiarra-20040215/NEWS tiarra-20040223/NEWS
--- tiarra-20040215/NEWS	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/NEWS	2004-02-23 11:47:36.000000000 +0900
@@ -1,3 +1,44 @@
+2004-02-23  Topia  <topia@clovery.jp>
+
+	* sample.conf
+	  - 順序が変わっています。注意してください。
+	  - general/omit-sysmsg-prefix-when-possible 削除。
+	  - general/sysmsg-prefix-use-masks ブロック追加。
+
+	* Log::Recent
+	  - no-client-logs クライアントオプションが追加されました。
+	    クライアントオプションの使い方は、
+	    realname 部分に $no-client-logs=1$ を指定します。
+	    複数ある場合は $no-client-logs=1;a=1;...$ のように指定できます。
+
+	* 全般
+	  - クライアントとの接続時にチャンネルの送出順を指定する patch を
+	    暫定的に取り込みました。 network に fixed-channels ブロックを
+	    作り、中に channel をキー名としてマスクを列挙します。
+	    例:
+	      fixed-channels {
+	        channel: #てすとちゃんねる@ircnet
+	        channel: #てすと@localserver
+	        channel: *@localserver
+	        channel: *@localserver:*.jp
+	      }
+	    マッチしなかったチャンネルについては最後にまとめて
+	    (順番がごちゃごちゃになって)送られてきます。
+	    conf の設定場所は暫定です。変わる可能性があるので注意してください。
+	  - doc/ 以下に HTML でのドキュメントが生成されていますが、
+	    まだ未調整な部分も多くあるので、正確な記述は sample.conf を参照してください。
+
+2004-02-21  phonohawk  <phonohawk@ps.sakura.ne.jp>
+
+	* Channel::Freeze
+	freezeコマンドの引数は、これまでは完全なチャンネル名であったが、
+	これはマスクに変更。その時にJOINしている全てのチャンネルの中から
+	マスクに一致した全てのチャンネルを凍結する。
+
+	* 設定 general/omit-sysmsg-prefix-when-possible 追加。
+	これが1である時、sysmsg-prefixはチャンネルに対してのメッセージ
+	でなければ省略する。デフォルトは1。
+
 2004-02-15  Topia  <topia@clovery.jp>
 
 	* Client::Cache
diff -urN tiarra-20040215/main/Configuration/Block.pm tiarra-20040223/main/Configuration/Block.pm
--- tiarra-20040215/main/Configuration/Block.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/main/Configuration/Block.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Block.pm,v 1.10 2003/10/24 06:12:29 admin Exp $
+# $Id: Block.pm,v 1.11 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 package Configuration::Block;
 use strict;
@@ -37,7 +37,7 @@
 # $block->get('foo_bar','all');
 # パラメータ"foo_bar"の値を返す。
 #
-# 以上の事から、Configuration::Blockはnew,block_name,set,get,
+# 以上の事から、Configuration::Blockはnew,block_name,table,set,get,
 # reinterpret-encoding,AUTOLOADといった属性はget()でしか読めない。
 # また、属性名にアンダースコアを持つ属性もget()でしか読めない。
 
@@ -60,6 +60,14 @@
     $this->[BLOCK_NAME];
 }
 
+sub table {
+    my ($this,$newvalue) = @_;
+    if (defined $newvalue) {
+	$this->[TABLE] = $newvalue;
+    }
+    $this->[TABLE];
+}
+
 sub equals {
     # 二つのConfiguration::Blockが完全に等価なら1を返す。
     my ($this,$that) = @_;
@@ -128,7 +136,7 @@
 	if ($@) {
 	    die "\%CODE{ }EDOC\% interpretation error.\n".
 		"block: ".$this->[BLOCK_NAME]."\n".
-		"origianl: $str\n".
+		"original: $str\n".
 		"$@\n";
 	}
 	$result;
diff -urN tiarra-20040215/main/Configuration.pm tiarra-20040223/main/Configuration.pm
--- tiarra-20040215/main/Configuration.pm	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/main/Configuration.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Configuration.pm,v 1.22 2004/02/14 11:48:18 topia Exp $
+# $Id: Configuration.pm,v 1.24 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # このクラスはフック`reloaded'を用意します。
 # フック`reloaded'は、設定ファイルがリロードされた時に呼ばれます。
@@ -187,6 +187,11 @@
 	'client-out-encoding' => 'jis',
 	'stdout-encoding' => 'euc',
 	'sysmsg-prefix' => 'tiarra',
+	'sysmsg-prefix-use-masks' => {
+	    'system' => '*',
+	    'priv' => '',
+	    'channel' => '*',
+	},
     },
     networks => {
 	'name' => 'main',
@@ -199,53 +204,53 @@
 sub _complete_table_with_defaults {
     my ($blocks) = @_;
 
-    my $find_block = sub {
-	my $name = shift;
-	# 引数として与えられたブロックの中から、指定された名を持つものを探す。
-	# 見付からなければundefを返す。
-	foreach my $block (@$blocks) {
-	    if ($block->block_name eq $name) {
-		return $block;
-	    }
-	}
-	undef;
-    };    
-    my $copy_and_store_block = sub {
-	# nameはスカラー、blockはハッシュ。
-	my ($name,$table) = @_;
-	my $block = Configuration::Block->new($name);
-	while (my ($key,$value) = each %$table) {
-	    $block->add($key,$value);
-	}
-	push @$blocks,$block;
-    };
+    my $root_block = Configuration::Block->new('ROOT');
+    map {
+	$root_block->set($_->block_name, $_);
+    } @$blocks;
+    _complete_block_with_defaults($root_block, $defaults);
+
+    # networksのdefaultだけは別処理。
+    my $networks = $root_block->networks;
+    if (!defined $networks->default) {
+	$networks->set('default',$networks->name);
+    }
+
+    @$blocks = values(%{$root_block->table});
+    $blocks;
+}
+
+sub _complete_block_with_defaults {
+    my ($blocks, $defaults) = @_;
 
     while (my ($default_block_name,$default_block) = each %{$defaults}) {
 	# このブロックは存在しているか？
-	unless (defined $find_block->($default_block_name)) {
-	    # ブロックごと省略されていたのでデフォルトのブロックをコピーして定義。
-	    $copy_and_store_block->($default_block_name,$default_block);
-	    next; # コピーしたので値の不足は考えなくて良い。
+	unless (defined $blocks->get($default_block_name)) {
+	    # ブロックごと省略されていたので空のブロックを定義。
+	    $blocks->set($default_block_name,
+			 Configuration::Block->new($default_block_name));
 	}
 	
+	my $block = $blocks->get($default_block_name);
+	my $must_check_child = {};
 	while (my ($default_key,$default_value) = each %{$default_block}) {
-	    my $block = $find_block->($default_block_name);
-	    # この値は存在しているか？
-	    if (!defined $block->get($default_key)) {
-		# 値が省略されていたので値を定義。
-		$block->add($default_key,$default_value);
+	    if ((!ref($default_value)) ||
+		    (ref($default_value) eq 'ARRAY')) {
+		# この値は存在しているか？
+		if (!defined $block->get($default_key)) {
+		    # 値が省略されていたので値を定義。
+		    $block->set($default_key,$default_value);
+		}
+	    } elsif (ref($default_value) eq 'HASH') {
+		$must_check_child->{$default_key} = $default_value;
 	    }
 	}
-    }
-
-    # networksのdefaultだけは別処理。
-    my $networks = $find_block->('networks');
-    if (!defined $networks->default) {
-	$networks->set('default',$networks->name);
+	if (values %$must_check_child) {
+	    _complete_block_with_defaults_recursive($block, $must_check_child);
+	}
     }
 }
 
-
 my $required = {
     general => ['nick','user','name'],
     # [ネットワーク名]のhost,portは別処理。
diff -urN tiarra-20040215/main/IrcIO/Client.pm tiarra-20040223/main/IrcIO/Client.pm
--- tiarra-20040215/main/IrcIO/Client.pm	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/main/IrcIO/Client.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Client.pm,v 1.23 2004/02/14 11:48:20 topia Exp $
+# $Id: Client.pm,v 1.25 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # IrcIO::Clientはクライアントからの接続を受け、
 # IRCメッセージをやり取りするクラスです。
@@ -182,7 +182,7 @@
     if ($this->{nick} ne '' && $this->{username} ne '') {
 	# general/tiarra-passwordを取得
 	my $valid_password = Configuration->shared_conf->general->tiarra_password;
-	my $prefix = Configuration->shared->general->sysmsg_prefix;
+	my $prefix = RunLoop->shared_loop->sysmsg_prefix('system');
 	if (defined $valid_password && $valid_password ne '' &&
 	    ! Crypt::check($this->{pass_received},$valid_password)) {
 	    # パスワードが正しくない。
@@ -239,10 +239,16 @@
 		my $network_name = $_->network_name;
 		my $global_nick = $_->current_nick;
 		if ($global_nick ne $current_nick) {
-		    $send_message->('NOTICE', "*** Your global nick in $network_name is currently '$global_nick'.");
+		    #$send_message->('NOTICE', "*** Your global nick in $network_name is currently '$global_nick'.");
+		    $this->send_message(
+			new IRCMessage(
+			    Prefix => Runloop->shared_loop->sysmsg_prefix(qw(priv system)),
+			    Command => 'NOTICE',
+			    Params => [$current_nick,
+				       "*** Your global nick in $network_name is currently '$global_nick'."]));
 		}
 	    } values %{RunLoop->shared_loop->networks};
-
+	    
 	    $send_message->(RPL_YOURHOST, "Your host is $prefix, running version ".::version());
 	    $send_message->(RPL_MOTDSTART, "- $prefix Message of the Day -");
 	    foreach my $line (main::get_credit()) {
@@ -292,7 +298,7 @@
 	    } else {
 		$this->send_message(
 		    new IRCMessage(
-			Prefix => Configuration->shared->general->sysmsg_prefix,
+			Prefix => RunLoop->shared_loop->sysmsg_prefix('system'),
 			Command => ERR_ERRONEOUSNICKNAME,
 			Params => [RunLoop->shared_loop->current_nick,
 				   $msg->params->[0],
@@ -303,7 +309,7 @@
 	} else {
 	    $this->send_message(
 		new IRCMessage(
-		    Prefix => Configuration->shared->general->sysmsg_prefix,
+		    Prefix => RunLoop->shared_loop->sysmsg_prefix('system'),
 		    Command => ERR_NONICKNAMEGIVEN,
 		    Params => [RunLoop->shared_loop->current_nick,
 			       'No nickname given']));
@@ -337,109 +343,134 @@
     my $this = shift;
     my $multi = RunLoop->shared->multi_server_mode_p;
     my $local_nick = RunLoop->shared_loop->current_nick;
-    map {
-	my $network = $_;
+
+    my $send_channelinfo = sub {
+	my ($network, $ch) = @_;
 	my $global_nick = $network->current_nick;
 	my $global_to_local = sub {
 	    $_[0] eq $global_nick ? $local_nick : $_[0];
 	};
+	my $ch_name = do {
+	    if ($multi) {
+		Multicast::attach($ch->name, $network->network_name);
+	    }
+	    else {
+		$ch->name;
+	    }
+	};
 
-	map {
-	    my $ch = $_;
-	    my $ch_name = do {
-		if ($multi) {
-		    Multicast::attach($ch->name, $network->network_name);
-		}
-		else {
-		    $ch->name;
-		}
-	    };
-
-	    # まずJOIN
+	# まずJOIN
+	$this->send_message(
+	    IRCMessage->new(
+		Prefix => $this->fullname,
+		Command => 'JOIN',
+		Param => $ch_name));
+	# 次にRPL_TOPIC(あれば)
+	if ($ch->topic ne '') {
 	    $this->send_message(
 		IRCMessage->new(
 		    Prefix => $this->fullname,
-		    Command => 'JOIN',
-		    Param => $ch_name));
-	    # 次にRPL_TOPIC(あれば)
-	    if ($ch->topic ne '') {
-		$this->send_message(
-		    IRCMessage->new(
-			Prefix => $this->fullname,
-			Command => RPL_TOPIC,
-			Params => [$local_nick,$ch_name,$ch->topic]));
+		    Command => RPL_TOPIC,
+		    Params => [$local_nick,$ch_name,$ch->topic]));
+	}
+	# 次にRPL_TOPICWHOTIME(あれば)
+	if (defined($ch->topic_who)) {
+	    $this->send_message(
+		IRCMessage->new(
+		    Prefix => $this->fullname,
+		    Command => RPL_TOPICWHOTIME,
+		    Params => [$local_nick,$ch_name,$ch->topic_who,$ch->topic_time]));
+	}
+	# 次にRPL_NAMREPLY
+	my $ch_property_char = do {
+	    if ($ch->switches('s')) {
+		'@';
+	    }
+	    elsif ($ch->switches('p')) {
+		'*';
 	    }
-	    # 次にRPL_TOPICWHOTIME(あれば)
-	    if (defined($ch->topic_who)) {
+	    else {
+		'=';
+	    }
+	};
+	# 余裕を見てnickの列挙部が400バイトを越えたら行を分ける。
+	my $nick_enumeration = '';
+	my $flush_enum_buffer = sub {
+	    if ($nick_enumeration ne '') {
 		$this->send_message(
 		    IRCMessage->new(
 			Prefix => $this->fullname,
-			Command => RPL_TOPICWHOTIME,
-			Params => [$local_nick,$ch_name,$ch->topic_who,$ch->topic_time]));
+			Command => RPL_NAMREPLY,
+			Params => [$local_nick,
+				   $ch_property_char,
+				   $ch_name,
+				   $nick_enumeration]));
+		$nick_enumeration = '';
+	    }
+	};
+	my $append_to_enum_buffer = sub {
+	    my $nick_to_append = shift;
+	    if ($nick_enumeration eq '') {
+		$nick_enumeration = $nick_to_append;
+	    }
+	    else {
+		$nick_enumeration .= ' '.$nick_to_append;
 	    }
-	    # 次にRPL_NAMREPLY
-	    my $ch_property_char = do {
-		if ($ch->switches('s')) {
+	};
+	map {
+	    my $person = $_;
+	    my $mode_char = do {
+		if ($person->has_o) {
 		    '@';
 		}
-		elsif ($ch->switches('p')) {
-		    '*';
-		}
-		else {
-		    '=';
-		}
-	    };
-	    # 余裕を見てnickの列挙部が400バイトを越えたら行を分ける。
-	    my $nick_enumeration = '';
-	    my $flush_enum_buffer = sub {
-		if ($nick_enumeration ne '') {
-		    $this->send_message(
-			IRCMessage->new(
-			    Prefix => $this->fullname,
-			    Command => RPL_NAMREPLY,
-			    Params => [$local_nick,
-				       $ch_property_char,
-				       $ch_name,
-				       $nick_enumeration]));
-		    $nick_enumeration = '';
-		}
-	    };
-	    my $append_to_enum_buffer = sub {
-		my $nick_to_append = shift;
-		if ($nick_enumeration eq '') {
-		    $nick_enumeration = $nick_to_append;
+		elsif ($person->has_v) {
+		    '+';
 		}
 		else {
-		    $nick_enumeration .= ' '.$nick_to_append;
+		    '';
 		}
 	    };
-	    map {
-		my $person = $_;
-		my $mode_char = do {
-		    if ($person->has_o) {
-			'@';
-		    }
-		    elsif ($person->has_v) {
-			'+';
-		    }
-		    else {
-			'';
-		    }
-		};
-		$append_to_enum_buffer->($mode_char . $global_to_local->($person->person->nick));
-		if (length($nick_enumeration) > 400) {
-		    $flush_enum_buffer->();
-		}
-	    } values %{$ch->names};
-	    $flush_enum_buffer->();
-	    # 最後にRPL_ENDOFNAMES
-	    $this->send_message(
-		IRCMessage->new(
-		    Prefix => $this->fullname,
-		    Command => RPL_ENDOFNAMES,
-		    Params => [$local_nick,$ch_name,'End of NAMES list']));
+	    $append_to_enum_buffer->($mode_char . $global_to_local->($person->person->nick));
+	    if (length($nick_enumeration) > 400) {
+		$flush_enum_buffer->();
+	    }
+	} values %{$ch->names};
+	$flush_enum_buffer->();
+	# 最後にRPL_ENDOFNAMES
+	$this->send_message(
+	    IRCMessage->new(
+		Prefix => $this->fullname,
+		Command => RPL_ENDOFNAMES,
+		Params => [$local_nick,$ch_name,'End of NAMES list']));
+    };
+
+    my %channels = map {
+	my $network = $_;
+	map {
+	    my $ch = $_;
+	    (Multicast::attach($ch->name, $network->network_name) =>
+		    [$network, $ch]);
 	} values %{$network->channels};
     } values %{RunLoop->shared_loop->networks};
+
+    # Mask を使って、マッチしたものを出力
+    foreach (Configuration->shared->networks->
+		 fixed_channels('block')->channel('all')) {
+	my $mask = $_;
+	foreach (keys %channels) {
+	    my $ch_name = $_;
+	    if (Mask::match($mask, $ch_name)) {
+		$send_channelinfo->(@{$channels{$ch_name}});
+		delete $channels{$ch_name};
+		last;
+	    }
+	}
+    }
+
+    # のこりを出力
+    map {
+	$send_channelinfo->(@$_);
+    } values %channels;
 }
 
 1;
diff -urN tiarra-20040215/main/IrcIO/Server.pm tiarra-20040223/main/IrcIO/Server.pm
--- tiarra-20040215/main/IrcIO/Server.pm	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/main/IrcIO/Server.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Server.pm,v 1.51 2004/02/14 11:48:20 topia Exp $
+# $Id: Server.pm,v 1.52 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # IrcIO::ServerはIRCサーバーに接続し、IRCメッセージをやり取りするクラスです。
 # このクラスはサーバーからメッセージを受け取ってチャンネル情報や現在のnickなどを保持しますが、
@@ -24,6 +24,7 @@
     my $obj = $class->SUPER::new;
     $obj->{network_name} = $network_name;
     $obj->{current_nick} = ''; # 現在使用中のnick。ログインしていなければ空。
+    $obj->{server_hostname} = ''; # サーバが主張している hostname。こちらもログインしてなければ空。
     $obj->reload_config;
 
     $obj->{logged_in} = 0; # このサーバーへのログインに成功しているかどうか。
@@ -48,6 +49,10 @@
     shift->{current_nick};
 }
 
+sub server_hostname {
+    shift->{server_hostname};
+}
+
 sub channels {
     # @options(省略可能):
     #   'even-if-kicked-out': 既に自分が蹴り出されてゐるチャンネルも返す。この動作は高速である。
@@ -357,6 +362,7 @@
     if ($reply eq RPL_WELCOME) {
 	# 成功した。
 	$this->{current_nick} = $first_msg->param(0);
+	$this->{server_hostname} = $first_msg->prefix;
 	if (!RunLoop->shared->multi_server_mode_p &&
 		RunLoop->shared_loop->current_nick ne $this->{current_nick}) {
 	    RunLoop->shared->broadcast_to_clients(
@@ -429,13 +435,15 @@
 		if (Configuration->shared->networks->always_notify_new_nick ||
 		    $this->{current_nick} ne $local_nick) {
 
+		    my $old_nick = $msg->nick;
 		    RunLoop->shared_loop->broadcast_to_clients(
 			IRCMessage->new(
 			    Command => 'NOTICE',
 			    Params => [$local_nick,
 				       "*** Your global nick in ".
-					   $this->{network_name}.
-					       " is currently '".$this->{current_nick}."'."]));
+					   $this->{network_name}." changed ".
+					       "$old_nick -> ".
+						   $this->{current_nick}."."]));
 		}
 	    } else {
 		RunLoop->shared_loop->set_current_nick($msg->param(0));
diff -urN tiarra-20040215/main/ModuleManager.pm tiarra-20040223/main/ModuleManager.pm
--- tiarra-20040215/main/ModuleManager.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/main/ModuleManager.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: ModuleManager.pm,v 1.13 2004/02/14 11:48:18 topia Exp $
+# $Id: ModuleManager.pm,v 1.14 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # このクラスは全てのTiarraモジュールを管理します。
 # モジュールをロードし、リロードし、破棄するのはこのクラスです。
@@ -126,12 +126,14 @@
     my $deleted_any = @$deleted > 0;
     foreach (@$deleted) {
 	# 削除されたモジュール。
-	# %loaded_modsに古い物が入っているので破棄した上、アンロードする。
+	# %loaded_modsに古い物が入っている場合は破棄した上、アンロードする。
 	$show_msg->("Module ".$_->block_name." will be unloaded.");
-	eval {
-	    $loaded_mods{$_->block_name}->destruct;
-	}; if ($@) {
-	    $show_msg->($@);
+	if (defined $loaded_mods{$_->block_name}) {
+	    eval {
+		$loaded_mods{$_->block_name}->destruct;
+	    }; if ($@) {
+		$show_msg->($@);
+	    }
 	}
 	$this->_unload($_);
     }
@@ -390,6 +392,7 @@
     no strict;
     local(*stab) = eval qq{\*${modname}::};
     my $defined_on;
+    my %showed_modules;
     while (my ($key,$val) = each(%stab)) {
 	local(*entry) = $val;
 	if (defined $entry) {
@@ -409,8 +412,22 @@
 		::debug_printmsg("unload subroutine: $key");
 		undef &entry;
 	    } else {
-		::debug_printmsg("not-unload subroutine: $key, on " .
-				     ($defined_on || '(undefined)'));
+		if (::debug_mode()) {
+		    if (!defined $defined_on) {
+			::printmsg("not-unload subroutine: $key, " .
+				       'defined on (anywhere)');
+		    } else {
+			++$showed_modules{$defined_on};
+			if ($showed_modules{$defined_on} <= 10) {
+			    ::printmsg("not-unload subroutine: $key" .
+					   ", defined on $defined_on");
+			}
+			if ($showed_modules{$defined_on} == 10) {
+			    ::printmsg("not-unload subroutine: omit the rest " .
+					   "of defined on $defined_on...");
+			}
+		    }
+		}
 	    }
 	}
 	if ($key ne "${modname}::" && defined %entry) {
diff -urN tiarra-20040215/main/Multicast.pm tiarra-20040223/main/Multicast.pm
--- tiarra-20040215/main/Multicast.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/main/Multicast.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Multicast.pm,v 1.20 2004/02/14 11:48:18 topia Exp $
+# $Id: Multicast.pm,v 1.22 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # サーバーからクライアントにメッセージが流れるとき、このクラスはフィルタとして
 # ネットワーク名を付加します。
@@ -12,6 +12,7 @@
 use warnings;
 use Configuration;
 use Carp;
+use NumericReply;
 my $runloop = undef; # デフォルトのRunLoopのキャッシュ。
 my $default_network = ''; # デフォルトのネットワーク名のキャッシュ。
 my $separator = ''; # セパレータ記号のキャッシュ。これらはcast_messageが呼ばれる度に更新される。
@@ -188,7 +189,7 @@
     $message->param(0,attach($message->param(0),$sender->network_name));
     $message->param(1,
 		    join(',',
-			 map{ s/^([@+]*)(.+)$/$1.global_to_local($2,$sender)/e; $_; } split(/,/,$message->param(1))));
+			 map{ s/^([\@+]*)(.+)$/$1.global_to_local($2,$sender)/e; $_; } split(/,/,$message->param(1))));
     $message;
 }
 
@@ -208,10 +209,11 @@
 	$message->param(0) eq $global_nick &&
 	$local_nick ne $global_nick) {
 	$sender->send_message(
-	    new IRCMessage(Prefix => Configuration->shared->general->sysmsg_prefix,
-			   Command => 'NOTICE',
-			   Params => [$local_nick,
-				      "*** Your global nick in $to is currently '$global_nick'."]));
+	    new IRCMessage(
+		Prefix => $runloop->sysmsg_prefix(qw(priv system)),
+		Command => 'NOTICE',
+		Params => [$local_nick,
+			   "*** Your global nick in $to is currently '$global_nick'."]));
     }
 
     forward_to_server($message,$to);
@@ -253,11 +255,32 @@
     $message->params->[3] =
 	join(' ',
 	     map {
-		 s/^([@+]*)(.+)$/$1.global_to_local($2,$sender)/e; $_;
+		 s/^([\@+]*)(.+)$/$1.global_to_local($2,$sender)/e; $_;
 	     } split / /,$message->params->[3]);
     $message;
 }
 
+sub _attach_RPL_WHOISCHANNELS {
+    my ($message,$sender) = @_;
+    $message->param(1,global_to_local($message->param(1),$sender));
+    $message->params->[2] =
+	join(' ',
+	     map {
+		 s/^([\@+]*)(.+)$/$1.attach($2, $sender->network_name)/e; $_;
+	     } split / /,$message->params->[2]);
+    $message;
+}
+
+sub _detach_RPL_WHOISCHANNELS {
+    my ($message,$sender) = @_;
+    $message->params->[2] =
+	join(' ',
+	     map {
+		 s/^([\@+]*)(.+)$/$1.detach($2)/e; $_;
+	     } split / /,$message->params->[2]);
+    $message;
+}
+
 my $g2l_cache = {};
 sub _gen_g2l_translator {
     my $index = shift;
@@ -316,35 +339,39 @@
     'SQUERY' => \&_MODE_from_server, # 多分これは鯖からも来るだろうが、良く分からない。
     'TOPIC' => \&_MODE_from_server,
     'NJOIN' => \&_NJOIN_from_server,
-    '301' => _gen_g2l_translator(1), # AWAY
-    '302' => \&_RPL_USERHOST,
-    '303' => \&_RPL_ISON,
-    '311' => _gen_g2l_translator(1), # WHOISUSER
-    '312' => _gen_g2l_translator(1), # WHOISSERVER
-    '313' => _gen_g2l_translator(1), # WHOISOPERATOR
-    '317' => _gen_g2l_translator(1), # WHOISIDLE
-    '318' => _gen_g2l_translator(1), # ENDOFWHOIS
-    '319' => _gen_g2l_translator(1), # WHOISCHANNELS
-    '314' => _gen_g2l_translator(1), # WHOWASUSER
-    '369' => _gen_g2l_translator(1), # ENDOFWHOWAS
-    '322' => _gen_attach_translator(1), # LIST
-    '325' => \&_RPL_INVITING, # UNIQOPIS (INVITINGと同じ処理)
-    '324' => _gen_attach_translator(1), # CHANNELMODEIS
-    '331' => _gen_attach_translator(1), # NOTOPIC
-    '332' => _gen_attach_translator(1), # TOPIC
-    '333' => _gen_attach_translator(1), # TOPICWHOTIME
-    '341' => \&_RPL_INVITING,
-    '346' => _gen_attach_translator(1), # INVITELIST
-    '347' => _gen_attach_translator(1), # ENDOFINVITELIST
-    '348' => _gen_attach_translator(1), # EXCEPTLIST
-    '349' => _gen_attach_translator(1), # ENDOFEXCEPTLIST
-    '352' => \&_RPL_WHOREPLY,
-    '315' => _gen_attach_translator(1), # ENDOFWHO
-    '353' => \&_RPL_NAMREPLY,
-    '366' => _gen_attach_translator(1), # ENDOFNAMES
-    '367' => _gen_attach_translator(1), # BANLIST
-    '368' => _gen_attach_translator(1), # ENDOFBANLIST
+    (RPL_UNIQOPIS) => \&_RPL_INVITING, # UNIQOPIS (INVITINGと同じ処理)
     # TRACE系のリプライはTiarraは関知しない。少なくとも今のところは。
+    do {
+	my $sub = _gen_g2l_translator(1);
+	map {
+	    (NumericReply::fetch_number($_), $sub)
+	} (map {"RPL_$_"}
+	       ((map {"WHOIS$_"} qw(USER SERVER OPERATOR IDLE)),
+		(map {"ENDOF$_"} qw(WHOIS WHOWAS)),
+		qw(WHOWASUSER AWAY)))},
+    do {
+	my $sub = _gen_attach_translator(1);
+	map {
+	    (NumericReply::fetch_number($_), $sub);
+	} ((map {"RPL_$_"}
+		((map { ("$_", "ENDOF$_"); } qw(INVITELIST EXCEPTLIST BANLIST)),
+		 (map {"ENDOF$_"} qw(WHO NAMES)),
+		 qw(LIST CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME))),
+	   qw(ERR_TOOMANYCHANNELS))},
+    do {
+	no strict 'refs';
+	map {
+	    my $funcname = "_$_";
+	    (NumericReply::fetch_number($_), \&$funcname)
+	} (map {"RPL_$_"}
+	       qw(USERHOST ISON INVITING WHOREPLY NAMREPLY))},
+    do {
+	no strict 'refs';
+	map {
+	    my $funcname = "_attach_$_";
+	    (NumericReply::fetch_number($_), \&$funcname)
+	} (map {"RPL_$_"}
+	       qw(WHOISCHANNELS))},
 };
 
 my $client_sent = {
@@ -394,23 +421,24 @@
     'SERVER' => undef,
     'WALLOPS' => \&_MODE_from_client, # クライアントからWALLOPSを発行出来るのかどうかは知らないが…
     # 以下リプライ。これはdetach_network_nameの為だけにある。
-    '322' => _gen_detach_translator(1), # LIST
-    '325' => _gen_detach_translator(1), # UNIQOPIS (INVITINGと同じ処理)
-    '324' => _gen_detach_translator(1), # CHANNELMODEIS
-    '331' => _gen_detach_translator(1), # NOTOPIC
-    '332' => _gen_detach_translator(1), # TOPIC
-    '333' => _gen_detach_translator(1), # TOPICWHOTIME
-    '341' => _gen_detach_translator(1), # INVITING
-    '346' => _gen_detach_translator(1), # INVITELIST
-    '347' => _gen_detach_translator(1), # ENDOFINVITELIST
-    '348' => _gen_detach_translator(1), # EXCEPTLIST
-    '349' => _gen_detach_translator(1), # ENDOFEXCEPTLIST
-    '352' => _gen_detach_translator(1), # WHOREPLY
-    '315' => _gen_detach_translator(1), # ENDOFWHO
-    '353' => _gen_detach_translator(2), # NAMREPLY
-    '366' => _gen_detach_translator(1), # ENDOFNAMES
-    '367' => _gen_detach_translator(1), # BANLIST
-    '368' => _gen_detach_translator(1), # ENDOFBANLIST
+    (RPL_NAMREPLY) => _gen_detach_translator(2),
+    do {
+	my $sub = _gen_detach_translator(1);
+	map {
+	    (NumericReply::fetch_number($_), $sub)
+	} ((map {"RPL_$_"}
+		((map { ("$_", "ENDOF$_"); } qw(INVITELIST EXCEPTLIST BANLIST)),
+		 (map {"ENDOF$_"} qw(WHO NAMES)),
+		 qw(LIST CHANNELMODEIS NOTOPIC TOPIC TOPICWHOTIME),
+		 qw(INVITING UNIQOPIS WHOREPLY))),
+	   qw(ERR_TOOMANYCHANNELS))},
+    do {
+	no strict 'refs';
+	map {
+	    my $funcname = "_detach_$_";
+	    (NumericReply::fetch_number($_), \&$funcname)
+	} (map {"RPL_$_"}
+	       qw(WHOISCHANNELS))},
 };
 
 
diff -urN tiarra-20040215/main/RunLoop.pm tiarra-20040223/main/RunLoop.pm
--- tiarra-20040215/main/RunLoop.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/main/RunLoop.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: RunLoop.pm,v 1.51 2004/02/14 11:48:19 topia Exp $
+# $Id: RunLoop.pm,v 1.53 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 # このクラスはTiarraのメインループを実装します。
 # select()を実行し、サーバーやクライアントとのI/Oを行うのはこのクラスです。
@@ -19,6 +19,7 @@
 use IrcIO::Server;
 use IrcIO::Client;
 use Unicode::Japanese;
+use Mask;
 use ModuleManager;
 use Multicast;
 use Timer;
@@ -191,6 +192,24 @@
     undef;
 }
 
+sub sysmsg_prefix {
+    my ($this,$purpose,$category) = @_;
+    $category = (caller)[0] . (defined $category ? "::$category" : '');
+    # $purpose は、この関数で得た prefix を何に使うかを示す。
+    #     いまのところ system(NumericReply など)/priv/channel
+    # $category は、大まかなカテゴリ。
+    #     いまのところ log/system/notify があるが、
+    #     どうしようか決めかねている…。
+
+    if (Mask::match_array([
+	Configuration->shared_conf->general->
+	    sysmsg_prefix_use_masks('block')->get($purpose, 'all')], $category)) {
+	Configuration->shared->general->sysmsg_prefix;
+    } else {
+	undef
+    }
+}
+
 sub _multi_server_mode_changed {
     my $this = shift;
     # 一旦全てのチャンネルについてPARTを発行した後、
@@ -363,7 +382,7 @@
 	$this->_rejoin_all_channels($network);
 	$this->broadcast_to_clients(
 	    IRCMessage->new(
-		Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+		Prefix => $this->sysmsg_prefix(qw(priv system)),
 		Command => 'NOTICE',
 		Params => [$this->current_nick,
 			   '*** The connection has been revived between '.$network->network_name.'.']));
@@ -371,7 +390,7 @@
     elsif ($event eq 'disconnected') {
 	$this->broadcast_to_clients(
 	    IRCMessage->new(
-		Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+		Prefix => $this->sysmsg_prefix(qw(priv system)),
 		Command => 'NOTICE',
 		Params => [$this->current_nick,
 			   '*** The connection has been broken between '.$network->network_name.'.']));
@@ -384,7 +403,7 @@
 	$this->_rejoin_all_channels($network);
 
 	my $msg = IRCMessage->new(
-	    Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+	    Prefix => $this->sysmsg_prefix(qw(channel system)),
 	    Command => 'NOTICE',
 	    Params => ['', # チャンネル名は後で設定。
 		       '*** The connection has been revived between '.$network->network_name.'.']);
@@ -399,7 +418,7 @@
     }
     elsif ($event eq 'disconnected') {
 	my $msg = IRCMessage->new(
-	    Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+	    Prefix => $this->sysmsg_prefix(qw(channel system)),
 	    Command => 'NOTICE',
 	    Params => ['', # チャンネル名は後で設定。
 		       '*** The connection has been broken between '.$network->network_name.'.']);
@@ -838,7 +857,7 @@
 		$network->send_message(
 		    IRCMessage->new(
 			Command => 'PING',
-			Param => $network->host));
+			Param => $network->server_hostname));
 
 		my $cntr = $network->remark('pong-drop-counter');
 		if (defined $cntr) {
@@ -1247,7 +1266,7 @@
 	    $this->broadcast_to_clients(
 		map {
 		    IRCMessage->new(
-			Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+			Prefix => $this->sysmsg_prefix(qw(priv notify)),
 			Command => 'NOTICE',
 			Params => [$this->current_nick,
 				   "*** $_"]);
diff -urN tiarra-20040215/main/TiarraDoc.pm tiarra-20040223/main/TiarraDoc.pm
--- tiarra-20040215/main/TiarraDoc.pm	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/main/TiarraDoc.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # ------------------------------------------------------------------------
-# $Id: TiarraDoc.pm,v 1.1 2003/08/04 09:29:20 admin Exp $
+# $Id: TiarraDoc.pm,v 1.2 2004/02/23 02:46:18 topia Exp $
 # ------------------------------------------------------------------------
 # tiarra-docのパーサとトランスレータ群。
 # ------------------------------------------------------------------------
@@ -289,6 +289,7 @@
     # infoヘッダの内容を出力。無ければエラー。
     # ただしinfo-is-omittedが定義されていて真であれば出力しない。
     my $indent = ' ' x $indent_level;
+    my $block_indent = '';
     my $info = $pod->header->{info};
     if (defined $info) {
 	if (!$pod->header->{'info-is-omitted'}) {
@@ -332,24 +333,33 @@
 
 	    die "$errstr\n$list";
 	};
-	
+
 	$result .= $indent . do {
 	    if ($line eq '') {
 		'';
 	    }
 	    elsif ($line =~ m/^\s*#/) {
 		(my $stripped = $line) =~ s/^\s*//;
-		$stripped;
+		"$block_indent$stripped";
 	    }
-	    elsif ($line =~ m/^(.+?)\s*:\s*(.+)$/) {
+	    elsif ($line =~ m/^(.+?)\s*:\s*(.*)$/) {
 		my ($key,$value) = ($1,$2);
 		if ($key =~ s/^-//) {
-		    "#$key: $value";
+		    "$block_indent#$key: $value";
 		}
 		else {
-		    "$key: $value";
+		    "$block_indent$key: $value";
 		}
 	    }
+	    elsif ($line =~ m/^(.+?)\s*{\s*$/) {
+		$_ = "$block_indent$1 {";
+		$block_indent .= ' ' x 2;
+		$_;
+	    }
+	    elsif ($line =~ m/^}\s*$/) {
+		substr($block_indent, 0, 2) = '';
+		"$block_indent}";
+	    }
 	    else {
 		$error->('illegal line');
 	    }
diff -urN tiarra-20040215/module/Auto/Alias.pm tiarra-20040223/module/Auto/Alias.pm
--- tiarra-20040215/module/Auto/Alias.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Alias.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Alias.pm,v 1.9 2003/10/19 12:30:23 topia Exp $
+# $Id: Alias.pm,v 1.10 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # $Clovery: tiarra/module/Auto/Alias.pm,v 1.13 2003/07/27 07:17:07 topia Exp $
 package Auto::Alias;
@@ -79,3 +79,53 @@
 }
 
 1;
+
+=pod
+info: ユーザエイリアス情報の管理を行ないます。
+default: off
+
+# エイリアスは基本的にname,userの二つのフィールドから成っており、
+# それぞれユーザー名、ユーザーマスクを表します。
+
+# エイリアス定義ファイルのパスと、そのエンコーディング。
+# このファイルは次のようなフォーマットである。
+# 1. それぞれの行は「<キー>: <値>」の形式である。
+# 2. 空の行で、各ユーザーを区切る。
+# 3. <値>はカンマで区切られて複数の値とされる。
+#
+# エイリアス定義ファイルの例:
+#
+# name: sample
+# user: *!*sample@*.sample.net
+#
+# name: sample2,[sample2]
+# user: *!sample2@*.sample.net,*!sample2@*.sample2.net
+#
+alias: alias.txt
+alias-encoding: euc
+
+# この発言をした人のエイリアスが登録されていれば、それをprivで送る。
+confirm: エイリアス確認
+
+# 「<addで指定したキーワード> user *!*user@*.user.net」のようにして情報を追加。
+# 発言をした人のエイリアスが未登録だった場合は、userのみ受け付けて新規追加とする。
+add: エイリアス追加
+
+# 「<removeで指定したキーワード> name ユーザー」のようにして情報を削除。
+# userを全て削除されたエイリアスは他の情報(name等)も含めて消滅する。
+remove: エイリアス削除
+
+# メッセージが追加されたときの反応を指定します。
+# ランダムなメッセージを発言する際のフォーマットを指定します。
+# エイリアス置換が有効です。#(nick.now)、#(channel)は
+# それぞれ相手のnick、チャンネル名に置換されます。
+# #(key)、#(value)は、追加されたキーと値に置換されます。
+added-format: #(name|nick.now): エイリアス #(key) に #(value) を追加しました。
+
+# メッセージが削除されたときの反応を指定します。
+# added-formatで指定できるものと同じです。
+removed-format: #(name|nick.now): エイリアス #(key) から #(value) を削除しました。
+
+# エイリアスの追加や削除が許されている人。省略された場合は「*!*@*」と見做される。
+modifier: *!*@*
+=cut
diff -urN tiarra-20040215/module/Auto/Answer.pm tiarra-20040223/module/Auto/Answer.pm
--- tiarra-20040215/module/Auto/Answer.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Answer.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Answer.pm,v 1.3 2003/02/13 05:26:02 topia Exp $
+# $Id: Answer.pm,v 1.4 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # $Clovery: tiarra/module/Auto/Answer.pm,v 1.3 2003/02/13 04:38:56 topia Exp $
 package Auto::Answer;
@@ -15,13 +15,13 @@
   my ($this,$msg,$sender) = @_;
   my @result = ($msg);
 
-  my ($get_ch_name,undef,undef,$reply_anywhere)
-    = Auto::Utils::generate_reply_closures($msg,$sender,\@result);
-
   # サーバーからのメッセージか？
   if ($sender->isa('IrcIO::Server')) {
     # PRIVMSGか？
     if ($msg->command eq 'PRIVMSG') {
+      my ($get_ch_name,undef,undef,$reply_anywhere)
+	= Auto::Utils::generate_reply_closures($msg,$sender,\@result);
+
       # replyに設定されたものの中から、一致しているものがあれば発言。
       # 一致にはMask::matchを用いる。
       foreach ($this->config->reply('all')) {
@@ -38,3 +38,20 @@
 }
 
 1;
+
+=pod
+info: 特定の発言に反応して対応する発言をする。
+default: off
+
+# Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+
+# 反応する発言と、それに対する返事を定義します。
+# エイリアス置換が有効です。#(nick.now)と$(channel)はそれぞれ
+# 相手の現在のnickとチャンネル名に置換されます。
+#
+# 書式: <反応する発言のマスク> <それに対する返事>
+# 例:
+-reply: こんにちは* こんにちは、#(name|nick.now)さん。
+# この例では誰かが「こんにちは」で始まる発言をすると、
+# 発言した人のエイリアスを参照して「こんにちは、○○さん。」のように発言します。
+=cut
diff -urN tiarra-20040215/module/Auto/ChannelWithoutOper.pm tiarra-20040223/module/Auto/ChannelWithoutOper.pm
--- tiarra-20040215/module/Auto/ChannelWithoutOper.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/ChannelWithoutOper.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: ChannelWithoutOper.pm,v 1.2 2003/02/06 11:51:45 admin Exp $
+# $Id: ChannelWithoutOper.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Auto::ChannelWithoutOper;
 use strict;
@@ -84,3 +84,14 @@
 
 1;
 
+=pod
+info: チャンネルオペレータ権限がなくなってしまったときに発言する。
+default: off
+
+# +で始まらない特定のチャンネルで、+aモードでも+rモードでもないのに
+# 誰もチャンネルオペレータ権限を持っていない状態になっている時、
+# そこに誰かがJOINする度に特定のメッセージを発言するモジュールです。
+
+# 書式: <チャンネル名> <メッセージ>
+-channel: #IRC談話室@ircnet なると消失しました。
+=cut
diff -urN tiarra-20040215/module/Auto/Joined.pm tiarra-20040223/module/Auto/Joined.pm
--- tiarra-20040215/module/Auto/Joined.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Joined.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Joined.pm,v 1.1 2003/04/05 08:45:28 admin Exp $
+# $Id: Joined.pm,v 1.2 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Auto::Joined;
 use strict;
@@ -55,3 +55,15 @@
 
 1;
 
+=pod
+info: 特定のチャンネルに誰かがJOINする度に特定のメッセージを発言する。
+default: off
+
+# Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+
+# 発言を行なうチャンネルと、その内容を定義します。
+# #(nick.now)と$(channel)は、それぞれ相手の現在のnickとチャンネル名に置換されます。
+#
+# 書式: <チャンネル名> <発言内容>
+-channel: #チャンネル@ircnet   「#ちゃんねる」に移転しました。
+=cut
diff -urN tiarra-20040215/module/Auto/MesMail.pm tiarra-20040223/module/Auto/MesMail.pm
--- tiarra-20040215/module/Auto/MesMail.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/MesMail.pm	2004-02-23 11:47:37.000000000 +0900
@@ -259,3 +259,108 @@
 }
 
 1;
+
+=pod
+info: 伝言をメールとして送信する。
+default: off
+
+# メールアドレスはエイリアスの mail を参照します。
+
+# Fromアドレス。[default: OSのユーザ名]
+from: example1@example.jp
+
+# 送信用のキーワード [default: mesmail_send]
+send: 速達伝言
+
+# 使用を許可する人&チャンネルのマスク。
+# 例はTiarraモード時。 [default: なし]
+mask: * +*!*@*
+# [plum-mode] mask: +*!*@*
+
+# maskで拒否されたときのメッセージ [default: なし]
+deny: 伝言したくない。
+
+# 一度に送れる宛先の量 [default: 無制限]
+max-send-address: 5
+
+# 宛先を探すエイリアスエントリ [default: なし]
+alias-key: name
+alias-key: nick
+
+# 宛先の人を判別出来なかったときのメッセージ [default: なし]
+unknown: #(who)さんと言うのは誰ですか?
+
+# メールの日付形式
+date: %H:%M:%S
+
+# エイリアスは見付かったけれどメールアドレスが登録されていなかったときのメッセージ。 [default: なし]
+-none-address: #(who)さんはアドレスを登録していません。
+
+# SMTPのホスト [default: localhost]
+-smtphost: localhost
+
+# SMTPのポート [default: smtp(25)]
+-smtpport: 25
+
+# SMTPで自ホストのFQDN [default: localhost]
+-smtpfqdn: localhost
+
+# 送信するメールの既定件名(エイリアス使用不可) [default: Message from IRC]
+-subject: Message from IRC
+
+# 送信するメールの本文 [default: #(date) << #(from.name|from.nick|from.nick.now) >> #(message)]
+-format: #(date)に#(from.name|from.nick|from.nick.now)さんから#(message)という伝言です。
+
+# 送信したときのメッセージ。 [default: なし]
+accept: #(who)さんに#(message)と伝言しておきました。
+
+# ---- POP before SMTP の指定 ----
+# POP before SMTPを使う。 [default: no]
+-use-pop3: yes
+
+# POP before SMTPのタイムアウト時間(分)。分からない場合は指定しなくて良い。 [default: 0]
+-pop3-expire: 4
+
+# POPのホスト。 [default: localhost]
+-pop3host: localhost
+
+# POPのポート。 [default: pop(110)]
+-pop3port: 110
+
+# POPのユーザ [default: OSのユーザ名]
+-pop3user: example1
+
+# POPのパスワード [default: 空パスワード('')]
+-pop3pass: test-password
+
+# ---- エラーメッセージの設定 ----
+
+# 一般エラー。
+# error-[state] と言う形式で詳細エラーメッセージを指定できる。
+# [state]は、
+#    * mailfrom(メールの送信者を指定しようとしてエラー)
+#    * rcptto(メールの送信先を指定しようとしてエラー)
+#    * norcptto(メールの送信先が全部無くなった)
+#    * data(メールの中身を送信しようとしてエラー)
+#    * finish(メールの中身を送信したらエラー)
+# がある。特に欲しくなければerror-[state]は指定しなくても構わない。
+# メッセージを出したくないなら中身の無いエントリを指定すれば良い。
+# error-[state]が指定されてない場合は代わりに error を使う。 [default: 未定義]
+
+-error-rcptto:
+-error-norcptto: #(who)さんには送れませんでした。送信できるメールアドレスがありません。
+-error-data: メールが送信できません。DATAコマンドに失敗しました。#(line;サーバ応答:%s|;)
+-error: メール送信エラーです。#(line;サーバ応答:%s|;)#(state; on %s|;)
+
+# 致命的なエラー。メールに個別なエラーではないので送信者(のprefix)毎に1メッセージ送られる。
+# fatalerror-[state]
+# [state]:
+#    * first(接続エラー)
+#    * helo(SMTPセッションを開始出来ない)
+# がある。特に欲しくなければfatalerror-[state]は指定しなくても構わない。
+# メッセージを出したくないなら中身の無いエントリを指定すれば良い。
+# fatalerror-[state]が指定されてない場合は代わりに fatalerror を使う。 [default: 未定義]
+
+-fatalerror-first: SMTPサーバに接続できません。
+-fatalerror: SMTPセッションで致命的なエラーがありました。#(line; サーバ応答:%s|;)#(state; on %s|;)
+=cut
diff -urN tiarra-20040215/module/Auto/Oper.pm tiarra-20040223/module/Auto/Oper.pm
--- tiarra-20040215/module/Auto/Oper.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Oper.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Oper.pm,v 1.10 2003/07/31 07:34:13 topia Exp $
+# $Id: Oper.pm,v 1.11 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Auto::Oper;
 use strict;
@@ -70,3 +70,63 @@
 }
 
 1;
+
+=pod
+info: 特定の文字列を発言した人を+oする。
+default: off
+
+# Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+
+# +oを要求する文字列(マスク)を指定します。
+request: なると寄越せ
+
+# チャンネルオペレータ権限を要求した人と要求されたチャンネルが
+# ここで指定したマスクに一致しなかった場合は
+# denyで指定した文字列を発言し、+oをやめます。
+# 省略された場合は誰にも+oしません。
+# 書式は「チャンネル 発言者」です。
+# マッチングのアルゴリズムは次の通りです。
+# 1. チャンネル名にマッチするmask定義を全て集める
+# 2. 集まった定義の発言者マスクを、定義された順にカンマで結合する
+# 3. そのようにして生成されたマスクで発言者のマッチングを行ない、結果を+o可能性とする。
+# 例1:
+# mask: *@2ch* *!*@*
+# mask: #*@ircnet* *!*@*.hoge.jp
+# この例ではネットワーク 2ch の全てのチャンネルで誰にでも +o し、
+# ネットワーク ircnet の # で始まる全てのチャンネルでホスト名 *.hoge.jp の人に+oします。
+# #*@ircnetだと「#hoge@ircnet:*.jp」などにマッチしなくなります。
+# 例2:
+# mask: #hoge@ircnet -*!*@*,+*!*@*.hoge.jp
+# mask: *            +*!*@*
+# 基本的に全てのチャンネルで誰にでも +o するが、例外的に#hoge@ircnetでは
+# ホスト名 *.hoge.jp の人にしか +o しない。
+# この順序を上下逆にすると、全てのチャンネルで全ての人を +o する事になります。
+# 何故なら最初の* +*!*@*が全ての人にマッチするからです。
+mask: * *!*@*
+
+# +oを要求した人を実際に+oする時、ここで指定した発言をしてから+oします。
+# #(name|nick)のようなエイリアス置換を行います。
+# エイリアス以外でも、#(nick.now)を相手のnickに、#(channel)を
+# そのチャンネル名にそれぞれ置換します。
+message: 了解
+
+# +oを要求されたが+oすべき相手ではなかった場合の発言。
+# 省略されたら何も喋りません。
+deny: 断わる
+
+# +oを要求されたが相手は既にチャンネルオペレータ権限を持っていた場合の発言。
+# 省略されたらdenyに設定されたものを使います。
+oper: 既に@を持っている
+
+# +oを要求されたが自分はチャンネルオペレータ権限を持っていなかった場合の発言。
+# 省略されたらdenyに設定されたものを使います。
+not-oper: @が無い
+
+# チャンネルに対してでなく自分に対して+oの要求を行なった場合の発言。
+# 省略されたらdenyに設定されたものを使います。
+private: チャンネルで要求せよ
+
+# チャンネルの外から+oを要求された場合の発言。+nチャンネルでは起こりません。
+# 省略されたらdenyに設定されたものを使います。
+out: チャンネルに入っていない
+=cut
diff -urN tiarra-20040215/module/Auto/Random.pm tiarra-20040223/module/Auto/Random.pm
--- tiarra-20040215/module/Auto/Random.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Random.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Random.pm,v 1.6 2003/07/31 07:34:13 topia Exp $
+# $Id: Random.pm,v 1.7 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # $Clovery: tiarra/module/Auto/Random.pm,v 1.12 2003/07/27 07:29:22 topia Exp $
 package Auto::Random;
@@ -123,3 +123,64 @@
 }
 
 1;
+
+=pod
+info: 特定の発言に反応してランダムな発言をします。
+default: off
+
+# Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+
+# 使用するブロックの定義。
+blocks: wimikuji
+
+wimikuji {
+  # ランダムに発言するメッセージの書かれたファイルと、その文字コードを指定します。
+  # ファイルの中では一行に一つのメッセージを書いて下さい。
+  file: random.txt
+  file-encoding: euc
+
+  # 反応する発言を表すマスクを指定します。
+  request: ゐみくじ
+
+  # メッセージの登録数を返答するキーワードを指定します。
+  count-query: ゐみくじ登録数
+
+  # メッセージの登録数を返答するときの反応を指定します。
+  # formatで指定できるものと同じです。#(count)は登録数になります。
+  count-format: ゐみくじは#(count)件登録されています。
+
+  # ランダムなメッセージを発言する際のフォーマットを指定します。
+  # エイリアス置換が有効です。#(message)、#(nick.now)、#(channel)は
+  # それぞれメッセージ内容、相手のnick、チャンネル名に置換されます。
+  # 何も登録されていないときのために、#(message|;無登録)のように指定すると良いでしょう。
+  format: #(name|nick.now)の運命は#(message)
+
+  # 反応する人のマスク。
+  mask: * *!*@*
+  # plum: mask: *!*@*
+
+  # メッセージが追加されたときの反応を指定します。
+  # formatで指定できるものと同じです。#(message)は追加されたメッセージになります。
+  added-format: #(name|nick.now): ゐみくじ #(message) を追加しました。
+
+  # メッセージが削除されたときの反応を指定します。
+  # formatで指定できるものと同じです。#(message)は削除されたメッセージになります。
+  removed-format: #(name|nick.now): ゐみくじ #(message) を削除しました。
+
+  # 発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。
+  rate: 100
+
+  # メッセージを追加するキーワードを指定します。
+  # ここで指定したキーワードを発言すると、新しいメッセージを追加します。
+  # 実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。
+  add: ゐみくじ追加
+
+  # メッセージを削除するキーワードを指定します。
+  # 実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。
+  remove: ゐみくじ削除
+
+  # addとremoveを許可する人。省略された場合は誰も変更できません。
+  modifier: * *!*@*
+  # plum: modifier: *!*@*
+}
+=cut
diff -urN tiarra-20040215/module/Auto/Reply.pm tiarra-20040223/module/Auto/Reply.pm
--- tiarra-20040215/module/Auto/Reply.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Reply.pm	2004-02-23 11:47:37.000000000 +0900
@@ -133,9 +133,11 @@
 	    }
 
 	    # match
-	    my $key = (_search($block, $msg->param(1), 1, $block->{rate}))[0];
-	    if (defined $key) {
-		$reply_anywhere->($block->{database}->get_value_random($key));
+	    if (Mask::match_deep_chan($block->{mask}, $msg->prefix, $get_full_ch_name->())) {
+		my $key = (_search($block, $msg->param(1), 1, $block->{rate}))[0];
+		if (defined $key) {
+		    $reply_anywhere->($block->{database}->get_value_random($key));
+		}
 	    }
 	}
     }
@@ -170,3 +172,69 @@
 }
 
 1;
+
+=pod
+info: 特定の発言に反応して発言をします。
+default: off
+
+# Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+
+# 使用するブロックの定義。
+blocks: std
+
+std {
+  # データファイルと文字コードを指定します。
+  # ファイルの中では一行に一つの"反応:メッセージ"を書いて下さい。
+  file: reply.txt
+  file-encoding: euc
+
+  # 反応チェックを行うキーワードを指定します。
+  # 実際の指定方法は、「<requestで指定したキーワード> <チェックしたい発言>」です。
+  request: 反応チェック
+
+  # request に反応するときのフォーマットを指定します。
+  # #(key) がキーワード、 #(message) が発言に置換されます。
+  reply-format: 「#(key)」という発言に「#(message)」と反応します。
+
+  # request に反応する最大個数を指定します。
+  # あまり大きな値を指定すると、アタックが可能になったり、ログが流れて邪魔なので注意してください。
+  max-reply: 5
+
+  # メッセージの登録数を返答するキーワードを指定します。
+  count-query: 反応登録数
+
+  # メッセージの登録数を返答するときの反応を指定します。
+  # formatで指定できるものと同じです。#(count)は登録数になります。
+  count-format: 反応は#(count)件登録されています。
+
+  # 反応する人のマスク。
+  mask: * *!*@*
+  # plum: mask: *!*@*
+
+  # 反応が追加されたときの反応を指定します。
+  # formatで指定できるものと同じです。#(message)は追加されたメッセージになります。
+  added-format: #(name|nick.now): #(key) に対する反応 #(message) を追加しました。
+
+  # メッセージが削除されたときの反応を指定します。
+  # formatで指定できるものと同じです。#(message)は削除されたメッセージになります。
+  removed-format: #(name|nick.now): #(key) #(message;に対する反応 %s|;) を #(count) 件削除しました。
+
+  # 発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。
+  rate: 100
+
+  # メッセージを追加するキーワードを指定します。
+  # ここで指定したキーワードを発言すると、新しいメッセージを追加します。
+  # 実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。
+  add: 反応追加
+
+  # メッセージを削除するキーワードを指定します。
+  # 実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。
+  remove: 反応削除
+
+  # addとremoveを許可する人。省略された場合は「*!*@*」と見做します。
+  modifier: *!*@*
+
+  # 正規表現拡張を許可するか。省略された場合は許可します。
+  use-re: 1
+}
+=cut
diff -urN tiarra-20040215/module/Auto/Response.pm tiarra-20040223/module/Auto/Response.pm
--- tiarra-20040215/module/Auto/Response.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Auto/Response.pm	2004-02-23 11:47:37.000000000 +0900
@@ -55,3 +55,35 @@
 }
 
 1;
+
+=pod
+info: データファイルの指定にしたがって反応する。
+default: off
+
+# 大量の反応データを定義するのに向いています。
+
+# データファイルのフォーマット
+# | pattern: re:^(こん(に)?ちは)
+# | rate: 90
+# | mask: * *!*@*
+# | #plum: mask: *!*@*
+# | response: こんにちは。
+# | response: いらっしゃいませ。
+# |
+# | pattern: おやすみ
+# | rate: 20
+# | response: おやすみなさい。
+# patternは一行しか書けません。(手抜き
+# maskもrateも省略できます。省略した場合はmaskは全員、rateは100となります。
+# responseは複数書いておけばランダムに選択されます。
+
+# データファイル
+file: response.txt
+
+# 文字コード
+charset: euc
+
+# 使用を許可する人&チャンネルのマスク。
+mask: * *!*@*
+# plum: mask: +*!*@*
+=cut
diff -urN tiarra-20040215/module/CTCP/ClientInfo.pm tiarra-20040223/module/CTCP/ClientInfo.pm
--- tiarra-20040215/module/CTCP/ClientInfo.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/CTCP/ClientInfo.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: ClientInfo.pm,v 1.2 2003/03/23 07:00:19 topia Exp $
+# $Id: ClientInfo.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # BulletinBoardのctcp-clientinfo-で始まる値を探し、それをCLIENTINFOとして応答する。
 # -----------------------------------------------------------------------------
@@ -50,3 +50,11 @@
 }
 
 1;
+
+=pod
+info: CTCP CLIENTINFOに応答する。
+default: off
+
+# CTCP::Versionのintervalと同じ。
+interval: 3
+=cut
diff -urN tiarra-20040215/module/CTCP/Ping.pm tiarra-20040223/module/CTCP/Ping.pm
--- tiarra-20040215/module/CTCP/Ping.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/CTCP/Ping.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Ping.pm,v 1.2 2003/03/23 07:00:19 topia Exp $
+# $Id: Ping.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package CTCP::Ping;
 use strict;
@@ -40,3 +40,11 @@
 }
 
 1;
+
+=pod
+info: CTCP PINGに応答する。
+default: off
+
+# CTCP::Versionのintervalと同じ。
+interval: 3
+=cut
diff -urN tiarra-20040215/module/CTCP/Time.pm tiarra-20040223/module/CTCP/Time.pm
--- tiarra-20040215/module/CTCP/Time.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/CTCP/Time.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Time.pm,v 1.2 2003/03/23 07:00:19 topia Exp $
+# $Id: Time.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package CTCP::Time;
 use strict;
@@ -42,3 +42,11 @@
 }
 
 1;
+
+=pod
+info: CTCP TIMEに応答する。
+default: off
+
+# CTCP::Versionのintervalと同じ。
+interval: 3
+=cut
diff -urN tiarra-20040215/module/CTCP/UserInfo.pm tiarra-20040223/module/CTCP/UserInfo.pm
--- tiarra-20040215/module/CTCP/UserInfo.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/CTCP/UserInfo.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: UserInfo.pm,v 1.2 2003/03/23 07:00:19 topia Exp $
+# $Id: UserInfo.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package CTCP::UserInfo;
 use strict;
@@ -40,3 +40,14 @@
 }
 
 1;
+
+=pod
+info: CTCP USERINFOに応答する。
+default: off
+
+# CTCP::Versionのintervalと同じ。
+interval: 3
+
+# USERINFOとして返すメッセージ。
+message: テスト
+=cut
diff -urN tiarra-20040215/module/CTCP/Version.pm tiarra-20040223/module/CTCP/Version.pm
--- tiarra-20040215/module/CTCP/Version.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/CTCP/Version.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Version.pm,v 1.2 2003/03/23 07:00:19 topia Exp $
+# $Id: Version.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # CTCP flood対策のため、VERSION、USERINFO等は一度反応する度に
 # IrcIO::Serverに「last-ctcp-replied => 反応時刻」というremarkを付ける。
@@ -44,3 +44,18 @@
 }
 
 1;
+
+=pod
+info: CTCP VERSIONに応答する。
+default: on
+
+# 連続したCTCPリクエストに対する応答の間隔。単位は秒。
+# 例えば3秒に設定した場合、一度応答してから3秒間は
+# CTCPに一切応答しなくなる。デフォルトは3。
+#
+# なお、CTCP受信時刻の記録は、全てのCTCPモジュールで共有される。
+# 例えばCTCP VERSIONを送った直後にCTCP CLIENTINFOを送ったとしても、
+# CTCP::ClientInfoのintervalで設定された時間を過ぎていなければ
+# 後者は応答しない。
+interval: 3
+=cut
diff -urN tiarra-20040215/module/Channel/Freeze.pm tiarra-20040223/module/Channel/Freeze.pm
--- tiarra-20040215/module/Channel/Freeze.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Freeze.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,7 +1,7 @@
 # -----------------------------------------------------------------------------
-# $Id: Freeze.pm,v 1.4 2004/02/14 11:48:20 topia Exp $
+# $Id: Freeze.pm,v 1.6 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
-# このモジュールは再起動しても凍結設定を失はないやうにする爲、
+# このモジュールは再起動しても凍結設定を失なわないようにする為、
 # 設定をBulletinBoardのfrost-channelsに保存します。
 # -----------------------------------------------------------------------------
 package Channel::Freeze;
@@ -12,7 +12,6 @@
 use Timer;
 use BulletinBoard;
 use Mask;
-use Configuration;
 
 sub new {
     my $class = shift;
@@ -35,12 +34,12 @@
 sub set_timer_if_required {
     my $this = shift;
     if (defined $this->{reminder_timer}) {
-	# 既にタイマーが入つてゐる。
+	# 既にタイマーが入っている。
 	return;
     }
 
     if (!$this->config->reminder_interval) {
-	# 報告しないやうに設定されてゐる。
+	# 報告しないやうに設定されている。
 	return;
     }
 
@@ -71,7 +70,7 @@
 	# 報告
 	RunLoop->shared->broadcast_to_clients(
 	    IRCMessage->new(
-		Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+		Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(priv system)),
 		Command => 'NOTICE',
 		Params => [
 		    RunLoop->shared->current_nick,
@@ -90,7 +89,7 @@
 	    my $notice = shift;
 	    RunLoop->shared->broadcast_to_clients(
 		IRCMessage->new(
-		    Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+		    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(priv system)),
 		    Command => 'NOTICE',
 		    Params => [
 			RunLoop->shared->current_nick,
@@ -148,24 +147,15 @@
 
 sub freeze {
     # 今囘のfreezeの呼出しでフリーズされたチャンネル名の配列を返す。
-    my ($this, $ch_full) = @_;
+    my ($this, $ch_mask) = @_;
 
-    if (!defined $ch_full) {
+    if (!defined $ch_mask) {
 	# リスト表示
 	$this->notify_list_of_frost_channels;
 	return ();
     }
 
-    if ($ch_full =~ m/,/) {
-	# カンマで分割して再歸。
-	return map {
-	    $this->freeze($_);
-	} split /\s*,\s*/,$ch_full;
-    }
-    
-    $ch_full = &normalize($ch_full);
-
-    if (defined $ch_full) {
+    if (defined $ch_mask) {
 	my $board = BulletinBoard->shared;
 	my $channels = $board->frost_channels;
 	
@@ -174,15 +164,26 @@
 	    $channels = {}; # {フルチャンネル名 => 1}
 	    $board->frost_channels($channels);
 	}
-
-	if (!$channels->{$ch_full}) {
-	    $channels->{$ch_full} = 1;
+	
+	# 全てのサーバーの、全てのjoinしているチャンネルの中から、
+	# このマスクに該当するチャンネル名を探し、全てfreezeする。
+	my @ch_to_freeze;
+	foreach my $network (RunLoop->shared->networks_list) {
+	    foreach my $ch ($network->channels_list) {
+		my $longname = Multicast::attach($ch, $network);
+		if (Mask::match($ch_mask, $longname)) {
+		    if (!$channels->{$longname}) {
+			$channels->{$longname} = 1;
+			push @ch_to_freeze, $longname;
+		    }
+		}
+	    }
 	}
 
 	# 必要ならタイマー起動。
 	$this->set_timer_if_required;
 
-	return ($ch_full);
+	return @ch_to_freeze;
     }
     else {
 	return ();
@@ -232,3 +233,24 @@
 }
 
 1;
+
+=pod
+info: 特定のチャンネルの発言を、一時的に受信するのをやめる。
+default: off
+
+# ログを取っているなら、ログには記録される。
+
+# チャンネルの凍結に用いるコマンド名。
+# 省略時は freeze であり、/freeze #channel@network のように使う。
+# チャンネル名を省略すると、現在フリーズされているチャンネルのリストを表示する。
+freeze-command: freeze
+
+# 凍結解除に用いるコマンド名。
+# 省略時は defrost であり、/defrost #channel@network のように使う。
+defrost-command: defrost
+
+# 凍結しているチャンネルが存在する時、一定時間毎にその旨を報告する事も可能。
+# この機能は凍結した事を忘れないようにする為にある。
+# 単位は分、デフォルトはゼロ(報告しない)。
+reminder-interval: 30
+=cut
diff -urN tiarra-20040215/module/Channel/Join/Invite.pm tiarra-20040223/module/Channel/Join/Invite.pm
--- tiarra-20040215/module/Channel/Join/Invite.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Join/Invite.pm	2004-02-23 11:47:38.000000000 +0900
@@ -41,3 +41,15 @@
 
 
 1;
+
+=pod
+info: 招待されたらそのチャンネルに入る。
+default: off
+
+# 許可するユーザ/チャンネルのマスク。
+mask: * *!*@*
+# plum: *!*@*
+
+# 招待されたチャンネルに流すメッセージのフォーマット。
+-message: こんばんわ〜。
+=cut
diff -urN tiarra-20040215/module/Channel/Join/Kicked.pm tiarra-20040223/module/Channel/Join/Kicked.pm
--- tiarra-20040215/module/Channel/Join/Kicked.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Join/Kicked.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Kicked.pm,v 1.1 2003/04/29 08:32:48 admin Exp $
+# $Id: Kicked.pm,v 1.2 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Channel::Join::Kicked;
 use strict;
@@ -33,3 +33,11 @@
 }
 
 1;
+
+=pod
+info: 特定のチャンネルからkickされた時に、自動で入りなおす。
+default: off
+  
+# 対象となるチャンネル名のマスク
+channel: *
+=cut
diff -urN tiarra-20040215/module/Channel/Mode/Get.pm tiarra-20040223/module/Channel/Mode/Get.pm
--- tiarra-20040215/module/Channel/Mode/Get.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Mode/Get.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Get.pm,v 1.4 2003/03/01 07:13:01 admin Exp $
+# $Id: Get.pm,v 1.5 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Channel::Mode::Get;
 use strict;
@@ -73,3 +73,15 @@
 }
 
 1;
+
+=pod
+info: チャンネルにJOINした時、そのチャンネルのモードを取得します。
+default: off
+
+# Channel::Mode::Set等が正しく動くためには
+# チャンネルのモードをTiarraが把握しておく必要があります。
+# 自動的にモードを取得するクライアントであれば必要ありませんが、
+# そうでなければこのモジュールを使うべきです。
+
+# 設定項目は無し。
+=cut
diff -urN tiarra-20040215/module/Channel/Mode/Oper/Grant.pm tiarra-20040223/module/Channel/Mode/Oper/Grant.pm
--- tiarra-20040215/module/Channel/Mode/Oper/Grant.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Mode/Oper/Grant.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Grant.pm,v 1.5 2003/03/02 04:15:52 topia Exp $
+# $Id: Grant.pm,v 1.6 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Channel::Mode::Oper::Grant;
 use strict;
@@ -125,3 +125,18 @@
 }
 
 1;
+
+=pod
+info: 特定のチャンネルに特定の人間がjoinした時に、自分がチャンネルオペレータ権限を持っていれば+oする。
+default: off
+
+# splitからの復帰などで+o対象の人が一度に大量に入って来ても+oは少しずつ実行します。
+# Excess Floodにはならない筈ですが、本格的な防衛BOTに使える程の物ではありません。
+
+# 対象の人間がjoinしてから実際に+oするまで何秒待つか。
+# 省略されたら待ちません。
+wait: 0
+
+# チャンネルと人間のマスクを定義。Auto::Operと同様。
+-mask: * example!~example@*.example.ne.jp
+=cut
diff -urN tiarra-20040215/module/Channel/Mode/Set.pm tiarra-20040223/module/Channel/Mode/Set.pm
--- tiarra-20040215/module/Channel/Mode/Set.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Mode/Set.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Set.pm,v 1.2 2003/01/23 13:38:48 admin Exp $
+# $Id: Set.pm,v 1.3 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # 掲示板のdo-not-touch-mode-of-channels (HASH*)に記述されているチャンネルのモードは弄らない。
 # -----------------------------------------------------------------------------
@@ -68,3 +68,15 @@
 }
 
 1;
+
+=pod
+info: チャンネルを作成した時に自動的にモードを設定するモジュール。
+default: off
+
+# 書式は<チャンネル名にマッチするマスク> <設定するモード>[,<設定するモード>,...]です。
+# #IRC談話室@ircnetなら+t+nを、それ以外なら+nを設定する例。
+-channel: #IRC談話室@ircnet +t
+-channel: *                +n
+# LimeChat 標準設定を模倣する設定例。
+-channel: * +sn
+=cut
diff -urN tiarra-20040215/module/Channel/Rejoin.pm tiarra-20040223/module/Channel/Rejoin.pm
--- tiarra-20040215/module/Channel/Rejoin.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/Channel/Rejoin.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Rejoin.pm,v 1.3 2004/02/14 11:48:20 topia Exp $
+# $Id: Rejoin.pm,v 1.4 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # このモジュールは動作時に掲示板のdo-not-touch-mode-of-channelsを使います。
 # -----------------------------------------------------------------------------
@@ -310,3 +310,16 @@
 }
 
 1;
+
+=pod
+info: チャンネルオペレータ権限を無くしたとき、一人ならjoinし直す。
+default: off
+
+# +チャンネルや+aされているチャンネル以外でチャンネルオペレータ権限を持たずに
+# 一人きりになった時、そのチャンネルの@を復活させるために自動的にjoinし直すモジュール。
+# トピック、モード、banリスト等のあらゆるチャンネル属性をも保存します。
+
+# +b,+I,+eリストの復旧を行なうかどうか。
+# あまりに長いリストを取得するとMax Send-Q Exceedで落とされるかも知れません。
+save-lists: 1
+=cut
diff -urN tiarra-20040215/module/Client/Cache.pm tiarra-20040223/module/Client/Cache.pm
--- tiarra-20040215/module/Client/Cache.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Client/Cache.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Cache.pm,v 1.3 2004/02/15 00:19:31 topia Exp $
+# $Id: Cache.pm,v 1.4 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Client::Cache;
 use strict;
@@ -8,7 +8,6 @@
 use Mask;
 use Multicast;
 use NumericReply;
-use Configuration;
 
 sub _yesno {
     my ($this, $value, $default) = @_;
@@ -90,7 +89,7 @@
 		if (!exists $remark->{$chan_long}) {
 		    $sender->send_message(
 			IRCMessage->new(
-			    Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+			    Prefix => RunLoop->shared_loop->sysmsg_prefix('system'),
 			    Command => RPL_CHANNELMODEIS,
 			    Params => [
 				RunLoop->shared_loop->current_nick,
@@ -133,7 +132,7 @@
 		# cache がそろっているかわからないため、
 		# とりあえず作ってみて、足りなかったらあきらめる。
 		my $message_tmpl = IRCMessage->new(
-		    Prefix => Configuration->shared_conf->general->sysmsg_prefix,
+		    Prefix => RunLoop->shared_loop->sysmsg_prefix('system'),
 		    Command => RPL_WHOREPLY,
 		    Params => [
 			RunLoop->shared_loop->current_nick,
@@ -162,7 +161,9 @@
 			$message->param(2, $p->username);
 			$message->param(3, $p->userhost);
 			$message->param(4, $p->server);
-			$message->param(5, $p->nick);
+			$message->param(5,
+					Multicast::global_to_local($p->nick,
+								   $network));
 			$message->param(6,
 					(length($p->away) ? 'G' : 'H') .
 					    $p_ch->priv_symbol);
diff -urN tiarra-20040215/module/Client/Eval.pm tiarra-20040223/module/Client/Eval.pm
--- tiarra-20040215/module/Client/Eval.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Client/Eval.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Eval.pm,v 1.1 2004/02/14 11:48:20 topia Exp $
+# $Id: Eval.pm,v 1.2 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 package Client::Eval;
 use strict;
@@ -27,12 +27,10 @@
 	    };
 
 	    my $message = IRCMessage->new(
+		Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(priv system)),
 		Command => 'NOTICE',
 		Params => [RunLoop->shared_loop->current_nick,
 			   ''],
-		Remarks => {
-		    'fill-prefix-when-sending-to-client' => 1,
-		},
 	       );
 	    do {
 		local($Data::Dumper::Terse) = 1;
diff -urN tiarra-20040215/module/Log/Recent.pm tiarra-20040223/module/Log/Recent.pm
--- tiarra-20040215/module/Log/Recent.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/Log/Recent.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Recent.pm,v 1.7 2004/02/14 11:48:20 topia Exp $
+# $Id: Recent.pm,v 1.9 2004/02/23 02:46:19 topia Exp $
 # -----------------------------------------------------------------------------
 # Local: $Clovery: tiarra/module/Log/Recent.pm,v 1.5 2003/02/11 07:59:32 topia Exp $
 package Log::Recent;
@@ -11,7 +11,6 @@
 use Log::Logger;
 use IRCMessage;
 use Mask;
-use Configuration;
 
 sub new {
     my $class = shift;
@@ -40,12 +39,14 @@
 
 sub client_attached {
     my ($this,$client) = @_;
+    # no-recent-logs オプションが指定されていれば何もしない
+    return if defined $client->option('no-recent-logs');
     # まずはpriv
     my $local_nick = RunLoop->shared->current_nick;
     foreach my $elem (@{$this->{priv_log}}) {
 	$client->send_message(
 	    IRCMessage->new(
-		Prefix => Configuration->shared->general->sysmsg_prefix,
+		Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(priv log)),
 		Command => 'NOTICE',
 		Params => [$local_nick,$elem->[1]])); # $elem->[0]は常に'priv'
     }
@@ -62,7 +63,7 @@
 			    $elem->[0] : $ch->name;
 		    $client->send_message(
 			IRCMessage->new(
-			    Prefix => Configuration->shared->general->sysmsg_prefix,
+			    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(channel log)),
 			    Command => 'NOTICE',
 			    Params => [$ch_name,$elem->[1]]));
 		}
@@ -165,3 +166,22 @@
 }
 
 1;
+
+=pod
+info: クライアントを接続した時に、保存しておいた最近のメッセージを送る。
+default: off
+
+# クライアントオプションの no-recent-logs が指定されていれば送信しません。
+
+# 各行のヘッダのフォーマット。省略されたら'%H:%M'。
+header: %H:%M:%S
+
+# ログをチャンネル毎に何行まで保存するか。省略されたら10。
+line: 15
+
+# PRIVMSGとNOTICEを記録する際に、自分の発言と他人の発言でフォーマットを変えるかどうか。1/0。デフォルトで1。
+distinguish-myself: 1
+
+# どのメッセージを保存するか。省略されたら保存可能な全てのメッセージを保存する。
+command: privmsg,notice,topic,join,part,quit,kill
+=cut
diff -urN tiarra-20040215/module/System/Macro.pm tiarra-20040223/module/System/Macro.pm
--- tiarra-20040215/module/System/Macro.pm	2004-02-15 09:21:37.000000000 +0900
+++ tiarra-20040223/module/System/Macro.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Macro.pm,v 1.2 2003/07/19 05:15:56 admin Exp $
+# $Id: Macro.pm,v 1.3 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package System::Macro;
 use strict;
@@ -54,3 +54,15 @@
 }
 
 1;
+
+=pod
+info: 新規にコマンドを追加し、そのコマンドが使われた時に特定の動作をまとめて実行します。
+default: off
+
+# 書式: <コマンド> <動作>
+# コマンド"switch"を追加して、それが使われると
+# #a@ircnet,#b@ircnet,#c@ircnetにjoinして、
+# #d@ircnet,#e@ircnet,#f@ircnetからpartする例。
+-macro: switch join #a@ircnet,#b@ircnet,#c@ircnet
+-macro: switch part #d@ircnet,#e@ircnet,#f@ircnet
+=cut
diff -urN tiarra-20040215/module/System/Pong.pm tiarra-20040223/module/System/Pong.pm
--- tiarra-20040215/module/System/Pong.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/System/Pong.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,31 +1,63 @@
 # -----------------------------------------------------------------------------
-# $Id: Pong.pm,v 1.6 2004/02/14 11:48:20 topia Exp $
+# $Id: Pong.pm,v 1.7 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 # $Clovery: tiarra/module/System/Pong.pm,v 1.2 2003/02/09 02:23:58 topia Exp $
 package System::Pong;
 use strict;
 use warnings;
+use NumericReply;
 use base qw(Module);
 
 sub message_arrived {
     my ($this,$message,$sender) = @_;
     
     if ($message->command eq 'PING') {
-	my ($prefix);
-	if ($sender->isa('IrcIO::Server')) {
-	    $prefix = undef;
+	my ($prefix) = do {
+	    if ($sender->isa('IrcIO::Server')) {
+		undef;
+	    } else {
+		RunLoop->shared_loop->sysmsg_prefix(qw(system));
+	    }
+	};
+	my ($nick) = do {
+	    if ($sender->isa('IrcIO::Server')) {
+		$sender->current_nick;
+	    } else {
+		RunLoop->shared_loop->current_nick;
+	    }
+	};
+	if ($message->n_params < 1) {
+	    # これを送りつけてきたサーバー/クライアントにエラーを返す。
+	    $sender->send_message(
+		new IRCMessage(
+		    Prefix => $prefix,
+		    Command => ERR_NOORIGIN,
+		    Params => [
+			$nick,
+			'No origin specified',
+		       ]));
 	} else {
-	    $prefix = $message->param(0);
+	    my ($target);
+	    if ($sender->isa('IrcIO::Server')) {
+		$nick = undef;
+		$target = $sender->server_hostname;
+	    } else {
+		$target = RunLoop->shared_loop->sysmsg_prefix(qw(system));
+	    }
+	    # これを送りつけてきたサーバー/クライアントにPONGを送り返す。
+	    $sender->send_message(
+		new IRCMessage(
+		    Prefix => $prefix,
+		    Command => 'PONG',
+		    Params => [
+			$target,
+			(defined $nick ? $nick : ()),
+		       ]));
 	}
-	# これを送りつけてきたサーバー/クライアントにPONGを送り返す。
-	$sender->send_message(
-	    new IRCMessage(
-		Command => 'PONG',
-		Params => $message->params));
-	
 	# print "System::Pong ponged to ".$message->params->[0].".\n";
 	
-	return $message;
+	# PINGメッセージはこれ以上伝達させず、ここで消してしまう。
+	return undef;
     }
     elsif ($message->command eq 'PONG') {
 	# PONGメッセージはこれ以上伝達させず、ここで消してしまう。
@@ -37,3 +69,14 @@
 }
 
 1;
+
+=pod
+info: サーバーからのPINGメッセージに対し、自動的にPONGを返す。
+default: on
+
+# これをoffにするとクライアントが自らPINGに応答せざるを得なくなりますが、
+# クライアントからのPONGメッセージはデフォルトのサーバーへ送られるので
+# デフォルト以外のサーバーからはPing Timeoutで落とされるなど
+# 全く良い事がありません。
+#   設定項目はありません。
+=cut
diff -urN tiarra-20040215/module/System/Raw.pm tiarra-20040223/module/System/Raw.pm
--- tiarra-20040215/module/System/Raw.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/System/Raw.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,12 +1,12 @@
 # -----------------------------------------------------------------------------
-# $Id: Raw.pm,v 1.2 2004/02/14 11:48:20 topia Exp $
+# $Id: Raw.pm,v 1.4 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package System::Raw;
 use strict;
 use warnings;
 use base qw(Module);
 use Mask;
-use Configuration;
+use NumericReply;
 
 sub message_arrived {
     my ($this, $msg, $sender) = @_;
@@ -16,11 +16,11 @@
 	if ($msg->n_params < 2) {
 	    $sender->send_message(
 		IRCMessage->new(
-		    Prefix => Configuration->shared->general->sysmsg_prefix,
-		    Command => 'NOTICE',
+		    Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(system)),
+		    Command => ERR_NEEDMOREPARAMS,
 		    Params => [
 			RunLoop->shared->current_nick,
-			"*** command `".$msg->command."' requires 2 or more parameters",
+			"command `".$msg->command."' requires 2 or more parameters",
 		       ]));
 	}
 	else {
@@ -44,7 +44,7 @@
 	    if (!$sent) {
 		$sender->send_message(
 		    IRCMessage->new(
-			Prefix => Configuration->shared->general->sysmsg_prefix,
+			Prefix => RunLoop->shared_loop->sysmsg_prefix(qw(priv system)),
 			Command => 'NOTICE',
 			Params => [
 			   RunLoop->shared->current_nick, 
@@ -58,3 +58,16 @@
 }
 
 1;
+=pod
+info: マスクで指定したサーバーにIRCメッセージを加工せずに直接送る。
+default: off
+
+# 例えばQUITを送る事で一時的な切断が可能。
+
+# この機能を利用するためのコマンド名。デフォルトは「raw」。
+# 「/raw ircnet quit」のようにして使う。
+# 一つ目のパラメータは送り先のネットワーク名。ワイルドカード使用可能。
+# CHOCOA の場合、 raw がクライアントで使われてしまうので、
+# コマンド名を変えるか、 /raw raw ircnet quit のようにする必要がある。
+command: raw
+=cut
diff -urN tiarra-20040215/module/System/RemoteControl.pm tiarra-20040223/module/System/RemoteControl.pm
--- tiarra-20040215/module/System/RemoteControl.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/System/RemoteControl.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: RemoteControl.pm,v 1.2 2003/02/17 08:16:53 topia Exp $
+# $Id: RemoteControl.pm,v 1.3 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package System::RemoteControl;
 use strict;
@@ -29,3 +29,19 @@
 }
 
 1;
+
+=pod
+info: 特定の発言が送られてきたとき、それに反応してIRCコマンドを実行します。
+default: off
+
+# 実行を許可する人間を表すマスク。
+-mask: *!*example@example.net
+
+# 構文: + <nick> <IRC Message>
+# <nick>は反応するbotのnickを表すマスク。
+# <IRCMessage>はサーバーに向けて発行するIRCメッセージ。
+#
+# 例:
+# + hoge NICK [hoge]
+# hogeというBOTが[hoge]にnickを変更する。
+=cut
diff -urN tiarra-20040215/module/System/Shutdown.pm tiarra-20040223/module/System/Shutdown.pm
--- tiarra-20040215/module/System/Shutdown.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/System/Shutdown.pm	2004-02-23 11:47:38.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Shutdown.pm,v 1.3 2003/01/24 16:07:15 admin Exp $
+# $Id: Shutdown.pm,v 1.4 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package System::Shutdown;
 use strict;
@@ -43,3 +43,24 @@
 }
 
 1;
+
+=pod
+info: Tiarraを終了させる。
+default: off
+
+# クライアントから特定のコマンドが実行された時や、
+# 誰かから個人的に(privで)特定の発言が送られた時に
+# Tiarra を終了させます。
+
+# 追加するコマンド。省略された場合はコマンドでのシャットダウンは無効になります。
+-command: shutdown
+
+# Tiarraをシャットダウンさせるprivの発言。
+# 省略された場合はprivでのシャットダウンは無効になります。
+-message: shutdown
+
+# privでのシャットダウンを許可する人。
+# 省略された場合はprivでのシャットダウンは無効になります。
+# 複数のマスクを指定した場合は、一つでもマッチするものがあればシャットダウンします。
+-mask: example!example@*.example.jp
+=cut
diff -urN tiarra-20040215/module/User/Away/Client.pm tiarra-20040223/module/User/Away/Client.pm
--- tiarra-20040215/module/User/Away/Client.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Away/Client.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Client.pm,v 1.1 2003/01/27 05:04:01 admin Exp $
+# $Id: Client.pm,v 1.2 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::Away::Client;
 use strict;
@@ -44,3 +44,11 @@
 }
 
 1;
+
+=pod
+info: クライアントが一つも接続されていない時にAWAYを設定します。
+default: off
+  
+# どのようなAWAYメッセージを設定するか。省略された場合はAWAYを設定しません。
+-away: 居ない。
+=cut
diff -urN tiarra-20040215/module/User/Away/Nick.pm tiarra-20040223/module/User/Away/Nick.pm
--- tiarra-20040215/module/User/Away/Nick.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Away/Nick.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Nick.pm,v 1.1 2003/01/27 11:04:06 admin Exp $
+# $Id: Nick.pm,v 1.2 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::Away::Nick;
 use strict;
@@ -68,3 +68,20 @@
 }
 
 1;
+
+=pod
+info: ニックネーム変更に応じて AWAY を設定します。
+default: off
+
+# ニックネームを変更したときに、そのニックネームに対応するAWAYが
+# 設定されていれば、そのAWAYを設定します。そうでなければAWAYを取り消します。
+
+# 書式: <nickのマスク> <設定するAWAYメッセージ>
+#
+# nickをhoge_zzzに変更すると、「寝ている」というAWAYを設定する。
+# hoge_workまたはhoge_zzzに変更した場合は、「仕事中」というAWAYを設定する。
+# それ以外のnickに変更した場合はAWAYを取り消す。
+# 後者は正規表現を利用して「away: re:hoge_(work|zzz) 仕事中」としても良い。
+-away: hoge_zzz           寝ている
+-away: hoge_work,hoge_zzz 仕事中
+=cut
diff -urN tiarra-20040215/module/User/Filter.pm tiarra-20040223/module/User/Filter.pm
--- tiarra-20040215/module/User/Filter.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Filter.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Filter.pm,v 1.1 2003/03/23 07:44:50 admin Exp $
+# $Id: Filter.pm,v 1.2 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::Filter;
 use strict;
@@ -28,3 +28,13 @@
 }
 
 1;
+
+=pod
+info: 指定された人物からのPRIVMSGやNOTICEを書き換える。
+default: off
+
+# 人物のマスクと、置換パターンを定義。
+# 置換パターン中の#(message)は、発言内容に置換されます。
+# 人物が複数のマスクに一致する場合は、最初に一致したものが使われます。
+pattern: *!*@* #(message)
+=cut
diff -urN tiarra-20040215/module/User/Ignore.pm tiarra-20040223/module/User/Ignore.pm
--- tiarra-20040215/module/User/Ignore.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Ignore.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Ignore.pm,v 1.3 2003/08/04 09:29:20 admin Exp $
+# $Id: Ignore.pm,v 1.4 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::Ignore;
 use strict;
@@ -38,5 +38,5 @@
 command: privmsg,notice
 
 # maskは複数定義可能。定義された順番でマッチングが行なわれます。
-mask: sample!*@*.sample.net
+mask: example!*@*.example.net
 =cut
diff -urN tiarra-20040215/module/User/Nick/Detached.pm tiarra-20040223/module/User/Nick/Detached.pm
--- tiarra-20040215/module/User/Nick/Detached.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Nick/Detached.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Detached.pm,v 1.2 2003/01/27 11:04:06 admin Exp $
+# $Id: Detached.pm,v 1.3 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 # このモジュールはRunLoopのcurrent_nick、すなわちローカルnickを変更しない。
 # -----------------------------------------------------------------------------
@@ -47,3 +47,13 @@
 }
 
 1;
+
+=pod
+info: クライアントが接続されていない時に、特定のnickに変更します。
+default: off
+
+# クライアントが接続されていない時のnick。
+# このnickが既に使われていたら、適当に変更が加えられて使用されます。
+# クライアントが再び接続されると、切断前のローカルnickに戻ります。
+detached: PHO_d
+=cut
diff -urN tiarra-20040215/module/User/ServerOper.pm tiarra-20040223/module/User/ServerOper.pm
--- tiarra-20040215/module/User/ServerOper.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/ServerOper.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: ServerOper.pm,v 1.1 2003/01/27 11:04:06 admin Exp $
+# $Id: ServerOper.pm,v 1.2 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::ServerOper;
 use strict;
@@ -33,3 +33,14 @@
 }
 
 1;
+
+=pod
+info: 特定のネットワークに接続した時、OPERコマンドを発行してします。
+default: off
+
+# 書式: <ネットワーク名> <オペレータ名> <オペレータパスワード>
+#
+# ネットワーク"local"に接続した時、オペレータ名oper、
+# オペレータパスワードoper-passでOPERコマンドを発行する例。
+-oper: local oper oper-pass
+=cut
diff -urN tiarra-20040215/module/User/Vanish.pm tiarra-20040223/module/User/Vanish.pm
--- tiarra-20040215/module/User/Vanish.pm	2004-02-15 09:21:36.000000000 +0900
+++ tiarra-20040223/module/User/Vanish.pm	2004-02-23 11:47:37.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Vanish.pm,v 1.4 2003/07/26 14:00:36 admin Exp $
+# $Id: Vanish.pm,v 1.5 2004/02/23 02:46:20 topia Exp $
 # -----------------------------------------------------------------------------
 package User::Vanish;
 use strict;
@@ -299,3 +299,36 @@
 }
 
 1;
+
+=pod
+info: 指定された人物の存在を、様々なメッセージから消去する。
+default: off
+
+# 対象となった人物の発行したJOIN、PART、INVITE、QUIT、NICKは消去され、NAMESの返すネームリストからも消える。
+# また、対象となった人物のNJOINも消去される。
+
+# Vanish対象が発行したMODEを消去するかどうか。デフォルトで0。
+# 消去するとは云え、本当にMODEそのものを消してしまうのではなく、
+# そのユーザーの代わりに"HIDDEN!HIDDEN@HIDDEN.BY.USER.VANISH"がMODEを実行した事にする。
+drop-mode-by-target: 1
+
+# Vanish対象を対象とするMODE +o/-o/+v/-vを消去するかどうか。デフォルトで1。
+drop-mode-switch-for-target: 1
+
+# Vanish対象が発行したKICKを消去するかどうか。デフォルトで0。
+# 本当に消すのではなく、"HIDDEN!HIDDEN@HIDDEN"がKICKを実行した事にする。
+drop-kick-by-target: 1
+
+# Vanish対象を対象とするKICKを消去するかどうか。デフォルトで0。
+drop-kick-for-target: 0
+
+# Vanish対象が発行したTOPICを消去するかどうか。デフォルトで0。
+# 本当に消すのでは無いが、他の設定と同じ。
+drop-topic-by-target: 1
+
+# チャンネルとVanish対象の定義。
+# 特定のチャンネルでのみ対象とする、といった事が可能。
+# また、privの場合は「#___priv___@ネットワーク名」という文字列をチャンネル名の代わりとしてマッチングを行なう。
+# 書式: mask: <チャンネルのマスク> <ユーザーのマスク>
+mask: #example@example  example!exapmle@example.com
+=cut
diff -urN tiarra-20040215/sample.conf tiarra-20040223/sample.conf
--- tiarra-20040215/sample.conf	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/sample.conf	2004-02-23 11:47:36.000000000 +0900
@@ -1,6 +1,6 @@
 # -*- tiarra-conf -*-
 # -----------------------------------------------------------------------------
-# $Id: sample.conf,v 1.62 2004/02/14 11:48:18 topia Exp $
+# $Id: sample.conf,v 1.64 2004/02/23 02:46:17 topia Exp $
 # -----------------------------------------------------------------------------
 # tiarra.conf サンプル
 #
@@ -15,10 +15,13 @@
 #
 # 特に指定が無い場合、同じ設定を二度以上繰り返した時は最初に定義された設定が有効になります。
 #
+# ブロックごと省略した場合は、そのブロックの全ての値が省略されたものとみなします。
+# ただし省略不可能な設定もありますので御注意下さい。
+#
 # 「@include foo.conf」という行があると、foo.confがその場所に
 #  挿入されたかのように処理します。
 #
-# {}記号の位置には、ある程度の自由度があります。
+# {}記号の位置には、それなりの自由度があります。
 # 次の例は全て有効です。
 # block {
 #   foo: bar
@@ -48,8 +51,7 @@
 #
 # tiarra.conf自身の文字コードやユーザー情報などを指定するブロックです。
 # -----------------------------------------------------------------------------
-general
-{
+general {
   # tiarra.conf自身の文字コード
   # コード名はjis,sjis,euc,utf8,utf16,utf32等。(この値はUnicode::Japaneseにそのまま渡されます)
   # autoが指定された、または省略された場合は自動判別します。
@@ -72,12 +74,12 @@
   # Tiarraが開くポート。ここに指定したポートへクライアントに接続させる。
   # 省略されたらポートを開かない。
   tiarra-port: 6667
-
+  
   # Tiarraがポートtiarra-portを開く際、IPv6とIPv4のどちらでリスニングを行なうか。
   # 'v4'または'v6'で指定します。デフォルトは'v4'です。
   # IPv6を使うためにはSocket6.pmが利用可能である必要があります。
   #tiarra-ip-version: v4
-
+  
   # Tiarraがポートtiarra-portを開く際のローカルアドレス。
   # 意味が分からなければ省略して下さい。
   # デフォルトは、IPv4のはINADDR_ANY、IPv6のはin6addr_anyになります。
@@ -87,7 +89,7 @@
   # Tiarraにクライアントが接続する際に要求するパスワードをcryptした文字列。
   # 空の文字列が指定されたり省略された場合はパスワードを要求しない。
   tiarra-password: xl7cflIcH9AwE
-
+  
   # 外部プログラムからtiarraをコントロールする為のUNIXドメインソケットの名前。
   # 例えば"foo"を指定した場合、ソケット/tmp/tiarra-control/fooが作られる。
   # 省略された場合はこの機能を無効とする。
@@ -112,7 +114,7 @@
   # Tiarraはエラーメッセージを標準出力に出力するが、その時に接続しているクライアントがあればクライアントにもNOTICEで送る事が出来る。
   # この値を1にすると、その機能が有効になる。省略するか0を指定するとこの機能は無効になる。
   notice-error-messages: 1
-
+  
   # Tiarraでチャンネルとユーザーのマスクを指定するときの形式。
   # plum形式とTiarra形式が選択できます。
   #-----------------
@@ -131,20 +133,36 @@
   #  mask: *                                     -*!*@*
   #-----------------
   # となります。 この二つはまったく同じマスクを表しています。
-
+  
   # この値をplumにすると、plum形式、省略するかtiarraを指定すると、Tiarra形式になります。
   chanmask-mode: tiarra
-
+  
   # サーバーに接続する際、ローカル側のどのアドレスにバインドするか。
   # 意味が分からなければ省略して下さい。
   # デフォルトは、IPv4のはINADDR_ANY、IPv6のはin6addr_anyになります。
   #ipv4-bind-addr: 0.0.0.0
   #ipv6-bind-addr: ::0
-
+  
   # tiarra が、 001 や 002 や、 recent log を送信するときなどに使う prefix
   # を指定します。 hostname や fqdn っぽいものを指定すると良いかもしれません。
   # デフォルトは tiarra です。普通変える必要はありません。
   #sysmsg-prefix: tiarra
+  
+  sysmsg-prefix-use-masks {
+    # sysmsg-prefix を使用する場所を指定する。
+  
+    # システムメッセージ(NumericReply など)。デフォルトは * です。
+    # ふつうこれを変更する必要はありません。
+    system: *
+  
+    # 個人宛メッセージ(Notice,Privmsg の中で)。デフォルトはなし。
+    #priv: 
+  
+    # チャンネル宛メッセージ(Notice,Privmsg の中で)。デフォルトは * です。
+    # Ziciz などのクライアントを接続する場合は、
+    # -*::log を指定しておくといいかもしれません。
+    channel: *
+  }
 }
 
 # -----------------------------------------------------------------------------
@@ -154,8 +172,7 @@
 # 一つも定義しなかった場合やこのブロックを省略した場合は、
 # "main"というネットワークが一つだけ指定されたものと見做します。
 # -----------------------------------------------------------------------------
-networks
-{
+networks {
   # 複数のサーバーへの接続を可能にするかどうか。1(オン)と0(オフ)で指定。
   # これを1にすると、次のnameを複数個定義する事が可能になり、
   # 複数のサーバーに同時に接続出来るようになります。
@@ -167,7 +184,7 @@
   # その直後にjoinし直したように見えます。
   # デフォルトでは1です。
   multi-server-mode: 1
-
+  
   # 接続するIRCネットワークに名前を付けます。この名前は後で使用します。
   # 複数のネットワークに接続したい場合は多重定義して下さい。
   name: ircnet
@@ -195,7 +212,7 @@
   #    再接続に成功すると再びNOTICEで報告する。JOINやPARTはしない。
   # デフォルトはpart-and-joinです。
   action-when-disconnected: message-for-each
-
+  
   # NICKを変更する度に、変更したサーバーでの新しいNICKをNOTICEで常に通知するかどうか。
   # 1なら必ず通知し、0なら変更後のnickがローカルnick(クライアントが見る事の出来るnick)と違っている場合のみ通知する。
   # デフォルトは0です。
@@ -208,28 +225,27 @@
 # networksブロックで定義した全てのネットワークについて、
 # そのアドレス、ポート、(必要なら)パスワードを定義します。
 # -----------------------------------------------------------------------------
-ircnet
-{
+ircnet {
   # サーバーのホストとポート。省略不可。
-  host: irc.kyoto.wide.ad.jp
+  host: irc.nara.wide.ad.jp
   port: 6663
   
   # general/userで設定したユーザ名を使わずに、各ネットワークで独自のユーザ名を使用する事も可能。
   # 省略されたら当然、general/userで設定したものが使われる。
   #user: hoge
-
+  
   # general/nameで設定した本名(建前上)を使わずに、各ネットワークで独自の本名を使用可能。
   #name: hoge
   
   # このサーバーの要求するパスワード。省略可能。
   #password: hoge
-
+  
   # general/setver-in/out-encodingで設定したエンコーディングを使わずに、
   # 各ネットワークで独自のエンコーディングを使用する事も可能。
   # 省略されたら当然、generalで設定したものが使われる。
   #in-encoding: jis
   #out-encoding: jis
-
+  
   # general/(ipv4|ipv6)bind-addrで設定したローカルアドレスを使わずに、
   # 各ネットワークで独自のbind_addrを使用する事も可能。
   # 省略されたらgeneralで設定したものが使われる。
@@ -237,8 +253,7 @@
   #ipv6-bind-addr: ::0
 }
 
-2ch
-{
+2ch {
   host: irc.2ch.net
   port: 6667
 }
@@ -278,9 +293,10 @@
 # tiarra*  これはtiarraで始まる文字列を表す。
 # +*!*tiarra@*.jp,-re:\d  これは*!*tiarra@*.jpにマッチして、かつ文字列中に数字を含まないものを表す。
 
-- Auto::Alias
-{
+
+- Auto::Alias {
   # ユーザエイリアス情報の管理を行ないます。
+
   # エイリアスは基本的にname,userの二つのフィールドから成っており、
   # それぞれユーザー名、ユーザーマスクを表します。
   
@@ -318,18 +334,18 @@
   # それぞれ相手のnick、チャンネル名に置換されます。
   # #(key)、#(value)は、追加されたキーと値に置換されます。
   added-format: #(name|nick.now): エイリアス #(key) に #(value) を追加しました。
-
+  
   # メッセージが削除されたときの反応を指定します。
   # added-formatで指定できるものと同じです。
   removed-format: #(name|nick.now): エイリアス #(key) から #(value) を削除しました。
-
+  
   # エイリアスの追加や削除が許されている人。省略された場合は「*!*@*」と見做される。
   modifier: *!*@*
 }
 
-- Auto::Answer
-{
-  # 特定の発言に反応して対応する発言をするモジュールです。
+- Auto::Answer {
+  # 特定の発言に反応して対応する発言をする。
+
   # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
   
   # 反応する発言と、それに対する返事を定義します。
@@ -338,15 +354,27 @@
   #
   # 書式: <反応する発言のマスク> <それに対する返事>
   # 例:
-  # reply: こんにちは* こんにちは、#(name|nick.now)さん。
+  #reply: こんにちは* こんにちは、#(name|nick.now)さん。
   # この例では誰かが「こんにちは」で始まる発言をすると、
   # 発言した人のエイリアスを参照して「こんにちは、○○さん。」のように発言します。
 }
 
+- Auto::ChannelWithoutOper {
+  # チャンネルオペレータ権限がなくなってしまったときに発言する。
+
+  # +で始まらない特定のチャンネルで、+aモードでも+rモードでもないのに
+  # 誰もチャンネルオペレータ権限を持っていない状態になっている時、
+  # そこに誰かがJOINする度に特定のメッセージを発言するモジュールです。
+  
+  # 書式: <チャンネル名> <メッセージ>
+  #channel: #IRC談話室@ircnet なると消失しました。
+}
+
 - Auto::Joined {
-  # 特定のチャンネルに誰かがJOINする度に特定のメッセージを発言するモジュールです。
-  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+  # 特定のチャンネルに誰かがJOINする度に特定のメッセージを発言する。
 
+  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+  
   # 発言を行なうチャンネルと、その内容を定義します。
   # #(nick.now)と$(channel)は、それぞれ相手の現在のnickとチャンネル名に置換されます。
   #
@@ -354,90 +382,80 @@
   #channel: #チャンネル@ircnet   「#ちゃんねる」に移転しました。
 }
 
-- Auto::ChannelWithoutOper
-{
-  # +で始まらない特定のチャンネルで、+aモードでも+rモードでもないのに
-  # 誰もチャンネルオペレータ権限を持っていない状態になっている時、
-  # そこに誰かがJOINする度に特定のメッセージを発言するモジュールです。
-  
-  # 書式: <チャンネル名> <メッセージ>
-  #channel: #IRC談話室@ircnet なると消失しました。
-}
+- Auto::MesMail {
+  # 伝言をメールとして送信する。
 
-- Auto::MesMail
-{
-  # 伝言をメールとして送信するモジュールです。
   # メールアドレスはエイリアスの mail を参照します。
-
+  
   # Fromアドレス。[default: OSのユーザ名]
   from: example1@example.jp
-
+  
   # 送信用のキーワード [default: mesmail_send]
   send: 速達伝言
-
+  
   # 使用を許可する人&チャンネルのマスク。
   # 例はTiarraモード時。 [default: なし]
   mask: * +*!*@*
   # [plum-mode] mask: +*!*@*
-
+  
   # maskで拒否されたときのメッセージ [default: なし]
   deny: 伝言したくない。
-
+  
   # 一度に送れる宛先の量 [default: 無制限]
   max-send-address: 5
-
+  
   # 宛先を探すエイリアスエントリ [default: なし]
   alias-key: name
   alias-key: nick
-
+  
   # 宛先の人を判別出来なかったときのメッセージ [default: なし]
   unknown: #(who)さんと言うのは誰ですか?
-
+  
   # メールの日付形式
   date: %H:%M:%S
-
+  
   # エイリアスは見付かったけれどメールアドレスが登録されていなかったときのメッセージ。 [default: なし]
   #none-address: #(who)さんはアドレスを登録していません。
-
+  
   # SMTPのホスト [default: localhost]
   #smtphost: localhost
-
+  
   # SMTPのポート [default: smtp(25)]
   #smtpport: 25
-
+  
   # SMTPで自ホストのFQDN [default: localhost]
   #smtpfqdn: localhost
-
+  
   # 送信するメールの既定件名(エイリアス使用不可) [default: Message from IRC]
   #subject: Message from IRC
-
+  
   # 送信するメールの本文 [default: #(date) << #(from.name|from.nick|from.nick.now) >> #(message)]
   #format: #(date)に#(from.name|from.nick|from.nick.now)さんから#(message)という伝言です。
-
+  
   # 送信したときのメッセージ。 [default: なし]
   accept: #(who)さんに#(message)と伝言しておきました。
-
+  
   # ---- POP before SMTP の指定 ----
   # POP before SMTPを使う。 [default: no]
   #use-pop3: yes
-
+  
   # POP before SMTPのタイムアウト時間(分)。分からない場合は指定しなくて良い。 [default: 0]
   #pop3-expire: 4
-
+  
   # POPのホスト。 [default: localhost]
   #pop3host: localhost
-
+  
   # POPのポート。 [default: pop(110)]
   #pop3port: 110
-
+  
   # POPのユーザ [default: OSのユーザ名]
   #pop3user: example1
-
+  
   # POPのパスワード [default: 空パスワード('')]
   #pop3pass: test-password
-
+  
   # ---- エラーメッセージの設定 ----
-
+  
   # 一般エラー。
   # error-[state] と言う形式で詳細エラーメッセージを指定できる。
   # [state]は、
@@ -449,12 +467,12 @@
   # がある。特に欲しくなければerror-[state]は指定しなくても構わない。
   # メッセージを出したくないなら中身の無いエントリを指定すれば良い。
   # error-[state]が指定されてない場合は代わりに error を使う。 [default: 未定義]
-
-  #error-rcptto:
+  
+  #error-rcptto: 
   #error-norcptto: #(who)さんには送れませんでした。送信できるメールアドレスがありません。
   #error-data: メールが送信できません。DATAコマンドに失敗しました。#(line;サーバ応答:%s|;)
   #error: メール送信エラーです。#(line;サーバ応答:%s|;)#(state; on %s|;)
-
+  
   # 致命的なエラー。メールに個別なエラーではないので送信者(のprefix)毎に1メッセージ送られる。
   # fatalerror-[state]
   # [state]:
@@ -463,14 +481,14 @@
   # がある。特に欲しくなければfatalerror-[state]は指定しなくても構わない。
   # メッセージを出したくないなら中身の無いエントリを指定すれば良い。
   # fatalerror-[state]が指定されてない場合は代わりに fatalerror を使う。 [default: 未定義]
-
+  
   #fatalerror-first: SMTPサーバに接続できません。
   #fatalerror: SMTPセッションで致命的なエラーがありました。#(line; サーバ応答:%s|;)#(state; on %s|;)
 }
 
-- Auto::Oper
-{
-  # 特定の文字列を発言した人を+oするモジュールです。
+- Auto::Oper {
+  # 特定の文字列を発言した人を+oする。
+
   # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
   
   # +oを要求する文字列(マスク)を指定します。
@@ -527,136 +545,136 @@
   out: チャンネルに入っていない
 }
 
-- Auto::Random
-{
+- Auto::Random {
   # 特定の発言に反応してランダムな発言をします。
-  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
 
+  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+  
   # 使用するブロックの定義。
   blocks: wimikuji
-
+  
   wimikuji {
     # ランダムに発言するメッセージの書かれたファイルと、その文字コードを指定します。
     # ファイルの中では一行に一つのメッセージを書いて下さい。
     file: random.txt
     file-encoding: euc
-
+  
     # 反応する発言を表すマスクを指定します。
     request: ゐみくじ
-
+  
     # メッセージの登録数を返答するキーワードを指定します。
     count-query: ゐみくじ登録数
-
+  
     # メッセージの登録数を返答するときの反応を指定します。
     # formatで指定できるものと同じです。#(count)は登録数になります。
     count-format: ゐみくじは#(count)件登録されています。
-
+  
     # ランダムなメッセージを発言する際のフォーマットを指定します。
     # エイリアス置換が有効です。#(message)、#(nick.now)、#(channel)は
     # それぞれメッセージ内容、相手のnick、チャンネル名に置換されます。
     # 何も登録されていないときのために、#(message|;無登録)のように指定すると良いでしょう。
     format: #(name|nick.now)の運命は#(message)
-
+  
     # 反応する人のマスク。
     mask: * *!*@*
     # plum: mask: *!*@*
-
+  
     # メッセージが追加されたときの反応を指定します。
     # formatで指定できるものと同じです。#(message)は追加されたメッセージになります。
     added-format: #(name|nick.now): ゐみくじ #(message) を追加しました。
-
+  
     # メッセージが削除されたときの反応を指定します。
     # formatで指定できるものと同じです。#(message)は削除されたメッセージになります。
     removed-format: #(name|nick.now): ゐみくじ #(message) を削除しました。
-
+  
     # 発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。
     rate: 100
-
+  
     # メッセージを追加するキーワードを指定します。
     # ここで指定したキーワードを発言すると、新しいメッセージを追加します。
     # 実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。
     add: ゐみくじ追加
-
+  
     # メッセージを削除するキーワードを指定します。
     # 実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。
     remove: ゐみくじ削除
-
+  
     # addとremoveを許可する人。省略された場合は誰も変更できません。
     modifier: * *!*@*
     # plum: modifier: *!*@*
   }
 }
 
-- Auto::Reply
-{
+- Auto::Reply {
   # 特定の発言に反応して発言をします。
-  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
 
+  # Auto::Aliasを有効にしていれば、エイリアス置換を行ないます。
+  
   # 使用するブロックの定義。
   blocks: std
-
+  
   std {
     # データファイルと文字コードを指定します。
     # ファイルの中では一行に一つの"反応:メッセージ"を書いて下さい。
     file: reply.txt
     file-encoding: euc
-
+  
     # 反応チェックを行うキーワードを指定します。
     # 実際の指定方法は、「<requestで指定したキーワード> <チェックしたい発言>」です。
     request: 反応チェック
-
+  
     # request に反応するときのフォーマットを指定します。
     # #(key) がキーワード、 #(message) が発言に置換されます。
     reply-format: 「#(key)」という発言に「#(message)」と反応します。
-
+  
     # request に反応する最大個数を指定します。
     # あまり大きな値を指定すると、アタックが可能になったり、ログが流れて邪魔なので注意してください。
     max-reply: 5
-
+  
     # メッセージの登録数を返答するキーワードを指定します。
     count-query: 反応登録数
-
+  
     # メッセージの登録数を返答するときの反応を指定します。
     # formatで指定できるものと同じです。#(count)は登録数になります。
     count-format: 反応は#(count)件登録されています。
-
+  
     # 反応する人のマスク。
     mask: * *!*@*
     # plum: mask: *!*@*
-
+  
     # 反応が追加されたときの反応を指定します。
     # formatで指定できるものと同じです。#(message)は追加されたメッセージになります。
     added-format: #(name|nick.now): #(key) に対する反応 #(message) を追加しました。
-
+  
     # メッセージが削除されたときの反応を指定します。
     # formatで指定できるものと同じです。#(message)は削除されたメッセージになります。
     removed-format: #(name|nick.now): #(key) #(message;に対する反応 %s|;) を #(count) 件削除しました。
-
+  
     # 発言に反応する確率を指定します。百分率です。省略された場合は100と見做されます。
     rate: 100
-
+  
     # メッセージを追加するキーワードを指定します。
     # ここで指定したキーワードを発言すると、新しいメッセージを追加します。
     # 実際の追加方法は「<addで指定したキーワード> <追加するメッセージ>」です。
     add: 反応追加
-
+  
     # メッセージを削除するキーワードを指定します。
     # 実際の削除方法は「<removeで指定したキーワード> <削除するキーワード>」です。
     remove: 反応削除
-
+  
     # addとremoveを許可する人。省略された場合は「*!*@*」と見做します。
     modifier: *!*@*
-
+  
     # 正規表現拡張を許可するか。省略された場合は許可します。
     use-re: 1
   }
 }
 
-- Auto::Response
-{
-  # データファイルの指定にしたがって反応するモジュールです。
-  # 大量の反応データを定義するのに向いています。
+- Auto::Response {
+  # データファイルの指定にしたがって反応する。
 
+  # 大量の反応データを定義するのに向いています。
+  
   # データファイルのフォーマット
   # | pattern: re:^(こん(に)?ちは)
   # | rate: 90
@@ -671,31 +689,77 @@
   # patternは一行しか書けません。(手抜き
   # maskもrateも省略できます。省略した場合はmaskは全員、rateは100となります。
   # responseは複数書いておけばランダムに選択されます。
-
+  
   # データファイル
   file: response.txt
-
+  
   # 文字コード
   charset: euc
-
+  
   # 使用を許可する人&チャンネルのマスク。
   mask: * *!*@*
   # plum: mask: +*!*@*
 }
 
+- CTCP::ClientInfo {
+  # CTCP CLIENTINFOに応答する。
+
+  # CTCP::Versionのintervalと同じ。
+  interval: 3
+}
+
+- CTCP::Ping {
+  # CTCP PINGに応答する。
+
+  # CTCP::Versionのintervalと同じ。
+  interval: 3
+}
+
+- CTCP::Time {
+  # CTCP TIMEに応答する。
+
+  # CTCP::Versionのintervalと同じ。
+  interval: 3
+}
+
+- CTCP::UserInfo {
+  # CTCP USERINFOに応答する。
+
+  # CTCP::Versionのintervalと同じ。
+  interval: 3
+  
+  # USERINFOとして返すメッセージ。
+  message: テスト
+}
+
++ CTCP::Version {
+  # CTCP VERSIONに応答する。
+
+  # 連続したCTCPリクエストに対する応答の間隔。単位は秒。
+  # 例えば3秒に設定した場合、一度応答してから3秒間は
+  # CTCPに一切応答しなくなる。デフォルトは3。
+  #
+  # なお、CTCP受信時刻の記録は、全てのCTCPモジュールで共有される。
+  # 例えばCTCP VERSIONを送った直後にCTCP CLIENTINFOを送ったとしても、
+  # CTCP::ClientInfoのintervalで設定された時間を過ぎていなければ
+  # 後者は応答しない。
+  interval: 3
+}
+
 - Channel::Freeze {
   # 特定のチャンネルの発言を、一時的に受信するのをやめる。
+
   # ログを取っているなら、ログには記録される。
   
   # チャンネルの凍結に用いるコマンド名。
   # 省略時は freeze であり、/freeze #channel@network のように使う。
   # チャンネル名を省略すると、現在フリーズされているチャンネルのリストを表示する。
   freeze-command: freeze
-
+  
   # 凍結解除に用いるコマンド名。
   # 省略時は defrost であり、/defrost #channel@network のように使う。
   defrost-command: defrost
-
+  
   # 凍結しているチャンネルが存在する時、一定時間毎にその旨を報告する事も可能。
   # この機能は凍結した事を忘れないようにする為にある。
   # 単位は分、デフォルトはゼロ(報告しない)。
@@ -717,29 +781,28 @@
   #channel: #ddddd@ircnet
 }
 
-- Channel::Join::Kicked {
-  # 特定のチャンネルからkickされた時に、自動で入りなおすモジュール。
-  
-  # 対象となるチャンネル名のマスク
-  channel: *
-}
-
-- Channel::Join::Invite
-{
+- Channel::Join::Invite {
   # 招待されたらそのチャンネルに入る。
 
   # 許可するユーザ/チャンネルのマスク。
   mask: * *!*@*
   # plum: *!*@*
-
+  
   # 招待されたチャンネルに流すメッセージのフォーマット。
   #message: こんばんわ〜。
 }
 
-- Channel::Mode::Get
-{
+- Channel::Join::Kicked {
+  # 特定のチャンネルからkickされた時に、自動で入りなおす。
+
+  # 対象となるチャンネル名のマスク
+  channel: *
+}
+
+- Channel::Mode::Get {
   # チャンネルにJOINした時、そのチャンネルのモードを取得します。
-  # 下のChannel::Mode::Set等が正しく動くためには
+
+  # Channel::Mode::Set等が正しく動くためには
   # チャンネルのモードをTiarraが把握しておく必要があります。
   # 自動的にモードを取得するクライアントであれば必要ありませんが、
   # そうでなければこのモジュールを使うべきです。
@@ -747,20 +810,9 @@
   # 設定項目は無し。
 }
 
-- Channel::Mode::Set
-{
-  # チャンネルを作成した時に自動的にモードを設定するモジュール。
-  
-  # 書式は<チャンネル名にマッチするマスク> <設定するモード>[,<設定するモード>,...]です。
-  # 例:
-  # channel: #IRC談話室@ircnet +t
-  # channel: *                +n
-  # この例では#IRC談話室@ircnetなら+t+nを、それ以外なら+nを設定します。
-}
-
-- Channel::Mode::Oper::Grant
-{
+- Channel::Mode::Oper::Grant {
   # 特定のチャンネルに特定の人間がjoinした時に、自分がチャンネルオペレータ権限を持っていれば+oする。
+
   # splitからの復帰などで+o対象の人が一度に大量に入って来ても+oは少しずつ実行します。
   # Excess Floodにはならない筈ですが、本格的な防衛BOTに使える程の物ではありません。
   
@@ -769,11 +821,23 @@
   wait: 0
   
   # チャンネルと人間のマスクを定義。Auto::Operと同様。
-  #mask: * sample!~sample@*.sample.ne.jp
+  #mask: * example!~example@*.example.ne.jp
+}
+
+- Channel::Mode::Set {
+  # チャンネルを作成した時に自動的にモードを設定するモジュール。
+
+  # 書式は<チャンネル名にマッチするマスク> <設定するモード>[,<設定するモード>,...]です。
+  # #IRC談話室@ircnetなら+t+nを、それ以外なら+nを設定する例。
+  #channel: #IRC談話室@ircnet +t
+  #channel: *                +n
+  # LimeChat 標準設定を模倣する設定例。
+  #channel: * +sn
 }
 
-- Channel::Rejoin
-{
+- Channel::Rejoin {
+  # チャンネルオペレータ権限を無くしたとき、一人ならjoinし直す。
+
   # +チャンネルや+aされているチャンネル以外でチャンネルオペレータ権限を持たずに
   # 一人きりになった時、そのチャンネルの@を復活させるために自動的にjoinし直すモジュール。
   # トピック、モード、banリスト等のあらゆるチャンネル属性をも保存します。
@@ -783,15 +847,6 @@
   save-lists: 1
 }
 
-- Client::Eval {
-  # クライアントから Perl 式を実行できるようにする。
-
-  # eval を実行するコマンド名。省略されるとコマンドを追加しません。
-  # この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された
-  # コマンド名を設定すべきではありません。
-  command: eval
-}
-
 - Client::Cache {
   # データをキャッシュしてサーバに問い合わせないようにする
 
@@ -806,6 +861,15 @@
   use-who-cache: 1
 }
 
+- Client::Eval {
+  # クライアントから Perl 式を実行できるようにする。
+
+  # eval を実行するコマンド名。省略されるとコマンドを追加しません。
+  # この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された
+  # コマンド名を設定すべきではありません。
+  command: eval
+}
+
 - Log::Channel {
   # チャンネルやprivのログを取るモジュール。
 
@@ -871,9 +935,10 @@
   channel: others *
 }
 
-- Log::Recent
-{
+- Log::Recent {
   # クライアントを接続した時に、保存しておいた最近のメッセージを送る。
+
+  # クライアントオプションの no-recent-logs が指定されていれば送信しません。
   
   # 各行のヘッダのフォーマット。省略されたら'%H:%M'。
   header: %H:%M:%S
@@ -888,9 +953,20 @@
   command: privmsg,notice,topic,join,part,quit,kill
 }
 
-+ System::Pong
-{
-  #   サーバーからのPINGメッセージに対し、自動的にPONGを返すモジュール。
+- System::Macro {
+  # 新規にコマンドを追加し、そのコマンドが使われた時に特定の動作をまとめて実行します。
+
+  # 書式: <コマンド> <動作>
+  # コマンド"switch"を追加して、それが使われると
+  # #a@ircnet,#b@ircnet,#c@ircnetにjoinして、
+  # #d@ircnet,#e@ircnet,#f@ircnetからpartする例。
+  #macro: switch join #a@ircnet,#b@ircnet,#c@ircnet
+  #macro: switch part #d@ircnet,#e@ircnet,#f@ircnet
+}
+
++ System::Pong {
+  # サーバーからのPINGメッセージに対し、自動的にPONGを返す。
+
   # これをoffにするとクライアントが自らPINGに応答せざるを得なくなりますが、
   # クライアントからのPONGメッセージはデフォルトのサーバーへ送られるので
   # デフォルト以外のサーバーからはPing Timeoutで落とされるなど
@@ -898,108 +974,154 @@
   #   設定項目はありません。
 }
 
-+ System::Reload
-{
-  # .confやモジュールが更新されていればそれをリロードするコマンドを追加します。
+- System::PrivTranslator {
+  # クライアントからの個人的なprivが相手に届かなくなる現象を回避する。
+
+  # このモジュールは個人宛てのprivmsgの送信者のnickにネットワーク名を付加します。
+  # 設定項目はありません。
+}
+
+- System::Raw {
+  # マスクで指定したサーバーにIRCメッセージを加工せずに直接送る。
+
+  # 例えばQUITを送る事で一時的な切断が可能。
   
+  # この機能を利用するためのコマンド名。デフォルトは「raw」。
+  # 「/raw ircnet quit」のようにして使う。
+  # 一つ目のパラメータは送り先のネットワーク名。ワイルドカード使用可能。
+  # CHOCOA の場合、 raw がクライアントで使われてしまうので、
+  # コマンド名を変えるか、 /raw raw ircnet quit のようにする必要がある。
+  command: raw
+}
+
++ System::Reload {
+  # confファイルやモジュールの更新をリロードするコマンドを追加する。
+
   # リロードを実行するコマンド名。省略されるとコマンドを追加しません。
-  # 例えば"load"を設定すると、"/load"と発言した時にリロードを実行します。
+  # 例えば"load"を設定すると、"/load"と発言しようとした時にリロードを実行します。
   # この時コマンドはTiarraが握り潰すので、IRCプロトコル上で定義された
   # コマンド名を設定すべきではありません。
   command: load
-  
-  # 何秒間隔で更新をチェックするか。省略されると自動での更新チェックは行いません。
-  interval: 60
 }
 
-- System::Macro
-{
-  # 新規にコマンドを追加し、そのコマンドが使われた時に
-  # 特定の動作をまとめて実行します。
+- System::RemoteControl {
+  # 特定の発言が送られてきたとき、それに反応してIRCコマンドを実行します。
+
+  # 実行を許可する人間を表すマスク。
+  #mask: *!*example@example.net
   
-  # 書式: <コマンド> <動作>
+  # 構文: + <nick> <IRC Message>
+  # <nick>は反応するbotのnickを表すマスク。
+  # <IRCMessage>はサーバーに向けて発行するIRCメッセージ。
+  #
   # 例:
-  # macro: switch join #a@ircnet,#b@ircnet,#c@ircnet
-  # macro: switch part #d@ircnet,#e@ircnet,#f@ircnet
-  # この例ではコマンド"switch"を追加して、それが使われると
-  # #a@ircnet,#b@ircnet,#c@ircnetにjoinして、
-  # #d@ircnet,#e@ircnet,#f@ircnetからpartします。
+  # + hoge NICK [hoge]
+  # hogeというBOTが[hoge]にnickを変更する。
 }
 
-- System::Shutdown
-{
+- System::Shutdown {
+  # Tiarraを終了させる。
+
   # クライアントから特定のコマンドが実行された時や、
   # 誰かから個人的に(privで)特定の発言が送られた時に
-  # Tiarraを終了させるモジュールです。
+  # Tiarra を終了させます。
   
   # 追加するコマンド。省略された場合はコマンドでのシャットダウンは無効になります。
-  command: shutdown
+  #command: shutdown
   
   # Tiarraをシャットダウンさせるprivの発言。
   # 省略された場合はprivでのシャットダウンは無効になります。
-  message: shutdown
+  #message: shutdown
   
   # privでのシャットダウンを許可する人。
   # 省略された場合はprivでのシャットダウンは無効になります。
   # 複数のマスクを指定した場合は、一つでもマッチするものがあればシャットダウンします。
-  mask: sample!sample@*.sample.jp
+  #mask: example!example@*.example.jp
 }
 
-- System::PrivTranslator
-{
-  # 個人的なprivやnoticeが来た時に、その送信者のnickにネットワーク名を付ける事によって
-  # クライアントからprivが届かなくなる現象を回避するモジュール。
-  
-  # 設定項目はありません。
+- User::Away::Client {
+  # クライアントが一つも接続されていない時にAWAYを設定します。
+
+  # どのようなAWAYメッセージを設定するか。省略された場合はAWAYを設定しません。
+  #away: 居ない。
 }
 
-- System::RemoteControl
-{
-  # 特定の発言が送られてきたとき、それに反応してIRCコマンドを実行します。
-  
-  # 実行を許可する人間を表すマスク。
-  #mask: *!*hoge@hoge.net
+- User::Away::Nick {
+  # ニックネーム変更に応じて AWAY を設定します。
+
+  # ニックネームを変更したときに、そのニックネームに対応するAWAYが
+  # 設定されていれば、そのAWAYを設定します。そうでなければAWAYを取り消します。
   
-  # 構文: + <nick> <IRC Message>
-  # <nick>は反応するbotのnickを表すマスク。
-  # <IRCMessage>はサーバーに向けて発行するIRCメッセージ。
+  # 書式: <nickのマスク> <設定するAWAYメッセージ>
   #
-  # 例:
-  # + hoge NICK [hoge]
-  # hogeというBOTが[hoge]にnickを変更する。
+  # nickをhoge_zzzに変更すると、「寝ている」というAWAYを設定する。
+  # hoge_workまたはhoge_zzzに変更した場合は、「仕事中」というAWAYを設定する。
+  # それ以外のnickに変更した場合はAWAYを取り消す。
+  # 後者は正規表現を利用して「away: re:hoge_(work|zzz) 仕事中」としても良い。
+  #away: hoge_zzz           寝ている
+  #away: hoge_work,hoge_zzz 仕事中
 }
 
-- System::Raw
-{
-  # マスクで指定したサーバーにIRCメッセージを加工せずに直接送る。
-  # 例えばQUITを送る事で一時的な切断が可能。
+- User::Filter {
+  # 指定された人物からのPRIVMSGやNOTICEを書き換える。
 
-  # この機能を利用するためのコマンド名。デフォルトは「raw」。
-  # 「/raw ircnet quit」のようにして使う。
-  # 一つ目のパラメータは送り先のネットワーク名。ワイルドカード使用可能。
-  command: raw
+  # 人物のマスクと、置換パターンを定義。
+  # 置換パターン中の#(message)は、発言内容に置換されます。
+  # 人物が複数のマスクに一致する場合は、最初に一致したものが使われます。
+  pattern: *!*@* #(message)
+}
+
+- User::Ignore {
+  # 指定された人間からのPRIVMSGやNOTICEを破棄してクライアントへ送らないようにするモジュール。
+
+  # 対象となるコマンドのマスク。省略時には"privmsg,notice"が設定されている。
+  # ただしprivmsgとnotice以外を破棄してしまうと、(Tiarraは平気でも)クライアントが混乱する。
+  command: privmsg,notice
+  
+  # maskは複数定義可能。定義された順番でマッチングが行なわれます。
+  mask: example!*@*.example.net
+}
+
+- User::Nick::Detached {
+  # クライアントが接続されていない時に、特定のnickに変更します。
+
+  # クライアントが接続されていない時のnick。
+  # このnickが既に使われていたら、適当に変更が加えられて使用されます。
+  # クライアントが再び接続されると、切断前のローカルnickに戻ります。
+  detached: PHO_d
+}
+
+- User::ServerOper {
+  # 特定のネットワークに接続した時、OPERコマンドを発行してします。
+
+  # 書式: <ネットワーク名> <オペレータ名> <オペレータパスワード>
+  #
+  # ネットワーク"local"に接続した時、オペレータ名oper、
+  # オペレータパスワードoper-passでOPERコマンドを発行する例。
+  #oper: local oper oper-pass
 }
 
 - User::Vanish {
-  # 指定された人物の存在を、様々なメッセージから消去するモジュール。
+  # 指定された人物の存在を、様々なメッセージから消去する。
+
   # 対象となった人物の発行したJOIN、PART、INVITE、QUIT、NICKは消去され、NAMESの返すネームリストからも消える。
   # また、対象となった人物のNJOINも消去される。
-
+  
   # Vanish対象が発行したMODEを消去するかどうか。デフォルトで0。
   # 消去するとは云え、本当にMODEそのものを消してしまうのではなく、
   # そのユーザーの代わりに"HIDDEN!HIDDEN@HIDDEN.BY.USER.VANISH"がMODEを実行した事にする。
   drop-mode-by-target: 1
-
+  
   # Vanish対象を対象とするMODE +o/-o/+v/-vを消去するかどうか。デフォルトで1。
   drop-mode-switch-for-target: 1
-
+  
   # Vanish対象が発行したKICKを消去するかどうか。デフォルトで0。
   # 本当に消すのではなく、"HIDDEN!HIDDEN@HIDDEN"がKICKを実行した事にする。
   drop-kick-by-target: 1
-
+  
   # Vanish対象を対象とするKICKを消去するかどうか。デフォルトで0。
   drop-kick-for-target: 0
-
+  
   # Vanish対象が発行したTOPICを消去するかどうか。デフォルトで0。
   # 本当に消すのでは無いが、他の設定と同じ。
   drop-topic-by-target: 1
@@ -1011,117 +1133,3 @@
   mask: #example@example  example!exapmle@example.com
 }
 
-- User::Ignore
-{
-  # 指定された人間からのPRIVMSGやNOTICEを破棄してクライアントへ送らないようにするモジュール。
-  
-  # 対象となるコマンドのマスク。省略時には"privmsg,notice"が設定されている。
-  # ただしprivmsgとnotice以外を破棄してしまうと、(Tiarraは平気でも)クライアントが混乱する。
-  command: privmsg,notice
-  
-  # maskは複数定義可能。定義された順番でマッチングが行なわれます。
-  mask: sample!*@*.sample.net
-}
-
-- User::Filter
-{
-  # 指定された人物からのPRIVMSGやNOTICEを書き換えるモジュール。
-
-  # 人物のマスクと、置換パターンを定義。
-  # 置換パターン中の#(message)は、発言内容に置換されます。
-  # 人物が複数のマスクに一致する場合は、最初に一致したものが使われます。
-  pattern: *!*@* #(message)
-}
-
-- User::Away::Client
-{
-  # クライアントが一つも接続されていない時にAWAYを設定します。
-  
-  # どのようなAWAYメッセージを設定するか。省略された場合はAWAYを設定しません。
-  #away: 居ない。
-}
-
-- User::Away::Nick
-{
-  # ニックネームを変更したときに、そのニックネームに対応するAWAYが
-  # 設定されていれば、そのAWAYを設定します。そうでなければAWAYを取り消します。
-  
-  # 書式: <nickのマスク> <設定するAWAYメッセージ>
-  #
-  # 例：
-  # away: hoge_zzz           寝ている
-  # away: hoge_work,hoge_zzz 仕事中
-  #
-  # この例ではnickをhoge_zzzに変更すると、「寝ている」というAWAYを設定する。
-  # hoge_workまたはhoge_zzzに変更した場合は、「仕事中」というAWAYを設定する。
-  # それ以外のnickに変更した場合はAWAYを取り消す。
-  # 後者は正規表現を利用して「away: re:hoge_(work|zzz) 仕事中」としても良い。
-}
-
-- User::Nick::Detached
-{
-  # Tiarraにクライアントが接続されていない時に、特定のnickに変更します。
-    
-  # クライアントが接続されていない時のnick。
-  # このnickが既に使われていたら、適当に変更が加えられて使用されます。
-  # クライアントが再び接続されると、切断前のローカルnickに戻ります。
-  detached: PHO_d
-}
-
-- User::ServerOper
-{
-  # 特定のネットワークに接続した時、OPERコマンドを発行して
-  # サーバーオペレーター権限を取得します。
-  
-  # 書式: <ネットワーク名> <オペレータ名> <オペレータパスワード>
-  #
-  # 例:
-  # oper: local oper oper-pass
-  # この例ではnetworks/nameで定義されたネットワーク"local"に接続した時、
-  # オペレータ名oper、オペレータパスワードoper-passでOPERコマンドを発行します。
-}
-
-+ CTCP::Version {
-  # CTCP VERSIONに応答するためのモジュール。
-
-  # 連続したCTCPリクエストに対する応答の間隔。単位は秒。
-  # 例えば3秒に設定した場合、一度応答してから3秒間は
-  # CTCPに一切応答しなくなる。デフォルトは3。
-  #
-  # なお、CTCP受信時刻の記録は、全てのCTCPモジュールで共有される。
-  # 例えばCTCP VERSIONを送った直後にCTCP CLIENTINFOを送ったとしても、
-  # CTCP::ClientInfoのintervalで設定された時間を過ぎていなければ
-  # 後者は応答しない。
-  interval: 3
-}
-
-- CTCP::ClientInfo {
-  # CTCP CLIENTINFOに応答するためのモジュール。
-
-  # CTCP::Versionのintervalと同じ。
-  interval: 3
-}
-
-- CTCP::UserInfo {
-  # CTCP USERINFOに応答するためのモジュール。
-
-  # CTCP::Versionと同じ。
-  interval: 3
-
-  # USERINFOとして返すメッセージ。
-  message: テスト
-}
-
-- CTCP::Ping {
-  # CTCP PINGに応答するためのモジュール。
-
-  # CTCP::Versionと同じ。
-  interval: 3
-}
-
-- CTCP::Time {
-  # CTCP TIMEに応答するためのモジュール。
-
-  # CTCP::Versionと同じ。
-  interval: 3
-}
diff -urN tiarra-20040215/tiarra tiarra-20040223/tiarra
--- tiarra-20040215/tiarra	2004-02-15 09:21:35.000000000 +0900
+++ tiarra-20040223/tiarra	2004-02-23 11:47:36.000000000 +0900
@@ -5,7 +5,7 @@
 # This is free software; you can redistribute it and/or modify it
 #   under the same terms as Perl itself.
 # -----------------------------------------------------------------------------
-# $Id: tiarra,v 1.32 2004/02/14 16:40:34 admin Exp $
+# $Id: tiarra,v 1.33 2004/02/23 02:46:18 topia Exp $
 # -----------------------------------------------------------------------------
 require 5.006;
 use strict;
@@ -177,6 +177,7 @@
     };
     $SIG{__DIE__} = sub {
 	use Carp;
+	die @_ if $_[0] =~ /^[Cc]ouldn't connect/;
 	die(Carp::longmess(@_));
     }
 } else {
