#!/usr/local/bin/perl
# =================================================================
# 名前: wwwsrch.cgi Ver3.05
# 機能: ホームページの内容を検索するCGIスクリプト。
# 作者: とほほ
# 参照: http://wakusei.cplaza.ne.jp/twn/wwwsrch.htm
# =================================================================
#
# 1997.09.28 初版
# 1997.10.09 検索結果に検索フォームを表示するようにした
# 1997.10.26 大文字、小文字を区別しないモードを追加
# 1997.11.02 文字化け修正
# 1997.11.09 検索結果のジャンプ先を別ウィンドウに表示するようにした
# 1997.12.16 wwwsrch.logにIPアドレスも記録するようにした
# 1998.02.01 高速版大文字・小文字同一視処理
# 1998.03.15 「ー」を検索するとエラーになるバグ修正
# 1998.05.10 マッチした行の前後n行を表示できるようにした
# 1998.05.24 行末の <... が残ってしまうバグを修正
# 1998.07.19 コメント文の取り扱いに関するバグ修正
# 1998.08.12 「ブラウザ」が「ブラウブ」にマッチしてしまう問題に対処
# 1998.08.12 検索対象ファイルがJISコードでも動作可能にした
# 1998.08.17 Ver3.01 検索結果が文字化けしてしまうバグを修正
# 1998.09.13 Ver3.02 検索結果のタイトルが文字化けしてしまうバグを修正
# 1998.09.13 Ver3.02 検索結果が太字にならないことがあるというバグを修正
# 1998.09.13 Ver3.02 Mac形式の改行コードのファイルへの対応
# 1999.01.24 Ver3.03 $how_many_linesが無視されるバグを修正
# 1999.03.07 Ver3.04 perl4で途中までしか検索できないことがある問題に対応
# 1999.09.19 Ver3.05 Ver3.04の対応がミスっていたのを修正
#
#
# 変更・確認必要パラメータ
#
$target_dir = '..'; # 検索対象ディレクトリ
$return_url = '../index.html'; # [戻る]ボタン
$sufix{".htm"} = 1; # 拡張子 .htm を検索する
$sufix{".html"} = 1; # 拡張子 .html を検索する
$how_many_lines = 2; # マッチした行の前後何行を表示するか
$do_logging = 1; # 検索キーワードのロギング
#
# CGIテスト用
#
if ("$ARGV[0]" eq "test") {
print "Content-type: text/html\n";
print "\n";
print "CGI Script OK.\n";
exit(0);
}
#
# 初期設定
#
$| = 1; # 出力をバッファリングしないようにする
require "jcode.pl"; # 漢字コード変換ライブラリ読み込み
#
# このスクリプトの漢字コードを調べる
#
if ((ord("漢") == 0xb4) || (ord("漢") == -76)) { $kcode_cgi = "euc"; }
if ((ord("漢") == 0x8a) || (ord("漢") == -118)) { $kcode_cgi = "sjis"; }
if (ord("漢") == 0x1b) { $kcode_cgi = "jis"; }
#
# メインルーチン
#
{
# フォームからの入力データを読み込む
if ($#ARGV == -1) {
&readform();
} else {
$FORM{'WORD'} = $ARGV[0];
}
# 検索語をEUCに変換する
$word = $FORM{'WORD'};
&jcode'convert(*word, "euc");
if ($word =~ /[\x80-\xff]/) { $jflag = 1; }
# 全角空白を半角空白に置換する
$word =~ s/^(([\x80-\xff][\x80-\xff]|[\x00-\x7f])*)\xa1\xa1/$1 /g;
# 検索後を分割する
@words = split(/ +/, $word);
# 検索語ログに追加する
if ($do_logging && ($word ne "")) {
($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
open(OUT, ">> wwwsrch.log");
printf(OUT "%04d-%02d-%02d %02d:%02d:%02d %s %s\n",
$year + 1900, $mon + 1, $mday, $hour, $min, $sec,
$ENV{'REMOTE_ADDR'},
join(" ", @words));
close(OUT);
}
# HTML文書を書き出す
print "Content-type: text/html\n";
print "\n";
print "\n";
print "
\n";
print "検索結果\n";
print "\n";
print "\n";
print "\n";
print "検索
\n";
print "\n";
print "\n";
print "- このホームページの内容を検索します。\n";
print "
- 複数の単語を入力する時はスペースで区切ってください。\n";
print "
\n";
if ($return_url ne "") {
print "[戻る]\n";
}
print "
\n";
if (defined($FORM{'WORD'})) {
for ($i = 0; $i <= $#words; $i++) {
$words[$i] =~ s/([\+\*\.\?\^\$\[\-\]\|\(\)\\])/\\$1/g;
}
print "\n";
&search1($target_dir);
print "
\n";
print "
\n";
print "検索が完了しました。\n";
}
print "\n";
print "\n";
}
#
# フォームからの入力データを読み込んで $FORM{'XXXX'} に設定する
#
sub readform {
if ($ENV{'REQUEST_METHOD'} eq "POST") {
read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'});
} else {
$query_string = $ENV{'QUERY_STRING'};
}
@a = split(/&/, $query_string);
foreach $x (@a) {
($name, $value) = split(/=/, $x);
$value =~ tr/+/ /;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;
&jcode'convert(*value, "euc");
$FORM{$name} = $value;
}
}
#
# すべてのファイルをなめ回す
#
sub search1 {
local($dir) = $_[0];
local(@filelist, $file, $filename);
opendir(DIR, $dir);
@filelist = readdir(DIR);
closedir(DIR);
foreach $file (@filelist) {
if ($file eq ".") { next; }
if ($file eq "..") { next; }
$filename = "$dir/$file";
if (-d $filename) {
&search1($filename);
} else {
&search2($filename, $dir);
}
}
}
#
# ファイルの中身を検索する
#
sub search2 {
local($target, $tdir) = @_;
# 指定していない拡張子のファイルは無視する
$fname = substr($target, rindex($target, "."));
if ($sufix{$fname} != 1) {
return;
}
# 各種変数を初期化する
undef %wordflag;
$title = "";
$match_count = 0;
# ファイルを読み込む
open(IN, $target);
@lines = ;
close(IN);
# Macの \r 改行のファイルに対する考慮
if (($#lines == 0) && ($lines[0] =~ /\r[^\n]/)) {
@lines = split(/\r/, $lines[0]);
}
# それぞれの行に対し・・・
loop: for ($i = 0; $i <= $#lines; $i++) {
$line = $lines[$i];
# EUCに変換する
if ($jflag) {
&jcode'convert(*line, "euc");
}
# タイトルを覚えておく
if (($title eq "") && ($line =~ //i)) {
$title = $line;
}
# それぞれの検索語に対して・・・
foreach $word (@words) {
# すでに見つかっているなら次の行
if ($wordflag{$word} == 1) { next; }
# 検索語が見つからないなら次の行
if (!($line =~ /$word/i)) { next; }
# 見つかったことを覚えておく
$wordflag{$word} = 1;
# AND検索ですべて見つかったのでないなら次の行
if (($FORM{'ANDOR'} eq "and") &&
(++$match_count != $#words + 1)) {
next;
}
# 表示する
print "\n";
print "
";
$title =~ s/<[^>]*(>|$)//g;
$title =~ s/[\r\n]+//g;
&jcode'convert(*title, $kcode_cgi);
if ($title eq "") {
$title = $target;
}
print "$title\n";
print "( ";
$target =~ s/$tdir\/?//;
print "$target )\n";
print "";
$imin = $i - $how_many_lines;
if ($imin < 0) { $imin = 0; }
$imax = $i + $how_many_lines;
if ($imax > $#lines) { $imax = $#lines; }
for ($j = $imin; $j <= $imax; $j++) {
$line = $lines[$j];
&jcode'convert(*line, "euc");
$line =~ s/<[^>]*(>|$)//g;
$line =~ s/($word)/$1<\/B>/ig;
&jcode'convert(*line, $kcode_cgi, "euc");
print "$line ";
}
print "\n";
last loop;
}
}
}