#!/usr/bin/perl # プロバイダーの指示による # # --- dengon.cgi 記事閲覧 (Apache) 実施1版 --- # $ENV{'TZ'} = "JST-9"; # Set timezone @wdays = ( "日", "月", "火", "水", "木", "金", "土", "日" ); # # --- 設置状態により変える ----------------------------------- $progrm_name = "dengon.cgi"; $msg_logfile = "./dengon.log"; # 対象ファイルにより変更 $msg_tmpfile = "./dengon.tmp"; # フォルダにより変更 $msg_lockfda = "./msgboardloc"; # フォルダにより変更 $jcode_pfile = "./jcode.pl"; # フォルダにより変更 $adminiPass = "......"; # 管理者Password ←★変えるべき★ $allow_html = 1; # Allow HTML tags $max_msgs = 500; # Maximum number of messages $kj_last = 0; # (notUsed)作業用(Paging前の最終記事SeqNo):変えない $henmssg = ""; # TextAreaの初期値(変更のとき使う) # rmdir($msg_lockfda); # <--- File unlock # # --- 環境変数の取得 ----------------------------------------- # $usr_adr = $ENV{'REMOTE_ADDR'}; $usr_cook = $ENV{'HTTP_COOKIE'}; # --- クッキー情報の取得→(@cookTbl) --- @a = split(/; /, $usr_cook); # ; (space)で分解 foreach $x (@a) { if ($x =~ /^MsgL2=/) { # MsgL2=で始まっていたら $x =~ s/MsgL2=//; @cookTbl = split(/,/, $x); # $cookTbl[0]=名前,$cookTbl[1]=Key } } # # --- 管理者か? --- if ($usr_adr eq "127.0.0.1" || $cookTbl[1] eq $adminiPass) { $myself = "yes"; } else { $myself = "no"; } # # --- Japanese KANJI code ------------------------------------ # if (-f $jcode_pfile) { $jflag = true; require $jcode_pfile; $code = ord(substr("漢", 0, 1)); if ($code == 0xb4) { $ccode = "euc"; $hcode = "x-euc-jp"; } elsif ($code == 0x1b) { $ccode = "jis"; $hcode = "iso-2022-jp"; } else { $ccode = "sjis"; $hcode = "x-sjis"; } } # # --- File lock ----------------------------------------------- # foreach $i ( 1, 2, 3 ) { if (mkdir($msg_lockfda, 0755)) { last; } elsif ($i == 1) { ($mtime) = (stat($msg_lockfda))[9]; if ($mtime < time() - 600) { rmdir($msg_lockfda); } } elsif ($i < 3) { sleep(1); } else { print "Content-type: text/html\n"; print "\n"; print "メッセージリスト\n"; print "\n"; print "

メッセージリスト

\n"; print "
\n"; print "只今、メッセージ閲覧が混雑、しばらく後で再度アクセスして下さい。\n"; print "
\n"; print "\n"; exit(1); } } # # --- 記事の最大番号取得 --- $maxnumb = 0; $msgnumb[0] = 0; # メッセージ番号の変数 open(IN, $msg_logfile); # log fileは空でも必ずある while () { # log fileの第1行を読む if ($_ =~ /\e/) { # \eがあれば @msgnumb = split(/\e/, $_); # \eで分解(最初はッセージ番号) if ($msgnumb[0] > $maxnumb) {$maxnumb = $msgnumb[0];} } } close(IN); # # --- Read from 標準入力 ------------------------------------------------ # if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'}); @a = split(/&/, $query_string); foreach $x (@a) { ($name, $value) = split(/=/, $x); $value =~ tr/+/ /; # spaceは"+"で来る $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg; # URL文字列のDeCode if ($jflag) { &jcode'convert(*value, "euc"); } if ($allow_html) { # "","0",0は偽、以外は真 $value =~ s//-->/g; } else { $value =~ s/&/&/g; $value =~ s/"/"/g; $value =~ s//>/g; } if ($jflag) { # jcode.plファイルが存在すれば &jcode'convert(*value, $ccode); } if ($name eq "dspchk") {$name = $name . $value;} # (★)工夫した $FORM{$name} = $value; } } # # --- 初期表示 ------------------------------------------------------------ # if ($ARGV[0] eq "") { &hyohyoj(); rmdir($msg_lockfda); exit(0); } # # --- (SUB) タイトル一覧表示のHTML document 作成 --------------------------- # sub hyohyoj { print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "伝言板\n"; print "\n"; print "
\n"; print " 伝言板 : 読者と作者の情報交換

