■ゆいちゃっとFAQ■


▼設置編▼
設置する際に注意すべきことをまとめてみました。
サポート掲示板に寄せられる質問も,実はほとんどがこれらの問題か,その変形であるようです。
実際には,サーバによって条件が異なりますので,ここに書いてある情報だけでは不足でしょう。


◆ CGIを設置するにあたっての心得
CGIプログラムは,プログラムなのです。
環境によっても,条件によっても動いたり動かなかったりしますし,ちょっとの見落としがエラーを招いたりもします。
エラーが出てもあわてず,落ち着いて次はどうしたらいいかを考えましょう。

この項では,設置にあたって起こりがちなトラブルの原因と対処法を紹介しています。きっと,役に立つでしょう。(って,ホントかなぁ.....汗)

◆ 設置したけど動きません&サーバーエラーが出るのですが
.....という質問がしばしば寄せられますが,これではさっぱりわかりません。
道行く人に「わたしの家はどこですか?」と訊ねるようなものです。
もしあなたが地図を読むことができないのなら,最低限住所くらいは教えないと,訊かれた人が困ってしまいます。もしあるなら,地図を渡してかわりに読んでもらうべきでしょう。

これとおなじことがCGIのデバッグにもいえます。
もし自分で対処できないのなら,URL(住所)とソース(地図)を見せて,どうやって対処するべきかを訊ねましょう。具体的なエラーが出るのであれば,エラーの内容も伝えるべきでしょう。あなたがささいなことだと思う要素でも,その情報があるのと無いのとでは,原因追究の手間が10倍も違うことがあるのです...。

▼ サーバーエラーの原因は
では実際に,サーバーエラーになったときどのあたりに原因があることが多いか....
どこから確認したら効率がよいかというのは,実はだいたい決まっているのです。(例外もありますが)
ここでは,「ありがち」なエラーについて解説しましょう....

◆ CGIの使えるプロバイダですか?
さて。CGIプログラムを設置したけど動かない〜とあわてる前に,まず確認です。

・あなたの使っているプロバイダは,本当にCGIを許可していますか?ひょっとしたら決められたCGIしか使えないなんてこともあります。

・CGIプログラムを置く場所は,本当にそこでよいのですか?決められたディレクトリや決められたサーバに置かなくてはならないところが結構あります。また,CGIプログラムを置く場所には,それ以外のものを置けない場合もありますので注意。

・プロバイダによって,特殊変数や関数の使用が制限されているものはありませんか?

・ファイル名は,それでよいですか?プログラムをすべて〜.plという名前にしなければ動かないところもあります....

◆ ソースをなおしました?
オリジナルのソースを改変したところがありますか?
もしあるなら,もしかするとそれがおかしいのかもしれません。
おかしな直しかたをすると,コードが正常に終了しません.....というか,コンパイルできません。これはシェルテストをしてみるとすぐにわかる問題です。
はじめて設置する場合は,ソースの変更は可能な限り最低限にとどめるべきでしょう。デザイン変更などは,動作が確認できてから行えばよいのです。

デザインと動作することと,どちらが優先かは言うまでもないでしょう.....(苦笑)

