#!/usr/bin/perl #┌───────────────────────────────── #│ Honey Board v2.3 - 2006/06/14 #│ Copyright (c) KentWeb #│ webmaster@kent-web.com #│ http://www.kent-web.com/ #└───────────────────────────────── $ver = 'Honey Board v2.3'; #┌───────────────────────────────── #│ [注意事項] #│ 1. このスクリプトはフリーソフトです。このスクリプトを使用した #│ いかなる損害に対して作者は一切の責任を負いません。 #│ 2. 設置に関する質問はサポート掲示板にお願いいたします。 #│ 直接メールによる質問は一切お受けいたしておりません。 #└───────────────────────────────── # # 【ファイル構成例】 # # public_html (ホームディレクトリ) # | # +-- honey / honey.cgi [705] # | honeylog.cgi [606] # | jcode.pl [604] # | # +-- img / *.gif # | # +-- lock [707] / # # # [ チェックモードの仕方 ] : mode=check という引数を付けて呼出す # # 例 http://〜〜/honey.cgi?mode=check #------------------------------------------------- # 基本設定 #------------------------------------------------- # 文字コードライブラリ取込み require './jcode.pl'; # タイトル名 $title = "いちひこ 掲示板"; # タイトル文字の色 $t_color = "#DD0000"; # タイトル文字のタイプ $t_face = "MS Pゴシック"; # タイトル文字サイズ $t_point = '24px'; # 本文の文字サイズ $b_size = '13px'; # スクリプト名 $script = './honey.cgi'; # ログファイル名 $logfile = './honeylog.cgi'; # 管理用パスワード $pass = '0123'; # 最大記事数(これを超える記事は古い順に削除されます) $max = 50; # 戻り先 $home = "../index.html"; # 画像格納ディレクトリ # → フルパスなら http:// から記述する # → 最後は / を閉じない $imgurl = "./img"; # 背景色、文字色 $bgrnd = ""; # 壁紙 $bgcol = "#FFF7DD"; # 背景色 $text = "#452815"; # 文字色 $link = "#0000FF"; # リンク色:未訪問 $vlink = "#800080"; # リンク色:既訪問 $alink = "#DD0000"; # リンク色:訪問中 # 記事タイトル色 / 記事Noの色 $onepnt = "#008000"; # 文字色 @colors = ('#800000','#DF0000','#008040','#0000FF','#C100C1','#FF80C0','#FF8040','#000080'); # Eメールアドレスの必須入力 (0=no 1=yes) $in_email = 0; # 記事の更新は method=POST 限定 (0=no 1=yes) # --> 連続投稿などの荒らし対策 $postonly = 1; # 同一IPアドレスからの連続投稿時間(秒数) # --> 連続投稿などの荒らし対策 # --> 値を 0 にするとこの機能は無効になります $wait = 100; # URLの自動リンク (0=no 1=yes) $autolink = 1; # 1ページあたりの記事表示件数 $logview = 7; # レスがついたらツリー毎トップへ移動 (0=no 1=yes) $top_sort = 1; # ロックファイル機構 (0=no 1=symlink関数 2=mkdir関数) $lockkey = 0; # ロックファイル名 $lockfile = "./lock/honey.lock"; # メール通知機能 # --> 0 : no # --> 1 : yes 自分の投稿記事もメール通知する # --> 2 : yes 自分の投稿記事はメール通知しない $mailing = 0; # sendmailのパス(メール通知する場合) $sendmail = '/usr/lib/sendmail'; # メール通知先アドレス(メール通知する場合) $mailto = 'xxx@xxx.xxx'; # キャラクタを指定(上下の配列はペアで) @icon1 = ( 'boy1.gif','boy2.gif','seinen.gif','girl1.gif','girl2.gif', 'ol1.gif','ol2.gif','ol3.gif','china.gif','cook.gif','piero.gif', 'dog.gif','cat.gif','mouse.gif','pig.gif','hiyoko.gif','flog.gif'); @icon2 = ( '少年1','少年2','青年','少女1','少女2', 'OL風1','OL風2','OL風3','中国風','コック風','ピエロ', '子犬','子猫','子ネズミ','子ブタ','ヒヨコ','カエル'); # 管理者用アイコン # --> 管理アイコンを指定する場合は「削除キー」欄に管理用パスワードを # 同時に入力する必要があります。 $mgr_icon = "master.gif"; # タグ広告挿入オプション # → の代わりに「広告タグ」を挿入する。 # → 広告タグ以外に、MIDIタグ や LimeCounter等のタグにも使用可能です。 $banner1 = ''; # 掲示板上部に挿入 $banner2 = ''; # 掲示板下部に挿入 # タイトル画像を使う場合 # --> 画像URLを http:// から記述 $ImgT = ""; $ImgW = 150; # 画像横幅 $ImgH = 50; # 画像縦幅 # 投稿後の処理 # → 掲示板自身のURLを記述しておくと、投稿後リロードします # → ブラウザを再読み込みしても二重投稿されない措置。 # → Locationヘッダの使用可能なサーバのみ $location = ''; # ホスト取得方法 # 0 : gethostbyaddr関数を使わない # 1 : gethostbyaddr関数を使う $gethostbyaddr = 0; # アクセス制限(半角スペースで区切る、アスタリスク可) # → 拒否ホスト名を記述(後方一致)【例】*.anonymizer.com $deny_host = ''; # → 拒否IPアドレスを記述(前方一致)【例】210.12.345.* $deny_addr = ''; # 1回当りの最大投稿サイズ (bytes) $maxData = 51200; # 他サイトから投稿排除時に指定する場合(セキュリティ対策) # → 掲示板のURLをhttp://から書く $baseUrl = ''; # 禁止ワード # → 投稿時禁止するワードをコンマで区切る $no_wd = ''; # 日本語チェック(投稿時日本語が含まれていなければ拒否する) # 0=No 1=Yes $jp_wd = 0; # URL個数チェック # → 投稿コメント中に含まれるURL個数の最大値 $urlnum = 3; # 親記事の吹出色 # → 順に、「幅」「下地色」「画像ファイル名」 $oyaWid = 500; $oyaCol = "#FFFFFF"; @oyaCol = ("wh1.gif","wh2.gif","wh3.gif","wh4.gif","wh5.gif","wh6.gif"); # レス記事の吹出色 # → 順に、「幅」「下地色」「画像ファイル名」 $resWid = 380; $resCol = "#EFEFEF"; @resCol = ("lg1.gif","lg2.gif","lg3.gif","lg4.gif","lg5.gif","lg6.gif"); #------------------------------------------------- # 設定完了 #------------------------------------------------- &decode; &axscheck; if ($mode eq 'regist') { ®ist; } if ($mode eq 'find') { &find; } if ($mode eq 'howto') { &howto; } if ($mode eq 'admin') { &admin; } if ($mode eq 'usrdel') { &usrdel; } if ($mode eq 'image') { ℑ } if ($mode eq 'res') { &res_form; } if ($mode eq 'check') { ✓ } &html; #------------------------------------------------- # アクセス制限 #------------------------------------------------- sub axscheck { # IP&ホスト取得 $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($gethostbyaddr && ($host eq "" || $host eq $addr)) { $host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2); } # IPチェック local($flg); foreach ( split(/\s+/, $deny_addr) ) { s/\./\\\./g; s/\*/\.\*/g; if ($addr =~ /^$_/i) { $flg = 1; last; } } if ($flg) { &error("アクセスを許可されていません"); # ホストチェック } elsif ($host) { foreach ( split(/\s+/, $deny_host) ) { s/\./\\\./g; s/\*/\.\*/g; if ($host =~ /$_$/i) { $flg = 1; last; } } if ($flg) { &error("アクセスを許可されていません"); } } if ($host eq "") { $host = $addr; } } #------------------------------------------------- # 記事表示処理 #------------------------------------------------- sub html { # ヘッダ &header; print "
\n"; if ($banner1 ne "") { print "$banner1\n