\n"; print " \n"; print " これは(書き込み者と主宰者)の1対1伝言板です。
\n"; print " 記事を読む場合、書き込み時のパスワードを必要とします。
\n"; print " 主宰者が返信した場合、元記事と同じパスワードで見られます。

\n"; print "
\n"; print "
\n"; # print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "

書き込みフォームは下にあり
伝言タイトル一覧 内容を表\示したいタイトルにチェックをつけてください。"; print " (最大記事番号=$maxnumb)
\n"; # # --- 記事選択フォーム --------------------- # print "\n"; print "\n"; # TARGET=\"_blank\" print "\n"; print "\n"; # - 保存記事ファイルの読込、htmlの組立 - $kjtotal = 0; open(IN, $msg_logfile); $kjheader[0] = 0; while () { if ($_ =~ /\e/) { # \eがあれば $kjtotal ++; @kjheader = split(/\e/, $_); # \eで分解 $kjban = $kjheader[0]; $kjheader[4] =~ s/\n//; $kjheader[4] =~ s/
//; # 今は不要だが,旧Logに備えて print "
\n"; print " \n"; } } close(IN); print "\n"; print "

 password:\n"; print " \n"; print "(mailアドレスなど)
$kjban:$kjheader[1]"; ## print "投稿者$kjheader[2]$kjheader[3]"; print "  "; if ($cookTbl[1] eq $adminiPass) { print " ($kjheader[4])"; } print "
\n"; # # --- (変更)削除フォーム ------------- # print "
変更・削除フォーム
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "

 \;番号:"; print "  password:"; print " "; print "    
\n"; # # --- 投稿フォーム --------------------- # print "
\n"; print "\n"; print "
\n"; print "

"; print "\n"; print "\n"; print " The story begins thirty years before when the Earnshaw family lived at Wuthering Heights consisting \n"; print "of, as well as the mother and father, Hindley, a boy of fourteen, and six-year-old Catherine, the same \n"; print "person that he had dreamt about and the mother of the present mistress. In that year, Mr Earnshaw \n"; print "travels to Liverpool where he finds a homeless, gypsy boy of about seven whom he decides to adopt as \n"; print "his son. He names him \"Heathcliff\". Hindley, who finds himself excluded from his father's affections by \n"; print "this newcomer, quickly learns to hate him but Catherine grows very attached to him. Soon Heathcliff and \n"; print "Catherine are like twins, spending hours on the moors together and hating every moment apart.\n"; print "\n"; print "

\n"; print "\n"; print "
\n"; print "
\n"; print "書き込みフォーム "; print "記入者欄は省略して下さい。特に書きたいなら書いてよい。
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; #---if ($myself eq "yes") { $tempStr = $cookTbl[1]; } print "\n"; print "\n"; print "\n"; print "
題名:\n"; print " 記入者:"; print "\n"; # $cookTbl[0] print " password:"; print " 
伝言:
\n"; # valign=\"top\" print "$FORM{'PRENUM'}"; print "$FORM{'PREKUB'}"; print "
保存可能\
=$max_msgs件
$tempStr
\n"; print "

\n"; print " トップページ\n"; print "\n"; } # #--- 記事変更フォーム --------------------------------- # sub kjhenkou { print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "記事変更\n"; print "\n"; print "記事変更フォーム "; print " 記入者欄は省略して下さい。
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
題名:\n"; print " 記入者:"; print "\n"; print " password:"; print " 
伝言:
\n"; print "
"; print "$FORM{'PRENUM'}"; print "$FORM{'PREKUB'}"; print "
\n"; print "\n"; } # # --- 記事内容表示 ------------------------------------------------------ # if ($ARGV[0] eq "etsuran") { print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "メッセージ閲覧\n"; print "\n"; print "
"; print "
記事内容表\示

