#!/usr/local/bin/perl

#┌─────────────────────────────────
#│ Aska BBS v2.4 (2002/08/01)
#│ Copyright(C) Kent Web 2002
#│ webmaster@kent-web.com
#│ http://www.kent-web.com/
#└─────────────────────────────────
$ver = 'ASKA BBS v2.4';
#┌─────────────────────────────────
#│ [注意事項]
#│ 1. このスクリプトはフリーソフトです。このスクリプトを使用した
#│    いかなる損害に対して作者は一切の責任を負いません。
#│ 2. 設置に関する質問はサポート掲示板にお願いいたします。
#│    直接メールによる質問は一切お受けいたしておりません。
#└─────────────────────────────────
#
# 【ファイル構成例】
#
#  public_html (ホームディレクトリ)
#      |
#      +-- aska / aska.cgi [755]
#            |    aska.log [666]
#            |    jcode.pl [644]
#            |
#            +-- lock [777] /
#

#============#
#  基本設定  #
#============#

# 文字コード変換ライブラリ取り込み
require './jcode.pl';

# タイトル名
$title = "らくがきコーナー";

# タイトル文字の色
$t_color = "#008080";

# タイトル文字のタイプ
$t_face = "ＭＳ Ｐゴシック";

# タイトル文字サイズ（スタイルシートで有効）
$t_size = '18pt';

# 本文文字サイズ（スタイルシートで有効）
$b_size = '10pt';

# 記事題名の色
$sub_color = "#DD0000";

# スクリプト名
$script = './aska.cgi';

# ログファイル名
$logfile = './aska.log';

# 管理用パスワード
$pass = '0123';

# 最大記事数（これを超える記事は古い順に削除されます）
$max = 100;

# 戻り先
$home = "../index.html";

# タイトル画像を使う場合 (http://から画像を指定)
$ImgT = "./cgi_title.gif";
$ImgW = 342;	# 横幅サイズ
$ImgH = 116;	# 縦幅サイズ

# bodyタグ
$body = '<body bgcolor="#F7F7F0" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">';

# URLの自動リンク (0=no 1=yes)
$autolink = 1;

# 引用部色変更
#  1) ここに色指定を行うと「引用部」を色変更します
#  2) この機能を使用しない場合は何も記述しないで下さい ($refcolor="";)
$refcolor = "#804000";

# １ページあたりの記事表示件数
$p_log = 10;

# ファイルロック形式
#  → 0=no 1=symlink関数 2=mkdir関数
$lockkey = 2;

# ロックファイル名
$lockfile = './lock/aska.lock';

# メール通知機能
#   0 : 通知しない
#   1 : 通知する → 自分の投稿記事も通知する
#   2 : 通知する → 自分の投稿記事は通知しない
$mailing = 0;

# メールソフトのパス（メール通知する場合）
#  → sendmailの例： /usr/lib/sendmail
#  → blatjの例： c:\www\mail\blatj.exe
$mailprog = '/usr/lib/sendmail';

# メール通知先アドレス（メール通知する場合）
$mailto = 'info@ibsanuki.com';

# タグ広告挿入オプション (FreeWebなど）
#  → <!-- 上部 --> <!-- 下部 --> の代わりに「広告タグ」を挿入する。
#  → 広告タグ以外に、MIDIタグ や LimeCounter等のタグにも使用可能です。
$banner1 = '<!-- 上部 -->';  # 表示部上部に挿入
$banner2 = '<!-- 下部 -->';  # 表示部下部に挿入

# アクセス制限（半角スペースで区切る）
#  → 拒否するホスト名又はIPアドレスを記述（アスタリスク可）
#  → 記述例 $deny = '*.anonymizer.com *.denyhost.xx.jp 211.154.120.*';
$deny = '';

# 記事の更新は method=POST 限定 (0=no 1=yes)
# （セキュリティ対策）
$postonly = 1;

# 同一IPアドレスからの連続投稿時間（秒数）
#  → 連続投稿などの荒らし対策
#  → 値を 0 にするとこの機能は無効になります
$wait = 90;

