#!/usr/local/bin/perl # ###################################################################### ### ### ### CGI簡易掲示版 T-Note Ver.4.05 ### [1/1] 本体 (tnote.cgi) ### (c) 1996-2005 Takahiro Nishida ### http://www.mytools.net/ ### ### ###################################################################### # ### 変数設定部 (詳細は上記ページをご覧下さい) ###################### # データファイルの入っているディレクトリ $basedir = "."; # CGIプログラムの拡張子 $ext = "cgi"; # 文字コード $code = "sjis"; # フォームの送信方法 $method = "post"; # 管理パスワード $password = "TNote405"; # 管理者メールアドレス $admin_email = "your\@email.address"; # 文章の最大長(全角での文字数) $max_words = 3000; ### 変数設定部 (ここまで)########################################### # 標準時とのズレ(時間) $time_fix = 0; # 標準のBOOK名 $default_book = ""; # クッキーの有効期限(日) $cookie_lifetime = 30; # スクリプトの名前 $script_name = "tnote"; # クッキーのPATHの設定/非設定 $enable_cookiepath = 1; # 更新日を見るためのキーワード $update_keyword = "update"; # スパム扱いするキーワード @spamwords = ("url.com", "萌", "エッチ", "女子高生", "セフレ", "奥様", "シークレット", "エロ", "ギャル", "放題", "artemisweb", "freexy", "巨乳", "ぴちぴち", "マ○", "芸能人"); # スパムエラー時のメッセージ(0-14:適当なメッセージ、15:スパム専用メッセージ、詳しくはerror関数を参照) $SPAM_ERROR_ID = 3; # jcode.plの位置 require './jcode.pl'; ##### 発言表示のテンプレート # "#xxx#" のところに文字が埋め込まれる(xxxの種類は以下の通り) # ID ... 発言ID # HEAD ... 発言タイトル # NAME ... 名前 # MAIL ... メールアドレス # URL ... ページのURL # CONT ... 発言内容 # REPLY ... 返信フォーム、返信文 sub article_template{ " No.#ID# (#DATE#)   #HEAD#
Name:#NAME##HOST#
Email:
#MAIL#
URL:#URL#

#CONT#

#REPLY#


"; } ##### 標準の配色、背景画像 $defcol = "#333333,#FFFFFF,#0000BB,#000099,#FF0000,#CC00FF,#FF5555,#6699FF,#FF3333,#003300,"; $lockfile = "$basedir/lockdir/tn.lock"; $pwdfile = "$basedir/tnpwd.$ext"; $verno = '4.05'; &main; sub main{ &lock; &init_variables; &check_input; &open_datafiles; &exec_admin; &get_configs; &add_newdata; &add_newreply; &cut_log; &update_datafiles; &deal_cookie; &select_datas; &cut_data; &show_html; &unlock; } ########## 変数の初期化 sub init_variables{ local($addr); ### ホスト名 $addr = $ENV{'REMOTE_ADDR'}; $host = $ENV{'REMOTE_HOST'}; ($addr eq $host) && ($host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2)); $host = $host || $addr || ""; ### 時刻(秒、時間) $date_now = &get_time(time); } ########## 入力の受け取り、チェック sub check_input{ local($buffer, $vn, $pair, @pairs); if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } ### 各ノートの更新日表示 ($update_keyword) && ($buffer eq $update_keyword) && (&show_update); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($vn, $value) = split(/=/, $pair); $F{$vn} .= $value; } $book = $F{'book'} || $default_book || &error(3); $name = &decode($F{'name'}); $mail = &decode($F{'mail'}); $url = &decode($F{'url'}); $head = &decode($F{'head'}); $cont = &decode($F{'cont'}); $pid = $F{'pid'}; $find = &decode($F{'find'}); $page = $F{'page'}; $cook = $F{'cook'}; $rcont= $F{'rcont'}; $pwd = $F{'pwd'}; $ppr = $F{'ppr'}; $type = $F{'type'} || 'and'; ($book =~ /^\w+$/) || &error(4); (!$mail) || ($mail =~ /^[\w\-\+\.]+\@[\w\-\+\.]+$/) || &error(5); (!$url) || ($url =~ /^http:\/\/+./) || &error(6); (!$pid) || ($pid =~ /^\d+$/) || &error(7); ### スパムキーワードチェック &check_spamword($head) && &error($SPAM_ERROR_ID); &check_spamword($cont) && &error($SPAM_ERROR_ID); } ########## 更新日の表示 sub show_update{ local($htmlbuf, $file, $book_name, $datafile, $book_update, $book_title); opendir(DIR, $basedir) || &error(14, "ディレクトリが開けません"); $htmlbuf = "Content-type: text/html\n\n"; $htmlbuf .= "

