• 締切済み

postで送られてきたパラメータが処理できない(perlCGI)

postで送られてきたパラメータが処理できない(perlCGI) postメソッドで送信されてきたパラメータの値によって条件分岐しようとしているのですが どうも受け取ったパラメータがハッシュ値のはずなのにハッシュ値として処理できなくて困っています。perl自体初心者なのでなにか勘違いしている可能性が高いですが、意味不明で完全に行き詰っているのでよろしくお願いします。 (送信パラメータは{"key":"1"}) #!/usr/bin/perl read(STDIN, $data, $ENV{'CONTENT_LENGTH'}); print "Content-type: text/html\n"; print "\n"; print "$data{'key'}\n"; 確認のため上のコードのようにしてみたところなにも表示されません。 しかし最後の行でprint "$data\n"; という風に帰るとkey=1といった表示が出力されます。 $dataの中身が単純な文字列になっているかと思えばそうでもなく、かといって $data{"key"}, $data{'key'}で$dataの"key"に対応する要素を取り出そうとしてもなぜかできません。 postメソッドはただの値ではなくハッシュ値ではないと送れないみたいで多いに困っています。そもそもなんで連想配列を受け取っているはずなのに処理できないのでしょうか? 心当たりがある方、よろしくお願いします。

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

みんなの回答

  • YkazubonY
  • ベストアンサー率30% (26/86)
回答No.5

元のフォーム画面に問題が在るのでは? <form>タグのパラメータに下記が記述されていますか? ENCTYPE="application/x-www-form-urlencoded これが無いと、read()関数で読み込むとおかしくなりますね。

  • ralf124c
  • ベストアンサー率52% (232/446)
回答No.4

CGIから受け渡されるパラメータはPOSTでもGETでも フォーム要素名1=値1&フォーム要素名2=値2&フォーム要素名3=値3&・・・フォーム要素名n=値n という形式で「&」で接続されて一気に送られてきます。 決してハッシュ(連想配列)で送られてくるわけではありません。  ブラウザのフォーム → Webサーバアプリ(ApacheやIISなど)内のCGI → CGIによって起動されるシステム内のプログラム これを標準入力バッファで受け取るのがPOSTメソッドで、環境変数で受け取るのがGETメソッドです。 この受信したデータのかたまりをそのまま扱うよりは ------------------------------- ハッシュ名{フォーム要素名1} の内容は 値1 ハッシュ名{フォーム要素名2} の内容は 値2 ハッシュ名{フォーム要素名3} の内容は 値3 ハッシュ名{フォーム要素名n} の内容は 値n ------------------------------- とハッシュに分割して扱う方が後の処理が簡単になるので専用のサブルーチン集やPerlモジュールを利用してプログラム内でハッシュに変換しているのです。 自動でそうなるわけでなく、意図的にそうするのです。 ツールを使うと動作原理が理解できないままでトラブルシューティングにもならないので以下のようなサブルーチンを組んで ## ---------------------------------------------------------ここから ## メソッド読み込み ## ---------------------------------------------------------  sub readMethod{   my %rm_in;   my $paramPost;   my @tmpPrmt = split(/&/,$ENV{'QUERY_STRING'});   foreach(@tmpPrmt){    my ($p1,$v1) = split(/=/,$_);    $v1 =~ tr/+/ /;    $v1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego;    if(exists($rm_in{$p1})){     $rm_in{$p1} .= "\t".$v1;    }else{     $rm_in{$p1}=$v1;    }   }   read(STDIN, $paramPost, $ENV{'CONTENT_LENGTH'});   my @tmpData=split(/&/,$paramPost);   foreach(@tmpData){    my ($p1,$p2)=split(/=/,$_);    $p1 =~ tr/+/ /;    $p1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego;    $p2 =~ tr/+/ /;    $p2 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego;    if(exists($rm_in{$p1})){     $rm_in{$p1} .= "\t".$p2;    }else{     $rm_in{$p1}=$p2;    }   }   return %rm_in;  } ## ---------------------------------------------------------ここまで  my %ハッシュ変数名 = readMethod(); という具合に読み込んでやれば「$ハッシュ変数名{キー名}」で参照が可能となります。 ご質問の例の場合 my %hIN = readMethod(); print "Content-type: text/plain\n\n"; print $hIN{'key'}; で「1」という結果が表示されるようになります。 このサブルーチンはそんなに長いものでないので上から順序良く読んでいってください。 GETとPOSTの各メソッド処理を混在させています。 前半がGETの処理で後半がPOSTの処理です。 Web専門でないデザイナーとか俄デザイナーとかがよくフォームの要素名について配慮せずコピペなんかでダブらせているケースや、チェックボックス群をひとつで扱いたい場合があるので、その対策として「$ハッシュ変数名{キー名}=値1\t(タブ)値2\t・・・値n」となるように組んでいます。