よくある「間違った」ソースの改変
・エスケープ忘れ
Perlでは,「"」や「'」は,基本的に「文字列を囲むもの」です。
そして「文字列を囲むもの」として使われる場合,これらの記号は必ず対になっていなく
てはなりません。このため,もともと「"」で囲まれている文字列内に「"」を使う場合,
「\"」と表記して「"」の働きを無効化(エスケープ)する必要があります。
(正しい例) $value = "This is a \"SAMPLE\" for FAQ\n";
(誤りの例) $value = "This is a "SAMPLE" for FAQ\n";
違いがわかるでしょうか?
後者の場合,Perlはどこまでが「""」で囲まれた部分なのかわからなくなってしまいます。
蛇足ですが,「""」と「''」の違いを簡単に....
結論から言うと「""」のばあい囲まれた値は展開されますが,「''」のばあいは展開され
ません。つまり
$a = 'test';
(変数$aの値がtestのとき)
print "$a";
とすると,printされるのは「test」という文字列ですが
print '$a';
とすると,printされるのは「$a」という文字列なのです。
・閉じ忘れ
「{」,「}」(ブレース)で囲まれた部分は,例外もありますが「ブロック」と呼びます。
これらのブロックは,必ず閉じていなければいけません。ブロックはある一連の処理をひ
とかたまりとして定義するものです。たとえば
if($test eq 'y'){ $test2 = 'yes'; }
(もし変数$testの値がyなら,変数$test2の値にyesを代入しなさい。)
この場合,if文で示された内容が真であれば,ブロック内の処理を行うのです。
ここでブロックが閉じてなかったとしたら,次に「}」が現れるまでがひとつのブロックと
なってしまうのです。これはさすがにまずいでしょ?
・メタ文字の不適切な挿入
メタ文字は何種類かあります。これらはPerlの文法上,重要な役割を持っているため,不
用意な使い方をするとひどい目に遭うことがあります。
メタ文字は「\ | ( ) [ { ^ $ * + ? . 」などです。これらの文字はそれ自身が固有の意
味を持っているため,本来の使い方以外で扱う必要があるときは,「\」を前につけて無害
な形で使いましょう。また変数に値として代入する際には「'+'」などとして展開されない
ような習慣をつけると良いかもしれません。
・「$」,「@」の落とし穴
$は変数名を,@は配列名をあらわします。
したがって,通常の文字列で使う場合は「'Micro$oft'」「'nobody@anonymizer.com'」
あるいは「"Micro\$oft"」「"nobody\@anonymizer.com"」としなくてはいけません。

etc.etc......

◆ flock&symlinkについての噂
サーバーによっては,flock()関数が使えません....
窓系サーバなどで良くあるのですが,サーバのファイルシステムがflock()関数を実装してないと,スクリプトが実行できないことがあります。ゆいちゃっとでは,flock文を直接実行するのではなくeval()で評価しているためスクリプトが正常終了しないという例は少ないのですが.......中にはこの文を無効にしないとダメな場合もあります。なにもしない時はちゃんと実行できるのに,入室や発言(つまりログへの書き込みアクション時)にエラーになるときは,これを疑ってみる必要があるでしょう。
(flock()は,システム側でファイルの排他制御を行うものです。あるプロセスがファイルをlockしている間,ほかのプロセスがファイルに書き込みを行わないというのが基本的な動作原理です)

また,オプションになっている"ロックファイル"はsymlink()関数を利用しています。これはUNIXでいう"シンボリックリンク"を利用するもので,ファイルシステムがこの機能を実装してない場合,確実にサーバエラーになります。

◆ 文字コードの呪い
Perlで日本語をあつかう場合,最も適した文字コードはEUCです。
というのが結論なのですが,これは何故でしょうか?

[JISのばあい]
JISコードの日本語には,Perlにとってイヤなコードが含まれています。
JISコードをASCIIコードに直してみましょう。
■ひらがな
  ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く ぐ け げ こ ご さ ざ し 
  $! $" $# $$ $% $& $' $( $) $* $+ $, $- $. $/ $0 $1 $2 $3 $4 $5 $6 $7 
  じ す ず せ ぜ そ ぞ た だ ち ぢ っ つ づ て で と ど な に ぬ ね の 
  $8 $9 $: $; $< $= $> $? $@ $A $B $C $D $E $F $G $H $I $J $K $L $M $N 
  は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み む め も ゃ や ゅ 
  $O $P $Q $R $S $T $U $V $W $X $Y $Z $[ $\ $] $^ $_ $` $a $b $c $d $e 
  ゆ ょ よ ら り る れ ろ ゎ わ ゐ ゑ を ん
  $f $g $h $i $j $k $l $m $n $o $p $q $r $s
■カタカナ
  ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク グ ケ ゲ コ ゴ サ ザ シ 
  %! %" %# %$ %% %& %' %( %) %* %+ %, %- %. %/ %0 %1 %2 %3 %4 %5 %6 %7 
  ジ ス ズ セ ゼ ソ ゾ タ ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ 
  %8 %9 %: %; %< %= %> %? %@ %A %B %C %D %E %F %G %H %I %J %K %L %M %N 
  ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ ム メ モ ャ ヤ 
  %O %P %Q %R %S %T %U %V %W %X %Y %Z %[ %\ %] %^ %_ %` %a %b %c %d 
  ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ ヰ ヱ ヲ ン ヴ ヵ ヶ 
  %e %f %g %h %i %j %k %l %m %n %o %p %q %r %s %t %u %v
[SJISのばあい]
こちらは,一見問題ないように見えて,実はかえってそれがやっかいの種なのです。
日本語の文字は1文字2バイトでできているのですが,SJISコードには1バイトずつ区切って
解釈したとき,その後ろ側1バイトがメタ文字と同じコードになってしまう文字が存在する
のです。これらの文字を見つけたとき,Perlはそれをメタ文字として認識してしまい,結
果として文字化けやエラーを引き起こします。
問題となる文字の一部を例としてあげておきます。
<ここから>
ー―‐ゼソゾ閏噂云骸浬馨擬欺犠啓圭珪梗構江纂蚕讃充十従深申疹措曾曽端箪綻甜貼転
納能脳票表評房暴望夕予余麓禄肋 </ここまで> もしSJISでCGIプログラムを書いていて,これらの文字をprintする必要があるなら,問題 となる文字を「表\」などと書いてみてください。きっと大丈夫でしょう。 ただし,これらの文字を人工無能の名前に使いたい場合などは,文字コードをEUCにするこ とをおすすめします。

[注意:EUCの落とし穴]
EUCにしたからこその落とし穴も,じつは存在します....
EUCコードで表記された日本語を1バイトずつ見たとき,ある文字の後半1バイトと次の文字の前半1バイトがまったく別の日本語の文字と同じコードになってしまう場合があります。
...と,これだけではよくわからないので詳しくはこの事例をご覧ください。

◆ パーミッションは重要です。
パーミッションは,正しいでしょうか?
動作させるCGIプログラムのパーミッションは,通常は755(705のことも)です。これはプロバイダから特に指定がない限り,このままでよいでしょう。
ログファイル類は,CGIによって書き込まれる必要があるので666(606のことも)です。
また,pref.cgiやjcodeLE.plなど,書き込まれることも直接実行されることもないファイルは644(604)でよいでしょう。ただし,プロバイダから特別に指定がある場合はそちらを優先してください。
なお,CGIプログラムを置くディレクトリ自体は705にしておくことが多いです。
これが700だったりすると,特殊な場合(自分の権限でCGIプログラムが実行される)を除き,動作しませんので注意してください。

◆ ログファイルを忘れないで
意外と多いのが,この手の"転送忘れ"です。
ログファイルがない場合(もしくは,pref.cgiで指定した名前と違う場合)は,エラートラップにひっかかるため
$sanka_file open error
などとエラーが表示されます。

一番わかりにくいのが(そして結構多いのが)jcodeLE.plの転送忘れやEUC化後のファイル名の定義し直し忘れでしょう。このばあい,多くは「文書にデータが含まれていません」といったメッセージとして帰ってきます。シェルテストを行って
Can't locate ./jcodeLE.pl in @INC at chat.cgi line 5.
などというメッセージがでる場合,多くはこれが原因です。

[豆知識:@INC]
@INCという配列には,perlが実行時に参照するPATHが入っています。
perl自身のpathと,関連ライブラリ関係のpath,さらに実行時のカレントディレクトリ(./)等がこの中に含まれており,ここで定義されているディレクトリに存在するファイルは,絶対pathを指定しなくても「require」したり「use」したりすることができます。

◆ .htaccess
エラーがでる,あるいはソースがそのまま表示されてしまうばあい,ひょっとするとあなたのサーバは.htaccessでMIMEタイプを設定する必要があるのかもしれません....
CGIを設置するディレクトリに.htaccessという名前のファイルを作り(パーミッションは644),その中に
Options FollowSymLinks ExecCGI Includes
AddType application/x-httpd-cgi .cgi
と記述してみてください。

◆ [その他]ServerErrorで困ったら...
ここに,ゆいさんのサーバーエラーに関するドキュメントがあります。
じっくり読んでみてください。

◆ [対処法]シェルテスト
これは,UNIXシェルを開放しているサーバでのみ有効な方法です....
1)サーバにtelnetでloginし,cdでちゃっと設置ディレクトリに移動します。
2)コマンドプロンプトから
	% chat.cgi
