if($subj){
$subj1 = "<title>$subl</title>";
$subj2 = "<font size=+" color=red><b>$subj</b>,/font>";
}

新規スレッドのタイトルを、そのスレッドのhtmlのヘッダと、body部の表示用に 二つのスカラーを作成。 とうぜんだけとど、レスの場合は、$subjがないから、 この処理はなされない。 あと「color=red」のredを別の色に変えれば、 スレッドタイトルの色は赤以外になる


$line = <<EOL;
<form method=post action="../$cgi">
<input type=hidden name="res" value="$res">
投稿者 <input type=text name="name" size=20>
メール <input type=text name="mail" size=20><br>
<input type=submit value="↑へのレスカキコ" ><br>
<textarea name="comm" rows=4 cols=70 ></textarea>
</form>
EOL
$line =~ s/\n//g;
print W "$line\n";
flock(W, 8);
close(W);

}


1行目から4行目(通しで113から116行目)は、 $lineにスレッドの最初のカキコを代入 それをつぎの2行(117と118行目)で、まず代入されたものから改行コードをとって、 次に、その$line自体の最後に改行コードを入れたかたちで、Wに書きこんでいる。 続く10行(通しで119から129行目)は、最後のレスカキコ用のhtmlフォーム部品を 同じようにして、Wに書きこんでいる。 残りは、ファイルハンドルWのロックを解除して、さらに閉じて、 通しで68行目から始まったifも閉じている。 このifは、結局、新規スレッドを立ち上げる操作。 この操作は、もう少し続くみたい。 レスのカキコは、55行目で指定されているサプルーチンresが行うみたい。

さて、ここまでが$reloadに1が入っている場合無視されるところですね。

open(R, "./blist.txt");
while(<R>){
chop;
($fol, $color, $title) = split(/,/);
last if $fol eq $folder;
}
close(R);


blistから、それぞれの板のディレクトリ名、背景色、タイトルをとりこむ作業。 (これを毎回やっているのだから、ここはアメスクをちょっとは遅くしているはず) 1行目(通しで135行目)で、掲示板リスト(blist.txt)を 読みこみモードでファイルハンドルRに開いて、 whileで1行ずつ、まず行末の改行コードを削除(通しで137行目)、 つぎに「,」でくぎって、$fol、$col、$titleに順番に代入、 (ここで、この順に代入するから、blist.txtは、1行「ディレクトリ名,色,タイトル」で家かなけきゃだめ) それを$folと今作業しているディレクトリ(通しで31行か53行でつくった$folder)と 比較して、同じなら、その行で、代入をやめる。 つまり、mainならたいていのblistで1行目だろうから、そこでこのwhileは終わり、ってこと 最後の行でRを閉じている。


$page = '2' if $next != 21;
$index = "index$page.html";
$file = "./$folder/$index";

index.htmlなのかindex2.htmlなのかを決める処理。 通しで56から58行目で作った$nextの値が21、 つまり、1頁目でなければ、$pageに2を代入 1ページ目なら、この処理はされない で、2行目(通しで144行目)でindex.htmlなのか、index2.htmlなのかを決めてる 上の行で$pageに2が入ってりゃ、index2.htmlが$indexに代入され、 上の行で作業がなされていなけりゃ(つまり、1ページ目なら)、$pageは未定義だから、 数値としては0だけど、ここでは、クォートされて文字列として扱われているので空文字になる つまり、「index$page.html」の$page部分には何もないから、$indexにindex.htmlが代入される で、最後に、そのどっちかのhtmlのファイル(つまり、1ページ目か2ページ目か)の位置を$fileに代入 ちなみに、3ページ目以降は、ブラウザ表示としてはあるけど、ファイルとしてはない。


