perl cgi 文字コード変換について

このQ&Aのポイント
  • perl cgi 文字コード変換について
  • 掲示板でログファイルへの書き出しの際に文字コードをshift-jisに変更したいのですが、unshift(@file, "$name1 $name2 ");と記述すると何も書かれずに空白になってしまいます。なぜでしょうか?困っています。教えて下さい。
  • ちなみにunshift(@file, "$in{'handle'} $in{'message'} "); と文字コードの変更を意識しなかった場合にはちゃんとファイルに書かれています。jcode.plなどは使わずにencodeで行いたいです。
回答を見る
  • ベストアンサー

perl cgi 文字コード変換について

掲示板でログファイルへの書き出しの際に文字コードをshift-jisに変更したいのですが, #投稿された値を受け取る if ($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'}); } else { $alldata = $ENV{'QUERY_STRING'}; } foreach $data (split(/&/, $alldata)) { ($key, $value) = split(/=/, $data); $value =~ s/\+/ /g; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg; $value =~ s/\t//g; $in{"$key"} = $value; } #ヘッダの表示 print "<html>\n"; print "<head><title>掲示板</title></head>\n"; print "<body>\n"; #受け取ったデータをファイルに書き込む if ($in{'handle'} ne '' && $in{'message'} ne '') { if (open(FH, "bbs.txt")) { @file = <FH>; close(FH); use CGI; $cgi=new CGI; $name1=$cgi->param('handle'); $name2=$cgi->param('number'); use Encode; use Encode::Guess qw(euc-jp shiftjis 7bit-jis); encode("shiftjis",decode('Guess',$name1)); encode("shiftjis",decode('Guess',$name2)); unshift(@file, "$name1\t$name2\n"); ##この部分で if (open(FH, ">bbs.txt")) { print FH @file; close(FH); } else { print "<p>ファイルに書き込めません。</p>"; } } else { print "<p>ファイルを読み込めません。</p>"; } } #投稿フォームの表示 print "<form method=\"post\" action=\"bbs.cgi\">\n"; print "<p>\n"; print "ハンドルネーム<br>\n"; print "<input type=\"text\" name=\"handle\" size=\"20\" value=\"\"><br>\n"; print "メッセージ<br>\n"; print "<input type=\"text\" name=\"message\" size=\"20\" value=\"\">\n"; print "</p>\n"; print "<p><input type=\"submit\" value=\"送信する\"></p>\n"; print "</form>\n"; #記事の一覧表示 if (open(FH, "bbs.txt")) { while ($data = <FH>) { ($handle, $message) = split(/\t/, $data); print "<p>\n"; print "投稿者:$handle<br>\n"; print "メッセージ:$message\n"; print "</p>\n"; } } else { print "<p>ファイルを読み込めません。</p>"; } #フッタの表示 print "</body>\n"; print "</html>\n"; exit; このような感じでかいたのですが文字コードを変更し,unshift(@file, "$name1\t$name2\n");と記述すると何も書かれずに空白になってしまいます..なぜでしょうか?困っています.教えて下さい. ちなみにunshift(@file, "$in{'handle'}\t$in{'message'}\n"); と文字コードの変更を意識しなかった場合にはちゃんとファイルに書かれています. jcode.plなどは使わずにencodeで行いたいです.

  • Perl
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • N60-BASIC
  • ベストアンサー率80% (17/21)
回答No.2