を実行します。

	Content-type: text/html

	<HTML><HEAD><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=x-sjis">
	<TITLE>ゆいちゃっと</TITLE></HEAD>
	<BODY BGCOLOR="#A1FE9F" TEXT="#000000" LINK="#ff0000" VLINK="#ff0000" ALINK="#FF0000">
ここで,chat.cgiのHTMLソースがこのようにずらずらっと表示されれば,ひとまずは大丈夫でしょう。
また,一行目の"Content-type: text/html"のあとは,必ず一行空いてないといけません
なお,
 
	/usr/local/bin/perl: Command not found.
などと表示される場合は,Perlのpathが違うかもしれません。

▼ 参加者欄に自分しか出てきません。
よく似た事例として,参加者欄の人数があわない(実際より少ない),特定の参加者が入れ替わりになる(Aさんが表示されている間はBさんが表示されない)などがあります。
これらは$hostつまり参加者のhost名が取得できていない場合や,取得できても同じ値である場合にあらわれる現象です。

ゆいちゃっとでは,参加者の判別にhost名を用いています。これは通常の場合host名とIPアドレスはネットワーク上でuniqueな値であるからです。つまりhost名やIPアドレスがわかれば,それはどこのコンピュータなのか一意に対象を特定できるのです。
しかしhttpによるサービスの場合例外的な場合が存在します。