$main = "(メイン)" if $folder eq 'main';
($color, $bg) = split(/!/, $color);
$bg = " background=\"$bg\"" if $bg;
$text = q( text="#ffffff" link="firebrick" vlink="firebrick") if $color =~ "#0";
$title =~ s/#c#/,/g;
$title0 = $title;
if($title0 =~ /alt=\"([^\"]+)/){
$title0 = $1;
undef $amezo;
}

index(2).htmlでのヘッダをつくるための変数を準備する作業 1行目(通しで146行目)で、それぞれの設置者がメインに指定した板のヘッダに 「(メイン)」をつけるための変数を、 作業している板がblistでmainに指定されているときだけ作成 「(メイン)」は書き換えてもいい。 2行目(通しで147行目)は、blistで、たとえば、 title,iro!e.gif,タイトル と背景の絵を指定しているとき、背景色と色を分ける処理 で、3行目(通しで148行目)で、背景の絵があれば、それを$bgに代入 4行目(通しで149行目)は、背景色が#0で始まっている時の、 テキストとかリンクの色をしする$textを作成、 q(...)はシングルクォートのこと、 q/.../あるいは'...'と同じ 残りの通しで150から155行目は、 サポートさん(?)のblistだけにかかわる処理(だと思う)から シラン。

open(W, "+< $file");
&redirect unless flock(W, 6);

今度は、index(2).htmlをファイルハンドルWとして、読み書き両用で開く 次の行で、6は2+4のことだから、他からロックされていたら、とっとと サブルーチンredirectにうつる 他からロックされていなければ、排他ロックする。 このWは、255行目で閉じてるみたい。


print W <<EOF;
<html><head><title>$title0$amezo$main</title></head>
$copyright
<body$bg bgcolor="$color"$text>
<font size=+2>$title$amezo$main</font>
EOF

open(R, "./header.html");
print W while <R>;
close(R);

print W <<EOF;
<form method=post action="../$cgi">
<input type=submit value="次のページ">
<input type=text name="next" value="$next" size="3">〜</form>
<font size=2>
<!-- HEAD LINE -->
EOF

見なれた「次のページ 数字 〜」までのところを Wとして開いてあるindex(2).htmlに書きこむ処理 8から10(通しで167から169)行目で、header.htmlを開いて、 index(2).htmlに書きこんでいる。 これは、複数の板を一つのcgiで処理しようという根性の証しなのだろう。 (でも、きっと少し、重くしている)

opendir(DIR, "./$folder");
」 @dir = readdir(DIR);
closedir(DIR);
for($i=0;$dir[$i];$i++){ $ts = ($dir[$i] =~ /^\d+\.html/) ? (stat("./$folder/$dir[$i]"))[9] - 800000000 : ' ';
$dir[$i] = "$ts,$dir[$i]";
}
@dir = sort {$b cmp $a;} @dir;

スレッドの順番を時間順に並べ替える処理 2行目(通しで180行目)でスレッドのhtmlファイル名を配列dirとして取得 5〜9行目(通しで183から187行目)は、まず$iに0を代入して、 それから配列dirの$i番目が数字.htmlというファイル名かをチェックして、 そうだったら最終更新時刻(stat...[9])から800000000を引いた数を$tsに代入 そうでなかったら$tsには空文字を代入 (800000000は今では、もっとでかい数にしているのだろう、たぶん・・・) 8行目(通しで186行目)で、その引いた数か空文字をつけたファイル名を @dirの$i番目(つまり、同じ場所)に代入 そして、$iを1増やして、 @dirの最後の項目まで、これを繰り返す 最後の行で、@dirを降順に並べ替えるお決まりの処理をする これが、スレッドの並びを最新に変える仕組み あめぞう型スクリプトの真骨頂の本丸


for($i=$next - 21;$i < $next+100-21 && $dir[$i];$i++){
($ts, $file) = split(/,/, $dir[$i]);
last if $ts eq ' ';
open(R, "./$folder/$file");
$_ = <R>;
close(R);
/<b>([^\<]*)<\/b>/;
$j = $i+1;
print W " $j<a href=\"$file\">$1</a>\n";
}
print W "<!-- HEAD LINE END -->\n</font>\n";

