#!/usr/bin/perl #Web Board ResVersion (2004/01/19) $ver = '2.08'; # #Copyright(C) Knight 2002-2004 #Mail ... knight@big.or.jp #Home ... http://www.big.or.jp/~knight/ #――――― 設定項目 ―――――――――――――――――――――――― #――――― 基本設定 ――――――――――――――――――― #タイトル $title = 'Free Talk Board'; #トップメッセージ $top_message = '★ み ん な と お は な し が し た い な ぁ  ★'; #管理者用パスワード $admin_pwd = 'sadmin'; #リンクの戻り先 $back_url = '/lmp/infomation.shtml'; #――――― タイトル画像の設定 #掲示板タイトルの画像(タイトルに画像を使用しない場合は空欄にする) $title_img = 'bbs.gif'; #タイトル画像の幅(タイトルに画像を使用した場合に設定) $title_width = '725'; #タイトル画像の高さ(タイトルに画像を使用した場合に設定) $title_height = '100'; #――――― システムの設定 ―――――――――――――――― #スクリプト $script = './board.cgi'; #ログファイル $log_file = './board.log'; #ロックファイル $lock_file = './lock/board.lock'; #スタイルシート $css_file = './style.css'; #過去ログ作成ディレクトリ(過去ログを作成しない場合は無効) $past_dir = './past/'; #過去ログファイルの拡張子(過去ログを作成しない場合は無効) $past_ext = '.log'; #文字コード変換ライブラリ require './jcode.pl'; #――――― 投稿時の設定 #投稿記事本文の色の指定(0 … 指定不可 / 1 … 指定可) $color_mode = 1; #投稿記事本文の色の設定(本文の色の指定機能を使用しない場合は無効) @color = ( '#808080', '#B38099', '#8080B3', '#80B380', '#B3B380', '#FF9955', '#FF77DD', '#FF7777', '', '' ); #――――― ログ関連の設定 #1ページの表示ログ数 $page_size = 10; #過去ログの作成機能の使用(0 … 使用しない / 1 … 使用する) $make_past = 0; #スレッドの最大保存数(過去ログを作成する場合は無効) $max_log = 30; #過去ログスレッドの作成サイズ(過去ログを作成しない場合は無効) $past_size = 30; #――――― アクセス制限の設定 #自サイトのURL(設定すると、このURLを含まないサイトからの投稿を拒否します。http:// から指定すること) $base_url = ''; #ホスト名取得時のgethostbyaddr関数の使用(0 … 使用しない / 1 … 使用する) $gethostbyaddr = 1; #――――― クッキーの設定 #クッキー保存日数(30日以上に設定すること) $hold_days = 90; #クッキーの識別名 $cookie_id = 'webboard'; #――――― 設定項目終了 ―――――――――――――――――――――― ### メイン処理 &decode(); if ($in{'mode'} eq 'res') { &res(); } elsif ($in{'mode'} eq 'howto') { &howto(); } elsif ($in{'mode'} eq 'search') { &search(); } elsif ($in{'mode'} eq 'userdel') { &userdel(); } elsif ($in{'mode'} eq 'past' && $make_past == 1) { &past(); } elsif ($in{'mode'} eq 'admin') { &admin(); } elsif ($in{'mode'} eq 'regist') { ®ist(); } &html(); ### HTML出力 sub html { open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); $parent = 0; foreach (@logs) { if ((split(/\t/))[1] == 0) { $parent++; } } &header(); print <<"_HTML_";
_HTML_ if ($title_img ne '') { print qq|
$title

\n|; } else { print qq|

$title

\n|; } print <<"_HTML_"; $top_message


_HTML_ &form(); &navigator(); &showlog(); &navigator(); print qq|
\n|; &footer(); } ### 投稿フォーム表示 sub form { if ($ENV{'REQUEST_METHOD'} ne 'POST') { %cookie = &get_cookie($cookie_id); if ($cookie{'url'} eq '') { $cookie{'url'} = 'http://'; } if ($cookie{'color'} eq '') { $cookie{'color'} = $color[0]; } } if ($in{'mode'} eq 'res') { $subj = 'Re:' . (split(/\t/, $logs[0]))[6]; $submit = '返信する'; } else { $subj = ''; $in{'no'} = 0; $submit = '投稿する'; } print <<"_HTML_";

