#webliberty::App::Comment.pm (2006/03/11)
#Copyright(C) 2002-2006 Knight, All rights reserved.

package webliberty::App::Comment;

use strict;
use base qw(webliberty::Basis Exporter);
use webliberty::Host;
use webliberty::Cookie;
use webliberty::Lock;
use webliberty::Skin;
use webliberty::Sendmail;
use webliberty::App::Init;
use webliberty::App::Diary;

our @EXPORT_OK = qw(check regist);

### コンストラクタ
sub new {
	my $class = shift;

	my $self = {
		init   => shift,
		config => shift,
		query  => shift,
		html   => undef
	};
	bless $self, $class;

	return $self;
}

### メイン処理
sub run {
	my $self = shift;

	if ($self->{query}->{work} eq 'regist') {
		$self->check;
		if ($self->{query}->{exec_preview}) {
			$self->output_preview;
		} else {
			$self->regist;
			$self->output_complete;
		}
	} else {
		$self->output_list;
	}

	return;
}

### 入力内容チェック
sub check {
	my $self = shift;

	my $flag;

	if ($ENV{'REQUEST_METHOD'} ne 'POST') {
		$flag = 1;
	}
	if ($ENV{'HTTP_REFERER'} and $self->{config}->{base_url} and $ENV{'HTTP_REFERER'} !~ $self->{config}->{base_url}) {
		$flag = 1;
	}
	if (!$self->{config}->{proxy_mode} and ($ENV{'HTTP_VIA'} or $ENV{'HTTP_FORWARDED'} or $ENV{'HTTP_X_FORWARDED_FOR'})) {
		$flag = 1;
	}

	my $host_ins = new webliberty::Host;
	foreach (split(/<>/, $self->{config}->{black_list})) {
		if ($host_ins->get_host =~ /$_/i) {
			$flag = 1;
			last;
		}
	}

	if ($flag) {
		$self->error('不正なアクセスです。');
	}

	my $name_ins  = new webliberty::String($self->{query}->{name});
	my $mail_ins  = new webliberty::String($self->{query}->{mail});
	my $url_ins   = new webliberty::String($self->{query}->{url});
	my $subj_ins  = new webliberty::String($self->{query}->{subj});
	my $text_ins  = new webliberty::String($self->{query}->{text});
	my $pwd_ins   = new webliberty::String($self->{query}->{pwd});

	$name_ins->create_line;
	$mail_ins->create_line;
	$url_ins->create_line;
	$subj_ins->create_line;
	$text_ins->create_text;
	$pwd_ins->create_line;

	my $init_ins = new webliberty::App::Init;
	my %label = %{$init_ins->get_label};

	if (!$name_ins->get_string) {
		$self->error("$label{'pc_name'}が入力されていません。");
	}
	if (!$subj_ins->get_string) {
		$self->error("$label{'pc_subj'}が入力されていません。");
	}
	if (!$text_ins->get_string) {
		$self->error("$label{'pc_text'}が入力されていません。");
	}

	if ($name_ins->check_length > 20 * 2) {
		$self->error("$label{'pc_name'}の長さは全角20文字までにしてください。");
	}
	if ($mail_ins->check_length > 50) {
		$self->error("$label{'pc_mail'}の長さは半角50文字までにしてください。");
	}
	if ($url_ins->check_length > 100) {
		$self->error("$label{'pc_url'}の長さは半角100文字までにしてください。");
	}
	if ($text_ins->check_length > 2000 * 2) {
		$self->error("$label{'pc_text'}の長さは全角2000文字までにしてください。");
	}
	if ($text_ins->check_line > 200) {
		$self->error("$label{'pc_text'}は200行までにしてください。");
	}
	if ($pwd_ins->get_string and ($pwd_ins->check_length < 4 or $pwd_ins->check_length > 10)) {
		$self->error("$label{'pc_pwd'}の長さは半角4文字以上10文字以内にしてください。");
	}

	if ($mail_ins->get_string and ($mail_ins->get_string =~ /[^\w\.\@\d\-\_]/ or $mail_ins->get_string !~ /(.+)\@(.+)\.(.+)/)) {
		$self->error("$label{'pc_mail'}の入力内容が正しくありません。");
	}

	if ($self->{config}->{ng_word}) {
		foreach (split(/<>/, $self->{config}->{ng_word})) {
			if ($_ and $text_ins->get_string =~ /$_/) {
				$self->error("「$_」は使用禁止ワードに設定されています。");
			}
		}
	}

	return;
}