スレッドhtmlにカキコが新しい順に番号をつけるて、 それを「次のページ・・・」の次にある一覧に表示する処理 56-58行目で決定した$nextから21引く(1ページ目かどうかのちぇっく) で、それを$iに代入 @dirの$i番目から、上でくっつけた数字とfileネームを分ける で、数字でなく空白がくっついてるのが見つかったら、このforを止める @dirの$i番目にあたるスレッドのhtmlをRで開いて、それを$_に代入して、Rを閉じる $_に代入されているスレッドのhtmlからタイトル部分を探す(このスレなら、「amezo.cgiうんたら」) スレッドの順番を$jに代入 157行目でWとして開いたindex(2).htmlに、 スレッドに順番をつけて、そのスレッドにリンクをはるタグを書きこむ $iをインクリメントする その$iが100より小さくて、上でつくった@dirのなかに$i番目のエントリーがあるあいだ上の書きこみ作業を繰り返す んで、forを抜けたら、<!-- HEAD LINE END--> とかを最後に書きこむ これで、スレッド以前の部分ができあがる。

for($i=$next - 21;$i < $next - 1 && $dir[$i];$i++){

今回は、ちょっと親切にこれは次と同じこと

$i = $next-21;
while($i < $next - 1 && $dir[$i])
{
 いろいろ
 $i++;

このループが閉じているのは、通しで244行目 &&は論理and これは、スレッドをindex(2).html内に表示させる処理の始まり。 通しで56から58行目で決定した$nextから21を引いて、$iの値が1になれば、1ページ目じゃないですか。 んで、いろいろ処理の最後に$iの値を1ずつ増やす。これが21になれば、2ページ目じゃないですか んで、3ペーじ目とかも、同じようにして確かめられるけど、最後のページかを判定しなきゃなので、 && のあとに その番号のスレッドhtmlがあるかを、確かめてる つーこと。

($ts, $file) = split(/,/, $dir[$i]);
last if $ts eq ' ';
printW <<EOL;
< table border=1 cellspacing=1 cellpadding=2 width=100% bgcolor="#efefef"><tr><td><font color="#000000">
EOL

スレッドごとのtableをつくるhtmlタグを 157行目でファイルハンドルWとして開いておいてある index(2).htmlに書きこむ処理。 最初の2行は、191、192行目と同じ処理だから解釈を省略。 残りは、htmlタグを知っている人には見ればわかるので省略。 EOLつーのは、エンドトークンとか言うらしい。別にEOLでなくてもいい。 171行目とかでは、EOFを使ってるし、別に統一してないようだ。

open(R, "./$folder/$file");

$_ = <R>;
s/<title>.*</title>//;
print W;各スレッドの1行目をindex(2).html=Wに書きこむ処理

スレッドhtmlをファイルハンドルRで開く。 それを$_に代入。 スレッドhtmlの1行目の<title>・・・</tilte>を削除
(//は、/空白/ではない、スラッシュは続けて書いてあるから、削除できる)んで、その削除したものをWに書きこむ
最後の行は
print W "$_";
でも同じ。


for($j=0;<R>;$j++){
last if /^<form/;
$lines[$j % 7] = $_;
}
close(R);
$k = $j - 7;
$k = 0 if $k < 0;
for($m=$k;$m < $j;$m++){
print W "$lines[$m % 7]";
}


長くなったスレッドの最新レスだけを表示させる処理。

1行目(通しで212行目)については、上と同じ表現だから、省略。
2行目でRとして開いてあるスレッドhtmlを「投稿者」とかのレス用htmlフォームの前で読みこみを止めさせている。
(このforループを抜け出すってこと)

3行目(通しで214行目)は、スレッドの2行目からを@linesにインデックスつきで代入する。
このインデックスが$j % 7になってるのが、最新レスだけを載せる最初のポイント
$j % 7は、$jを7で割ったあまりを返すはず。何で7なのかは、
すでに暴露されたようにわたしは算数ができないので、わからん。

通しで217と218行目は、インクリメントされた$jから7を引いて、&kに代入
それが0未満になっちゃったら、$kに0を代入しなおしている
(0未満じゃなきゃそのまま)

で、通しで220行目で、最新レスをWに書きこむ。

ここにある二つのforループは、別々のループだけと、二つ1セットで、
最新レスを順番に書きこんでいる。
それができるのは、この二つのforが202行から始まっているforのなかだから。

なんで7だとか、どうやって最新レスだけになっているかとか、算数上の問題は、
わたしにはわからん。マジでわからん。どうしてこれでうまくいくのかわからん。
でも、この処理が、アメスクの真骨頂の大本丸なのっす。たぶん。
78投稿者:>77 投稿日:07月14日(金)00時05分14秒
7で割った余り→0〜6→@linesは要素を7こ持った配列

これに読みこんだ行を入れていくからループ終了時には
$lines[0]〜$lines[6]には最新の7個が入る

$file =~ /(.+)\.html/;
$res = $1;
undef $sub;
$k = $j - 98;
$sub = <<EOL if $j > 200;
<input type=text name="from" value="$k" size="4">
<input type=submit name="sub" value="〜">
EOL
print W <<EOL;
</font></td></tr></table>
<form method=post action="../$cgi">
<input type=hidden name="res" value="$res">
投稿者 <input type=text name="name" size=20>
メール <input type=text name="mail" size=20><br>
<input type=submit value="↑へのレスカキコ" >
<a href="$res.html">レス全部を見る</a>
$sub<a href="#top">上へ </a><a href="./">リロード</a><br>
<textarea name="comm" rows=4 cols=70 ></textarea>
</form><hr>
</td></tr></table>
EOL

}

スレッドごとの区切り、hrまでの処理。

まず、今処理しているスレッドhtmlのファイル名から数字部分を取り出す
それを$resに代入
$subを未定義にして(つーか、まだ定義されていないけどね)
インクリメントされた$j(1スレッド内のカキコ数)から、98を引いて$kに代入
(マイナスになるようなときは、使わないから、気にしないのかな)
$jが200より大きければ、$subにEOLまでを代入
(これは、レスが多いスレッドだけに使うってこと、後で出てくるけど
「レス全部見る」と「上へ」のあいだに入る、わひょさんの広場では98ではなく
50引いてるみたい)
で、あとは、tableを閉じて、「投稿者」から、レスようのエリアまでのhtmlのform部品をindex(2).htmlに書きこんでる。

これは、202行からのループの最後の処理、これを繰り返して、最新レスの順にindex(2).htmlができあがるということ。
244行目で、202行目からのループは終わり。
print W <<EOF;
<form method=post action="../$cgi">
<input type=submit value="次のページ">
<input type=text name="next" value="$next" size="3">〜</form>
<hr></body></html>
EOF


index(2).htmlの最後を書きこむ処理。
truncate(W, tell(W));
flock(W, 8);
close(W);
&redirect;


index(2).htmlを最終的に表示させる処理。

まず、作ったindex(2).htmlから最後の行を削除している。
んで、Wのロックを解除して。
Wを閉じて、
サブルーチンredirectを呼び出す。
sub redirect {
undef $index unless $page;
print "Location: $urlbase$folder/$index\n\n\n";
exit;
}


index(2).htmlを書き出す処理。サブルーチン。

2ページ目じゃなきゃ、$indexを未定義にしちゃう。
(だから、雨スクでは、たとえばこの板なら「??/support/」が表示されて、
index.htmlだったりindex2.htmlじゃないのね、へー。なーるほど。)

んで、そのurlを吐けッ、てブラウザに命令してる。
(改行コードが三つなのは、MIMEの問題なのだろう。わたしはシラン。)
最後の行で、アメスク脱出ーー!!
sub error {
print "Content-type: text/html\n\n<html><body><h2>$_[0]</h2></body></html>";
exit;
}


エラーのサブルーチン。

$_[0]は、配列@_ がサブルーチンへ引数を渡す配列だから、
そっから最初の引数をとってる。
つーか、アメスクでは &errorに渡す引数はいっつも1つだから、これでいい。
sub res {
print "Content-type: text/html\n\n";
open(R, "./$folder/$res.html");
print <R>."";
while(<R>){
/<dt>(\d+)/;
last if $1 >= $form{'from'};
}
print;
$fol = "<input type=hidden name=\"folder\" value=\"$folder\">";
while(<R>){
if(/<\/form>/){
s/(action=\")\.\.\//$1/;
s/(<\/form>)/$fol$1/;
}
print;
}
exit;
}


通しで55行目で呼び出しているサブルーチン。

つまり、カキコが多いスレッドの「〜」ボタンをおしたときに
最初のカキコと近場のカキコを表示させる処理。
「〜」ボダンをおした時だけ、amezo.cgiがむき出しになるのは、このため。
そうすることによって、新しいhtmlをつくらないで済ますという
超絶なワザ。マジで感心した。

279行目のwhileは、285行目で閉じている。
そのなかでifをやっていて、アドレスを普通は1階層下のディレクトリだけど、
これはちがうので、自分のディレクトリに変えている。
そのifをのぞけば、このwhileは
while(<R>){
print;
}
だから、上の通しで273行目の1回目のwhileを抜け出した後のカキコを書き出すだけ。

わからないところがあるので、親切な方教えてください。
「print <R>."";」の「.""」の意味。何をしているのでしょうか?
 
sub del {
if($mail){
$name = $admin;
undef $mail unless $name =~ /\@/;
return;
}
print "Content-type: text/html\n\n";
exit unless $res;
$file = "./$folder/$res.html";
if(!$comm){
unlink($file);
exit;
}
$comm = ',' . $comm . ',';
$comm =~ s/(\d+)\-(\d+)/join(',',($1..$2))/eg;
$comm =~ s/<br>/,/g;
$ts = (stat($file))[9];
open(R, $file);
@lines = <R>;
close(R);
open(W, "+> $file");
flock(W, 2);
foreach(@lines){
next if /<dt>(\d+)/ && ($n=','.$1.',') && $comm =~ /$n/;
print W;
}
close(W);
utime $ts+1, $ts+1, $file;
exit;
}


管理者カキコと削除のサブルーチン。
通しで74行目で呼び出される。

通しで290から294行目は、管理者がキャップなしで投稿者名を書ける仕組み。だから、あんまり解釈したくないので、しない。
通しで295から296行目は、慎重さのあらわれかなぁ?
通しで297から301行目は、コメント欄に何も書かれてなかったら、そのスレッドのファイルを削除。
通しで302から304行目も、慎重さの現れ。管理者がどういうかたちで、スレッド内の削除したいカキコ番号を指定しても、たいていうまくいくようにしている。
削除したいカキコ番号が、$commに「,」で区切られて入る。
通しで306から308行目は、削除対象スレッドのhtml内容を@linesに代入。
通しで309行目で、も一回削除対象スレッドhtmlを書きこみできるかたちでWとして開き、
310行目で、吐いたロックしておいて、311行目から314行目で、削除指定されたカキコ番号だと、print命令を実行しない(nextで飛ばしている)、
それ以外の番号のときは、Wに書きこむ、を行ごとに繰り返す。
(これで、削除指定されたカキコ番号以外のカキコだけが対象スレッドhtmlに残る)
んで、Wを閉じて、通しで316行目では、上の305行目でとっておいた更新時間に1を足した時間が、
アクセス時間と更新時間になるように、タイムスタンプを書き換えている。(何で1秒足すんだろう?)