#! /usr/bin/perl
#============================================
#mamas2.cgi ver.1.0
#《mamas2.cgiは、mamas.cgiのスキン式バージョンです。》

#Edited : --------
#Copyright (C) 2004,by p.ink
#Web Site : http://pink.obi.ne.jp/
#First Edition 2004/08/20 
#============================================
#この書類のタブ幅は24pt

#設置例；検索するディレクトリー内ヘ以下のファイルを設置。
#  	mamas2.cgi (755)
# 	jcode.pl(644)
#	HTM_search.html(644)

#以下のフォームをコピーして、任意のページに設置して下さい。必要なら、action=パス、を書き替えて下さい。
# <form action="./mamas2.cgi" method=post>	
# <input type=radio name=mode value=and checked>AND
# <input type=radio name=mode value=or>OR
# <input size=20 name=inwords maxlength="50">
# <input type=submit value="検索">
# </form>

#●ディレクトリー設定
##############################
#注意；ディレクトリー記述で最後の、/、は不要。

#設定1　検索開始ディレクトリを、本スクリプトからの相対パス。
# 例　$start = "../eban";	#１つ上のディレクトリーにある、eban、ディレクトリーを検索するとき。
# 例　$start = "./files";	#同じディレクトリーにある、files、ディレクトリーを検索するとき。
# 例　$start = ".";			#同じディレクトリーを検索するとき。

$start = "../..";

#設定2　ホームが「http://xxx/」で、eban、ディレクトリーへスクリプトを設置したとして、
#例　$url = "http://xxx";				#１つ上にある別ディレクトリーを検索するように設定したときは、１つ上のディレクトリー。
#例　$url = "http://xxx/eban";			#設置したディレクトリーにある、files、ディレクトリーを検索するときは、設置したディレクトリー。
#例　$url = "http://xxx/eban";			#設置したディレクトリーを検索するときは、設置したディレクトリー。

$url = "http://contest2005.thinkquest.jp/tqj2005/80520";

#●初期設定
##############################
#スキンファイル
$searchskin = "./search.htm";

# このスクリプトの名前
$script = "mamas2.cgi";

#表示タイトル
$scriptitle = "Search";

#jcode.pl のパス
$jcode = "./jcode.pl";

# 検索対象とするファイルの拡張子。例；("html","htm","txt");
@filetype = ("html","htm","txt");

# ヒット不要ディレクトリーの名前。例； ("xxx","himityu","lock");	例；();
@avoidir = ("img","icon","lock"); 

# 検索結果出力時に１ページに表示する最大件数
$pagemax = 10;

#検索結果ページへのリンクターゲット
$target = "target=\"_blank\"";

#●カラー設定
# キーワードにマッチした文字列の色は、スキン上に記述してあるスタイルシートの「spanカラー」で指定して下さい。
#検索結果表示の一番下に表示される「ページ数字ナビ」	の文字色設定
$xopen2 = "<font size=2 color=#898989><B>";		#リンク無し(当ページ)での、開始フォントタグ
$xclose2 = "</B></font>";							#リンク無し(当ページ)での、閉じフォントタグ

$xopen1 = "<font size=2>";					#リンク有り(他ページ)での、開始フォントタグ(カラーはリンク色)
$xclose1 = "</font>";							#リンク有り(他ページ)での、閉じフォントタグ

#●メインルーチン
##################################
require $jcode;
&decode;

@keywords = split (/ /,$inwords);
$keys = join (" ",@keywords);
$viewkeys = join (" ,",@keywords);

&readskin;

#入力フォーム
$headhtml =~ s/value=\"?or\"?/value=\"or\" checked/i if $chkor;
$headhtml =~ s/value=\"?and\"?/value=\"and\" checked/i if $chkand;
$headhtml =~ s/name=\"?inwords\"?/name=\"inwords\" value=\"$keys\"/i;

if (! $mode) { &xpageview("・複数のキーを入力するにはスペースで分けて下さい。<br>");} 
if (! $inwords) { &xpageview("<b>！</b>検索キーが入力されていません<br>"); }

#ヘッダータイトル
print "Content-type:text/html; charset=shift_jis\n\n";
print $headhtml;

