掲示板でログファイルへの書き出しの際に文字コードを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で行いたいです.
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')のようなミスは避けられるはずです。
わからない点があればその旨ご返答頂ければ補足できるかもしれません。頑張ってください。
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が見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- PHP PHP MySql 画像を取得 1 2022/06/04 14:05
- PHP PHPで画像の渡しが上手く行きません。 1 2023/02/02 09:39
- PHP PostgreSQLからCSV形式でエクスポートする際にカラム内の改行をとる方法 1 2023/02/22 10:05
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
サーバーのテキストファイルを...
-
標準入力からデータが読込めない
-
wordの数式について 定積分を書...
-
ラジオボタンが両方とも選択で...
-
WEBページを強制的に横画面で見...
-
ディレクトリのファイル数取得
-
チェックボックスの返す値
-
フォントサイズを変えるには?
-
selectboxの画面遷移で、postデ...
-
ブックマークからのアクセスを...
-
select値をhiddenのvalueに渡し...
-
FC2 掲示版のカスタマイズの仕...
-
コンボ1の内容に応じてコンボ...
-
<select>タグの幅設定
-
INPUT TYPE
-
htmlファイルが表示できません
-
CGI(Perl)内での必須項目チェ...
-
プログラミングについての質問...
-
CGI実行できない。ソースが表示...
-
「value」に2つの値をセットす...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
サーバーのテキストファイルを...
-
canonicalのURLエンコードについて
-
Perl CGI 初心者
-
sendmailの文字化け
-
If文について教えてください。
-
フォームメール確認用ページ
-
ヒアドキュメントが表示されない
-
サーバー(UNIX)上のフォルダ...
-
jcode.pl 使い方
-
perlでHTMLソースを解析してfor...
-
IIS の@INC ERRORについて教えて
-
IIS上でフリーCGIが動かない
-
SUN BBSの改造方法
-
ラジオボタンが両方とも選択で...
-
「value」に2つの値をセットす...
-
WEBページを強制的に横画面で見...
-
select値をhiddenのvalueに渡し...
-
チェックボックスの返す値
-
INPUT TYPE
-
wordの数式について 定積分を書...
おすすめ情報