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秒足すんだろう?)