更新日一覧

\n"; $htmlbuf .= "\n"; $htmlbuf .= "\n"; while($file = readdir(DIR)){ ($file =~ /^(\w+)\.txt$/) || next; $book_name = $1; $datafile = "$basedir/$file"; &openfile($datafile, *datas); ($datas[3] =~ /^\d+\n$/) || next; @t = stat($datafile); $book_update = &get_time($t[9]); $book_title = (split("\t", $datas[0]))[1]; $htmlbuf .= "\n"; $htmlbuf .= "\n"; $htmlbuf .= "\n"; } $htmlbuf .= "
タイトルBOOK名更新日付
$book_title$book_name$book_update
\n"; closedir(DIR); print $htmlbuf; &unlock; exit; } ########## ファイルのオープン sub open_datafiles{ $datafile = "$basedir/$book.txt"; &openfile($datafile, *datas); ### 初めての場合 if($datas[0] !~ /\t/){ &init_config; } ### Ver.3 -> Ver.4 elsif($datas[3] !~ /^\d+\n$/){ &ver3to4; } } ########## アップグレード sub ver3to4{ local($newline, $tid, $ttime, $tname, $tmail, $turl, $tcont, $thost, $thead); $tid = 1; for (4..$#datas){ if($datas[$_] =~ /^\n$/){ $newline = "$tid\tD\t\n"; } else{ ($ttime, $tname, $tmail, $turl, $tcont, $thost, $thead) = split("\t", $datas[$_]); $newline = "$tid\t\t$ttime\t$tname\t$thost\t$tmail\t$turl\t$thead\t$tcont\t\t\n"; } $datas[$_] = $newline; $tid++; } # コンフィグ行初期化(行数は一緒なので) &init_config($tid-1); $upf_data = 1; } ########## 管理 sub exec_admin{ ($pwd) || return; local($pwdmatch, $i, $delpos); local($id, $pid, $date, $name, $host, $mail, $url, $head, $cont, $repline); # 入力チェック $delid = $F{'delid'}; $delre = $F{'delre'}; (!$delid) || ($delid =~ /^\d+/) || &error(9); (!$delre) || ($delre =~ /^\d+/) || &error(9); # マッチング用にハッシュを作る &openfile($pwdfile, *pwds); foreach(@pwds){ ($cbook, $cid, $cpwd) = split("\t"); $UP{"$cbook\t$cid"} = $cpwd; } # システム管理者又はbook管理者なら無条件 if(($pwd eq $password) || ($UP{"$book\tADM"} eq $pwd)){ $pwdmatch = 1; } ### この時点で更新フラグを立てとく(安全策) $upf_data = 1; ### 削除 if($F{'del'}){ # 親がないことはあり得ない ($delid) || &error(9); # 対応するハッシュキー $delkey = ($delre) ? "$book\t$delid-$delre" : "$book\t$delid"; # 権限チェック ($pwdmatch) || ($UP{$delkey} eq $pwd) || &error(8); ### 消す for(4..$#datas){ if($datas[$_] =~ /^$delid\t\d*\t/){ # Replyの削除 if($delre){ ($id, $pid, $date, $name, $host, $mail, $url, $head, $cont, $repline) = split("\t", $datas[$_]); @replys = split("", $repline); $repline = ""; foreach $brep(@replys){ ($brep =~ /<>$delre$/) || ($repline .= $brep . ""); } $datas[$_] = "$id\t$pid\t$date\t$name\t$host\t$mail\t$url\t$head\t$cont\t$repline\t\n"; } # 発言自体の削除 else{ $datas[$_] = "$delid\tD\t\n"; } } } # 対応する削除キーを削除 delete($UP{$delkey}); # 更新用に配列に納め直す undef @pwds; while(($key, $value) = each %UP){ push(@pwds, "$key\t$value\t\n"); } # 更新フラグ $upf_pwd = 1; } ### 管理 if($F{'admin'}){ $admmode = 1; ($pwdmatch) || &error(8); &update_config; } } ########## 設定の変更 sub update_config{ ($F{'fix'}) || return; local($atitle, $ahead, $acom, $aback, $asdef, $acol, $abpwd); local(@sws, $i, $delpos); $atitle = &decode($F{'atitle'}); $ahead = &decode($F{'ahead'}, 1); $acom = &decode($F{'acom'}, 1); $aback = &decode($F{'aback'}); $asdef = $F{'asdef'}; $acol = &decode($F{'acol'}); $abgimg = &decode($F{'abgimg'}); $abpwd = &decode($F{'abpwd'}); ($asdef =~ /^\d+$/) || &error(11, '発言単位'); ($F{'alg'} =~ /\d+$/) || &error(11, '最大ログ件数'); ($F{'colreset'}) && ($acol = $defcol); $datas[0] = "$ahead\t$atitle\t$acom\t$aback\t\n"; $datas[1] = "$acol$abgimg,\n"; $datas[2] = "$asdef,"; @sws = ('afm', 'apv', 'app', 'asc', 'ahd', 'ahs', 'arp', 'asd', 'aan', 'alg'); foreach(@sws){ $datas[2] .= $F{$_} . ","; } $datas[2] .= "\n"; $upf_data = 1; } ########## コンフィグ行の初期化 sub init_config{ local($bid) = @_; ($bid) || ($bid = "0"); $datas[0] = "

