#!/usr/pkg/bin/perl
#========================================================#
# DiaryViewer
#	2002.07.03 新規作成							ren
#   2002.08.19 1.00c							ren
#========================================================#
# read_ini			設定取得
# read_form			フォームからのデータ取得
# write_log			ログ記録
# show_pass			パスワード入力画面表示
# print_ban			日記参照を禁止
#========================================================#
use DMutil;

#-----------------------  メイン  -----------------------#
&read_ini();
&read_form();

my($addr,$host,$ref,$agent,$query) = &DMutil::get_env();
if($query eq ''){ &DMutil::error("引数がありません。"); }

($query) = split(/&|\?/,$query);		#アンテナ対策
if($query eq 'form'){	#フォーム対応
	my($dviewercgi) = &DMutil::get_ini('dviewercgi');
	$in{'year'} = (defined $in{'year'}) ? $in{'year'} : '';
	$in{'mon'} = (defined $in{'mon'}) ? $in{'mon'} : '';
	if($in{'mon'} < 10 && $in{'mon'} !~ /^0/){ $in{'mon'} = "0$in{'mon'}"; }
	print "Location: $dviewercgi?$in{'year'}$in{'mon'}\n\n";
	exit;
}

#アクセス制限チェック
my $show = 1;
if($show){ $show = &DMutil::check_ip(*in,$addr,$host); }
if($show){ $show = &DMutil::check_ag(*in,$agent); }
if( &DMutil::check_keitai(*in,$agent)){ $show = 2; }

#管理者は制限しない
{
	if($show == 0){
		#クッキー取得
		my($dm_cid,$passfile) = &DMutil::get_ini('dm_cid','passfile');
		my %cookie = &DMutil::get_cookie($dm_cid);
		unless(defined $cookie{'pw'}){ last; }
		unless(-f $passfile){ last; }
		open(IN,$passfile) || last;
		my $pass = <IN>;
		close(IN);
		if($pass eq crypt($cookie{'pw'},'dm')){
			$show = 1;
		}
	}
}

#ログ記録
if($in{'maxvlog'}){ &write_log($show); }

if($show == 0){
	#制限
	&print_ban();
}

if($in{'member'}){
	my($dv_cid) = &DMutil::get_ini('dv_cid');
	#クッキー削除
	if($query eq 'logout'){
		&DMutil::del_cookie($dv_cid);
		&show_pass('ログアウトしました。');
	}
	#クッキー取得
	my %cookie = &DMutil::get_cookie($dv_cid);
	$cookie{'pw'} = (defined $cookie{'pw'}) ? $cookie{'pw'} : '';
	if(defined $cookie{'pw'} && $cookie{'pw'} eq $in{'member'}){	#cookieあり
		if($query eq 'new'){	#cookie再セット
			&DMutil::set_cookie($dv_cid,"pw:$cookie{'pw'}");
		}
	}else{	#cookieなし
		if(defined $in{'pw'} && $in{'pw'}){	#pw入力あり
			if($in{'pw'} eq $in{'member'}){
				$cookie{'pw'} = $in{'pw'};
				&DMutil::set_cookie($dv_cid,"pw:$cookie{'pw'}");
			}else{
				&show_pass('パスワードが違います。');
			}
		}else{
			&show_pass('パスワードを入力してください。');
		}
	}
}

