#!/usr/bin/perl ########################################################### # # 新型・簡易BBS # v.1.20 (c)2003 by CGI-RESCUE # # [履歴] ( )は更新されたファイル # v.1.00 2003/06/10 リリース # v.1.10 2003/06/12 検閲モードの追加 # v.1.11 2003/06/13 投稿枠を使う場合の歪さを是正(imgbbs.cgi,imgbbs2.cgi) # v.1.12 2003/06/17 通常投稿時の確認画面で"返信投稿"と表示されてしまう症状を修正(imgbbs.cgi) # v.1.20 2003/06/18 年令と住所域を使う使わないを選択できるようにした(imgbbs.cgi) # ########################################################### # # 簡単設置(初心者向け) # # 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 = 'http://www.kariyado-e.ed.jp/kurabu/imgbbs/data/'; # ※1の仮想パス(URL式)で設定します。http://から書いてもよい。 $tmp_dir = './tmp/'; # ※2のサーバ内部のパスで設定します。 $tmp_url = 'http://www.kariyado-e.ed.jp/kurabu/imgbbs/tmp/'; # ※2の仮想パス(URL式)で設定します。http://から書いてもよい。 # この4設定は、上記の配置にできる場合は変更する必要はありません。 # 2.必要最低限必要な設定をします。 # これらの設定をしたらサーバにUPし、このファイルを実行してください。 # さらに詳細な設定をしたい場合は3.以下を設定してください。 $master_key = 'kari152'; # 任意の投稿を削除するための管理パスワード(マスターキー)です。''の間に半角英数字で。 $home = 'http://www.kariyado-e.ed.jp/'; # "ホームページに戻る"リンクになるアドレスです。 $location = 'http://www.kariyado-e.ed.jp/kurabu/imgbbs/imgbbs.cgi'; # このCGIファイルをアドレスで設定します。 # 3.投稿速報メールの設定 $repo = 0; # 受け取る場合は 1 を、必要ない場合は 0 を設定します。 $mailto = 'あなたのメールアドレスを半角で'; # $repo = 1; にする場合は、投稿速報メールの送信先を設定。 $reply_to = 'あなたのメールアドレスを半角で'; # $repo = 1; にする場合は、投稿速報メールの返信先を設定。(通常は送信先と同じで良い) $sendmail = '/usr/sbin/sendmail'; # $repo = 1; にする場合は、"sendmail"のパスを設定します。不明な場合はサーバ管理者に聞いてください。 $UUENCODE = "/usr/bin/uuencode"; # $repo = 1; にする場合は、"uuencode"のパスを設定します。不明な場合はサーバ管理者に聞いてください。 # 4.掲示板の仕様に関する設定 $bbs_title = 'インターネットクラブ専用画像掲示板'; # ブラウザのタイトルバー(お気に入りする場合の文字列)の設定。タグは使えません。 $message = <<'EOF'; # 掲示板上部に挿入する文章。(HTML書式で) 次の行からEOFの間に書くこと。

インターネットクラブ専用画像掲示板

雁宿小学校インターネットクラブと交流のある人が使う掲示板です。
掲示板の使い方について勉強しましょう。

この画像掲示板は雁宿小学校の認証を受けないとUPできません。(制限が付いています)

