#!/usr/bin/perl
###!/usr/local/bin/perl

#┌─────────────────────────────────
#│ Quick DB : quick.cgi - 2019/11/17
#│ copyright (c) kentweb, 1997-2019
#│ http://www.kent-web.com/
#└─────────────────────────────────

# モジュール宣言
use strict;
use CGI::Carp qw(fatalsToBrowser);

# 設定ファイル認識
require "./init.cgi";
my %cf = set_init();

# データ受理
my %in = parse_form();

# 検索
if ($in{mode} eq 'find') { find_db(); }
main_page();

#-----------------------------------------------------------
#  メインページ
#-----------------------------------------------------------
sub main_page {
	# カテゴリ
	my %op;
	foreach my $i (1 .. 3) {
		foreach my $op (0 .. $#{$cf{"cate$i"}}) {
			$op{$i} .= qq|<option value="$op">$cf{"cate$i"}->[$op]\n|;
		}
	}
	
	# テンプレート読み込み
	open(IN,"$cf{tmpldir}/quick.html") or error('open err: quick.html');
	my $tmpl = join('',<IN>);
	close(IN);
	
	# 文字置き換え
	$tmpl =~ s/!(topurl|html_title|db_cgi|admin_cgi)!/$cf{$1}/g;
	$tmpl =~ s|!css_url!|$cf{cmnurl}/style.css|;
	$tmpl =~ s/!box-([1-3])!/$cf{categ}->[$1-1]/g;
	$tmpl =~ s/<!-- op-([1-3]) -->/$op{$1}/g;
	$tmpl =~ s/!word!/$in{word}/g;
	
	# 表示
	print "Content-type: text/html; charset=utf-8\n\n";
	footer($tmpl);
}

#-----------------------------------------------------------
#  検索
#-----------------------------------------------------------
sub find_db {
	# ページ数
	$in{pg} =~ s/\D//g;
	my $pg = $in{pg} || 0;
	
	# UTF-8定義
	my $byte1 = '[\x00-\x7f]';
	my $byte2 = '[\xC0-\xDF][\x80-\xBF]';
	my $byte3 = '[\xE0-\xEF][\x80-\xBF]{2}';
	my $byte4 = '[\xF0-\xF7][\x80-\xBF]{3}';
	
	# キーワード処理
	$in{word} =~ s/　/ /g;
	my @wd = split(/\s+/,$in{word});
	
	# データベース展開
	my $i = 0;
	my @log;
	open(DB,"$cf{datadir}/db.cgi") or error('open err: db.cgi');
	while(<DB>) {
		my ($no,$ttl,$com,$cat1,$cat2,$cat3,$ex,$w,$h) = split(/<>/);
		
		# カテゴリ検索
		next if ($in{cat1} != $cat1 && $in{cat1} ne '');
		next if ($in{cat2} != $cat2 && $in{cat2} ne '');
		next if ($in{cat3} != $cat3 && $in{cat3} ne '');
		
		# ワード検索
		if ($in{word} ne '') {
			my $flg;
			foreach my $wd (@wd) {
				if ($com =~ /^(?:$byte1|$byte2|$byte3|$byte4)*?\Q$wd\E/i) {
					$flg++;
				} else {
					$flg = 0;
					last;
				}
			}
			next if (!$flg);
		}
		
		# 表示件数を分ける
		$i++;
		next if ($i < $pg + 1);
		next if ($i > $pg + $cf{logs});
		
		push(@log,$_);
	}
	close(DB);
	
	# 不正エラー
	if ($pg > $i) { error('ページ数が不正です'); }
	
	# テンプレート読み込み
	open(IN,"$cf{tmpldir}/find.html") or error('open err: find.html');
	my $tmpl = join('',<IN>);
	close(IN);
	
	# 文字置換
	$tmpl =~ s/!(db_cgi|html_title)!/$cf{$1}/g;
	$tmpl =~ s/!hit!/$i/g;
	$tmpl =~ s|<!-- pager -->|make_pager($i,$pg)|eg;
	$tmpl =~ s|!css_url!|$cf{cmnurl}/style.css|;
	
	# テンプレート分割
	my ($head,$loop,$foot) = $tmpl =~ m|(.+)<!-- loop -->(.+?)<!-- /loop -->(.+)|s
			? ($1,$2,$3)
			: error('テンプレート不正');
	
	# 画面表示
	print "Content-type: text/html; charset=utf-8\n\n";
	print $head;
	
	# 検索結果展開
	foreach (@log) {
		my ($no,$ttl,$com,$cat1,$cat2,$cat3,$ex,$w,$h) = split(/<>/);
		my %cat = (1 => $cat1, 2 => $cat2, 3 => $cat3);
		
		# 添付あり
		if ($ex) {
			# 画像あり
			if ($ex =~ /^(jpg|gif|png)$/) {
				$com = image($no,$ex,$w,$h,$com);
			
			# 画像以外
			} else {
				my $icon = defined($cf{ext}{$ex}) ? $cf{ext}{$ex} : $cf{ext_o};
				$com = qq|<a href="$cf{uplurl}/$no.$ex" target="_blank"><img src="$cf{cmnurl}/$icon" class="image" alt="$icon"></a>$com|;
			}
		}
		
		# 自動リンク
		$com = auto_link($com) if ($cf{auto_link});
		
		# 置換
		my $tmp = $loop;
		$tmp =~ s/!title!/$ttl/g;
		$tmp =~ s/!box-([1-3])!/$cf{categ}->[$1-1]/g;
		$tmp =~ s/!cat-([1-3])!/$cf{"cate$1"}->[$cat{$1}]/g;
		$tmp =~ s/!comment!/$com/g;
		print $tmp;
	}
	
	# フッター
	footer($foot);
}