[参考:例外的な場合]
・proxy(代理),Gatewayを経由するアクセスの場合。
・キャッシュサーバの場合。
・NAT,PIXなどを経由するPrivateIPネットワークからのアクセスの場合。
etc.etc....

以下の項でこれらのケースごとに対処法を説明しましょう。

◆ [Case1]環境変数$ENV{'REMOTE_HOST'}を取得できないサーバ
プロバイダによっては環境変数のうち$ENV{'REMOTE_HOST'}が使用できないばあいもあります。また,このようなサーバではgethostbyaddr()関数も制限されていることが多いようです。

対処方法は,「host名をあきらめてIPアドレスを使う」ことになります。
(IPアドレスを取得できないサーバは,寡聞にして聞きません。もしあったら....そんなプロバイダからは撤退したほうがよいかも....苦笑)

具体的には,pref.cgiで
$host = $ENV{'REMOTE_HOST'};
となっている部分を
$host = $ENV{'REMOTE_ADDR'};
とするだけです。
なお,人によってhost名が取得できたりできなかったりする場合は
$host = $ENV{'REMOTE_HOST'};	$host = $ENV{'REMOTE_ADDR'} if(!$host);
で良いでしょう。

◆ [Case2]キャッシュサーバ
キャッシュサーバというのは,ProxyもしくはGatewayの一種です。
ただし通常と違う点は,「Webサーバの手前に」ProxyないしGatewayが存在し,主にキャッシュを行うことでWebサーバの負荷を軽減し,なおかつWebサーバに対して直接アクセスされるのを防ぐことでセキュリティレベルを保とうという方針で運用されているものです(だとおもいます....汗)
したがって,Webサーバへのリクエストはすべてこのキャッシュサーバを通るため,CGIから渡される環境変数$ENV{'REMOTE_HOST'},$ENV{'REMOTE_ADDR'}はすべてこのキャッシュサーバのものになります。
対処方法は,参加者ごとの固有の値を取得できれば良いのですから,キャッシュサーバからWebサーバに渡される環境変数のうち,アクセス元のIPアドレス情報を取得することで対処できます。これらの"役立つ"環境変数は$ENV{'HTTP_FORWARDED'};,$ENV{'HTTP_X_FORWARDED_FOR'},$ENV{'HTTP_VIA'},$ENV{'HTTP_FROM'};などの名前でCGIに渡されます(キャッシュサーバの実装によって名前が若干違います)。

具体的な方法は以下のとおり。
(この方法はキャッシュサーバだけでなく,同一Proxyを利用する参加者が複数いる場合にも有効です)
###ゆいさんの公開している"Proxy対策"文書を一部加工・引用したものです。
今まで、
$host=$ENV{'REMOTE_HOST'};
の一行を、
$host = &gethost;
に変えて、下記のサブルーチンを追加する。
sub gethost{
$host=$ENV{'REMOTE_HOST'};
$host2=$ENV{'HTTP_VIA'} if( $ENV{'HTTP_VIA'}=~s/.*\s(\d+)\.(\d+)\.(\d+)\.(\d+)/$1.$2.$3.$4/ );
$host2=$ENV{'HTTP_X_FORWARDED_FOR'} if( 
$ENV{'HTTP_X_FORWARDED_FOR'}=~s/^(\d+)\.(\d+)\.(\d+)\.(\d+)(\D*).*/$1.$2.$3.$4/ );
$host2=$ENV{'HTTP_FORWARDED'} if( 
$ENV{'HTTP_FORWARDED'}=~s/.*\s(\d+)\.(\d+)\.(\d+)\.(\d+)/$1.$2.$3.$4/ );

$host .="$host2" if($host2);#$host2があれば、$hostに追加。
#オリジナルは $host .="[$host2]" if($host2); となってますが,
#この場合clear機能がつかえなくなるので....
return $host;
}#gethost END
###
なお,最新版のゆいちゃっとProではこの処理が最初から組み込まれています。