見だしはここ

\tタイトル\t説明文をここに書いて下さい\thttp://www.your/homepage/\t\n"; $datas[1] = "$defcol,,\n"; $datas[2] = "20,1,1,1,1,1,1,1,1,1,0,\n"; $datas[3] = "$bid\n"; $upf_data = 1; } ########## 設定を取得 sub get_configs{ @configs = @datas[0..3]; ### タイトル文字列など ($headline, $title, $comment, $backurl) = split("\t", $configs[0]); ### 配色 ($ctext, $cbody, $clink, $cvlnk, $calnk, $cname, $cnumb, $chead, $crnam, $crtxt, $bgimg) = split(",", $configs[1]); ### 各種スイッチ ($show_scale, $sw_form, $sw_preview, $sw_ppr, $sw_search, $sw_head, $sw_host, $sw_reply, $sw_showdel, $sw_anobar, $sw_log) = split(",", $configs[2]); } ########## 新規発言の追加 sub add_newdata{ ($name && $cont && !$F{'search'}) || return; local($newid); # 削除パスワードが必須なのにない場合はエラー ($sw_ppr == 2) && (!$ppr) && &error(14); # 発言番号 $newid = ++$datas[3]; $datas[3] .= "\n"; # 新規行 $newline = "$newid\t$pid\t$date_now\t$name\t$host\t$mail\t$url\t$head\t$cont\t\t\n"; # プレビューだったらここで終了 ($F{'chk'}) && return; # 新規行の格納 push(@datas, $newline); $upf_data = 1; # 削除パスワードが入力されていたら追加 if($ppr){ $newpwds[0] = "$book\t$newid\t$ppr\t\n"; $adf_pwd = 1; } } ########## 新規コメントの追加 sub add_newreply{ ($F{'reply'}) || return; local($tmp, $pwdmatch); $repid = $F{'repid'}; $repname = &decode($F{'repname'}); $repcont = &decode($F{'repcont'}); &check_spamword($repname.$repcont) && &error($SPAM_ERROR_ID); if($sw_reply == 2){ ($pwd) || &error(8); # マッチング用にハッシュを作る &openfile($pwdfile, *pwds); foreach(@pwds){ ($cbook, $cid, $cpwd) = split("\t"); $UP{"$cbook\t$cid"} = $cpwd; } # システム管理者かbook管理者じゃなきゃダメ ($password eq $pwd) || ($UP{"$book\tADM"} eq $pwd) || &error(8); } else{ # 削除パスワードが必須なのに無い場合はエラー ($sw_ppr == 2) && (!$ppr) && &error(14); } ($repid > 0) || &error(7); ($repname && $repcont) || &error(12); for(4..$#datas){ if($datas[$_] =~ /^$repid\t(.+)\t/){ ($1 eq "D") && &error(7); $rno = ($datas[$_] =~ /<>(\d+)\t\n/) ? $1 + 1 : 1; $repline = "$date_now<>$repname<>$repcont<>$rno"; $datas[$_] =~ s/\t\n/$repline\t\n/; $upf_data = 1; } } ($upf_data) || &error(7); # 削除パスワードが入力されていたら追加 if($ppr){ $newpwds[0] = "$book\t$repid-$rno\t$ppr\t\n"; $adf_pwd = 1; } } ########## ログの削除 sub cut_log{ # ログ数が指定されていなかったら終了 ($sw_log > 0) || return; # ログ数が規定を超えてなければ終了 (@datas > $sw_log + 4) || return; # カット splice(@datas, 4, @datas - 4 - $sw_log); # 更新フラグ $upf_data = 1; } ########## データファイルの更新 sub update_datafiles{ ($upf_data) && &updatefile($datafile, *datas); ($upf_pwd) && &updatefile($pwdfile, *pwds); ($adf_pwd) && &updatefile($pwdfile, *newpwds, 1); } ########## データの抽出 sub select_datas{ # コンフィグ行を削り落とす splice(@datas, 0, 4); # 全件数 $hitno = $allno = @datas; # 新しい順にするためひっくり返す @datas = reverse(@datas); # 検索でない場合は終了 ($F{'search'}) || return; # 検索文字列が指定されていなかったらヒット無しにして終了 if($find eq ''){ @datas = (); $hitno = 0; return; } local($bid, $bpid, $bdate, $bname, $bhost, $bmail, $burl, $bhead, $bcont, $breps); local(@hits, $efind, $match, $pattern); # 検索文字の処理 $efind = $find; $efind =~ s/ / /g; $efind =~ s/(\W)/\\$1/g; # 空白で分割 @efinds = split(/\\\s+/, $efind); ### 検索 foreach(@datas){ ($bid, $bpid, $bdate, $bname, $bhost, $bmail, $burl, $bhead, $bcont, $breps) = split("\t"); $str = "($bid)\t$bid\t$bname\t$bmail\t$burl\t$bhead\t$bcont\t$breps"; $match = 0; # マッチング foreach $pattern(@efinds){ if($str =~ /$pattern/){ $match++; } } ### and検索の場合、マッチ数が文字数に一致しなければダメ ($type eq 'and') && ($match < @efinds) && ($match = 0); ($match != 0) && push(@hits, "$bid\t$bpid\t$bdate\t$bname\t$bhost\t$bmail\t$burl\t$bhead\t$bcont\t$breps\t\n"); } @datas = @hits; $hitno = @datas; ($hitno) || ($html_nomatch = "