回答No.3

> そもそもなんで連想配列を受け取っているはずなのに処理できないのでしょうか? 連想配列は受け取っていません。 自分で連想配列に作り直して下さい。 > postメソッドはただの値ではなくハッシュ値ではないと送れないみたいで この書き方から推測すると、JavaScriptのAjax関連のライブラリを利用されていると思いますが、 いきなり複雑なことをせず、 CGIはどういうものか、HTMLフォームとはどういうものかというところから、順番に勉強したほうが良いと思います。

回答No.2

どのようなフォームデータをCGIで受け取っているのかわからないのですが、 CGI.pmを使って、処理するのが簡単ですよ。 Perlのバージョンにもよりますが、多分標準装備だと思うんで「use CGI;」 って書いたら使えますよ。参考URLに詳しいです。一応例書いておきます。 CGI側の処理です use CGI; my $q = CGI->new; #項目一個につき値が一個の時の例 my $from = $q->param('from'); my $to = $q->param('to'); #項目一個につき値が複数の時の例 @past = $q->param('past'); 頑張ってください

参考URL:
http://www.futomi.com/lecture/form/cgi-pm.html
回答No.1

Perlでは $data @data %data は全て別の変数です。 スカラ変数で受け取ったPOSTの内容はsplitなどで整形しなければ、 勝手にハッシュに変換されることはありません。 環境変数は元からハッシュですが、 readでファイルハンドルにSTDINを指定しているという事は、 POSTは標準入力でしかありません。 #!/usr/bin/perl read(STDIN, $data, $ENV{'CONTENT_LENGTH'}); ##追加 @data = split(/&/, $data); foreach $pair (@data) { ($name, $value) = split(/=/, $pair); $data{$name} = $value; } ##追加終わり print "Content-type: text/text\n"; print "\n"; print "$data{'key'}\n"; ※動作チェックはしてませんw

