#!/usr/bin/perl
#
# 1.次の構成でフォルダを作成してファイルを配置してください。
# < >内はパーミッションの相当値です。
#
# /任意のフォルダ/ ← CGIが実行できる場所
# |
# |-- /data/ <777> ← ※1
# |-- /tmp/ <777> ← ※2
# |
# |-- imgbbs.cgi <755>
# |-- imgbbs2.cgi <644>
# |-- imgbbs3.cgi <644>
# |-- imgbbs4.cgi <644>
# |-- cgi-lib217.pl <644>
# |-- jcode.pl <644>
#
# ※1,2 このフォルダは画像のWeb表示可能な場所である必要があります。
# CGI"専用"フォルダの場合(HTMLや画像が混在できない場合)には画像を記録しても表示できないので、
# 可能な位置に作成して $base_dir $base_url $tmp_dir $tmp_url を適切に設定してください。
$base_dir = './data/'; # ※1のサーバ内部のパスで設定します。
$base_url = './data/'; # ※1の仮想パス(URL式)で設定します。http://から書いてもよい。
$tmp_dir = './tmp/'; # ※2のサーバ内部のパスで設定します。
$tmp_url = './tmp/'; # ※2の仮想パス(URL式)で設定します。http://から書いてもよい。
# この4設定は、上記の配置にできる場合は変更する必要はありません。
# 2.必要最低限必要な設定をします。
# これらの設定をしたらサーバにUPし、このファイルを実行してください。
# さらに詳細な設定をしたい場合は3.以下を設定してください。
$master_key = '20040422'; # 任意の投稿を削除するための管理パスワード(マスターキー)です。''の間に半角英数字で。
$home = 'http://bees-knees.info/bidders/jaaso/index.html'; # "ホームページに戻る"リンクになるアドレスです。
$location = 'http://bees-knees.info/bidders/jaaso/bbs/imgbbs.cgi'; # このCGIファイルをアドレスで設定します。
$noSendmail = 0; # sendmailが使えないサーバは 1 に設定。【注意】1に設定すると、入力されたメールアドレスは公開されます。
# 3.投稿速報メールの設定
# $noSendmail = 1; に設定している場合はこの設定項目は無視されます。
$repo = 1; # 受け取る場合は 1 を、必要ない場合は 0 を設定します。
$mailto = 'jaaso-ogunikyo-deka@bees-knees.info'; # $repo = 1; にする場合は、投稿速報メールの送信先を設定。
$reply_to = 'jaaso-ogunikyo-deka@bees-knees.info'; # $repo = 1; にする場合は、投稿速報メールの返信先を設定。(通常は送信先と同じで良い)
$sendmail = '/usr/sbin/sendmail'; # $repo = 1; にする場合は、"sendmail"のパスを設定します。不明な場合はサーバ管理者に聞いてください。
$UUENCODE = "/usr/bin/uuencode"; # $repo = 1; にする場合は、"uuencode"のパスを設定します。不明な場合はサーバ管理者に聞いてください。
# 4.掲示板の仕様に関する設定
$bbs_title = 'JA阿蘇−小国郷 掲示板'; # ブラウザのタイトルバー(お気に入りする場合の文字列)の設定。タグは使えません。
$message = <<'EOF'; # 掲示板上部に挿入する文章。(HTML書式で) 次の行からEOFの間に書くこと。
『JA阿蘇−小国郷』専用掲示板です。
『JA阿蘇−小国郷』商品についての質問やご意見等、ご自由にお書き込みください。
※次のような内容の書き込みは、ご遠慮ください。
○個人情報、他人の誹謗・中傷など個人のプライバシーに関わる情報
○広告・営業目的の投稿など当掲示板に関係のない書き込み
書き込みいただいた後に、弊社にて内容をチェックし掲載させいただきます。
そのため、メッセージが掲載されるまでに、お時間がかかる場合があります。
なお、上記に触れるような内容があった場合、スタッフの判断により
掲載しない場合があります。ご了承ください。
EOF
$body = ''; # 画面の色や文字やリンクの色の設定。要するにタグの設定。
$max_num = 100; # 最大投稿記録件数。
$maxAttc = 4; # 1投稿に添付できるようにする画像の数。(返信投稿時は"1"に固定される)
$page = 5; # 1ページ(画面)のリスト件数。
$waku_border = 0; # 投稿枠の設定。0 で枠なし。数値により枠の太さが変わります。
$logup = 0; # 返信投稿があった記事を最新位置に移動するかどうか。1で上げる、0で移動なし。
$respsort = 1; # 返信投稿のリスト順の設定。0で昇順(古い順)、1で降順(新しい順)。
$maxResp = 6; # 1投稿で許可する返信投稿件数の上限。
$img_width = 100; # 擬似サムネイルの横サイズ(単位はピクセル)。縦横比は自動調整。
$img_ret = 200; # 擬似サムネイルの横サイズの合計がこの値以上になると2段目に配置する。(単位はピクセル)
# 例えば、$img_width = 100; の場合に画像2枚で横が200ピクセルになるので、
# $img_ret = 200; にしておけば、3枚目から2段目に表示するようになる。
$sakujo = '削除'; # 削除リンクの設定。ゴミ箱アイコンにしたい場合は、そのアイコンを次のように設定する。
# $sakujo = '';
$henshin = '返信'; # 返信リンクの文字設定。同様にアイコン化も可能。
$bar_bg_color = '#ffa500'; # タイトルバーの背景色。
$bar_text_color = '#FFFFFF'; # タイトル文字の色。
$honbun_bg_color = '#Faebd7'; # 投稿本文の背景の色。
$honbun_text_color = '#8b4513'; # 投稿本文の文字の色。
$use_AGEs = 0; # 1:年令域を利用する 0:利用しない
$use_PREFs = 0; # 1:住所域を利用する 0:利用しない
# 5.高度な設定
@AGEs = ("(〜19才)","(20〜29才)","(30〜39才)","(40〜49才)","(50〜59才)","(60才〜)");
@PREFs = ("北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", "茨城県", "栃木県",
"群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", "新潟県", "富山県", "石川県", "福井県", "山梨県",
"長野県", "岐阜県", "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県",
"和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県",
"福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県", "海外");
$style = <<'EOF'; # スタイルシートの挿入。
body {
scrollbar-darkshadow-color: #aaaaaa;
scrollbar-face-color: #888888;
scrollbar-highlight-color: #eeeeee;
scrollbar-shadow-color: #aabbcc;
scrollbar-track-color: #ffffff;
}
EOF
$cgiext = '.cgi'; # CGI実行用の拡張子が".cgi"ではない場合に設定。
$wrap = 'SOFT'; # 本文テキストエリアの改行の取扱い方法の設定。いずれも表示上は画面の大きさに合わせて自動改行されます。
# SOFT .. 枠内で折り返し、改行コード(リターンまたはエンター)を入力しなければ改行位置を加えない。
# HARD .. 枠内で折り返す位置で強制的に改行コードが挿入される。
# OFF .. 改行コード(リターンまたはエンター)を入力しなければ改行位置を加えない。
# 6.検閲モード
# 検閲モードとは?
# ・投稿後リアルタイムに表示せず、管理者が内容を確認(検閲)した後公開する方式です。
# ・画面左下に( )内に検閲待ち投稿および返信数の合計が表示されます。
# ・検閲待ちがある場合に管理リンクが現れますのでログインし、公開する投稿または返信の"検閲"をクリックすると公開されます。
$sec = 1; # 0: 通常モード(リアルタイム投稿) 1: 検閲モード(管理人のチェック後公開)
$sview = 0; # 検閲モードで、0: 未検閲があることを非表示 1: 未検閲があることを表示
$master_key2 = '20040422'; # 検閲のための管理ログインするための管理パスワード(マスターキーでも管理モードにアクセス可能)
$bar_bg_color2 = '#FF0000'; # 公開確認待ち投稿のタイトルバーの背景色。
$bar_text_color2 = '#FFFFFF'; # 公開確認待ち投稿のタイトル文字の色。
$honbun_bg_color2 = '#FFFFFF'; # 公開確認待ち投稿の投稿本文の背景の色。
$honbun_text_color2 = '#FF0000';# 公開確認待ち投稿の投稿本文の文字の色。
########################################################### 設定は以上。
require './imgbbs2.cgi';
require './imgbbs3.cgi';
require './imgbbs4.cgi';
require './cgi-lib217.pl';
require './jcode.pl';
&decCookie("$location\-2");
if ($ENV{'CONTENT_LENGTH'} > 131072) { &error2("処理エラー","処理できない大きなファイルを受信しました。-> $ENV{'CONTENT_LENGTH'} bytes","サイズが100,000バイト程度を上限に画像を送信してください。","最初からやり直してください。"); &Menu; exit; }
&ReadParse;
while (($name,$value) = each %in) {
if ($name eq "upfile") { next; }
if ($name =~ /;fix;/) { $fix = 1; }
if ($name =~ /;clear;/) { $clear = 1; }
if ($ENV{'QUERY_STRING'} ne "") {
if ($name ne "vp" && $name ne "allhits" && $name ne "ff") { next; }
}
&jcode'convert(*name,'sjis');
&jcode'convert(*value,'sjis');
if ($val !~ /(\d\d\d\d\d);/) { $val =~ s/&/&/g; }
$value =~ s/"/"/g;
$value =~ s/</g;
$value =~ s/>/>/g;
$value =~ s/\r\n/\n/g;
$value =~ s/\r/\n/g;
$value =~ s/\f//g;
$value =~ s/\t//g;
$in{$name} = $value;
}
if ($fix) { $in{'action'} = ""; }
if ($clear) {
if (!$in{'hozon'}) { &setCookie($location,,0); } # 消去
if ($in{'base'} ne "") { print "Location: $location?resp\+$in{'base'}\n\n"; }
else { print "Location: $location\n\n"; }
exit;
}
if ($ENV{'QUERY_STRING'} =~ /^imgset\+(\d+)/) { # 画像添付フォーム
&tmp_delete();
$key = $1;
&getImages($key);
if (!-e "$tmp_dir$key$cgiext") { # 重複防止用
if (open(TMP,"> $tmp_dir$key$cgiext")) { close(TMP); chmod(0666,"$tmp_dir$key$cgiext"); }
}
&headHTML();
&attcForm($maxAttc);
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} =~ /^imgset2\+(\d+)/) { # 画像添付フォーム(返信用)
$key = $1;
&getImages($key);
if (!-e "$tmp_dir$key$cgiext") { # 重複防止用
if (open(TMP,"> $tmp_dir$key$cgiext")) { close(TMP); chmod(0666,"$tmp_dir$key$cgiext"); }
}
$in{'maxtype'} = "resp";
&headHTML();
&attcForm(1);
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} =~ /^mail\+(.+)/) { # メールフォーム
$key = $1;
if ($key eq "") { &error("エラー","不明な操作を検知しました。"); }
if (!-e "$base_dir$key$cgiext") { &error("エラー","投稿が削除されていますのでメールできません。"); }
&decCookie($location); # クッキー読みこみ
&headHTML();
&mailForm();
&endHTML(1);
}
elsif ($in{'action'} eq "mail") { # メール送信
if ($in{'key'} eq "") { &error("エラー","不明な操作を検知しました。"); }
if (!-e "$base_dir$in{'key'}$cgiext") { &error("エラー","投稿が削除されましたのでメールできません。"); }
&mailsend();
&headHTML();
&okForm();
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} =~ /^tmpup\+(.+)/) { # 画像表示(投稿確認時)
$file = $1;
if (!-e "$tmp_dir$file") { &error2($!,"画像の表\示に失敗しました。"); }
&headHTML();
&imgWindow1($file);
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} =~ /^imgup\+(.+)/) { # 画像表示
$file = $1;
if (!-e "$base_dir$file") { &error2($!,"画像の表\示に失敗しました。"); }
&headHTML();
&imgWindow2($file);
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} =~ /^resp\+(.+)/) { # 返信投稿
$in{'base'} = $1;
if (!-e "$base_dir$in{'base'}$cgiext" || $in{'base'} eq "") { &error($!,"元になる投稿は削除されました。"); }
$check = (eval { opendir(DIR,$base_dir); }, $@ eq "");
if (!$check) { &error("システムエラー","致命的なエラーが発生しました。"); }
@files = readdir(DIR);
close(DIR);
@resfiles = grep(/$in{'base'}\.(\d+)$cgiext$/,@files);
$maxf = @resfiles;
if ($maxResp <= $maxf) { &error("返信できません","1投稿に返信できる数は$maxResp件までです。"); }
if ($in{'key'} eq "") {
$key = $$;
while (-e "$tmp_dir$key$cgiext") { $key ++; } # 重複を避ける
}
else { $key = $in{'key'}; }
if (!$fix) { &decCookie($location); } # 修正でない場合はクッキー読みこみ
&headHTML();
&respForm();
&endHTML(1);
}
elsif ($ENV{'QUERY_STRING'} eq "admin" && $sec) { # 管理者確認フォーム
&headHTML();
&setCookieForm();
&endHTML(1);
}
elsif ($in{'action'} eq "setc") { # 管理者モードセット
if ($in{'passwd'} eq $master_key || $in{'passwd'} eq $master_key2) { &setCookie("$location\-2","admin\t1",1); }
print "Location: $location\n\n";
}
elsif ($ENV{'QUERY_STRING'} =~ /^cfm\+(.+)/) { # 検閲
$cfm = $1;
if (!-e "$base_dir$cfm$cgiext" || $cfm eq "") { &error($!,"投稿は削除されました。"); }
$check = (eval { opendir(DIR,$base_dir); }, $@ eq "");
if (!$check) { &error("システムエラー","致命的なエラーが発生しました。"); }
@files = readdir(DIR);
close(DIR);
@base = grep(/^$cfm/,@files);
foreach $base (@base) {
if ($base =~ /(\d+)S(.+)$/) {
$f1 = $1; $f2 = $2;
rename("$base_dir$base","$base_dir$f1$f2");
}
}
print "Location: $location\n\n";
}
elsif ($ENV{'QUERY_STRING'} =~ /^del\+(.+)/) { # 削除フォーム
$del = $1;
if ($del eq "") { &error("エラー","不明な操作を検知しました。"); }
if (!-e "$base_dir$del$cgiext") { &error($!,"投稿は削除されているか、存在しません。"); }
&headHTML();
&delForm($del);
&endHTML(1);
}
elsif ($in{'action'} eq "del") { # 投稿削除
if ($in{'del'} eq "") { &error("エラー","不明な操作を検知しました。"); }
if (!-e "$base_dir$in{'del'}$cgiext") { &error($!,"投稿は削除されているか、存在しません。"); }
if ($in{'admin'} && $in{'passwd'} eq $master_key2) { ; }
elsif ($in{'passwd'} eq $master_key) { ; }
else {
if (open(DAT,"$base_dir$in{'del'}$cgiext")) {
while ($line = ) {
$line =~ s/\n//g;
($name,$value) = split(/\t/,$line,2);
if ($name eq "パスワード") { $passwd = $value; last; }
}
close(DAT);
}
else { &error($!,"投稿は削除されているか、存在しません。","または権限不良により削除できません。","管理者にご依頼ください。"); }
if ($passwd eq "") { &error("エラー","ファイルが破損している可能\性があります。","この投稿は管理者に削除を依頼してください。"); }
if ($in{'passwd'} ne $passwd) { &error("エラー","パスワードが合いません。","パスワード忘失の場合は、管理者に削除を依頼してください。"); }
}
$check = (eval { opendir(DIR,$base_dir); }, $@ eq "");
if (!$check) { &error("システムエラー","致命的なエラーが発生しました。"); }
@files = readdir(DIR);
close(DIR);
foreach $file (@files) {
next if $file eq '.';
next if $file eq '..';
if ($file =~ /($in{'del'}$cgiext)/) { push(@DEL,$1); }
if ($file =~ /($in{'del'}\.\d+\..+)/) { push(@DEL,$1); }
}
foreach $del (@DEL) {
if (!unlink("$base_dir$del")) { push(@ERR,"$! $del"); }
}
if (@ERR) { &error("削除エラー",@ERR); }
else { print "Location: $location\n\n"; exit; }
}
elsif ($in{'action'} eq "attc" || $in{'action'} eq "delete") { # 画像添付と削除
$key = $in{'key'};
if ($key eq "") { &error2("エラー","不明な操作が行われました。"); }
&getImages($key);
&setImages($in{'action'});
if ($in{'action'} eq "delete") { &getImages($key); }
if ($in{'maxtype'} eq "resp") { $maxAttc = 1; }
&headHTML();
&attcForm($maxAttc);
&endHTML(1);
}
elsif ($in{'action'} eq "check") { # 投稿前の確認
$key = $in{'key'};
if ($key eq "") { &error("エラー","不明な操作が行われました。"); }
($errors) = ®ist_check(); # 内容チェック
if (open(TMP,"> $tmp_dir$key$cgiext")) {
print TMP "$in{'パスワード'}";
close(TMP);
chmod(0666,"$tmp_dir$key$cgiext");
}
&getImages($key);
&headHTML();
&checkForm($errors);
&endHTML(1);
}
elsif ($in{'action'} eq "post") { # 投稿
if ($in{'key'} eq "") { &error("エラー","不明な処理を検出しました。"); }
$key = $in{'key'};
if (open(TMP,"$tmp_dir$key$cgiext")) {
$in{'パスワード'} = ;
close(TMP);
}
else { &error($!,"異常終了しました。","2重投稿は出来ません。"); }
if ($in{'パスワード'} eq "") { &error("エラー","不明な操作を検知しました。"); }
($errors) = ®ist_check(); # 内容チェック
if ($errors) {
&headHTML();
&postForm($errors);
&endHTML();
exit;
}
if ($in{'action'} eq "post" && $in{'base'} ne "") { &getImages($key); ®ist2(); } # 返信投稿
elsif ($in{'action'} eq "post") { &getImages($key); ®ist(); } # 投稿
print "Location: $location\n\n";
exit;
}
else {
if ($in{'key'} eq "") {
$key = $$;
while (-e "$tmp_dir$key$cgiext") { $key ++; } # 重複を避ける
}
else { $key = $in{'key'}; }
if (!$fix) { &decCookie($location); } # 修正でない場合はクッキー読みこみ
if ($sec) {
$Scount = 0;
if (opendir(DIR,$base_dir)) {
@Sfile = readdir(DIR);
close(DIR);
}
@Sfile = grep(/$cgiext$/,@Sfile);
@Sfile = grep(/(\d+)S\./,@Sfile);
$Scount = @Sfile;
}
if ($in{'base'} ne "") { &headHTML(); &respForm(); &endHTML(); }
else {
&headHTML($message);
&postForm();
&listData();
&endHTML();
}
}
exit;
#--------------------------------------------------------------
sub postForm {
local($errors) = @_;
$checked1{$in{'自動リンク'}} = " checked";
if ($in{'hozon'}) { $cookie_set = 1; }
$checked2{$cookie_set} = " checked";
$selected1{$in{'年令'}} = " selected";
$selected2{$in{'お住まい'}} = " selected";
print <<"EOF";
EOF
}
#--------------------------------------------------------------
sub respForm {
local($errors) = @_;
($number,$e) = split(/\./,$in{'base'},2);
$checked1{$in{'自動リンク'}} = " checked";
$selected1{$in{'年令'}} = " selected";
$selected2{$in{'お住まい'}} = " selected";
if ($in{'hozon'}) { $cookie_set = 1; }
$checked2{$cookie_set} = " checked";
print "
\n";
&viewFile("$in{'base'}$cgiext",0);
print <<"EOF";
EOF
}
#--------------------------------------------------------------
sub checkForm {
local($errors) = @_;
if ($in{'base'} ne "") { $aresp = "#resp"; $in{'タイトル'} = "返信投稿"; }
if ($in{'メール'} =~ /\b[-\w.]+@[-\w.]+\.[-\w]+\b/) { $uname = "$in{'なまえ'}"; }
else { $uname = $in{'なまえ'}; }
print <<"EOF";
$in{'タイトル'} |
$uname $in{'年令'} $in{'お住まい'} |
EOF
if (@attc_file) { print "\n"; }
$i = 0;
foreach $attc (@attc_file) {
$i = $img_width + $i;
$isize = -s "$tmp_dir$attc";
1 while $isize =~ s/(.*\d)(\d\d\d)/$1,$2/g;
$SNL = "";
print "$SNL | \n";
if ($i >= $img_ret) { $i = 0; print " \n"; }
}
if (@attc_file) { print " \n"; }
$VALUE = $in{'本文'};
$VALUE =~ s/\n/ \n/g;
$VALUE =~ s/ / /g;
if ($in{'自動リンク'}) {
$VALUE =~ s/"/"/g;
$VALUE =~ s/(https?|ftp|gopher|telnet|whois|news)\:([\w|\:\!\#\$\%\=\&\-\^\`\\\|\@\~\[\{\]\}\;\+\*\,\.\?\/]+)/$1\:$2<\/a>/ig;
$VALUE =~ s/\b([-\w.]+@[-\w.]+\.[-\w.]+)\b/$1<\/a>/g;
}
print <<"EOF";
$VALUE
|
投稿者のデータ > $access_data (表\示しませんが記録されます) |
|
EOF
}
#--------------------------------------------------------------
sub delForm {
local($del) = @_;
if ($del =~ /^(\d+)(.?)$/) { $caution = "
\n◇ 返信があれば全て含めて削除します。"; $number = $del; }
else {
($number,$n) = split(/\./,$del,2);
$number = "$number\-$n";
}
print <<"EOF";
EOF
}
#--------------------------------------------------------------
sub setCookieForm {
print <<"EOF";
EOF
}