### コメント投稿
sub regist {
	my $self = shift;

	my $pno_ins  = new webliberty::String($self->{query}->{pno});
	my $name_ins = new webliberty::String($self->{query}->{name});
	my $mail_ins = new webliberty::String($self->{query}->{mail});
	my $url_ins  = new webliberty::String($self->{query}->{url});
	my $subj_ins = new webliberty::String($self->{query}->{subj});
	my $text_ins = new webliberty::String($self->{query}->{text});
	my $icon_ins = new webliberty::String($self->{query}->{icon});
	my $pwd_ins  = new webliberty::String($self->{query}->{pwd});
	my $save_ins = new webliberty::String($self->{query}->{save});

	$pno_ins->create_number;
	$name_ins->create_line;
	$mail_ins->create_line;
	$url_ins->create_line;
	$subj_ins->create_line;
	$text_ins->create_text;
	$icon_ins->create_line;
	$pwd_ins->create_line;
	$save_ins->create_line;

	if ($url_ins->get_string eq 'http://') {
		$url_ins->set_string('');
	}

	if ($save_ins->get_string) {
		my $cookie_ins = new webliberty::Cookie($self->{config}->{cookie_id});
		$cookie_ins->set_holddays($self->{config}->{cookie_holddays});
		$cookie_ins->set_cookie(
			name => $name_ins->get_string,
			mail => $mail_ins->get_string,
			url  => $url_ins->get_string,
			icon => $icon_ins->get_string,
			pwd  => $pwd_ins->get_string
		);
	}

	my $lock_ins = new webliberty::Lock("$self->{init}->{data_dir}$self->{init}->{data_lock}");
	if (!$lock_ins->file_lock) {
		$self->error('ファイルがロックされています。時間をおいてもう一度投稿してください。');
	}

	open(FH, "$self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{init}->{data_comt_index}") or $self->error("Read Error : $self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{init}->{data_comt_index}");
	my @index = sort { $b <=> $a } <FH>;
	close(FH);

	my $new_no       = (split(/\t/, $index[0]))[0] + 1;
	my $comment_file = "$self->{init}->{data_dir}$self->{init}->{data_comt_dir}" . $pno_ins->get_string . "\.$self->{init}->{data_ext}";

	if (!-e $comment_file) {
		open(FH, ">$comment_file") or $self->error("Write Error : $comment_file");
		close(FH);

		if ($self->{init}->{chmod_mode}) {
			if ($self->{init}->{suexec_mode}) {
				chmod(0600, "$comment_file") or $self->error("Chmod Error : $comment_file");
			} else {
				chmod(0606, "$comment_file") or $self->error("Chmod Error : $comment_file");
			}
		}
	}

	if ($pwd_ins->get_string) {
		$pwd_ins->create_password;
	}
	my $host_ins = new webliberty::Host;

	my($last_date, $last_host) = (split(/\t/, $index[0]))[3, 6];
	chomp($last_host);
	if (time - $last_date < $self->{config}->{wait_time} and $host_ins->get_host eq $last_host) {
		$lock_ins->file_unlock;
		$self->error("連続投稿は$self->{config}->{wait_time}秒以上時間をあけてください。");
	}

	open(FH, ">>$comment_file") or $self->error("Write Error : $comment_file");
	print FH "$new_no\t" . $pno_ins->get_string . "\t1\t" . time . "\t" . $name_ins->get_string . "\t" . $mail_ins->get_string . "\t" . $url_ins->get_string . "\t" . $subj_ins->get_string . "\t" . $text_ins->get_string . "\t\t" . $icon_ins->get_string . "\t\t\t" . $pwd_ins->get_string . "\t" . $host_ins->get_host . "\n";
	close(FH);

	unshift(@index, "$new_no\t" . $pno_ins->get_string . "\t1\t" . time . "\t" . $name_ins->get_string . "\t" . $subj_ins->get_string . "\t" . $host_ins->get_host . "\n");

	open(FH, ">$self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{init}->{data_comt_index}") or $self->error("Write Error : $self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{init}->{data_comt_index}");
	print FH @index;
	close(FH);

	$lock_ins->file_unlock;

	if ($self->{config}->{sendmail_cmt_mode}) {
		my $flag;
		foreach (split(/<>/, $self->{config}->{sendmail_admin})) {
			if ($name_ins->get_string eq $_) {
				$flag = 1;
				last;
			}
		}

		if (!$flag) {
			my $sendmail_ins = new webliberty::Sendmail($self->{config}->{sendmail_path});
			foreach (split(/<>/, $self->{config}->{sendmail_list})) {
				if (!$_) {
					next;
				}

				my($flag, $message) = $sendmail_ins->sendmail(
					send_to => $_,
					subject => "$self->{config}->{site_title}にコメントの投稿がありました",
					name    => $name_ins->get_string,
					message => "$self->{config}->{site_title}に以下のコメントが投稿されました。\n\n投稿者：" . $name_ins->get_string . "\n\n" . $text_ins->get_string
				);
				if (!$flag) {
					$self->error($message);
				}
			}
		}
	}

	my $dammy;
	$dammy->{query}->{no} = $pno_ins->get_string;

	my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $dammy->{query});
	$diary_ins->update;

	return;
}

