#!/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"; &jcode'convert(*word, $kcode_cgi, "euc"); print "\n"; print "\n"; if ($FORM{'ANDOR'} eq "and") { print "AND\n"; print "OR\n"; } else { print "AND\n"; print "OR\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 "<P>\n"; print "<DT><A HREF=\"$target\" TARGET=out>"; $title =~ s/<[^>]*(>|$)//g; $title =~ s/[\r\n]+//g; &jcode'convert(*title, $kcode_cgi); if ($title eq "") { $title = $target; } print "$title</A>\n"; print "( <A HREF=\"$target\" TARGET=out>"; $target =~ s/$tdir\/?//; print "$target</A> )\n"; print "<DD>"; $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)/<B>$1<\/B>/ig; &jcode'convert(*line, $kcode_cgi, "euc"); print "$line "; } print "\n"; last loop; } } }