#ディレクトリー検索開始
&opendir($start);
$total = 0;
foreach $file(@dirfiles) {
	#次のディレクトリーが有る場合戻ってもう一度検索し、@dirfilesが増える。
	if (! ($file =~ /\.\w/)) {
		&opendir($file);
		next;
	}
		
	@msgs = ();
	$andmatch = $match = 0;
		
	#キーワードごとにページ検索開始
	foreach $keyword(@keywords) {
		$flag = 0;

		#ファイルだったら読む
		open(IN,$file);
		while(<IN>){
		
		if ($_ =~ /<title>(.*)<\/title>/i) { $title = $1; }
		$_ =~ s/.*\/\/.*//g;		#コメント消去
		$_ =~ s/<[^>]*(>|$)//g;		#タグ消去
		$_ =~ s/&#?\w+?;//g;		#HTML特殊文字消去
		
		#マッチした次の行も読み、これ以上は検索せずに次のキーワードへ。
		if ($flag == 1){push (@msgs,$_);last;}
		
		#マッチしたら、その行を読み、色を付ける。
		if ($_ =~ /\Q$keyword\E/i) {
			$flag = 1;
			if ($mode eq "or"){$match = 1;}
			$_ =~ s/(\Q$keyword\E)/<span>$1<\/span>/ig;
			push (@msgs,$_); 
#			last;		#ここをコメントアウト、頭の#印を消去、すると、ヒットした一行だけを表示します。
		}
		}#/IN
		if ($flag == 1){$andmatch ++;}
	}#$keywords
	if (($mode eq "and") && ($andmatch == @keywords)){$match = 1;}
	$hitsong = join ("",@msgs);
	
	if ($match == 1) {
		$total ++;

		#トップ設定
		if ($page) { $top = $page;
		} else { $top = 0; }
		
		#エンド設定 $viewはプラスする数
		$view = $pagemax - 1;	
		$end = $top + $view;

		if ($total <= $top) {next;}
		elsif ($total > $end+1){next;}		#lastも可
		else {
	if (! $title) { $title = "notitle"; }
	$file =~ s/\.+\///g;

	#結果URLの表示が実際と異なる場合正しい表示へ変換します。
	#$file =~ s|aa|bb|;

#●表示テーブルの中身
$buf = $mainhtml;

$buf =~ s/\$total/$total/i;
$buf =~ s/\$url/$url/ig;
$buf =~ s/\$file/$file/gi;
$buf =~ s/\$title/$title/i;
$buf =~ s/\$target/$target/ig;
$buf =~ s/\$hitsong/$hitsong/i;

print $buf; 

		}
	}
}#/$file

#一番最後の番号設定
$total --;
if ($end > $total) { $end = $total; }

#検索結果のコメント表示
if ($total >= 0) {
#表示用の数字
$pagetop = $top + 1; $pageend = $end + 1; $pagetotal = $total + 1;
$printmsg =<<PRT;
	<b>「$viewkeys」</b> のヒット数 <b>$pagetotal</b> 件の内
	$pagetop 〜 $pageend 件を表\示しています。
PRT
} else {
$printmsg =<<PRT;
 	<font color=$rptcolor><b>「$viewkeys」</b> を検索した結果マッチするページは見つかりませんでした。</font>
PRT
}

$foothtml =~ s/\$printmsg/$printmsg/i;

$marklist = "";
$end++;
$prevpage = $top - $pagemax;
$inwords =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;

if ($page != 0) {
	$foothtml =~ s/\n([^\n]*)\$prev([^\n]*)\n/\n$1.\/$script?page=$prevpage&mode=$mode&inwords=$inwords$2\n/i;
	} else {
	$foothtml =~ s/\n([^\n]*)\$prev([^\n]*)\n//i;
	}
	
if ($end <= $total) {
	$foothtml =~ s/\n([^\n]*)\$next([^\n]*)\n/\n$1.\/$script?page=$end&mode=$mode&inwords=$inwords$2\n/i;	
	} else {
	$foothtml =~ s/\n([^\n]*)\$next([^\n]*)\n//i;	
	}

