• ベストアンサー

次のカウンターのCGIプログラムで間違っているところはどこでしょうか?

参考書を手にしながら次のようにCGIを作成しましたが、上手く動きません。 個人別カウンター(アクセスしてきた個人ごとにカウンターが変わる)CGIです。 いろいろ調べたのですが、どこが間違っているのか分からなくなりました。 どうぞお願いいたします。 ======= #!/usr/local/bin/perl $cookie = $ENV{'HTTP_COOKIE'}; @array = split(/; /, $cookie); foreach $tmp (@array){ ($key, $value) = split(/=/, $tmp); if($key eq 'count'){ $count = $value; } } if( $key == ""){ $count = 0; } $count++; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime(time + 60*60*24*30); @day = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "sat"); @month = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Set", "Oct", "Nov", "Dec"); $expireDate = sprintf("%s\, %02d\-%s\-%04d %02d:%02d:%02d GMT", $day[$wday], $mday, $month[$mon], $year+1900, $hour, $min, $sec); print "Content-Type: text/html\n"; print "Set-cookie: count=$count; expires=$expireDate \n\n"; Print "<html>\n"; Print "<title>counter4</title>\n"; print "<body>\n"; print "<h1>個人別カウンター</h1>\n<hr />"; print "あなたは$count回目のご訪問です。\n"; print "</body>\n"; print "</html>"; exit;

  • CGI
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • lesstia
  • ベストアンサー率45% (44/96)
回答No.2

とりあえず。 ・クッキーを読み出す箇所はあるが保存する箇所がない ・Print (先頭大文字)になってる箇所がある

mutsukiame
質問者

お礼

有難う御座います。 ・Print (先頭大文字)になってる箇所がある<< すみません。本当の基本を間違っていまして・・・。何度も見直したつもりだったのですが・・・。 大文字を小文字に変えたところ、エラー500というCGIページが表示されなかった状態から、見事にページ自体が表示される状態へとなりました。 が、しかし・・・ ・クッキーを読み出す箇所はあるが保存する箇所がない<< まさしくこの通りか、cookieの設定を有効にしたにもかかわらず、何度訪問しても「1回目のご訪問」と表示されてしまいます。 保存の方法を調べてみます。

mutsukiame
質問者

補足

本で確認したのですが・・・ 「クッキー情報をnameとvalueに分解して、name属性に当たる部分に[count]という文字列と一致するものがあれば、以前にクッキーに格納した個人のアカウント数であるとする」 そして、 「新しいカウント数をクッキーにセットするのに、HTTPヘッダで行う」 とあります。 この部分は、 print "Set-cookie: count=$count; expires=$expireDate \n\n"; ということらしいです・・・

その他の回答 (3)

  • ORUKA1951
  • ベストアンサー率45% (5062/11036)
回答No.4

