#!/usr/bin/perl # G_BOOK ver1.45.00 (Az Board OIDON version!) # # このスクリプトは「じゃわ」と「おいどん」の共同制作です。 # # じゃわ http://www7.big.or.jp/~jawa/ # おいどん http://www.iod.co.jp/~oidon/ # # このスクリプトは再配布しない限りフリーです。 # ////////////////////////////////////////////////////////// # オプションの設定を変更することができます。 # 変更する場合は、readme.htm をご覧になってから行ってください。 # 設定変更には充分注意してください。 # ////////////////////////////////////////////////////////// # ---------------------------------------------------------- # G_BOOK の管理者(あなた)の情報です。 # ---------------------------------------------------------- $admin_name ='teachan'; # 管理人(あなた)の名前 $master = 'tskplati'; # 管理用のパスワード # ---------------------------------------------------------- # G_BOOK のカスタマイズ項目です。 # ---------------------------------------------------------- $reg_max = 500; # 最大保持数(最大9998まで) $max = 20; # 1ページに表示する数です。 $max_msg = 1200; # 投稿を受理する最大文字数(半角 n 文字) $title = 'G_BOOK v1.45 (Az Board OIDON version!)'; # このゲストブックのタイトル(タグ不可) $body_text = '#2b2b2b'; # タグの設定 $body_link = '#0000FF'; $body_alink = '#0000DD'; $body_vlink = '#FF0000'; $body_bgcolor = '#FFFFFF'; $body_back = 'kabe.gif'; $back_url = "http://www.tsk-web.com/edform/index.htm"; # 帰りの URL $image_url = "./"; # 画像がある URL(絶対でも、相対でも可能) $title_gif = "title.gif"; # タイトル画像 $top_gif = "top.gif"; # 「トップに戻る」選択用画像 $back_gif = "older.gif"; # 「前のページ」選択用画像 $next_gif = "newer.gif"; # 「次のページ」選択用画像 $home_gif = "home.gif"; # 「投稿者HP」選択用画像 $user_icons[0] = 'boy1.gif=少年1'; # ユーザーのアイコンの画像 $user_icons[1] = 'boy2.gif=少年2'; # 画像ファイル名=画像の名称 という形で書く。 $user_icons[2] = 'sala1.gif=青年'; # 間にスペース等は入れてはいけません。 $user_icons[3] = 'oyaji.gif=おやじ風'; # 駄目! → 'boy1.gif = 少年1' $user_icons[4] = 'girl1.gif=少女'; $user_icons[5] = 'ol1.gif=OL風'; $user_icons[6] = 'shufu.gif=主婦'; $user_icons[7] = 'neko.gif=ねこ'; $user_icons[8] = 'mouse.gif=ねずみ'; $admin_icons[0] = 'admin.gif=管理者'; # 管理者のアイコンの画像 $admin_icons[1] = 'bm3.gif=男性'; # 画像ファイル名=画像の名称 という形で書く。 $admin_icons[2] = 'ol11_1c.gif=女性'; # 間にスペース等は入れてはいけません。 # 駄目! → 'admin.gif = 管理者' $date = "year/mon/day hour:min"; # year:年 mon:月 day:日 hour:時 min:分 sec:秒 $date_type = 1; # 一桁のとき二桁に修正するか? # 0:しない 1:する(時分秒) 2:する(全て) $name_color = '#287800'; # 投稿者の名前の色 $date_color = '#CF4994'; # 日付表示の色 $admsg_color = '#AA2222'; # 管理人メッセージの色 $admin_color = 'green'; # 管理人の名前の色 (色は #xxxxxx で表現可能です) $check_url = ""; # ここに G_BOOK の正確な URL (http://〜) を書いておくと他サイトから # 不正に投稿されたものを拒否できます。 # (イタズラされて、初めて利用すること!) @check_ipad = (); # ここに 登録されたくない方の IPアドレスを書いておくと、 # その IPアドレスからの全ての投稿を拒否します。 # (イタズラされて、初めて利用すること!) $check_proxy = 0; # ここの値を 1 にすると、プロクシ経由で来る匿名な訪問者を # 排除ですきますが、通常の方を排除する可能性もあります。 # (イタズラされて、初めて利用すること!) # ファイル関連の設定 $cookie_name = 'id_gbook'; # クッキーのID $method = 'POST'; # METHOD の設定('POST' or 'GET') $tz = "JST-9"; # TimeZone $cginame = './g_book.cgi'; # この CGI のファイルの名前 $jcode = './jcode.pl'; # jcode.pl のある場所 $logfile = './g_book.log'; # 記録用ファイル(一部プロバイダでは書き換え必要) $lock1 = './g_book1.lock'; # 鍵ファイル(1) $lock2 = './g_book2.lock'; # 鍵ファイル(2) $lock_flag = 1; # 鍵ファイルの 1:使用 0:不使用 # -------------------- # 独自の JavaScript や スタイルシートはここに $html_head=<<"_EOF_"; _EOF_ # ↑ この _EOF_ はこのままにしておくこと! # -------------------- # 上にバナー(広告)をつける必要があるならここに $html_topbanner=<<"_EOF_"; _EOF_ # ↑ この _EOF_ はこのままにしておくこと! # -------------------- # 下にバナー(広告)をつける必要があるならここに $html_bottombanner=<<"_EOF_"; _EOF_ # ↑ この _EOF_ はこのままにしておくこと! # ///////////////////////////////////////////////////////////////////////////// # オプションの設定はここまでです。 # 以下は CGI のプログラムです。 # 書き換えは個人の責任で行って下さい。 # ///////////////////////////////////////////////////////////////////////////// $image_url =~ s/\/$//; &check_code; &get_cookie; &read_form; @logs = &read_file($logfile); if ($FORM{'pass'} eq $master) { if ($FORM{'func'} eq 'unlock') { &editor_unlock; } if ($FORM{'func'} eq 'html') { &editor_html; } if ($FORM{'func'} eq 'download') { &editor_download; } if ($FORM{'func'} eq 'del') { &editor_del; } &editor_main; } if ($FORM{'mode'} eq 'test') { &check_mode;} if ($FORM{'mode'} eq 'password') { &editor_password; } if ($FORM{'mode'} eq 'regist') { ®ist; } &html_header; &html_title; &html_form; &html_list; &html_footer; exit; # [ タイトル部分 ] # sub html_title { print<<"_EOF_";