ヒットしませんでした。
条件を変えて再度検索してください。


"); } ########## データを表示単位で切り抜く sub cut_data{ local($t, $f); ### 範囲指定が変だったら一ページ目を表示 $page = int($page); $allpage = int(($hitno-1) / $show_scale) + 1; ($page > 0) && ($page <= $allpage) || ($page = 1); ### 表示範囲の特定 $t = $page * $show_scale; $f = $t - $show_scale + 1; ($t < $hitno) ? ($next = $page + 1) : ($t = $hitno); ($f > 1) && ($prev = $page - 1); ### 前後を切り取る unshift(@datas, "dmy"); @datas = splice(@datas, $f, $show_scale); } ########## ページリンク sub html_pagelink{ local($htmlbuf, $no_f, $no_t, $linkcgi); $htmlbuf = ""; ### 通常モード if(!$F{'search'}){ $linkcgi = "$script_name.$ext?book=$book"; ($no_f) = $datas[0] =~ m|^(\d+)\t|; ($no_t) = $datas[$#datas] =~ m|^(\d+)\t|; # 全保存件数 $htmlbuf .= "全$allno件 "; # 表示範囲 $htmlbuf .= "【No.$no_f-$no_t】 / "; # 最新xx件 $htmlbuf .= "最新$show_scale件 "; } ### 検索モード else{ $linkcgi = "$script_name.$ext?book=$book&search=true&find=$F{'find'}&type=$type"; $htmlbuf .= "文字列:"; $htmlbuf .= $find || "----"; $htmlbuf .= " ($type) "; $htmlbuf .= "/ ヒット数:"; $htmlbuf .= $hitno || "--"; $htmlbuf .= "件 "; } ### 前のxx件 $htmlbuf .= ($prev) ? "/ ↑$show_scale件 " : "/ 先頭です "; ### 後のxx件 $htmlbuf .= ($next) ? "/ $show_scale件↓" : "/ 末尾です"; ### 検索窓 if($sw_search){ $htmlbuf .= ($F{'search'}) ? "/ 通常モード " : "/ 検索モード "; } ### 新規書き込み if(!$sw_form && !$F{'search'}){ $htmlbuf .= "/ 発言する "; } $htmlbuf .= "
"; $htmlbuf; } ########## 画面表示 sub show_html{ local($htmlbuf); $pagelink = &html_pagelink; $htmlbuf = &html_header; $htmlbuf .= &html_form_admin if ($admmode); $htmlbuf .= &html_form_new if (!$F{'search'} && $sw_form && !$admmode); # 発言欄が上の場合 $htmlbuf .= &html_preview if ($F{'chk'} && $name && $cont); $htmlbuf .= &html_search if ($F{'search'}); $htmlbuf .= $pagelink . $html_nomatch; $htmlbuf .= &html_articles; $htmlbuf .= $pagelink; $htmlbuf .= &html_form_new if (!$F{'search'} && !$sw_form && !$admmode); # 発言欄が下の場合 $htmlbuf .= &html_form_delete; $htmlbuf .= &html_footer; print $cookieline; print "Content-type: text/html\n"; print "\n"; print $htmlbuf; } ########## ヘッダ sub html_header{ if($sw_anobar){ $cssbuf = " "; } " $title $cssbuf [戻る]