### 投稿完了画面表示
sub output_complete {
	my $self = shift;

	my $skin_ins = new webliberty::Skin;
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_header}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_complete}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_footer}");

	my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $self->{query});

	$skin_ins->replace_skin(
		$diary_ins->info
	);

	print $self->header;
	print $skin_ins->get_data('header');
	print $skin_ins->get_data('contents');
	print $skin_ins->get_data('footer');

	return;
}

### プレビュー表示
sub output_preview {
	my $self = shift;

	my $skin_ins = new webliberty::Skin;
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_header}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_diary}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_comment}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_footer}");

	my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $self->{query});

	$skin_ins->replace_skin(
		$diary_ins->info
	);

	$self->{html}->{header} = $skin_ins->get_data('header');

	$self->{html}->{comment_head} = $skin_ins->get_replace_data(
		'comment_head',
		ARTICLE_COMMENT_START => '<!--',
		ARTICLE_COMMENT_END   => '-->',
	);
	$self->{html}->{comment} .= $skin_ins->get_replace_data(
		'comment',
		$diary_ins->comment_article($self->{query}->{pno}, $self->{query}->{pno}, '', time, $self->{query}->{name}, $self->{query}->{mail}, $self->{query}->{url}, $self->{query}->{subj}, $self->{query}->{text}, '', $self->{query}->{icon}, '', '', $self->{query}->{pwd}, '')
	);
	$self->{html}->{comment_foot} = $skin_ins->get_data('comment_foot');

	my $form_save;
	if ($self->{query}->{save}) {
		$form_save = ' checked="checked"';
	}

	$self->{html}->{form} = $skin_ins->get_replace_data(
		'form',
		$diary_ins->comment_form($self->{query}->{pno}, $self->{query}->{pno}, '', '', $self->{query}->{name}, $self->{query}->{mail}, $self->{query}->{url}, $self->{query}->{subj}, $self->{query}->{text}, '', $self->{query}->{icon}, '', '', $self->{query}->{pwd}, ''),
		FORM_MODE          => 'comment',
		FORM_WORK          => 'regist',
		FORM_SAVE          => $form_save,
		FORM_COMMENT_START => '<!--',
		FORM_COMMENT_END   => '-->',
		FORM_EDIT_START    => '<!--',
		FORM_EDIT_END      => '-->',
		FORM_ERROR_START   => '<!--',
		FORM_ERROR_END     => '-->'
	);

	$self->{html}->{footer} = $skin_ins->get_data('footer');

	print $self->header;
	foreach ($skin_ins->get_list) {
		print $self->{html}->{$_};
	}

	return;
}