_EOF_ } # [ ヘッダー部分 ] # sub html_header { print<<"_EOF_"; Content-type: text/html $title $html_head $html_topbanner _EOF_ } # [ フッター部分(著作権は表示すること) ] # sub html_footer { print<<"_EOF_";
CGI-StaTIon KENT Web 牛飼いとアイコンの部屋
$html_bottombanner _EOF_ } # [ タイトル&登録フォーム ] # sub html_form { if ($FORM{'pass'} eq $master) { ($no,$title,$name,$url,$email,$user_icon,$user_message,$admin_icon,$admin_message) = @_; $user_message =~ s/
/\n/ig; $admin_message =~ s/
/\n/ig; } else { ($name,$url,$email,$user_icon) = ($COOKIE{'bbs_name'},$COOKIE{'bbs_url'},$COOKIE{'bbs_email'},$COOKIE{'bbs_icon'}); } local($nam_wid,$url_wid,$com_wid) = (29,45,50); $agent = $ENV{'HTTP_USER_AGENT'}; if ($agent =~ /MSIE 3/i) { ($nam_wid,$url_wid,$com_wid) = (32,69,87); } elsif ($agent =~ /MSIE 4/i) { ($nam_wid,$url_wid,$com_wid) = (48,83,67); } elsif (($agent =~ /[ja]/i) && ($agent =~ /3\./)) { ($nam_wid,$url_wid,$com_wid) = (28,52,58); } print<<"_EOF_";
_EOF_ if ($FORM{'pass'} eq $master) { print<<"_EOF_";
お名前  イメージ
メール
URL
内 容
管理人イメージ
レ ス
_EOF_ } else { print<<"_EOF_"; ・ お名前と内容は必須です(省略することはできません)
・ 記事は最大 $reg_max 件までで、それを超えると古い記事から削除されます
・ タグは使えません(URL等は自動的にリンクされます)
・ 商用の書き込みはご遠慮下さい。
・ 当サイトの趣旨に添わないものは削除する場合があります。
_EOF_ } } # [ 内容表示部分 ] # sub html_list { local($next_page,$back_page) = ($FORM{'page'} - $max,$FORM{'page'} + $max); print "
\n\n"; if ($back_page > @logs-1) { $back_page = @logs; } else { print "\n"; } if ($next_page > -1) { print "\n"; } print"
\n"; &html_draw($FORM{'page'},$back_page); } sub html_draw { local($page,$back_page) = @_; for ($i=$page;$i<$back_page;$i++) { local($no,$title,$name,$url,$email,$date,$rhost,$ipad,$user_icon,$user_message,$admin_icon,$admin_message) = split(/<>/,$logs[$i]); $admin_message =~s/\n$//; $user_message = &auto_link($user_message); $admin_message = &auto_link($admin_message); if ($FORM{'pass'} eq $master) { print "
\n"; print "[削除] [編集] [$rhost($ipad)]\n"; print "
\n"; } else { print "\n
"; } print "\n"; if ($url) { print"\n"; } print "
\n[$no]\n"; if ($email) { print "$name"; } else { print "$name"; } print " - [$date]
\n"; print "