_HTML_ if ($color_mode == 1) { print <<"_HTML_"; _HTML_ } print <<"_HTML_";
名前
Eメール
URL _HTML_ if ($in{'mode'} ne 'res') { print <<"_HTML_";
題名 _HTML_ } else { print <<"_HTML_"; _HTML_ } print <<"_HTML_";
本文
本文の色 _HTML_ foreach (@color) { if ($_ eq '') { next; } if ($cookie{'color'} eq $_) { print qq| / |; } else { print qq| / |; } } print <<"_HTML_";
削除キー


_HTML_ return; } ### 投稿記事表示 sub showlog { $start = $in{'page'} * $page_size; $end = $start + $page_size; $i = 0; $flag = 0; foreach (@logs) { ($no, $reno, $date, $name, $mail, $url, $subj, $text, $color, $icon, $file, $rank, $pwd, $host) = split(/\t/); if ($in{'mode'} eq 'search' || $reno == 0) { $i++; } if ($i <= $start) { next; } if ($i > $end) { last; } ($sec, $min, $hour, $day, $mon, $year, $week) = localtime($date); @week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); $date = sprintf("/ %04d/%02d/%02d/%s/%02d:%02d", $year + 1900, $mon + 1, $day, $week[$week], $hour, $min); if ($mail ne '') { $mail = qq|/ Eメール|; } if ($url ne '') { $url = qq|/ URL|; } if ($in{'mode'} eq '') { $res = qq|/ 返信|; } $text = &auto_link($text); if ($color_mode == 1) { if ($color eq '') { $color = $color[0]; } $text = qq|$text|; } chop($host); if (($in{'mode'} eq 'search' && $flag == 1) || ($flag == 1 && $reno == 0)) { print <<"_HTML_";

_HTML_ } if ($in{'mode'} eq 'search' || $reno == 0) { $flag = 1; print <<"_HTML_";

_HTML_ } else { print <<"_HTML_"; _HTML_ } } print <<"_HTML_";
$subj $res
No.$no - $name $mail $url $date

  $text  

No.$no - $name $mail $url $date

  $text  

_HTML_ return; } ### ページナビゲーター表示 sub navigator { $new = '最新の投稿'; $prev = '↑前のページ'; $next = '↓次のページ'; if ($in{'page'} > 0) { $new = qq|$new|; } if ($in{'page'} > 0) { $n = $in{'page'} - 1; $prev = qq|$prev|; } if (int(($parent - 1) / $page_size) > $in{'page'}) { $n = $in{'page'} + 1; $next = qq|$next|; } print qq|\n|; return; } ### 返信フォーム表示 sub res { open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); @res = (); foreach (@logs) { ($no, $reno) = split(/\t/); if ($in{'no'} == $no || $in{'no'} == $reno) { push(@res, $_); } } @logs = @res; &header(); print <<"_HTML_";

返信フォーム

_HTML_ &showlog(); &form(); &footer(); } ### 使い方表示 sub howto { if ($color_mode == 1) { $color_cookie = '本文の色、'; } &header(); print <<"_HTML_";

掲示板の使い方

■ 記事の投稿

  1. 入力の必須項目は、名前本文です。その他の項目は任意となります。
  2. ブラウザがクッキー対応の場合、名前EメールURL、$color_cookie削除キーの情報は、次回から自動的に入力されます。
  3. 投稿記事にHTMLタグを使用することはできません。
  4. 本文にURLを入力すると、自動的にリンクが張られます。

■ 掲示板の機能\

  1. 投稿記事の返信をクリックすると、その記事に対して返信ができます。
  2. ログ検索をクリックすると、ログの内容を検索することができます。
  3. 削除キーを入力しておくと、記事削除から自分の投稿記事を削除することができます。

