diff -urN tiarra-20100211/.svnversion tiarra-20100212/.svnversion
--- tiarra-20100211/.svnversion	2010-02-11 03:24:27.000000000 +0900
+++ tiarra-20100212/.svnversion	2010-02-12 03:34:30.000000000 +0900
@@ -1 +1 @@
-36684
\ No newline at end of file
+36726
\ No newline at end of file
diff -urN tiarra-20100211/ChangeLog.svn tiarra-20100212/ChangeLog.svn
--- tiarra-20100211/ChangeLog.svn	2010-02-11 03:24:41.000000000 +0900
+++ tiarra-20100212/ChangeLog.svn	2010-02-12 03:34:42.000000000 +0900
@@ -1,4 +1,108 @@
 ------------------------------------------------------------------------
+r36726 | topia | 2010-02-12 03:33:27 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/all.conf
+   M /lang/perl/tiarra/trunk/doc/module/Channel.html
+   M /lang/perl/tiarra/trunk/sample.conf
+
+update documentation.
+------------------------------------------------------------------------
+r36725 | topia | 2010-02-12 03:33:02 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Channel/Join/Connect.pm
+
+make it worked with old configuration module.
+------------------------------------------------------------------------
+r36724 | topia | 2010-02-12 03:28:00 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/NEWS
+
+write NEWS to release archive.
+------------------------------------------------------------------------
+r36723 | topia | 2010-02-12 03:26:27 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/doc-src/conf-main.tdoc
+
+add comment about irc.juggler.jp.
+------------------------------------------------------------------------
+r36722 | topia | 2010-02-12 03:25:53 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Channel/Join/Connect.pm
+
+use general configuration entry.
+------------------------------------------------------------------------
+r36721 | topia | 2010-02-12 03:18:25 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/doc-src/conf-main.tdoc
+
+add documentation for general/join-{interval,channels-per-command}.
+------------------------------------------------------------------------
+r36720 | topia | 2010-02-12 03:13:54 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/main/Configuration.pm
+   M /lang/perl/tiarra/trunk/main/IrcIO/Server.pm
+   M /lang/perl/tiarra/trunk/main/RunLoop.pm
+
+add interval config entry for rejoin channels at network reconnected.
+------------------------------------------------------------------------
+r36719 | topia | 2010-02-12 02:24:01 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/all.conf
+   M /lang/perl/tiarra/trunk/doc/module-toc.html
+   M /lang/perl/tiarra/trunk/doc-src/module-group.tdoc
+   M /lang/perl/tiarra/trunk/sample.conf
+
+update documentation.
+------------------------------------------------------------------------
+r36718 | topia | 2010-02-12 02:21:29 +0900 (Fri, 12 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Channel/Rejoin.pm
+   A /lang/perl/tiarra/trunk/module/Network
+   A /lang/perl/tiarra/trunk/module/Network/Freenode.pm
+
+add chanserv-controlled channel handling to Channel::Rejoin, and add Network::Freenode for discover chanserv-controlled channel.
+------------------------------------------------------------------------
+r36709 | topia | 2010-02-11 19:47:42 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/doc/module/Channel.html
+   M /lang/perl/tiarra/trunk/sample.conf
+
+update documentation.
+------------------------------------------------------------------------
+r36708 | syo68k | 2010-02-11 19:23:54 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/all.conf
+
+Channel::Join::Connect::interval追加
+------------------------------------------------------------------------
+r36707 | syo68k | 2010-02-11 19:22:35 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Channel/Join/Connect.pm
+
+intervalの説明について微修正
+------------------------------------------------------------------------
+r36687 | topia | 2010-02-11 05:27:11 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Channel/Join/Connect.pm
+
+add interval configuration entry.
+------------------------------------------------------------------------
+r36686 | topia | 2010-02-11 03:47:59 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/all.conf
+   M /lang/perl/tiarra/trunk/doc/module/Log.html
+   M /lang/perl/tiarra/trunk/module/Log/Channel.pm
+   M /lang/perl/tiarra/trunk/sample.conf
+
+fix documentation.
+------------------------------------------------------------------------
+r36685 | klm | 2010-02-11 03:35:23 +0900 (Thu, 11 Feb 2010) | 1 line
+Changed paths:
+   M /lang/perl/tiarra/trunk/module/Log/Channel.pm
+   M /lang/perl/tiarra/trunk/sample.conf
+
+a new variable lc_channel is available for unifying log directories of Log::Channel in case-sensitive filesystems.
+------------------------------------------------------------------------
 r36684 | topia | 2010-02-11 03:20:57 +0900 (Thu, 11 Feb 2010) | 1 line
 Changed paths:
    M /lang/perl/tiarra/trunk/NEWS
diff -urN tiarra-20100211/NEWS tiarra-20100212/NEWS
--- tiarra-20100211/NEWS	2010-02-11 03:24:27.000000000 +0900
+++ tiarra-20100212/NEWS	2010-02-12 03:34:30.000000000 +0900
@@ -1,3 +1,17 @@
+2010-02-12  Topia  <topia@clovery.jp>
+
+	* Log::Channel (thanks klm)
+	  - ログディレクトリの大文字小文字問題に対応するため
+	    lc_channel を追加した。
+	* IrcIO::Server, Channel::Join::Connect (thanks syo68k)
+	  - irc.juggler.jp において多数のチャンネルに join する際に
+	    Excess Flood が生じる問題に対応するため、 interval と
+	    channels を設定可能にした。
+	* Channel::Rejoin
+	  - chanserv で管理されていると検出した場合は無視するようにした。
+	* Network::Freenode
+	  - freenode 用の ChanServ 検出モジュール。
+
 2010-02-11  Topia  <topia@clovery.jp>
 
 	* Channel::Rejoin
diff -urN tiarra-20100211/all.conf tiarra-20100212/all.conf
--- tiarra-20100211/all.conf	2010-02-11 03:24:31.000000000 +0900
+++ tiarra-20100212/all.conf	2010-02-12 03:34:33.000000000 +0900
@@ -136,6 +136,20 @@
   # multi-server-mode 時のデフォルトは 0 、 single-server-mode 時のデフォルトは 1 です。
   #nick-fix-mode: 0
 
+  # Tiarra がチャンネルに join する際の挙動を設定します。
+  # デフォルト設定で Excess Flood になってしまう場合に設定してください。
+  #
+  # irc.juggler.jp (2ch@IRC) にて 25 チャンネル以上 join している場合に
+  # Excess Flood になってしまった事例があるそうです。
+
+  # JOIN コマンドを送信する間隔 (秒)
+  # デフォルトは1秒です。
+  join-interval: 1
+
+  # 一つの JOIN コマンドで指定するチャンネルの数
+  # デフォルトは5チャンネルです。
+  join-channels-per-command: 5
+
   messages {
     # Tiarra が使用する、いくつかのメッセージを指定する。
 
@@ -1253,6 +1267,11 @@
   #   「#aaaaa@ircnet」、「#bbbbb@ircnet:*.jp」、「#ccccc@ircnet」、「#ddddd@ircnet」の4つのチャンネルに入る。
   #channel: #aaaaa@ircnet,#bbbbb@ircnet:*.jp, #ccccc@ircnet
   #channel: #ddddd@ircnet
+
+  # join 送出の間隔(秒)
+  # この設定は obsolete です。 general/join-interval を利用してください。
+  # 設定されていた場合は general/join-interval に優先されます。
+  #interval: 1
 }
 
 - Channel::Join::Invite {
@@ -1592,8 +1611,12 @@
   # それ以外(privも含む)のログはothers/%Y.%m.%d.txtに保存される。
   # #(channel) はチャンネル名に展開される。
   # (古いバージョンだと展開されずにそのままディレクトリ名になってしまいます。)
+  # IRCのチャンネル名は大文字小文字が区別されず、サーバからは各送信者が指定した通りの
+  # チャンネル名が送られてきます。そのため、大文字小文字が区別されるファイルシステムでは
+  # 同じチャンネルが別々のディレクトリに作られることになります。
+  # この問題を回避するため、チャンネル名を小文字に統一した #(lc_channel) が利用できます。
   channel: priv priv
-  channel: #(channel) *
+  channel: #(lc_channel) *
   #channel: others *
 
   # ファイル名のエンコーディング.
@@ -1723,6 +1746,21 @@
   command: privmsg,notice,topic,join,part,quit,kill
 }
 
++ Network::Freenode {
+  # Freenode サポート
+
+  # 現状では ChanServ の検出以外の機能はありません。
+  # drop による状況の変化についてもサポートしていません。
+
+  # Channel::Rejoin では、このモジュールによってチャンネルが
+  # ChanServ の管理下にあると検出した時には Rejoin 動作を
+  # 行わなくなります。
+
+  # 設定はありません。
+  # また、 freenode 以外のネットワークでこのモジュールが
+  # 有効になっていても不都合はないはずです。
+}
+
 - Skeleton {
   # Skeleton for tiarra-module.
 
diff -urN tiarra-20100211/doc/module/Channel.html tiarra-20100212/doc/module/Channel.html
--- tiarra-20100211/doc/module/Channel.html	2010-02-11 03:24:31.000000000 +0900
+++ tiarra-20100212/doc/module/Channel.html	2010-02-12 03:34:33.000000000 +0900
@@ -95,6 +95,12 @@
 </p>
 <div class="element"><span class="key">channel</span>:<span class="value">#aaaaa@ircnet,#bbbbb@ircnet:*.jp, #ccccc@ircnet</span></div>
 <div class="element"><span class="key">channel</span>:<span class="value">#ddddd@ircnet</span></div>
+<p class="comment">
+join 送出の間隔(秒)<br />
+この設定は obsolete です。 general/join-interval を利用してください。<br />
+設定されていた場合は general/join-interval に優先されます。<br />
+</p>
+<div class="element"><span class="key">interval</span>:<span class="value">1</span></div>
 
         </div>
       </div>
diff -urN tiarra-20100211/doc/module/Log.html tiarra-20100212/doc/module/Log.html
--- tiarra-20100211/doc/module/Log.html	2010-02-11 03:24:31.000000000 +0900
+++ tiarra-20100212/doc/module/Log.html	2010-02-12 03:34:33.000000000 +0900
@@ -103,9 +103,13 @@
 それ以外(privも含む)のログはothers/%Y.%m.%d.txtに保存される。<br />
 #(channel) はチャンネル名に展開される。<br />
 (古いバージョンだと展開されずにそのままディレクトリ名になってしまいます。)<br />
+IRCのチャンネル名は大文字小文字が区別されず、サーバからは各送信者が指定した通りの<br />
+チャンネル名が送られてきます。そのため、大文字小文字が区別されるファイルシステムでは<br />
+同じチャンネルが別々のディレクトリに作られることになります。<br />
+この問題を回避するため、チャンネル名を小文字に統一した #(lc_channel) が利用できます。<br />
 </p>
 <div class="element"><span class="key">channel</span>:<span class="value">priv priv</span></div>
-<div class="element"><span class="key">channel</span>:<span class="value">#(channel) *</span></div>
+<div class="element"><span class="key">channel</span>:<span class="value">#(lc_channel) *</span></div>
 <div class="element"><span class="key">channel</span>:<span class="value">others *</span></div>
 <p class="comment">
 ファイル名のエンコーディング.<br />
diff -urN tiarra-20100211/doc/module/Network.html tiarra-20100212/doc/module/Network.html
--- tiarra-20100211/doc/module/Network.html	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20100212/doc/module/Network.html	2010-02-12 03:34:33.000000000 +0900
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+	  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+	  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!-- $Id: contents.html 11393 2008-05-11 06:56:12Z topia $ -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <title>Network 関係のモジュール - Tiarra Documentation</title>
+    <link rel="stylesheet" type="text/css" href="../default.css" />
+  </head>
+  <body>
+    <div class="header">
+      <h1>Network 関係のモジュール</h1>
+    </div>
+
+    <hr class="sep" />
+
+    <div class="pane-main">
+      
+      <div id="module-Network::Freenode" class="module">
+        <div class="module-header"><h2 title="Freenode サポート">Network::Freenode</h2>
+          <span class="description">Freenode サポート</span></div>
+        <div class="content">
+	  <p class="comment">
+現状では ChanServ の検出以外の機能はありません。<br />
+drop による状況の変化についてもサポートしていません。<br />
+</p>
+<p class="comment">
+Channel::Rejoin では、このモジュールによってチャンネルが<br />
+ChanServ の管理下にあると検出した時には Rejoin 動作を<br />
+行わなくなります。<br />
+</p>
+<p class="comment">
+設定はありません。<br />
+また、 freenode 以外のネットワークでこのモジュールが<br />
+有効になっていても不都合はないはずです。<br />
+</p>
+
+        </div>
+      </div>
+
+      
+      
+    </div>
+
+    <div class="pane-sidebar">
+      <ul class="menu">
+        
+        <li><a href="#module-Network::Freenode" title="Freenode サポート">Network::Freenode</a></li>
+        
+        <li><a href="../module-toc.html">モジュール一覧に戻る</a></li>
+      </ul>
+    </div>
+  </body>
+</html>
diff -urN tiarra-20100211/doc/module-toc.html tiarra-20100212/doc/module-toc.html
--- tiarra-20100211/doc/module-toc.html	2010-02-11 03:24:31.000000000 +0900
+++ tiarra-20100212/doc/module-toc.html	2010-02-12 03:34:33.000000000 +0900
@@ -161,6 +161,15 @@
       </li>
       
       <li>
+	<a href="module/Network.html">Network</a> <span class="group-description">個別IRC ネットワーク対応のモジュール</span>
+	<ul class="toc-individual">
+	  
+	  <li><a href="module/Network.html#module-Network::Freenode">Network::Freenode</a> <span class="module-description">Freenode サポート</span></li>
+	  
+	</ul>
+      </li>
+      
+      <li>
 	<a href="module/System.html">System</a> <span class="group-description">Tiarra自身の動作に関するもの</span>
 	<ul class="toc-individual">
 	  
diff -urN tiarra-20100211/doc-src/conf-main.tdoc tiarra-20100212/doc-src/conf-main.tdoc
--- tiarra-20100211/doc-src/conf-main.tdoc	2010-02-11 03:24:30.000000000 +0900
+++ tiarra-20100212/doc-src/conf-main.tdoc	2010-02-12 03:34:32.000000000 +0900
@@ -1,5 +1,5 @@
 -*- outline -*-
-$Id: conf-main.tdoc 36552 2010-01-27 14:53:29Z drry $
+$Id: conf-main.tdoc 36723 2010-02-11 18:26:27Z topia $
 
 perlのソースに使うpodパーサを流用しているので、package文と=pod〜=cutで書く必要があります。
 ヘッダのinfo-is-ommitedとno-switchはどちらも値を真に定義しなければなりません。
@@ -134,6 +134,20 @@
 # multi-server-mode 時のデフォルトは 0 、 single-server-mode 時のデフォルトは 1 です。
 -nick-fix-mode: 0
 
+# Tiarra がチャンネルに join する際の挙動を設定します。
+# デフォルト設定で Excess Flood になってしまう場合に設定してください。
+#
+# irc.juggler.jp (2ch@IRC) にて 25 チャンネル以上 join している場合に
+# Excess Flood になってしまった事例があるそうです。
+
+# JOIN コマンドを送信する間隔 (秒)
+# デフォルトは1秒です。
+join-interval: 1
+
+# 一つの JOIN コマンドで指定するチャンネルの数
+# デフォルトは5チャンネルです。
+join-channels-per-command: 5
+
 messages {
   # Tiarra が使用する、いくつかのメッセージを指定する。
 
diff -urN tiarra-20100211/doc-src/module-group.tdoc tiarra-20100212/doc-src/module-group.tdoc
--- tiarra-20100211/doc-src/module-group.tdoc	2010-02-11 03:24:30.000000000 +0900
+++ tiarra-20100212/doc-src/module-group.tdoc	2010-02-12 03:34:32.000000000 +0900
@@ -1,5 +1,5 @@
 -*- outline -*-
-$Id: module-group.tdoc 11365 2008-05-10 14:58:28Z topia $
+$Id: module-group.tdoc 36719 2010-02-11 17:24:01Z topia $
 
 各モジュールの分類名(= グループ名)と、その説明。
 グループ名とは、モジュール名のm/^(.+?)::/で与えられる部分を指す。
@@ -42,6 +42,12 @@
 description: ログの記録
 =cut
 
+* Network
+package Network;
+=pod
+description: 個別IRC ネットワーク対応のモジュール
+=cut
+
 * System
 package System;
 =pod
diff -urN tiarra-20100211/main/Configuration.pm tiarra-20100212/main/Configuration.pm
--- tiarra-20100211/main/Configuration.pm	2010-02-11 03:24:28.000000000 +0900
+++ tiarra-20100212/main/Configuration.pm	2010-02-12 03:34:31.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Configuration.pm 29652 2009-02-06 13:55:13Z topia $
+# $Id: Configuration.pm 36720 2010-02-11 18:13:54Z topia $
 # -----------------------------------------------------------------------------
 # このクラスはフック`reloaded'を用意します。
 # フック`reloaded'は、設定ファイルがリロードされた時に呼ばれます。
@@ -187,6 +187,8 @@
 	'client-out-encoding' => 'jis',
 	'stdout-encoding' => 'utf8',
 	'sysmsg-prefix' => 'tiarra',
+	'join-interval' => 1,
+	'join-channels-per-command' => 5,
 	'sysmsg-prefix-use-masks' => {
 	    'system' => '*',
 	    'priv' => '',
diff -urN tiarra-20100211/main/IrcIO/Server.pm tiarra-20100212/main/IrcIO/Server.pm
--- tiarra-20100211/main/IrcIO/Server.pm	2010-02-11 03:24:28.000000000 +0900
+++ tiarra-20100212/main/IrcIO/Server.pm	2010-02-12 03:34:30.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Server.pm 36683 2010-02-10 17:15:44Z topia $
+# $Id: Server.pm 36720 2010-02-11 18:13:54Z topia $
 # -----------------------------------------------------------------------------
 # IrcIO::ServerはIRCサーバーに接続し、IRCメッセージをやり取りするクラスです。
 # このクラスはサーバーからメッセージを受け取ってチャンネル情報や現在のnickなどを保持しますが、
@@ -471,6 +471,10 @@
 	$this->{timer}->uninstall;
 	$this->{timer} = undef;
     }
+    if (defined $this->{rejoin_timer}) {
+	$this->{rejoin_timer}->uninstall;
+	$this->{rejoin_timer} = undef;
+    }
     if ($this->state_terminating) {
 	$this->state_terminated(1);
     } elsif ($this->state_finalizing) {
@@ -1247,7 +1251,9 @@
 	# 常に Tiarra が処理します。
 
 	$this->_set_to_next_nick($msg->param(1));
-	return undef;
+	$msg->remark('do-not-send-to-clients',1);
+	## 破棄せず do-not-send-to-clients をつける。
+	return $msg;
     } elsif ($mode == 1) {
 	# クライアントにそのまま投げます。
 	# 複数のクライアントが nick 重複を処理する場合は非常に危険です。
@@ -1330,4 +1336,56 @@
     return $nick;
 }
 
+sub rejoin_all_channels {
+    my ($this) = @_;
+    # 記憶している全てのチャンネルにJOINする。
+    # そもそもJOINしていないチャンネルは通常IrcIO::Serverは記憶していないが、
+    # サーバーから切断された時だけは例外である。
+    my @ch_with_key; # パスワードを持ったチャンネルの配列。要素は["チャンネル名","パスワード"]
+    my @ch_without_key; # パスワードを持たないチャンネルの配列。要素は"チャンネル名"
+
+    foreach my $ch ($this->channels_list) {
+	my $key = $ch->parameters('k');
+	if (defined $key && $key ne '') {
+	    push(@ch_with_key, [$ch->name, $key]);
+	} else {
+	    push(@ch_without_key, $ch->name);
+	}
+    }
+
+    my $interval = $this->_runloop->_conf_general->join_interval;
+    my $channels = $this->_runloop->_conf_general->join_channels_per_command;
+
+    $this->{rejoin_timer} = Timer->new(
+	Name => $this->_gen_msg('rejoin timer'),
+	Interval => $interval,
+	Repeat => 1,
+	Code => sub {
+	    my $timer = shift;
+	    my $remind = $channels;
+	    if ($remind && @ch_with_key) {
+		my (@targets) = splice(@ch_with_key, 0, $remind);
+		$this->send_message(
+		    $this->construct_irc_message(
+			Command => 'JOIN',
+			Params => [join(',', map { $_->[0] } @targets),
+				   join(',', map { $_->[1] } @targets)]));
+		$remind -= scalar(@targets);
+	    }
+	    if ($remind && @ch_without_key) {
+		my (@targets) = splice(@ch_without_key, 0, $remind);
+		$this->send_message(
+		    $this->construct_irc_message(
+			Command => 'JOIN',
+			Params => [join(',', @targets)]));
+		$remind -= scalar(@targets);
+	    }
+	    if (!@ch_with_key && !@ch_without_key) {
+		## nothing found
+		$this->{rejoin_timer} = undef;
+		$timer->uninstall;
+	    }
+	})->install;
+}
+
 1;
diff -urN tiarra-20100211/main/RunLoop.pm tiarra-20100212/main/RunLoop.pm
--- tiarra-20100211/main/RunLoop.pm	2010-02-11 03:24:28.000000000 +0900
+++ tiarra-20100212/main/RunLoop.pm	2010-02-12 03:34:31.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: RunLoop.pm 13831 2008-06-13 14:01:33Z topia $
+# $Id: RunLoop.pm 36720 2010-02-11 18:13:54Z topia $
 # -----------------------------------------------------------------------------
 # このクラスはTiarraのメインループを実装します。
 # select()を実行し、サーバーやクライアントとのI/Oを行うのはこのクラスです。
@@ -419,60 +419,7 @@
 }
 sub _rejoin_all_channels {
     my ($this,$network) = @_;
-    # networkが記憶している全てのチャンネルにJOINする。
-    # そもそもJOINしていないチャンネルは通常IrcIO::Serverは記憶していないが、
-    # サーバーから切断された時だけは例外である。
-    # 尚、註釈kicked-outが付けられているチャンネルにはJOINしない。
-    my @ch_with_key; # パスワードを持ったチャンネルの配列。要素は["チャンネル名","パスワード"]
-    my @ch_without_key; # パスワードを持たないチャンネルの配列。要素は"チャンネル名"
-    foreach my $ch (values %{$network->channels}) {
-	next if $ch->remarks('kicked-out');
-
-	my $password = $ch->parameters('k');
-	if (defined $password && $password ne '') {
-	    push @ch_with_key,[$ch->name,$password];
-	}
-	else {
-	    push @ch_without_key,$ch->name;
-	}
-    }
-    # JOIN実行
-    my ($buf_ch,$buf_key) = ('','');
-    my $buf_flush = sub {
-	return if ($buf_ch eq '');
-	my $params = do {
-	    if ($buf_key eq '') {
-		[$buf_ch];
-	    }
-	    else {
-		[$buf_ch,$buf_key];
-	    }
-	};
-	$network->send_message(
-	    $this->construct_irc_message(
-		Command => 'JOIN',
-		Params => $params));
-	$buf_ch = $buf_key = '';
-    };
-    my $buf_put = sub {
-	my ($ch,$key) = @_;
-	$buf_ch .= ($buf_ch eq '' ? $ch : ",$ch");
-	$buf_key .= ($buf_key eq '' ? $key : ",$key") if defined $key;
-	if (length($buf_ch) + length($buf_key) > 400) {
-	    # 400バイトを越えたら自動でフラッシュする。
-	    $buf_flush->();
-	}
-    };
-    # パスワード付きのチャンネルにJOIN
-    foreach (@ch_with_key) {
-	$buf_put->($_->[0],$_->[1]);
-    }
-    $buf_flush->();
-    # パスワード無しのチャンネルにJOIN
-    foreach (@ch_without_key) {
-	$buf_put->($_);
-    }
-    $buf_flush->();
+    $network->rejoin_all_channels();
 }
 
 sub update_networks {
diff -urN tiarra-20100211/module/Channel/Join/Connect.pm tiarra-20100212/module/Channel/Join/Connect.pm
--- tiarra-20100211/module/Channel/Join/Connect.pm	2010-02-11 03:24:29.000000000 +0900
+++ tiarra-20100212/module/Channel/Join/Connect.pm	2010-02-12 03:34:31.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Connect.pm 36683 2010-02-10 17:15:44Z topia $
+# $Id: Connect.pm 36725 2010-02-11 18:33:02Z topia $
 # -----------------------------------------------------------------------------
 # copyright (C) 2002 Topia <topia@clovery.jp>. all rights reserved.
 package Channel::Join::Connect;
@@ -16,6 +16,8 @@
     # channellist : HASH
     #   shortname => チャンネルショートネーム
     #   key => channel key
+    $this->{interval} = 1; # interval (sec)
+    $this->{channels} = 5; # channels
     $this->_init;
 }
 
@@ -41,6 +43,19 @@
 	}
     }
 
