- ベストアンサー
ファイルの中身を変更するCGIの実装について
- ファイルの中身を変更するCGIの実装についてお手伝いいたします。特定のステップを最後に実行する一連のCGIを作成し、漢字化機能を追加する方法を説明します。
- 現在実装しているCGIに漢字化のステップを追加するためのロジックについて誤りがある可能性があります。具体的な問題点を特定し、上手く動作するよう修正する方法を教えます。
- 漢字化のステップが正しく実行されず、また予期せぬステップも実行される問題が発生しています。問題の原因を特定し、適切な修正方法を提案いたします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
decode関数でPOSTフォームを読み込んでいて、STDINのポインタが進んでいるのが原因ではないかと思います。 以下のようにseek関数でこれを元に戻せばうまくいくのではないでしょうか? my @kanji_names = CGI->new->param('kanji'); ↓ ↓ ↓追加 seek STDIN, 0, 0; my @kanji_names = CGI->new->param('kanji');
その他の回答 (2)
- ryu_chan
- ベストアンサー率37% (69/186)
q{}は文字列をシングルクオテーション(')、qq{}は文字列をダブルクオテーション(")でくくったに相当します。 例えば、 q{これは単なる文字列です}='これは単なる文字列です' qq{これは単なる文字列です}="これは単なる文字列です" ということです。 スクリプト全体の流れがよくわからないので、うまく動作しない原因がよくわかりません。 今回の原因とはあまり関係ないかもしれませんが、action属性にスクリプト名を入れてみてください。 print qq{<form method="post"><p>\n}; ↓ ↓ ↓変更 print qq{<form method="post" action="$ENV{SCRIPT_NAME}"><p>\n}; 勘ですが、以下のように変更するとどうなるでしょうか? if ($FORM{'mode'} eq 'jikkou') {&header; &cstp1; &cstp2; &cstp3; &cstp4; &cstp5; &cstp6;} else {&kijunbi;} exit. ↓ ↓ ↓変更 if ($FORM{'mode'} eq 'jikkou') {&header; &cstp1; &cstp2; &cstp3; &cstp4; &cstp5; &cstp6;} elsif ($FORM{'mode'} eq 'kanji') { &cstp6; } else {&kijunbi;} exit. print qq{<input type="hidden" name="mode" value="jikkou">\n}; ↓ ↓ ↓変更 print qq{<input type="hidden" name="mode" value="kanji">\n};
お礼
何回も有り難うございます。 qについては了解しました。 有り難うございました。 肝心な方は、以下の全てを実行しましたが、全て駄目でした。 変化がありません。 (1)action="$ENV{SCRIPT_NAME}"の対応 (2)modeをkanjiにする対応 (3)上記でもう一度cstp6を実行する対応 動きは全て期待した動き方をしていますが、 結果の出力がありません。 ところで、 やってみた中で原因は分からないのですが事実が判明しました。 実は関係ないと思って表示していませんでしたが、 前述の以下のコーディングの前に、 入力画面を取得のために &decodeを実行していまして、 その後にcstp6があるとダメみたいです。 ***************ここから &decode; <---- 実際はこれがある。 if ($FORM{'mode'} eq 'jikkou') {&header; &cstp1; &cstp2; &cstp3; &cstp4; &cstp5; &cstp6;} else {&kijunbi;} exit. ***************ここまで そして、decodeの内容は以下のとおりです。 ***************ここから #デコード処理 sub decode { # プラウザからのデータ取込み read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # プラウザからのデータ変換 @pairs = split(/&/,$buffer); foreach $pair (@pairs) { #1行毎に$name,$valueを取り出す ($name, $value) = split(/=/, $pair); # 変換演算子 tr + を スペースに置き換え $value =~ tr/+/ /; # 変換演算子 s/// 単語の構成文字にマッチ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # " を " に変換 $value =~ s/"/"/g; #\n を "" に変換 $value =~ s/\n//g; # 日本語に変換(デコード処理部分) &jcode'convert(*value,'sjis'); &jcode'convert(*name,'sjis'); $FORM{$name} = $value; } } *************ここまで 私は昔から分からないままこれをコピーして使ってきましたが、 これが原因しているかと。 宜しくお願いします。
- ryu_chan
- ベストアンサー率37% (69/186)
確信は持てないのですが、”mode”に”jikkou”という値を入れてPOSTする必要があるように思えます。 前回のスクリプトに以下の行を追加するとどうなるでしょうか? print qq{<form method="post"><p>\n}; ↓ ↓追加 print qq{<form method="post"><p>\n}; print qq{<input type="hidden" name="mode" value="jikkou">\n}; あと、前回のスクリプトを見直しました結果、以下の箇所を修正したほうがよさそうです。 open my $out, '>', $new_file or die $!; flock $out, LOCK_EX; for my $i ( 0..$#students ) { print {$out} "$students[$i]{name}<>$students[$i]{score}<>$kanji_names[$i]\n"; $students[$i]{kanji} = $kanji_names[$i]; } close $out; ↓ ↓修正 my $tmp_file = $$ . ".tmp"; open my $out, '>', $tmp_file or die $!; flock $out, LOCK_EX; for my $i ( 0..$#students ) { $students[$i]{kanji} = $kanji_names[$i] || $students[$i]{kanji}; print {$out} join( "<>", map $students[$i]{$_}, qw(name score kanji) ), "\n"; } close $out; rename $tmp_file => $new_file;
お礼
今回も付き合っていただき、 誠に有り難うございます。 お世話になります。 まず、 やってみた結果のご報告ですが、 (1)関係(ファイルの出力)ですが、 単体では相変わらず問題なく綺麗に出力されますが、 最終形(本件を最終ステップに持っていったパタン)では、 出力されません。 言ってみれば、 今回見直していただいた出力ロジックに変更しても変化はなかった。 ということです。 また、 (2)関係(終了せずに繰り返す)ですが、 formに'jikkou'を入れ、メインルーティンでjikkouだったらexit;と やりましたが、これも止まりませんでした。 (入れる前と状況は変化無しです) もう少し色々やってみたいと思いますが、 とりあえずご報告です。 お世話になりますが、宜しくお願いいたします。
補足
確認の仕方が誤っていました。 (2)の終わらない、ですが、 チャンと終了できました。 オリジナルを保存しておくために、コピー(リネーム)してテストしていましたが、 今回に関係ないstage1のactionを変更していませんでした。 このため元のcgiが使われていたと思われます。 修正したところ、チャンと終了しました。 ただ、(1)のファイルが出力されない点には変化がありません。 もう一つ、 print q{ のようにある qですが、 qとqqが存在していたので分からないままに、 qとしたりqqとしたり、やってみました。 それでも変化がありませんでした。 そもそもこのqは1個と2個で意味があるのでしょうか。 1個と2個では違うモノなのでしょうか。 私が考えられることはやった感じです。 極端には、ステップ1~5までと、ステップ6(本件漢字化)を分ければ解決なのですが、 折角漢字化が出来たので繋げたいと思っています。 お手数をおかけしますが宜しくお願いします。
お礼
#!/usr/local/bin/perl $|=1; #データのフラッシュ require './jcode.pl'; #jcode.plへのパス print "Content-type: text/html\n\n"; # データ形式 $bgcolor = "green"; $home = "../compctl1.html"; #main &decode; if ($FORM{'mode'} eq 'stage2') {&header; &cstp6;} elsif ($FORM{'mode'} eq 'kanji') {cstp6;} else {&stage1;} exit; sub cstp6 { use CGI; use Fcntl qw(:flock); my $org_file = 'compewk.log'; # オリジナルファイル(漢字名なし) my $new_file = 'compewk.txt'; # 新規作成ファイル(末尾に漢字名あり) my @students; open my $fh, -f $new_file ? $new_file : $org_file or die $!; flock $fh, LOCK_SH; while ( my $line = <$fh> ) { chomp $line; my %data; @data{ qw(name score kanji) } = split /<>/, $line, -1; push @students, \%data; } close $fh; seek STDIN, 0, 0; my @kanji_names = CGI->new->param('kanji'); if (@kanji_names) { my $tmp_file = $$ . ".tmp"; open my $out, '>', $tmp_file or die $!; flock $out, LOCK_EX; for my $i ( 0..$#students ) { $students[$i]{kanji} = $kanji_names[$i] || $students[$i]{kanji}; print {$out} join( "<>", map $students[$i]{$_}, qw(name score kanji) ), "\n"; } close $out; rename $tmp_file => $new_file; } print "Content-Type: text/html\n\n"; print qq{<form action="$ENV{SCRIPT_NAME}" method="post"><p>\n}; print qq{<input type="hidden" name="mode" value="kanji">\n}; for my $student (@students) { print qq{$student->{name}<input type="text" name="kanji" value="$student->{kanji}">$student->{score}<br>\n}; } print q{<input type="submit" value="送信"></p></form>}; }
補足
#デコード処理 sub decode { # プラウザからのデータ取込み read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # プラウザからのデータ変換 @pairs = split(/&/,$buffer); foreach $pair (@pairs) { #1行毎に$name,$valueを取り出す ($name, $value) = split(/=/, $pair); # 変換演算子 tr + を スペースに置き換え $value =~ tr/+/ /; # 変換演算子 s/// 単語の構成文字にマッチ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # " を " に変換 $value =~ s/"/"/g; #\n を "" に変換 $value =~ s/\n//g; # 日本語に変換(デコード処理部分) &jcode'convert(*value,'sjis'); &jcode'convert(*name,'sjis'); $FORM{$name} = $value; } } sub stage1 { &header; print <<"TKDBBS"; <center> <FORM action="./sample.cgi" method="POST"> 抽出基準日:<input size="10" type="text" name="kijun" istyle="4"><br> <input type="submit" value="抽出する"><br> <input type="hidden" name="mode" value="stage2"><br> </FORM> </center> </BODY> </HTML> TKDBBS } #ヘッダ部分処理 sub header { print <<"TKDBBS"; <HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <TITLE>大会</TITLE> </HEAD> <BODY bgcolor="$bgcolor"> <A href="$home"><font color="red">戻る</font></A><br> <center> <h3><font color="red">大会作業</font></h3><hr> </center> TKDBBS } ryu_chanさん、大変お世話になります。 seek、変化がありませんでした。 唐突ですが、 また説明漏れが怖いので、全てをアップさせて貰いました。 (文字数の関係で、お礼から補足へ繋がります) 指摘を受けたところは出来ていると思うのですが自信がありません。 一通り見て頂けると嬉しいです。 cstp1~5は問題ないと思い、割愛しました。 (別の方法で確認しました。) お手間を掛けさせ恐縮ですが宜しくお願いいたします。