◆ [特殊な例1]同一の匿名proxyを経由する参加者
さて,一般のProxyを経由したアクセスの場合は[Case2]のとおりなのですが,Proxyにはそれ以外にいわゆる匿名Proxyというものがあります。(これは正しい呼び方ではありません,念のため。)
これはどのようなものかというと,「アクセス先Webサーバにアクセス元のIPアドレスなどの情報を渡さないProxy」です。これらの匿名Proxyは,主に管理者の知識不足や設定ミスなどによって生まれることが多いようです。(意図的に作られる匿名Proxyは,それほど多くないと思われます)。また,Proxyのエンジンによっては,そもそもこれらの情報を渡すことができないものもあります。
こういった匿名Proxyのうち,まったく同じProxyを利用している参加者が同時に複数やってきた場合,非常に困ったことになります。どちらがどちらなのか,host名をもとにしては判断がつかないのです。こういった場合,host名と名前の両方で参加者の特定を行う方法もありますが,いっそのこと匿名Proxy経由のアクセス拒否するという手段をとっても良いでしょう。
#a)匿名Proxyの排除
###ゆいさんの公開している"Proxy対策"文書を一部加工・引用したものです。
本来のIPを取得できれば、Proxyの利用を許可します。
Proxyを利用せざるを得ない特殊な環境の人のために、専用のCGIを用意しておきませう。
###
今まで、
$host=$ENV{'REMOTE_HOST'};
の一行を、
$host = &gethost;
に変えて、下記のサブルーチン2つを追加します。
sub gethost{
local($proxycheck,$host,$host2);
$proxycheck=0;
$proxycheck=1 if($ENV{'HTTP_VIA'});
$proxycheck=1 if($ENV{'HTTP_X_FORWARDED_FOR'});
$proxycheck=1 if($ENV{'HTTP_FORWARDED'});
$proxycheck=1 if($ENV{'HTTP_USER_AGENT'}=~/via/i);

#exit if($proxycheck);#串チェックに引っかかれば終了...っておいおい。でもこれも効果的かも。

$host=$ENV{'REMOTE_HOST'};
if( $ENV{'HTTP_VIA'}=~s/.*\s(\d+)\.(\d+)\.(\d+)\.(\d+)/$1.$2.$3.$4/ ){
$host2=$ENV{'HTTP_VIA'};$proxycheck=0;}
if( 
$ENV{'HTTP_X_FORWARDED_FOR'}=~s/^(\d+)\.(\d+)\.(\d+)\.(\d+)(\D*).*/$1.$2.$3.$4/ ){
$host2=$ENV{'HTTP_X_FORWARDED_FOR'};$proxycheck=0;}
if( 
$ENV{'HTTP_FORWARDED'}=~s/.*\s(\d+)\.(\d+)\.(\d+)\.(\d+)/$1.$2.$3.$4/ ){
$host2=$ENV{'HTTP_FORWARDED'};$proxycheck=0;}
&proxyerror if($proxycheck);

$host .="$host2" if($host2);#$host2があれば、$hostに追加。
return $host;
}#gethost END