\n"; # # --- 記事保存ファイルの読込、htmlの組立 --- $delkey = $FORM{'PASWRD'}; $kjdspln = 0; open(IN, $msg_logfile); $kjheader[0] = 0; while () { if ($_ =~ /\e/) { # \eがあれば @kjheader = split(/\e/, $_); # \eで分解 $kjban = $kjheader[0]; $name = "dspchk$kjban"; $dspflg = 0; if ($FORM{$name} == $kjban) { $dspflg = 1; $kjdspln ++; $kjheader[4] =~ s/\n//; if ($kjdspln > 1) { print "
\n"; } if ($delkey eq $adminiPass || $delkey eq $kjheader[4]) { print "
\n"; print "$kjban:"; print "$kjheader[1]"; ## print " 投稿者$kjheader[2]"; ## print " $kjheader[3]"; if ($kjheader[2] eq "" || $kjheader[2] =~ /省略/) { print "  "; } else { print " 投稿者:$kjheader[2]"; } if ($delkey eq $adminiPass) { print " ($kjheader[4])"; } print "\n

\n"; } else { print "
\n"; print "$kjban:"; print "$kjheader[1]"; if ($kjheader[2] eq "" || $kjheader[2] =~ /省略/) { print "  "; } else { print " 投稿者:$kjheader[2]"; } print "

\n"; print "---(パスワードが違う)--- 
\n"; $dspflg = 0; } } } else { if ($dspflg == 1) {print;} # これが無いと出ない } } close(IN); print "


\n"; print "
\n"; print " 指定された password($delkey)
\n"; print " トップページ\n"; print "\n"; rmdir($msg_lockfda); exit(0); } # # --- When 変更 -------------------------------------------------------------- # if ($ARGV[0] eq "innyou" && $FORM{'DELKUB'} eq "変更") { $wildel = $FORM{'DELBAN'}; if ($FORM{'DELKEY'} eq "") { rmdir($msg_lockfda); &errmsg("記事に設定した照合キーを入力してください。"); } $delkey = $FORM{'DELKEY'}; $nowban = 0; $delcnt = 0; $gyocnt = -1; # # --- Read log-file --- open(IN, $msg_logfile); $kjheader[0] = 0; while () { if ($_ =~ /\e/) { # \eがあれば @kjheader = split(/\e/, $_); # \eで分解 $nowban = $kjheader[0]; $nowkey = $kjheader[4]; $nowkey =~ s/\n//; if ($nowban eq $wildel) { if ($nowkey eq $delkey) { $delcnt = 1; $FORM{'DAIMEI'} = "$kjheader[1]"; } else { rmdir($msg_lockfda); &errmsg("照合キーが違います。($FORM{'DELKEY'})"); #($nowkey) } } } # --- 記事を一時保管 --- if ($nowban eq $wildel) { $gyocnt++; $_ =~ s/
|
//g; $gyomoj[$gyocnt] = $_; } else { if ($gyocnt > -1) {last;} } } close(IN); if ($delcnt == 0) { rmdir($msg_lockfda); # <--- File unlock &errmsg("(変更)番号に該当する記事がありません。"); } $FORM{'PRENUM'} = $wildel; $FORM{'PREKUB'} = "変更"; # # --- 記事の編集 --- $henmssg = ""; $iiimax = $gyocnt; if ($iiimax >= 0) { $gyomoj[$iiimax] =~ s/\n//g; # Add 少し効果ある for ($iii = 1; $iii <= $iiimax; $iii++) { $henmssg = $henmssg . $gyomoj[$iii]; } } $henmssg =~ s/\n$//; # 最後の"\n"のみ取り除く &kjhenkou(); rmdir($msg_lockfda); # <--- File unlock exit(0); } # # --- When(仮)削除 ------------------------------------------------------------------ # if ($ARGV[0] eq "innyou" && $FORM{'DELKUB'} eq "削除") { $wildel = $FORM{'DELBAN'}; $wilkey = $FORM{'DELKEY'}; # --- 削除の確認 --- print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "削除の確認\n"; print "\n"; print "\n"; print "
削除指示の確認