$headline

$comment


"; } ########## フッタ sub html_footer{ "
"; } ########## 入力フォーム sub html_form_new{ local($html_pphrase, $html_preview, $html_head); local($contbuf, $headbuf); ### プレビューの場合元の情報を載せる if($F{'chk'}){ ### タグを改行に逆変換 $contbuf = $cont; $contbuf =~ s/
/\n/g; $contbuf =~ s/

/\n\n/g; $headbuf = $head; } ### スイッチ処理 # 削除キー入力欄 if($sw_ppr){ $pprcase = ($sw_ppr == 2) ? "(必須)" : "書かない場合発言の削除ができません"; $html_pphrase = " 削除キー:   発言削除用のパスワード。$pprcase "; } # プレビューボタン $html_submitlabel = "発言"; if($sw_preview == 1){ $html_preview = ""; } # 常にプレビュー elsif($sw_preview == 2){ $html_submitlabel = "プレビュー"; $html_prehidden = "\n"; } # 発言タイトル入力欄 if($sw_head){ $html_head = " 題名 "; } ($cook eq ".") || ($cookbuf = "CHECKED"); "

$html_prehidden $html_head
名前
メール
URL
 
※ 名前と内容は必須です。文章は全角$max_words文字まで。タグは使えません。
  $html_pphrase