sub proxyerror{
print "Content-type: text/html\n\n";
print <<"_HTML_";
<HTML><HEAD><TITLE>Proxyエラー</TITLE>
<BODY BGCOLOR="lavender" TEXT="darkblue" LINK="blue" VLINK="blue" ALINK="red">
<H2>Proxyエラーによりアクセスできません。</H2>
<HR>
あなたの利用されているProxyサーバは当掲示板への書き込みができません。<BR>
ごく一部のProxyサーバから書き込みを行うために、別サイトに専用のCGIを置いてあります。<BR>
詳しくは管理人まで、<A HREF="mailto:xxx@xxx.or.jp">E-Mail</A>でお問い合わせください。<BR>
</BODY></HTML>
_HTML_
exit;
}
#########
#b)host名と名前の両方で参加者の特定を行う
###pref.cgi  sub sanka###
#変更前
if(($host2 eq $host) && $flag){#ホスト名が同一の場合、時間と名前を最新のものにする。
#変更後
if(($handle eq $name) && ($host2 eq $host) && $flag){#ホスト名,なまえが同一の場合、時間と名前を最新のものにする。
###

◆ [特殊な例2]NATを経由する参加者
特殊なネットワークの一形態として,"プライベートIPネットワーク"というものがあります。
通常は,インターネット上のIPアドレスはそれぞれ固有のものであり,それぞれのネットワークごとに使うことのできるIPアドレスの割り当てを受けその範囲で使用しているのですが,プライベートIPネットワークではそれとは別にプライベートIPアドレスと呼ばれるものを使ったネットワークを構築技術なのです。外部とはまったく異なったIPアドレス形態を使い,外部と通信を行う時にだけ外部に通用するIPアドレスに変換して通信するため,実際に割り当てを受けたIPアドレスの数が少なくても,それ以上のhostをネットワークに接続することができます。また外部への出口となるゲートウェイ以外では外部のネットワークとほぼ完全に遮断されているため,セキュリティのレベルも非常に高く保てるという利点があります。
さて,このプライベートIPネットワークとグローバルなネットワークの中継をするGatewayとして機能するのがNAT(NetworkAddressTranslator)と呼ばれる機器なのですが,これは概ね以下のような働きをします。

・NATはグローバルなIPアドレスをプールしている。
・内部から外部へのアクセス要求があった場合,プールしているIPアドレスのうちのひとつを,リクエスト元の内部IPアドレスと関連づけ,グローバルに通用するIPアドレスからのリクエストとして外部に送出する。

ところで,HTTPは常時コネクション型のプロトコルではなく,なにかを行うたびに新たなリクエストが発行されるため,一連の動作であっても1アクションごとに接続は切れてしまいます。このためNATが毎回別のグローバルIPアドレスを同一hostに割り振ってしまうという現象が起きます。これはゆいちゃっとにとって以下のような不審な動作をする原因となります。

・発言のたびにホスト名が違う。(このためclearが効かない)
 NATによって前回のリクエスト時と別のIPアドレスを割り当てられたとき起こります。

・参加者欄に同じ名前の参加者が2人以上現れる。
 ゆいちゃっとの仕様では,60秒以内の参加者は参加者欄に表示されるのですが,参加
 者が60秒以内にリロードないし発言を行った場合で,かつ,NATによって前回のリクエ
 スト時と別のIPアドレスを割り当てられたとき起こります。

・参加者欄のAさんの名前が消えて,Bさんがあらわれる。
 AさんとBさんが同一NATを経由してくる場合で,さっきAさんに割り当てられていた
 IPアドレスがBさんに割り当てられたとき起こります。

etc.etc......

◆ [おまけ]Proxyのしくみ
 Proxyとは,本来は代理サーバーのことです。
 HTTPのみに話を限定すると,
[通常]
  ローカルホスト → リモートホスト      (request)
  ローカルホスト ← リモートホスト      (要求したページの配信)
 という仕組みなのですが,

[proxy経由]
  ローカルホスト → proxy           (request)
            proxy → リモートホスト (該当するページrequest)
            proxy ← リモートホスト (該当するページの配信)
  ローカルホスト ← proxy           (ページを配信)
となります。
また,ほとんどのProxyはキャッシュの機能を持っています。この場合,

[proxy経由:キャッシュあり]
  ローカルホスト → proxy           (request)
            proxy → リモートホスト (該当するページの情報要求)
            proxy ← リモートホスト (該当するページの情報)
 ここで,要求のあったページの最新のキャッシュがあれば   
  ローカルホスト ← proxy           (キャッシュされているページを配信)
 キャッシュがなかったり,あっても古い場合は
            proxy → リモートホスト (該当するページ要求)
            proxy ← リモートホスト (該当するページ配信)
  ローカルホスト ← proxy           (ページを配信)
なお,ネットワークの負荷(無駄な情報を流さないように)を考えると,キャッシュをうまく使うことは推奨されるべきでしょう。また,Proxyをうまく選択することで,(ある程度)恣意的に目的ホストまでの経路を選択することが可能になります。....と,このあたり,わかる人だけわかってください...苦笑

なお,最近誤った認識が広まっているようですが,「proxyとは匿名性を実現するための道具である」というのは,間違いです。ただしい知識を持ちましょう。

参考文献
 RFC1945,RFC2068

▼ 退室がうまくいかないのですが
退室がうまくいかない....という例があります。
現象としては,「退室ログは出るけど,入室したまま」という場合と,「文書にデータが含まれていません」という場合です。
これらについて傾向と対策を以下に示します。

◆ $endpage(退出後に表示するページ)の設定は?
「退室ログは出るけど,入室したまま」という場合,まず確認すべきことは「$endpage」で指定したURLが有効か?ということです。
このページの記述にミスがあったり,URLが見つからない場合,ブラウザは開くべきページが見つからず立ち往生してしまいます。
結果として,画面には入室したままの状態でちゃっとが表示され続けるでしょう。

◆ サーバは?(IISの問題)
退室時,「文書にデータが含まれていません。」というメッセージがでるばあい,Webサーバの種類を確認してみてください。
IISの場合,別のページに飛ばすために使っている「Location:」がそのままではうまく動作しないという報告があります。
いちどchat.cgi sub write の退室処理部分で
print "Location: $endpage\n\n";

print "HTTP/1.0 302 Moved Temporarily\n";
print "Location: $endpage\n\n";
に変更してみましょう。

▼ デザインを変えるにはどうしたらいいですか?
デザインを変える前に,オリジナルの状態で動作を確認しましょう。
変更してからでは,エラーの原因を探すときに,手間が増えます。
動作が確認できていれば,それ以降のエラーの原因は変更点を調べるだけで済むのですから....

◆ 色を変えるにはどうしたらいいですか?
pref.cgiの$bodyという変数を見てみましょう。
ここで,ちゃっとのHTML出力時の<BODY>を定義してます。
色を変えるのなら,ここの値を変更すればおっけーです。背景画像もここで指定しましょう。

◆ 画像を貼り付けるには
ちゃっとの発言欄出力部分は,フレームありの場合enter.cgiに,なしの場合chat.cgiにあります。
ここで,普通に
<IMG SRC="http://www.hoge.ne.jp/~hogehoge/hoge.gif">
とか書くことでイメージを貼り付け可能です。
ただし,注意点をひとつ.....
ヒアドキュメント内
print <<"_HTML_";
から
_HTML_
までの間に書く場合は,通常HTMLを書くときのように普通に書けばよいのですが,
print "<IMG SRC=\"http://www.hoge.ne.jp/~hogehoge/hoge.gif\">\n";
のようにする場合は,「"」の扱いに注意してください。

なお,どちらの場合にも「$」や「@」などの扱いにも注意しましょう。

◆ 発言欄のデザインを変えたい
基本的には,「画像を貼り付けるには」の項で説明した部分を守っていれば大丈夫です。
ただし,退室処理のために一度<FORM>タグを閉じて開き直している部分があります。この内部出あればFORMの順番を変えても問題ないのですが,<FORM>タグを越えてFORMを移動させてはいけません。.....当然のことではありますが

また,$hidden,$logw,$kaoなどという文字列が書いてある部分があります。これはそれぞれ,「type=hiddenのFORM」「ログ行数選択用FORM」「顔文字選択用FORM」が入っています。いちいち書いていては煩雑になる部分をひとつにまとめてあるだけなので,これらの内容を編集したい場合はpref.cgi の sub hide を直すとよいでしょう。

[注意]
TABLEタグの扱いは,注意しましょう。TABLEタグは,ちゃんと閉じてない場合もじらではテーブル自体表示されなかったりします。IE使いのかたは要注意です。
また,IEではテーブルの無効部分(<TABLE>と<TR>の間等)に記載した<FORM>タグは無効になるという情報があります。注意しましょう。

◆ ログに表示される内容・順番を変えたい
入室ログ変更は,enter.cgiの20行目前後にある
$value = "<FONT COLOR=\"#0000ff\"><B>管理人</B></FONT> > <B><FONT COLOR=\"$color\" SIZE=+2>$name</FONT></B><FONT COLOR=\"red\"><B>さん、おいでやすぅ。</B> $brauza</FONT><FONT COLOR=\"#888888\" SIZE=-1>($date $host)$histry</FONT><HR>\n";
を変えてください。
順序については,全くの自由です。ただ,書き方をまちがえると大変です。
「サーバーエラーの原因は」項の「ソースをなおしました?」を参考にして,正しく記述してください。

退室ログと,通常の発言ログの変更は,chat.cgiのsub writeを修正します。
$valueに代入している値を修正してください。

◆ してはいけないこと
ゆいちゃっとでは,index.htmlとchat.cgiに「消さないで」とコメントしてある部分が一カ所ずつあります。
特に,chat.cgiの「ゆいちゃっと(Free)」というロゴは,消してはいけません。ちゃっとを訪れた人に見えるような形でこのアンカーを残しておいてください。
ゆいちゃっとに限らずFreeのソフトを使うなら,スクリプトの著作権表示を残しておくのは最低限のマナ−です。

▼ ぼっとの名前を変えたいのですが
ゆいぼっとを設置する場合,ぼっとの名前を変えたいというのは良くある要望です。
方法は,それほど難しいものではありません。変更する必要があるのは
 chat.cgi
 bot.pl
 辞書ファイル
の中の「ゆい」「ゅぃ」という表記を変更するだけでよいです。
辞書の中身を訂正するのを忘れるばあいが結構あるようです。
(ただし「ゆいちゃっと」という文字列は,当然変える必要はありません.....)


なお,ゆいぼっとMultiのばあい,bot.plのぼっと定義部分

#(1)まずは増やしたいだけ名前を設定。
$bots[0] = 'ゆい';
$bots[1] = 'みゆ';
と,辞書の変更だけで対応できます。

[注意]
SJISの場合,ぼっとの名前に使ってはいけない文字があります。
詳しくは「文字コードの呪い」の項を参照してください。
なお,これらの文字を使わない場合でもさまざまな問題が起きやすいため,文字コードはEUCにしておくほうがよいかもしれません。

◆ EUC化について
どうしてEUCコードにしたほうがよいか....というのは「文字コードの呪い」の項をご覧ください。

具体的な方法は,実はそれほど難しくはありません。

[スクリプトの変更(2箇所)]
1)
pref.cgi  sub init で
$metacode = '<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=x-sjis">';#SJIS認識させる
という文を
$metacode = '<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=x-euc-jp">';#EUC認識させる
こうします。

2)
pref.cgi  sub decodeで
		&jcode'convert(*value,'sjis');
