#!/usr/local/bin/perl

# yyregi.cgi 最終更新 2007/04/04

#┌─────────────────────────────────
#│ [ YY-BOARD ]
#│ regist.cgi - 2006/10/09
#│ Copyright (c) KentWeb
#│ webmaster@kent-web.com
#│ http://www.kent-web.com/
#└─────────────────────────────────

# YY-BOARD v5.33用携帯電話対応スクリプト
# 2005/01/04　湯一路　http://www.url-battle.com/cgi/

# 外部ファイル取込
require './yyini.cgi';
require "$jcode_file";
require "$cgi_lib_file";
# use CGI::Carp qw(fatalsToBrowser);

# メイン処理
&maxdata if (-e "$maxdata_file"); # 添付データ投稿受理最大サイズ取得
&agent; # 携帯端末別の分岐
&decode;

# 外部ファイル取込
require "./$room/yyini2.cgi";

# 設定ファイル読み込み
&data_load;

# 携帯電話用タイトル画像・絵文字メッセージ
&agent2;

# 絵文字入力フォーム
if ($em_form eq 1) { $com_name = "comment2" }
else { $com_name = "comment" }

# 外部ファイル取込 # <e-PAD>
if ($epad_use) {
	require "$epad_file";
	&emoji_table; # 絵文字変換テーブル
}

# 外部ファイル取込 ファイル添付機能
# if ($upload == 1) { require './resize.pl' if(-e './resize.pl'); }

# メイン処理
# &agent; # 携帯端末別の分岐
# &decode;
# DoCoMoで閲覧時機種情報取得
if ($UtnOn == 3 && ($imode == 3 || $imode == 8)) { $DCMUtn = ' utn'; }
else { $DCMUtn = ''; }
require "${libDir}regadlib.pl";
&axsCheck;
if ($miruPass && $mode ne "ninsho_del" && $mode ne "ninsho_edt" && $mode ne "ied" && $mode ne "urml") { &miruPass; }
if ($ProxyChk >= 4) { &ProxyChk; }
if (($UtnOn == 2 && $imode && $imode != 3 && $imode != 8) || ($UtnOn == 3 && $imode)) { &UtnCheck; }

if ($mode eq "regist" && ($in{'pview'} eq "on" || $pview == 1 && $in{'pview'} ne "ed")) { require "${libDir}kakunin.pl"; &kakunin; }
elsif ($mode eq "regist") { require "${libDir}regist.pl"; &regist; }
elsif ($mode eq "dele") { require "${libDir}dele.pl"; &dele; }
elsif ($mode eq "edit") { require "${libDir}edit.pl"; &edit; }
elsif ($mode eq "ninsho_del") { require "${libDir}ninsho_edt_del.pl"; &ninsho_edt_del; }
elsif ($mode eq "ninsho_edt") { require "${libDir}ninsho_edt_del.pl"; &ninsho_edt_del; }
elsif ($mode eq "ied") { require "${libDir}iedtdel.pl"; &iedtdel; }
elsif ($mode eq "past") { require "${libDir}past.pl"; &past; }
elsif ($mode eq "past2") { require "${libDir}past2.pl"; &past2; }
elsif ($mode eq "mobilemail") { require "${libDir}mobilemail.pl"; &mobilemail; }
elsif ($mode eq "urml") { require "${libDir}usrmail.pl"; &usrmail; }
elsif ($mode eq "mlrcv") { require "${libDir}mlrcv.pl"; &mlrcv; }
elsif ($mode eq "iconreg") { require "${libDir}iconup.pl"; &iconreg; }
&error("不明な処理です");

