アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になります。
少し前の質問「ファイルの中身を変更するcgi」
http://oshiete1.goo.ne.jp/qa5533718.html)で
ryu chanさんに教えていただきました。

本件については全く上手く動いたので、
喜んでいまして、
これが出来たので最終的にやろうとしていたことを実行したく、
再度質問させていただいた次第です。

というのは、
今回単体では漢字化が可能になり、
結果も思ったとおりに出力されているのですが、
最終構想ではこのステップを最後ステップにして
一連のcgiを作成したいと思っています。

具体的には、
***************ここから
if ($FORM{'mode'} eq 'jikkou') {&header;
&cstp1;
&cstp2;
&cstp3;
&cstp4;
&cstp5;
&cstp6;}
else {&kijunbi;}
     exit.
***************ここまで
(初めに基準日を入力させ、以降ファイルの化工をし、
最後に漢字化して終了)

の様なロジックになっており、
今回教えていただいた部分(漢字化)はcstp6に該当します。
前段で作成したファイルを読み、漢字化して終了、
という構想です。


喜んでcstp6に埋め込んだのですが、
上手く動きません。
基本的なことが分かっていないからだと思います、
申し訳在りません。


症状は、
(1)漢字の入力まで行きますが、出力してくれず、
(2)また&kijunbiを実行してしまいます。

(2)はなぜかは分かりますが、対応の方法が分かりません。
(1)についてはサッパリ分かりません。

ということで、
前回同様、手直し部分を教えていただきたいのです。
なにとぞ宜しくお願いします。

A 回答 (3件)

decode関数でPOSTフォームを読み込んでいて、STDINのポインタが進んでいるのが原因ではないかと思います。



以下のようにseek関数でこれを元に戻せばうまくいくのではないでしょうか?

my @kanji_names = CGI->new->param('kanji');
↓   ↓    ↓追加
seek STDIN, 0, 0;
my @kanji_names = CGI->new->param('kanji');

この回答への補足

#デコード処理
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は問題ないと思い、割愛しました。
(別の方法で確認しました。)
お手間を掛けさせ恐縮ですが宜しくお願いいたします。

補足日時:2009/12/22 22:30
    • good
    • 0
この回答へのお礼

#!/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>};
}

お礼日時:2009/12/22 22:28

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};
    • good
    • 0
この回答へのお礼

何回も有り難うございます。
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;

# " を &quot; に変換
$value =~ s/"/&quot;/g;
#\n を "" に変換
$value =~ s/\n//g;

# 日本語に変換(デコード処理部分)
&jcode'convert(*value,'sjis');
&jcode'convert(*name,'sjis');
$FORM{$name} = $value;

}
}
*************ここまで

私は昔から分からないままこれをコピーして使ってきましたが、
これが原因しているかと。
宜しくお願いします。

お礼日時:2009/12/22 14:50

確信は持てないのですが、”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;

この回答への補足

確認の仕方が誤っていました。
(2)の終わらない、ですが、
チャンと終了できました。

オリジナルを保存しておくために、コピー(リネーム)してテストしていましたが、
今回に関係ないstage1のactionを変更していませんでした。
このため元のcgiが使われていたと思われます。
修正したところ、チャンと終了しました。
ただ、(1)のファイルが出力されない点には変化がありません。

もう一つ、
print q{ のようにある qですが、
qとqqが存在していたので分からないままに、
qとしたりqqとしたり、やってみました。
それでも変化がありませんでした。
そもそもこのqは1個と2個で意味があるのでしょうか。
1個と2個では違うモノなのでしょうか。

私が考えられることはやった感じです。
極端には、ステップ1~5までと、ステップ6(本件漢字化)を分ければ解決なのですが、
折角漢字化が出来たので繋げたいと思っています。
お手数をおかけしますが宜しくお願いします。

補足日時:2009/12/22 06:38
    • good
    • 0
この回答へのお礼

今回も付き合っていただき、
誠に有り難うございます。
お世話になります。

まず、
やってみた結果のご報告ですが、
(1)関係(ファイルの出力)ですが、
単体では相変わらず問題なく綺麗に出力されますが、
最終形(本件を最終ステップに持っていったパタン)では、
出力されません。

言ってみれば、
今回見直していただいた出力ロジックに変更しても変化はなかった。
ということです。

また、
(2)関係(終了せずに繰り返す)ですが、
formに'jikkou'を入れ、メインルーティンでjikkouだったらexit;と
やりましたが、これも止まりませんでした。
(入れる前と状況は変化無しです)

もう少し色々やってみたいと思いますが、
とりあえずご報告です。
お世話になりますが、宜しくお願いいたします。

お礼日時:2009/12/21 22:47

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!