#日記表示
if($show == 1){
	#最新日記HTMLを利用して出力
	{
		unless($query eq 'new' && $in{'html'}){ last; }
		unless(-f $in{'html'}){ &DMutil::make_html(*in); }	#なかったら生成
		my $ctime = (stat $in{'html'})[9];
		my $ttime = (stat $in{'new_temp'})[9];
		my($inifile) = &DMutil::get_ini('inifile');
		my $itime = (stat $inifile)[9];
		if($ttime > $ctime){	#テンプレートが新しければ生成し直し
			&DMutil::make_html(*in);
			$ctime = $ttime;
		}elsif($itime > $ctime){	#設定が新しければ生成し直し	<1.00c>
			&DMutil::make_html(*in);
			$ctime = $itime;
		}
		open(IN,$in{'html'}) || &DMutil::error("最新日記HTMLファイルが開けません。");
		flock(IN,1);
		my $html = '';
		while(<IN>){ $html .= $_; }
		close(IN);
		&DMutil::print_gzip(*in,$html,$ctime);
	}
	#データ取得
	@diary = &DMutil::get_diary(*in,$query);
	@comment = &DMutil::get_comment(*in,*diary);
	#指定テンプレートでHTML作成
	my $template = $in{'past_temp'};
	if($query eq 'new'){ $template = $in{'new_temp'}; }
	elsif($query eq 'cmt'){ $template = $in{'cmt_temp'}; }
	my $html = &DMutil::make_diary(*in,*diary,*comment,$template);
	&DMutil::print_gzip(*in,$html);
}elsif($show == 2){
	#データ取得
	@diary = &DMutil::get_diary(*in,$query);
	@comment = &DMutil::get_comment(*in,*diary);
	if($in{'spnum'} > 0 && $#diary+1 > $in{'spnum'}){ splice(@diary,$in{'spnum'}); }
	my $html = &DMutil::make_diary(*in,*diary,*comment,$in{'simple'});
	&DMutil::print_gzip(*in,$html);
}

exit 0;

#-----------------------   サブ   -----------------------#
# 設定取得
#-------------------------------------------------
#  in  : -
# out  : -
#-------------------------------------------------
sub read_ini{

	my($inifile) = &DMutil::get_ini('inifile');

	if(-f $inifile){
		#設定を連想配列%inに入れ込む
		open(IN,$inifile) || &DMutil::error("設定ファイル($inifile)が開けません。");
		flock(IN,1);
		my @pairs = <IN>;
		close(IN);
		foreach(@pairs){
			my($key,$value) = split(/<>/);
			$value =~ s/\r|\n//g;
			$in{$key} = $value;
		}
	}else{
		&DMutil::error("設定ファイル($inifile)がありません。一度DiaryMakerを起動してください。");
	}
	return;
}

# フォームからのデータ取得
#-------------------------------------------------
#  in  : -
# out  : -
#-------------------------------------------------
sub read_form{

	unless(defined $ENV{'REQUEST_METHOD'} && $ENV{'REQUEST_METHOD'} eq 'POST'){ return; }
	my $buffer;
	read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
	my @pairs = split(/&/,$buffer);

	foreach(@pairs){
		my($key,$value) = split(/=/);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;

		$in{$key} = &DMutil::escape($value);
	}
	return;
}

# ログ記録
#-------------------------------------------------
#  in  : $show		[日記表示の許可/不許可]
# out  : -
#-------------------------------------------------
sub write_log{

	my($show) = @_;
	if($show == 1){ $show = 'o'; }
	elsif($show == 2){ $show = 's'; }
	else{ $show = 'x'; }

	#現在時刻
	my($sec,$min,$hour,$day,$mon,$year) = localtime(&DMutil::get_time($in{'timeshift'}));
	$mon++;
	$year += 1900;
	if($mon  < 10){ $mon  = "0$mon";  }
	if($day  < 10){ $day  = "0$day";  }
	if($hour < 10){ $hour = "0$hour"; }
	if($min  < 10){ $min  = "0$min";  }
	if($sec  < 10){ $sec  = "0$sec";  }
	my $date = "$mon/$day $hour:$min:$sec";

	#ディレクトリ作成
	unless(-d $in{'vlog'}){
		mkdir($in{'vlog'},0777) || &DMutil::error("アクセスログ保存ディレクトリ($in{'vlog'})を作成できません。");
		chmod(0777,$in{'vlog'}) || &DMutil::error("アクセスログ保存ディレクトリ($in{'vlog'})のパーミッションを変更できません。");
	}

	#ファイルサイズがMAXを超えてたら記録しない
	if(-f "$in{'vlog'}/$year$mon$day.log"){
		if($in{'maxsize'}){
			my $size = (-s "$in{'vlog'}/$year$mon$day.log");
			$size /= 1024;
			if($size > $in{'maxsize'}){ return; }
		}
	}

	#ログ書き込み
	open(OUT,">>$in{'vlog'}/$year$mon$day.log");
	flock(OUT,2);
	print OUT "$date<>$query<>$addr<>$host<>$ref<>$agent<>$show\n";
	close(OUT);

	#余剰分を消す
	opendir(DIR,$in{'vlog'}) || return;
	my @files = readdir(DIR);
	closedir(DIR);
	if($#files >= $in{'maxvlog'}){
		@files = reverse(sort @files);
		my $num = 0;
		foreach my $file (@files){
			if($file !~ /^[0-9]{8}\.log$/){ next; }
			if($num < $in{'maxvlog'}){ $num++; }
			else{ unlink("$in{'vlog'}/$file") || &DMutil::error("アクセスログファイル($in{'vlog'}/$file)を消去できません。"); }
		}
	}
	return;
}

# パスワード入力画面表示
#-------------------------------------------------
#  in  : $memo		[表示内容]
# out  : -
#-------------------------------------------------
sub show_pass{

	my($memo)= @_;
	my($dviewercgi,$cgititle,$version,$url) = &DMutil::get_ini('dviewercgi','cgititle','version','url');
	(my $style = $in{'style'}) =~ s/<\\n>/\n/g;
	$query = (defined $query) ? $query :'';

	my $html = qq(
		<HTML>
		<HEAD>
		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Shift_JIS">
		<TITLE>パスワード入力画面</TITLE>
		$style
		</HEAD>
		<BODY>
		<BLOCKQUOTE>
		<FORM METHOD="post" ACTION="$dviewercgi?new">
		$memo<BR>
		<BR>
		<INPUT TYPE="password" NAME="pw" SIZE="10" VALUE="">
		<INPUT TYPE="submit" VALUE="送信">
		</FORM>
		<DIV ALIGN="right">
		<A HREF="$url">$cgititle $version</A>
		</DIV>
		</BLOCKQUOTE>
		</BODY>
		</HTML>
	);

	$html =~ s/\t//g;
	print "Content-type: text/html\n\n";
	print $html;

	exit 0;
}

# 日記参照を禁止
#-------------------------------------------------
#  in  : -
# out  : -
#-------------------------------------------------
sub print_ban{

	(my $html= $in{'ban'}) =~ s/<\\n>/\n/g;

	#最終更新時間読み込み
	my $latestdate = &DMutil::get_time($in{'timeshift'});
	my($updatedat) = &DMutil::get_ini('updatedat');
	if(-f $updatedat){ $latestdate = (stat $updatedat)[9]; }
	$lshow = &fix_date($latestdate,$in{'late_form'},$in{'week_form'},$in{'mon_form'});

	#最新日記タイトル読み込み
	my($new) = &DMutil::get_diary(*in,'new');
	my(undef,$title) = split(/<>/,$new);

	$html =~ s/<\\n>/\n/g;
	$html =~ s/_IP_/$addr/g;
	$html =~ s/_HOST_/$host/g;
	$html =~ s/_AGENT_/$agent/g;
	$html =~ s/_LAST_MOD_/$lshow/g;
	$html =~ s/_NEW_TITLE_/$title/g;

	&DMutil::print_gzip(*in,$html,$latestdate);

	exit;
}
