#!/usr/local/bin/perl

;# 簡易サーチエンジン jSearch <SJIS専用> v1.12     jsearch.cgi
;#
;# www.rescue.ne.jp
;# (c)rescue.ne.jp

;# History
;# 26/Jun/98 v1.00 初版
;# 6/July/98 v1.10 @TARGETで設定した最後のディレクトリしか認識されないバグを修正
;# 17/Dec/98 v1.11 全角文字マッチの不具合の訂正
;# 20/Jan/99 v1.12 検索手法のミスの修正

#--------------------------------------------------------------------------------------------

# 例えば、					< >内はパーミッション値の例
#
# ~rescue/ (最上位URL/パス)
#     |
#     |-- cgi/
#     |    |-- jsearch/
#     |            |-- jsearch.cgi <755>
#     |
#     |-- cgi-bin/
#     |      |-- jcode.pl <644>
#     |
#     |-- foo/
#     |    |--bar/
#
# という構成であるとし、cgi/ 内の *.html と *.txt および foo/ 内の *.html および foo/bar/ 内の *.txt を探して検索する
# 場合は下記のような位置関係の設定をします。戻るでは、ホームページに戻るような設定です。
# これを参考にして位置関係とその相対設定の記述の仕方を覚えてください。

#日本語コード変換ライブラリ
require '../../cgi-bin/jcode.pl';

#このスクリプト(jsearch.cgi)から見た検索対象の最上位域までのパス 最後に/を忘れずに
$base = '../../';

#ホームページディレクトリ(最上位URL) 最後に/を忘れずに http://から書いても可
$baseurl = '/~rescue/';

#<BODY>設定
$body = '<body>';

#$baseで設定した位置から見た検索対象パス この書式でいくつでも設定可能
@TARGET = ('cgi/*.html','cgi/*.txt','foo/*.html','foo/bar/*.txt');

#タイトル
$title = 'サーバ内検索';

#戻るリンク
$modoru_url = '/~rescue/';

#--------------------------------------------------------------------------------------------

if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }

@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {

	($name,$value) = split(/=/,$pair);
	$value =~ tr/+/ /;
	$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
	&jcode'convert(*value,'euc');
	if ($name eq 'search_strings') { $str = $value; $value =~ s/(\W)/\\$1/g; }
	$FORM{$name} = $value;
}

if ($buffer eq '' || $FORM{'search_strings'} eq '') { &html; exit; }

#--------------------------------------------------------------------------------------------

chdir($base);

foreach $target (@TARGET) {

	$list = `ls $target`;
	@lists = split(/\s+/,$list);
	push(@files,@lists);
}

@search_strings = split(/\\\s+/,$FORM{'search_strings'});
&jcode'convert(*str,'sjis');

#--------------------------------------------------------------------------------------------

foreach $file (@files) {

	open(DB,"$file");
	@lines = <DB>;
	close(DB);

	$string = join(' ',@lines);
	$string =~ s/(\n|\r|\t)//g;
	&jcode'convert(*string,'euc');

	if ($FORM{'ronri'} eq 'AND') {

		foreach $moji (@search_strings) {

			if (!($string =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$moji/i)) { $found{$file} = 0; last; }
			else { $found{$file} = 1; }
		}
	}
	elsif ($FORM{'ronri'} eq 'OR') {

		foreach $moji (@search_strings) {

			if ($string =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$moji/i) { $found{$file} = 1; last; }
			else { $found{$file} = 0; }
		}
	}

	if ($found{$file}) { 

		if ($string =~ /<title>(.*)<\/title>/i) { $title{$file} = "$1"; }
		else { $title{$file} = "$file"; }
	}
}

#--------------------------------------------------------------------------------------------

if ($FORM{'ronri'} eq 'AND') { $houhou="論理積(かつ)"; }
if ($FORM{'ronri'} eq 'OR') { $houhou="論理和(または)"; }

print "Content-type: text/html\n\n";
print "<html><head><title>検索結果</title></head>\n";
print "$body\n";
print "<h1>検索結果<hr noshade></h1>\n";

print "<li><b>検索文字列:</b> $str<br>\n";
print "<li><b>絞り込み方法\:</b> $houhou<p>\n";

$foo = 1;
print "<ol>\n";
foreach $key (keys %title) {

	$foo = 0;
	$ttl = $title{$key};
	&jcode'convert(*ttl,'sjis');

	print "<li><a href=\"$baseurl$key\">$ttl</a>\n";
}

if ($foo) { print "<li>抽出なし\n"; }
print "</ol><p>\n";

print "[<a href=\"$modoru_url\">戻る</a>]<p>\n";

print "<h4 align=right><hr noshade><a href=\"http://www.rescue.ne.jp/\" target=\"_top\">jSearch v1.12</a></h4><p>\n";
print "</body></html>\n";

exit;

#--------------------------------------------------------------------------------------------

sub html {

print <<"EOF";
Content-type: text/html\n
<html><head>
<title>$title</title></head>
$body
<h1>$title</h1>
<form method=post action="jsearch.cgi">
検索文字列
<input type=text name="search_strings" size=50>
(複数入力の場合は<b>半角スペース</b>で区切る)<p>
複数入力の場合の絞り込み方法 <select name="ronri">
<option value="AND">論理積(かつ)
<option value="OR" selected>論理和(または)
</select>
<input type=submit value="検索開始">
<input type=reset value="リセット">
</form><p>
[<a href="$modoru_url">戻る</a>]<p>
</body></html>
EOF
}