\n"; print "確かに削除するとき、下をクリック。 削除キャンセルなら戻って下さい。
\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "
\n"; print "記事番号 ($wildel)  password($wilkey)
"; print "
\n"; print "\n"; rmdir($msg_lockfda); # <--- File unlock ------ exit(0); } # # --- When 削除 ------------------------------------------------------------------ # if ($ARGV[0] eq "innyou" && $FORM{'DELKUB'} eq "削除する") { $wildel = $FORM{'DELBAN'}; $nowban = 0; $nowkey = ""; $delcnt = 0; # 削除該当あったか否か $delkey = $FORM{'DELKEY'}; # # --- Copy log -> tmp --- open(IN, $msg_logfile); open(OUT, "> $msg_tmpfile"); $msgnumb[0] = 0; while () { if ($_ =~ /\e/) { # \eがあれば @msgnumb = split(/\e/, $_); # \eで分解 if ($msgnumb[0] > 0) { $nowban = $msgnumb[0]; $nowkey = $msgnumb[4]; if ($nowban == $wildel) { $nowkey =~ s/\n//; # add if ($delkey eq $adminiPass || $nowkey eq $delkey) { $delcnt = 1; $delkij = $msgnumb[1]; } else { rmdir($msg_lockfda); &errmsg("削除キーが違います。($FORM{'DELKEY'})"); } } } } if ($nowban != $wildel) {print OUT;} } close(IN); close(OUT); if ($delcnt == 0) { rmdir($msg_lockfda); # <--- File unlock &errmsg("(削除)番号に該当する文書がありません。"); } # # --- Copy tmp -> log --- open(IN, $msg_tmpfile); open(OUT, "> $msg_logfile"); while () { print OUT; } close(IN); close(OUT); # # --- Print HTML -------------- print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "伝言ボード\n"; print "\n"; # #e8f8d0 print "伝言ボード

\n"; print "$wildel番「$delkij」を削除しました。 password($delkey)
\n"; print "
\n"; print "[戻る]ボタンで、3度戻る。 または下記で。
\n"; print "

 トップページ\n"; print "\n"; rmdir($msg_lockfda); # <--- File unlock exit(0); } # # --- 送信(投稿)時の処理 -------------------------------------------- # if ($ARGV[0] eq "toukou") { # --- add:アラシ対策 --- for ($iii = 0; $iii < length($FORM{'DAIMEI'}); $iii++) { $ichiji = substr($FORM{'DAIMEI'}, $iii, 1); if ($ichiji =~ /[a-zA-Z0-9\ \/:._\-]/) { } else { $alpnum = "NO"; last;} } if ($alpnum eq "NO") { } else { rmdir($msg_lockfda); &errmsg("error"); } # --- 未入力ほかチェック --- if ($FORM{'MESSAGE'} eq "") { rmdir($msg_lockfda); &errmsg("空メッセージはいけません。"); } if ($FORM{'PREKUB'} ne "変更" && " $date ($usr_adr)" eq $LastTitle) { rmdir($msg_lockfda); &errmsg("連続投稿はできません。"); } # --- クッキー情報の設定 --- $set_cook = "$FORM{'SHIMEI'},$FORM{'DELKEY'}"; $set_yuko = "Fri, 1-Jan-2020 01:01:01 GMT"; print "Set-Cookie: MsgL2=$set_cook; expires=$set_yuko\n"; # クッキー出力 # --- メッセージ番号Count-up:新規のみだが,変更でも害なし --- $maxnumb ++; if ($maxnumb < 10) {$maxnumb = "00" . $maxnumb;} elsif ($maxnumb < 100) {$maxnumb = "0" . $maxnumb;} $msgnumb[0] = $maxnumb; # --- Pre-Append messages. -------------- $henban = $FORM{'PRENUM'}; $henkub = $FORM{'PREKUB'}; $FORM{'PRENUM'} = ""; $FORM{'PREKUB'} = ""; $found = 0; open(IN, $msg_logfile); open(OUT, "> $msg_tmpfile"); if ($henkub eq "変更") { while ($logbuf = ) { if ($logbuf =~ /\e/) { # \eがあれば @kjheader = split(/\e/, $logbuf); # \eで分解 if ($kjheader[0] eq $henban) { $found = 1; $logHozon = $logbuf; # 記事ヘッダを一時記憶 } else { if ($found == 1) {$found = 2; last;} } } if ($found == 0) {print OUT $logbuf;} # 変更対象記事の直前まで出力 } if ($found == 0) { rmdir($msg_lockfda); &errmsg("対象番号の記事がありません。(削除済か?)"); } } # --- メッセージ記録の内容調整 ------------- # 下は完全でないが,3改行ぐらいならOK $FORM{'MESSAGE'} =~ s/\r\n*$//g; # ←「1個以上の\r\nで終わる」か? $FORM{'MESSAGE'} =~ s/\r*$//g; # ←「1個以上の\rで終わる」か? $FORM{'MESSAGE'} =~ s/\n*$//g; # ←「1個以上の\nで終わる」か? $FORM{'MESSAGE'} =~ s/\r/