#-------------------------------------------------
#  投稿時間差確認
#-------------------------------------------------
# 送信なし、指定時間(規定値：5秒)以下、指定時間(同：30分)超はエラー
sub tokoJikanCheck {
	my $error='';
	my $a;
	if ($mode eq 'iconreg') { $a = $in{'c87ojFCq'}; } # アイコン登録時
	else { $a = $in{'L76nI5Dm'}; }
	if ($a eq '') { $error = "投稿時間が異常です -E00-"; }
	else {
		$a =~ s/%2e/./ig; # URLデコード(必要ないかも)
		$a =~ s/%2f/\//ig; # URLデコード(必要ないかも)
		my $check = time;
		my $b = $ENV{'HTTP_USER_AGENT'};
		if (($UtnOn==1 || $UtnOn==2) && $imode==3) { $b =~ s/\/ser.{11}$//; }
		if (($UtnOn==1 || $UtnOn==2) && $imode==8) { $b =~ s/;ser.{15}\s*;icc.{20}//; }
		if (!$imode) { $b = substr($host,1,5) . substr($b,-15); }
		else { $b = substr($b,-20); }
		my $c = &decrypt($b, $a);
		if ($c != 1) { $error = "投稿時間が異常です -E01-"; }
		else {
			$a =~ s/\W//g; # 英数字以外削除
			$check -= $in{$a};
			if ($tokoJikan1 > 0 && $check <= $tokoJikan1) { $error = "投稿時間が異常です -E02($check)-"; }
			if ($tokoJikan2 > 0 && $check > $tokoJikan2 * 60) { $error = "投稿時間が異常です -E03($check)-"; }
		}
	}
	if ($error && $ngreg >= 1) { require "${libDir}ngreg.pl"; &ngreg($error); $error =~ s/\(\d+\)//; &error($error); }
	elsif ($error) { $error =~ s/\(\d+\)//; &error($error); }
}

#-------------------------------------------------
#  入力確認
#-------------------------------------------------
sub formCheck {
	my ($task) = @_;
	my (@error) = (); # 投稿記事プレビュー時
	my $ng_call = 0;

	# プロキシ制限
	if ($ProxyChk >= 1) { &ProxyChk; }

	# 携帯個体識別情報チェック
	if ($imode && $UtnOn >= 1) { &UtnCheck; }

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

	# 他サイトからのアクセス排除
	if ($task ne 'edit' && $baseUrl && $in{'job'} ne 'kakunin') {
		my $ref = $ENV{'HTTP_REFERER'};
		$ref =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg;
		$baseUrl =~ s/(\W)/\\$1/g;
		if ($ref && $ref !~ /$baseUrl/i) { &error("不正なアクセスです(2)"); }
	}

	# Referer（参照元）がない投稿の拒否
	if($NoRefNG == 1 && !$ENV{'HTTP_REFERER'} && !$imode) { &error("Referer（参照元）が取得出来ないため投稿出来ません"); }

	# 絵文字入力フォーム用
	if ($em_form == 1 && !$in{'comment'} && $in{'comment2'}) {
		$in{'comment'} = $in{'comment2'};
	}

	if ($epad_use) {
		# 絵文字受理 <e-PAD>
		$in{'sub'}     = &emoji($in{'sub'});
		$in{'name'}    = &emoji($in{'name'});
		$in{'comment'} = &emoji($in{'comment'});
	}

	# 名前とコメントは必須
	if ($in{'name'} eq "") { if ($task eq 'view' ) { push(@error,"お名前が入力されていません"); } else { &error("お名前が入力されていません"); } }
	if ($in{'comment'} eq "") { if ($task eq 'view' ) { push(@error,"コメントが入力されていません"); } else { &error("コメントが入力されていません"); } }
	if ($in_email && !$in{'email'}) { if ($task eq 'view' ) { push(@error,"Ｅメールの入力は必須です"); } else { &error("Ｅメールの入力は必須です"); } }
	if ($in{'email'} && $in{'email'} !~ /^[\w\.\-]+\@[\w\.\-]+\.[a-zA-Z]{2,6}$/) { if ($task eq 'view' ) { push(@error,"Ｅメールの入力内容が正しくありません"); } else { &error("Ｅメールの入力内容が正しくありません"); } }
	if ($task eq 'view' && ($in{'sub'} eq "" || $in{'sub'} eq "無題")) { push(@error,"タイトルが入力されていません"); }

	# 投稿可能な最大文字数
	if ($nameMax && length($in{'name'}) > $nameMax*2) { if ($task eq 'view' ) { push(@error,"お名前が長すぎます"); } else { &error("お名前が長すぎます"); } }
	if ($subMax) {
		if ($in{'reno'}) { $subMax += 2; }
		if (length($in{'sub'}) > $subMax*2) { if ($task eq 'view' ) { push(@error,"タイトルが長すぎます"); } else { &error("タイトルが長すぎます"); } }
	}
	if ($commMax && length($in{'comment'}) > $commMax*2) { if ($task eq 'view' ) { push(@error,"メッセージが長すぎます"); } else { &error("メッセージが長すぎます"); } }

	# アイコン
	if ($iconMode) {
		my @ico1 = split(/\s+/, $ico1);

		# 登録アイコンを読み込み
		if ($iconUp > 0) {
			my ($tmpico) = $in{'icon'} - @ico1;
			my ($i)=0;
			my ($myicon_error)=0;
			my ($chk,$nam,$iconNam,$filename,$myico);
			open(ICON,"$iconUp_file") || &error("Can't open $iconUp_file");
			my $top = <ICON>;
			while (<ICON>) {
				($chk,$nam,$iconNam,$filename,$myico) = (split(/<>/))[1,3,4,5,7];
				if (!$iconCheck || $chk == 1) {
					push(@ico1,"$filename");
					# 専用アイコンを照合
					if ($tmpico == $i && $myico) {
						local($match) = &decrypt("$in{'pwd'}","$myico");
						if ($match != 1)  { $myicon_error=1; last; }
					}
					$i++;
				}
			}
			close(ICON);

			if ($myicon_error == 1) {
				if ($task eq 'view' ) { push(@error,"$iconNamは$namさん専用アイコンです"); } else { &error("$iconNamは$namさん専用アイコンです"); }
			}
		}

		if ($my_icon) { push(@ico1,"$my_gif"); }
		if ($imode_icon && $imode) { push(@ico1,"$imode_gif"); }

		if ($in{'icon'} =~ /\D/ || $in{'icon'} < 0 || $in{'icon'} > @ico1 || $in{'icon'} eq '') {
			 if ($task eq 'view' ) { push(@error,"アイコン情報が不正です"); } else { &error("アイコン情報が不正です"); }
		}
		$in{'icon'} = $ico1[$in{'icon'}];

		# 管理アイコンチェック
		my $check = &decrypt($in{'pwd'}, $mspass);
		if ($my_icon && $in{'icon'} eq $my_gif && $check != 1) {
			if ($task eq 'view' ) { push(@error,"管理用アイコンは管理者専用です"); } else { &error("管理用アイコンは管理者専用です"); }
		}
	}

	# 文字色情報チェック
	# 文字色情報を配列へ
	@col = split(/\s+/, $color);

	# ケータイ用文字色を配列に付加
	if ($keitaiCol) { push(@col,"$keitaiCol"); }

	if ($in{'color'} =~ /\D/ || $in{'color'} < 0 || $in{'color'} > @col) {
		if ($task eq 'view' ) { push(@error,"文字色情報が不正です"); } else { &error("文字色情報が不正です"); }
	}

	# URL
	if ($in{'url'} eq "http://") { $in{'url'} = ""; }

	# 禁止ワード
	my $ng_flag=0;
	if ($NGWord == 1) {
		my $sub2 = $in{'sub'}; &jcode'convert(*sub2, 'euc');
		my $name2 = $in{'name'}; &jcode'convert(*name2, 'euc');
		my $comment2 = $in{'comment'}; &jcode'convert(*comment2, 'euc');
		my $email2 = $in{'email'}; &jcode'convert(*email2, 'euc');
		my $url2 = $in{'url'}; &jcode'convert(*url2, 'euc');

		open(IN,"$ngword_file") || &error("Open Error: $ngword_file");
		while (<IN>) {
			if ($_ =~ /^#/) { next; } 
			$_ =~ s/\r\n$//; $_ =~ s/\n$//; $_ =~ s/\r$//;
			if (!$_) { next; } 
			&jcode'convert(*_, 'euc');
			if (index($sub2,$_) >= 0) { $ng_flag=1; last; }
			if (index($name2,$_) >= 0) { $ng_flag=1; last; }
			if (index($comment2,$_) >= 0) { $ng_flag=1; last; }
			if (index($email2,$_) >= 0) { $ng_flag=1; last; }
			if (index($url2,$_) >= 0) { $ng_flag=1; last; }
		}
		close(IN);
	}
	if ($ng_flag && $task eq 'view' ) {
		push(@error,"禁止ワードが含まれています");
	} elsif ($ng_flag && $ngreg >= 1) {
		if (!$ng_call) { require "${libDir}ngreg.pl"; $ng_call++; }
		&ngreg("禁止ワード");
		&error("不正な投稿です");
	} elsif ($ng_flag) {
		&error("不正な投稿です");
	}

	# 投稿検査
	my $c = $in{'comment'};
	if ($UrlComNG >= 1 && $in{'url'} && $c =~ /\Q$in{'url'}\E/i) {
		if ($task eq 'view' ) {
			push(@error,"参照先のアドレスはコメント中に投稿できません");
		} else {
			if ($ngreg >= 1) {
				if (!$ng_call) { require "${libDir}ngreg.pl"; $ng_call++; }
				&ngreg("参照先アドレスとコメント中アドレスの一致");
			}
			&error("参照先のアドレスはコメント中に投稿できません");
		}
	}
	if ($NoNihonNG >= 1 && $c !~ /[\x80-\xff]/) {
		if ($task eq 'view' ) {
			push(@error,"コメント中に日本語が含まれていません");
		} else {
			if ($ngreg >= 1) {
				if (!$ng_call) { require "${libDir}ngreg.pl"; $ng_call++; }
				&ngreg("コメント中に日本語なし");
			}
			&error("コメント中に日本語が含まれていません");
		}
	}
	if ($ComUrlsMax >= 1 && ($c =~ s/http/http/g) > $ComUrlsMax) {
		if ($task eq 'view' ) {
			push(@error,"コメント中のアドレスは$ComUrlsMax個までです");
		} else {
			if ($ngreg >= 1) {
				if (!$ng_call) { require "${libDir}ngreg.pl"; $ng_call++; }
				&ngreg("コメント中のアドレス数過多");
			}
			&error("コメント中のアドレスは$ComUrlsMax個までです");
		}
	}

	# コメントの最後の改行、全角スペース、半角スペース等の連続を削除
	if ($ComSeikei == 1) {
		local($comment,$a1,$a2,$a3) = ($in{'comment'},'\s','　','<br>');
		&jcode'convert(*comment, 'euc');
		&jcode'convert(*a1, 'euc');
		&jcode'convert(*a2, 'euc');
		&jcode'convert(*a3, 'euc');
		$comment =~ s/($a1|$a2|$a3)+$//;
		&jcode'convert(*comment, 'sjis');
		$in{'comment'} = $comment;
	}

	# 投稿記事プレビュー時
	if ($task eq "view") { return @error; }
}

#-------------------------------------------------
#  暗証キー確認
#-------------------------------------------------
sub pwd_check {
	my ($flag,$flag2,$check,$check2,$oya_work) = ('0','0','0','0','0');
	my ($no,$re,$pw,$mytime);

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

	open(IN,"$logfile") || &error("Open Error: ログファイル");
	my $top = <IN>;
	while (<IN>) {
		($no,$re,$pw,$mytime) = (split(/<>/))[0,1,9,12];
		if ($in{'oya'} == $no && $oyaWork) { # 親記事の暗証キー確認
			if ($pw ne '') { $check2 = &decrypt($in{'pwd'}, $pw); }
			if ($check2 == 1) { $oya_work=1; }
		} elsif ($in{'no'} == $no) { # 該当記事
			if ($mytime =~ /^0/ || $mytime =~ /^9/) { $flag2=1;}
#			if ($check == 1 && $in{'oya'} == $re && $oyaWork) { $flag=1; last; }
			if ($in{'oya'} && $in{'oya'} != $re) { $flag=0; last; }
			if ($pw ne '') { $check = &decrypt($in{'pwd'}, $pw); }
			$flag=1; last;
		}
	}
	close(IN);
	if ($check == 1 && $check2 == 1) { $oya_work=0; }
	elsif ($check != 1 && $oyaWork) { $check = $check2; }

	if (!$flag) { &error("該当の記事が見当たりません"); }
# 下の行の先頭の#を削除すると、マスターパスワードでも認証されます
#	if ($check != 1) { $check = &decrypt($in{'pwd'}, $mspass); }
	if ($pw eq "" && $check != 1) { &error("暗証キーが設定されていません"); }
	if ($check != 1) { &error("暗証キーが違います"); }
	if ($oya_work && $flag2) { &error("この記事は親記事投稿者による変更はできません"); }

	return $oya_work;
}

#-------------------------------------------------
#  時間取得
#-------------------------------------------------
sub get_time {
	$ENV{'TZ'} = "JST-9";
	$times = time;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime($times);
	my @week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');

	# 日時のフォーマット
	$date = sprintf("%04d/%02d/%02d(%s) %02d:%02d",
			$year+1900,$mon+1,$mday,$week[$wday],$hour,$min);
}


__END__