+    ## FIXME _conf_general
+    $this->{interval} = $this->_runloop->_conf_general->join_interval;
+    $this->{interval} = 1 unless defined $this->{interval};
+    $this->{channels} = $this->_runloop->_conf_general->join_channels_per_command;
+    $this->{channels} = 5 unless defined $this->{channels};
+
+    if ($this->config->interval) {
+	$this->{interval} = 0+$this->config->interval;
+	if ($this->{interval} == 0) {
+	    die "Channel::Join::Connect: do not set interval to 0!"
+	}
+    }
+
     $this;
 }
 
@@ -51,13 +66,13 @@
 
     if (defined($session)) {
 	Timer->new(
-	    Interval => 1,
+	    Interval => $this->{interval},
 	    Repeat => 1,
 	    Code => sub {
 		my $timer = shift;
 		if (@$session > 0) {
 		    # 一度に五つずつ送り出す。
-		    my $msg_per_trigger = 5;
+		    my $msg_per_trigger = $this->{channels};
 		    my (@param_chan, @param_key);
 		    for (my $i = 0; $i < @$session && $i < $msg_per_trigger; $i++) {
 			if (!defined($session->[$i]->{key}) || $session->[$i]->{key} eq '') {
@@ -98,4 +113,9 @@
 #   「#aaaaa@ircnet」、「#bbbbb@ircnet:*.jp」、「#ccccc@ircnet」、「#ddddd@ircnet」の4つのチャンネルに入る。
 -channel: #aaaaa@ircnet,#bbbbb@ircnet:*.jp, #ccccc@ircnet
 -channel: #ddddd@ircnet
+
+# join 送出の間隔(秒)
+# この設定は obsolete です。 general/join-interval を利用してください。
+# 設定されていた場合は general/join-interval に優先されます。
+-interval: 1
 =cut
diff -urN tiarra-20100211/module/Channel/Rejoin.pm tiarra-20100212/module/Channel/Rejoin.pm
--- tiarra-20100211/module/Channel/Rejoin.pm	2010-02-11 03:24:29.000000000 +0900
+++ tiarra-20100212/module/Channel/Rejoin.pm	2010-02-12 03:34:31.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Rejoin.pm 36682 2010-02-10 17:06:17Z topia $
+# $Id: Rejoin.pm 36718 2010-02-11 17:21:29Z topia $
 # -----------------------------------------------------------------------------
 # このモジュールは動作時に掲示板のdo-not-touch-mode-of-channelsを使います。
 # -----------------------------------------------------------------------------
@@ -94,6 +94,10 @@
 	# 自分が@を持っている。
 	return;
     }
+    if ($ch->remark('chanserv-controlled')) {
+	# ChanServ 管理チャンネルであれば、無駄な努力はしない。
+	return;
+    }
     return 1;
 }
 
@@ -221,7 +225,9 @@
 sub session_work {
     my ($this,$msg,$server) = @_;
     my $session;
-    # ウォッチの対象になるのはJOIN,324,368,349,347。
+    # ウォッチの対象になるのはJOIN,324,368,349,347,482。
+    # リストはコマンドを発行していれば IrcIO::Server が
+    # 保持しておいてくれる。
 
     my $got_reply = sub {
 	my $type = shift;
diff -urN tiarra-20100211/module/Log/Channel.pm tiarra-20100212/module/Log/Channel.pm
--- tiarra-20100211/module/Log/Channel.pm	2010-02-11 03:24:29.000000000 +0900
+++ tiarra-20100212/module/Log/Channel.pm	2010-02-12 03:34:31.000000000 +0900
@@ -1,5 +1,5 @@
 # -----------------------------------------------------------------------------
-# $Id: Channel.pm 12214 2008-05-22 11:34:11Z topia $
+# $Id: Channel.pm 36686 2010-02-10 18:47:59Z topia $
 # -----------------------------------------------------------------------------
 package Log::Channel;
 use strict;
@@ -194,7 +194,7 @@
 	      sprintf('=%02x', unpack("C", $1));
 	    }ge;
 	    my $chan_dir = Tools::HashTools::replace_recursive(
-		$ch->[0], [{channel => $chan_filename}]);
+		$ch->[0], [{channel => $chan_filename, lc_channel => lc $chan_filename}]);
 	    my $fpath_format = "$chan_dir/$fname_format";
 
 	    $this->{matching_cache}->{$channel} = $fpath_format;
@@ -409,8 +409,12 @@
 # それ以外(privも含む)のログはothers/%Y.%m.%d.txtに保存される。
 # #(channel) はチャンネル名に展開される。
 # (古いバージョンだと展開されずにそのままディレクトリ名になってしまいます。)
+# IRCのチャンネル名は大文字小文字が区別されず、サーバからは各送信者が指定した通りの
+# チャンネル名が送られてきます。そのため、大文字小文字が区別されるファイルシステムでは
+# 同じチャンネルが別々のディレクトリに作られることになります。
+# この問題を回避するため、チャンネル名を小文字に統一した #(lc_channel) が利用できます。
 channel: priv priv
-channel: #(channel) *
+channel: #(lc_channel) *
 -channel: others *
 
 # ファイル名のエンコーディング.
diff -urN tiarra-20100211/module/Network/Freenode.pm tiarra-20100212/module/Network/Freenode.pm
--- tiarra-20100211/module/Network/Freenode.pm	1970-01-01 09:00:00.000000000 +0900
+++ tiarra-20100212/module/Network/Freenode.pm	2010-02-12 03:34:32.000000000 +0900
@@ -0,0 +1,64 @@
+# -----------------------------------------------------------------------------
+# $Id: Freenode.pm 36718 2010-02-11 17:21:29Z topia $
+# -----------------------------------------------------------------------------
+# Freenode support.
+# -----------------------------------------------------------------------------
+# copyright (C) 2010 Topia <topia@clovery.jp>. all rights reserved.
+package Network::Freenode;
+use strict;
+use warnings;
+use NumericReply;
+use base qw(Module);
+
+sub config_reload {
+    my ($this, $old_config) = @_;
+    return $this;
+}
+
+sub message_arrived {
+    my ($this,$msg,$sender) = @_;
+
+    if ($sender->isa('IrcIO::Server') &&
+	    ($sender->isupport->{NETWORK} || '') eq 'freenode') {
+	my $cmd = $msg->command;
+	if (($msg->prefix->prefix eq 'ChanServ!ChanServ@services.') &&
+		$cmd =~ /^(?:PART|JOIN|MODE|TOPIC)$/) {
+	    my $ch_name = $msg->param(0);
+	    my $ch = $this->_runloop->channel($ch_name);
+	    if (defined $ch) {
+		$ch->remark('chanserv-controlled', 1);
+	    }
+	} elsif ($cmd eq RPL_ENDOFNAMES) {
+	    my $ch_name = $msg->param(1);
+	    my $ch = $this->_runloop->channel($ch_name);
+	    if (defined $ch->names('ChanServ')) {
+		$ch->remark('chanserv-controlled', 1);
+	    }
+	}
+    }
+
+    return $msg;
+}
+
+1;
+
+=begin tiarra-doc
+
+info: Freenode サポート
+default: on
+section: important
+
+# 現状では ChanServ の検出以外の機能はありません。
+# drop による状況の変化についてもサポートしていません。
+
+# Channel::Rejoin では、このモジュールによってチャンネルが
+# ChanServ の管理下にあると検出した時には Rejoin 動作を
+# 行わなくなります。
+
+# 設定はありません。
+# また、 freenode 以外のネットワークでこのモジュールが
+# 有効になっていても不都合はないはずです。
+
+=end tiarra-doc
+
+=cut
diff -urN tiarra-20100211/sample.conf tiarra-20100212/sample.conf
--- tiarra-20100211/sample.conf	2010-02-11 03:24:30.000000000 +0900
+++ tiarra-20100212/sample.conf	2010-02-12 03:34:33.000000000 +0900
@@ -175,6 +175,20 @@
   # multi-server-mode 時のデフォルトは 0 、 single-server-mode 時のデフォルトは 1 です。
   #nick-fix-mode: 0
 
+  # Tiarra がチャンネルに join する際の挙動を設定します。
+  # デフォルト設定で Excess Flood になってしまう場合に設定してください。
+  #
+  # irc.juggler.jp (2ch@IRC) にて 25 チャンネル以上 join している場合に
+  # Excess Flood になってしまった事例があるそうです。
+
+  # JOIN コマンドを送信する間隔 (秒)
+  # デフォルトは1秒です。
+  join-interval: 1
+
+  # 一つの JOIN コマンドで指定するチャンネルの数
+  # デフォルトは5チャンネルです。
+  join-channels-per-command: 5
+
   messages {
     # Tiarra が使用する、いくつかのメッセージを指定する。
 
@@ -528,6 +542,11 @@
   #   「#aaaaa@ircnet」、「#bbbbb@ircnet:*.jp」、「#ccccc@ircnet」、「#ddddd@ircnet」の4つのチャンネルに入る。
   #channel: #aaaaa@ircnet,#bbbbb@ircnet:*.jp, #ccccc@ircnet
   #channel: #ddddd@ircnet
+
+  # join 送出の間隔(秒)
+  # この設定は obsolete です。 general/join-interval を利用してください。
+  # 設定されていた場合は general/join-interval に優先されます。
+  #interval: 1
 }
 
 - Channel::Join::Invite {
@@ -708,8 +727,12 @@
   # それ以外(privも含む)のログはothers/%Y.%m.%d.txtに保存される。
   # #(channel) はチャンネル名に展開される。
   # (古いバージョンだと展開されずにそのままディレクトリ名になってしまいます。)
+  # IRCのチャンネル名は大文字小文字が区別されず、サーバからは各送信者が指定した通りの
+  # チャンネル名が送られてきます。そのため、大文字小文字が区別されるファイルシステムでは
+  # 同じチャンネルが別々のディレクトリに作られることになります。
+  # この問題を回避するため、チャンネル名を小文字に統一した #(lc_channel) が利用できます。
   channel: priv priv
-  channel: #(channel) *
+  channel: #(lc_channel) *
   #channel: others *
 
   # ファイル名のエンコーディング.
@@ -737,6 +760,21 @@
   command: privmsg,notice,topic,join,part,quit,kill
 }
 
++ Network::Freenode {
+  # Freenode サポート
+
+  # 現状では ChanServ の検出以外の機能はありません。
+  # drop による状況の変化についてもサポートしていません。
+
+  # Channel::Rejoin では、このモジュールによってチャンネルが
+  # ChanServ の管理下にあると検出した時には Rejoin 動作を
+  # 行わなくなります。
+
+  # 設定はありません。
+  # また、 freenode 以外のネットワークでこのモジュールが
+  # 有効になっていても不都合はないはずです。
+}
+
 + System::Error {
   # サーバーからのERRORメッセージをNOTICEに埋め込む
 