# 投稿後の処理
#  → 掲示板自身のURLを記述しておくと、投稿後リロードします
#  → ブラウザを再読み込みしても二重投稿されない措置。
#  → Locationヘッダの使用可能なサーバのみ
$location = 'http://www.ibsanuki.com/tsuhan/aska/aska.cgi';

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

&decode;
&axs_check;
if ($mode eq 'regist') { &regist; }
elsif ($mode eq 'find') { &find; }
elsif ($mode eq 'howto') { &howto; }
elsif ($mode eq 'admin') { &admin; }
elsif ($mode eq 'usrdel') { &usrdel; }
elsif ($mode eq 'check') { &check; }
&html;

#----------------#
#  アクセス制限  #
#----------------#
sub axs_check {
	# ホスト名を取得
	&get_host;

	local($flag)=0;
	foreach (split(/\s+/, $deny)) {
		s/\*/\.\*/g;
		if ($host =~ /$_/i) { $flag=1; last; }
	}
	if ($flag) { &error("アクセスを許可されていません"); }
}

#----------------#
#  記事表示処理  #
#----------------#
sub html {
	local($flag,$no,$date,$name,$mail,$sub,$r_sub,$r_com,$next,$back);

	# クッキー情報を取得
	local($cname,$cmail,$curl,$cpwd) = &get_cookie;

	# レス処理
	if ($mode eq 'resmsg') {
		$flag=0;
		open(IN,"$logfile") || &error("Open Error : $logfile");
		while (<IN>) {
			($no,$date,$name,$mail,$sub,$com) = split(/<>/);
			if ($in{'no'} == $no) { $flag=1; last; }
		}
		close(IN);
		if (!$flag) { &error("該当記事が見つかりません"); }

		$sub   =~ s/^Re://g;
		$r_sub = "Re:[$no] $sub";
		$r_com = "&gt; $com";
		$r_com =~ s/<br>/\r&gt; /ig;
	}

	&header;
	print "<center>\n";
	print "$banner1<P>\n" if ($banner1 ne "<!-- 上部 -->");

	# タイトル
	if ($ImgT) {
		print "<img src=\"$ImgT\" width=$ImgW height=$ImgH alt=\"$title\">\n";
	} else {
		print "<font color=\"$t_color\" face=\"$t_face\" size=5><b style=\"font-size:$t_size\">$title</b></font>\n";
	}

	print <<"EOM";
<hr width="90%">
[<a href="$home" target="_top">トップに戻る</a>]
[<a href="$script?mode=howto">留意事項</a>]
[<a href="$script?mode=find">ワード検索</a>]
[<a href="$script?mode=admin">管理用</a>]
<hr width="90%">
</center>
<blockquote>
<form action="$script" method="POST">
<input type=hidden name=mode value="regist">
<table cellpadding=1 cellspacing=1>
<tr>
  <td><b>おなまえ</b></td>
  <td><input type=text name=name size=28 value="$cname"></td>
</tr>
<tr>
  <td><b>Ｅメール</b></td>
  <td><input type=text name=email size=28 value="$cmail"></td>
</tr>
<tr>
  <td><b>題　　名</b></td>
  <td>
    <input type=text name=sub size=36 value="$r_sub">
    <input type=submit value="送信する"><input type=reset value="リセット">
  </td>
</tr>
<tr>
  <td colspan=2>
    <b>メッセージ</b><br>
    <textarea name=comment cols=56 rows=7 wrap=soft>$r_com</textarea>
  </td>
</tr>
<tr>
  <td><b>ＵＲＬ</b></td>
  <td><input type=text name=url size=50 value="http://$curl"></td>
</tr>
<tr>
  <td><b>削除キー</b></td>
  <td>
    <input type=password name=pwd size=8 maxlength=8 value="$cpwd">
    (記事削除用。英数字で8文字以内)
  </td>
</tr>
<tr>
  <td></td>
  <td>
    <input type=checkbox name=cook value="on" checked>
    クッキー情報を保存
  </td>
</tr>
</table>
<table>
<tr><td><font color="ff0000">商品についてのご意見やご希望、名産品についてのフリートークや</td></tr>
<tr><td><font color="ff0000">私だけが知っている「通」な情報など、どんどん書き込んで下さい。</td></tr>
</table>
</form>
</blockquote>
<DL>
EOM
	$i=0;
	open(IN,"$logfile") || &error("Open Error : $logfile");
	while (<IN>) {
		$i++;
		if ($i < $page + 1) { next; }
		if ($i > $page + $p_log) { next; }

		($no,$date,$name,$mail,$sub,$com,$url) = split(/<>/);
		if ($mail) { $name = "<a href=\"mailto:$mail\">$name</a>"; }
		if ($autolink) { &auto_link($com); }
		if ($refcolor) { $com =~ s/([\>]|^)(&gt;[^<]*)/$1<font color=\"$refcolor\">$2<\/font>/g; }
		print "<DT><hr>[<b>$no</b>] <font color=\"$sub_color\"><b>$sub</b></font> ",
		"投稿者：<b>$name</b> 投稿日：$date ",
		"[<a href=\"$script?mode=resmsg&no=$no\">返信</a>]<br><br><DD>$com";
		print "<P><a href=\"http://$url\" target=\"_blank\">http://$url</a>" if ($url);
		print "<br><br>\n";
	}
	close(IN);
	print "<DT><hr></DL>\n";

	$next = $page + $p_log;
	$back = $page - $p_log;
	print "<table align=left><tr>\n";
	if ($back >= 0) {
		print "<td><form action=\"$script\" method=\"POST\">\n",
		"<input type=hidden name=page value=\"$back\">\n",
		"<input type=submit value=\"前の$p_log件\"></td></form>\n";
	}
	if ($next < $i) {
		print "<td><form action=\"$script\" method=\"POST\">\n",
		"<input type=hidden name=page value=\"$next\">\n",
		"<input type=submit value=\"次の$p_log件\"></td></form>\n";
	}
	print <<"EOM";
</tr></table>
<table align=right><tr><td nowrap align=center>
<form action="$script" method="POST">
<input type=hidden name=mode value="usrdel">
記事No<input type=text name=no size=3>
削除キー<input type=password name=pwd size=4 maxlength=8>
<input type=submit value="記事削除"></td></form>
</tr></table><br clear=all>
<!-- 著作権表\示（削除不可）-->
<div align='center'>$banner2<P><!-- $ver -->
<span style='font-size:9pt;font-family:verdana'>
- <a href='http://www.kent-web.com/' target='_top'>ASKA BBS</a> -
</span></div>
</body>
</html>
EOM
	exit;
}

#----------------#
#  書きこみ処理  #
#----------------#
sub regist {
	local($no, $pwd, $time, @file, @f, @w);

	# POST限定
	if ($postonly && !$post_flag) { &error("不正なアクセスです"); }

	# フォーム内容をチェック
	if ($in{'name'} eq "") { &error("名前が入力されていません"); }
	if ($in{'comment'} eq "") { &error("コメントが入力されていません"); }

	# ロック処理
	&lock if ($lockkey);

	open(IN,"$logfile") || &error("Open Error : $logfile");
	@file = <IN>;
	close(IN);

	# 重複投稿チェック
	$time = time;
	local(@f) = split(/<>/, $file[0]);
	if ($in{'name'} eq $f[2] && $in{'comment'} eq $f[5]) {
		&error("二重投稿は禁止です");
	}
	# 同一ホストの連続投稿チェック
	if ($host eq $f[7] && $wait > $time - $f[9]) {
		&error("連続投稿はもうしばらく時間をおいて下さい");
	}

	# 記事Noを採番
	$no = $f[0] + 1;

	# 削除キーを暗号化
	if ($in{'pwd'} ne "") { $pwd = &encrypt($in{'pwd'}); }

	# 時間を取得
	local($min,$hour,$mday,$mon,$year,$wday) = (localtime($time))[1..6];
	@w = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
	$date = sprintf("%04d/%02d/%02d(%s) %02d:%02d",
			$year+1900,$mon+1,$mday,$w[$wday],$hour,$min);

	# 更新
	while ($max <= @file) { pop(@file); }
	unshift(@file,"$no<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'comment'}<>$in{'url'}<>$host<>$pwd<>$time<>\n");
	open(OUT,">$logfile") || &error("Write Error : $logfile");
	print OUT @file;
	close(OUT);

	# ロック解除
	&unlock if ($lockkey);

	# クッキーを記憶
	if ($in{'cook'} eq 'on') { &set_cookie; }

	# メール通知処理
	if ($mailing == 1) { &mail_to; }
	elsif ($mailing == 2 && $in{'email'} ne $mailto) { &mail_to; }

	# リロード
	if ($location) {
		if ($ENV{'PERLXS'} eq "PerlIS") {
			print "HTTP/1.0 302 Temporary Redirection\r\n";
			print "Content-type: text/html\n";
		}
		print "Location: $location\n\n";
	} else {
		&header;
		print "<div align=center><hr width=400>\n";
		print "<h3>投稿は正常に処理されました</h3>\n";
		print "<form action=\"$script\">\n";
		print "<input type=submit value='掲示板へ戻る'></form>\n";
		print "<hr width=400></div>\n</body></html>\n";
	}
	exit;
}

#--------------#
#  ワード検索  #
#--------------#
sub find {
	local($wd,$flag,$i,$next,$back,$enwd,@wd);

	&header;
	print <<"EOM";
[<a href="$script?">掲示板に戻る</a>]
<UL>
  <LI>検索したい<b>キーワード</b>を入力し「検索」ボタンを押してください。
  <LI>キーワードは「半角スペース」で区切って複数指定することができます。
<form action="$script" method="POST">
<input type=hidden name=mode value="find">
キーワード：<input type=text name=word size=35 value="$in{'word'}">
検索条件：<select name=cond>
EOM

	foreach ("AND", "OR") {
		if ($in{'cond'} eq $_) {
			print "<option value=\"$_\" selected>$_\n";
		} else {
			print "<option value=\"$_\">$_\n";
		}
	}
	print "</select>\n 表\示件数：<select name=view>\n";
	foreach (10,15,20,25,30) {
		if ($in{'view'} == $_) {
			print "<option value=\"$_\" selected>$_\n";
		} else {
			print "<option value=\"$_\">$_\n";
		}
	}
	print "</select>\n<input type=submit value=' 検索 '></form>\n</UL>\n";

	# ワード検索の実行と結果表示
	if ($in{'word'} ne "") {

		# 入力内容を整理
		$in{'word'} =~ s/　/ /g;
		@wd = split(/\s+/, $in{'word'});

		# 検索
		print "<DL>\n";
		$i=0;
		open(IN,"$logfile") || &error("Open Error : $logfile");
		while (<IN>) {
			$flag=0;
			foreach $wd (@wd) {
				if (index($_,$wd) >= 0) {
					$flag=1;
					if ($in{'cond'} eq 'OR') { last; }
				} else {
					if ($in{'cond'} eq 'AND') { $flag=0; last; }
				}
			}
			if ($flag) {
				$i++;
				if ($i < $page + 1) { next; }
				if ($i > $page + $in{'view'}) { next; }

				local($no,$date,$name,$mail,$sub,$com,$url) = split(/<>/);
				if ($mail) { $name="<a href=\"mailto:$mail\">$name</a>"; }

				print "<DT><hr>[<b>$no</b>] ",
				"<font color=\"$sub_color\"><b>$sub</b></font> ",
				"投稿者：<b>$name</b> 投稿日：$date<br><br><DD>$com";
				print "<P><a href=\"http://$url\" target=\"_blank\">http://$url</a>" if ($url);
				print "<br><br>\n";
			}
		}
		close(IN);
		print "<DT><hr>検索結果：<b>$i</b>件</DL>\n";

		$next = $page + $in{'view'};
		$back = $page - $in{'view'};
		$enwd = &url_enc($in{'word'});
		if ($back >= 0) {
			print "[<a href=\"$script?mode=find&page=$back&word=$enwd&view=$in{'view'}&cond=$in{'cond'}\">前の$in{'view'}件</a>]\n";
		}
		if ($next < $i) {
			print "[<a href=\"$script?mode=find&page=$next&word=$enwd&view=$in{'view'}&cond=$in{'cond'}\">次の$in{'view'}件</a>]\n";
		}

	}
	print "</body>\n</html>\n";
	exit;
}

#--------------#
#  管理モード  #
#--------------#
sub admin {
	local($no,$date,$name,$mail,$sub,$com,$url,$host,$pw,@new);

	if ($in{'pass'} eq "") {
		&header;
		print "<center><h4>パスワードを入力して下さい</h4>\n",
		"<form action=\"$script\" method=\"POST\">\n",
		"<input type=hidden name=mode value=\"admin\">\n",
		"<input type=password name=pass size=8>\n",
		"<input type=submit value=' 認証 '></form>\n",
		"</body>\n</html>\n";
		exit;
	}
	elsif ($in{'pass'} ne $pass) { &error("パスワードが違います"); }

	# 削除処理
	if ($in{'del'}) {
		@del = split(/\0/, $in{'del'});

		# POST限定
		if ($postonly && !$post_flag) { &error("不正なアクセスです"); }

		# ロック処理
		&lock if ($lockkey);

		# 削除情報をマッチング
		@new=();
		open(IN,"$logfile") || &error("Open Error : $logfile");
		while (<IN>) {
			$flag=0;
			($no) = split(/<>/);
			foreach $del (@del) {
				if ($no == $del) { $flag=1; last; }
			}
			if (!$flag) { push(@new,$_); }
		}
		# 更新
		open(OUT,">$logfile") || &error("Write Error : $logfile");
		print OUT @new;
		close(OUT);

		# ロック解除
		&unlock if ($lockkey);
	}

	# 削除画面を表示
	&header;
	print <<"EOM";
[<a href="$script?">掲示板に戻る</a>]
<form action="$script" method="POST">
<input type=hidden name=mode value="admin">
<input type=hidden name=pass value="$in{'pass'}">
<input type=submit value="記事を削除">
<DL>
EOM
	# 記事を展開
	open(IN,"$logfile") || &error("Open Error : $logfile");
	while (<IN>) {
		($no,$date,$name,$mail,$sub,$com,$url,$host) = split(/<>/);
		if ($mail) { $name="<a href=\"mailto:$mail\">$name</a>"; }
		$com =~ s/<br>//ig;
		$com =~ s/</&lt;/g;
		$com =~ s/>/&gt;/g;
		if (length($com) > 60) {
			$com = substr($com,0,58);
			$com .= "...";
		}
		print "<DT><input type=checkbox name=del value=\"$no\">",
		"[$no] <b>$sub</b> $name - $date &lt;$host&gt;\n",
		"<DD><span style='font-size:8pt'>$com</span>\n";
	}
	close(IN);
	print "</DL></form>\n</body>\n</html>\n";
	exit;
}

#--------------#
#  使い方表示  #
#--------------#
sub howto {
	&header;
	print <<"EOM";
[<a href="$script?">掲示板に戻る</a>]
<h3>留意事項</h3>
<OL>
<LI>この掲示板は<b>クッキー対応</b>です。１度記事を投稿いただくと、おなまえ、Ｅメール、ＵＲＬ、削除キーの情報は２回目以降は自動入力されます。<br>
	（ただし利用者のブラウザがクッキー対応の場合）<br><br>
<LI>投稿記事には、<b>タグは一切使用できません。</b><br><br>
<LI>記事を投稿する上での必須入力項目は<b>「おなまえ」</b>と<b>「メッセージ」</b>です。Ｅメール、ＵＲＬ、題名、削除キーは任意です。<br><br>
<LI>記事には、<b>半角カナは一切使用しないで下さい。</b>文字化けの原因となります。<br><br>
<LI>記事の投稿時に<b>「削除キー」</b>にパスワード（英数字で8文字以内）を入れておくと、その記事は次回<b>削除キー</b>によって削除することができます。<br><br>
<LI>記事の保持件数は<b>最大 $max件</b>です。それを超えると古い順に自動削除されます。<br><br>
<LI>既存の記事に簡単に<b>「返信」</b>することができます。各記事にある<b>「返信」</b>のリンク部を押すと投稿フォームが返信用となります。<br><br>
<LI>過去の投稿記事から<b>「キーワード」によって簡易検索ができます。</b>トップメニューの<a href="$script?mode=find">「ワード検索」</a>のリンクをクリックすると検索モードとなります。<br><br>
<LI>管理者が著しく不利益と判断する記事や他人を誹謗中傷する記事は予\告なく削除することがあります。
</OL>
</body>
</html>
EOM
	exit;
}

#------------------#
#  ユーザ記事削除  #
#------------------#
sub usrdel {
	local($no,$date,$name,$mail,$sub,$com,$url,$host,$pw,@new);

	# POST限定
	if ($postonly && !$post_flag) { &error("不正なアクセスです"); }

	if ($in{'no'} eq '' || $in{'pwd'} eq '') {
		&error("削除Noまたは削除キーが入力モレです");
	}

	# ロック処理
	&lock if ($lockkey);

	$flag=0;
	@new=();
	open(IN,"$logfile") || &error("Open Error : $logfile");
	while (<IN>) {
		($no,$date,$name,$mail,$sub,$com,$url,$host,$pw) = split(/<>/);
		if ($in{'no'} == $no) { $flag=1; $PWD=$pw; }
		else { push(@new,$_); }
	}
	close(IN);
	if (!$flag) { &error("該当記事が見当たりません"); }
	if ($PWD eq '') { &error("該当記事には削除キーが設定されていません"); }

	# 削除キーを照合
	$match = &decrypt($in{'pwd'}, $PWD);
	if ($match ne 'yes') { &error("削除キーが違います"); }

	# ログを更新
	open(OUT,">$logfile") || &error("Write Error : $logfile");
	print OUT @new;
	close(OUT);

	# ロック解除
	&unlock if ($lockkey);
}

#----------------#
#  デコード処理  #
#----------------#
sub decode {
	local($buf, $key, $val);
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		$post_flag=1;
		if ($ENV{'CONTENT_LENGTH'} > 51200) { &error("投稿量が大きすぎます"); }
		read(STDIN, $buf, $ENV{'CONTENT_LENGTH'});
	} else {
		$post_flag=0;
		$buf = $ENV{'QUERY_STRING'};
	}
	foreach (split(/&/, $buf)) {
		($key, $val) = split(/=/);
		$val =~ tr/+/ /;
		$val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

		# S-JISコード変換
		&jcode'convert(*val, "sjis", "", "z");

		# タグ処理
		$val =~ s/&/&amp;/g;
		$val =~ s/"/&quot;/g;
		$val =~ s/</&lt;/g;
		$val =~ s/>/&gt;/g;
		$val =~ s/\0//g;

		# 改行処理
		if ($key eq "comment") {
			$val =~ s/\r\n/<br>/g;
			$val =~ s/\r/<br>/g;
			$val =~ s/\n/<br>/g;
		} else {
			$val =~ s/\r//g;
			$val =~ s/\n//g;
		}
		$in{$key} .= "\0" if (defined($in{$key}));
		$in{$key} .= $val;
	}
	$in{'url'} =~ s/^http\:\/\///;
	if ($in{'sub'} eq "") { $in{'sub'} = "無題"; }
	$page = $in{'page'};
	$mode = $in{'mode'};

	# タイムゾーン設定
	$ENV{'TZ'} = "JST-9";
}