\n"; if ($admin_message) { print "

\n"; print "\n"; } print "
$user_message
$admin_message
\n"; print "[From $admin_name]
\n\n

\n\n"; } } # [ 登録処理 ] # sub regist { local($name,$email,$url,$user_icon,$user_message,$error) = ($FORM{'name'},$FORM{'email'},$FORM{'url'},$FORM{'user_icon'},$FORM{'user_message'},''); $name =~ s/\r\n//g; $name =~ s/\r|\n//g; $email =~ s/\r\n//g; $email =~ s/\r|\n//g; $url =~ s/\r\n//g; $url =~ s/\r|\n//g; $user_message =~ s/\r\n/
/g; $user_message =~ s/\r|\n/
/g; local($ipad,$rhost) = ($ENV{'REMOTE_ADDR'},$ENV{'REMOTE_HOST'}); $rhost = $rhost eq $ipad?gethostbyaddr(pack('C4',split(/\./,$ipad)),2)||'':$rhost; local($ref_url) = $ENV{'HTTP_REFERER'}; s/\?(.|\n)*//ig; s/\%7E/\~/ig; if ($url =~ /^http:\/\//) { $url =~ s/^http\:\/\///g; } if (($name eq '') || (length($name) > 30)) { $error = "名前の記入漏れ、又は文字数制限を超過しています。
\n" } if ((($email !~ /(.*)\@(.*)\.(.*)/) && ($email ne '')) || (length($email) > 120)) { $error .= "メールアドレスの間違い、又は文字数制限を越えています。
\n" } if (($user_message eq '') || (length($user_message) > $max_msg)) { $error .= "メッセージの記入漏れ、又は文字数制限を越えています。
\n" } if($check_url && ($ref_url !~ $check_url)){ $error .= "不当なアクセスです。
$ref_url
\n" } foreach (@check_ipad) { if ($ipad =~ /^$_/) { &error(1,"$ipad からの投稿は拒否されてます。\n"); } } if ($check_proxy) { local($envkey,$envvalue) = (); while(($envkey,$envvalue) = each(%ENV)){ if($envkey =~ /proxy/i || $envvalue =~ /proxy/i){ $error .= "プロクシ経由でのアクセスは禁止されてます。\n"; } } } foreach (@user_icons) { local($icon_gif,$icon_name) = split(/=/,$_); if ($user_icon eq $icon_name) { $user_icon = $icon_gif; $icon_flag = 1;} } if (!$icon_flag) { $error .= "アイコンの選択が不正です。\n"; } if ($error) { &error(1,$error); } &get_date; $no = 0; foreach (@logs) { push(@new,$_); if ($reg_max-2 < ++$no) { last; } } local($count,$ttitle,$tname,$turl,$temail,$tdate,$trhost,$tipad,$tuser_icon,$tuser_message,$tadmin_icon,$tadmin_message) = split(/<>/,$logs[0]); if (($name eq $tname) && ($url eq $turl) && ($email eq $temail) && ($user_icon eq $tuser_icon) && ($user_message eq $tuser_message)) { &error(1,"再読み込み(リロード)による二重投稿は禁止です。"); } if (++$count > 9999) { $count = 1; } unshift (@new,"$count<>$title<>$name<>$url<>$email<>$date<>$rhost<>$ipad<>$user_icon<>$user_message<><>\n"); @logs = &write_file($logfile,@new); &put_cookie($name,$email,$url,$user_icon); } # [ エディターメイン(画面の表示等) ] # sub editor_main { local($edit_data) = &editor_edit; if ($edit_data) { &editor_res($edit_data); } $kiji = @logs; $size = (stat($logfile))[7]; if ($lock_flag) { if (-f $lock1 || -f $lock2) { $comment = "・ ロックファイルが検出されました(ロック中)
"; } else { $comment = "・ ロック機構\は正常に動作しています。
"; } } else { $comment = "・ ロック機構\を使用していません
"; } &html_header; print<<"_EOF_";

[やめる]

G_EDIT


[ G_BOOK の状態 ]
・ 現在 $kiji 件の記事があり、ログファイルは $size バイトになってます
$comment
機能\選択:
良ければ:   やめるなら:
_EOF_ &html_list; print "
\n"; &html_footer; exit; } # [ パスワード入力(エディター) ] # sub editor_password { &html_header; print<<"_EOF_";
管理用パスワードを入力してください。