\n"; } # タイトル部 if ($ImgT) { print "\"$title\"\n"; } else { print "$title\n"; } print < [トップに戻る] [留意事項] [ワード検索] [管理用]


EOM # フォームを表示 &form_view; local($i,$top); open(IN,"$logfile") || &error("Open Error: $logfile"); $top = ; while () { local($no,$reno,$date,$name,$eml,$sub,$icon,$icon2,$com,$color,$url,$host,$pw) = split(/<>/); if ($reno eq "") { $i++; } if ($i < $page + 1) { next; } if ($i > $page + $logview) { last; } if ($eml) { $name = "$name"; } if ($url) { if ($url !~ /^http/i) { $url = "http://$url"; } $url = "home"; } # 1マスの大きさ $pix = 18; # レス記事 if ($reno) { $wide = $resWid; $iro = $resCol; @gif = ("",@resCol); # 親記事 } else { $wide = $oyaWid; $iro = $oyaCol; @gif = ("",@oyaCol); } # 記事を表示 if (!$reno) { print "

\n"; } print "\n"; # 反転対象部分1 if (!$flag) { print "\n"; print "
\n"; print "\n"; } else { print "

\n"; } print "\n"; print "\n"; print "\n"; # 反転対象部分2 if ($flag == 0) { print ""; print "\n"; } else { print "\n\n"; } print "\n"; print "\n"; if ($flag == 1) { print "\n"; } print "\n"; # 反転対象部分3 if ($flag == 0) { print "\n"; } print "\n"; print "\n"; print "\n"; if ($flag == 1) { print "\n"; } print "



