#! /usr/local/bin/perl
#################################################
#BooFormMailNeo,v1.06 / this program is free. #
# (C) BooBooClub 2013-2015 #
#################################################
#settings
$cgi = './bfmn.cgi';
$sendmail = '/path/to/sendmail';
$to = 'your@mail.address';
$cc = '';
$bcc = '';
$subject = '*';
#$subject = 'From BooFormMailNeo';
$from = '*';
$type = 'r';
$sendbutton = '送 信';
$confirmf = 'confirm.html';
$thanksf = 'thanks.html';
$errorf = 'error.html';
$tbop = 'border="1" cellspacing="0" cellpadding="3" bordercolor="#888888"';
$tdlo = 'align="left"';
$tdro = 'align="left"';
$fontn = 'size="3"';
$fontv = 'size="3"';
$head = '【';
$sepa = '】';
$rtn = 'off';
$raddr = 'on';
$chbr = 'on';
$chkblack = 'on';
$blacklist = './blacklist.txt';
$blacklistcode = '';
$htmlchrcode = '*';
#module&library
use Encode;
use Encode::Guess qw(euc-jp shiftjis 7bit-jis);
require './bmail.pl';
$cgicode = '';#(( '' / euc-jp / shiftjis / 7bit-jis / utf8 , '' = shiftjis)
$pricode = 'utf8';#( euc-jp / shiftjis / 7bit-jis / utf8 )
$inputchrcode = '';#(( '' / euc-jp / shiftjis / 7bit-jis / utf8 , '' = guess from chrptn "&")
$no_chrcode = 'deny';#(allow=set pricode as inputchrcode / deny=show error, when can't get code)
#main
&get_time;
&cgi_chrcode;
&html_chrcode;
&read_blacklist;
&read_data;
&read_ENV;
&set_html;
&return_code;
&data_order;
&check_data;
&set_header;
&action;
sub get_time{
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($sec < 10) {$sec = "0$sec";}
if ($min < 10) {$min = "0$min";}
if ($hour < 10) {$hour = "0$hour";}
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
$time = "$year/$mon/$mday $hour\:$min\:$sec";
$now = time();
}
sub cgi_chrcode{
if($cgicode eq ''){
$cgicode = 'shiftjis';
}
if($cgicode ne 'euc-jp' && $cgicode ne 'shiftjis' && $cgicode ne '7bit-jis' && $cgicode ne 'utf8'){
$cgicode = 'shiftjis';
&error($errorf,'設定エラー
(ERROR-CODE:ER-CHRCODE-01)');
}
}
sub html_chrcode{
if($htmlchrcode eq '*'){
open (HTML,"$confirmf");
$temp = join('',);
close (HTML);
$fchrcode = '';
if($temp =~ /(charset=Shift_JIS|charset="Shift_JIS")/i){
$fchrcode = 'shiftjis';
}
elsif($temp =~ /(charset=EUC-JP|charset="EUC-JP")/i){
$fchrcode = 'euc-jp';
}
elsif($temp =~ /(charset=ISO-2022-JP|charset="ISO-2022-JP")/i){
$fchrcode = '7bit-jis';
}
elsif($temp =~ /(charset=UTF-8|charset="UTF-8")/i){
$fchrcode = 'utf8';
}
else{
&error($errorf,'設定エラー
(ERROR-CODE:ER-NFCODE-01)');
}
$confirmfcode = $fchrcode;
open (HTML,"$thanksf");
$temp = join('',);
close (HTML);
$fchrcode = '';
if($temp =~ /(charset=Shift_JIS|charset="Shift_JIS")/i){
$fchrcode = 'shiftjis';
}
elsif($temp =~ /(charset=EUC-JP|charset="EUC-JP")/i){
$fchrcode = 'euc-jp';
}
elsif($temp =~ /(charset=ISO-2022-JP|charset="ISO-2022-JP")/i){
$fchrcode = '7bit-jis';
}
elsif($temp =~ /(charset=UTF-8|charset="UTF-8")/i){
$fchrcode = 'utf8';
}
else{
&error($errorf,'設定エラー
(ERROR-CODE:ER-NFCODE-02)');
}
$thanksfcode = $fchrcode;
open (HTML,"$errorf");
$temp = join('',);
close (HTML);
$fchrcode = '';
if($temp =~ /(charset=Shift_JIS|charset="Shift_JIS")/i){
$fchrcode = 'shiftjis';
}
elsif($temp =~ /(charset=EUC-JP|charset="EUC-JP")/i){
$fchrcode = 'euc-jp';
}
elsif($temp =~ /(charset=ISO-2022-JP|charset="ISO-2022-JP")/i){
$fchrcode = '7bit-jis';
}
elsif($temp =~ /(charset=UTF-8|charset="UTF-8")/i){
$fchrcode = 'utf8';
}
else{
&error($errorf,'設定エラー
(ERROR-CODE:ER-NFCODE-R03)');
}
$errorfcode = $fchrcode;
}
else{
if($htmlchrcode ne 'euc-jp' && $htmlchrcode ne 'shiftjis' && $htmlchrcode ne '7bit-jis' && $htmlchrcode ne 'utf8'){
&error($errorf,'設定エラー
(ERROR-CODE:ER-FCHRCODE-01)');
}
$fchrcode = $htmlchrcode;
$confirmfcode = $fchrcode;
$thanksfcode = $fchrcode;
$errorfcode = $fchrcode;
}
}
sub read_blacklist{
if($chkblack eq 'on'){
open (BL,"$blacklist");
$blacklist = join('',);
close (BL);
}
if($blacklistcode eq ''){
$blacklistcode = 'shiftjis';
}
if($blacklistcode ne 'euc-jp' && $blacklistcode ne 'shiftjis' && $blacklistcode ne '7bit-jis' && $blacklistcode ne 'utf8'){
$blacklistcode = 'shiftjis';
&error($errorf,'設定エラー
(ERROR-CODE:ER-LCHRCODE-01)');
}
if($blacklistcode ne $cgicode){
Encode::from_to($blacklist, $blacklistcode => $cgicode);
}
@blacklist = split(/\r\n|[\r\n]/,$blacklist);
}
sub read_data{
if ($ENV{'REQUEST_METHOD'} eq "POST"){
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else{
$buffer = $ENV{'QUERY_STRING'};
}
if (length($buffer) < 1 || length($buffer) > 1048576){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-BUFR01)');
}
if($buffer ne ''){
@pairs = split(/&/,$buffer);
$orginputchrcode = $inputchrcode;
$chrptn = '';
if($inputchrcode eq ''){
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value = &decode_readdata($value,);
if($inputchrcode eq '' && $name eq 'chrptn'){
$inputchrcode = $g_chrcode;
$chrptn = $value;
$chrptn = encode($cgicode, $chrptn);
if($chrptn ne '&'){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-NFPTN01)');
}
last;
}
}
if($chrptn eq ''){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-NFPTN02)');
}
}
if($inputchrcode eq ''){
if($no_chrcode eq 'allow'){
$inputchrcode = $pricode;
}
else{
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-ENC01)');
}
}
elsif($inputchrcode ne 'euc-jp' && $inputchrcode ne 'shiftjis' && $inputchrcode ne '7bit-jis' && $inputchrcode ne 'utf8'){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-WRONGCODE01)');
}
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/(\r\n|[\r\n])\.(\r\n|[\r\n])/$1\. $2/g;
$name =~ s/\Q(!--Sym_lt--)\E//g;
$name =~ s/\Q(!--Sym_quot--)\E/"/g;
$value =~ s/\Q(!--Sym_lt--)\E//g;
$value =~ s/\Q(!--Sym_quot--)\E/"/g;
$name = &decode_readdata($name,);
$value = &decode_readdata($value,);
if($value ne ''){
$FORM{$name} .= "\0".$value;
$xname = encode($cgicode,$name);
$xvalue = encode($cgicode,$value);
$XFORM{$xname} .= "\0".$xvalue;
}
if($valsort !~ /_\Q$name\E_/){
push(@valsort,$name);
$valsort .= '_'."$name".'_';
}
if($chkblack eq 'on'){
$tempname = encode($cgicode, $name);
$tempvalue = encode($cgicode, $value);
foreach $black(@blacklist){
if($black ne '' && ($tempname =~ /\Q$black\E/ || $tempvalue =~ /\Q$black\E/)){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-CB01)');
}
}
}
}
foreach $key(keys %FORM){
$FORM{$key} =~ s/^\0//;
}
foreach $xkey(keys %XFORM){
$XFORM{$xkey} =~ s/^\0//;
}
}
}
sub decode_readdata{
($input,$d) = @_;
if($inputchrcode eq ''){
$g_chrcode = guess_encoding($input, qw/euc-jp shiftjis 7bit-jis/);
if(ref($g_chrcode)){
$guess_result = 'success';
$uctxt = decode("Guess", $input);
$g_chrcode = guess_encoding($input)->name;
}
else{
$guess_result = 'failed';
$uctxt = decode($pricode, $input);
}
}
else{
$uctxt = decode($inputchrcode, $input);
}
return($uctxt);
}
sub read_ENV{
$remoteaddr = $ENV{'REMOTE_ADDR'};
if($remoteaddr eq ''){
$remoteaddr = 'Unknown';
}
}
sub set_html{
if($FORM{'*confirmf'} ne '' || $FORM{'*thanksf'} ne '' || $FORM{'*error'} ne ''){
if($FORM{'*confirmf'} ne ''){
$confirmf = $FORM{'*confirmf'};
}
if($FORM{'*thanksf'} ne ''){
$thanksf = $FORM{'*thanksf'};
}
if($FORM{'*errorf'} ne ''){
$errorf = $FORM{'*errorf'};
}
&html_chrcode;
}
if($confirmf !~ /\.html$/
|| $thanksf !~ /\.html$/
|| $errorf !~ /\.html$/){
&error($errorf,'設定エラーを検出しました。
(ERROR-CODE:ER-SETF01)');
}
}
sub return_code{
$space = '';
if($rtn eq 'on'){
$rtncode = "\n";
$rtncode .= "$space";
}
else{
$rtncode = '';
}
}
sub data_order{
if($FORM{'*set'} ne ''){
@set = split(/,/,$FORM{'*set'});
}
}
sub check_data{
if($FORM{'*check'} ne ''){
@check = split(/,/,$FORM{'*check'});
foreach $check(@check){
if($FORM{$check} eq '' || $FORM{$check} =~ /^\0+$/){
$nodata .= "\0".$check;
}
}
$nodata =~ s/^\0//;
$nodata =~ s/\0/
/g;
if($nodata ne ''){
$nodata = encode($cgicode, $nodata);
&error($errorf,"以下の内容が入力されていません。
$nodata");
}
}
}
sub set_header{
if ($from eq '*'){
$fb = '*';
$from = $FORM{'E-mail'};
}
if ($subject eq '*'){
$sb = '*';
$subject = $FORM{'Subject'};
}
else{
$subject = decode($cgicode, $subject);
}
}
sub action{
if ($type eq 's' || $FORM{'r'} ne ''){
&mail;
&s;
}
elsif ($type eq "r"){
&r;
}
else{
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-SETTYPE01)');
}
}
sub mail{
$to =~ s/\r\n|[\r\n]//g;
$cc =~ s/\r\n|[\r\n]//g;
$bcc =~ s/\r\n|[\r\n]//g;
$from =~ s/\r\n|[\r\n]//g;
$subject =~ s/\r\n|[\r\n]//g;
if($from eq ''){
$from = $to;
}
if($from eq ''
|| length($from) > 245
|| $from =~ /\@.*[\,\@]/
|| $from !~ /[^@]+@[\w\-]+\..+/
|| $subject eq ''
){
&error($errorf,'処理中にエラーが発生しました。
(ERROR-CODE:ER-CSD01)');
}
$subject = encode("7bit-jis", $subject);
$subject = &bmail::mime(header,$subject);
open(SEND,"|$sendmail -t");
print SEND 'From: '."$from"."\n";
print SEND 'Subject: '."$subject"."\n";
print SEND 'MIME-Version: 1.0'."\n";
print SEND 'X-Mailer: BooFormMailNeo-CGI'."\n";
print SEND 'X-Mailer-Produced-by: BooBooClub'."\n";
if($raddr eq 'on'){
print SEND 'X-RemoteAddress: '."$remoteaddr"."\n";
}
print SEND 'To: '."$to"."\n";
if($cc ne ''){
print SEND 'Cc: '."$cc"."\n";
}
if($bcc ne ''){
print SEND 'Bcc: '."$bcc"."\n";
}
print SEND 'Content-Type: text/plain; charset=iso-2022-jp'."\n\n";
&body;
$body =~ s/\r//g;
if($rtn eq 'on'){
$body =~ s/
/\n$space/g;
}
else{
$body =~ s/
/,/g;
}
#$body = decode($cgicode, $body);
$body =~ tr/[\x{ff5e}\x{2225}\x{ff0d}\x{ffe0}\x{ffe1}\x{ffe2}]/[\x{301c}\x{2016}\x{2212}\x{00a2}\x{00a3}\x{00ac}]/;
$body = encode("7bit-jis", $body);
print SEND "$body"."\n";
close SEND;
}
sub s{
$view = ''."\n";
open (HTML,"$thanksf");
@msg = ;
close (HTML);
$msg = join('',@msg);
$view = encode($thanksfcode, $view);
$msg =~ s//$view/g;
print "Content-type:text/html\n\n";
print $msg;
exit 0;
}
sub r{
&body;
$sendbutton = decode($cgicode, $sendbutton);
$view = ''."\n";
open (HTML,"$confirmf");
@msg = ;
close (HTML);
$msg = join('',@msg);
$view = encode($confirmfcode, $view);
$msg =~ s//$view/g;
print "Content-type:text/html\n\n";
print $msg;
exit 0;
}
sub body{
$head = decode($cgicode, $head);
$sepa = decode($cgicode, $sepa);
if($FORM{'*set'}){
if($FORM{'chrptn'}){
$hide .= ''."\n";
}
$hide .= ''."\n";
if($FORM{'*check'}){
$hide .= ''."\n";
}
foreach $set(@set){
$name = $set;
$value = $FORM{$set};
if($value =~ /\0/){
@value = split(/\0/,$value);
foreach $value(@value){
&setbody;
}
}
else{
&setbody;
}
}
}
else{
foreach $set (@valsort){
$name = $set;
$value = $FORM{$set};
if($value =~ /\0/){
$value =~ s/\0/
/g;
&setbody;
}
else{
&setbody;
}
}
}
}
sub setbody{
$hname = $vname = $name;
$hvalue = $vvalue = $value;
$hname =~ s/(!--Sym_lt--)/g;
$hname =~ s/>/(!--Sym_gt--)/g;
$hname =~ s/"/(!--Sym_quot--)/g;
$hvalue =~ s/(!--Sym_lt--)/g;
$hvalue =~ s/>/(!--Sym_gt--)/g;
$hvalue =~ s/"/(!--Sym_quot--)/g;
$vname =~ s/</g;
$vname =~ s/>/>/g;
$vvalue =~ s/</g;
$vvalue =~ s/>/>/g;
$vvalue =~ s/<br>/
/g;
$hide .= ''."\n";
if($set ne 'chrptn' && $set ne 'Subject' && $set ne 'r' && $set !~ /^\*/){
$body .= $head.$name.$sepa.$rtncode.$value.$rtncode."\n";
if($chbr eq 'on'){
$vvalue =~ s/\n/
\n/g;
}
$view .= ''."$vname".' | '."$vvalue".' |
'."\n";
}
}
sub error{
($errfile,$errmsg) = @_;
if($errfile ne ''){
open (ERR,"$errfile");
@html = ;
close (ERR);
$html = join('',@html);
}
if($errfile eq '' || $errorfcode eq ''){
$html = ''."\n";
$html .= 'Error'."\n";
$html .= ''."\n";
$html .= 'Error'."\n";
$html .= '
'."\n";
$html .= ''."\n";
$html .= ''."\n";
$html .= ''."\n";
}
if($errorfcode eq ''){
$errorfcode = $cgicode;
}
$errmsg = decode($cgicode, $errmsg);
$errmsg = encode($errorfcode, $errmsg);
$html =~ s//$errmsg/;
print "Content-type: text/html\n\n";
print $html;
exit 0;
}