#--------------#
#  HTMLヘッダ  #
#--------------#
sub header {
	if ($headflag) { return; }
	print <<"EOM";
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
<META HTTP-EQUIV="Content-Style-Type" content="text/css">
<STYLE TYPE="text/css">
<!--
body,tr,td,th { font-size:$b_size }
-->
</STYLE>
<title>$title</title></head>
$body
EOM
	$headflag=1;
}

#--------------#
#  エラー処理  #
#--------------#
sub error {
	if ($lockflag) { &unlock; }
	&header;
	print "<center><hr width=400><h3>ERROR !</h3>\n";
	print "<font color='#dd0000'>$_[0]</font>\n";
	print "<P><hr width=400></center>\n</body>\n</html>\n";
	exit;
}

#------------------#
#  クッキーの発行  #
#------------------#
sub set_cookie {
	local($gmt, $cook, @t, @m, @w);
	@t = gmtime(time + 60*24*60*60);
	@m = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
	@w = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');

	$gmt = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT",
			$w[$t[6]], $t[3], $m[$t[4]], $t[5]+1900, $t[2], $t[1], $t[0]);

	$cook = "$in{'name'}<>$in{'email'}<>$in{'url'}<>$in{'pwd'}";
	print "Set-Cookie: ASKABBS=$cook; expires=$gmt\n";
}

