
投票cgiを作成していますが、以下のPerlでは、同一IPから1日1回の投票しかできません。
同一IPからの投票を1日連続5回まで許可する仕組みにしたいと考えています。(6回目以降は単にカウントされないだけで警告等は出さない)
以下のPerlをどのように改造すれば良いか具体的にアドバイスを頂けると大変助かります。
かなり専門的な内容で恐縮ですが、困っておりますので、何卒よろしくお願い致します。
m(_ _)m
---------------------
# IPアドレスのチェック
sub IpCheck {
if (!-e $iplog) {
&TimeLog;
}
$last = (localtime((stat($iplog))[9] + $jisa))[3];
$today = (localtime($nowtime))[3];
if ($last != $today) {
unlink($iplog);
&TimeLog;
}
open(TLOG,"<$iplog");
@IP = <TLOG>;
close(TLOG);
$l = 0;
foreach (@IP) {
$_ =~ s/\r|\n//g;
if ($_ =~ /^$addr/) {
&NoCnt;
}
elsif ($l == $#IP) {
if (!open(RTIP,">>$iplog")) {
&Error(4);
}
print RTIP "$addr\n";
close(RTIP);
&CNTUP;
}
$l++;
}
}
sub TimeLog {
if (!open(TIME,">$iplog")) {
&Error(5);
}
print TIME "$addr\n";
close(TIME);
chmod(0666,$iplog);
&CNTUP;
}
#-------------------------------------------------
# クリックカウントアップ
sub CNTUP {
#ファイルロック開始
if( $lockkey ne '0' ){ &LOCK; }
if (!open(IN,"$linkdata_file")) { &ERROR( read_linkdata ); }
@BASE = <IN>;
close(IN);
foreach $data (@BASE) {
#データリスト読込
&LINKDATALIST;
if( $in{'targetno'} eq $CNTNUM ){
$COUNTERUP = $CLICK + 1;
$targeturl = $LINKURL;
$new_data = "$CNTNUM,$DATE_LINKDATA,$DATE_LMT,$DATE_ESY,$OPN,$NEWMARK,$CATEGORY,$LINKNAME,$HONORIFIC,$LINKURL,$COMMENT,$COUNTERUP,$IMAGE,\n";
}else{
$new_data = "$CNTNUM,$DATE_LINKDATA,$DATE_LMT,$DATE_ESY,$OPN,$NEWMARK,$CATEGORY,$LINKNAME,$HONORIFIC,$LINKURL,$COMMENT,$CLICK,$IMAGE,\n";
}
#ファイルの最初にデータを保存する
push( @TOTAL , $new_data );
}
#実際にファイルに書き込む
if (!open(NOTE,">$linkdata_file")) { &ERROR( read_linkdata ); }
print NOTE @TOTAL;
close(NOTE);
#ファイルロック解除
if( $lockkey ne '0' ){ &UNLOCK; }
#HTML出力
print "Location: $targeturl\n\n";
exit;
No.2ベストアンサー
- 回答日時:
# IPアドレスのチェック結果に応じてカウント処理
sub IpCheck {
_IpCheck($addr, $iplog) ? CNTUP() : NoCnt();
}
# IPアドレス毎の書き込み回数チェック
sub _IpCheck {
my $addr = shift;# 調べたいIPアドレス
my $iplog = shift;# データファイル名
my $count_max = 5;# IPアドレス毎の最大書き込み回数
# 現在日付の取得
my $today = sub {
my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($_[0]);
sprintf('%04d/%02d/%02d', $year+1900, $mon+1, $mday);
}->(time);
# IPアドレス毎の書き込み回数の読み書き
use Fcntl;
sysopen(my $fh, $iplog, O_CREAT|O_RDWR) or Error(5);# 読み書きモード/ファイルがなければ新規作成
eval { flock($fh, 2); };# ちゃんとロックしないと壊れます
eval { chmod(0666, $fh); };# 動かない環境もあるので念のためeval
binmode($fh, ':crlf') if($^O =~ /MSWin32/);# Windowsでは改行コードをCR+LFで読み書き
seek($fh, 0, 0);
my $lastday = <$fh> || '';# データファイルの1行目の日付を読む
chomp $lastday;
my %count;
if($lastday eq $today) {
# 日付が同じ場合だけ過去データを読む
while(my $data = <$fh>) {
chomp $data;
my($ip, $c) = split /\t/, $data;
$count{$ip} = $c;
}
}
$count{$addr}++;
return if($count{$addr} > $count_max);# 回数オーバーならundefを返す
seek($fh, 0, 0);
print $fh $today."\n";# データファイルの1行目に日付を保存
foreach my $ip (sort keys %count) {
print $fh $ip."\t".$count{$ip}."\n";
}
truncate($fh, tell($fh));
close($fh);
return 1;# 書き込み可能な場合は1を返す
}
# Perl5の入門書を読むことをお勧めします。
# Perl4は絶滅して久しいですし、何よりPerl4で書かれたプログラムは読むのがつらい・・・
この回答への補足
N60-BASICさま
先ほど、試しました!完璧でした!!(^^)/
感動して、背中に武者震いが走りました!
貴方様のような素晴らしい方に御指導いただけて大変光栄です。
大変困っていたので、今回の御指導には筆舌に尽くしがたいほど非常に感謝しております。
世の中には天才プログラマーがいるんだということを身を持って感じました。
誠にありがとうございました。m(_ _)m
N60-BASICさま
詳細な御説明、誠にありがとうございました。
m(_ _)m
非常に参考になり、目から鱗が落ちました!
スペシャリストの方は、やはり違いますね!感動です。
早速、組み込んで試してみたいと思います。
Perl5も勉強します!
No.1
- 回答日時:
自分なら、dbmopen/tieを使って、IPアドレス:日付をキーにしてアクセス回数を管理します。
間違いを気にせず書くと、こんな感じ:tie %cnt, (略) or die;
$v = $cnt{ $ip, $today };
if ( $v < 5 ){
データ追記処理; $cnt{ $ip, $today } = $v + 1;
}
untie %cnt;
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
改行コードが勝手に
-
ExcelをCSV書き出す場合のシー...
-
エクセルVBA コードが同じでも...
-
5行おきに5行ずつ抽出するに...
-
FindFirstFileとFindNextFileで...
-
batファイルでrenameができませ...
-
バッチファイルの作り方(CSV→...
-
python renameについて
-
Perl-CGI で排他制御はどうすれ...
-
C言語でファイル名を取得
-
デルファイ TabControl タブの...
-
fopenでディレクトリ内の全ファ...
-
ListBoxのデータを高速でファイ...
-
dos変数の%~dp0は powershellで...
-
perlでcsvファイルを読む(ダブ...
-
Perlで フォルダ内の全て...
-
【エラー】Unrecognized character
-
ReadLineでの読み出し行を指定する
-
データが消えてしまう
-
[Perl]ファイル出力のエンコー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
close()で例外が投げられる理由
-
where can I buy snowbord in t...
-
パイプをopenして/usr/bin/grep...
-
perlで複数のファイルの処理に...
-
ファイルから読み込んだ文字を
-
perlのflock関数でロックをかけ...
-
Perlでログファイルからユーザ...
-
ファイルのロックについて
-
マッチ演算子に変数をはさんで...
-
perlで大容量CSVのsort方法につ...
-
perlを用いた特定文字列間の抽...
-
テキストファイルの本文中に行...
-
open中のファイルをrename
-
PICでFatFsでオープンした内容...
-
文字列比較がどうしてもできま...
-
パスワードを外部ファイルから...
-
Perlのファイルオープン時...
-
perlでのスキンの利用方法
-
Perlでハードウェア制御?
-
ログに記録又は読み出す際、最...
おすすめ情報