EOF $body = ''; # 画面の色や文字やリンクの色の設定。要するにタグの設定。 $max_num = 100; # 最大投稿記録件数。 $maxAttc = 4; # 1投稿に添付できるようにする画像の数。(返信投稿時は"1"に固定される) $page = 10; # 1ページ(画面)のリスト件数。 $waku_border = 1; # 投稿枠の設定。0 で枠なし。数値により枠の太さが変わります。 $logup = 0; # 返信投稿があった記事を最新位置に移動するかどうか。1で上げる、0で移動なし。 $respsort = 0; # 返信投稿のリスト順の設定。0で昇順(古い順)、1で降順(新しい順)。 $maxResp = 10; # 1投稿で許可する返信投稿件数の上限。 $img_width = 100; # 擬似サムネイルの横サイズ(単位はピクセル)。縦横比は自動調整。 $img_ret = 200; # 擬似サムネイルの横サイズの合計がこの値以上になると2段目に配置する。(単位はピクセル) # 例えば、$img_width = 100; の場合に画像2枚で横が200ピクセルになるので、 # $img_ret = 200; にしておけば、3枚目から2段目に表示するようになる。 $sakujo = '削除'; # 削除リンクの設定。ゴミ箱アイコンにしたい場合は、そのアイコンを次のように設定する。 # $sakujo = '削除'; $henshin = '返信'; # 返信リンクの文字設定。同様にアイコン化も可能。 $bar_bg_color = '#888888'; # タイトルバーの背景色。 $bar_text_color = '#FFFFFF'; # タイトル文字の色。 $honbun_bg_color = '#FFFFFF'; # 投稿本文の背景の色。 $honbun_text_color = '#555588'; # 投稿本文の文字の色。 $use_AGEs = 1; # 1:年令域を利用する 0:利用しない $use_PREFs = 1; # 1:住所域を利用する 0:利用しない # 5.高度な設定 @AGEs = ("(1年生)","(2年生)","(3年生)","(4年生)","(5年生)","(6年生)"); @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 = 1; # 検閲モードで、0: 未検閲があることを非表示 1: 未検閲があることを表示 $master_key2 = 'kame0040'; # 検閲のための管理ログインするための管理パスワード(マスターキーでも管理モードにアクセス可能) $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/\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(); &imgWindow("$tmp_dir$file"); &endHTML(1); } elsif ($ENV{'QUERY_STRING'} =~ /^imgup\+(.+)/) { # 画像表示 $file = $1; if (!-e "$base_dir$file") { &error2($!,"画像の表\示に失敗しました。"); } &headHTML(); &imgWindow("$base_dir$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";
\n"; if ($errors) { print "\n"; } print <<"EOF";
なまえ EOF if ($use_AGEs) { print <<"EOF"; EOF } if ($use_PREFs) { print <<"EOF"; EOF } print <<"EOF";
メールアドレス
タイトル
本文  アドレスをリンクする  〔 画像の添付と削除
パスワード    EOF if ($fix || $cookie_set) { print <<"EOF"; EOF } print " なまえ等を保存"; print "
$errors

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";
\n"; if ($errors) { print "\n"; } print <<"EOF";

返信投稿

なまえ EOF if ($use_AGEs) { print <<"EOF"; EOF } if ($use_PREFs) { print <<"EOF"; EOF } print <<"EOF";
メールアドレス
本文  アドレスをリンクする  〔 画像の添付と削除
パスワード    EOF if ($fix || $cookie_set) { print <<"EOF"; EOF } print " なまえ等を保存"; print "
$errors

掲示板に戻る      ホームページに戻る

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 = "\"$isizeバイト\""; print "\n"; if ($i >= $img_ret) { $i = 0; print "\n"; } } if (@attc_file) { print "
$SNL
\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 if ($errors) { print "\n"; } else { print "\n"; } print <<"EOF";
$errors
EOF } #-------------------------------------------------------------- sub delForm { local($del) = @_; if ($del =~ /^(\d+)(.?)$/) { $caution = "
\n◇ 返信があれば全て含めて削除します。"; $number = $del; } else { ($number,$n) = split(/\./,$del,2); $number = "$number\-$n"; } print <<"EOF";

投稿の削除

◇ No.$number を削除しますので、投稿したときに設定したパスワードをどうぞ。 $caution

パスワード


掲示板に戻る      ホームページに戻る

EOF } #-------------------------------------------------------------- sub setCookieForm { print <<"EOF";

管理者モードセット

◇ 管理者認識IDをブラウザにセットします。IDはブラウザを閉じるまで有効となります。

◇ 共用している場合は安全のため、作業終了後にはブラウザを閉じてください。

◇ クッキーを遮断しているブラウザやPCからのセットは出来ません。

管理パスワード


掲示板に戻る      ホームページに戻る

EOF }