「混ぜるな危険。」という言葉が適切かと思います。 おそらく、似たような既存のCGIスクリプトから(意味がわからないまま)寄せ集めたのではありませんか? CGIスクリプト冒頭で、 > #投稿された値を受け取る > if ($ENV{'REQUEST_METHOD'} eq 'POST') { > read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'}); > } else { > $alldata = $ENV{'QUERY_STRING'}; > } > foreach $data (split(/&/, $alldata)) { > ($key, $value) = split(/=/, $data); > > $value =~ s/\+/ /g; > $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg; > $value =~ s/\t//g; > $in{"$key"} = $value; > } と自作ルーチンでGET/POSTデータを全て%inに取得しているにもかかわらず、$name1と$name2ではCGIモジュールでもう一度取得し直そうとしています。 > use CGI; > $cgi=new CGI; > $name1=$cgi->param('handle'); > $name2=$cgi->param('number'); しかし、CGIモジュールが取得しようとした時点ではすでにPOSTデータを含んでいる標準入力(STDIN)のファイルポインタがread()によって末端に来ているため、データの取得に失敗しているのではないでしょうか。手元で検証していないので可能性の話ですけど。 どちらかのみを使えばとりあえずデータの取得はできるようになるでしょうが、冒頭部分のルーチンは1990年代、Perl4の時代によく使われていた類の太古のルーチンです。 私なら、CGIモジュールを使う方法で一本化します。 # 冒頭のルーチンを以下に差し替え。スクリプト中盤にある重複部分は削除。↓ use CGI; my $cgi = new CGI; my $name1 = $cgi->param('handle'); # なんで「$name1」なんだろう・・・ my $name2 = $cgi->param('number'); # なんで「$name2」なんだろう・・・ my $message = $cgi->param('message'); # if ($in{'handle'} ne '' && $in{'message'} ne '') { # の部分を差し替え↓ if($name1 ne '' && $message ne '') { ところで、HTMLフォームに<INPUT name="number">がないんですけど、$cgi->param('number')はどこからどんなデータを引っ張ってきているんでしょうね? あと、質問とは内容が離れるかもしれませんが、質問者さんのスクリプトはいろいろと問題を抱えているように見受けられます。 ●HTMLフォームがUTF-8であれば、送られてくるデータもUTF-8であることが(今時のPCブラウザなら)保証されるのにもかかわらず、なぜ文字コードの自動判定(Encode::Guess)でわざわざUTF-8以外の文字コードとみなすようにしているのでしょうか。また、あえて「Shift_JIS」を使うということは、UTF-8よりも利用できる文字種がはるかに少ないということに留意してください。これらはどちらも文字化けやセキュリティホールの原因にもなります。携帯電話への対応や外部システムとの連携が必要でない限り、データ保存を含めて全てUTF-8で行うのが現代の主流です。 ●BBSデータファイルの読み書きで、(文法ではなく)ロジックに問題があります。適切な排他制御を行っていないために、読み書きが同時に発生した場合にはそれまで書き込まれたデータが失われる等の不具合が発生することでしょう。適切な排他処理の方法については、以前別の質問で回答したことがありますので参考にしてみてください。 http://okwave.jp/qa/q6697390.html http://okwave.jp/qa/q6105773.html ●この入力フォームにHTMLタグを入力したらどうなるかを考えてみてください。悪意を持って書き込んだら、入力フォーム自体を見えなくしたり、別のページに自動ジャンプすることさえ可能です。 ●ケアレスミスを防ぐために、Perl4ではなくPerl5の文法で書きましょう。スクリプト冒頭にはuse strict; use warnings;をつけて。myによる変数の初期化が必要になりますが、未定義の値が紛れ込んだりした場合に警告してくれますので、$cgi->param('number')のようなミスは避けられるはずです。 わからない点があればその旨ご返答頂ければ補足できるかもしれません。頑張ってください。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

えぇっと, Encode::encode や Encode::decode を使うときには use CGI; $cgi=new CGI; $name1=$cgi->param('handle'); $name2=$cgi->param('number'); encode("shiftjis",decode('Guess',$name1)); encode("shiftjis",decode('Guess',$name2)); unshift(@file, "$name1\t$name2\n"); としているのに, 使わないときには unshift(@file, "$in{'handle'}\t$in{'message'}\n"); とするのは変ではありませんか? まあ Encode::encode/Encode::decode の使い方も違うけど.

