# newentry: Blosxom 用に新しいエントリを生成する
# Author(s): Fukazawa tsuyoshi (fukaz55@fo.main.jp)
# Version: 2005-05-28
# Modified by Gosuke Miyashita at 2005-08-15
package newentry;
use CGI qw/:standard/;
use FileHandle;
# --- Configurable variables -----------
# このプラグインの名前
$newentry_plugin_name = "newentry";
# エントリを追加するデフォルトのディレクトリ名
$newentry_category = "bbs";
# 作成するファイルの拡張子
$file_extension = $blosxom::file_extension;
# 許可するコメントのバイト数(最大)
$max_length_comment = 8096;
# 許可するコメントのバイト数(最小)
$min_length_comment = 5;
# 許可する改行の数
$denyret = 30;
# 同一IPから許可する書き込み間隔(秒)
$deny_timesrc = 60;
# エントリ1行目のフォーマット
# $title: 入力タイトル / $name: 名前(URLかe-mailへのリンク込み)
# title がない場合、$name が使用されます
$format_first_line = '$title';
# Writebackがあったエントリを上位に持ってくる機能(いわゆるage)を使用?
$use_age = 1;
# デフォルトのフォーム
my $def_form_template =<<'FORM_';
FORM_
# Writeback 関連設定
# blosxom Starter Kit を使っていない場合、ここに直接値を埋め込んで下さい
# クッキー
my $cookie_expires = $blosxom::writeback_cookie_expires;
my $cookie_domain = $blosxom::writeback_cookie_domain;
my $cookie_path = $blosxom::writeback_cookie_path;
# writebackのデータを保存するディレクトリ名
$writeback_dir = $blosxom::writeback_dir;
# writebackのデータファイルの拡張子
$writeback_file_extension = $blosxom::writeback_file_extension;
# --- Plug-in package variables --------
# 余所から参照できるグローバル変数
$response; # Newentry からのメッセージ
$form; # 入力フォーム
$date; # このエントリの更新時刻文字列 (Writeback 風味)
# このモジュール内部だけで使用する変数
my $create_entry_fn = ''; # このセッションで新規作成したファイル名
my $cookie;
my $fh = new FileHandle;
# --------------------------------------
sub start {
# 書き込み以外で呼ばれた場合はここで終了
if (request_method() ne 'POST' or param('plugin') ne $newentry_plugin_name) {
$response = "Ready to post a comment.";
return 1;
}
# Formから値を取得
my $pref_name = param('name') || '';
my $pref_url = param('url') || '';
my $title = param('title') || '';
my $comment = param('comment') || '';
my $category = param('category') || '';
my $firstline;
my $target_dir = $newentry_category;
$target_dir = $category if ($category);
my $newentry_dir = "$blosxom::datadir/$target_dir";
if (!-d $newentry_dir or !-w $newentry_dir) {
$response = "$path seems to be strange; this entry has not been saved.\n";
return 0;
}
# タグをクリアしたり改行をbrタグに変えたり
$pref_name = &distagcode($pref_name);
$pref_url = &distagcode($pref_url);
$comment = &modcomment($comment);
# 入力チェック
$response = "";
$response = "Please input the name." if ($pref_name eq '');
$response = "Please input the title." if ($title eq '');
$response = "Please input the comments. " if ($comment eq '');
$response = "The comment is too long." if ((length($comment) > $max_length_comment) && $max_length_comment > 0);
$response = "The comment is too short. " if (length($comment) < $min_length_comment);
my @retcheck = split(/
/, $comment);
$response = "There are a lot of changing line. " if ((@retcheck > $denyret) && $denyret > 0);
# 連続書き込み抑制
my $ip = $ENV{'REMOTE_ADDR'};
my $timevalue = time;
if ($fh->open("$newentry_dir/ip.cgi")) {
$ipdata = <$fh>;
@iplog_ary = split(/<>/, $ipdata);
$response = "Please write it again a little more after time passes." if (($iplog_ary[0] eq $ip) && ($iplog_ary[1] > $timevalue - $deny_timesrc));
}
$fh->close();
# block: Invalid Referer
if (param('$comment') and $ENV{'HTTP_REFERER'} ne "$blosxom::url") {
$response = "Someone post a Comment with invalid referer.";
}
# コメントスパム対応
if (isSPAM($comment)) {
$response = "The comment was refused.";
}
# チェックにひっかかったらこの段階で終了
return 1 if ($response ne "");
# IPアドレス記録
if ($fh->open("> $newentry_dir/ip.cgi")) {
print $fh "$ip<>$timevalue";
}
$fh->close();
# 記事のファイル名を生成
my $fn = &create_entry_name($timevalue);
$create_entry_fn = "$newentry_dir/$fn.$file_extension";
# 書き込み
if ($fh->open("> $create_entry_fn")) {
# タイトルにURL/メアドを付加
my $pref_name_a = $pref_name;
if ($pref_url =~ /[!-~]+\@[!-~]+\.[!-~]+/) {
$pref_name_a = qq!$pref_name!;
} elsif ($pref_url ne '') {
$pref_name_a = qq!$pref_name!;
}
# タイトルがない場合は名前をタイトルに
if ($title eq '') {
$firstline = $pref_name_a;
} else {
$firstline = $format_first_line;
$firstline =~ s/\$title/$title/ge;
$firstline =~ s/\$name/$pref_name_a/ge;
}
# 読みやすいようにコメントに改行をつける
$comment =~ s!
!
\n!g;
# metaでtitle, name, url, mailを記述
my $secondline = "meta-title: $title\n";
$secondline .= "meta-name: $name\n";
if ($pref_url =~ /[!-~]+\@[!-~]+\.[!-~]+/) {
$secondline .= "meta-mail: $pref_url\n";
} elsif ($pref_url ne '') {
$secondline .= "meta-url: $pref_url\n";
}
$secondline .= "meta-link: $pref_name_a\n";
# 書き込み
print $fh "$firstline\n$secondline\n$comment\n";
}
$fh->close();
# クッキーに保存
$cookie = cookie (
-name => 'writeback',
-value => {
name => $pref_name,
url => $pref_url,
},
-expires => $cookie_expires,
-domain => $cookie_domain,
-path => $cookie_path,
) if param('save_preferences');
# おわり
$response = "Thank you for writing it!";
1;
}
sub filter {
my ($pkg, $files_ref) = @_;
# さっき作成したファイルがリストになかったらここで追加
# ($blosxom::show_future_entries = 0 の場合は追加してくれない可能性があるため)
if ((-f $create_entry_fn) && (!grep(/^$create_entry_fn$/, keys %$files_ref))) {
$files_ref->{$create_entry_fn} = (stat($create_entry_fn))[9];
}
1;
}
sub head {
my($pkg, $currentdir, $head_ref) = @_;
my %param = ();
my $pref_name;
my $pref_url;
# Writebackクッキーから名前とURLを取得
if (%cookies = cookie(-name => 'writeback')) {
$pref_name = $cookies{'name'};
$pref_url = $cookies{'url'};
}
$param{'name'} = $pref_name;
$param{'url'} = $pref_url;
$param{'response'} = $response;
# フォームを展開
$form = &$blosxom::template($path,'newentry','html') || $def_form_template;
$form =~ s/\$newentry::(\w+)/$param{$1}/ge;
1;
}
sub sort {
return undef if (!$use_age);
return sub {
my($files_ref) = @_;
my %blogts;
my $wb_filename;
foreach (keys %$files_ref) {
# ファイル時刻を取得
$blogts{$_} = $files_ref->{$_};
# このファイルに対するWritebackファイル名を作成
$wb_filename = $_;
$wb_filename =~ s/$blosxom::datadir/$writeback_dir/;
$wb_filename =~ s/\.$blosxom::file_extension/\.$writeback_file_extension/;
# もしWritebackがあったら、エントリの更新時刻をWritebackのものに置き換える
$blogts{$_} = (stat($wb_filename))[9] if (-f $wb_filename);
}
return sort { $blogts{$b} <=> $blogts{$a} } keys %blogts;
};
}
sub story {
# エントリの日付文字列をWritebackっぽく生成
my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
my $entry_filename = "$blosxom::datadir$path/$filename.$blosxom::file_extension";
if (-e $entry_filename) {
my $ft = (stat($entry_filename))[9];
$date = &get_posttime_str($ft);
}
1;
}
sub foot {
# クッキー書き込み
$blosxom::header->{'-cookie'} = $cookie if $cookie;
1;
}
# タグを削除
sub distagcode {
$_ = shift;
s/<.*?>//gm; s/\r|\n//gm;
s/&/&/gm; s/&/&/gm; s/"/"/gm; s/'/'/gm; # この行を追加
return $_;
}
# コメント加工
sub modcomment {
$_ = shift;
s/<.*?>//gm; # この行を追加
s/&/&/gm; s/&/&/gm; s/"/"/gm; s/'/'/gm; # この行を追加
# 末尾の改行は削除
s/\r\n$//; s/\r$//; s/\n$//;
# 改行はタグに変換
s!\r\n!
!g; s!\r!
!g; s!\n!
!g;
# URL変換
s!http://([\x21-\x3b\x3d\x3f-\x7e]+)!http://$1!g;
return $_;
}
# ファイル名生成
sub create_entry_name {
my $time = shift;
my($ss, $nn, $hh, $dd, $mm, $yy, $ww) = format_time($time);
return "$yy$mm$dd" . "_" . "$hh$nn$ss";
}
# 表示する日時を生成
sub get_posttime_str {
my $time = shift;
my($ss, $nn, $hh, $dd, $mm, $yy, $ww) = format_time($time);
return "$yy/$mm/$dd ($ww) $hh:$nn:$ss";
}
sub format_time {
my $time = shift;
my($ss, $nn, $hh, $dd, $mm, $yy, $ww) = localtime($time);
$yy = $yy + 1900;
$mm = sprintf "%02d", ++$mm;
$dd = sprintf "%02d", $dd;
$hh = sprintf "%02d", $hh;
$nn = sprintf "%02d", $nn;
$ss = sprintf "%02d", $ss;
my @wdays = qw(Sun Mon Tue Wed Thu Fri Sat);
$time = "$yy/$mm/$dd ($wdays[$ww]) $hh:$nn:$ss";
return ($ss, $nn, $hh, $dd, $mm, $yy, $wdays[$ww]);
}
# コメントスパム対応
# 全部アルファベットだったらスパム
sub isSPAM {
my $t = shift;
$t =~ s/[\n\t 0-9\-+!@#$\%^&*(){}_=a-zA-Z\[\]\\;`':",.\/<>?|\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]//ge;
if ($t eq "") {
return 1;
} else {
return 0;
}
}
sub debug_log {
$fh->open(">> $newentry_plugin_name.log");
foreach (@_) {
print $fh $_, ":";
}
print $fh "\n";
$fh->close();
}
1;
__END__
# Mod: 2005-05-28:
# 機能そぎ落とし版作成