#-----------------------------------------------------------
#  繰越ボタン作成
#-----------------------------------------------------------
sub make_pager {
	my ($i,$pg) = @_;
	
	# ページ繰越定義
	$cf{logs} ||= 10;
	my $next = $pg + $cf{logs};
	my $back = $pg - $cf{logs};
	
	# 引数
	my $param;
	$param .= "&amp;word=" . url_encode($in{word}) if ($in{word} ne '');
	$param .= "&amp;cat1=$in{cat1}" if ($in{cat1} ne '');
	$param .= "&amp;cat2=$in{cat2}" if ($in{cat2} ne '');
	$param .= "&amp;cat3=$in{cat3}" if ($in{cat3} ne '');
	
	# ページ繰越ボタン作成
	if ($back >= 0 or $next < $i) {
		my ($pager,$n);
		$n = $i;
		
		if ($back >= 0) {
			$pager .= qq|<a href="$cf{db_cgi}?mode=find&amp;pg=$back$param" class="page gradient">&laquo;</a>\n|;
		}
		
		my ($x,$y) = (1,0);
		while ($i > 0) {
			if ($pg == $y) {
				$pager .= qq|<span class="page active">$x</span>\n|;
			} else {
				$pager .= qq|<a href="$cf{db_cgi}?mode=find&amp;pg=$y$param" class="page gradient">$x</a>\n|;
			}
			$x++;
			$y += $cf{logs};
			$i -= $cf{logs};
		}
		
		if ($next < $n) {
			$pager .= qq|<a href="$cf{db_cgi}?mode=find&amp;pg=$next$param" class="page gradient">&raquo;</a>\n|;
		}
		
		return qq|<div class="pager">$pager</div>|;
	} else {
		return;
	}
}

#-----------------------------------------------------------
#  フォームデコード
#-----------------------------------------------------------
sub parse_form {
	my ($buf,%in);
	if ($ENV{REQUEST_METHOD} eq "POST") {
		error('受理できません') if ($ENV{CONTENT_LENGTH} > $cf{maxdata});
		read(STDIN,$buf,$ENV{CONTENT_LENGTH});
	} else {
		$buf = $ENV{QUERY_STRING};
	}
	foreach ( split(/&/,$buf) ) {
		my ($key,$val) = split(/=/);
		$val =~ tr/+/ /;
		$val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg;
		
		# 無効化
		$val =~ s/&/&amp;/g;
		$val =~ s/</&lt;/g;
		$val =~ s/>/&gt;/g;
		$val =~ s/"/&quot;/g;
		$val =~ s/'/&#39;/g;
		$val =~ s/[\r\n]//g;
		
		$in{$key} .= "\0" if (defined $in{$key});
		$in{$key} .= $val;
	}
	return %in;
}

#-----------------------------------------------------------
#  フッター
#-----------------------------------------------------------
sub footer {
	my $foot = shift;
	
	# 著作権表記（削除・改変禁止）
	my $copy = <<EOM;
<p style="margin-top:2em;text-align:center;font-family:Verdana,Helvetica,Arial;font-size:10px;">
	- <a href="http://www.kent-web.com/" target="_top">Quick DB</a> -
</p>
EOM

	if ($foot =~ /(.+)(<\/body[^>]*>.*)/si) {
		print "$1$copy$2\n";
	} else {
		print "$foot$copy\n";
		print "</body></html>\n";
	}
	exit;
}

#-----------------------------------------------------------
#  エラー画面
#-----------------------------------------------------------
sub error {
	my $err = shift;
	
	open(IN,"$cf{tmpldir}/error.html") or die;
	my $tmpl = join('',<IN>);
	close(IN);
	
	$tmpl =~ s/!error!/$err/g;
	$tmpl =~ s|!css_url!|$cf{cmnurl}/style.css|;
	
	print "Content-type: text/html; charset=utf-8\n\n";
	print $tmpl;
	exit;
}

#-----------------------------------------------------------
#  URLエンコード
#-----------------------------------------------------------
sub url_encode {
	my $str = shift;
	
	$str =~ s/([^\w ])/'%'.unpack('H2', $1)/eg;
	$str =~ tr/ /+/;
	return $str;
}

#-----------------------------------------------------------
#  画像表示
#-----------------------------------------------------------
sub image {
	my ($no,$ex,$w,$h,$com) = @_;
	
	my $image;
	if (-f "$cf{upldir}/$no-s.$ex") {
		$image = qq|<img src="$cf{uplurl}/$no-s.$ex" class="image" alt="$no-s.$ex">|;
	
	} else {
		($w,$h) = &resize($w,$h);
		$image = qq|<img src="$cf{uplurl}/$no.$ex" width="$w" height="$h" class="image" alt="$no.$ex">|;
	}
	return qq|<a href="$cf{uplurl}/$no.$ex" target="_blank">$image</a>$com|;
}

#-----------------------------------------------------------
#  自動リンク
#-----------------------------------------------------------
sub auto_link {
	my $text = shift;
	
	$text =~ s/(s?https?:\/\/([\w-.!~*'();\/?:\@=+\$,%#]|&amp;)+)/<a href="$1" target="_blank">$1<\/a>/g;
	return $text;
}