\n"; print "$sub
\n"; if (!$reno) { print "投稿者:"; } print "$name - $date No\.$no "; if (!$reno) { print "[返信]   \n"; } print "$url
\n"; print "
$com
\n"; print "


 
\n"; if ($flag == 1) { print "
\n"; } print "
\n"; if (!$reno) { if ($flag == 0) { $flag=1; } else { $flag=0; } } } close(IN); local($next) = $page + $logview; local($back) = $page - $logview; print "
\n"; if ($back >= 0) { print "\n"; } if ($next < $i) { print "\n"; } print "
\n"; print "\n"; print "
\n"; print "\n"; print "
\n"; print "\n"; print "\n"; print "
\n"; print "\n"; print "記事No\n"; print "削除キー\n"; print "

\n"; # 著作権表示(削除不可) print "
$banner2

\n"; print "\n"; print "- Honey Board -\n"; print "

\n\n"; exit; } #------------------------------------------------- # 書きこみ処理 #------------------------------------------------- sub regist { # 投稿チェック if ($postonly && !$post_flag) { &error("不正なアクセスです"); } if ($baseUrl) { &refCheck; } # チェック if ($no_wd) { &no_wd; } if ($jp_wd) { &jp_wd; } if ($urlnum > 0) { &urlnum; } # フォーム内容をチェック if ($in{'name'} eq "") { &error("名前が入力されていません"); } if ($in{'comment'} eq "") { &error("コメントが入力されていません"); } if ($in_email && $in{'email'} !~ /^[\w\.\-]+\@[\w\.\-]+\.[a-zA-Z]{2,5}$/) { &error("メールアドレスの入力が不正です"); } if ($in{'url'} eq "http://") { $in{'url'} = ''; } if ($in{'sub'} eq "") { $in{'sub'} = "無題"; } # 管理者アイコン処理 if ($in{'icon'} eq $mgr_icon && $in{'pwd'} ne $pass) { &error("管理者アイコンは管理者以外は使用できません"); } # ロック処理 &lock if ($lockkey); open(IN,"$logfile") || &error("Open Error: $logfile"); local(@lines) = ; close(IN); # 記事NO処理 local($top) = shift(@lines); local($no,$ip,$time2) = split(/<>/, $top); $no++; # 連続投稿チェック if ($addr eq $ip && $wait > $times - $time2) { &error("連続投稿はもうしばらく時間をおいて下さい"); } # 削除キーを暗号化 if ($in{'pwd'} ne "") { $PW = &encrypt($in{'pwd'}); } # URL自動リンク if ($autolink) { &auto_link($in{'comment'}); } # 親記事の場合 if ($in{'reno'} eq "") { # 最大記事数処理 while ($max <= @lines) { pop(@lines); } unshift(@lines,"$no<><>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'icon'}<>$icon2<>$in{'comment'}<>$in{'color'}<>$in{'url'}<>$host<>$PW<>\n"); unshift(@lines,"$no<>$addr<>$times<>\n"); # 更新 open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @lines; close(OUT); # レス記事の場合:トップソートあり } elsif ($in{'reno'} && $top_sort) { local($f,$match,@new,@tmp); foreach (@lines) { ($no2,$reno2) = split(/<>/); if ($in{'reno'} eq $no2) { if ($reno2) { $f++; last; } $match=1; push(@new,$_); } elsif ($in{'reno'} eq $reno2) { push(@new,$_); } elsif ($match == 1 && $in{'reno'} ne $reno2) { $match=2; push(@new,"$no<>$in{'reno'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'icon'}<>$icon2<>$in{'comment'}<>$in{'color'}<>$in{'url'}<>$host<>$PW<>\n"); push(@tmp,$_); } else { push(@tmp,$_); } } if ($f) { &error("不正な返信要求です"); } if ($match == 1) { push(@new,"$no<>$in{'reno'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'icon'}<>$icon2<>$in{'comment'}<>$in{'color'}<>$in{'url'}<>$host<>$PW<>\n"); } push(@new,@tmp); # 更新 unshift(@new,"$no<>$addr<>$times<>\n"); open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @new; close(OUT); # レス記事の場合:トップソートなし } else { local($f,$match,@new); foreach (@lines) { ($no2,$reno2) = split(/<>/); if ($match == 0 && $in{'reno'} eq $no2) { if ($reno2) { $f++; last; } $match=1; } elsif ($match == 1 && $in{'reno'} ne $reno2) { $match=2; push(@new,"$no<>$in{'reno'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'icon'}<>$icon2<>$in{'comment'}<>$in{'color'}<>$in{'url'}<>$host<>$PW<>\n"); } push(@new,$_); } if ($f) { &error("不正な返信要求です"); } if ($match == 1) { push(@new,"$no<>$in{'reno'}<>$date<>$in{'name'}<>$in{'email'}<>$in{'sub'}<>$in{'icon'}<>$icon2<>$in{'comment'}<>$in{'color'}<>$in{'url'}<>$host<>$PW<>\n"); } # 更新 unshift(@new,"$no<>$addr<>$times<>\n"); open(OUT,">$logfile") || &error("Write Error: $logfile"); print OUT @new; close(OUT); } # ロック解除 &unlock if ($lockkey); if ($in{'cook'} eq 'on') { &set_cookie($in{'name'},$in{'email'},$in{'url'},$in{'pwd'},$in{'color'},$in{'icon'}); } # メール通知処理 if ($mailing == 1) { &mail_to; } elsif ($mailing == 2 && $in{'email'} ne $mailto) { &mail_to; } # リロード if ($location) { if ($ENV{'PERLXS'} eq "PerlIS") { print "HTTP/1.0 302 Temporary Redirection\r\n"; print "Content-type: text/html\n"; } print "Location: $location?\n\n"; } else { &header; print "