関連するQ&A

  • perlでファイルへの書き込みができません!

    perlでファイルへの書き込みができません! 教えてください. webプログラミング初心者なのですが, フォームから送信されたデータをshift-jisに変換させてからbbs1.txtへの内容の書き出しを行いたいのですが, #!/Applications/XAMPP/xamppfiles/bin/perl print "Content-type: text/html; charset=utf-8\n\n"; # フォーム部分を表示する print <<EOL; <html> <body> <h2>一行掲示板</h2> <form method="post" action="bbs1.cgi"> メッセージ:<input type="text" name="message" size="60"> <input type="submit" value="送信"> </form> <hr> EOL &ReadParse(*form); # フォームの値を取得 $message = $form{"message"}; use Encode; use Encode::Guess qw(euc-jp shiftjis 7bit-jis); encode("shiftjis",decode('Guess',$message)); # ログファイル読み込み open(IN, "bbs1.txt"); @log = <IN>; close(IN); # メッセージが入力されているときは書き込み処理を行なう if ($message ne "") { # ログ先頭にメッセージを格納 unshift @log, "$message\n"; # ログファイルに書き込み open(OUT, "> bbs1.txt"); print OUT @log; close(OUT); } # ログ表示 foreach $data (@log) { chop $data; print "$data<br>\n"; } print "</body>\n</html>\n"; このような感じにし実行して後でtxtファイルを見ると何も書かれていません>< なぜでしょうか...? 教えて下さい>< 今気づいたのですがそれに関連してなのかログも表示されていませんでした...>< txtファイルのアクセス権は読み書き可になっています encodeはあえてつかっています.

    • ベストアンサー
    • Perl
  • Webプログラミング.ファイルへの保存について

    Webプログラミング初心者です. ファイルへの保存について質問です>< フォームから受け取ったデータを文字コード変更させてファイルに保存する場合 $name1=$cgi->param('name'); $name2=$cgi->param('number); このように一度変数にいれ. 次に文字コードの変換をし変換した内容を再び$name1,$name2に格納した場合, ファイルの書き出し•保存のソースコードは, if (open(FH, "form.txt")) { @file = <FH>; close(FH); unshift(@file, "$in{'name1'}\t$in{'name2'}\n"); //ココの部分です. if (open(FH, ">form.txt")) { print FH @file; close(FH); } else { print "<p>ファイルに書き込めません。</p>"; } } else { print "<p>ファイルを読み込めません。</p>"; } このような感じで良いのでしょうか? unshift(@file, "$in{'name1'}\t$in{'name2'}\n"); の変数名の部分では例題はフォームから受け取ったものを そのまま書いてある例が多くどのように記述したら良いかわかりません. 一度やってみてできなかったので他の部分にミスがあったのかと探し中ではありますが... 教えてください.お願いします><

    • ベストアンサー
    • Perl
  • utf8使用時のフォーム入力文字コード

    use utf8; binmode(STDIN,":encoding(shiftjis)"); をすると、入力時に内部変換がかかり、UTF-8として扱える という認識で使っていたのですが、下記のコードを実行してみると 入力した文字は普通に sjisで表示されます。 binmode(STDIN~ はどのような意味を持つのでしょうか。 http://www.lr.pi.titech.ac.jp/~abekawa/perl/perl_unicode.html http://www.hikoboshi.org/perl/doc/encode.html 他、いろいろなサイトで調べてみたのですが、いまひとつ 納得する回答を得ることができません。 //////////////////////////////////////////////////// use utf8; use open 'encoding(utf8)'; binmode(STDIN,":encoding(shiftjis)"); use CGI; print "content-type:text/html; charset=Shift_JIS \n\n"; print <<"EOM"; <form action="xxx.cgi"> <input type="text" name="hoe"> <input type="submit"> </form> ここは UTF-8文字列なので化ける<br> EOM $cgi = CGI->new; print $cgi->param('hoe'); //////////////////////////////////////////////////// 現在は下記のコードで自前で UTF-8に変換しています //////////////////////////////////////////////////// foreach( $cgi->param() ){ my $str = $cgi->param($_); $str = Encode::encode('utf-8', Encode::decode('shiftjis', $str)); $cgi->param( -name=>$_, -value=>$str ); }

    • ベストアンサー
    • Perl
  • perlのcgiが文字化けします。

    perlを使ったcgiを作ろうと思い、こんなプログラムを書いてみたのですが、htmlのタグに囲まれた部分の日本語が文字化けしてしましいます。ファイルの文字列は上手く表示できるのですが… どうすればいいでしょうか。 文字コード判別をしてみたところ、このプログラム自体はShift-JISで書かれているようです。 開いているファイルはutf-8のようです。 #!/usr/bin/perl #ヘッダの表示 print "Content-Type: text/html; charset=utf-8\n\n"; print "<html>\n"; print "<head><title>掲示板</title></head>\n";#これが文字化け print "<body>\n"; print "<input type=\"text\" name=\"mail\" size=\"20\" value=\"\"><br>\n"; print "メッセージ<br>\n";#これも文字化け my $File = 'party0339.html'; if (-e $File) { #####@ファイルを開く…上でファイルが存在してることを確認して開けない場合はエラーメッセージ open(FF,"<:utf8",$File) or die "ファイル:$File を開けない $! \n"; my @FILE = <FF>; close (FF); ####@読み込んだデータを$Dataに格納する foreach (@FILE) { $Data = $_; print "$Data<br>\n"; } } #フッタの表示 print "</body>\n"; print "</html>\n"; exit (); 対策や原因などを教えてくださるとありがたいです。よろしくお願いします。

  • cgi出力での文字コードについて

    下記のソースをsjisで作っていて、出力するdata.txtをuft-8で保存したいです。 どのようにすればよいでしょうか? 下記ソースでは、data.txtはsjisになっています。 尚、htmlはsjisなのでそのまま使用したいです。 どなたか教えてください。 宜しくお願いします。 ############################# #!/usr/local/bin/perl require 'jcode.pl'; require 'cgi-lib.pl'; &ReadParse; $datafile='data.txt'; ←これの保存のみutf-8にしたい open(FH,">$datafile"); print FH "$in{'name'}"; close(FH); rint "Content-type:text/html\n\n"; print "<meta http-equiv='Content-Type' content='text/html; charset=Shift_JIS'>"; print "<html><head></head><title>テスト</title><body>\n"; print "<center>入力完了しました。</center><hr /><br>\n"; print "<b>名前:</b>$in{'name'}<br>\n"; print "<hr />\n"; print "</body></html>";

    • 締切済み
    • CGI
  • cgiメールの文字変換がうまくできない

    CGIメールです。 元々shiftjisなので、これをiso-2022-jpに変換させようとしてます。 $charset = "iso-2022-jp"; open(MAIL,"| $sendmail -t") || &error("失敗"); print MAIL "To: <$to>\n"; print MAIL "From: <$from>\n"; &jis("タイトル"); &base64("$msg"); print MAIL "Subject: $str\n"; print MAIL "MIME-Version: 1.0\n"; print MAIL "Content-type: text/plain; charset=$charset\n"; print MAIL "Content-Transfer-Encoding: 7bit\n"; foreach ( split(/\n/, $body) ) { &jis("$_"); print MAIL $_, "\n"; } close(MAIL); sub jis{ $msg = $_[0]; Encode::from_to($msg, "shiftjis", $charset); ####1#### } sub base64 { use MIME::Base64; $str = $_[0]; if($str =~ /[^!-~\s]/){ $str = encode_base64($str, ""); if($charset eq "utf8"){ $str = '=?utf-8?B?' . $str . '?='; }else{ $str = '=?iso-2022-jp?B?' . $str . '?='; } } } このようにしてみたのですが、タイトル部分はきちんと表示されるのですが、ボディー部分が文字化けしてしまいます。(メーラーで手動にてshit-jisにエンコードしたらボディー部分が読めタイトル部分は文字化けする) Encode::from_to($msg, "shiftjis", $charset); の$charsetを"$charset"にしても同じ現象です また、元々参考にしたものでは####1####に retern $msg; があったのですが、これを入れるとsyntax errorになったので、これをコメントアウトしたらエラーにはならず送信そのものはできました ただ目的の文字変換ができないのですが、どこをどう改善すればいいでしょうか。 どうかご存じの方ぜひ教えてください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perl メール文字化け

    #メール本体設定 my $start = '~ホームページより以下の内容を受け取りました~'; my $Name =$q->param('Name'); if($Name eq ""){ print "Content-type: text/plain; charset=Shift_JIS\n\n"; print "名前が入力されていません。\n\nブラウザの戻るボタンで戻ってください。"; exit(1); } my $Sex =$q->param('q1'); my $Age =$q->param('q2'); my $ie =$q->param('ie'); my $Tell =$q->param('Tell'); my $body = $q->param('body'); if($body eq ""){ print "Content-type: text/plain; charset=Shift_JIS\n\n"; print "本文が入力されていません。\n\nブラウザの戻るボタンで戻ってください。"; exit(1); } #my $subject = $q->param('subject'); my $End = '~~~~~~~~~~~~~~~~~~~~~'; #メール送信オブジェクト設定 my $smtp = Net::SMTP->new('n-doboku.jp'); if ( !$smtp ) { print "メールサーバーにアクセスできません!"; exit; } #メール文字コード変換 Encode::from_to($start, 'shiftjis', 'iso-2022-jp'); Encode::from_to($Name, 'utf8', 'shiftjis'); Encode::from_to($Sex, 'utf8', 'shiftjis'); Encode::from_to($Age, 'utf8', 'shiftjis'); Encode::from_to($ie, 'utf8', 'shiftjis'); Encode::from_to($Tell, 'utf8', 'shiftjis'); Encode::from_to($body, 'utf8', 'shiftjis'); Encode::from_to($End, 'shiftjis', 'iso-2022-jp'); #メール送信 $smtp->mail($from); $smtp->to($mailto); $smtp->to($mailcc); $smtp->data(); $smtp->datasend($header); $smtp->datasend("$start\n\n"); $smtp->datasend("名   前 : $Name\n\n"); $smtp->datasend("性   別 : $Sex\n\n"); $smtp->datasend("年   齢 : $Age\n\n"); $smtp->datasend("住   所 : $ie\n\n"); $smtp->datasend("電話番号 : $Tell\n\n"); $smtp->datasend("本   文 : $body\n\n"); $smtp->datasend("$End\n\n"); $smtp->dataend(); $smtp->quit; 現在、 SMTPを使用しメール送信を作成している最中です。 やっと、パソコンからパソコンへメール送信では文字化けしなくなったのですが まず (1)パソコンでも異字体などは文字化けしてしまう(髙や﨑等) おそらく「Content-Transfer-Encoding: 8bit」これを使うのですが、使いかたがわからないです・・・ (2)スマホにメール送信したときはすべて文字化けしてしまうのですが、 スマホでの文字コードとはなんなのでしょうか・・・? また、一回utf8に変換しているのですが、この場合どうするのでしょうか・・・?

    • ベストアンサー
    • Perl
  • perlがうごきません

    htmlファイルには <html> <form action="form2.cgi" method="get"> 食品名1<input type="text"name="form1"> <br> 食品名2<input type="text"name="form2"> <input type="submit"value="送信"> </form> </html> cgiファイルには #! /usr/bin/perl require "cgi-lib.pl"; &ReadParse(); print "Content-type:text/html\n"; print "\n"; print "<html>\n"; print "<head>\n"; print "<title>フォーム</title>\n"; print "</head>\n"; print "<body>\n"; print "おいしい$in{'form1'}\n"; print "まずい$in{'form2'}\n"; print "</body>\n"; print "</html>\n"; exit; cgi-lib.plはサーバーにいれております。 どうしてうごかないのでしょうか。 perlの場所も正確です。

    • ベストアンサー
    • Perl
  • Perlがサーバー上でうごきません

    htmlファイルには <html> <form action="form2.cgi" method="get"> 食品名1<input type="text"name="form1"> <br> 食品名2<input type="text"name="form2"> <input type="submit"value="送信"> </form> </html> cgiファイルには #! /usr/bin/perl require "cgi-lib.pl"; &ReadParse(); print "Content-type:text/html\n"; print "\n"; print "<html>\n"; print "<head>\n"; print "<title>フォーム</title>\n"; print "</head>\n"; print "<body>\n"; print "おいしい$in{'form1'}\n; print "まずい$in{'form2'}\n; print "</body>\n"; print "</html>\n"; exit; cgi-lib.plはサーバーにいれております。 どうしてうごかないのでしょうか。

    • ベストアンサー
    • Perl
  • Perlの文字コード変換についての質問です。

    Perlの文字コード変換についての質問です。 ホームページ全体は、UTF-8で作成されています。 そのため、$qsは、どうも、S-JISのようなので、UTF-8に変換して URLデコードさせたいのですがうまくいきません。 文字化けしないで、UTF-8で作成されたページに表示させたいのですがどうすればよいでしょうか? 宜しくお願い致します。 ------------------------------------ $qs = $ENV{'QUERY_STRING'}; use Encode::Guess qw/ shiftjis /; use Encode qw/ decode /; $enc = guess_encoding ( $qs ); if ( ref $enc ) { $utf8 = decode ( $enc->name , $qs ); } $qs =~ tr/+/ /; $qs =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; print "$qs";

    • ベストアンサー
    • Perl

専門家に質問してみよう