[posting.cgi] -- #!/usr/local/bin/perl use strict; use Fcntl ':flock'; require "./webtool.pl"; require "./tree.pl"; require "./jcode.pl"; ;## ## ;## Copyright (C) 2002 by Junro YOSHINO ## ;## ## ;## Bulletin Board System; handler of posting ## ;## ## ;#-------------------------------------------------- ;# constants my $GCONF = "./gen.conf"; # configuration file my $BCONF = "./board.conf"; my $BCGI = "posting.cgi"; my $GCGI = "gen.cgi"; my $CGIDIR = "/cgi-bin/"; my $SITEROOT = "/~ju_y"; my ($_LITERAL, $_LIST, $_SET) = (0, 1, 2); ;# reseive data my (%decoded_data); webtool::parse_form_data(\%decoded_data, "POST"); my ($th) = ($decoded_data{"th"} =~ /([\d+])/); my ($board) = ($decoded_data{"board"} =~ /([\d\w]+)/); my $name = $decoded_data{"name"}; my $email = $decoded_data{"email"}; my $mes = $decoded_data{"mes"}; _error("Request Error: Invalid Thread No.: $th") if $th <= 0; ;# get configuration 1 my $count = 0; open(BFILE, "<" . $BCONF) || _error("File Error: Open Failed: board configuration"); my ($bconf_name, $bconf_type, @bconf_param); tree::parse_treeroot(\*BFILE, \$bconf_name, \$bconf_type, \@bconf_param, \$count) || _error("Data Error: Violation Found: at $BCONF line $count"); _error("Data Error: Not Configuration File: $BCONF") if($bconf_type != $_SET || $bconf_name ne "bconf"); my $bconf_ref = {'*NAME*' => "bconf"}; tree::parse_tree(\*BFILE, $bconf_ref, \$count, @bconf_param) || _error("Data Error: Violation Found: at $BCONF line $count"); ;# the following structure required: ;# bconf/-+-(board id):-+-(id for gen) ;# | +-(Th1 name) ;# | +-(Th2 name) ;# | +-... ;# +-... close BFILE; exists $bconf_ref->{$board} || _error("Request Error: Board Not Found: $board"); my $bid = tree::element_at($bconf_ref, "$board/1"); ;# get configuration2 $count = 0; open(GFILE, "<" . $GCONF) || _error("File Error: Open Failed: generator configuration"); my ($gconf_name, $gconf_type, @gconf_param); tree::parse_treeroot(\*GFILE, \$gconf_name, \$gconf_type, \@gconf_param, \$count) || _error("Data Error: Violation Found: at $GCONF line $count"); _error("Data Error: Not Configuration File: $GCONF") if($gconf_type != $_SET || $gconf_name ne "conf"); my $gconf_ref = {'*NAME*' => "conf"}; tree::parse_tree(\*GFILE, $gconf_ref, \$count, @gconf_param) || _error("Data Error: Violation Found: at $GCONF line $count"); ;# the following structure required: ;# conf/-+-(entry id):-+-(name of directory containing datafiles) ;# | +-(name of indexfile) ;# +-... close GFILE; exists $gconf_ref->{$bid} || _error("Data Error: Confliction Found: between board and generator configurations"); my ($path, $indexfile) = ( tree::element_at($gconf_ref, "$bid/1"), tree::element_at($gconf_ref, "$bid/2") ); ;# parse index tree $count = 0; open(IFILE, "+<" . $path . $indexfile) || _error("File Error: Open Failed: $path$indexfile"); flock(IFILE, LOCK_EX); my ($root_name, $root_type, @root_param); tree::parse_treeroot(\*IFILE, \$root_name, \$root_type, \@root_param, \$count) || _error("Data Error: Violation Found: at $path$indexfile line $count"); _error("Data Error: Not Index File: $path$indexfile") if($root_type != $_SET || $root_name ne "root"); my $root_ref = {'*NAME*' => "root"}; tree::parse_tree(\*IFILE, $root_ref, \$count, @root_param) || _error("Data Error: Violation Found: at $path$indexfile line $count"); ;# the following structure required: ;# root/-+-files/ -+-(message id):---(real filename) ;# | +-... ;# +-(iname): -+-(thread id): -+-(message id) ;# | | +-... ;# | +-... ;# +-control/ -+-indexname: ---(iname) my $iname = tree::element_at($root_ref, "control/indexname/"); ;# get infomation about target board/thread my $targetth = tree::element_at($root_ref, "$iname/Th$th"); defined($targetth) || _error("Request Error: No Such Thread: Th$th"); my($lastmes) = ($targetth->[1] =~ /Mes([\d]+)/); _error("Request Error: このスレッドにはこれ以上書き込めません。") if $lastmes <=0; my $currentmes = $lastmes + 1; ;# prepare data jcode::convert(\$name, "euc", "", "z"); jcode::convert(\$email, "euc", "", "z"); if(($email !~ m{^[\d\w\-]+\@[\w\-\.\d]+$}) && ($email !~ m{^[\d\w\-]+$})){ $email = ""; } jcode::convert(\$mes, "euc", "", "z"); $mes =~ s{\n}{
}g; $mes =~ s/\n//g; $mes =~ s/\r//g; $name = "Anonymous visitor" if $name eq ""; my @times = localtime; my $currentdate = sprintf("%s %02u, %04u (%s)", ( ["Jan.", "Feb.", "Mar.", "Apr.", "May", "Jun.", "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."]->[$times[4]], $times[3], $times[5] + 1900, ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]->[$times[6]])); my $currenttime = sprintf("%02u:%02u:%02u JST", ($times[2], $times[1], $times[0])); if ($ENV{'REMOTE_HOST'} eq "" || $ENV{'REMOTE_HOST'} eq $ENV{'REMOTE_ADDR'}){ $ENV{'REMOTE_HOST'} = gethostbyaddr(pack('C4', split(/\./, $ENV{'REMOTE_ADDR'})), 2) || $ENV{'REMOTE_ADDR'}; } ;# compare current message with last message my $lastmesname = tree::element_at($root_ref, "files/$targetth->[1]/"); $count = 0; open(LFILE, "<" . $path . $lastmesname) || _error("File Error: Open Failed: $path$lastmesname"); my ($l_name, $l_type, @l_param); tree::parse_treeroot(\*LFILE, \$l_name, \$l_type, \@l_param, \$count) || _error("Data Error: Violation Found: at $path$lastmesname line $count"); _error("Data Error: Not Message File: $path$lastmesname") if($l_type != $_SET || $l_name ne "leaf"); my $l_ref = {'*NAME*' => "leaf"}; tree::parse_tree(\*LFILE, $l_ref, \$count, @l_param) || _error("Data Error: Violation Found: at $path$lastmesname line $count"); ;# the following structure required: ;# leaf /-+-(message id)/-+-id: ---(id) ;# +-email:---(email) ;# +-name: ---(name) ;# +-date: ---(date) ;# +-time: ---(time) ;# +-mes: ---(message) ;# +-host: ---(remote host name) ;# +-addr: ---(remote host ip address) close LFILE; tree::element_at($l_ref, "Mes$lastmes/addr/") ne $ENV{'REMOTE_ADDR'} || tree::element_at($l_ref, "Mes$lastmes/name/") ne $name || tree::element_at($l_ref, "Mes$lastmes/email/") ne $email || tree::element_at($l_ref, "Mes$lastmes/mes/") ne $mes || _error("Request Error: 何か違うこと書いてくださいよぉ。"); ;# write message to file my $c_ref = { '*NAME*' => "leaf", "Mes$currentmes" => { '*NAME*' => "Mes$currentmes", "id" => ["id", $currentmes], "email" => ["email", $email], "name" => ["name", $name], "mes" => ["mes", $mes], "date" => ["date", $currentdate], "time" => ["time", $currenttime], "host" => ["host", $ENV{'REMOTE_HOST'}], "addr" => ["addr", $ENV{'REMOTE_ADDR'}] } }; my $currentfilename = "Th$th/message" . $currentmes . ".dat"; open(DFILE, ">" . $path . $currentfilename) || _error("File Error: Cannot Create $path$currentfilename"); flock(DFILE, LOCK_EX); tree::construct_tree(\*DFILE, $c_ref); close DFILE; chmod 0400, $path.$currentfilename; ;# update configuration my $cmes = "Th$th" . "Mes$currentmes"; $root_ref->{"files"}->{$cmes} = [$cmes, $currentfilename]; my $arraysize = $#{$targetth}; for(my $i = $arraysize; $i >= 1; $i --){ $targetth->[$i + 1] = $targetth->[$i]; } $targetth->[1] = $cmes; seek(IFILE, 0, 0); truncate(IFILE, 0); tree::construct_tree(\*IFILE, $root_ref) || _error("Internal Error:"); close IFILE; webtool::url_encode(\$decoded_data{'name'}); webtool::url_encode(\$decoded_data{'email'}); print "Location: http://$ENV{'SERVER_NAME'}$SITEROOT$CGIDIR$GCGI?name=$bid\&top=0\&cat=Th$th\&th=$th\&yname=$decoded_data{'name'}\&email=$decoded_data{'email'}\n\n"; exit(0); sub _error{ my ($errmes) = @_; webtool::url_encode(\$decoded_data{'name'}); webtool::url_encode(\$decoded_data{'email'}); webtool::url_encode(\$decoded_data{'mes'}); print "Content-type: text/html; charset=euc-jp\n\n"; print < Error

$errmes

戻る

ENDQ exit(0); } -- Copyright (C) Junro YOSHINO