#------------------#
#  クッキーを取得  #
#------------------#
sub get_cookie {
	local($key, $val, *ck);

	$ck = $ENV{'HTTP_COOKIE'};
	foreach (split(/;/, $ck)) {
		($key, $val) = split(/=/);
		$key =~ s/\s//g;
		$ck{$key} = $val;
	}
	@ck = split(/<>/, $ck{'ASKABBS'});
	return (@ck);
}

#----------------#
#  ホスト名取得  #
#----------------#
sub get_host {
	$host = $ENV{'REMOTE_HOST'};
	$addr = $ENV{'REMOTE_ADDR'};

	if ($host eq "" || $host eq $addr) {
		$host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2) || $addr;
	}
}

#----------------------#
#  パスワード暗号処理  #
#----------------------#
sub encrypt {
	local($inpw) = $_[0];
	local($salt, $encrypt, @s);

	@s = ('a'..'z', 'A'..'Z', '0'..'9', '.', '/');
	srand;
	$salt = $s[int(rand(@s))] . $s[int(rand(@s))];
	$encrypt = crypt($inpw, $salt) || crypt ($inpw, '$1$' . $salt);
	return $encrypt;
}

#----------------------#
#  パスワード照合処理  #
#----------------------#
sub decrypt {
	local($inpw, $logpw) = @_;
	local($salt, $key, $check);

	$salt = $logpw =~ /^\$1\$(.*)\$/ && $1 || substr($logpw, 0, 2);
	$check = "no";
	if (crypt($inpw, $salt) eq $logpw || crypt($inpw, '$1$' . $salt) eq $logpw)
		{ $check = "yes"; }
	return $check;
}

