#!/usr/bin/perl
# -*- tab-width: 4 -*-
#$ontcgi_path = '/nasu/ns_list/nasu011/cgi/';

$index_max = 200;

require "${ontcgi_path}jcode.pl";
use Fcntl;
use AnyDBM_File;

sub warningMessage;	# 削除してよいかを確認する
sub thanksMessage;	# 詳細への感謝メッセージを表示する
sub sysOpCommand;	# 管理者専用コマンドを実行する
sub makeMenu;		# メニューを作成する
sub printTitles;	# 付記のタイトルを表示する
sub remakeIndex;	# 指定された案内を再構築する

sub parseFormData;	# フォームデータを解析する
sub errorMessage;	# エラーメッセージを表示する
sub retryFlock;		# flockを繰り返す
sub retryRename;	# renameを繰り返す
sub base64;			# base64形式に変換する

@weekMoji = ('日', '月', '火', '水', '木', '金', '土');

$currentTime = time;

require "${ontcgi_path}ontenv.pl";

$menu_file = (($miniMenu_flag & 8) == 8) ? 'index.shtml' : 'index.html';

&parseFormData();
$job		= $in{'job'};		# フォームで押したボタン
$note_no	= $in{'no'};		# 削除する案内番号
$post_no	= $in{'re'};		# 削除する詳細番号(0なら案内自体を削除)
$move_no	= $in{'move'};		# 移動先の案内番号
$deletePass = $in{'passwd'};	# 削除用パスワード
$sysOpPass	= $in{'syspass'};	# 管理者専用パスワード

open(DMYFILE, "${ontcgi_path}data/ont_dmy")
  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
flock(DMYFILE, 2);
tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDONLY, 0644
  or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

