最近、うちの掲示板のログをいろいろとサルベージする必要に迫られましてね。
結果、うちの掲示板スクリプトにバグがある事を見つけてしまいました。
具体的には、永続的URL対応の部分です。
そして、この部分にバグがあるということは、私がその機能を実装して納品
した、ここ野ざらし言のスクリプトにもバグがあるということです。
ごめんなさい。
あまり実害がないのは幸い。とはいえ、美しくないのは間違いのないところ。
私の公開したソースに基づいて実装しているkonnoさんのところにも混入して
いると思われます。
まず、バグがどうこうの前に、記憶を新たにするため、というか、永続的URLの
実装がどうなっているかというのは以下のURL参照。
toshiki.la.coocan.jp/computer/itabei/url.html
一括表示の部分を書き換えたわけですが、書き換えた部分の冒頭、ツリー表示の
部分のアルゴリズムをざっくり抽出すると、以下のとおり。
$flag=0;
while ($flag == 0) {
もし過去ログなら
過去ログ番号を取得
ツリー表示の前処理
ログファイルを開く
while (ログファイルの終わりまで){
該当のツリーがあれば{
$flag=1;
ページ冒頭のツリー表示
]
}
ログファイルを閉じる
ツリー表示の後処理
if ($flag == 0){
もし現行ログを走査していたら
次は過去ログ走査
もし過去ログを走査していたら{
過去ログ番号を次は1つ減らす
過去ログ番号が0まで達したら
$flag=1;
} else { #もし現行ログを走査していたら
過去ログ番号を取得
}
}
}
このコードの何が悪いか。
ツリー表示の部分で、該当のツリーがなければ当然、ツリー表示はなされま
せん。
そして、ループを回すことで、該当のツリーが見つかるまで探すわけですよ。
ところが、ツリー表示の前処理と後処理は、目的とするツリーが見つからなく
ても実行されます。
つまり、古い過去ログに入っている発言を表示させようとすると、何回もループ
を回るため、前処理と後処理が余分に何回も実行されてしまうわけですよ。
ただ、一般に、前処理と後処理はきちんとセットで実行されれば実害は生じま
せん。だから、こんな単純なバグに15年も気がつかなかったわけですよ。
また、開発当初は過去ログが1つしかありませんでした。その状況では当然、
ループは最大1回しか回らないわけですから、バグは発現しません。
解決策は簡単。
前処理と後処理の部分を、ループの外に出してやるだけです。
「$flag=1」を目印に探せば、該当のルーチンは簡単に見つかるでしょう。
めざらさんのところでは、前処理と後処理はそれぞれ「<ul>」「</ul>」を表示
しているだけだと思います。konnoさんのところは、フォントのサイズを変えて
いるようですね。
私のところでは、テーブルに押し込めているので、ちょっと派手かも。
現時点では酔いどれているので(だからバグを見つけられたのかも)、明日、
酔いが醒めてからコードを書き換える予定。
おそらく、そんなに手間もかからず副作用も発生しないことでしょう。
いや、そうであってほしいな。