#!/usr/local/bin/perl
# 上記は、使用するサ−バ−のパスにあわせる事。
#-----------------------------------------------------
# Guest book Ver. 2
#-----------------------------------------------------
# ---------- ココから下を変更して下さい。-------------
# デザインのテンプレートHTMLファイル名。
$template_file = './guest_book.html';
# 投稿内容のログファイル名。
$log_file = './log.dat';
# 管理者パスワード。必ず変更して下さい。
$master_passwd = 'coffee';
# 1画面に表示するスレット数。
$pages = 10;
# 1メッセージの文字数制限値。0なら制限なし。
$max_len = 2000;
# このCGIのURL。
# フルパスで指定する場合はhttp://から正しく記述する。
# 例: $cgi_url = 'http://www.lens.gr.jp/~html/cgi-bin/board.cgi'
$cgi_url = 'http://www.q-michinoeki.net/cgi/bbs/board.cgi';
# 削除ボタンのラベル。
$delete_label = '削除';
# 返信ボタンのラベル。
$reply_label = '返信';
# 返信フォーム画面のタイトル。
# $reply_title1はメッセージ番号の前、$reply_title2は後に表示される。
$reply_title1 = 'Message No. ';
$reply_title2 = 'への返信';
# 次ページ表示ボタンのラベル。
$next_label = '次のページ';
# name欄への入力が無かった場合のデフォルト。
$nanashi_label = '匿名希望';
# name表示色
$name_color = '#FF3300';
# subject欄への入力が無かった場合のデフォルト。
$no_subject = 'タイトルなし';
# subject表示色
$subject_color = '#FF9900';
# blood欄への入力が無かった場合のデフォルト。
$no_blood = '一般';
# 曜日名の表現
@wday_array = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
# ---------- ココまで!! ----------------------------
require './jcode.pl';
&GetQuery;
if ($FORM{'mode'} eq "Write") {
$date = &GetDates;
&WriteData;
&PrintData;
} elsif ($FORM{'mode'} eq "Delete") {
&DeleteData;
&PrintData;
} elsif ($FORM{'mode'} eq "WriteRes") {
&PrintResForm;
} else {
&PrintData;
}
exit;
sub GetDates {
my $times = time;
my ($sec, $min, $hour, $mday, $month, $year, $wday, $yday, $isdst) = localtime($times);
$min = "0$min" if ($min < 10);
$hour = "0$hour" if ($hour < 10);
$mday = "0$mday" if ($mday < 10);
$month = $month + 1;
$month = "0$month" if ($month < 10);
$year = $year + 1900;
my $youbi = $wday_array [$wday];
return "$year/$month/$mday($youbi) $hour:$min";
}
sub GetQuery {
my (@pairs, $buffer, $pro);
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
&jcode'convert(*value, 'sjis');
$value =~ s/\t/ /g;
$value =~ s/\r/\n/g;
$value =~ s/\n\n/\n/g;
$value =~ s/\n/
/g;
$FORM{$name} = $value;
}
}
sub WriteData {
$org_number = $FORM{'org_number'};
$host = $FORM{'host'};
if ($FORM{'password'} eq "") {
$password = &encrypt($master_passwd);
} else {
$password = &encrypt($FORM{'password'});
}
$name = $FORM{'name'};
$name =~ s/ //g;
$name =~ s/ //g;
$name =~ s/</g;
$name =~ s/>/>/g;
$name = $nanashi_label if (!$name);
$email = $FORM{'email'};
$blood = $FORM{'blood'};
$blood =~ s/</g;
$blood =~ s/>/>/g;
$blood = $no_blood if (!$blood);
$url = $FORM{'url'};
$url ="" if ($url eq "http://");
$subject = $FORM{'subject'};
$subject =~ s/</g;
$subject =~ s/>/>/g;
$subject = $no_subject if (!$subject);
$board = $FORM{'board'};
if (length($board) > $max_len && $max_len != 0) {
$max_moji = $max_len/2;
&error("$max_moji文字以内で書き込んで下さい。");
}
$board =~ s/
]*)>(.*)/$1/;
$tag =~ s/^\/(.*)//;
$tag =~ s/^([^\s]*).*/$1/;
}
$board .= '>' if ($board =~ /<\/$/);
@tags = reverse(@tags);
foreach $tag (@tags) {
next if ($tag =~ /(img|^hr$|^br$)/i);
$board .= "$tag>" if ($tag);
}
$board .= '">TagError?' if (($board =~ /.*<\/A>/i));
$board =~ s/;
close(LOG);
if (@lines <= 1) { @lines = (); }
$counter = shift(@lines);
if ($counter eq "") { $counter = 0; }
$counter = $counter + 1;
@newlines = ();
if ($org_number eq "") {
unshift(@lines, "$counter\t0\t$date\t$host\t$password\t$name\t$email\t$blood\t$url\t$subject\t$board\n");
@newlines = @lines;
} else {
$mode = 0;
foreach (@lines) {
($number, $resnum) = split(/\t/);
if ($mode == 0 && $number == $org_number) {
$mode = 1;
} elsif ($mode == 1 && $resnum == 0) {
push(@newlines, "$counter\t$org_number\t$date\t$host\t$password\t$name\t$email\t$blood\t$url\t$subject\t$board\n");
$mode = 2;
}
push(@newlines, $_);
}
if ($mode == 1) {
push(@newlines, "$counter\t$org_number\t$date\t$host\t$password\t$name\t$email\t$blood\t$url\t$subject\t$board\n");
}
}
unshift(@newlines, "$counter\n");
open(LOG, ">$log_file") || &error("Can't Write Log File.");
&lock;
seek(LOG, 0, 0);
print LOG @newlines;
&unlock;
close(LOG);
}
}
sub DeleteData {
if ($FORM{'number'} ne "" && $FORM{'password'} ne "") {
@lines = ();
open(LOG, "$log_file") || &error("Can't Open Log File.");
seek(LOG, 0, 0);
@lines = ;
close(LOG);
$counter = shift(@lines);
if ($counter eq "") { $counter = 0; }
$mode = 0;
foreach (@lines) {
($number, $org_number, $date, $host, $password) = split(/\t/);
if ($mode == 0 && $number == $FORM{'number'}) {
$org_password = $password;
if ($org_number == 0) {
$mode = 2;
} else {
$mode = 1;
}
} elsif ($mode == 2 && $org_number == $FORM{'number'}) {
next;
} else {
push(@newlines, $_);
}
}
if ($mode != 0 && (&checkpass($FORM{'password'}, $org_password) eq 'Ok' || $FORM{'password'} eq $master_passwd)) {
unshift(@newlines, $counter);
open(LOG, ">$log_file") || &error("Can't Write Log File.");
&lock;
seek(LOG, 0, 0);
print LOG @newlines;
&unlock;
close(LOG);
}
}
}
sub PrintData {
open(ENT, "$template_file") || &error("Can't Read HTML Skeleton File");
seek(ENT, 0, 0);
@enter = ;
close(ENT);
open(LOG, "$log_file") || &error("Can't Open Log File.");
seek(LOG, 0, 0);
print "Content-type: text/html\n\n";
foreach (@enter) {
s/\r/\n/g;
s/\n\n/\n/g;
push @html, split(/\n/);
}
$progress = 'START';
foreach (@html) {
if (//) {
print "$_\n";
$progress = 'MESSAGE END';
} elsif ($progress eq 'MESSAGE') {
next;
} elsif (//) {
print "$_\n";
$progress = 'MESSAGE';
$counter = ;
$page = $FORM{'page'};
if ($page eq "") {
$page = 1;
}
$start = (($page - 1) * $pages) + 1;
$count = 0;
while () {
chop($_);
($number, $org_number, $date, $host, $password, $name, $email, $blood, $url, $subject, $board) = split(/\t/);
if ($org_number == 0) { $count++; }
if ($count >= $start && $count < ($start + $pages)) {
if ($email =~ /([\w\-]+)@(.+)\.(.+)/) {
$name_usr = "$name";
} else {
$board =~ s/\t/</g;
$name_usr = "$name";
}
if ($url) {
$data_usr = "[$date]($host)
$url";
} else {
$data_usr = "[$date]($host)";
}
if ($org_number == 0) {
print "
\n";
print "\n";
print " \n";
print "
\n";
print "\n";
print " $data_usr | \n";
print "
\n";
} else {
print "
\n";
print "\n";
print "
| \n";
print " No. $number $subject : $name_usr($blood): | \n";
print "
\n";
print "\n";
print "
| \n";
print " $data_usr | \n";
print "
\n";
}
}
}
print "
\n";
print "\n";
print " | \n";
print "
\n";
if ($count >= ($start + $pages)) {
$next_page = $page + 1;
print "\n";
print " | \n";
print "
\n";
}
} else {
print "$_\n";
}
}
close(LOG);
}
sub PrintResForm {
open(ENT, "$template_file") || &error("Can't Read HTML Skeleton File");
seek(ENT, 0, 0);
@enter = ;
close(ENT);
open(LOG, "$log_file") || &error("Can't Open Log File.");
seek(LOG, 0, 0);
foreach (@enter) {
s/\r/\n/g;
s/\n\n/\n/g;
push @html, split(/\n/);
}
print "Content-type: text/html\n\n";
$progress = 'START';
foreach (@html) {
if (//) {
print "$_\n";
$progress = 'MESSAGE END';
} elsif ($progress eq 'MESSAGE') {
next;
} elsif (//) {
print "$_\n";
print "\n";
print " | $reply_title1$FORM{'org_number'}$reply_title2 | \n";
print "
\n";
} elsif (//) {
print "$_\n";
print "\n";
print "\n";
} elsif (//) {
print "$_\n";
$progress = 'MESSAGE';
$counter = ;
while () {
chop($_);
($number, $org_number, $date, $host, $password, $name, $email, $blood, $url, $subject, $board) = split(/\t/);
if ($number == $FORM{'org_number'} || $org_number == $FORM{'org_number'}) {
if ($email =~ /([\w\-]+)@(.+)\.(.+)/) {
$name_usr = "$name";
} else {
$board =~ s/\t/</g;
$name_usr = "$name";
}
if ($url) {
$data_usr = "[$date]($host)
$url";
} else {
$data_usr = "[$date]($host)";
}
if ($org_number == 0) {
print "
\n";
print "\n";
print " | No. $number $subject : $name_usr($blood):\n";
print " |
\n";
print "\n";
print " $data_usr | \n";
print "
\n";
} else {
print "
\n";
print "\n";
print "
| \n";
print " No. $number $subject : $name_usr($blood): | \n";
print "
\n";
print "\n";
print "
| \n";
print " $data_usr | \n";
print "
\n";
}
}
}
print "
\n";
} else {
print "$_\n";
}
}
close(LOG);
}
sub encrypt {
my $plain = shift(@_);
my (@salts, $salt, $crypted);
@salts = ('a'..'z', 'A'..'Z', '0'..'9', '.', '/');
srand(time ^ $$);
$salt = $salts[int(rand(@salts))] . $salts[int(rand(@salts))];
$crypted = crypt($plain, $salt);
return $crypted;
}
sub checkpass {
my ($inputpass, $logpass) = @_;
my $salt;
$salt = substr($logpass, 0, 2);
if (crypt($inputpass, $salt) eq $logpass) {
return 'Ok';
} else {
return 'No';
}
}
sub lock {
my $retry = 5;
my $symlink_check = (eval { symlink("",""); }, $@ eq "");
if (-e "$log_file.lock") {
($mtime) = (stat("$log_file.lock"))[9];
if ($mtime < time - 180) {
unlink("$log_file.lock");
}
}
if (!$symlink_check) {
while(-f "$log_file.lock") {
if (--$retry <= 0) { &error("System is busy. Please Retry."); }
sleep(1);
}
open(LOCK,">$log_file.lock");
close(LOCK);
} else {
while (!symlink(".", "$log_file.lock")) {
if (--$retry <= 0) { &error("System is busy. Please Retry."); }
sleep(1);
}
}
}
sub unlock {
unlink("$log_file.lock");
}
sub error {
if (-e "$log_file.lock") {
unlink("$log_file.lock");
}
print "Content-type: text/html\n\n";
print "\n";
print "\n";
print "ERROR\n";
print "\n";
print "\n";
print "
\n";
print "ERROR !
\n";
print "$_[0]
\n";
print "
\n";
print "\n";
exit;
}