/g; # \rはリターン、標準入力ではこうなる # --- 変更:旧タイトルと変更したメッセージをLOGファイルに記録 --- if ($henkub eq "変更") { @kjheader = split(/\e/, $logHozon); # \eで分解 print OUT "$kjheader[0]\e$FORM{'DAIMEI'}\e$FORM{'SHIMEI'}\e"; print OUT "$kjheader[3]\e$kjheader[4]"; print OUT "$FORM{'MESSAGE'}
\n"; # メッセージ # --- 新規:新メッセージをLOGファイルに記録 ---------- } else { $delkey = $FORM{'DELKEY'}; # -- 番号・タイトル・名前・日付(IPadr)・delky -- print OUT "$msgnumb[0]\e$FORM{'DAIMEI'}\e$FORM{'SHIMEI'}\e"; print OUT " $date ($usr_adr)\e$delkey\n"; # -- メッセージ -- if ($FORM{'MESSAGE'} ne "") {print OUT "$FORM{'MESSAGE'}
\n";} } # --- Append-2 messages. -------------- if ($found == 2) {print OUT $logbuf;} # 変更書込の時;次記事ヘッダ読んでるから while () { # 後続Logの転記 print OUT; } close(IN); close(OUT); # # --- Copy .tmp to .log ------------------------- open(IN, $msg_tmpfile); open(OUT, "> $msg_logfile"); $msgs = 0; while () { if ($_ =~ /\e/) { # \eがあれば if ($max_msgs != 0) { if ($msgs++ >= $max_msgs) {last;} } } print OUT; } close(IN); close(OUT); &outhtml(); rmdir($msg_lockfda); # <--- File unlock exit(0); } # # ---- (SUB) Print HTML document ----------------------------------------- # sub outhtml { # --- Print HTML(投稿後の記事のみ表示) -------------- print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "伝言ボード\n"; print "\n"; # #e8f8d0 print "伝言ボード

\n"; if ($henkub eq "変更") {print " ($henban番記事を変更しました。)\n";} else {print " (新規)書き込みを受理しました。[戻る]ボタンで、2回戻る。 または下記で。\n";} # ---add sta----------------------------------------------- print "

\n"; print "
\n"; if ($henkub eq "変更") {print "
変更した記事
\n";} else {print "
新規記事内容
\n";} # --- 記事保存ファイルの読込、htmlの組立 --- open(IN, $msg_logfile); $kjcnt = 0; while () { if ($henkub eq "") { if ($_ =~ /\e/) { # \eがあれば if ($kjcnt == 1) { last; } # Loopから出る $kjcnt ++; @kjheader = split(/\e/, $_); # \eで分解 $kjban = $kjheader[0]; print "
\n"; print "$kjban:"; print "$kjheader[1]"; if ($kjheader[2] eq "" || $kjheader[2] =~ /省略/) { print "  "; } else { print " 投稿者:$kjheader[2]"; } print "

\n"; } else { print; } } elsif ($henkub eq "変更") { if ($_ =~ /\e/) { # \eがあれば if ($kjcnt == 1) { last; } # Loopから出る @kjheader = split(/\e/, $_); # \eで分解 $kjban = $kjheader[0]; if ($kjban == $henban) { $kjcnt = 1; print "
\n"; print "$kjban:"; print "$kjheader[1]"; if ($kjheader[2] eq "" || $kjheader[2] =~ /省略/) { print "  "; } else { print " 投稿者:$kjheader[2]"; } print "

\n"; } } else { if ($kjcnt == 1) {print;} } } } close(IN); print "


\n"; print "
\n"; # ---add end----------------------------------------------- print "

 トップページ\n"; print "\n"; } # # --- (SUB) Print ERROR document --------------------------------------------- # sub errmsg { print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "エラー\n"; print "\n"; print "\n"; print "
エラー
\n"; print "
\n"; print "$_[0]\n"; # <-- 引数はここに来るらしい print "\n"; print "\n"; exit(0); } # # --- 引数エラーに備えて(開発段階のみ) ------ # rmdir($msg_lockfda); &errmsg("自己診断:CGI プログラム(msglst2.cgi)の引数エラー");