(管理用のエディタを使用するためには、管理用パスワードが必要です。)

_EOF_ &html_footer; exit; } # [ ログの削除・編集(エディター) ] # sub editor_edit { foreach (@user_icons) { local($icon_gif,$icon_name) = split(/=/,$_); if ($FORM{'user_icon'} eq $icon_name) { $FORM{'user_icon'} = $icon_gif; } } foreach $data (@logs) { if (!$del[(split(/<>/,$data))[0]]) { if ($reg[(split(/<>/,$data))[0]]) { local($no,$title,$name,$url,$email,$date,$rhost,$ipad,$user_icon,$user_message,$admin_icon,$admin_message) = split(/<>/,$data); if ($FORM{'url'} =~ /^http:\/\//) { $FORM{'url'} =~ s/^http\:\/\///g; } $FORM{'user_message'} =~ s/\r\n/
/g; $FORM{'user_message'} =~ s/\r|\n/
/g; $FORM{'admin_message'} =~ s/\r\n/
/g; $FORM{'admin_message'} =~ s/\r|\n/
/g; push (@new,"$no<>$title<>$FORM{'name'}<>$FORM{'url'}<>$FORM{'email'}<>$date<>$rhost<>$ipad<>$FORM{'user_icon'}<>$FORM{'user_message'}<>$FORM{'admin_icon'}<>$FORM{'admin_message'}\n"); $edit_flag = 1; } else { push(@new,$data); } if ($edit[(split(/<>/,$data))[0]]) { $edit_data = $data; } } else { $edit_flag = 1; } } if ($edit_flag) { @logs = &write_file($logfile,@new); } return ($edit_data); } # [ ログの編集画面表示 (エディター) ] # sub editor_res { local($no,$title,$name,$url,$email,$date,$rhost,$ipad,$user_icon,$user_message,$admin_icon,$admin_message) = split(/<>/,$_[0]); $admin_message =~s/\n$//; &html_header; print<<"_EOF_";

G_EDIT