\n"; print "

投稿は正常に処理されました

\n"; print "
\n"; print "
\n"; print "
\n\n"; } exit; } #------------------------------------------------- # ワード検索 #------------------------------------------------- sub find { local($no,$reno,$date,$name,$mail,$sub,$icon,$icon2,$com,$res,$url); &header; print <<"EOM"; [戻る]
  • 検索したいキーワードを入力し「検索」を押してください。
  • キーワードは「半角スペース」で区切って複数指定することができます。
    キーワード 検索条件
EOM # ワード検索の実行と結果表示 if ($in{'word'} ne "") { # 入力内容を整理 $in{'word'} =~ s/ / /g; @wd = split(/\s+/, $in{'word'}); # 検索処理 print "
\n"; $i = 0; open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; while () { $flag = 0; foreach $wd (@wd) { if (index($_,$wd) >= 0) { $flag=1; if ($in{'cond'} eq 'OR') { last; } } else { if ($in{'cond'} eq 'AND') { $flag=0; last; } } } next if (!$flag); # 結果を表示 $i++; ($no,$reno,$date,$name,$mail,$sub,$icon,$icon2,$com,$res,$url) = split(/<>/); if ($mail) { $name = "$name"; } if ($url) { if ($url !~ /^http/i) { $url = "http://$url"; } $url = "[HOME]"; } print "

[$no] $sub ", "投稿者:$name 投稿日:$date $url

$com
\n"; } close(IN); print "

検索結果は $i件です。\n"; } print "

\n\n\n"; exit; } #------------------------------------------------- # 管理モード #------------------------------------------------- sub admin { if ($in{'pass'} ne "" && $in{'pass'} ne $pass) { &error("パスワードが違います"); } &header; print "[掲示板に戻る]\n"; if ($in{'pass'} eq "") { print "

パスワードを入力して下さい