#--------------#
#  ロック処理  #
#--------------#
sub lock {
	# 1分以上古いロックは削除する
	if (-e $lockfile) {
		local($mtime) = (stat($lockfile))[9];
		if ($mtime < time - 60) { &unlock; }
	}
	local($retry) = 5;
	# symlink関数式ロック
	if ($lockkey == 1) {
		while (!symlink(".", $lockfile)) {
			if (--$retry <= 0) { &error('LOCK is BUSY'); }
			sleep(1);
		}
	# mkdir関数式ロック
	} elsif ($lockkey == 2) {
		while (!mkdir($lockfile, 0755)) {
			if (--$retry <= 0) { &error('LOCK is BUSY'); }
			sleep(1);
		}
	}
	$lockflag=1;
}

#--------------#
#  ロック解除  #
#--------------#
sub unlock {
	if ($lockkey == 1) { unlink($lockfile); }
	elsif ($lockkey == 2) { rmdir($lockfile); }
	$lockflag=0;
}

#--------------#
#  メール送信  #
#--------------#
sub mail_to {
	local($mail_sub, $mail_body, $m_com, $email);

	# メールプログラムのパスチェック
	unless (-e $mailprog) { &error("メールプログラムのパスが不正です"); }
	if ($mailprog =~ /blat/i) { $prog_type=2; } else { $prog_type=1; }

	# メールタイトルを定義
	$mail_sub = "[$title : $no] $in{'sub'}";

	# 本文の改行・タグを復元
	$m_com = $in{'comment'};
	$m_com =~ s/<br>/\n/g;
	$m_com =~ s/&lt;/</g;
	$m_com =~ s/&gt;/>/g;
	$m_com =~ s/&amp;/&/g;

$mail_body = <<"EOM";
--------------------------------------------------------
$titleに以下の投稿がありました。

投稿日時：$date
ホスト名：$host
ブラウザ：$ENV{'HTTP_USER_AGENT'}

おなまえ：$in{'name'}
Ｅメール：$in{'email'}
タイトル：$in{'sub'}
ＵＲＬ  ：http://$in{'url'}
コメント：

$m_com
--------------------------------------------------------
EOM

	# BlatJ送信
	if ($prog_type == 2) {

		# 一時ファイルを書き出し
		local($tempfile) = "./$$\.tmp";
		open(TMP,">$tempfile") || &error("Write Error : $tempfile");
		print TMP $mail_body;
		close(TMP);

		# 送信処理
		open(MAIL,"| $mailprog $tempfile -t $mailto -s \"$mail_sub\" -q")
					|| &error("メール送信に失敗しました");
		close(MAIL);

		# 一時ファイル削除
		unlink($tempfile);

	# sendmail送信
	} else {

		# JISコード変換
    		&jcode'convert(*mail_sub,'jis');
    		&jcode'convert(*mail_body,'jis');

		# メールアドレスがない場合は管理者アドレスに置き換え
		if ($in{'email'} eq "") { $email = $mailto; }
		else { $email = $in{'email'}; }

		# sendmail送信
		open(MAIL,"| $mailprog -t") || &error("メール送信に失敗しました");
		print MAIL "To: $mailto\n";
		print MAIL "From: $email\n";
		print MAIL "Subject: $mail_sub\n";
		print MAIL "MIME-Version: 1.0\n";
		print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n";
		print MAIL "Content-Transfer-Encoding: 7bit\n";
		print MAIL "X-Mailer: $ver\n\n";
		print MAIL $mail_body;
		close(MAIL);
	}
}

