#!/usr/bin/perl

$version = "Ver 0.14";					# 変更しないでください。
#┌─────────────────────────────────
#│  JOYFUL NOTE v1.41 (2002/08/22)
#│  Copyright(C) Kent Web 2002
#│  webmaster@kent-web.com
#│  http://www.kent-web.com/
#└─────────────────────────────────
$cgiorgname = "kei Skin";				# 変更しないでください。
#
#============#
#  設定項目  #
#============#
# ライブラリ取込
@INC = ( "./", "../" );
require 'jcode.pl';
require 'cgi-lib.pl';
require 'kei.pl';

# スクリプトのファイル名
$script  = "./keiskin.cgi";

# Add Skin
# keidb.cgi の役割をするファイルパス（名前を変えた場合のみ）
# (例) "./keidb.cgi"
$mtncgi = "./keidb.cgi";

# ファイルロック形式
# Windows系サーバーの場合は2にしてください。
# → 0=no 1=symlink関数 2=mkdir関数
$kei'lockkey = 1;

# ロックファイル名（パスではなくファイル名のみ）
$kei'lockfile = 'keidb.lock';

# テーブルのデータ格納ディレクトリ（テーブル・ディレクトリまでのパスです）
# (例)テーブル名に sample を指定した場合に $datpath = "./" とすると、./sample/rec.dat として記録されます。
#     テーブル・ディレクトリ(sample)以降は指定しません。
# → パスの最後は / で終わること
$datpath = "./";

# バイナリファイルの格納ディレクトリ（テーブル・ディレクトリまでのパスです）
# (例)テーブル名に sample を指定した場合に $binpath = "./" とすると、./sample/bin/bin000.jpg として記録されます。
#     テーブル・ディレクトリ(sample)以降は指定しません。
# → パスの最後は / で終わること
$binpath = "./";

# バイナリファイルＵＲＬ（テーブル・ディレクトリまでのパスです）
# (例)テーブル名に sample を指定した場合に
#     バイナリが、http://www.***.com/~user/keidb/sample/bin/bin000.jpg の場合は
#      $BinUrl = "http://www.***.com/~user/keidb/"; と指定します。
#     テーブル・ディレクトリ(sample)以降は指定しません。
# → パスの最後は / で終わること
$BinUrl = "http://www.sayurinosato.co.jp/kyoudo/keidb/";

#============#
#  設定完了  #
#============#

