#! /usr/local/bin/perl $mailprog = '/usr/lib/sendmail'; $head= '=?iso-2022-jp?B?'; $tail= '?='; #■■■############## #$maildate="98/09/09 12:12:12"; #@FORM{'action'}='regist'; #@FORM{'name'}='雀部陽一郎'; #@FORM{'email'}='WJ6Y-SSB@j.asahi-net.or.jp'; #@FORM{'value'}='こんにちは、みなさん #お元気ですか?'; #$host='destroy@sasabe.com'; #@FORM{'subject'}='これはタイトルです。'; #@FORM{'page'}='http://www.sasabe.com/'; #■■■############## ;# ↑このパスはプロバイダによって違うので調べて設定する ;# (これはこのスクリプトの最初の1行になければならず、それより上に空行があってもいけません。) ;# (この設定が必要ないサーバもあります。一般的な場合を想定して解説を入れています。) ;# (他に、プロバイダからアナウンスされている情報を十分理解しておいてください。) ;# ;# 簡易BBS version 7.4(フリーソフト) ;# ;# Script written by Kazu.Y ;# Created on: 96/May/02 ;# Last Modified on: 97/May/23 ;# I can be reached at: rescue@ask.or.jp ;# Scripts Found at: http://www.ask.or.jp/~rescue/cgitips/ ;# ;# <利用規定の抜粋> ;# 1.このスクリプトは自分で使うために承諾なしに自由に改造することができます。 ;# 2.改造の有無にかかわらず、このスクリプトを再配布することはできません。 ;# 3.このシステムを有償で他人に設置してあげたりする行為は無断ではできません。 ########################################################################################### # # 基本構成(初期設定はこの構成を前提に解説します) # # public_html(ホームページディレクトリ) # | # |-- cgi-bin(任意のディレクトリ) # | # |-- jcode.pl (755) # |-- minibbs.cgi (755) # |-- minibbs.dat (666) # # ・この minibbs.pl は minibbs.cgi にファイル名を変更する # ・minibbs.dat は中身が空っぽのファイルをパソコン上で作成して転送する # ・このシステムに必要な3つのファイルを同じ場所に設置する # ・( )内はパーミッッション値 # ・jcode.plは中身を全くいじらずにそのままアスキー転送する # ・jcode.plはjperlでは利用できないので注意すること # ・これら3つのファイルはアスキーモードで取り扱う(転送)すること # ########################################################################################### #----------------# # 初期設定 # #----------------# #--- 必ずあなたの環境に合わせて書き替える項目 --------------------------------------------# # 削除モード移行パスワードの設定(''内に任意のパスワードを記述する) $password = 'toshiko'; # 掲示板の名前 $title = '久美沙織オンラインファンクラブ掲示板'; # このスクリプトをURLで設定 $reload = 'http://www.sasabe.com/SF/kumi/minibbs.cgi'; # 画面に張る「戻る」リンクをURLで設定(相対設定でも可) $modoru = 'http://www.sasabe.com/SF/kumi/'; # クッキーを格納する名前を設定する # 複数の簡易BBSまたは他スクリプトで同じ名前のクッキーを使用すると弊害がある場合があります。 # 任意の英数字を設定します。クッキー機能はサーバが対応していなければ動作しませんが、 # この掲示板のその他の動作に影響はありません。複数設置する場合はこの名前を別々に付けます。 # 半角英数字であれば名前は何でも構いません。 $cookie_name = '01234567'; # ■おしらせ # # 投稿したら「他サイトからの投稿はできません」というメッセージが表示されてしまった # 場合は、このスクリプトの下の方にある「■注」を読んで対処してください。 #-----------------------------------------------------------------------------------------# #--- 必要に応じて設定する項目 ------------------------------------------------------------# # タグを使えるようにするかどうかの設定 # については入力フォームが用意してあるので、いたずらやタグの # 閉じ忘れ等による混乱を避けるためにできるだけ使えないようにしておくことをお勧めします。 # 使える:1 使えない:0 $tag = 0; # 文字色や背景などの設定(通常のタグ) # 題名と投稿者色はスクリプト内のタグを探して設定してください。 $body = ''; # 1ページに表示する件数 $def = 20; # 書き込み件数の最大登録数の設定です。この件数を超えると、古いものから削除されていきます。 # ページ処理機能が付きましたので、この件数を大きくしても一度に表示される記事数は限定されます。 # 記録されたファイルの巨大化を防止する為に、ある程度の件数で自動削除されるようにします。 $max = '100'; # 日本語コード変換ライブラリ # この jcode.pl を minibbs.cgi と違うディレクトリに設置する場合は相対的に設定すること require '../hashimoto/jcode.pl'; #require 'Macintosh HD:Desktop Folder:jcode.pl'; # 内容が書き込まれる記録ファイルのパスを設定 # この minibbs.dat を minibbs.cgi と違うディレクトリに設置する場合は相対的に設定すること #$file = 'Macintosh HD:Desktop Folder:minibbstext.dat'; #$file = "./minibbstextplusmail.dat"; $file = "./minibbstext.dat"; #■■■■■■配送先の氏名とメールアドレスを記録したファイルのパスを設定■■■■■■ #この haisousaki.dat を minibbs.cgi と違うディレクトリに設置する場合は相対的に設定すること $haisousaki = './haisousaki.dat'; $ConfigBcc = './ConfigBcc.dat'; $ConfigSubj = './ConfigSubji.dat'; $ConfigFrom = './ConfigFrom.dat'; $ConfigMemo = './ConfigMemo.dat'; # 海外サーバ等で時差が生じる場合は修正します # 海外時間に+9時間する場合 = localtime(time + 9*60*60); # 海外時間に−9時間する場合 = localtime(time - 9*60*60); # (参考)timeには1970年からの秒数が入っています ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time + 32400); # クッキーの消化設定 # 最終書き込みから 30日後 30*24*60*60 # 1日後 24*60*60 # 10時間後 10*60*60 $ENV{'TZ'} = "GMT"; # 国際標準時を取得する ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = localtime(time + 30*24*60*60); # 入力形式の設定 標準入力:post その他:get # 投稿ボタンを押して Method not implemented.. というエラーが出る場合は get で試すこと $method = 'post'; ########################################################################################### # # ・スクリプトの中身を書き替える場合は、perlやCGIやHTMLなどのそれなりの知識が必要です。 # ・設置に関する質問はチャレンジCGI専用掲示板をご利用ください。改造の質問は受けません。 # http://www2r.meshnet.or.jp/~rescue/webboard/ # ・改造についての質問はメーリングリストをご利用ください。 # http://www.ask.or.jp/~rescue/ML/ # ########################################################################################### # 上記のlocaltimeで取得した$monには0から11までの数字が入るので修正処理 $month = ($mon + 1); # 時刻を2桁に統一する処理(削除処理に関係するので書き替えないこと) if ($month < 10) { $month = "0$month"; } if ($mday < 10) { $mday = "0$mday"; } if ($sec < 10) { $sec = "0$sec"; } if ($min < 10) { $min = "0$min"; } if ($hour < 10) { $hour = "0$hour"; } # 曜日変換処理 # $wdayには0から6までの数字が入り曜日に対応している $y0="日"; $y1="月"; $y2="火"; $y3="水"; $y4="木"; $y5="金"; $y6="土"; $youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wday]; # 時刻フォーマット(削除処理に関係するので書き替えないこと) $date_now = "$month月$mday日($youbi)$hour時$min分$sec秒"; # フォーム入力されたデータを$bufferに格納する(getかpostかによって取得方法が異なる) if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } # $bufferに格納されたFORM形式のデータを取り出す @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; # 処理の都合上の処理 $value =~ s/\n//g; # 改行文字はデータの記録に影響があるので消去する if ($tag) { # 掲示板に書き込まれたくないタグを設定する(タグが使える場合に有効) if ($value =~ //i) { &error(tag); } if ($value =~ //i) { &error(tag); } if ($value =~ //i) { &error(tag); } if ($value =~ / 削除処理して通常画面へ # action=remove --> 削除記事選択画面へ # action=regist --> 記事記録処理して通常画面へ # その他 --> 通常画面へ if ($FORM{'action'} eq 'remove' && $FORM{'pwd'} eq $password) { &remove2; &remove1; exit; } elsif ($FORM{'pwd'} eq $password) { &remove1; exit; } elsif ($FORM{'action'} eq 'regist') { ®ist; } &html; sub html { #--- クッキーの取得(独自方式)-----------------------# $cookies = $ENV{'HTTP_COOKIE'}; @pairs = split(/;/,$cookies); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $name =~ s/ //g; $DUMMY{$name} = $value; } @pairs = split(/,/,$DUMMY{$cookie_name}); foreach $pair (@pairs) { ($name, $value) = split(/:/, $pair); $COOKIE{$name} = $value; } #--- 入力フォーム画面 --------------------------------# # CGIで出力されたデータをHTMLとして認識させるヘッダの出力 print "Content-type: text/html\n\n"; print "$title\n"; print "$body\n"; print "
\n"; print "
\n"; print "
$title