\n"; print "
\n"; print "\n"; print "\n"; print ""; print "\n"; print "
\n"; } else { # 削除処理 if ($DEL[0]) { # ロック処理 &lock if ($lockkey); # 削除情報をマッチングし更新 @new = (); open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; while () { $flag=0; ($no,$reno,$date) = split(/<>/); foreach $del (@DEL) { if ($no eq "$del" || $reno eq "$del") { $flag=1; last; } } if ($flag == 0) { push(@new,$_); } } close(IN); # 更新 unshift(@new,$top); open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @new; close(OUT); # ロック解除 &unlock if ($lockkey); } # 管理を表示 if ($page eq "") { $page = 0; } print "

\n"; print "
  • 削除する記事のチェックボックスにチェックを入れ、削除ボタンを押して下さい。\n"; print "
  • 親記事を削除するとレス記事も一括して削除されます。
\n"; print "
\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print ""; print "\n"; print "

\n"; print ""; print "\n"; # ページ区切り処理 $start = $page + 1; $end = $page + $logview; open(IN,"$logfile") || &error("Open Error: $logfile"); $top = ; $i=0; while () { ($no,$reno,$date,$name,$mail,$sub,$icon,$icon2,$com,$color,$url,$host,$pw) = split(/<>/); if ($reno eq "") { $i++; } if ($i < $start) { next; } if ($i > $end) { last; } if ($mail) { $name="$name"; } ($date) = split(/\(/, $date); if ($url) { if ($url !~ /^http/i) { $url = "http://$url"; } $url = "Home"; } else { $url = '-'; } $com =~ s/
//ig; $com =~ s//>/g; if (length($com) > 50) { $com = substr($com,0,48); $com = "$com" . "..."; } if ($reno eq "") { print "
\n"; } # 削除チェックボックス print ""; print ""; print ""; print ""; print "\n"; } close(IN); print "\n"; print "
削除記事NO投稿日タイトル投稿者URLコメントホスト名

$no$date$sub$name$url$com$host

\n"; } $next_page = $page + $logview; $back_page = $page - $logview; print "

\n"; if ($back_page >= 0) { print "\n"; } if ($next_page < $i) { 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 "