#----------------------------------------------------------------------------#
# 機能：メイン
#----------------------------------------------------------------------------#
&kei'fdebug( "START----------------------------------------[ kei SKIN ]" );
&init;
&get_parameter;
if ($ENV{'REQUEST_METHOD'} eq "POST"){ &proc_div; }
else{
		if($kei'lockkey) { &kei'lock; }	# ロック処理
		$reccount = &kei'read_recs_ref( $datafile, *rec );
		if($kei'lockkey) { &kei'unlock; }	# ロック解除
		&page_add;
}
&kei'fdebug( "END------------------------------------------[ kei SKIN ]\n" );
#----------------------------------------------------------------------------#
# 機能：初期化
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub init
{
	$zensp = '(?:\x81\x40)';					# sjis
#	$zensp = '(?:\xA1\xA1)';					# euc
	$updstr = "$kei'zsp更$kei'zsp新$kei'zsp";
	$delstr = "$kei'zsp削$kei'zsp除$kei'zsp";

	@rec = ();
	%ck = ();

	$kei'cgiorgname = $cgiorgname;
	$kei'version = $version;

	# 著作権表示部（削除変更不可）
	$kei'copyright = "[ <a href='http://www.kei.ne.jp/~db/' target='_blank'>$kei'cgiorgname</a> $kei'version ]";

	# 現在日付と時刻
	&kei'get_ltime($wkday,$today,$sec,$tmin,$hour,$mday,$mon,$year,$wday);
	$todaynow = "$year$mon$mday$hour$tmin$sec";
}
#----------------------------------------------------------------------------#
# 機能：CGI パラメータチェック
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub get_parameter
{
	local( $para, @opt, @dum );

	$para = $ENV{'QUERY_STRING'};
	@opt = split( /\&/, $para );
	foreach(@opt){
		@dum = split( /=/, $_ );
		if( $dum[0] eq "table" )      { $table = $dum[1]; }
		elsif( $dum[0] eq "view"     ){ $view = $dum[1]; }
		elsif( $dum[0] eq "recpoint" ){ $recpoint = $dum[1]; }
		elsif( $dum[0] eq "skin" )    { $skin = $dum[1]; }		# Add Skin
		elsif( $dum[0] eq "search" )  {							# Add Skin
			$swords = $dum[1];
			$swords =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
		}
		elsif( $dum[0] eq "mode"     ){ $mode = $dum[1]; }		# ADD 0.14
	}
	if( $skin eq "" ){ $skin = "skin.html"; }					# Add Skin
	if( $recpoint eq "" ){ $recpoint = 0; }
	if( $table eq "" ){ &kei'create_error( "テーブルを指定してください。" ); }
	else{ &table_para; }
	if( $view eq "" ){
		if( $config'masteredit == 1 ){ $view = "L"; }
		else{ $view = "M"; }
	}
}
#----------------------------------------------------------------------------#
# 機能：テーブル定義（config.pl & table.def）の読み込み
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub table_para
{
	# テーブル別パラメーターの取得
	if( substr( $datpath, -1, 1 ) ne "/" ){ $datpath .= "/"; }
	$conpath   = $datpath . $table . "/config.pl";
	unless( -e $conpath ){ &kei'create_error( "テーブル設定ファイルが存在しません。[$conpath]" ); }
	require "$conpath";
	$pagestep = $config'pagestep;
	$tlc      = $config'tlc;
	$tbc      = $config'tbc;
	$tdc      = $config'tdc;
	$sbc      = $config'sbc;

	if( $config'sort_reverse == 2 && ( $config'rec_max > 1000 || $config'rec_delete != 1 ) ){
		&kei'create_error( "ランダム表\示を利用する場合は<br>\$rec_delete を 1<br>\$rec_max を 1000件以内<br>としてください。" );
	}

	# ファイル/パス設定
	&table_para_path( $table );

	# テーブル定義取得
	if($kei'lockkey) { &kei'lock; }	# ロック処理
	open( FPR, "<$tablefile" ) || &kei'create_error( "ファイルのオープンに失敗しました。[$tablefile]" );
	@rec = <FPR>;
	close( FPR );
	if($kei'lockkey) { &kei'unlock; }	# ロック解除
	$imgari = 0;
	$strshow[0] = -1;
	$itemmax = 1;						# 0はキー項目
	@imgp = ();
	foreach $recwk ( @rec ){
		$recwk =~ s/\s*$//;
		@wk = split( /<>/, $recwk );
		if( $wk[3] eq "IMG" ){			# 添付ファイル
			push @imgp, $itemmax;
			$imgari          = 1;
		}
		$kouban[$itemmax]    = $wk[0];
		$fep[$itemmax]       = lc( $wk[1] );
		$inputsize[$itemmax] = $wk[2];
		$style[$itemmax]     = uc( $wk[3] );
		$name[$itemmax]      = lc( $wk[4] );	#Add SKIN(lc)
		$jname[$itemmax]     = $wk[5];
		$hissu[$itemmax]     = $wk[6];
		if( $wk[7] ){ $strshow[$itemmax] = $wk[7]; }	# Version 0.70 未満の対処
		else{
			if( $wk[7] ne 0 ){ $strshow[$itemmax] = -1; }
			else             { $strshow[$itemmax] = 0; }
		}
		if( $wk[8] ){					# Version 0.92 未満の対処
			$optlist[$itemmax] = $wk[8];
		}
		if( $name[$itemmax] eq "PASS" ||
			$name[$itemmax] eq "MPASS" ||
			$name[$itemmax] eq "MODE" ||
			$name[$itemmax] eq "SEARCH" ||
			$name[$itemmax] eq "SUBMIT" ||
			$name[$itemmax] eq "KEY" ||
			$name[$itemmax] eq "RND1" ||
			$name[$itemmax] eq "RND2" ||
			$name[$itemmax] eq "RECPOINT" ||
			$name[$itemmax] eq "RBCSV" ){
			&kei'create_error( "[$name[$itemmax]]は定義文字のため使用しないでください。" );
		}
		$ic{$name[$itemmax]} = $itemmax;
		$itemmax++;
	}
}
#----------------------------------------------------------------------------#
# 機能：テーブルごとのファイルパスを設定
# 引数：$table(i) / テーブル名
# 返値：なし
#----------------------------------------------------------------------------#
sub table_para_path
{
	local( $table ) = @_;

	# ファイル・パス設定
	if( $binpath eq "" ){ $binpath = $datpath; }
	# 閲覧者がダウンロードしたりＵＲＬ表示するものは、$binpath に入れる。
	$imgpath     = $binpath . $table . "/bin/";			# バイナリ格納
	$delimgpath  = $binpath . $table . "/bin_del/";		# バイナリ格納（自動削除分）
	$csvfilepath = $binpath . $table . "/csv/";			# CSV/TSVファイルパス

	# 上記で $binpath に入れたもののＵＲＬ表示。
	if( $BinUrl  eq "" ){ $BinUrl  = $binpath; }
	$CsvUrl      = $BinUrl  . $table . "/csv/";			# CSV/TSVＵＲＬ
	$BinUrl      = $BinUrl  . $table . "/bin/";			# 画像表示ＵＲＬ

	# システム内でのみ使用するファイル。ＵＲＬとして使用しないもの。
	$tablefile   = $datpath . $table . "/table.def";	# テーブル定義
	$datafile    = $datpath . $table . "/rec.dat";		# データ
	$deldatafile = $datpath . $table . "/rec_del.dat";	# データ（自動削除分）
	$lockpath    = $datpath . $table . "/lock/";		# ロックファイルディレクトリ
	$kei'lockfile = $lockpath . $kei'lockfile;		# テーブル単位ロックファイルパス

	unless( -e $tablefile   ){ &kei'create_error( "テーブル定義が存在しません。[$tablefile]" ); }
	unless( -d $imgpath     ){ &kei'create_dir( $imgpath ); }
	unless( -d $delimgpath  ){ &kei'create_dir( $delimgpath ); }
	unless( -d $csvfilepath ){ &kei'create_dir( $csvfilepath ); }
	unless( -d $lockpath    ){ &kei'create_dir( $lockpath ); }
	unless( -e $datafile    ){ &kei'create_file( $datafile ); }
	unless( -e $deldatafile ){ &kei'create_file( $deldatafile ); }

	#Add SKIN
	$skinfile   = $datpath . $table . "/" . $skin;			# スキンファイル
	unless( -e $skinfile ){ &kei'create_error( "スキンが存在しません。[$skinfile]" ); }
}
#----------------------------------------------------------------------------#
# 機能：フォームデータの取得と処理振り分け
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub proc_div
{
	&conv_form_data;					# フォーム取得

	# レコード処理振り分け
	if( $mode eq "search" ){			# 検索処理
		if($kei'lockkey) { &kei'lock; }	# ロック処理
		$reccount = &kei'read_recs_ref( $datafile, *rec );
		if($kei'lockkey) { &kei'unlock; }	# ロック解除
		&page_add;
	}
	else{								# 通常画面を表示
		if($kei'lockkey) { &kei'lock; }	# ロック処理
		$reccount = &kei'read_recs_ref( $datafile, *rec );
		if($kei'lockkey) { &kei'unlock; }	# ロック解除
		&page_add;
	}

}
#----------------------------------------------------------------------------#
# 機能：フォームデータの取得
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub conv_form_data
{
	local( $i, $j, $olcnt, $opliwk, @olitem );

	@in = ();
	&ReadParse;							# Reads in GET or POST data
	&kei'decode( *name, *imgp, *in );

	for( $i = 0 ; $i < $itemmax ; $i++ ){
		if( substr( $style[$i], 0, 3) eq "YMD" ){		# YMD1〜4
			if( $in{"$name[$i]1"} eq "" || $in{"$name[$i]2"} eq "" || $in{"$name[$i]3"} eq "" ){
				$field[$i] = "";
			}
			else{
				$field[$i] = sprintf( "%04d/%02d/%02d", $in{"$name[$i]1"}, $in{"$name[$i]2"}, $in{"$name[$i]3"} );
			}
		}
		elsif( substr( $style[$i], 0, 3) eq "HNS" ){	# HNS1〜4
			if( $in{"$name[$i]1"} eq "" || $in{"$name[$i]2"} eq "" || $in{"$name[$i]3"} eq "" ||
				$in{"$name[$i]4"} eq "" || $in{"$name[$i]5"} eq "" || $in{"$name[$i]6"} eq "" ){
				$field[$i] = "";
			}
			else{
				$field[$i] = sprintf( "%04d/%02d/%02d %02d:%02d:%02d", $in{"$name[$i]1"}, $in{"$name[$i]2"}, $in{"$name[$i]3"}, $in{"$name[$i]4"}, $in{"$name[$i]5"}, $in{"$name[$i]6"} );
			}
		}
		elsif( substr( $style[$i], 0, 3) eq "CHK" ){	# CHK系で保存するために'|'でくっつける
			$opliwk = $optlist[$i];				# EUCにするための作業用
			&jcode'convert(*opliwk, "euc");		# EUCコードに変換
			@olitem = split( /\|/, $opliwk );
			$olcnt = @olitem;					# ここでの@olitem はカウントのみ
			$field[$i] = "";
			for( $j = 0 ; $j < $olcnt ; $j++ ){
				$field[$i] .= $in{"$name[$i]$j"};
				$field[$i] .= "\|";
			}
			chop( $field[$i] );
		}
		else{
			$field[$i] = $in{$name[$i]};
		}
		$field[$i] =~ s/\,/ /g;			# カンマをSPACEに変換
		$field[$i] =~ s/\t/ /g;			# タブをSPACEに変換
		$field[$i] =~ s/<>/ /g;			# <>をSPACEに変換
		if( $style[$i] eq "MEMO1" || $style[$i] eq "MEMO2" || $style[$i] eq "TAGMEMO1" || $style[$i] eq "TAGMEMO2" ){ $field[$i] =~ s/\r\n/<BR>/g; }
		if( $style[$i] eq "URL" && $field[$i] eq "http://" ){ $field[$i] = ""; }
	}
	$mpass		= $in{'MPASS'};
	$pass		= $in{'PASS'};
	$mode		= $in{'MODE'};
	$swords		= $in{'SEARCH'};
	$command	= $in{'SUBMIT'};
	$field[0]	= $in{'KEY'};
	if( $in{'RND1'} ){ @rnd1 = split( / /, $in{'RND1'} ); }
	if( $in{'RND2'} ){ @rnd2 = split( / /, $in{'RND2'} ); }
}
#----------------------------------------------------------------------------#
# 機能：検索
# 引数：$swords(I)
#     ：@rectmp(I)
# 返値：@rec
#----------------------------------------------------------------------------#
sub search_rec
{
	local( $swords, *rectmp ) = @_;
	local( $i, $j, $litem, $dbrec, $dbrecl, $switem, $matchflag, @recsep, @olitem, @dbitem, @dat, @list_chk, @chk_chk, @pairs );

	if( $swords eq "" ){ return 0; }

	# 使用不可文字を半角SPACEに強制変換
	$swords =~ s/$zensp+/\x20/g;
	$swords =~ s/^\s+//o;
	$swords =~ s/\s+$//o;
	$swords =~ s/(\t|\,|<>)/\x20/g;
	&jcode'convert(*swords, "euc");			# 検索のためにEUCにしておく
	@pairs = split(/ /,$swords);

	for( $i=1 ; $i<$itemmax ; $i++ ){		# LIST/OPT/CHK 存在チェック
		$optlist_wk[$i] = $optlist[$i];
		&jcode'convert(\$optlist_wk[$i], "euc");	# 検索用
		$matchflag = 0;					# リストの中に該当有りか？
		foreach $switem ( @pairs ){
			if( $optlist_wk[$i] =~ /$switem/ ){
				$matchflag = 1;
				last;
			}
		}
		if( $matchflag == 1 ){
			if( $style[$i] eq "LIST" || $style[$i] eq "OPT" ){
				push @list_chk, $i;
			}
			elsif( $style[$i] eq "CHK" ){
				push @chk_chk, $i;
			}
#			@olitem = split( /\|/, $optlist_wk[$i] );
		}
	}

	@dat = ();
	$litem = $itemmax - 1;
	foreach $dbrec ( @rectmp ){
		@dbitem = split( /<>/, $dbrec );	# もともとEUC

		foreach $i ( @list_chk ){		# LIST / CHK の展開
#			@olitem = split( /\|/, $optlist_wk[$i] );
#			$dbitem[$i] = $olitem[$dbitem[$i]];
			$dbitem[$i] = ( split( /\|/, $optlist_wk[$i] ) )[$dbitem[$i]];
		}
		foreach $i ( @chk_chk ){					# CHK の展開
			@olitem = split( /\|/, $optlist_wk[$i] );
			@recsep = split( /\|/, $dbitem[$i] );
			for( $j=0 ; $j<=$#recsep ; $j++ ){
				$recsep[$j] =~ s/1/$olitem[$j]/;
			}
			$dbitem[$i] = join( "/", @recsep );
		}

		$dbrecl = join "/", @dbitem[1..$litem];		# PASS KEY 以外
#		study( $dbrecl );

		# map とか使うと遅くなる。
		$matchflag = 1;								# AND検索
		foreach $switem ( @pairs ){
			unless( $dbrecl =~ /$switem/ ){
				$matchflag = 0;
				last;
			}
		}
		if( $matchflag == 1 ){ push @dat, $dbrec; }
	}
	@rectmp = @dat;
	return $swords;
}
#----------------------------------------------------------------------------#
# 機能：データリストの並べ替え
# 引数：なし
# 返値：なし
#----------------------------------------------------------------------------#
sub listSORT
{
local( $loop );
if( $config'sort_reverse == 1 ){ # 逆順表示の場合
@rec = reverse @rec;
}
elsif( $config'sort_reverse == 2 ){ # ランダム表示
if( @rnd1 ){
$loop = 0;
foreach( @rnd1 ){
( $rec[$rnd1[$loop]] , $rec[$rnd2[$loop]] ) = ( $rec[$rnd2[$loop]], $rec[$rnd1[$loop]] );
$loop++;
}
}
else{
srand( time );
$loop = 0;
foreach( @rec ){
$rnd1[$loop] = int( rand( 1 ) * $reccount );
$rnd2[$loop] = int( rand( 1 ) * $reccount );
( $rec[$rnd1[$loop]] , $rec[$rnd2[$loop]] ) = ( $rec[$rnd2[$loop]], $rec[$rnd1[$loop]] );
$loop++;
}
}
}
elsif( $config'sort_reverse == 3 ){ # Add Item Sort
if( $config'sort_field ne ""){ # Add Item Sort
@recbuff = map( ( split( /<>/, $_ ) )[$config'sort_field], @rec ); # Add Item Sort
if( $config'sort_order eq "D" ){ # Add Item Sort
@rec = @rec[ sort( { $recbuff[$b] cmp $recbuff[$a] } (0 .. $#recbuff) ) ];
} # Add Item Sort
else{ # Add Item Sort
@rec = @rec[ sort( { $recbuff[$a] cmp $recbuff[$b] } (0 .. $#recbuff) ) ];
} # Add Item Sort
} # Add Item Sort
} # Add Item Sort
if( $mode eq "insert" ){
if( $config'sort_reverse == 1 ){ # 逆順表示の場合
$recpoint = 0;
}
else{ # その他の場合
$calcbuff = int( $reccount / $pagestep );
$recpoint = $calcbuff * $pagestep;
}
}
$sort= 1; # ITEM01 でソートする
@recbuff1 = map( ( split( /<>/, $_ ) )[$config'sort_field1], @rec );
@recbuff2 = map( ( split( /<>/, $_ ) )[$config'sort_field2], @rec );
if( $config'sort_order eq "D" ){
@rec = @rec[ sort( { $recbuff1[$b] cmp $recbuff1[$a] || $recbuff2[$b] cmp $recbuff2[$a] } (0 .. $#recbuff1) ) ];
}
else{
@rec = @rec[ sort( { $recbuff1[$a] cmp $recbuff1[$b] || $recbuff2[$a] cmp $recbuff2[$b] } (0 .. $#recbuff1) ) ];
}
}
#----------------------------------------------------------------------------#
#****************************************************************************#
# 以降はページの表示部分
#****************************************************************************#
sub page_add
{
#	$help = "■$kei'zspデータを新しく追加します$kei'zsp■";
	&page_common;
}
#----------------------------------------------------------------------------#
sub page_common
{
	&kei'get_cookie( "keiDB", *ck );
	$item[$itemmax] = $ck{'pwd'};
print "Content-type: text/html\n\n";
	if( $swords ne "" && $reccount > 100000 ){
		print "<font size='2'>しばらくお待ち下さい。</font><br>";
	}
	&view_SKIN;
}
#----------------------------------------------------------------------------#
sub make_SEARCH1
{
	$actcgi = $script . "?table=$table&skin=$skin&recpoint=0";
	$search1 = "";
	$search1 .= "<table width='100%' border='0' cellspacing='0' cellpadding='0'>\n";
	$search1 .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
	$search1 .= "<tr>\n";
	$search1 .= "<td align='center'><font size='2'>検索キー </font>";
	$search1 .= "<input type='text' name='SEARCH' size='30' value='$swords' class='active' maxlength='512'>\n";
	$search1 .= "<input type='hidden' name='MODE' value='search'>\n";
	$search1 .= "<input type='hidden' name='RND1' value=''>\n";
	$search1 .= "<input type='hidden' name='RND2' value=''>\n";
	$search1 .= "<input type='submit' name='SUBMIT' value='検索'>\n";
	$search1 .= "</td>\n";
	$search1 .= "</tr>\n";
	$search1 .= "</form>\n";
	$search1 .= "</table>\n";
}
#----------------------------------------------------------------------------#
sub make_TOOLBAR_setting
{
	#--------------------
	#- 共通ボタンの定義 -
	#--------------------
	$btncommon = <<HTML;
<input type='hidden' name='SEARCH' value='$swords'>
<input type='hidden' name='RND1' value='@rnd1'>
<input type='hidden' name='RND2' value='@rnd2'>
HTML
}

sub make_TOOLBAR_off
{
	local( $toolbar ) = @_;

	if( $swords ne "" ){
		$actcgi = $script . "?table=$table&skin=$skin&recpoint=0";
		$toolbar .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
		$toolbar .= "<td width='50'>\n";
		$toolbar .= "<input type='hidden' name='SEARCH' value=''>\n";
		$toolbar .= "<input type='hidden' name='RND1' value='@rnd1'>\n";
		$toolbar .= "<input type='hidden' name='RND2' value='@rnd2'>\n";
		$toolbar .= "<input type='submit' name='SUBMIT' value='検索解除'>\n";
		$toolbar .= "</td>\n";
		$toolbar .= "</form>\n";
	}

	@_[0] = $toolbar;
}

sub make_TOOLBAR_top
{
	local( $toolbar ) = @_;

	$actcgi = $script . "?table=$table&skin=$skin&recpoint=0";
	$toolbar .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
	$toolbar .= "<td width='50'>\n";
	$toolbar .= "$btncommon";
	$toolbar .= "<input type='submit' name='SUBMIT' value='<< 最初'>\n";
	$toolbar .= "</td>\n";
	$toolbar .= "</form>\n";

	@_[0] = $toolbar;
}

sub make_TOOLBAR_prev
{
	local( $toolbar ) = @_;

	$actcgi = $script . "?table=$table&skin=$skin&recpoint=$prevpoint";
	$toolbar .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
	$toolbar .= "<td width='50'>\n";
	if( $prevpoint >= 0 ){
		$toolbar .= "$btncommon";
		$toolbar .= "<input type='submit' name='SUBMIT' value='< 前へ'>\n";
	}
	$toolbar .= "</td>\n";
	$toolbar .= "</form>\n";

	@_[0] = $toolbar;
}

sub make_TOOLBAR_count
{
	local( $toolbar ) = @_;

	$toolbar .= "<td width='150' align='center'><font size='2'>( $frompoint-$topoint / ";
	if( $swords ne "" ){	$toolbar .= "検索$reccount件"; }
	else{					$toolbar .= "全$reccount件"; }
	$toolbar .= " )</font></td>\n";

	@_[0] = $toolbar;
}

sub make_TOOLBAR_next
{
	local( $toolbar ) = @_;

	$actcgi = $script . "?table=$table&skin=$skin&recpoint=$nextpoint";
	$toolbar .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
	$toolbar .= "<td width='50'>\n";
	if( $nextpoint < $reccount ){
		$toolbar .= "$btncommon";
		$toolbar .= "<input type='submit' name='SUBMIT' value='次へ >'>\n";
	}
	$toolbar .= "</td>\n";
	$toolbar .= "</form>\n";

	@_[0] = $toolbar;
}

sub make_TOOLBAR_last
{
	local( $toolbar ) = @_;

	$actcgi = $script . "?table=$table&skin=$skin&recpoint=$lastpage";
	$toolbar .= "<form method='post' action='$actcgi' enctype='multipart/form-data'>\n";
	$toolbar .= "<td width='50'>\n";
	$toolbar .= "$btncommon";
	$toolbar .= "<input type='submit' name='SUBMIT' value='最後 >>'>\n";
	$toolbar .= "</td>\n";
	$toolbar .= "</form>\n";

	@_[0] = $toolbar;
}
#----------------------------------------------------------------------------#
sub make_TOOLBAR1
{
	&make_TOOLBAR_setting;

	#--------------------
	#- ツールバーの定義 -
	#--------------------
	$toolbar1  = "";
	$toolbar1 .= "<table width='100%' border='0' cellspacing='1' cellpadding='1'>\n";
	$toolbar1 .= "<tr>\n";
	$toolbar1 .= "<td width='50'><font size='2'>[ <a href='$config'homepage'>Home</a> ]</font></td>\n";

	&make_TOOLBAR_off( $toolbar1 );
	&make_TOOLBAR_top( $toolbar1 );
	&make_TOOLBAR_prev( $toolbar1 );
	&make_TOOLBAR_count( $toolbar1 );
	&make_TOOLBAR_next( $toolbar1 );
	&make_TOOLBAR_last( $toolbar1 );

	$toolbar1 .= "<td align='right'><font size='2'>[ <a href='$mtncgi' target='_blank'>編集</a> ]</font></td>\n";

	$toolbar1 .= "</tr>\n";
	$toolbar1 .= "</table>\n";
}
#----------------------------------------------------------------------------#
sub make_TOOLBAR2
{
	&make_TOOLBAR_setting;

	#--------------------
	#- ツールバーの定義 -
	#--------------------
	$toolbar2  = "";
	$toolbar2 .= "<table width='400' border='0' cellspacing='1' cellpadding='1'>\n";
	$toolbar2 .= "<tr>\n";

	&make_TOOLBAR_off( $toolbar2 );
	&make_TOOLBAR_top( $toolbar2 );
	&make_TOOLBAR_prev( $toolbar2 );
	&make_TOOLBAR_count( $toolbar2 );
	&make_TOOLBAR_next( $toolbar2 );
	&make_TOOLBAR_last( $toolbar2 );

	$toolbar2 .= "</tr>\n";
	$toolbar2 .= "</table>\n";
}
#----------------------------------------------------------------------------#
sub view_SKIN
{
	local( $bodyflag );

	#--------
	#- 検索 -
	#--------
	if( $swords ne "" ){
		&search_rec( $swords, *rec );
		$reccount = @rec;
	}

	#----------
	#- ソート -
	#----------
	&listSORT;							# レコードソート
	if( $reccount <= $recpoint ){
		$recpoint = $recpoint - $pagestep;
	}

	#----------------------
	#- スキンファイル読込 -
	#----------------------
	open( FPR, "<$skinfile" ) || &kei'create_error( "ファイルのオープンに失敗しました。[$skinfile]" );
	@skin = <FPR>;
	close( FPR );

	#--------------------------------
	#- 前処理 繰り返し件数などの取得-
	#--------------------------------
	foreach $html ( @skin ){
		#----------------------------------
		#- １ページあたりの表示レコード数 -
		#----------------------------------
		if( $html =~ /<message(\d*)>/i ){
			if( $1 ne "" && $1 ne "0" ){
				$pagestep = $1;			# １ページあたりの表示レコード数
			}
		}
	}

	#----------------------
	#- レコード件数の計算 -
	#----------------------
	$prevpoint = $recpoint-$pagestep;					# 前ページ開始レコード
	$nextpoint = $recpoint+$pagestep;					# 次ページ開始レコード
	$pagemax=int(($reccount-1) / $pagestep )+1;			# 全ページ数
	$lastpage = ( $pagemax -1 ) * $pagestep;			# 最終ページ開始レコード
	$frompoint = $recpoint + 1;							# 表示開始レコード
	$topoint = $frompoint + $pagestep -1;				# 表示終了レコード
	if( $topoint > $reccount ){ $topoint = $reccount; }	# $toppoint補正
	if( $topoint < 0 ){ $topoint = 0; }					# $topoint補正
	if( $frompoint < 0 ){ $frompoint = 0; }				# $frompoint補正

	#----------------
	#- 定型文の定義 -
	#----------------
	$cgisign = "<!-- $kei'cgiorgname $kei'version http://www.kei.ne.jp/~db/ By kei DataBase -->";
	$mtncgi = $mtncgi . "?table=$table&recpoint=$recpoint";

	#-------------------
	#- toolbar  の定義 -
	#-------------------
	&make_TOOLBAR1;
	&make_TOOLBAR2;

	#------------------
	#- search1 の定義 -
	#------------------
	&make_SEARCH1;

	#-------------------
	#- recs_str の定義 -
	#-------------------
	if( $swords ne "" ){ $recs_str = "検索$reccount件"; }
	else{ $recs_str = "全$reccount件"; }

	#--------------------
	#- スキン変換＆表示 -
	#--------------------
	@skinmessage = ();					# データ部保存用
	$htmlflag = 0;
	foreach $html ( @skin ){
		#----------------------------
		#- 全体共通の固定項目の置換 -
		#----------------------------
		$html =~ s/<body(.*)>/<body$1>\n$cgisign/gi;			# kei-SKIN
		$html =~ s/\[sname\.\]/$kei'title/gi;					# [sname.]
		$html =~ s/\[home\.\]/$config'homepage/gi;				# [home.]
		$html =~ s/\[keidb\.\]/$mtncgi/gi;						# [keidb.]
		$html =~ s/\[kei\.\]/$script/gi;					# [kei.]	Ver 0.04
		$html =~ s/\[table\.\]/$table/gi;						# [table.]		Ver 0.04
		$html =~ s/\[skin\.\]/$skin/gi;							# [skin.]		Ver 0.04
		$html =~ s/\[copyright\.\]/$kei'copyright/gi;			# [copyright.]
		$html =~ s/\[comment\.\]/$config'tablecom/gi;			# [comment.]

		$html =~ s/\[pages\.\]/$pagemax/gi;						# [pages.]
		$html =~ s/\[recs\.\]/$reccount/gi;						# [recs.]
		$html =~ s/\[recfrom\.\]/$frompoint/gi;					# [recfrom.]
		$html =~ s/\[recto\.\]/$topoint/gi;						# [recto.]
		$html =~ s/\[log_new\.\]/$nextpoint/gi;					# [log_new.]
		$html =~ s/\[log_old\.\]/$prevpoint/gi;					# [log_old.]
		$html =~ s/\[log_top\.\]/0/gi;							# [log_top.]
		$html =~ s/\[log_last\.\]/$lastpage/gi;					# [log_last.]

		$html =~ s/\[recs_str\.\]/$recs_str/gi;					# [recs_str.]

		$html =~ s/\[search1\.\]/$search1/gi;					# [search1.]
		$html =~ s/\[toolbar1\.\]/$toolbar1/gi;					# [toolbar1.]
		$html =~ s/\[toolbar2\.\]/$toolbar2/gi;					# [toolbar2.]

		$html =~ s/\[@(\w*)\.\]/$jname[$ic{lc($1)}]/gi;			# [@項目名.]

		while( $html =~ /\[%(\w*)-(\d+)\.\]/i ){				# [%項目名.]
			$opliwk = $optlist[$ic{lc($1)}];					# EUCにするための作業用
			&jcode'convert(*opliwk, "euc");						# EUCコードに変換
			@li = split(/\|/,$opliwk);
			&jcode'convert(\$li[$2], "sjis");					# SJISコードに変換
			$html =~ s/\[%(\w*)-(\d+)\.\]/$li[$2]/i;
		}

		# Version 0.08 までの仕様も残す
		while( $html =~ /\[%(\D*)(\d+)\.\]/i ){					# [%項目名.]
			$opliwk = $optlist[$ic{lc($1)}];					# EUCにするための作業用
			&jcode'convert(*opliwk, "euc");						# EUCコードに変換
			@li = split(/\|/,$opliwk);
			&jcode'convert(\$li[$2], "sjis");					# SJISコードに変換
			$html =~ s/\[%(\D*)(\d+)\.\]/$li[$2]/i;
		}

		#----------------------------------
		#- データ部検出（ここまでヘッダ） -
		#----------------------------------
		if( $html =~ /<message(\d*)>/i ){
			$htmlflag = 1;
			$html =~ s/<message(\d*)>/<!-- BODY Start -->/i;
		}

		# <message> 及び </message> の後は必ず改行すること。

		#--------
		#- 表示 -
		#--------
		if( $htmlflag == 0 ){				# ボディ外部の場合の処理（ヘッダ／フッタ部表示）
#			print $html;
			&exec_ssi( $html );				# SSI-EXEC を処理	# Ver 0.13
		}
		elsif( $htmlflag == 1 ){			# ボディ内部の場合の処理（データ部取り出し）
			push @skinmessage, $html;
		}
		elsif( $htmlflag == 2 ){			# ボディ外部の場合の処理（データ部表示）
			&list_SKIN;
#			print $html;					# </message>の次の行を出力
			&exec_ssi( $html );				# SSI-EXEC を処理	# Ver 0.13
			$htmlflag = 0;					# ゼロクリア（データ部の繰り返しが可能）
		}
		else{								# ここは通らない
#			print $html;
			&exec_ssi( $html );				# SSI-EXEC を処理	# Ver 0.13
		}

		#----------------------------------
		#- データ部終了（ここからフッタ） -
		#----------------------------------
		if( $html =~ /<\/message(\d*)>/i ){
			$htmlflag = 2;
		}
	}
}
#----------------------------------------------------------------------------#
sub list_SKIN
{
	local( $i, $showmax );

	# 一覧表示
	$showmax = $recpoint + $pagestep;
	for( $loop=$recpoint ; $loop < $showmax ; $loop++ ){
		unless( $rec[$loop] ){ next; }		# 空行
		&jcode'convert(\$rec[$loop], "sjis");
		@recfield = split( /<>/, $rec[$loop] );

# Add SKIN
		foreach $htmllist( @skinmessage ){

			# オリジナルタグの置換
			$htmllist =~ s/<\/message(\d*)>/<!-- BODY End -->/i;

			$tmplist = $htmllist;											# コピーしてから

# Add SKIN
			# [$項目名.]の処理
			while( 1 ){
				if( $tmplist =~ /\[\$(\w*)\.\]/i ){			# $の場合はkeidbと同じ出力
					$i = $ic{lc($1)};

					if( $style[$i] eq "TEXT" ){
						$past[$i] = &kei'listTEXT( $recfield[$i], $strshow[$i], $config'omitimg, 'OFF' );
					}
					elsif( $style[$i] eq "MEMO1" ){
						$past[$i] = &kei'listMEMO1( $recfield[$i], $name[$i], 'OFF' );
					}
					elsif( $style[$i] eq "MEMO2" ){
						$past[$i] = &kei'listMEMO2( $recfield[$i], $strshow[$i], $config'omitimg, 'OFF' );
					}
					elsif( $style[$i] eq "TAGTEXT" ){	# タグ許可
						$past[$i] = &kei'listTEXT( $recfield[$i], $strshow[$i], $config'omitimg, 'ON' );
					}
					elsif( $style[$i] eq "TAGMEMO1" ){	# タグ許可
						$past[$i] = &kei'listMEMO1( $recfield[$i], $name[$i], 'ON' );
					}
					elsif( $style[$i] eq "TAGMEMO2" ){	# タグ許可
						$past[$i] = &kei'listMEMO2( $recfield[$i], $strshow[$i], $config'omitimg, 'ON' );
					}
					elsif( $style[$i] eq "IMG" ){
						$past[$i] = &kei'listIMG( $recfield[$i], $config'img_view, $config'img_icon, $config'bin_icon, $imgpath, $BinUrl, "" );
					}
					elsif( $style[$i] eq "URL" ){
						$past[$i] = &kei'listURL( $recfield[$i], $config'url_view, $config'url_icon );
					}
					elsif( $style[$i] eq "MAIL" ){
						$past[$i] = &kei'listMAIL( $recfield[$i], $config'mail_view, $config'mail_icon );
					}
					elsif( substr( $style[$i], 0, 3 ) eq "YMD" ){
						$past[$i] = &kei'listYMD( $recfield[$i] );
					}
					elsif( substr( $style[$i], 0, 3 ) eq "HNS" ){
						$past[$i] = &kei'listYMD( $recfield[$i] );
					}
					elsif( $style[$i] eq "LIST" || $style[$i] eq "OPT" ){
						$past[$i] = &kei'listLIST( $recfield[$i], $optlist[$i] );
					}
					elsif( $style[$i] eq "CHK" ){
						$past[$i] = &kei'listCHK( $recfield[$i], $optlist[$i] );
					}
					else{
						# nop
						$past[$i] = "<font color='#ff0000'>Error</a>";
					}
					$tmplist =~ s/\[\$(\w*)\.\]/$past[$ic{lc($1)}]/i;					# [$項目名.]
				}
				else{
					last;
				}
			}

			# [#項目名.]の処理															# Ver 0.07
			while( 1 ){
				if( $tmplist =~ /\[\#(\w*)\.\]/i ){			# #の場合は実値のみ
					$i = $ic{lc($1)};

					if( $style[$i] eq "IMG" ){
						$past[$i] = $imgpath . $recfield[$i];
						if( $recfield[$i] ne "" && -f $past[$i] ){
							# NOP
						}
						else{
							$past[$i] = $kei'zsp;
						}
					}
					else{
						$past[$i] = &kei'listTEXT( $recfield[$i], -1, "", 'ON' );
					}

					$tmplist =~ s/\[\#(\w*)\.\]/$past[$ic{lc($1)}]/i;					# [$項目名.]
				}
				else{
					last;
				}
			}

			# [autonum.]の処理															# Ver 0.12
			$looptmp = $loop + 1;
			$tmplist =~ s/\[autonum\.\]/$looptmp/gi;

			# SSI-EXEC を処理しつつ出力													# Ver 0.08
			&exec_ssi( $tmplist );

# Add SKIN
			if( $htmllist =~ /<messagenext>/i ){
				$loop++;				# 次レコードに強制移動
				&jcode'convert(\$rec[$loop], "sjis");
				@recfield = split( /<>/, $rec[$loop] );
			}

		}

	}
}
#----------------------------------------------------------------------------#
sub exec_ssi
{
	local( $tmplist ) = @_;

	if( $tmplist =~ /(.*?)<!--#(\w*?)\s(.*?)-->(.*\n)/ ){
		$ssicmd = lc($2);		# execなど
		$ssipara = $3;			# コマンド
		$tmplistZAN = $4;

		# SSIの前を出力
		print $1;

		# SSI を実行して出力
		if( $ssicmd eq "exec" ){
			$|=1;
			if( $ssipara =~ /cmd=\"(.*)\"/i ) {
				$ssipara = $1;
				$ssipara =~ s/\?/ /g;			# ? を半角空白に変換
				system( "$ssipara" );			# システム実行
			}
			else {
				print "SSI Non Support Command";
			}
			$|=0;
		}
		else{
			print "SSI Non Support Command";
		}

		# SSIの後を出力
		print $tmplistZAN;
	}
	else{
		print $tmplist;
	}
}
#----------------------------------------------------------------------------#