≫本を確認し変更したところ、無事、訪問回数が表示されるようになりました。 ≫でも、その意味合いが良く分かっていないのですが・・・。 ≫あなたは1回目のご訪問です。 ・・・【中略】・・・ ≫$cookie ≫count=1 ≫$key ≫count ≫$value ≫1 ≫$count ≫1  CGIの修正方法の原則は途中過程を表示させてミスの場所を探すということです。ですから、私が提示した方法は必須のテクニックです。  うまくカウントしなかった原因は、 if( $key == ""){ $count = 0; } $count++;  ですよね。$keyではなく、$countの値をチェックしないとなりません。だとすると if ($count == "" || $count ==0){ 等のほうが・・

mutsukiame
質問者

お礼

>>CGIの修正方法の原則は途中過程を表示させてミスの場所を探すということです。ですから、私が提示した方法は必須のテクニックです。 ●途中過程を表示させるようなテクニックが欲しかったので、今回は大変いい情報を得ることができました。ありがとうございます。 これから、途中経過を表示させミスを発見しながらCGI作らせていただきます。

  • zxcv0000
  • ベストアンサー率56% (111/196)
回答No.3

sprintf("%s\, %02d\-%s\-%04d %02d:%02d:%02d GMT", ... の部分、Perlのバージョンによりまずいかも。 "\" が必要なのは "," や "-" の直前では無く "%" の直前です。 あるいは、引用符を 「"」から「'」に替えれば "\" はいりません。 さらにあるいは、この様な日時表現の生成は、 HTTP::Date.pm が面倒をみてくれますよ。

mutsukiame
質問者

お礼

有難う御座います。 >>"\" が必要なのは "," や "-" の直前では無く "%" の直前です。 ・本が全部正しいってわけじゃないんですね。アドバイスを色々試してみたいと思います。 もっともっと勉強していきますので、またよろしくお願いいたします。

  • ORUKA1951
  • ベストアンサー率45% (5062/11036)
回答No.1

どう動かないの? 予想は立ちますが、そのまえに print "<body>\n"; print "<h1>個人別カウンター</h1>\n<hr />"; print "あなたは$count回目のご訪問です。\n"; print "</body>\n"; print "</html>"; の部分を print "<body>\n"; print "<h1>個人別カウンター</h1>\n<hr />"; print "<p>あなたは$count回目のご訪問です。</p>\n"; #ここから・・ print "<ol>\n"; print "<dt>\$cookie</dt>\n"; print "<dd>$cookie</dd>\n"; @array = split(/; /, $cookie); foreach $tmp (@array){ ($key, $value) = split(/=/, $tmp); print "<dt>\$key</dt>\n"; print "<dd>$key</dt>\n"; print "<dt>\$value</dt>\n"; print "<dd>$value</dd>\n"; } print "<dt>\$count</dt>\n"; print "<dd>$count</dd>\n</dl>\n"; # 追加こまで print "</body>\n"; print "</html>"; のように、処理過程を出力させてみるのが一番早い解決方法です。 その結果を・・・

mutsukiame
質問者

お礼

==== if( $key == ""){ $count = 0; } $count++; ==== の部分を ==== if( $count == ""){ $count = 0; } $count++; ==== 本を確認し変更したところ、無事、訪問回数が表示されるようになりました。 でも、その意味合いが良く分かっていないのですが・・・。 おかげさまで解決いたしました。

mutsukiame
質問者

補足

有難う御座います。 アドバイスを通り追加したところ、以下のような表示となりました。 ==== 個人別カウンター -------------------------------------------------------------------------------- あなたは1回目のご訪問です。 $cookie count=1 $key count $value 1 $count 1 ===== >>どう動かないの? すみません、言葉足らずでした。以前は全く表示されなかったのですが、printのPが大文字だったのを小文字に変えると、上記のように表示されるようになりました。 が、クッキーを有効にしても訪問回数は常に1回目となります。

関連するQ&A

  • cookieについて教えてください。

    iswebのサーバーを借りています。 cookieの書きこみを下のような記述を試しています。 ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time + 60*60*3); @mons = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); @week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sut'); $date = sprintf("%s, %02d\-%s\-%04d %02d:%02d:%02d GMT",$week[$wday], $mday, $mons[$mon], $year+1900, $hour, $min, $sec); $mydata = "abc"; print "Set-Cookie: AAA=$mydata; expires=$date;"; print "Content-type: text/html\n"; print "\n"; print "<meta http-equiv="Set-Cookie" content="AAA=$mydata; expires=$date">"; 以下いろいろつづく。 この時にSet-Cookie: AAA=$mydata; expires=$date;";を残すとエラーが出てmetaを残すと動きます。 自分のパソコンの中では、両方動きます。 そこで教えていただきたいのですが、 javascriptのdocument.cookie、perlのSet-Cookie、metaのSet-Cookieの違いを教えてください。

    • ベストアンサー
    • Perl
  • Perlでの Timeの足し算

    時間の足し算をやりたい。訳あってライブラリが使えません。 方法は無いでしょうか? 仮にライブラリが使えるなら、下記のようでうまく行っています。 --------------------------------------------------- use Time::Local; $year=2008; $mon =10; $mday=24; $hours = 23; $min = 0; $sec = 0; $time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year); $a1=($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time ); $mytimeORG= sprintf("%04d/%02d/%02d %2d:%2d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytimeORG\n"; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time + 32400); #9H加算 $mytime9H= sprintf("%04d/%02d/%02d %02d:%02d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytime9H\n"; ---------------------------------------------

    • ベストアンサー
    • Perl
  • CGIについて(時間表示)

    CGI初心者ですが、掲示板を作成中です。投稿するたびにメッセージの投稿時間がすべて現在時刻に書き換わります。 メッセージ毎に時間表示させたいのですが、いかのプログラムのどこを変更すればよいのでしょうか?宜しくお願いいたします。 # 時間処理 sub totime { ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time); $year +=1900; $month++; $year = sprintf("%04d", $year); $month = sprintf("%02d", $month); $mday = sprintf("%02d", $mday); $hour = sprintf("%02d", $hour); $min = sprintf("%02d", $min); $sec = sprintf("%02d", $sec); $date = "$month/$mday $hour:$sec"; }

    • ベストアンサー
    • CGI
  • 掲示板への書き込み時間

    掲示板CGIについて質問です。 使おうとしているスクリプトはそのままアップロードすると書き込みした時間の表示が 「4/14 (Sun) 17:10」 のようになります。 これを 「2003 4/14 (日) 17:10:50」 のように年と秒まで加えたいのです。 それで後者のように表示される掲示板CGIを参考にしてみましたが、目立った違いはないように思え、どこをどう変更すれば年や秒まで表示されるようになるかわかりません。 思い当たる部分はこのあたりなのですが…。 ↓このように記述されています ************ $ENV{'TZ'} = "JST-9"; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year = sprintf("%02d",$year + 1900); $month = sprintf("%02d",$mon + 1); $mday = sprintf("%02d",$mday); if ( substr($month,0,1) == 0 ) { $month =~ s/0/ /; } if ( substr($mday,0,1) == 0 ) { $mday =~ s/0/ /; } $hour = sprintf("%02d",$hour); $min = sprintf("%02d",$min); $sec = sprintf("%02d",$sec); $youbi = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wday]; $date_now = "$month/$mday ($youbi) $hour:$min"; ************ CGIに手を加えてレイアウトの変更くらいはいつもやっています。 もし書き換える方法がありましたら教えていただければと思います。 どうぞよろしくお願い致します。

    • ベストアンサー
    • CGI
  • 掲示板のcookieが消える?

    自分のサイトに設置してあるBBSなんですが、cookieで名前やメアドを記憶しているはずが、ある日を境に出なくなったんです。 cookieは60日間有効にするために、以下のように書いています。 local($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time+60*24*60*60); @month=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); $gmt = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $week[$wday],$mday,$month[$mon],$year+1900,$hour,$min,$sec); $cook="name<>$in{'name'}\,email<>$in{'email'}\,url<>$in{'url'}\,pwd<>$in{'pwd'}\,icon<>$in{'icon'}\,color<>$in{'color'}"; そして、これをprintで書き出しているのですが、なぜ消えてしまうんでしょう? 設定の仕方が間違っています?

  • 日付求め

    お世話になります。 早速ですが、perlで以下のように 現在時刻を求め表示するロジックがあります。 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); $year=$year + 1900; $mon =$mon + 1; $date81 = "$year年$mon月$mday日($days[$wday])"; $date82 = "$hour時$min分$sec秒"; この時、 例えば今年末であれば、 2009年1月1日0時と表示されると思います。 これを2008年12月31日24時と表示したいのですが、 何か妙案はあるでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • Perlの日付取得で月の表示がおかしい

    下記は、メールフォームCGIに書き込まれた日時などの情報をlog.cgiというファイルに書き出すスクリプトです。 2012/01/04 21:05:45 のような感じで、日付が刻まれるのですが、このうち月の部分がどの月に処理を行ってもいつも01になってしまうのですが、当方直し方がわかりません。 下記が実際の記載箇所です。4行目がおかしいのだと思いますが、どなたかお分かりの方、教えていただけないでしょうか。 my $path = "log.cgi"; my $ip = $ENV{'REMOTE_ADDR'}; ($sec, $min, $hour, $mday, $month, $year, $wday, $stime) = localtime(time()); my $time = sprintf("%04d\/%02d\/%02d %02d\:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec); my $message = $in{'メッセージ'}; $message =~ s/\r\n/ /g; $message =~ s/\n/ /g; if (open(FOUT, ">> $path")) { print FOUT "$time\t$ip\t" . $in{'お名前'} . "\t" . $in{'E-mail'} . "\t" . $message . "\r\n"; close(FOUT); } よろしくおねがいいたします。

    • ベストアンサー
    • Perl
  • cgiのログの書き方

    ここで教えてもらってログファイルの書き方(挿入のようなカンジで)をやってみたんですが、どうしても思い通りの動きをしません。 希望としては、IDが一緒なら、その同じIDの下に書き込みを行う。同じIDが見つからなければ、一番上に書き込みを行う。 というようにしたいのです。 上記のことを行うために以下のコードを書きました。 --------------- for ($w=0;$w<$gyou+1;$w++){ @log3 = split(/&/,$log2[$w]); foreach(@log3){ ($keyw,$valuew) = split(/=/,$_); $FORMw{$keyw} = $valuew; }#foreach open(FH3,">>log.log"); if ($ID == $FORMw{'ID'}){ print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$year/$m on/$day $hour:$min:$sec&SEARCHKEY=$year$mon$day$hour$min$sec\n"; last; } else { if($w+1 == $gyou){ print FH3"ID=$ID&COUNT=$COUNT&TITLE=$TITLE&NAME=$NAME&PASSWORD=$PASSWORD&NAKAMI=$NAKAMI&COLOR=$COLOR&TIME=$year/$m on/$day $hour:$min:$sec&SEARCHKEY=$year$mon$day$hour$min$sec\n"; close(FH3); } } }#for --------------- どうしてもログファイルの最新情報としてしか書き込みがされません。 また、最新ログを1番上に書き込む、ということをしたいのですができますか? 日付順などで並べ替えをしてしまうと、ぐちゃぐちゃになってしまうので、並べ替えを行わずに、です。 またこのような書き込みの仕方をしなくても、 例えば並べ替えで、Excelみたいに、1番目と3番目を基準に並べ替え、とかでできますか? (私は1つの方法でしか知らないので、どうしても意図する順番になりません。)

  • ディレクトリ内のファイル一覧を出力するCGI

    以下のような、ディレクトリファイル一覧を出力する スクリプトなんですが、apacheのように ファイル名、時間、ファイルサイズ順に並べ替える機能を 実現させるにはどうすればよいでしょうか? 力不足ですみません、教えて頂けると幸いです。 #!/usr/local/bin/perl opendir(DIR,"."); @item = readdir(DIR); use Cwd qw(getcwd); use File::Basename qw(basename); my $curdirname = basename getcwd(); $out = "<table>\n"; $out .= "<tr><td align=\"center\">ファイル名</td><td align=\"center\">サイズ(byte)</td><td align=\"center\">更新時刻</td></tr>\n"; foreach(@item){ # .か..か*.cgiなら飛ばす (($_ eq '.') or ($_ eq '..') or /\.cgi$/ or /\.htaccess$/ or /\.pl$/ or /\.dat$/) and next; # ファイルの情報 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($_); # 更新時刻変換 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($mtime); if(-d $_){ $size = "<b><font color=\"#FF0000\">ディレクトリ</font></b>"; $_ .= '/' } $year += 1900; #$month += 1; $mon += 1; $weekday += ('日','月','火','水','木','金','土'); ; #$out .= "<tr><td><a href=$_>$_</a></td><td>$size</td><td>$year/$month/$mday $hour:$min:$sec</td></tr>\n"; $out .= "<tr><td><a href=$_>$_</a></td><td align=\"right\">$size</td><td>$year\年$mon\月$mday\日 $hour:$min:$sec</td></tr>\n"; } $out .= "</table>\n"; print <<EOF; Content-type: text/html <html> <body> Index of \/$curdirname $out </body></html> EOF

    • 締切済み
    • CGI
  • perl-cgiのリネームについて

    Perl-CGIで ABCという、ディレクトリの中のファイルの名前を、ランダムな名前に変換したいのですがうまくいきません。 これを動作させるたびになぜか、どんどんファイルが減っていってしまいます。 どなたか、教えていただけないでしょうか? 宜しくお願い致します。 #!/usr/local/bin/perl print "Content-Type: text/plain\n\n"; $| = 1; my ($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time); my ($nowtime) = sprintf("%02d_%02d_%02d_%02d_%02d_",$year+1900,$mon+1,$mday,$hour,$min,$sec); #ディレクトリのファイル個数を記録する $dir = "./ABC/"; # ← ディレクトリを変数にセットする opendir DIR, $dir; @files = grep { !m/^(\.|\.\.)$/g } readdir DIR; # ← 「.」 「..」 以外のファイルを取得 close DIR; srand; for (my $i = @files; --$i; ) { my $j = int rand ($i + 1); next if $i == $j; @files[$i, $j] = @files[$j, $i]; } $num = 0; use File::Copy; foreach(@files){ $getpath = "$dir"."$_"; if( copy($getpath, "$dir".$nowtime.$num++.'.dat') eq 1){ $num++; unlink($getpath);}else{print "Copy Error"; exit;} }

    • ベストアンサー
    • CGI

専門家に質問してみよう