■ 免責事項

  1. 他人や組織に対する誹謗中傷、公序良俗に反する発言、その他管理人が著しく不利益と判断した記事は予\告なく削除することがあります。
  2. この掲示板の利用によって生じた如何なる損害も、管理人はその責を負いませんので予\めご了承ください。


_HTML_ &footer(); } ### ログ検索 sub search { &header(); print <<"_HTML_";

ログ検索

■ 検索したいキーワードを入力し、検索ボタンを押してください。
■ キーワードは半角スペースで区切って複数指定することができます。

_HTML_ if ($make_past == 1) { print <<"_HTML_"; _HTML_ } print <<"_HTML_";
キーワード:
検索条件:
検索対象:
 

_HTML_ if ($in{'word'} ne '') { if ($make_past == 0 || $in{'obje'} ne 'past') { open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @search = ; close(FILE); } if ($make_past == 1 && $in{'obje'} ne 'now') { opendir(DIR, "$past_dir") || &error("過去ログディレクトリを読み出せません"); @dir = readdir(DIR); closedir(DIR); @dir = sort {$b <=> $a} (@dir); @past = (); foreach (@dir) { if ($_ =~ /^\d+(\.\w+)$/ && $1 eq $past_ext) { open(FILE, "$past_dir$_") || &error("過去ログファイルを読み出せません"); @file = ; close(FILE); push(@past, @file); } } if ($in{'obje'} eq 'all') { push(@search, @past); } elsif($in{'obje'} eq 'past') { @search = @past; } } $in{'word'} =~ s/ / /g; @pairs = split(/\s+/, $in{'word'}); @logs = (); foreach (@search) { $flag = 0; foreach $pair (@pairs) { if (index($_, $pair) >= 0) { $flag = 1; if ($in{'cond'} eq 'or') { last; } } else { if ($in{'cond'} eq 'and') { $flag = 0; last; } } } if ($flag != 0) { push(@logs, $_); } } print qq|
\n|; &showlog(); } print '
'; &footer(); } ### ユーザー記事削除 sub userdel { if ($in{'prev'} ne '') { $in{'page'}--; } if ($in{'next'} ne '') { $in{'page'}++; } if ($in{'delete'} ne '') { if ($ENV{'REQUEST_METHOD'} ne 'POST') { &error("不正なアクセスです"); } if ($ENV{'HTTP_REFERER'} ne '' && $base_url ne '' && $ENV{'HTTP_REFERER'} !~ /^$base_url/i) { &error("不正なアクセスです"); } if ($in{'user_pwd'} eq '') { &error("削除キーを入力してください"); } if ($in{'del'} eq '') { &error("削除したい記事を選択してください"); } &lock($lock_file); open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); @new = (); $flag = 0; $del_list = ''; foreach (@logs) { ($no, $reno, $pwd) = (split(/\t/))[0, 1, 12]; if ($flag == 0 && $in{'del'} == $no) { &decrypt($in{'user_pwd'}, $pwd); $flag = 1; } elsif ($flag == 1 && $in{'del'} == $reno) { $flag = 1; } else { $flag = 0; } if ($flag == 0) { push(@new, $_); } else { $del_list .= " [$no]"; } } $work_mesg = "$del_list番の記事を削除しました"; open(FILE, ">$log_file") || &error("ログファイルに書き込めません"); print FILE @new; close(FILE); &unlock($lock_file); } open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); $parent = 0; foreach (@logs) { if ((split(/\t/))[1] == 0) { $parent++; } } &header(); print <<"_HTML_";

記事削除

削除キーを入力して削除したい記事にチェックを入れ、削除ボタンを押してください。
■ 投稿時に削除キーを設定していなければ記事を削除することはできません。



スレッド数 $parent件 / $work_mesg