### 記事一覧
sub output_list {
	my $self = shift;

	my $skin_ins = new webliberty::Skin;
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_header}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_diary}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_comment}");
	$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_footer}");

	my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $self->{query});

	$skin_ins->replace_skin(
		$diary_ins->info
	);

	my($index_date, $index_no, $flag);

	open(FH, "$self->{init}->{data_dir}$self->{init}->{data_diary_dir}$self->{init}->{data_diary_index}") or $self->error("Read Error : $self->{init}->{data_dir}$self->{init}->{data_diary_dir}$self->{init}->{data_diary_index}");
	while (<FH>) {
		chomp;
		my($date, $no, $id, $stat, $field, $name) = split(/\t/);

		if ($self->{query}->{no} == $no) {
			$index_date = $date;
			$index_no   = $no;

			$flag = 1;

			last;
		}
	}
	close(FH);

	if (!$flag) {
		$self->error('指定された記事は存在しません。');
	}

	my $data_file;
	if ($index_date =~ /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
		$data_file = "$1$2\.$self->{init}->{data_ext}";
	}

	$self->{html}->{header} = $skin_ins->get_data('header');
	$self->{html}->{diary}  = $skin_ins->get_data('diary_head');

	my $diary_subj;

	open(FH, "$self->{init}->{data_dir}$self->{init}->{data_diary_dir}$data_file") or $self->error("Read Error : $self->{init}->{data_dir}$self->{init}->{data_diary_dir}$data_file");
	while (<FH>) {
		chomp;
		my($no, $id, $stat, $break, $comt, $tb, $field, $date, $name, $subj, $text, $color, $icon, $file, $host) = split(/\t/);

		if ($index_no == $no) {
			if (!$comt) {
				$flag = 0;
			}

			$diary_subj = $subj;

			$self->{html}->{diary} .= $skin_ins->get_replace_data(
				'diary',
				$diary_ins->diary_article($no, $id, $stat, $break, $comt, $tb, $field, $date, $name, $subj, $text, $color, $icon, $file, $host)
			);

			last;
		}
	}
	close(FH);

	$self->{html}->{diary} .= $skin_ins->get_data('diary_foot');

	if (-e "$self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{query}->{no}\.$self->{init}->{data_ext}") {
		$self->{html}->{comment} = $skin_ins->get_replace_data(
			'comment_head',
			ARTICLE_COMMENT_START => '<!--',
			ARTICLE_COMMENT_END   => '-->',
		);

		open(FH, "$self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{query}->{no}\.$self->{init}->{data_ext}") or $self->error("Read Error : $self->{init}->{data_dir}$self->{init}->{data_comt_dir}$self->{query}->{no}\.$self->{init}->{data_ext}");
		while (<FH>) {
			chomp;
			my($no, $pno, $stat, $date, $name, $mail, $url, $subj, $text, $color, $icon, $file, $rank, $pwd, $host) = split(/\t/);

			$self->{html}->{comment} .= $skin_ins->get_replace_data(
				'comment',
				$diary_ins->comment_article($no, $pno, $stat, $date, $name, $mail, $url, $subj, $text, $color, $icon, $file, $rank, $pwd, $host)
			);
		}
		close(FH);

		$self->{html}->{comment} .= $skin_ins->get_replace_data(
			'comment_foot',
			ARTICLE_COMMENT_START => '<!--',
			ARTICLE_COMMENT_END   => '-->',
		);
	}

	if ($flag) {
		my $cookie_ins = new webliberty::Cookie($self->{config}->{cookie_id});

		my $form_save;
		if ($cookie_ins->get_cookie('name')) {
			$form_save = ' checked="checked"';
		}

		$self->{html}->{form} = $skin_ins->get_replace_data(
			'form',
			$diary_ins->comment_form($self->{query}->{no}, $self->{query}->{no}, '', '', $cookie_ins->get_cookie('name'), $cookie_ins->get_cookie('mail'), $cookie_ins->get_cookie('url'), "Re:$diary_subj", '', '', '', '', '', $cookie_ins->get_cookie('pwd'), ''),
			FORM_MODE          => 'comment',
			FORM_WORK          => 'regist',
			FORM_SAVE          => $form_save,
			FORM_PREVIEW_START => '<!--',
			FORM_PREVIEW_END   => '-->',
			FORM_EDIT_START    => '<!--',
			FORM_EDIT_END      => '-->',
			FORM_ERROR_START   => '<!--',
			FORM_ERROR_END     => '-->'
		);
	}

	$self->{html}->{footer} = $skin_ins->get_data('footer');

	print $self->header;
	foreach ($skin_ins->get_list) {
		print $self->{html}->{$_};
	}

	return;
}

### エラー出力
sub error {
	my $self    = shift;
	my $message = shift;

	if ($self->{query}->{exec_regist} or $self->{query}->{exec_preview}) {
		my $skin_ins = new webliberty::Skin;
		$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_header}");
		$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_diary}");
		$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_comment}");
		$skin_ins->parse_skin("$self->{init}->{skin_dir}$self->{init}->{skin_footer}");

		my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $self->{query});

		$skin_ins->replace_skin(
			$diary_ins->info,
			INFO_ERROR => $message
		);

		my $subj_ins = new webliberty::String($self->{query}->{subj});
		my $text_ins = new webliberty::String($self->{query}->{text});

		$subj_ins->create_line;
		$text_ins->create_text;

		my $form_save;
		if ($self->{query}->{save}) {
			$form_save = ' checked="checked"';
		}

		print $self->header;
		print $skin_ins->get_data('header');
		print $skin_ins->get_replace_data(
			'form',
			$diary_ins->comment_form($self->{query}->{no}, $self->{query}->{no}, '', '', $self->{query}->{name}, $self->{query}->{mail}, $self->{query}->{url}, $self->{query}->{subj}, $self->{query}->{text}, '', '', '', '', $self->{query}->{pwd}, ''),
			FORM_MODE          => 'comment',
			FORM_WORK          => 'regist',
			FORM_SAVE          => $form_save,
			FORM_COMMENT_START => '<!--',
			FORM_COMMENT_END   => '-->',
			FORM_PREVIEW_START => '<!--',
			FORM_PREVIEW_END   => '-->',
			FORM_EDIT_START    => '<!--',
			FORM_EDIT_END      => '-->',
		);
		print $skin_ins->get_data('footer');

		exit;
	}

	my $diary_ins = new webliberty::App::Diary($self->{init}, $self->{config}, $self->{query});
	$diary_ins->error($message);

	exit;
}

1;