という文を
		&jcode'convert(*value,'euc');
こうします。

[文字コード変換]
すべてのファイル(ゆいぼっとの場合,辞書を含む)の文字コードをEUCに変換する。
これは,nkf等のツールを使っても良いですが,もしあれば文字コード変換機能のあるエディタで行うのが楽でよいでしょう。なお,将来ソースを編集するときのことを考えると,これらの文字コード変換機能のあるエディタを入手しておくのが賢いかもしれません。
(例: 窓>秀丸エディタ,REエディタ,WZエディタなど, 林檎>JEditなど)

[注意点]
SJISの時にクッキーを食べている場合,EUC化するとクッキーのせいで文字が化けます。
これを防止するためには,クッキーの名前を変えると良いでしょう。
方法は,enter.cgi の sub getcookie と sub setcookie で「yuidata」という文字列をたとえば「yuieucdata」とかに書き換えてしまえば大丈夫です。

◆ ぼっとが最後まで言葉を言わない&ボットの発言の最後が「・」になる
これは,SJISで運用している場合に,まれに起こります。
あるバージョンのjperlでは,chopで文字列の最後についた改行コード(\n)を削る時に,ある特定の文字コードが末尾にあると余分に1バイト削ってしまうという報告がされています。
この場合は文字コードをEUCに変更するか,改行コードの削除方法を変える必要があります。