_HTML_ $start = $in{'page'} * $page_size; $end = $start + $page_size; $i = 0; foreach (@logs) { ($no, $reno, $date, $name, $mail, $url, $subj, $text, $color, $icon, $file, $rank, $pwd, $host) = split(/\t/); if ($reno == 0) { $i++; } if ($i <= $start) { next; } if ($i > $end) { last; } if ($reno == 0) { $subj = "$subj"; } $text =~ s/
//gi; $text =~ s//>/g; if (length($text) > 60) { $text = substr($text, 0, 60) . ' …'; } print <<"_HTML_"; _HTML_ } print <<"_HTML_";
削除 No 投稿者 題名 本文
$no $name $subj $text


_HTML_ &footer(); } ### 過去ログ表示 sub past { opendir(DIR, "$past_dir") || &error("過去ログディレクトリを読み出せません"); @dir = readdir(DIR); closedir(DIR); @dir = sort {$a <=> $b} (@dir); $past_byte = 0; foreach (@dir) { if ($_ =~ /^\d+(\.\w+)$/ && $1 eq $past_ext) { $past_byte += (stat("$past_dir$_"))[7]; } } &header(); print <<"_HTML_";

過去ログ

■ 表\示したい過去ログを選択し、表\示ボタンを押してください。
ログ検索によって過去ログを検索することができます。