$html_preview 名前、メール、URL、削除キーをブラウザに記憶させる
$html_search

"; } ########## 発言表示 sub html_articles{ local($htmlbuf, %C, $arttp, $html_line, $host, $replys); ### 発言の表示 $arttp = &article_template; foreach(@datas){ undef %C; ($C{'ID'}, $C{'PID'}, $C{'DATE'}, $C{'NAME'}, $host, $C{'MAIL'}, $C{'URL'}, $C{'HEAD'}, $C{'CONT'}, $repline) = split("\t"); # 件名か本文にスパムキーワードが含まれていた場合 if (&check_spamword($C{'NAME'}.$C{'URL'}.$C{'MAIL'}.$C{'CONT'}.$C{'HEAD'})) { if($sw_showdel) { $htmlbuf .= "No.$C{'ID'} (SPAM)
"; } next; } # 削除されていた場合 if($C{'PID'} eq "D"){ ($sw_showdel) && ($htmlbuf .= "No.$C{'ID'} (削除済)
"); next; } # ホスト表示 $C{'HOST'} = ($sw_host && $host) ? "  ($host)" : ""; ### コメントメッセージ if($sw_reply){ $C{'REPLY'} .= "
"; # 今までの返事を表示 @replys = split("", $repline); foreach(@replys){ ($rtime, $rname, $rcont, $rno) = split("<>"); # スパムワードが含まれていた場合 if(&check_spamword($rname.$rcont)) { if($sw_showdel) { $C{'REPLY'} .= " [Re.$rno] (SPAM)
"; } } else { $C{'REPLY'} .= " [Re.$rno] $rname($rtime)> $rcont 
"; } } $C{'REPLY'} .= "
"; } ### コメント用フォーム(一般用) if($sw_reply == 1){ $C{'REPLY'} .= "
返信: 名前  ひとこと  削除キー 
"; } ### 発言タイトル ($sw_head) || ($C{'HEAD'} = ""); # テンプレート取得→置換 $html_line = $arttp; $html_line =~ s/#(\w+)#/$C{$1}/g; $htmlbuf .= $html_line; } $htmlbuf; } ########## 検索窓 sub html_search{ local($type_or, $type_and); ($type eq 'or') ? ($type_or = "CHECKED") : ($type_and = "CHECKED"); unless($find){ @datas = (); $html_nomatch = "

検索文字列を入力して下さい。


"; } "
記事検索:    AND  OR 

"; } ########## プレビュー sub html_preview{ local($artbuf, $host, %C); ($C{'ID'}, $C{'PID'}, $C{'DATE'}, $C{'NAME'}, $host, $C{'MAIL'}, $C{'URL'}, $C{'HEAD'}, $C{'CONT'}) = split("\t", $newline); ($sw_host) && ($C{'HOST'} = "  ($host)"); $artbuf = &article_template; $artbuf =~ s/#(\w+)#/$C{$1}/g; ### プレビューの場合元の情報を載せる ### タグを改行に逆変換 $contbuf = $C{'CONT'}; $contbuf =~ s/
/\n/g; $contbuf =~ s/

/\n\n/g; $headbuf = $head; "

◆ プレビューモード
$artbuf
これでよろしければボタンを押してください →

"; } ########## 削除フォーム sub html_form_delete{ local($htmlbuf); $htmlbuf .= "
発言削除:No. -Re.    削除キー又はパスワード:
"; if($sw_reply == 2){ $htmlbuf .= " 返信: 発言No.  名前  ひとこと 
"; } $htmlbuf .= "

