- ベストアンサー
改造PerlでIPアドレスの投票回数制限を変更
- Perlの投票CGIで同一IPから1日連続5回までの投票を許可する方法を教えてください。
- IPアドレスのチェックとクリックカウントアップの処理を改造すれば実現できます。
- 具体的な改造方法をアドバイスします。
- みんなの回答 (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で書かれたプログラムは読むのがつらい・・・
その他の回答 (1)
- osamuy
- ベストアンサー率42% (1231/2878)
自分なら、dbmopen/tieを使って、IPアドレス:日付をキーにしてアクセス回数を管理します。間違いを気にせず書くと、こんな感じ: tie %cnt, (略) or die; $v = $cnt{ $ip, $today }; if ( $v < 5 ){ データ追記処理; $cnt{ $ip, $today } = $v + 1; } untie %cnt;
お礼
御回答誠にありがとうございました。 なるほど、日付をキーにして回数を管理するわけですね! とても参考になりました!(^^)
お礼
N60-BASICさま 詳細な御説明、誠にありがとうございました。 m(_ _)m 非常に参考になり、目から鱗が落ちました! スペシャリストの方は、やはり違いますね!感動です。 早速、組み込んで試してみたいと思います。 Perl5も勉強します!
補足
N60-BASICさま 先ほど、試しました!完璧でした!!(^^)/ 感動して、背中に武者震いが走りました! 貴方様のような素晴らしい方に御指導いただけて大変光栄です。 大変困っていたので、今回の御指導には筆舌に尽くしがたいほど非常に感謝しております。 世の中には天才プログラマーがいるんだということを身を持って感じました。 誠にありがとうございました。m(_ _)m