bot.plではchop()文は4〜5カ所あります。
これらすべてについて
 chop $res;
のばあい
 $res =~ s/\n//;
とかに変えてあげるとよいでしょう
 (chop $msg;のときは,とうぜん $msg =~ s/\n//; ですね。)
なお,Perlのバージョンが5なら,chop()の変わりにchomp()を使っても良いようです。

◆ ぼっとが同じ言葉を繰り返します
1)原因は,多くの場合,辞書ファイルにあります。
「ぼっとの名前」のみ,または「ぼっとの名前の一部分のみ」をぼっとに覚えさせるキーワードとして使ってはいけません。

[例]
ぼっとの名前が「みるきぃ」の場合,
みる:#僕のこと、呼びました?>NAME
みるきぃ:#呼びました?>NAME
というような登録があってはいけないのです....

[解説]
ぼっとは,自分の名前が含まれる発言に反応しますので,このとき$chatには「ぼっとの名前」がかならず含まれていることになります。
(参加者が一人のときは,内部で$chatに「>ぼっとのなまえ」を追加してます)
このため「ぼっとの名前のみ」や「ぼっとの名前の一部分のみ」のキーワードで辞書登録があると,検索したときかならず辞書にhitします。
また,教えてモードやぼけモードは,辞書にhitがないときだけ発動しますので,決して実行されなくなってしまうでしょう(苦笑)

-------------------------

2)ゆいぼっと構築時のミスが原因となることもあります
chat.cgiのsub jikan実行後に
srand($times);
という文が書いてないと,ランダムで辞書から拾ってくる言葉が常に一定になってしまいます。

perl に限ったことではありませんが、乱数には初期値が必要です。
なにもしないと初期値はあるきまった値になるので、プログラムを起動する毎に rand()関数が返す数字は同じもの、ということになります。
そこで,最初に時間(プログラムを実行するたびにちがうはず)で初期化するのです(^^;;

BACK NEXT