($userName, $email, $writeTime, $reply_no, $del_flag, $profile,
  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
  = split(/"/, $DBMFILE{"${note_no}:${post_no}"}, 11);

($noteOpWriteTime, $noteOpPassword_crypt)
  = (split(/"/, $DBMFILE{"${note_no}:0"}, 11))[2, 8];

$sysOpPass_crypt = $DBMFILE{'syspass'};
@notes_que = split(/&/, $DBMFILE{'queue'});

@pos = split(/&/, $DBMFILE{"${note_no}:IDX"});
for ($idx_no = 1; $DBMFILE{"${note_no}:IDX${idx_no}"}; $idx_no++) {
	@pos = (@pos, split(/&/, $DBMFILE{"${note_no}:IDX${idx_no}"}));
}
$pos_num = @pos;

untie %DBMFILE;
flock(DMYFILE, 8);
close(DMYFILE);

if (grep($_ == $note_no, @notes_que) == 0) {
	&errorMessage('** 倉庫にある案内ではこの機能は使えません **');
	exit(1);
}

if ($job ne '削除する') {
	&warningMessage();
	exit(0);
}

if ($sysOpPass ne '') {
	$crypt_tmp = crypt($sysOpPass, $deletePass);
	$crypt_tmp =~ s/\$.*\$//;
	if ($sysOpPass_crypt ne $crypt_tmp) {
		&errorMessage('** 管理者用パスワードが違っています **');
		exit(1);
	}

	if ($move_no =~ /^(?:up|menu|chek|make|ip|lock|unlk)$/) {
		&sysOpCommand($move_no);
		exit(0);
	}
	elsif ($move_no ne undef && grep($_ == $move_no, @notes_que) == 0){
		&errorMessage('** 移動先の案内がメニューにありません **');
		exit(1);
	}
}
else {
	if ($move_no ne undef) {
		&errorMessage('** この機能は管理者にしか使えません **');
		exit(1);
	}

	$writeTime =~ m!^\d+/\d+/(\d+)\(.+\)(\d+):(\d+)$!o;
	$salt = $3 + $2 * 60 + $1 * 60 * 24;
	if (crypt($deletePass, $salt) ne $password_crypt) {

		$noteOpWriteTime =~ m!^\d+/\d+/(\d+)\(.+\)(\d+):(\d+)$!o;
		$salt = $3 + $2 * 60 + $1 * 60 * 24;
		if ($userDelete_flag == 0
		  || crypt($deletePass, $salt) ne $noteOpPassword_crypt) {

			&errorMessage('** 削除用パスワードが違っています **');
			exit(1);
		}
	}

	if ($post_no == 0 && grep($_ != 0, @pos) > 1 && $userDelete_flag < 2) {
		&errorMessage('** 詳細のある案内は削除できません **');
		exit(1);
	}
}

&thanksMessage(($post_no == 0) ? $menu_file : "${note_no}.html",
 ($move_no eq undef) ? '削除' : '移動');

# 指定された案内や詳細を削除

open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
&retryFlock(\*DMYFILE, 2);
tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDWR | O_CREAT, 0644
  or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

@notes_que = split(/&/, $DBMFILE{'queue'});

if ($iModePosts_max > 0) {
	@iModePosts_que = split(/&/, $DBMFILE{'imodeque'});

	if ($post_no == 0) {
		@iModePosts_del = grep($_ =~ /^$note_no-/ && !($move_no ne undef
		  && $_ =~ /^$note_no-$post_no\./), @iModePosts_que);
		@iModePosts_que = grep($_ !~ /^$note_no-/ ||  ($move_no ne undef
		  && $_ =~ /^$note_no-$post_no\./), @iModePosts_que);
	}
	elsif ($move_no eq undef) {
		$iModePosts_del[0] = "${note_no}-${post_no}.html";
		@iModePosts_que
		  = grep($_ ne "${note_no}-${post_no}.html", @iModePosts_que);
	}
	$DBMFILE{'imodeque'} = join('&', @iModePosts_que);

	foreach $filename (@iModePosts_del) {
		unlink("${onthtml_path}/${filename}");
	}
}

if ($post_no == 0) {
	@notes_que = grep($_ != $note_no, @notes_que);
	$DBMFILE{'queue'} = join('&', @notes_que);

	for ($i = 0; $i <= $post_num; $i++) {
		delete $DBMFILE{"${note_no}:${i}"};
	}

	delete $DBMFILE{"${note_no}:IDX"};
	for ($idx_no = 1; $DBMFILE{"${note_no}:IDX${idx_no}"}; $idx_no++) {
		delete $DBMFILE{"${note_no}:IDX${idx_no}"};
	}

	untie %DBMFILE;
	&retryFlock(\*DMYFILE, 8);
	close(DMYFILE);

	open(NOTFILE, "${onthtml_path}/${note_no}.html")
	  or die "NOTFILE=${onthtml_path}/${note_no}.html : $!";
	flock(NOTFILE, 2);
	
	while (<NOTFILE>) {
		if (/^<BR>/) {
			$contents = $_;
			last;
		}
	}

	flock(NOTFILE, 8);
	close(NOTFILE);

	unlink("${onthtml_path}/${note_no}.html");
}
else {
	$DBMFILE{"${note_no}:${post_no}"}
	  = join('"', $userName, $email, $writeTime, $reply_no, 1, $profile,
	  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

	$pos[$pos_num - $post_no] = 0;

	$DBMFILE{"${note_no}:IDX"}
	  = join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	for ($idx_no = 1; @pos; $idx_no++) {
		$DBMFILE{"${note_no}:IDX${idx_no}"} =
		  join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	}

	untie %DBMFILE;
	&retryFlock(\*DMYFILE, 8);
	close(DMYFILE);

	open(NOTFILE, "${onthtml_path}/${note_no}.html")
	  or die "NOTFILE=${onthtml_path}/${note_no}.html : $!";
	flock(NOTFILE, 2);
	open(TMPFILE, ">${onthtml_path}/${note_no}.tmp")
	  or die "TMPFILE=${onthtml_path}/${note_no}.tmp : $!";
	&retryFlock(\*TMPFILE, 2);

	while (<NOTFILE>) {
		if (/^<A name="${post_no}"/o) {
			last;
		}
		print TMPFILE;
	}
	<NOTFILE>;

	$_ = <NOTFILE>;
	if (/<A href="#([^"]*"\s*)>▲<\/A>/o) {
		$before_no = $1;
	} 

	while (<NOTFILE>) {
		if (/^<BR>/o) {
			$contents = $_;

			$_ = <NOTFILE>;
			($profileHOST) = $_ =~ /<P[^>]*>([^<]*)<\/P>/o;
		}
		elsif (/^<HR width="95%"/o) {
			last;
		}
	}

	$_ = <NOTFILE>;
	print TMPFILE;
	$_ = <NOTFILE>;
	print TMPFILE;

	$_ = <NOTFILE>;
	$_ =~ s!<A href="#$post_no"\s*>▲</A>!<A href="#$before_no>▲</A>!o;
	print TMPFILE;

	while (<NOTFILE>) {
		print TMPFILE;
	}

	&retryFlock(\*TMPFILE, 8);
	close(TMPFILE);
	flock(NOTFILE, 8);
	close(NOTFILE);

	&retryRename("${onthtml_path}/${note_no}.tmp",
				 "${onthtml_path}/${note_no}.html");
}

# iモード用メニューから削除

if ($iModePosts_max > 0) {
	open(IMNFILE, "${onthtml_path}/imode.html")
	  or die "IMNFILE=${onthtml_path}/imode.html : $!";
	flock(IMNFILE, 2);
	open(TMPFILE, ">${onthtml_path}/imode.tmp")
	  or die "TMPFILE=${onthtml_path}/imode.tmp : $!";
	&retryFlock(\*TMPFILE, 2);

	while (<IMNFILE>) {
		if ($move_no ne undef && $_ =~ /^<A href="$note_no-$post_no\./o) {
			print TMPFILE;
		}
		elsif ($post_no == 0 && $_ !~ /^<A href="$note_no-/o) {
				print TMPFILE;
		}
		elsif ($post_no >  0 && $_ !~ /^<A href="$note_no-$post_no\./o) {
			print TMPFILE;
		}
	}

	&retryFlock(\*TMPFILE, 8);
	close(TMPFILE);
	flock(IMNFILE, 8);
	close(IMNFILE);

	&retryRename("${onthtml_path}/imode.tmp",
				 "${onthtml_path}/imode.html");
}

# 削除されたことをメールで通知

if ($sendMail_addr ne undef && $sendmail_path ne undef) {
	$message = <<END;
■ 下記の詳細が削除されました ■\r
\r
詳細番号: ${notes_name}${note_no}-詳細${post_no}\r
タイトル: ${title}\r
詳細者名: ${nameNEmail}\r
詳細日時: ${writeTime}\r
\r
${contents}\r
\r
( ${profile}${displayHOST} )\r
END

	&jcode'convert(*message, 'jis');

	$subject = "${notes_name}${note_no}-詳細${post_no}が削除されました";
	&jcode'convert(*subject, 'jis');
	$subject = '=?iso-2022-jp?B?' . &base64($subject) . '?=';
	open(MAIL, "|${sendmail_path} ${sendMail_addr}");

	print MAIL <<END;
Subject: [Open!NOTES:${note_no}-${post_no}] ${subject}\r
Message-ID: <ont${note_no}-${post_no}.${sendMail_addr}>\r
To: ${sendMail_addr}\r
From: ${sendMail_addr}\r
Reply-to: ${sendMail_addr}\r
MIME-Version: 1.0\r
Content-Transfer-Encoding: 7bit\r
Content-Type: text/plain; charset="ISO-2022-JP"\r
X-Priority: 3\r
X-Mailer: NetComplex Inc. Open!NOTES 2.0\r
\r
${message}
END

	close(MAIL);
}	

# 案内への登録

if ($move_no ne undef) {
	open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
	  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
	&retryFlock(\*DMYFILE, 2);
	tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDWR | O_CREAT,
	  0644 or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

	@post_data = split(/"/, $DBMFILE{"${move_no}:0"}, 11);
	$post_no = ++$post_data[3];
	$DBMFILE{"${move_no}:0"} = join('"', @post_data);

	$caption =~ s{<A[^>]*>…続く</A>$}
	  {<A href="${move_no}.html#${post_no}">…続く</A>}o;

	$DBMFILE{"${move_no}:${post_no}"}
	  = join('"',$userName, $email, $writeTime, 0, 0, $profile,
	  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

	@notes_que = split(/&/, $DBMFILE{'queue'});	#案内の順番の入れ換え

	if ($fixTopNotes_num == 0) {
		@notes_que = grep($_ != $move_no, @notes_que);
		unshift(@notes_que, $move_no);
	}
	elsif (grep($_ == $move_no, @notes_que[0, (($fixTopNotes_num < @notes_que)
	  ? $fixTopNotes_num : @notes_que) - 1]) == 0) {
		@notes_que = grep($_ != $move_no, @notes_que);
		splice(@notes_que, $fixTopNotes_num, 0, $move_no);
	}

	$DBMFILE{'queue'} = join('&', @notes_que);

	untie %DBMFILE;
	&retryFlock(\*DMYFILE, 8);
	close(DMYFILE);

	$nameNEmail = ($email eq undef)
	  ? $userName : "<A href=\"mailto:${email}\">${userName}</A>";

	open(NOTFILE, "${onthtml_path}/${move_no}.html")
	  or die "NOTFILE=${onthtml_path}/${move_no}.html : $!";
	flock(NOTFILE, 2);
	open(TMPFILE, ">${onthtml_path}/${move_no}.tmp")
	  or die "TMPFILE=${onthtml_path}/${move_no}.tmp : $!";
	&retryFlock(\*TMPFILE, 2);

	while (<NOTFILE>) {
		print TMPFILE;
	if (/^<HR width="95%"/o) {
			last;
		}
	}

	$dummySpace = ' ' x (3 - length($post_no));

	print TMPFILE <<END;
<A name="${post_no}"${dummySpace}></A>
<TABLE width="95%" border="0" cellspacing="0" class="post">
<TR><TD bgcolor="${noteBodyColor}" align="left" class="body">詳細${post_no} | ■${title} ${nameNEmail} ${writeTime}</TD><TD bgcolor="${noteBodyColor}" align="right" class="body"><A href="#top">▲</A> <A href="${ontcgi_url}/ontinput.cgi?no=${move_no}&re=${post_no}">付記</A> / <A href="${ontcgi_url}/ontdel.cgi?no=${move_no}&re=${post_no}">削除</A></TD></TR>
<TR><TD bgcolor="${postBodyColor}" colspan="2" align="left" class="foot"><SPAN>
${contents}</SPAN><P align="right">${profileHOST}</P></TD></TR>
</TABLE>
<HR width="95%" size="1">
END

	$pos = tell(TMPFILE);

	$_ = <NOTFILE>;
	print TMPFILE;
	$_ = <NOTFILE>;
	print TMPFILE;

	$_ = <NOTFILE>;
	$_ =~ s!<A href="#top">▲</A>!<A href="#$post_no"$dummySpace>▲</A>!o;
	print TMPFILE;

	while (<NOTFILE>) {
		print TMPFILE;
	}

	&retryFlock(\*TMPFILE, 8);
	close(TMPFILE);
	flock(NOTFILE, 8);
	close(NOTFILE);

	&retryRename("${move_no}.tmp",
				 "${move_no}.html");


	open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
	  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
	&retryFlock(\*DMYFILE, 2);
	tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDWR | O_CREAT,
	  0644 or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

	@pos = split(/&/, $DBMFILE{"${note_no}:IDX"});
	for ($idx_no = 1; $DBMFILE{"${note_no}:IDX${idx_no}"}; $idx_no++) {
		@pos = (@pos, split(/&/, $DBMFILE{"${note_no}:IDX${idx_no}"}));
	}

	$pos = $pos - $pos[0];
	splice(@pos, 1, 0, $pos);	#$posを@posの2番目に挿入

	$DBMFILE{"${note_no}:IDX"}
	  = join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	for ($idx_no = 1; @pos; $idx_no++) {
		$DBMFILE{"${note_no}:IDX${idx_no}"} =
		  join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	}

	untie %DBMFILE;
	&retryFlock(\*DMYFILE, 8);
	close(DMYFILE);
}

&makeMenu();


### sub warningMessage() : 削除してよいかを確認する
#
sub warningMessage {
	$cookieData = $ENV{'HTTP_COOKIE'};
	$cookieData =~ s/^ONT=//o;
	$cookieData =~ s/_sem_/;/go;
	@cookieData = split(/"/, $cookieData);

	for (@cookieData) {
		($key, $value) = /^([^:]*):(.*)$/;
		$cookie{$key} = $value;
	}

	print <<END;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
        "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-type" content="text/html; charset=EUC-JP">
${headTagOption}
<TITLE>${menuPageTitle} / この内容を削除する</TITLE>
</HEAD>

<BODY ${bodyTagOption} class="form">
END

	&printHeader(STDOUT, BACK, "href=\"${onthtml_url}/${note_no}.html\"",
	  'この詳細を削除する');

	print "<BR>\n** この詳細を削除してよろしいですか？ **<BR>\n<BR>\n";

	open(NOTFILE, "${onthtml_path}/${note_no}.html")
	  or die "NOTFILE=${onthtml_path}/${note_no}.html : $!";
	flock(NOTFILE, 2);

	if ($post_no > 0) {
		for ($i = 0; $i < ($pos_num - $post_no); $i++) {
			$pos += $pos[$i];
		}
		seek(NOTFILE, $pos, 0);
	}

	while (<NOTFILE>) {
		if (/^<TABLE width="95%"/o) {
			print;
			last;
		}		
	}

	$_ = <NOTFILE>;
	$_ =~ s!(?:<A[^>]*>▲</A> )?<A[^>]*>付記</A> / <A[^>]*>削除</A>!<BR>!o;
	print;

	while (<NOTFILE>) {
		print;
		if (/^<\/TABLE>/o) {
			last;
		}
	}

	flock(NOTFILE, 8);
	close(NOTFILE);

	print <<END;
<HR width="95%" size="1">
<FORM method="POST" action="${ontcgi_url}/ontdel.cgi">
<INPUT type="hidden" name="no" value="${note_no}">
<INPUT type="hidden" name="re" value="${post_no}">

<TABLE border="0" cellspacing="2" class="input">
<TR>
<TD bgcolor="${noteHeadColor}" align="left" class="head">削除パスワード</TD>
<TD bgcolor="${noteBodyColor}" align="left" class="body"><INPUT type="password" name="passwd" value="${cookie{'PASSWD'}}" size="8" maxlength="8">(詳細時に設定した削除パスワードを入力してください)</TD>
</TR>
<TR>
<TD bgcolor="${noteHeadColor}" align="left" class="head">管理者パスワード</TD>
<TD bgcolor="${noteBodyColor}" align="left" class="body"><INPUT type="password" name="syspass" size="8" maxlength="8"> 移動先案内番号/コマンド<INPUT type="text" name="move" size="4" maxlength="4"></TD>
</TR>
</TABLE>
<INPUT type="submit" name="job" value="削除する"><INPUT type="reset" value="リセット">
</FORM>
END

	&printFooter(STDOUT, BACK, "href=\"${onthtml_url}/${note_no}.html\"");
}

### sub sysOpCommand() :管理者専用コマンドを実行する
#
# (IN)
#	$command	:
		
sub sysOpCommand {
	my($command) = @_;

	if ($command eq 'up') {
		&thanksMessage($menu_file, '移動');

		open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
		  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
		&retryFlock(\*DMYFILE, 2);
		tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm",
		  O_RDWR | O_CREAT, 0644
		  or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

		@notes_que = split(/&/, $DBMFILE{'queue'});	#案内の順番の入れ換え
		@notes_que = grep($_ != $note_no, @notes_que);
		unshift(@notes_que, $note_no);
		$DBMFILE{'queue'} = join('&', @notes_que);

		untie %DBMFILE;
		&retryFlock(\*DMYFILE, 8);
		close(DMYFILE);

		&makeMenu();
	}
	elsif ($command eq 'menu') {
		&thanksMessage($menu_file, '更新');
		&makeMenu();
	}		
	elsif ($command eq 'chek') {
		print <<END;
Content-type: text/html

<HTML><HEAD>
<META http-equiv="Content-type" content="text/html; charset=EUC-JP">
<TITLE>インデックスを調査中</TITLE></HEAD>
<BODY bgcolor="#FFFFFF">
** インデックスを調査中 **<BR>
END

		open(NOTFILE, "${onthtml_path}/${note_no}.html")
		  or die "NOTFILE=${onthtml_path}/${note_no}.html : $!";
		flock(NOTFILE, 2);

		$index = 0;
		foreach $pos (@pos) {
			$index += $pos;
			seek(NOTFILE, $index, 0);

			$_ = <NOTFILE>;
			$_ =~ s/</&lt;/go;
			$_ =~ s/>/&gt;/go;
			print '<BR>', $_;
		}

		flock(NOTFILE, 8);
		close(NOTFILE);

		print '<BR><BR>** 終了 **</BODY></HTML>';
	}
	elsif ($command eq 'make') {
		&thanksMessage($menu_file, '再構築');
		&remakeIndex($note_no);
		&makeMenu();
	}
	elsif ($command eq 'ip') {
		&errorMessage("** この詳細のIPは、${remoteADDR}です **");
	}		
	elsif ($command eq 'lock' || $command eq 'unlk') {
		&thanksMessage("${note_no}.html",
		  ($command eq 'lock') ? '制限' : '解除');

		open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
		  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
		&retryFlock(\*DMYFILE, 2);
		tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm",
		  O_RDWR | O_CREAT, 0644
		  or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

		($userName, $email, $writeTime, $post_num, $lock_flag, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
		  = split(/"/, $DBMFILE{"${note_no}:0"}, 11);

		$lock_flag = ($command eq 'lock') ? 1 : 0;

		$DBMFILE{"${note_no}:0"} = join('"',
		  $userName, $email, $writeTime, $post_num, $lock_flag, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

		untie %DBMFILE;
		&retryFlock(\*DMYFILE, 8);
		close(DMYFILE);
	}
}



### sub thanksMessage() :詳細への感謝メッセージを表示する
#
# (IN)
#	$reloadFile		:リロードするファイル名
#	$job			:作業名
#
sub thanksMessage {
	my($reloadFile, $job) = @_;

	print <<END;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
        "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-type" content="text/html; charset=EUC-JP">
<META http-equiv="Refresh" content="${retryFlock_num}; URL=${onthtml_url}/${reloadFile}">
${headTagOption}
<TITLE>${menuPageTitle} / ${job}いたしました</TITLE>
</HEAD>

<BODY ${bodyTagOption} class="thanks">
<DIV align="center">
<TABLE width="100%" border="0" cellspacing="0" class="header"><TR>
<TD bgcolor="#999999" align="center" class="center"><STRONG><FONT color="#FFCC66" class="rhomb">■</FONT><FONT color="#FFFFFF"> ${job}いたしました </FONT><FONT color="#FFCC66" class="rhomb">■</FONT></STRONG></TD>
</TR></TABLE>
<BR>
<TABLE border="0" cellspacing="0" width="95%" class="message">
<TR><TD bgcolor="${noteBodyColor}" align="center"><SPAN>
** ${job}いたしました **<BR>
<BR>
${retryFlock_num}秒ほど待って案内が表示されない時は<A href="${onthtml_url}/${reloadFile}">ここをクリック</A>してください。<BR>
<BR>
詳細後、メニューや案内の内容が更新されないときは再読み込みしてください。<BR>
</SPAN></TD></TR>
</TABLE>
</DIV>
</BODY>
</HTML>
END
}

### sub makeMenu() :メニューの作成
#
sub makeMenu {
	my($updateTime);
	my($userName, $email, $writeTime, $post_num, $del_flag, $profile,
	   $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

	($sec, $min, $hour, $day, $mon, $year, $week) = localtime($currentTime);
	$year += ($year >= 80) ? 1900 : 2000;
	$updateTime = sprintf("%d/%d/%d(%s)%02d:%02d",
	  $year, $mon + 1, $day, $weekMoji[$week], $hour, $min);

	if (($miniMenu_flag & 1) == 1) {
		open(UPDFILE, ">${onthtml_path}/update");
		&retryFlock(\*UPDFILE, 2);
		
		print UPDFILE $updateTime;

		&retryFlock(\*UPDFILE, 8);
		close(UPDFILE);
	}

	open(DMYFILE, "${ontcgi_path}data/ont_dmy")
	  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
	flock(DMYFILE, 2);
	tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDONLY, 0644
	  or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

	open(MNUFILE, ">${onthtml_path}/${menu_file}")
	  or die "MNUFILE=${onthtml_path}/${menu_file} : $!";
	&retryFlock(\*MNUFILE, 2);

	if (($miniMenu_flag & 2) == 2) {
		open(MMNFILE, ">${onthtml_path}/minimenu");
		&retryFlock(\*MMNFILE, 2);
	}

	print MNUFILE <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
        "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-type" content="text/html; charset=EUC-JP">
<META http-equiv="Expires" content="Tue, 20 Aug 1996 00:00:00 GMT">
${headTagOption}
<TITLE>${menuPageTitle}</TITLE>
</HEAD>

<BODY ${bodyTagOption} class="menu">
END

	&printHeader(MNUFILE, HOME, $backFromMenu_url, $menuPageTitle);

	if (($miniMenu_flag & 6) == 6) {
		print MNUFILE <<END;
<BR>
<TABLE bgcolor="${noteHeadColor}" width="95%" class="minimenu">
<TR><TD align="left">
<!--#include file="minimenu"-->
</TD></TR>
</TABLE>
END
	}

	print MNUFILE <<END;
<FORM method="POST" action="${ontcgi_url}/ontinput.cgi">
${updateTime}更新<INPUT type="submit" name="job" value="新しい案内を作る"><INPUT type="submit" name="job" value="案内を一覧/検索">${mailToSysop} / <A href="stock/index.html">倉庫</A>
</FORM>
END

	($sec, $min, $hour, $day, $mon, $year, $week)
	  = localtime($currentTime - $displayPost_days * 60 * 60 * 24);
	$year += ($year >= 80) ? 1900 : 2000;
	$endDisplayTime = sprintf("%04d/%02d/%02d %02d:%02d",
	  $year, $mon + 1, $day, $hour, $min);

	($sec, $min, $hour, $day, $mon, $year, $week)
	  = localtime($currentTime - $markPost_days * 60 * 60 * 24);
	$year += ($year >= 80) ? 1900 : 2000;
	$markDisplayTime = sprintf("%04d/%02d/%02d %02d:%02d",
	  $year, $mon + 1, $day, $hour, $min);

	foreach $i (@notes_que) {
		($userName, $email, $writeTime, $post_num, $del_flag, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
		  = split(/"/, $DBMFILE{"${i}:0"}, 11);

		print MNUFILE <<END;
<A name="${i}"></A>
<FORM method="POST" action="${ontcgi_url}/ontinput.cgi">
<INPUT type="hidden" name="no" value="${i}">
<TABLE border="0" cellspacing="0" width="95%" class="index">
<TR><TD bgcolor="${noteHeadColor}" align="left" class="head">${notes_name}${i} | <A href="${i}.html">■${title}</A> ${userName} ${writeTime}</TD><TD bgcolor="${noteHeadColor}" align="right" class="head">( 詳細 ${post_num} 件 )</TD><TD bgcolor="${noteHeadColor}" width="5%" align="right" class="head"><INPUT type="submit" name="job" value="詳細"></TD></TR>
END

		if (($miniMenu_flag & 2) == 2) {
			print MMNFILE
"<A href=\"${onthtml_url}/${menu_file}#${i}\">|■${title}</A> ";
		}

		$writeTime =~ m!^(\d+)/(\d+)/(\d+)\(.+\)(.+)$!o;
		$writeTime_tmp = sprintf("%04d/%02d/%02d %s", $1, $2, $3, $4);

		if ($caption ne undef && ($writeTime_tmp gt $markDisplayTime
		  || ($captions_flag & 1) == 1)) {
			print MNUFILE <<END;
<TR><TD bgcolor="${noteHeadColor}" align="right" colspan="3">
<TABLE width="100%" cellpadding="2" class="caption">
<TR><TD bgcolor="${noteHeadColor}" width="5%" align="left"></TD><TD bgcolor="${noteBodyColor}" width="1%" align="left"><BR></TD><TD bgcolor="${noteHeadColor}" align="left">
${caption}<BR>
</TD></TR>
</TABLE>
</TD></TR>
END
		}

		if ($post_num > 0) {
			&printTitles($i, $post_num);
		}		

		print MNUFILE "</TABLE>\n</FORM>\n";
	}

	&printFooter(MNUFILE, HOME, $backFromMenu_url);

	if (($miniMenu_flag & 2) == 2) {
		&retryFlock(\*MMNFILE, 8);
		close(MMNFILE);
	}

	&retryFlock(\*MNUFILE, 8);
	close(MNUFILE);

	untie %DBMFILE;
	flock(DMYFILE, 8);
	close(DMYFILE);
}

### sub printTitles() : 詳細のタイトルを表示する
#
# (IN)
#	$note_no	:詳細を表示する案内番号
#	$post_num	:詳細総数
#
sub printTitles {
	my($note_no, $post_num) = @_;

	print MNUFILE <<END;
<TR><TD bgcolor="${noteBodyColor}" colspan="3" align="left" class="body">
END

	for ($j = $post_num; $j > 0; $j--) {
		($userName, $email, $writeTime, $reply_no, $del_flag, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
		  = split(/"/, $DBMFILE{"${note_no}:${j}"}, 11);

		if ($del_flag == 1) {	
			next;
		}

		$writeTime =~ m!^(\d+)/(\d+)/(\d+)\(.+\)(.+)$!o;
		$writeTime_tmp = sprintf("%04d/%02d/%02d %s", $1, $2, $3, $4);

		if ($writeTime_tmp le $endDisplayTime) {
			last;
		}

		if ($writeTime_tmp gt $markDisplayTime) {
			print MNUFILE <<END;
(${j})+<A href="${note_no}.html#${j}">■${title}</A> ${userName} ${writeTime}<BR>
END
			if (($miniMenu_flag & 2) == 2) {
				print MMNFILE "■${title} ";
			}

			if ($caption ne undef) {
				print MNUFILE <<END;
<TABLE width="100%" cellpadding="2" class="caption">
<TR><TD bgcolor="${noteBodyColor}" width="5%" align="left" class="left"><BR></TD><TD bgcolor="${postBodyColor}" width="1%" align="left" class="center"><BR></TD><TD bgcolor="${noteBodyColor}" align="left" class="right">
${caption}<BR>
</TD></TR>
</TABLE>
END
			}
		}
		else {
			print MNUFILE <<END;
(${j}) <A href="${note_no}.html#${j}">■${title}</A> ${userName} ${writeTime}<BR>
END
		}
	}
	print MNUFILE "</TD></TR>\n";
}

### sub remakeIndex() :指定された案内を再構築する
#
# (IN)
#	$note_no
#
sub remakeIndex {
	my($note_no) = @_;
	my($userName, $email, $writeTime, $post_num, $del_flag, $profile,
	   $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

	open(DMYFILE, ">${ontcgi_path}data/ont_dmy")
	  or die "DMYFILE=${ontcgi_path}data/ont_dmy : $!";
	retryFlock(\*DMYFILE, 2);
	tie %DBMFILE, AnyDBM_File, "${ontcgi_path}data/ont_dbm", O_RDWR | O_CREAT,
	  0644 or die "DBMFILE=${ontcgi_path}data/ont_dbm : $!";

	($userName, $email, $writeTime, $post_num, $del_flag, $profile,
	  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
	  = split(/"/, $DBMFILE{"${note_no}:0"}, 11);

	for ($i = 1; $i <= $post_num; $i++) {
		$pos[$i] = 0;

		($userName, $email, $writeTime, $reply_no, $del_flag, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
		  = split(/"/, $DBMFILE{"${note_no}:${i}"}, 11);
		
		$DBMFILE{"${note_no}:${i}"}
		  = join('"', $userName, $email, $writeTime, $reply_no, 1, $profile,
		  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);
	}

	open(NOTFILE, "${onthtml_path}/${note_no}.html")
	  or die "NOTFILE=${onthtml_path}/${note_no}.html : $!";
	flock(NOTFILE, 2);

	$post_no = 0;
	while (<NOTFILE>) {
		if (/^<A name="(.*)"/o) {
			if ($1 eq 'end') {
				last;
			}
			$post_no = ($1 eq 'top') ? 0 : $1;
		}
		elsif (/^<HR width="95%"/o) {
			$pos = tell(NOTFILE);
			if ($post_no == 0) {
				$pos[0] = $pos;
			}
			else {
				$pos[$post_num - $post_no + 1] = $pos - $beforePos;

				($userName, $email, $writeTime, $reply_no, $del_flag, $profile,
				  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption)
				  = split(/"/, $DBMFILE{"${note_no}:${post_no}"},11);
		
				$DBMFILE{"${note_no}:${post_no}"} = join('"',
				  $userName, $email, $writeTime, $reply_no, 0, $profile,
				  $remoteHOST, $remoteADDR, $password_crypt, $title, $caption);

			}
			$beforePos = $pos;
		}
	}
	flock(NOTFILE, 8);
	close(NOTFILE);

	$DBMFILE{"${note_no}:IDX"}
	  = join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	for ($idx_no = 1; @pos; $idx_no++) {
		$DBMFILE{"${note_no}:IDX${idx_no}"} =
		  join('&', splice(@pos, 0, (@pos > $index_max) ? $index_max : @pos));
	}

	untie %DBMFILE;
	retryFlock(\*DMYFILE, 8);
	close(DMYFILE);
}


### sub parseFormData() :フォームデータを解析する
#
# (OUT)
#	%IN		:フォームデータの内容

sub parseFormData {
	my($formData_buf, @formData); 
	my($name, $value);

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

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

		&jcode'convert(*value, 'euc');
		$in{$name} = $value;
	}
}

### sub errorMessage() :エラーメッセージを表示する
#
# (IN)
#	$message	:表示するエラーメッセージ 
#
sub errorMessage {
	my($message) = @_;

	print <<END;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
        "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-type" content="text/html; charset=EUC-JP">
${headTagOption}
<TITLE>${menuPageTitle} / エラーメッセージ</TITLE>
</HEAD>

<BODY ${bodyTagOption} class="error">
END

	&printHeader(STDOUT, MENU, "href=\"${onthtml_url}/${menu_file}\"",
	  'エラーメッセージ');

	print <<END;
<BR>
<TABLE width="95%" border="0" cellspacing="0" cellpadding="15" class="message">
<TR><TD bgcolor="${noteBodyColor}" align="center"><SPAN>
${message}<BR>
</SPAN></TD></TR>
</TABLE>
<BR>
END

	&printFooter(STDOUT, MENU, "href=\"${onthtml_url}/${menu_file}\"");
}

### sub retryFlock() :flockを繰り返す
#
# (IN)
#	$fh		:ファイルハンドル
#	$mode	:1=共有ロック、2=排他ロック、8=アンロック
#
sub retryFlock {
	my($fh, $mode) = @_;

	for ($i = 0; $i < $retryFlock_num; $i++) {
		if (flock($fh, $mode)) {
			return;
		}
		else {
			sleep 2;
		}
	}

	&errorMessage('** 正常に登録できなかった可能性があります **');
	exit(1);
}

### sub retryRename() :renameを繰り返す
#
# (IN)
#	$oldname	:古いファイル名
#	$newname	:新しいファイル名
#
sub retryRename {
	my($oldname, $newname) = @_;

	for ($i = 0; $i < $retryFlock_num; $i++) {
		unlink($newname);
		if (!-e $newname && rename($oldname, $newname)) {
			return;
		}
		else {
			sleep 1;
		}
	}
	&errorMessage('** 正常に登録できなかった可能性があります **');
	exit(1);
}

### sub base64() :base64形式に変換する
#
# (IN)
#	$_		:変換する文字列
# (OUT)
#	$result	:変換結果
#
sub base64 {
    local($_) = @_;
    my($chunk, $result);

   while(s/^((?:.|\n){45})//) {
		$chunk = substr(pack('u', $1), $[+1, 60);
		$chunk =~ tr/`!-`/A-Za-z0-9+\//;
		$result .= $chunk;
    }

    if($_ ne '') {
		$chunk = substr(pack('u', $_),
		  $[+1, int((length($_)+2)/3)*4 - (45-length($_))%3);
		$chunk =~ tr/`!-`/A-Za-z0-9+\//;
		$result .= $chunk . ('=' x ((60 - length($chunk)) % 4));
    }
    $result;
} 

# Open!NOTES 2.0a (C)1998-2002 NetComplex Inc. All rights reserved. 