#ヒット数が、ページ表示枠を超えたときダイレクトリンク数字を表示。
if ($view < $total) {
	$no = 0;
	for ($i = 0; $i <= $total; $i += $pagemax) {
		$no ++;
		if ($top == $i) {
			$mark = "$xopen2$no$xclose2\n";
		} else {
			$mark =  "$xopen1<a href=\"$script?mode=$mode\&inwords=$inwords\&page=$i\">$no<\/a>$xclose1\n";
		}
		$marklist = "$marklist"."$mark";
	}
}

$foothtml =~ s/\$marklist/$marklist/i;
print $foothtml;
exit;

#●デコード処理
##################################
sub decode{
my ($method,$buffer,@pairs,$pair);
$method = $ENV{"REQUEST_METHOD"};
if($method eq "POST"){
	if ($ENV{"CONTENT_LENGTH"} > 500) { &xpageview("投稿量が大きすぎます<br>"); }
	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;
	$value =~ s/\r\n/\n/g;
	$value =~ s/\r/\n/g;
	$value =~ s/<[^>]*(>|$)//g;
	$value =~ s/&/&amp;/g;
	$value =~ s/</&lt;/g;
	$value =~ s/>/&gt;/g;
	$value =~ s/"/&quot;/g;
	$value =~ s/\'/&#39;/g; 
	$value =~ s/　/ /g;
	&jcode'convert(*value,"sjis");	
	$form{$name} = $value;
}

$inwords = $form{"inwords"};
$mode 	= $form{"mode"};
$page 	= $form{"page"};			#マッチファイルのリスト番号

if (! $chkor && ! $chkand) { $chkand = "checked"; }

#チェックドの設定
if ($mode eq "or") {
	$chkor = "checked";
} else {
	$chkand = " checked";
}

$url =~ s/https?\:\/\///g;			#http://を消す
$inwords =~ s/^\s+//g;			#頭にスペースあったら消す。
}

#●ディレクトリーオープン
##################################
sub opendir {
my ($avoid,@dirvalue,$type,$avoidflag);
$dir = "$_[0]/";

#受けたディレクトリー内のファイル名を読む
opendir DIR,$dir;
@dirvalue = readdir DIR;
close (DIR);

foreach (@dirvalue) {
	if (! ($_ =~ /\./)) {
		$avoidflag = 0;
		foreach $avoid (@avoidir){		#不要ディレクトリーチェック
			if ("$_" eq "$avoid"){$avoidflag = 1 ; last;}
		}
		push (@dirfiles,"$dir$_") if $avoidflag != 1;		
	} else {
		foreach $type (@filetype) {	#ファイル拡張子チェック
			if ($_ =~ /\.$type/i) {
				push (@dirfiles,"$dir$_"); 
				last;
			} 
		}
	}
}
}

#	●スキン読み込み
##########################################
sub readskin {

($headhtml,$foothtml) = ("","");
open(IN,$searchskin);
my $flag = 0;
while(<IN>){
$_ =~ s/\r\n/\n/g;	
if ($_ =~ /<!--SEARCH-->/i){
	$flag = 1;	
} elsif ($_ =~ /<!--\/SEARCH-->/i){
	$flag = 2;
}

$headhtml .= $_ if $flag == 0;
$mainhtml .= $_ if $flag == 1;		#<!--SEARCH-->と、テーブル
$foothtml .=$_ if $flag == 2;	
}
}

#●エックスページ
##################################
sub xpageview {
my $report = "$_[0]"; 

$foothtml =~ s/\n([^\n]*)\$prev([^\n]*)\n//i;
$foothtml =~ s/\n([^\n]*)\$next([^\n]*)\n//i;	
$foothtml =~ s/\$marklist//i;
$foothtml =~ s/\$printmsg/&#160;/i;
$foothtml =~ s/<!--\/SEARCH-->/<!--\/SEARCH-->\n$report<br>\n/;

print "Content-type:text/html; charset=shift_jis\n\n";
print "$headhtml$foothtml";
exit;
}


#臨時エラー
sub error{	
print "Content-type:text/html; charset=shift_jis\n\n";
print <<EOD;
<head>
<meta http-equiv="content-type" content="text/html; charset=shift_jis">
<meta http-equiv="pragma" content="no-cache">
<title>first error</title>
</head>
<body>

$_[0]

</body>
</html>
EOD
exit;
}