関連するQ&A

  • Rubyでnet::httpを用いてPOSTする

    今晩わ。 RubyでNet::HTTPをもちいてPOST送信する際の処理について 質問です。 Net::HTTPクラスのインスタンスメソッドのpostメソッドを用いて送信する場合 送信内容を # version 1.2 (Ruby 1.8.x or later) response = http.post('/cgi-bin/search.rb', 'query=subject&target=ruby') 上記のように、引数に渡していると思います。 このとき、値の中にパラメータのデリミタと同じ&を入れたい場合どうしたらいいのでしょうか? 例えば query=subject&target=ruby&PHP のような感じでvalueとして&を渡す場合です。 Net**HTTP::Postクラスのrequestメソッドを用いてハッシュとして渡した時は問題なかったのですが、上記のpostメソッドの時がPOSTされた値を取得するときにキチンと取得できませんでした。これはなにか対処方法があるのでしょうか? ご教授ください。 おねがいします。

    • ベストアンサー
    • Ruby
  • WindowsアプリにPOSTのパラメータを渡す

    WebフォームからPOSTメソッドで送信したパラメータを、.NETのスマートクライアントに引き渡す方法を考えています。 ノータッチデプロイメントのスマートクライアントはどうやらクエリストリングを受け取ることはできるようですがPOSTが受け取れません。 現在試しているのはいったん、クエリストリングをASP.NETで受け取り、クエリストリングに変換してスマートクラインアントのページに転送するやりかたです。 この転送をサーバ内で処理しようとする(つまりServer.Transferを用いる)とブラウザはダウンロードされるのが.exeだとは気づかすテキストとして扱ってしまいます。Response.Ridirectを用いるとうまくいくのですが、これは結局クライアントがGETメソッドを投げてしまうので、できれば避けたい状況です。 なにかいい方法はないでしょうか?

  • サーブレットからパラメータをPOST形式で送信するには。

    現在JavaでWEBアプリケーションを開発しています。 技術的な事で、皆様にご質問がございます。 サーブレットから、他のWEBアプリケーションのサイトへ POST形式でパラメータを送信するには、どうすれば 良いのでしょうか? GET形式で送信するなら、 response.sendRedirect("http:aaa.com?key1=aaa&key2=bbb") ってな具合で、URLの後ろに送信したいパラメータを つければ、GET形式で送信できますが、 POST形式で送る事はできないのでしょうか? どなたか、ご存知の方がおられましたら、 ご教授よろしくお願い致します。

    • ベストアンサー
    • Java
  • jQueryのpostからのリクエストをCGIで受信して処理したい

    jQueryのpostからのリクエストをCGIで受信して処理したい こんにちわ。CGIはまったくの素人に近いですが、よろしくお願いします。 今作成中のページからjavascript(具体的にはjQuery)を使ってpostでリクエストをサーバに送信し、それをCGIで受け取ってカウンタを増やして返す的なことをやろうとしています。 送信側ではとりあえずページをロードしたら(view()で)リクエストを送り(下のtest.cgi)、帰ってきた値を(ID"count1"で)ページにまた反映するという形をとっています。 javascriptのpost部分抜粋 function view() {jQuery.post("../../../cgi-bin/test.cgi", {"key1":"1"}, function(data){ $("#count1").html(data) } ); }; 送信はできてるみたいなのですが受け取るCGIが問題で、「フォームからデータを送る場合」というのは山ほど解説があるのですが単純に送られてきたリクエストを受け取るのは下のプログラムではダメみたいです。 CGI部分 #!/usr/bin/perl my $counter=0; read( STDIN, $buffer, $ENV{'CONTENT_LENGTH'} ); $counter++; return("$counter"); 当初CGIが必要だとは思わずにいたので、昨日からCGIを勉強し始めたレベルの素人ですが じっくりと腰をすえて一人で解決する時間もないので、よろしくお願いします。

    • ベストアンサー
    • CGI
  • html::templateにおけるパラメータ受け渡し

    <開発環境> OS:Red Hat Enterprise Linux 4 WWWサーバー:Apache 2.0.52 Perl:5.8.8 フォームに入力し、ボタンを押すとメールが自動送信されるCGIを開発おり、URLの末尾(?以降)に持たせたパラメータが途中で失われてしまうため、困っております。 仕様は 1.入力画面→(POST)→2.確認画面→(POST)→3.送信完了画面 となっており、1で入力して2で確認し、3でメールを飛ばす処理は問題なく動いていますが、1から2へ遷移するとパラメータが失われてしまいます。 html::templateというモジュールを用いており、テンプレートファイルへの値の受け渡し方がよく分かりません。 1のURL末尾のパラメータを確保し、2以降へ受け渡す書き方を教えて頂けないでしょうか。 よろしくお願い致します。

    • ベストアンサー
    • CGI
  • PerlCGIでクエリの検索結果が途中で途切れる。

    PerlCGIでクエリの検索結果が途中で途切れる。 環境: Windows 7 Home Premium 32bit Mem: 3.24GB Apache for win 2.2 Perl: v5.10.1 built for MSWin32-x86-multi-thread access の mdb を ODBC 接続し perl cgi をフロントエンドとして クエリを表示させようとしています。 クエリの表示自体はエラーなくできましたが、検索結果が全て表示されません。 # 本来は 200件以上あるはずなのに、半分以下しか表示されない。 感触として、バッファかなにかのバイト制限のような気もするのですが、 全ての検索結果を表示するためにはどうすればよいのかご教示いただけないでしょうか? コードは以下のとおりです。 -------------------------------------------------------- #!c:/perl/bin/perl.exe use Win32::ODBC; print "Content-type: text/html\n\n"; print "<html>\n"; print "<body>\n"; print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=shift_jis\">\n"; $db= new Win32::ODBC("DSN=kaigai"); $str_sql = "SELECT q_prestounyu.hiduke, q_factory_master.koujyoryakumei, q_prestounyu.keiyaku, " ; $str_sql .= "q_prestounyu.hinban, q_pres_master.ryakumei, q_prestounyu.nyukousu "; $str_sql .= "FROM (q_prestounyu INNER JOIN q_pres_master ON q_prestounyu.presno = q_pres_master.presno) "; $str_sql .= "INNER JOIN q_factory_master ON q_prestounyu.koujyo = q_factory_master.koujyono "; $str_sql .= "WHERE (((q_prestounyu.hiduke)>=#2010/1/10# And (q_prestounyu.hiduke)<=#2010/1/31#)) "; $str_sql .= "ORDER BY q_prestounyu.hiduke;"; print "$str_sql<BR>\n"; $i=0; $db->Sql($str_sql); # 取得したレコードセットの数だけループして表示 while ( $db->FetchRow() ){ $i ++; undef %FIELDS; # 各フィールドのデータをハッシュに格納 %FIELDS= $db->DataHash(); print "$i "; print "$FIELDS{'hiduke'} $FIELDS{'koujyoryakumei'}\n"; print "$FIELDS{'keiyaku'} $FIELDS{'hinban'}\n"; print "$FIELDS{'ryakumei'} $FIELDS{'nyukousu'}<BR>"; } # データベースを閉じる $db->Close( ); print "</body></html>"; exit;

  • 1つのプログラム内で"html出力"の部分とそれ以外の処理部分の共存

    1つのプログラム内で"html出力"の部分とそれ以外の処理部分の共存 こんにちわ。 ・リロードイベントをキャッチしたhtmlからリクエストをcgiが受信(html出力部分) ・カウンタ値を保存しているtxtファイル(data.txt)から現在の値を読み出す ・+1してファイルにまた値を書き込む ・その値をhtmlにも返して表示させる(html出力部分) といった具合のプログラムを作りたいのですが、html出力をしている部分とそのほかの処理を同じcgiファイルに入れているとうまく動かないみたいです。 以下が問題のファイルの中身です。 (test.cgi) #!/usr/bin/perl open(IN, "../html/2010/data.txt"); my $counter=<IN>; close(IN); $counter++; open(OUT,"> ../html/2010/data.txt"); print (OUT "$counter\n"); close(OUT); print "Content-type: text/html\n"; print "\n"; read(STDIN, my $data, $ENV{'CONTENT_LENGTH'}); print "$counter\n"; ページをリロードして処理を確認するとdata.txt内の値は変わらないまま、それに1を足しただけの値が表示されます。しかしdata.txtの中身が0でサーバのコマンドラインで perl test.cgi といった風に動かしてみると Content-type: text/html 1 といった感じに今度はちゃんとdata.txt内の値もちゃんと書き換えられて出てきます。 html出力部分とdata.txtの書き換え部分は分離させたほうがよいのでしょうか?分離しなければいけない場合は互いのデータの受け渡し方法もご教授お願いします。

    • ベストアンサー
    • CGI
  • CGIへ飛ばずに処理だけさせたい

    HTMLのフォームからsubmitしてcgiにアクセスする。 cgiでHTMLからのポストとゲットを読み込んで ログファイルに書き込む。 というCGIを作ったんだけど、 print "Content-type: text/html\n\n"; を書かないと、submitしてからcgiの処理が 止まらないみたいでした。 print "Content-type: text/html\n\n"; を書くと、処理は正常になるけど、cgiファイルに ジャンプしてしまいます。 openで書き込みをする場合、cgiに飛ばずに 処理する方法を教えてください。

    • ベストアンサー
    • CGI
  • WinsockでwebにPOSTした後の処理について

    Winsockコントロールを使って掲示板などにPOSTでデータを送信する際、ヘッダー部分で Content-Length: ~~~ も送信してるのですが、 Content-Length:の値分のDATA?を送らないとサーバー側がずっと待機する状態になると思うのですが、 これはWinsockのCloseメソッドを使えばサーバーの待機状態が解除されますか? また、SendDataの途中でプログラムを終了する場合もCloseメソッドでいきなり閉じても大丈夫でしょうか? 自分が書いた該当部分のソースは下記の通りです。 Dim strHead As String 'ヘッダー Dim strData As String 'データ 'いろいろな処理  strHead=strHead & vbCrLf & "Content-Length: " & LenB(StrConv(strData, vbFromUnicode)) & vbCrLf & vbCrLf  'strHeadとstrDataにはきちんとデータが入ってる  Winsock1.SendData strHead & strData End Sub そして Winsock1_DataArrivalプロシージャーに Dim strBuf As String  Winsock1.GetData strBuf  If Instr(1,strBuf,"</HTML)") > 0 Then   Sleep 1000:DoEvents   Winsock1.Close  End If Form_QueryUnloadプロシージャーに  Sleep 1000:DoEvents  Winsock1.Close End Sub

  • sendmailの使えない環境でメールを送る

    いま使っている自分のサイトは CGI(Perl5)は OKですが sendmailが使えません。しかし、掲示板の書き込み内容をメールで送信したいと考えています。 で、幸いそのプロバイダには標準 CGIとしてメールデコードをサポートしています。これを巧く使ってメールを送信できないかとのご相談です。 件の CGIはPOSTメソッドで渡すので、CONTENT_LENGTHにその長さをセットし、標準入力へパラメータを。そして掲示板プログラムからメールでコードのCGIを呼び出せば巧くいきそうなのですが....。 1.まず、この方法は使えそうか? 2.perl中で別の CGIの標準入力へどのようにパラメータを渡すのか(パイプ?リダイレクト?) 3.環境変数 CONTENT_LENGTHへ CGI中から値を設定できるのか? 4.送信するパラメータはどんな文字列にすればいいのか?(エンコード、パラメータの区切りとか) 以上です。どなたかアドバイスお願いします

    • ベストアンサー
    • CGI

専門家に質問してみよう