"; $htmlbuf; } ########## 管理フォーム sub html_form_admin{ local($bgc, $fnc); local($fm1, $fm0, $pv1, $pv0, $pp1, $pp0, $sc1, $sc0); local($hd1, $hd0, $hs1, $hs0, $rp1, $rp0, $rp2, $sd1, $sd0); $bgc = "#6666FF"; $fnc = "#FFFFFF"; ### スイッチ処理 ($sw_form) ? ($fm1 = "CHECKED") : ($fm0 = "CHECKED"); ($sw_preview) ? ($pv1 = "CHECKED") : ($pv0 = "CHECKED"); ($sw_ppr) ? ($pp1 = "CHECKED") : ($pp0 = "CHECKED"); ($sw_search) ? ($sc1 = "CHECKED") : ($sc0 = "CHECKED"); ($sw_head) ? ($hd1 = "CHECKED") : ($hd0 = "CHECKED"); ($sw_host) ? ($hs1 = "CHECKED") : ($hs0 = "CHECKED"); ($sw_reply) ? ($rp1 = "CHECKED") : ($rp0 = "CHECKED"); ($sw_showdel) ? ($sd1 = "CHECKED") : ($sd0 = "CHECKED"); ($sw_anobar) ? ($an1 = "CHECKED") : ($an0 = "CHECKED"); if($sw_reply == 2){ $rp1 = ""; $rp2 = "CHECKED"; } if($sw_ppr == 2){ $pp1 = ""; $pp2 = "CHECKED"; } if($sw_preview == 2){ $pv1 = ""; $pv2 = "CHECKED"; } ### タグ殺し $ktitle = &killtag($title); $kheadline = &killtag($headline); $kcomment = &killtag($comment); "
◆ T-Note $verno 管理用フォーム ◆
※ 当管理ページは IE4以上またはNN3以上をお使いください。
タイトル
見出し
説明文
戻り先
表\示単位 発言ずつ表\示
配色 全体:文字  背景 
リンク:通常  訪問済  クリック 
発言:名前  番号  発言タイトル 
返信:名前  発言 
標準の配色に戻す
背景画像
ログ保存件数 最新※ 「0件」にすると「全ログを保存」になります。
スイッチ 発言フォームの位置 記事の下  記事の上
プレビューボタン なし  あり  常にプレビュー 
削除キー なし   あり 必須
検索モード なし   あり
発言タイトル なし   あり
発言者のホスト 非表\示   表\示
ひとこと返信 不可   可   管理者のみ可
削除された発言 何も表\示しない   「削除済」の文字を表\示
リンクの下線 あり   なし

[通常モードに戻る]


"; } #################### クッキーの処理 ########## メイン sub deal_cookie{ # 名前が空欄ならクッキーの取得 ($name) || &get_cookie; # 発言の際指定されたらクッキーの保存 ($cook && $name && $cont && !$F{'chk'}) && &set_cookie; } ########## クッキーを取り出す sub get_cookie{ local($cookbuf); # 現在のBOOK向けクッキーがなければ終了 (($cookbuf) = $ENV{'HTTP_COOKIE'} =~ m|$book=([^;]+)|) || return; $cookbuf =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; ($name, $mail, $url, $ppr) = split("\t", $cookbuf); $cook = 1; } ########## クッキーの発行 sub set_cookie{ local($expires, $path, $value); $expires = &get_time_GMT($^T + 60 * 60 * 24 * $cookie_lifetime); if($enable_cookiepath){ ($path) = $ENV{'SCRIPT_NAME'} =~ m|^(.+/)[^/]+$|; $path = "path=" . $path; } $value = "$name\t$mail\t$url\t$ppr"; $value =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg; $cookieline = "Set-Cookie: $book=$value; expires=$expires; $path\n"; } ########## 日本語のデコード sub decode{ local($w, $frag) = @_; $w =~ tr/+/ /; $w =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; unless($frag){ $w =~ s//>/g; $w =~ s/"/"/g; $w =~ s/'/'/g; } $w =~ s/\t//g; $w =~ s/\cM//g; $w =~ s/\n{2,}/