編集したい部分のみ編集して編集ボタンを押して下さい。
レスは管理人レスの部分に書いて下さい。
_EOF_ &html_form($no,$title,$name,$url,$email,$user_icon,$user_message,$admin_icon,$admin_message); &html_footer; exit; } # [ ロック解除(エディター) ] # sub editor_unlock { &unlock_file($lock1); &unlock_file($lock2); } # [ HTML化(エディター) ] # sub editor_html { &get_date; $kiji = @logs; print<<"_EOF_"; Content-type: text/download $title $body $title(G_BOOK) の過去ログです。
$date に作成され、$kiji件の記事があります。
_EOF_ &html_title; $FORM{'pass'} = ''; &html_draw(0,$kiji); &html_footer; exit 0; } sub check_mode { if (!(-f $logfile)) { $axs = "Not Found" } if (-r $logfile) { $axs = "r" } if (-w $logfile) { $axs .= "w" } print<<"_EOF_"; Content-type: text/html\n\n
Version:1.45.00
logfile[$axs] TimeZone:$tz
Method:$method FileName:$cginame Lock:$lock_flag
ImageUrl:$image_url
Owner:$admin_name($admin_email)
Reg_Max:$reg_max Page_Max:$max Msg_Max:$max_msg
TestFormText:$FORM{'test'}
_EOF_ exit; } # [ ログダウンロード(エディター) ] # sub editor_download { print "Content-type: text/download\n\n"; print @logs; exit 0; } # [ ログ初期化(エディター) ] # sub editor_del { @logs = &write_file($logfile,''); @logs = (); } # [ 日付取得 ] # sub get_date { $ENV{'TZ'} = $tz; # TimeZone (日本時間 = 国際標準時(JST) - 9時間) local($sec,$min,$hour,$day,$mon,$year) = localtime(); if ($year < 99) { $year += 100; } $year += 1900; $year = substr($year,length($year)-2,2); $mon++; if ($date_type) { if ($sec < 10) { $sec = "0$sec"; } # 秒の修正 if ($min < 10) { $min = "0$min"; } # 分 〃 if ($hour < 10) { $hour = "0$hour"; } # 時 〃 if ($date_type > 1) { if ($mon < 10) { $mon = "0$mon"; } # 月 〃 if ($day < 10) { $day = "0$day"; } # 日 〃 } } $date =~ s/year/$year/ig; $date =~ s/mon/$mon/ig; $date =~ s/day/$day/ig; $date =~ s/hour/$hour/ig; $date =~ s/min/$min/ig; $date =~ s/sec/$sec/ig; } # [ 自動リンク処理(独自方式 v2.2)] # sub auto_link { local($text) = $_[0]; &jcode'convert(*text,'euc'); $text =~ s/(http:\/\/[\w\.\~\-\/\?\&\+\=\:\@\%\#]+)/$1<\/A>/ig; $text =~ s/(ftp:\/\/[\w\.\~\-\/]+)/$1<\/A>/ig; $text =~ s/([\w\.\-]+)\@([\w\.\-]+)/$1\@$2<\/A>/ig; &jcode'convert(*text,$mojicode); return $text; } # [ フォームからデータ取得 ] # sub read_form { local($pair,$buffer); if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } local(@pairs) = split(/&/,$buffer); foreach $pair (@pairs) { local($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; if ($name eq 'del') { $del[$value] = 1; } elsif ($name eq 'edit') { $edit[$value] = 1; } elsif ($name eq 'reg') { $reg[$value] = 1; } else { $FORM{$name} = &change_code($value); } } } # [ 文字コード関連 ] # sub check_code { if (!(-r $jcode)) { &error(1,"jcode.pl がみつかりません。"); } require $jcode; local($text) = ord(substr("中澤重人=じゃわ(^-^;;",0,1)); if ($text == 0xc3) { $mojicode = "euc"; $charset_code = "x-euc-jp"; } elsif ($text == 0x92) { $mojicode = "sjis";$charset_code = "x-sjis"; } else { &error(1,"サポートしてない文字コードです"); } } sub change_code { local($text)=$_[0]; &jcode'convert(*text,$mojicode); if ($mojicode eq 'sjis') { &jcode'h2z_sjis(*text); } if ($mojicode eq 'euc') { &jcode'h2z_euc(*text); } $text =~ s/\&/&/g; $text =~ s//>/g; return $text; } # [ 記録ファイルの処理 ] # sub read_file { local($logfile) = $_[0]; if ($lock_error) { &error(1,"ロックファイルを検出しました。時間をおいてご利用下さい。"); } if (!open(IN,$logfile)) { &unlock_file; &error(1,"記録ファイルの読み込み不可"); } local(@files) = ; close(IN); return @files; } sub write_file { local($logfile,@lines) = @_; &lock_file($lock1);&lock_file($lock2); if ($lock_error) { &error(1,"ロックファイルを検出しました。時間をおいてご利用下さい。"); } if (!open(OUT,">$logfile")) { &unlock_file; &error(1,"記録ファイルの書き込み不可"); } print OUT @lines; close(OUT); &unlock_file($lock2);&unlock_file($lock1); return @lines; } # [ ロック機構 ] # sub lock_file { local($lockfile) = $_[0]; if (!$lock_flag) { return 1; } local($retry) = 5; while (-f $lockfile) { if ($retry-- <= 0) { local($mtime) = (stat($lockfile))[9]; if ($mtime < time()-60*15) { &unlock_file($lockfile); } $lock_error = 1; return 1; } sleep 1; } open (LOCK,">$lockfile"); close(LOCK); return 1; } sub unlock_file { local($lockfile) = $_[0]; unlink($lockfile); } # -*- クッキーの処理(まーちゃん改良式) *-*-*-*-*-*-*- sub put_cookie { local($name,$email,$url,$user_icon) = (@_); $ENV{'TZ'} = "GMT"; # 国際標準時の取得 local($sec,$min,$hour,$day,$mon,$year,$youbi) =localtime(time + 30*24*60*60); if ($year < 99) { $year += 100; } $year += 1900; if ($year < 10) { $year = "0$year"; } if ($day < 10) { $day = "0$day"; } if ($sec < 10) { $sec = "0$sec"; } if ($min < 10) { $min = "0$min"; } if ($hour < 10) { $hour = "0$hour"; } $mon = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mon]; $youbi = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday')[$youbi]; $date_gmt = "$youbi, $day\-$mon\-$year $hour:$min:$sec GMT"; $cook="bbs_name\:$name\,bbs_email\:$email\,bbs_url\:$url,bbs_icon\:$user_icon"; print"Set-Cookie: $cookie_name=$cook; expires=$date_gmt\n"; ($COOKIE{'bbs_name'},$COOKIE{'bbs_email'},$COOKIE{'bbs_url'},$COOKIE{'bbs_icon'}) = ($name,$email,$url,$user_icon); } sub get_cookie { $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); &jcode'convert(*value,$mojicode); $COOKIE{$name} = &change_code($value); } } # [ エラー処理 ] # sub error { ($err,$err_msg) = @_; if ($err) { print "Content-type: text/html\n\n"; } print<<"_EOF_";
エラー:$err_msg

[ G_BOOK ]
_EOF_ exit; }