\n"; print "\n\n"; exit; } #------------------------------------------------- # 返信レスフォーム #------------------------------------------------- sub res_form { &header; print <掲示板に戻る]
EOM local($flg,$top); open(IN,"$logfile") || &error("Open Error : $logfile"); $top = ; while () { local($no,$reno,$date,$name,$mail,$sub,$icon,$icon2,$com,$color,$url,$host,$pw) = split(/<>/); if ($in{'no'} == $no && $reno) { $flg++; } if ($in{'no'} eq $no || $in{'no'} eq $reno) { if ($mail) { $name = "$name"; } if ($url) { if ($url =~ /^http/i) { $url = "<Home>"; } else { $url = "<Home>"; } } # レス題名用 if ($reno eq "") { $res_sub = "Re: $sub"; } print "$sub $name - $date $url

\n"; print "

$com

\n"; } } close(IN); if ($flg) { &error("不正な返信要求です"); } &form_view($in{'no'}); print "
\n\n\n"; exit; } #------------------------------------------------- # 留意事項 #------------------------------------------------- sub howto { &header; print <

留意事項

  1. この掲示板はクッキー対応です。1度記事を投稿いただくと、おなまえ、Eメール、URL、削除キーの情報は2回目以降は自動入力されます。(ただし利用者のブラウザがクッキー対応の場合)
  2. 投稿記事には、タグは一切使用できません。 EOM if ($in_email) { print "
  3. 記事を投稿する上での必須入力項目は「おなまえ」「メッセージ」「Eメール」です。URLと削除キーは任意です。\n"; } else { print "
  4. 記事を投稿する上での必須入力項目は「おなまえ」「メッセージ」です。Eメール、URL、削除キーは任意です。\n"; } print <記事には、半角カナは一切使用しないで下さい。文字化けの原因となります。
  5. 記事の投稿時に「削除キー」にパスワード(英数字で8文字以内)を入れておくと、その記事は次回削除キーによって削除することができます。
  6. 記事の保持件数は最大 $max件です。それを超えると古い順に自動削除されます。
  7. 過去の投稿記事から「キーワード」によって簡易検索ができます。トップメニューの「ワード検索」のリンクをクリックすると検索モードとなります。
  8. 管理者が著しく不利益と判断する記事や他人を誹謗中傷する記事は予\告なく削除することがあります。

EOM exit; } #------------------------------------------------- # ユーザ記事削除 #------------------------------------------------- sub usrdel { # 投稿チェック if ($postonly && !$post_flag) { &error("不正なアクセスです"); } if ($baseUrl) { &refCheck; } if ($in{'no'} eq '' || $in{'pwd'} eq '') { &error("削除Noまたは削除キーが入力モレです"); } # ロック処理 &lock if ($lockkey); open(IN,"$logfile") || &error("Open Error : $logfile"); @lines = ; close(IN); $top = shift(@lines); $flag=0; foreach (@lines) { ($no,$reno,$date,$name,$mail,$sub,$icon,$icon2,$com,$color,$url,$host,$pw) = split(/<>/); if ($flag == 0 && $in{'no'} eq $no) { $PW = $pw; if ($reno eq "") { $flag=2; } else { $flag=1; } } elsif ($flag == 2 && $in{'no'} eq $reno) { next; } else { push(@new,$_); } } if ($flag == 0) { &error("該当記事が見当たりません"); } if ($PW eq '') { &error("該当記事には削除キーが設定されていません"); } # 削除キーを照合 $check = &decrypt($in{'pwd'}, $PW); if ($check != 1) { &error("削除キーが違います"); } else { # 更新 unshift(@new,$top); open(OUT,">$logfile") || &error("Write Error : $logfile"); print OUT @new; close(OUT); # ロック解除 &unlock if ($lockkey); } } #------------------------------------------------- # フォームデコード #------------------------------------------------- sub decode { local($buf); $post_flag = 0; if ($ENV{'REQUEST_METHOD'} eq "POST") { $post_flag = 1; if ($ENV{'CONTENT_LENGTH'} > $maxData) { &error("投稿量が大きすぎます"); } read(STDIN, $buf, $ENV{'CONTENT_LENGTH'}); } else { $buf = $ENV{'QUERY_STRING'}; } undef(%in); foreach ( split(/&/, $buf) ) { local($key, $val) = split(/=/); $val =~ tr/+/ /; $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg; # S-JISコード変換 &jcode'convert(*val, "sjis", "", "z"); # エスケープ $val =~ s/&/&/g; $val =~ s/"/"/g; $val =~ s//>/g; $val =~ s/\r\n/
/g; $val =~ s/\r/
/g; $val =~ s/\n/
/g; # 削除情報 if ($key eq 'del') { push(@DEL,$val); } $in{$key} = $val; } $mode = $in{'mode'}; $page = $in{'page'}; # 日時の取得 $ENV{'TZ'} = "JST-9"; $times = time; ($min,$hour,$mday,$mon,$year,$wday) = (localtime($times))[1..6]; # 日時のフォーマット @week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); $date = sprintf("%04d\/%02d\/%02d(%s) %02d\:%02d", $year+1900,$mon+1,$mday,$week[$wday],$hour,$min); } #------------------------------------------------- # HTMLヘッダ #------------------------------------------------- sub header { $headflag = 1; print "Content-type: text/html\n\n"; print <<"EOM"; $title EOM } #------------------------------------------------- # エラー処理 #------------------------------------------------- sub error { &unlock if ($lockflag); &header if (!$headflag); print <

ERROR !

$_[0]


EOM exit; } #------------------------------------------------- # クッキー発行 #------------------------------------------------- sub set_cookie { local(@cook) = @_; local($gmt, $cook, @t, @m, @w); @t = gmtime(time + 60*24*60*60); @m = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); @w = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); # 国際標準時を定義 $gmt = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $w[$t[6]], $t[3], $m[$t[4]], $t[5]+1900, $t[2], $t[1], $t[0]); # 保存データをURLエンコード foreach (@cook) { s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg; $cook .= "$_<>"; } # 格納 print "Set-Cookie: HoneyBoard=$cook; expires=$gmt\n"; } #------------------------------------------------- # クッキー取得 #------------------------------------------------- sub get_cookie { local($key, $val, *cook); # クッキーを取得 $cook = $ENV{'HTTP_COOKIE'}; # 該当IDを取り出す foreach ( split(/;/, $cook) ) { ($key, $val) = split(/=/); $key =~ s/\s//g; $cook{$key} = $val; } # データをURLデコードして復元 foreach ( split(/<>/, $cook{'HoneyBoard'}) ) { s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2", $1)/eg; push(@cook,$_); } return (@cook); } #------------------------------------------------- # パスワード暗号処理 #------------------------------------------------- sub encrypt { local($in) = @_; local($salt, $enc, @s); @s = ('a'..'z', 'A'..'Z', '0'..'9', '.', '/'); srand; $salt = $s[int(rand(@s))] . $s[int(rand(@s))]; $enc = crypt($in, $salt) || crypt ($in, '$1$' . $salt); $enc; } #------------------------------------------------- # パスワード照合処理 #------------------------------------------------- sub decrypt { local($in, $dec) = @_; local $salt = $dec =~ /^\$1\$(.*)\$/ && $1 || substr($dec, 0, 2); if (crypt($in, $salt) eq $dec || crypt($in, '$1$' . $salt) eq $dec) { return (1); } else { return (0); } } #------------------------------------------------- # ロック処理 #------------------------------------------------- sub lock { local($retry)=5; # 古いロックは削除 if (-e $lockfile) { local($mtime) = (stat($lockfile))[9]; if ($mtime < time - 30) { &unlock; } } # symlink関数式ロック if ($lockkey == 1) { while (!symlink(".", $lockfile)) { if (--$retry <= 0) { &error('LOCK is BUSY'); } sleep(1); } # mkdir関数式ロック } elsif ($lockkey == 2) { while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error('LOCK is BUSY'); } sleep(1); } } $lockflag=1; } #------------------------------------------------- # ロック解除 #------------------------------------------------- sub unlock { if ($lockkey == 1) { unlink($lockfile); } elsif ($lockkey == 2) { rmdir($lockfile); } $lockflag=0; } #------------------------------------------------- # メール送信 #------------------------------------------------- sub mail_to { local($com, $msub, $mbody); # メールタイトルを定義 $msub = &base64("[$title : $no] $in{'sub'}"); # 記事復元 $com = $in{'comment'}; $com =~ s/
/\n/g; $com =~ s/</</g; $com =~ s/>/>/g; $com =~ s/"/”/g; $com =~ s/&/&/g; # メール本文を定義 $mbody = <<"EOM"; 投稿日時:$date ホスト名:$host ブラウザ:$ENV{'HTTP_USER_AGENT'} 投稿者名:$in{'name'} Eメール:$in{'email'} URL :$in{'url'} タイトル:$in{'sub'} $com EOM # sendmail起動 if ($in{'email'} eq "") { $email = $mailto; } else { $email = $in{'email'}; } open(MAIL,"| $sendmail -t -i"); print MAIL "To: $mailto\n"; print MAIL "From: $email\n"; print MAIL "Subject: $msub\n"; print MAIL "MIME-Version: 1.0\n"; print MAIL "Content-type: text/plain; charset=ISO-2022-JP\n"; print MAIL "Content-Transfer-Encoding: 7bit\n"; print MAIL "X-Mailer: $ver\n\n"; foreach ( split(/\n/, $mbody) ) { &jcode'convert(*_, 'jis', 'sjis'); print MAIL $_, "\n"; } close(MAIL); } #------------------------------------------------- # BASE64変換 #------------------------------------------------- # とほほのWWW入門で公開されているルーチンを # 参考にしました。( http://tohoho.wakusei.ne.jp/ ) sub base64 { local($sub) = @_; &jcode'convert(*sub, 'jis', 'sjis'); $sub =~ s/\x1b\x28\x42/\x1b\x28\x4a/g; $sub = "=?iso-2022-jp?B?" . &b64enc($sub) . "?="; $sub; } sub b64enc { local($ch)="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; local($x, $y, $z, $i); $x = unpack("B*", $_[0]); for ($i=0; $y=substr($x,$i,6); $i+=6) { $z .= substr($ch, ord(pack("B*", "00" . $y)), 1); if (length($y) == 2) { $z .= "=="; } elsif (length($y) == 4) { $z .= "="; } } $z; } #------------------------------------------------- # イメージ表示 #------------------------------------------------- sub image { local($i,$j,$stop); &header; print "