/g; $w =~ s/\n/
/g; &jcode'convert(*w, $code); $w; } ##### タグを殺す sub killtag{ local($w) = @_; $w =~ s//>/g; $w =~ s/"/"/g; $w =~ s/'/'/g; $w; } ##### スパムキーワードをチェック $spam_pattern = ""; sub check_spamword { (@spamwords) || return; local($chkstr) = @_; # キーワードの初期化処理 if(!$spam_pattern) { foreach(@spamwords) { s/(\W)/\\$1/g; $spam_pattern .= $_ . "|"; } chop($spam_pattern); } # スパムワードがあったら1を、なかったら0を返す if($chkstr =~ /$spam_pattern/) { return 1; } return 0; } ##### 現在の時刻を得る sub get_time{ local($stime) = @_; $stime += $time_fix * 60 * 60; local($sec, $min, $hour, $mday, $mon, $year) = localtime($stime); $mon++; $year += 1900; return sprintf("%04d/%02d/%02d %02d:%02d", $year, $mon, $mday, $hour, $min); } ###### ファイルを開いて、中身を配列に代入する sub openfile{ local ($filename, *buf) = @_; open(FILE, "$filename") || &error(1, $filename); @buf = ; close(FILE); } ###### ファイルを更新する sub updatefile{ local ($filename, *buf, $frag) = @_; # フラグあり→追加、なし→更新 if($frag){ open(FILE, ">>$filename") || &error(1, $filename); } else{ open(FILE, ">$filename") || &error(1, $filename); } print FILE @buf; close(FILE); } ##### GMTを得る(クッキー用) sub get_time_GMT{ local($tsec) = @_; local($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($tsec); $wday = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')[$wday]; $mon = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')[$mon]; $year += 1900; return sprintf("$wday, %02d-$mon-$year %02d:%02d:%02d GMT", $mday, $hour, $min, $sec); } ##### ロック sub lock{ $try = 0; while(!mkdir($lockfile, 0700)) { (++$try > 3) && &error(0); sleep(1); } } ##### ロック解除 sub unlock{ rmdir($lockfile); } ##### エラーメッセージ sub error{ local ($id, $msg) = @_; local (@sts) = lstat($lockfile); local ($tn) = time(); $fmid[0] = 0; $msg[0] = 'ロック中です'; $fmid[1] = 1; $msg[1] = 'ファイルが開けません'; $fmid[2] = 1; $msg[2] = 'ファイルに書き込めません'; $fmid[3] = 0; $msg[3] = 'book が指定されていません'; $fmid[4] = 0; $msg[4] = 'book が不正です'; $fmid[5] = 0; $msg[5] = 'メールアドレスが不正です'; $fmid[6] = 0; $msg[6] = 'URLが不正です'; $fmid[7] = 0; $msg[7] = '親発言番号が不正です'; $fmid[8] = 0; $msg[8] = 'パスワードが間違っています'; $fmid[9] = 0; $msg[9] = '削除する番号が指定されていないか不正です'; $fmid[10] = 0; $msg[10] = "文章が長すぎます。全角で$max_words文字以下にして下さい"; $fmid[11] = 0; $msg[11] = "変数が不正です"; $fmid[12] = 0; $msg[12] = "返信は名前、コメント両方とも必須です"; $fmid[13] = 0; $msg[13] = "返信には管理パスワードが必要です"; $fmid[14] = 0; $msg[14] = "削除キーが入力されていません"; $fmid[15] = 0; $msg[15] = 'メッセージがスパム判定に引っかかりました。投稿できません'; $fmsg[0] = "Backを押して戻ってください。"; $fmsg[1] = "管理者に連絡してください。"; $fid = $fmid[$id]; ($msg) && ($detail = "($msg)"); print "Content-type: text/html\n\n"; print " T-Note 4 - Error!!

エラー発生

$msg[$id] $detail

$fmsg[$fid]


管理者:
$admin_email
※ ご一報の際には、サイトのURL、症状等をお書き添え下さいますようお願いします。
"; ($id) && &unlock; # ID が 0 以外の場合はロック解除 ($tn - $sts[9] > 15) && &unlock; # 約15秒以上ロックが続いてたら自動解除 exit; }