_HTML_ if ($in{'view'} ne '' && $in{'view'} =~ /^\d+\.\w+$/ && -e "$past_dir$in{'view'}") { open(FILE, "$past_dir$in{'view'}") || &error("過去ログファイルを読み出せません"); @logs = ; close(FILE); $page_size = $past_size; print '
'; &showlog(); } print '
'; &footer(); } ### 管理者用 sub admin { if ($in{'admin_pwd'} eq '') { &header(); print <<"_HTML_";

管理者パスワードを入力してください

_HTML_ &footer(); } else { if ($ENV{'REQUEST_METHOD'} ne 'POST') { &error("不正なアクセスです"); } if ($ENV{'HTTP_REFERER'} ne '' && $base_url ne '' && $ENV{'HTTP_REFERER'} !~ /^$base_url/i) { &error("不正なアクセスです"); } if ($in{'admin_pwd'} ne $admin_pwd) { &error("パスワードが違います"); } if ($in{'prev'} ne '') { $in{'page'}--; } if ($in{'next'} ne '') { $in{'page'}++; } if ($make_past == 1 && ($in{'create_log'} ne '' || $in{'read_log'} ne '')) { &lock($lock_file); opendir(DIR, "$past_dir") || &error("過去ログディレクトリを読み出せません"); @dir = readdir(DIR); closedir(DIR); @dir = sort {$a <=> $b} (@dir); open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); if ($in{'create_log'} ne '') { $dir[$#dir] =~ /([^\/\\]*)\.([^.\/\\]*)$/; $past_file = ($1 + 1) . $past_ext; @past = (); (*logs, *past) = &move_log(*logs, *past, $past_size); open(FILE, ">$past_dir$past_file") || &error("過去ログファイルを作成できません"); print FILE @past; close(FILE); chmod(0666, "$past_dir$past_file"); $work_mesg = "スレッド$past_size件を過去ログに移動しました"; } if ($in{'read_log'} ne '') { $past_file = $dir[$#dir]; open(FILE, "$past_dir$past_file") || &error("過去ログファイルを読み出せません"); @past = ; close(FILE); (*logs, *past) = &move_log(*logs, *past, 're'); unlink("$past_dir$past_file"); $work_mesg = "スレッド$past_size件を過去ログから読み戻しました"; } open(FILE, ">$log_file") || &error("ログファイルに書き込めません"); print FILE @logs; close(FILE); &unlock($lock_file); } if ($in{'delete'} ne '') { if ($delete[0] eq '') { &error("削除したい記事を選択してください"); } &lock($lock_file); open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); @new = (); $del_list = ''; foreach (@logs) { ($no, $reno) = split(/\t/); $flag = 0; foreach $del (@delete) { if ($no == $del || $reno == $del) { $flag = 1; last; } } if ($flag == 0) { push(@new, $_); } else { $del_list .= " [$no]"; } } $work_mesg = "$del_list番の記事を削除しました"; open(FILE, ">$log_file") || &error("ログファイルに書き込めません"); print FILE @new; close(FILE); &unlock($lock_file); } if ($in{'download'} ne '') { open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); print "Content-type: text/download\n\n"; print @logs; exit; } open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); $log_byte = &comma(int((stat($log_file))[7] / 1024)); if ($logs[0] ne '' && $log_byte == 0) { $log_byte = 1; } if ($make_past == 1) { opendir(DIR, "$past_dir") || &error("過去ログディレクトリを読み出せません"); @dir = readdir(DIR); closedir(DIR); $past_byte = 0; foreach (@dir) { if ($_ =~ /^\d+(\.\w+)$/ && $1 eq $past_ext) { $past_byte += (stat("$past_dir$_"))[7]; } } $past_byte = &comma(int($past_byte / 1024)); } $parent = 0; foreach (@logs) { if ((split(/\t/))[1] == 0) { $parent++; } } &header(); print <<"_HTML_";

管理者用

■ 削除したい記事にチェックを入れ、削除ボタンを押してください。
ダウンロードボタンを押すと、現在のログをダウンロードします。
_HTML_ if ($make_past == 1) { print qq|■ スレッドが$past_size件以上になると過去ログを作成することができます。
\n|; } else { print qq|■ スレッドが$max_log件以上になると古いスレッドから削除されます。
\n|; } print <<"_HTML_";

_HTML_ if ($make_past == 1 && $parent > $past_size) { print qq|\n|; } if ($make_past == 1 && $past_byte > 0) { print qq|\n|; } print <<"_HTML_";

ログサイズ $log_byteKB / _HTML_ if ($make_past == 1) { print qq|過去ログサイズ $past_byteKB / \n|; } print <<"_HTML_"; スレッド数 $parent件 / $work_mesg

_HTML_ $start = $in{'page'} * $page_size; $end = $start + $page_size; $i = 0; foreach (@logs) { ($no, $reno, $date, $name, $mail, $url, $subj, $text, $color, $icon, $file, $rank, $pwd, $host) = split(/\t/); if ($reno == 0) { $i++; } if ($i <= $start) { next; } if ($i > $end) { last; } if ($reno == 0) { $subj = "$subj"; } $text =~ s/
//gi; $text =~ s//>/g; if (length($text) > 60) { $text = substr($text, 0, 60) . ' …'; } chop($host); print <<"_HTML_"; _HTML_ } print <<"_HTML_";
削除 No 投稿者 題名 本文 ホスト
$no $name $subj $text $host


_HTML_ &footer(); } } ### 記事登録 sub regist { if ($ENV{'REQUEST_METHOD'} ne 'POST') { &error("不正なアクセスです"); } if ($ENV{'HTTP_REFERER'} ne '' && $base_url ne '' && $ENV{'HTTP_REFERER'} !~ /^$base_url/i) { &error("不正なアクセスです"); } $host = $ENV{'REMOTE_HOST'}; $addr = $ENV{'REMOTE_ADDR'}; if ($host eq "" || $host eq $addr) { if ($gethostbyaddr == 1) { $host = gethostbyaddr(pack("C4", split(/\./, $addr)), 2) || $addr; } } $in{'name'} = &create_line($in{'name'}); $in{'mail'} = &create_line($in{'mail'}); $in{'url'} = &create_line($in{'url'}); $in{'subj'} = &create_line($in{'subj'}); $in{'pwd'} = &create_line($in{'pwd'}); $in{'text'} = &create_text($in{'text'}); if ($in{'name'} eq '') { &error("名前が入力されていません"); } if (length($in{'name'}) > 15 * 2) { &error("名前の長さは全角15文字までにしてください"); } if (($in{'mail'} ne '' && $in{'mail'} =~ /[^\w\.\@\d\-\_]/ && $in{'mail'} !~ /(.*)\@(.*)\.(.*)/) || length($in{'mail'}) > 50) { &error("Eメールの入力内容が正しくありません"); } if (length($in{'url'}) > 70) { &error("URLの入力内容が正しくありません"); } if ($in{'reno'} == 0 && length($in{'subj'}) > 20 * 2) { &error("題名の長さは全角20文字までにしてください"); } elsif (length($in{'subj'}) > 22 * 2) { &error("題名の長さは全角22文字までにしてください"); } if ($in{'text'} eq '') { &error("本文が入力されていません"); } if (length($in{'text'}) > 3000 * 2) { &error("本文の長さは全角3000文字までにしてください"); } if (($in{'text'} =~ s/
/
/g) + 1 > 100) { &error("本文は100行までにしてください"); } if (length($in{'pwd'}) > 10) { &error("削除キーの長さは半角10文字までにしてください"); } $cookie{'name'} = $in{'name'}; $cookie{'mail'} = $in{'mail'}; $cookie{'url'} = $in{'url'}; $cookie{'color'} = $in{'color'}; $cookie{'pwd'} = $in{'pwd'}; &set_cookie(*cookie, $cookie_id, $hold_days); &lock($lock_file); open(FILE, "$log_file") || &error("ログファイルを読み出せません"); @logs = ; close(FILE); $no = 0; $parent = 0; $name = ''; $text = ''; foreach (@logs) { if ($_ + 0 > $no) { ($no, $date, $name, $text, $ip) = (split(/\t/))[0, 2, 3, 7, 13]; } if ((split(/\t/))[1] == 0) { $parent++; } } $no++; if ($in{'name'} eq $name && $in{'text'} eq $text) { &unlock($lock_file); &error("二重投稿は禁止です"); } chop($ip); if (time() - $date < 60 && $host eq $ip) { &unlock($lock_file); &error("連続投稿は60秒以上時間をあけてください"); } $date = time(); if ($in{'subj'} eq '') { $in{'subj'} = '無題'; } if ($in{'url'} eq 'http://') { $in{'url'} = ''; } if ($in{'pwd'} ne '') { $in{'pwd'} = &encrypt($in{'pwd'}); } $line = "$no\t$in{'reno'}\t$date\t$in{'name'}\t$in{'mail'}\t$in{'url'}\t$in{'subj'}\t$in{'text'}\t$in{'color'}\t$in{'icon'}\t$in{'file'}\t$in{'rank'}\t$in{'pwd'}\t$host\n"; if ($in{'reno'} != 0) { @new = (); $flag = 0; foreach (@logs) { ($no, $reno) = split(/\t/); if ($flag == 0 && $in{'reno'} == $no) { $flag = 1; } elsif ($flag == 1 && $in{'reno'} != $reno) { $flag = 2; push(@new, $line); } push(@new, $_); } if ($flag == 1) { push(@new, $line); } @logs = @new; } else { if ($make_past == 0 && $parent >= $max_log) { foreach (0 .. ($parent - $max_log)) { ($no, $reno) = split(/\t/, $logs[$#logs]); if ($reno == 0) { pop(@logs); } else { while ((split(/\t/, $logs[$#logs]))[1] != 0) { pop(@logs) } pop(@logs); } } } unshift(@logs, $line); } open(FILE, ">$log_file") || &error("ログファイルに書き込めません"); print FILE @logs; close(FILE); &unlock($lock_file); $in{'mode'} = ''; return; } ### デコード sub decode { if ($ENV{'REQUEST_METHOD'} eq 'POST') { if ($ENV{'CONTENT_LENGTH'} > 15000) { &error("投稿量が大きすぎます
現在の投稿量:$ENV{'CONTENT_LENGTH'} / 最大投稿量:15000"); } read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'}); } else { $alldata = $ENV{'QUERY_STRING'}; } foreach $data (split(/&/, $alldata)) { ($key, $value) = split(/=/, $data); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg; $value =~ s/\t//g; &jcode'convert(*value, 'sjis', '', 'z'); $value =~ s/&/&/g; $value =~ s//>/g; $value =~ s/"/"/g; if ($key eq 'del') { push(@delete, $value); } $in{"$key"} = $value; } $in{'page'} += 0; return; } ### HTMLヘッダ sub header { print <<"_HTML_"; Content-Type: text/html $title
_HTML_ return; } ### HTMLフッタ sub footer { print <<"_HTML_";
_HTML_ exit(); } ### エラー出力 sub error { local($_) = @_; &header(); print <<"_HTML_";




エラーが発生しました

$_



_HTML_ &footer(); } ### INPUT情報正規化 sub create_line { local($_) = @_; $_ =~ s/^\s+//; $_ =~ s/\s+$//; return $_; } ### TEXTAREA情報正規化 sub create_text { local($_) = @_; $_ =~ s/\r?\n/\r/g; $_ =~ s/^\r+//; $_ =~ s/\r+$//; $_ =~ s/\r/
/g; return $_; } ### オートリンク sub auto_link { local($_) = @_; $_ =~ s/(https?:\/\/[\w\.\~\-\/\?\&\#\+\=\:\;\@\%]+)/$1<\/a>/gi; $_ =~ s/([\w\-]+\@[\w\-\.]+)/$1<\/a>/gi; return $_; } ### コンマの付加 sub comma { local($_) = @_; while ($_ =~ s/^([-+]?\d+)(\d\d\d)/$1,$2/) {} return $_; } ### 削除キー暗号化 sub encrypt { local($_) = @_; srand(time + $$); local $salt = pack('CC', int(rand(26) + 65), int(rand(10) + 48)); return crypt($_, $salt); } ### 削除キー照合 sub decrypt { local($inpwd, $pwd) = @_; if ($pwd eq '') { &error("該当記事には削除キーが設定されていません"); } if (crypt($inpwd, $pwd) ne $pwd) { &error("削除キーが違います"); } return; } ### ログ移動処理 sub move_log { local(*logs, *past, $size) = @_; if ($size ne 're') { foreach (1 .. $size) { while ((split(/\t/, $logs[$#logs]))[1] != 0) { unshift(@past, pop(@logs)); } unshift(@past, pop(@logs)); } } else { foreach (@past) { push(@logs, $_); } } return (*logs, *past); } ### ファイルロック sub lock { local($lock_file) = @_; local $flag = 0; foreach (1 .. 5) { if (-e $lock_file) { if (time() > (stat($lock_file))[9] + 60) { &unlock($lock_file); next; } sleep(1); } else { open(LOCK, ">$lock_file") || &error("ロックファイルが作成できません"); close(LOCK); $flag = 1; last; } } if ($flag == 0) { &error("ファイルがロックされています
時間をおいてもう一度投稿してください"); } return; } ### ファイルロック解除 sub unlock { local($_) = @_; unlink($_); return; } ### クッキー関連の処理 sub get_cookie { local($cookie_id) = @_; local %all_cookies = (); foreach (split(/; /, $ENV{'HTTP_COOKIE'})) { local($key, $value) = split(/=/); $all_cookies{"$key"} = $value; } foreach (split(/&/, $all_cookies{"$cookie_id"})) { local ($key, $value) = split(/:/); $value =~ s/&/&/g; $value =~ s//>/g; $value =~ s/"/"/g; $cookie{&unescape($key)} = &unescape($value); } return %cookie; } sub set_cookie { local(*cookie, $cookie_id, $hold_days) = @_; if (time() > $cookie{'refresh'} + 60 * 60 * 24 * 30) { $cookie{'refresh'} = time(); } local @pairs = (); foreach (sort keys %cookie) { push(@pairs, &escape($_) . ':' . &escape($cookie{"$_"})); } local $new_cookie = join('&', @pairs); local $date = &gmt_date(time + 60 * 60 * 24 * $hold_days); if ($new_cookie ne $all_cookies{"$cookie_id"}) { print "Set-Cookie: $cookie_id=$new_cookie; expires=$date\n"; } return; } sub escape { local($_) = @_; $_ =~ s/([&:;=%\x00-\x21])/sprintf("%%%02X", unpack('C',$1))/ge; return $_; } sub unescape { local($_) = @_; $_ =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/ge; return $_; } sub gmt_date { local($_) = @_; local($sec, $min, $hour, $day, $mon, $year, $wday) = gmtime($_); local @week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); local @month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT", $week[$wday], $day, $month[$mon], $year + 1900, $hour, $min, $sec); }