投票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で質問しましょう!
似たような質問が見つかりました
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- その他(プログラミング・Web制作) python 気象データの取得 2 2023/06/20 23:54
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- PHP imageフォルダに、画像をリサイズして保存する時のファイル名を変更したい 1 2023/05/30 11:39
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- Excel(エクセル) マクロでテキストファイルを読み込んだ際の最終セルにデータと改行が含まれる問題の改善方法 2 2022/03/25 16:50
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストファイルの本文中に行...
-
close()で例外が投げられる理由
-
perlのflock関数でロックをかけ...
-
awkスクリプトでダブルクォーテ...
-
VBAで巨大なファイルの途中から...
-
fopenでディレクトリ内の全ファ...
-
ReadLineでの読み出し行を指定する
-
JSP URLに表示される拡張子 .jsp
-
window.open でのファイル指定方法
-
バッチファイルの作り方(CSV→...
-
エクセルVBAで素数だけを出力す...
-
LinuxのC言語で、ファイル名の...
-
VBAコードを張り付け後のエクセ...
-
無料配布の郵便番号自動入力cgi...
-
タブの色を変更する方法
-
Perl Vlookupみたいに
-
CSVファイルについて
-
重複するデータを抽出できる秀...
-
ExcelをCSV書き出す場合のシー...
-
foreachの制御
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
close()で例外が投げられる理由
-
perlのflock関数でロックをかけ...
-
改行コードが勝手に
-
巨大ファイルの行をを逆順に並...
-
オープンしたファイルで行の連結
-
Perl で syntax error
-
where can I buy snowbord in t...
-
perlを用いた特定文字列間の抽...
-
Perlで他サイトの情報を取得し...
-
open中のファイルをrename
-
die関数のエラー出力先について
-
ハッシュにファイルハンドル
-
perlで大容量CSVのsort方法につ...
-
テキストファイルの本文中に行...
-
サブスクリプトとのファイルハ...
-
AutoCADのスクリプト
-
フォルダが開かなくなりました。
-
ジョブショップスケジューリング
-
バッチファイルの作り方(CSV→...
-
awkスクリプトでダブルクォーテ...
おすすめ情報