\n"; print "

\n"; print "\n"; print "投稿者 "; print "メールアドレス
\n"; # クッキーが機能しないサーバの場合はこの2行は削除する print "投稿者/メールアドレスをブラウザに記憶させる\n"; print "(いくつかのブラウザで有効)

\n"; print "題名

\n"; print "内容(記入された通りに記録されますので、適宜改行をいれてください。\n"; if (!$tag) { print "タグは使えません。"; } print ")
\n"; print "メール転送(書き込みは、管理人に自動的に転送されます。\n"; print ")
\n"; print "メール転送ご希望の方は掲示板にお書き込み下さい。\n"; print "
\n"; print "

\n"; print "URL(リンクを入れる場合はここにhttp://から記入)
\n"; # print "

\n"; print "

\n"; print "

\n"; print "新しい記事から表\示します。最高$max件の記事が記録され、それを超えると古い記事から削除されます。
\n"; print "1回の表\示で$def件を越える場合は、下のボタンを押すことで次画面の記事を表\示します。

\n\n"; #--- 記録記事の出力 ----------------------------------# # 記録ファイルを読み出しオープンして、配列<@lines>に格納する if (!open(DB,"$file")) { &error(0); } @lines = ; close(DB); if ($FORM{'page'} eq '') { $page = 0; } else { $page = $FORM{'page'}; } $accesses = @lines; $accesses--; $page_end = $page + $def - 1; if ($page_end > $accesses) { $page_end = $accesses; } foreach ($page .. $page_end) { # データを各変数に代入する ($date,$name,$email,$value,$subject,$hpage) = split(/\,/,$lines[$_]); $value =~ s/\0/\,/g; # ヌルコードに変換記録した半角カンマを復帰させる chop($hpage) if $hpage =~ /\n/; print "


$subject"; # メールアドレスが記録されているデータにはリンクを付ける if ($email ne '') { print " 投稿者:$name\n"; } else { print " 投稿者:$name\n"; } print " 投稿日:$date

\n"; print "

$value

\n\n"; # URLが記録されているデータにはリンクを付ける if ($hpage ne '') { print "$hpage

\n"; } print "

\n"; } #--- 改ページ処理 ------------------------------------# print "

\n"; $page_next = $page_end + 1; $i = $page + 1; $j = $page_end + 1; if ($page_end ne $accesses) { print "以上は、現在登録されている新着順$i番目から$j番目までの記事です。

\n"; print "

\n"; print "\n"; print "
\n"; } else { print "以上は、現在登録されている新着順$i番目から$j番目までの記事です。"; print "これ以下の記事はありません。\n"; } print "

[戻る]

\n"; print "

\n"; print "

パスワード:\n"; print "

\n"; # このスクリプトの著作権表示(かならず表示してください) print "


MiniBBS v7.4 is Free.

\n"; print "\n"; exit; } sub regist { #別のページからこのCGIへの投稿を排除する処理 #■注:このCGIからの投稿もできない場合は次の2行を削除してください $ref = $ENV{'HTTP_REFERER'}; if (!($ref =~ /$reload/i)) { &error(form); } # 入力されたデータのチェック if ($FORM{'name'} eq "") { &error(1); } if ($FORM{'value'} eq "") { &error(2); } if ($FORM{'email'} =~ /,/) { &error(4); } if ($FORM{'email'} ne "") { if (!($FORM{'email'} =~ /(.*)\@(.*)\.(.*)/)) { &error(3); }} if ($FORM{'subject'} eq "") { $FORM{'subject'} = '(無題)'; } if ($FORM{'page'} eq "" || $FORM{'page'} eq "http://") { $FORM{'page'} = ''; } $FORM{'name'} =~ s///g; $FORM{'subject'} =~ s//>/g; $FORM{'email'} =~ s///g; if ($FORM{'cookie'} eq "on") { # クッキーの仕様通りに真面目にフォーマット(指定時刻はGMT) # クッキーの仕様書 http://www.netscape.com/newsref/std/cookie_spec.html if ($yearg < 10) { $yearg = "0$yearg"; } if ($secg < 10) { $secg = "0$secg"; } if ($ming < 10) { $ming = "0$ming"; } if ($hourg < 10) { $hourg = "0$hourg"; } if ($mdayg < 10) { $mdayg = "0$mdayg"; } $y0="Sunday"; $y1="Monday"; $y2="Tuesday"; $y3="Wednesday"; $y4="Thursday"; $y5="Friday"; $y6="Saturday"; $youbi = ($y0,$y1,$y2,$y3,$y4,$y5,$y6) [$wdayg]; $m0="Jan"; $m1="Feb"; $m2="Mar"; $m3="Apr"; $m4="May"; $m5="Jun"; $m6="Jul"; $m7="Aug"; $m8="Sep"; $m9="Oct"; $m10="Nov"; $m11="Dec"; $month = ($m0,$m1,$m2,$m3,$m4,$m5,$m6,$m7,$m8,$m9,$m10,$m11) [$mong]; $date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT"; # 独自方式のクッキーフォーマット # # この簡易BBSでは名前とメールアドレスを保存の対象にしています。 # それぞれを独立したクッキーとしてブラウザに食べさせればとても簡単ですが、 # ブラウザがクッキーを格納できる数に制限があるため、できるだけ一つのクッキーに # 保存データをまとめて食べさせることが望まれます。そのためにここでは独自の方法で # 1つのクッキー内に複数のデータを詰め込み、クッキーの取得時にそれらを展開して利用しています。 #  # name:,email: という形式にまとめて、これを一つのクッキーとして # cookieという名前でブラウザに送信しています。 # # 独自フォーマット cookie=name:,email: $cook="name\:$FORM{'name'}\,email\:$FORM{'email'}"; print "Set-Cookie: $cookie_name=$cook; expires=$date_gmt\n"; } else { # 保存しない場合は、空のデータを保存させることで前のデータを消去する print "Set-Cookie: $cookie_name=; expires=$date_gmt\n"; } # 記入者のリモートホスト名を取得する(これは表示されずHTMLソースで閲覧できる) $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq $addr) { $host = gethostbyaddr(pack('C4',split(/\./,$host)),2) || $addr; } # 記録ファイルを読み出しオープンして、配列<@lines>に格納する if (!open(DB,"$file")) { &error(0); } @lines = ; close(DB); # 最大保持記録数の処理 $i = 0; foreach $line (@lines) { $i++; if ($i == $max) { last; } push(@new,$line); } $value = "$date_now\,$FORM{'name'}\,$FORM{'email'}\,$FORM{'value'}\,$FORM{'subject'}\,$FORM{'page'}\n"; unshift(@new,$value); &get_maildate; #■■■■■■■■これとは別にメール配信用データを作成する■■■■■■■■ #ここまでで保持している変数データは下記の通り # #$date_now #$FORM{'name'} #$FORM{'email'} #$FORM{'value'} #$host #$FORM{'subject'} #$FORM{'page'} #これらをヘッダとともにJISコードに変換、 #特にSubject,nameはMIMEエンコードしておくべき #指定受取人リストを記録したファイルの各行に対して送信する。 # 配送先アドレスを取得、配列 @atesaki に読み込む # フォーマットは下記の通り # 氏名1,pop@domain1.com crlf # 氏名2,pop@domain2.com crlf # 氏名3,pop@domain3.com crlf # @onamae には氏名を入れておく # 記録ファイルを読み出しオープンして、配列<@atesaki>に格納する if (!open(AD,"$haisousaki")) { &error(0); } #$haisousakiにはメールアドレスを記録したファイルの名称が入っている @atesaki = ; close(AD); # @atesaki の各人に対して下記の処理を行う (一人ずつ送信する) foreach(@atesaki){ ########■■■■######################################################## @temp=split(/,/); $onamae=@temp[0]; $onamaejis=$onamae; &jcode'convert (*onamaejis,'jis'); $onamaejis64=old_encode_base64 ($onamaejis); chop($onamaejis64); $recipient=@temp[1]; $kanjisubj= '【久美沙織ファンクラブ BBS 自動送信】'; &jcode'convert (*kanjisubj,'jis'); $kanjisubj= old_encode_base64($kanjisubj); chop($kanjisubj); open(MAIL,"|$mailprog -t -n") || die "Can't open $mailprog!\n"; $mail_header =""; $mail_header .="From: bbs\@sasabe.com\n"; $mail_header .="To: $recipient ($head$onamaejis64$tail)\n"; $mail_header .="Date: $maildate\n"; $mail_header .="MIME-Version: 1.0\n"; $mail_header .="X-Mailer: AutoMailer_by_DigitalKurashiki\n"; $mail_header .="Content-Transfer-Encoding: 7bit\n"; $mail_header .="Content-Type: text/plain; charset=iso-2022-jp\n"; $mail_header .="Subject: $head$kanjisubj$tail\n"; print MAIL "$mail_header\n"; $mail_body = '久美沙織オンラインファンクラブのBBS に新しい書き込みがありました。'."\n"; $mail_body .= 'http://www.sasabe.com/SF/kumi/minibbs.cgi'."\n\n"; $mail_body .= '■日 時 :'; $mail_body .= "$date_now\n"; $mail_body .= '■タイトル:'; $mail_body .= "$FORM{'subject'}\n"; $mail_body .= '■お名前 :'; $mail_body .= "$FORM{'name'}\n"; $mail_body .= '■メール :'; $mail_body .= "$FORM{'email'}\n"; $mail_body .= '■URL :'; $mail_body .= "$FORM{'page'}\n"; $mail_body .= '■内 容 :'."\n"; $mail_body .= "-------------------------------------------------------\n"; $mail_body .= "$FORM{'value'}\n"; $mail_body .= "-------------------------------------------------------\n"; $mail_body .= 'このメールは登録された方のみに自動送信されています。'."\n"; $mail_body .= '送信を希望されない方はこのメールへの返信でその旨お伝え下さい。'."\n"; &jcode'convert(*mail_body,'jis'); print MAIL "$mail_body\n"; close (MAIL); ########■■■■######################################################## } #■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ # 記録ファイルを上書きオープンして、配列<@new>を書き出す if (!open(DB,">$file")) { &error(0); } print DB @new; close(DB); # 記録処理後、再読み込みする print "Location: $reload" . '?' . "\n\n"; exit; } sub error { # &error(xx); で呼び出されたルーチンは、()内の数字が $error に代入される。 $error = $_[0]; if ($error eq "0") { $error_msg = '記録ファイルの入出力にエラーが発生しました。'; } elsif ($error eq "1") { $error_msg = '投稿者名が記入されていません。'; } elsif ($error eq "2") { $error_msg = '内容が書かれていません。または記録禁止のタグが書かれています。'; } elsif ($error eq "3") { $error_msg = 'メールアドレスが正しく入力されていません。'; } elsif ($error eq "4") { $error_msg = 'メールアドレスは複数指定できません。'; } elsif ($error eq "tag") { $error_msg = '利用ができないタグが記述されていますので投稿できません。'; } elsif ($error eq "form") { $error_msg = "投稿画面のURLが
$reload
" . '以外からの投稿はできません。'; } print "Content-type: text/html\n\n"; print "$title\n"; print "$body\n"; print "

$error_msg

\n"; print "\n"; exit; } sub remove1 { if (!open(DB,"$file")) { &error(0); } @lines = ; close(DB); print "Content-type: text/html\n\n"; print "$title\n"; print "$body\n"; print "削除モード [戻る]

\n"; print "

\n"; print "\n"; print "
";
	print "   登録日                  投稿者               タイトル              内容
\n"; foreach $line (@lines) { ($date,$name,$email,$value,$subject) = split(/\,/,$line); $value =~ s/\0/\,/g; chop($subject) if $subject =~ /\n/; $value =~ s///ig; $value =~ s//>/ig; $value =~ s/\n/./g; $value =~ s/\r/./g; $i1 = length($subject); if ($i1 > 20) { $subject = substr($subject,0,18); $subject = $subject . '..'; } elsif ($i1 < 20) { $blank = ' ' x (20 - $i1); $subject = $subject . $blank; } $i2 = length($name); if ($i2 > 20) { $name = substr($name,0,18); $name = $name . '..'; } elsif ($i2 < 20) { $blank = ' ' x (20 - $i2); $name = $name . $blank; } if (length($value) > 40) { $value = substr($value,0,40); } print ""; print "$date $name $subject $value\n"; } print "

\n"; print "

\n"; print "\n"; } sub remove2 { if (!open(DB,"$file")) { &error(0); } @lines = ; close(DB); foreach $line (@lines) { ($date,$name,$email,$value,$subject) = split(/\,/,$line); $del = 0; foreach $target (@RM) { if ($target eq $date) { $del = 1; } } if ($del == 0) { push(@new,$line); } } if (!open(DB,">$file")) { &error(0); } print DB @new; close(DB); } ########################################################## sub get_maildate { #メールのヘッダーにはこちらを使うべし。 #JSTを英語表示で取得、$maildateに結果が入る @days = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); @months = ('Jan','Feb','Mar','Apr','May','Jun','Jul', 'Aug','Sep','Oct','Nov','Dec'); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time + 32400); if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $year = $year+1900; #2000に入ってこのように修正、↓「19$year年」も「$year年」に修正 $maildate = "$days[$wday], $mday $months[$mon] $year $hour\:$min\:$sec +0900 (JST)"; $shortdate = "$year/$mon/$mday($days[$wday])$hour\:$min\:$sec (JST)"; } ########################################################## sub old_encode_base64 ($;$) { my $res = ""; my $eol = $_[1]; $eol = "\n" unless defined $eol; pos($_[0]) = 0; # ensure start at the beginning while ($_[0] =~ /(.{1,45})/gs) { $res .= substr(pack('u', $1), 1); chop($res); } $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs # fix padding at the end my $padding = (3 - length($_[0]) % 3) % 3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; # break encoded string into lines of no more than 76 characters each if (length $eol) { $res =~ s/(.{1,76})/$1$eol/g; } $res; } ####################################################################### #end_of_script