#--------------#
#  自動リンク  #
#--------------#
sub auto_link {
	$_[0] =~ s/([^=^\"]|^)(http\:[\w\.\~\-\/\?\&\=\@\;\#\:\%]+)/$1<a href=\"$2\" target=\"_top\">$2<\/a>/g;
}

#-----------------#
#  URLエンコード  #
#-----------------#
sub url_enc {
	local($_) = @_;

	s/(\W)/'%' . unpack('H2', $1)/eg;
	s/\s/+/g;
	$_;
}

#------------------#
#  チェックモード  #
#------------------#
sub check {
	&header;
	print "<h2>Check Mode</h2>\n";
	print "<UL>\n";

	# ログファイル
	if (-e $logfile) {
		print "<LI>ログファイルパス：OK\n";
		if (-r $logfile && -w $logfile) { print "<LI>ログパーミッション：OK\n"; }
		else { print "<LI>ログパーミッションが不正です。\n"; }
	} else { print "<LI>ログファイルのパスが不正です：NG → $logfile\n"; }

	# ロックディレクトリ
	print "<LI>ロック形式：";
	if ($lockkey == 0) { print "ロック設定なし\n"; }
	else {
		if ($lockkey == 1) { print "symlink\n"; }
		else { print "mkdir\n"; }
		($lockdir) = $lockfile =~ /(.*)[\\\/].*$/;
		print "<LI>ロックディレクトリ：$lockdir\n";

		if (-d $lockdir) {
			print "<LI>ロックディレクトリのパス：OK\n";
			if (-r $lockdir && -w $lockdir && -x $lockdir) {
				print "<LI>ロックディレクトリのパーミッション：OK\n";
			} else {
				print "<LI>ロックディレクトリのパーミッション：NG → $lockdir\n";
			}
		} else { print "<LI>ロックディレクトリのパス：NG → $lockdir\n"; }
	}
	print "</UL>\n</body>\n</html>\n";
	exit;
}