\n"; print "画像イメージ\n"; print "

- 現在登録されている画像イメージは以下のとおりです -\n"; print "


\n"; print "

\n"; $i=0; $j=0; $stop = @icon1; foreach (0 .. $#icon1) { $i++; $j++; print "\n"; if ($j != $stop && $i >= 5) { print "\n"; $i=0; } elsif ($j == $stop) { if ($i == 0) { last; } while ($i < 5) { print ""; $i++; } } } print "
\"$icon1[$_]\" $icon2[$_]


\n"; print "

\n"; print "
\n\n\n"; exit; } #------------------------------------------------- # 自動リンク #------------------------------------------------- sub auto_link { $_[0] =~ s/([^=^\"]|^)(http\:[\w\.\~\-\/\?\&\=\@\;\#\:\%]+)/$1$2<\/a>/g; } #------------------------------------------------- # 投稿フォーム #------------------------------------------------- sub form_view { # クッキー情報を取得 local($cnam,$ceml,$curl,$cpwd,$ccol,$cico) = &get_cookie; if ($curl eq "") { $curl = 'http://'; } print "
\n"; if ($mode eq "res") { print "\n"; } print <<"EOM";
おなまえ
Eメール
タイトル  
メッセージ
参照先
イメージ [アイコン参照]
削除キー (記事の削除時に使用)
文字色 EOM if ($ccol eq "") { $ccol = $colors[0]; } foreach (0 .. $#colors) { if ($ccol eq "$colors[$_]") { print ""; print " \n"; } else { print ""; print " \n"; } } if ($_[0]) { print "\n"; } print "
\n"; print " "; print "クッキーを保存\n"; print "
\n
\n"; } #------------------------------------------------- # REFチェック #------------------------------------------------- sub refCheck { local($ref) = $ENV{'HTTP_REFERER'}; $ref =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2", $1)/eg; $baseUrl =~ s/(\W)/\\$1/g; if ($ref && $ref !~ /$baseUrl/i) { &error("不正なアクセスです"); } } #------------------------------------------------- # 禁止ワードチェック #------------------------------------------------- sub no_wd { local($flg); foreach ( split(/,/, $no_wd) ) { if (index("$in{'name'} $in{'sub'} $in{'comment'}",$_) >= 0) { $flg = 1; last; } } if ($flg) { &error("禁止ワードが含まれています"); } } #------------------------------------------------- # 日本語チェック #------------------------------------------------- sub jp_wd { local($sub, $com, $mat1, $mat2, $code1, $code2); $sub = $in{'sub'}; $com = $in{'comment'}; if ($sub) { ($mat1, $code1) = &jcode'getcode(*sub); } ($mat2, $code2) = &jcode'getcode(*com); if ($code1 ne 'sjis' && $code2 ne 'sjis') { &error("題名又はコメントに日本語が含まれていません"); } } #------------------------------------------------- # URL個数チェック #------------------------------------------------- sub urlnum { local($com) = $in{'comment'}; local($num) = ($com =~ s|(https?://)|$1|ig); if ($num > $urlnum) { &error("コメント中のURLアドレスは最大$urlnum個までです"); } } #------------------------------------------------- # チェックモード #------------------------------------------------- sub check { &header; print "

Check Mode

\n"; print "
    \n"; # ログパス if (-e $logfile) { print "
  • ログファイルのパス:OK\n"; # ログパーミッション if (-r $logfile && -w $logfile) { print "
  • ログファイルのパーミッション:OK\n"; } else { print "
  • ログファイルのパーミッション:NG\n"; } } else { print "
  • ログファイルのパス:NG → $logfile\n"; } # ロックディレクトリ print "
  • ロック形式:"; if ($lockkey == 0) { print "ロック設定なし\n"; } else { if ($lockkey == 1) { print "symlink\n"; } else { print "mkdir\n"; } ($lockdir) = $lockfile =~ /(.*)[\\\/].*$/; print "
  • ロックディレクトリ:$lockdir\n"; if (-d $lockdir) { print "
  • ロックディレクトリのパス:OK\n"; if (-r $lockdir && -w $lockdir && -x $lockdir) { print "
  • ロックディレクトリのパーミッション:OK\n"; } else { print "
  • ロックディレクトリのパーミッション:NG → $lockdir\n"; } } else { print "
  • ロックディレクトリのパス:NG → $lockdir\n"; } } print "
\n\n\n"; exit; } __END__