プロが教える店舗&オフィスのセキュリティ対策術

CGIを使用してフォームで入力された値を取得する時にデータ内にシングルクォートなどがあると
そこから先が消えてしまいます。

たとえばフォームに「X'mas」と入力されていた場合に、実際には「X」しか取得できません。

$buffer =~ s/'/\'/g;

としてみたのですが、ダメでした。

どのようにしたらいいのでしょうか?

A 回答 (2件)

> cgi内では"は使用できませんよね?


そんなことは無いです。ちゃんと使用できますよ。
ダブルクォートで囲んだ文字列の中にダブルクォートを入れる場合、
  $str = "<IMG src=\"xxx\">\n";
のように、「\」を使ってエスケープすれば大丈夫です。

ただ、この方法でHTMLを書くと \ だらけで大変見にくくなってしまうので、「ヒアドキュメント」や「qq 演算子」(または「q 演算子」)を使うことが多いです。
No.1では qq を使って「qq{文字列}」のように書きましたが、{ と } の部分は、他の種類のカッコか、別の記号文字でも構いません。
詳しくは参考書などで調べてみてください。

次に chr2ref 関数について。
「文字参照」は知ってますよね?(&lt; や &amp; など)
フォームのvalue内の一部の文字参照は、送信時に文字実体となって送信されます。
つまり、
  <INPUT type="hidden" name="a" value="b&amp;c">
という hiddenフォームの値を受け取ると
  a=b%26c   (「%26」をデコードすると「&」)
となっています。

もちろん、value="b&c" でも大丈夫ですが、前述のダブルクォートや文字参照自身を書きたい場合には必要です。
例えば「&lt;」自身を出力する場合は「&amp;lt;」としなければなりません。

通常の文字列を書き出す際に chr2ref を通すことは、フォームだけでなくHTML全体において有効ですが、受け取ったフォームの値を使う場合には注意が必要です。
なぜなら、掲示板のような‘入力された値をHTMLに出力するCGI’では、たいていの場合、入力された < や > をデコードの時点で文字参照に変換しているのです。
文字参照化されている文字列を chr2ref に通すと、
  入力値  <
   ↓
  デコード &lt;
   ↓
  chr2ref &amp;lt;
となってしまいます。

もしデコードで文字参照化を行っていなければ、No.1のお礼のやり方で問題ありません。
行っている場合は chr2ref は必要ないわけですが、デコードの文字参照化がちゃんと &、<、>、" の4文字を対象にしているか確認して下さい。
中途半端に < と > しかやっていないと、うまく行かないことがあります。
また、必ず & → &amp; の変換を最初に行って下さい。でないと < → &lt; → &amp;lt; となってしまいます。
    • good
    • 0

フォームのvalue値をシングルクォートで囲んでいませんか?


例えば、
  <INPUT type=hidden name=a value='X'mas'>
のようにすると、「value='X'」と その他の属性「mas'」であるかのように認識され、X しか送信されません。
回避するには value='X\'mas' のようにすればよいでしょう。

ただし、本来ならシングルクォートではなくダブルクォートで囲み、中のダブルクォートは文字参照(&quot;)に変換するべきです。
(同様に、&、<、> の変換も必要)
なので、そのような文字参照への変換関数を1つ作っておき、HTMLへの出力する値はその関数を通すようにしてはどうでしょう?

sub chr2ref {
  local($_) = @_;
  s/&/&amp;/g; s/</&lt;/g; s/>/&gt;/g; s/"/&quot;/g;
  $_;
}

print qq{<INPUT type="hidden" name="a" value="}, chr2ref("X'mas"), qq{">\n};
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

実際の書込みはcgiによるデータの送受信で行っているのですが、
その場合も
chr2ref("$FORM{'hogehoge'}")・・
のようにしてしまってもOKなのでしょうか?

またダブルクォーテーションを使用したかったのですが、cgi内では"は使用できませんよね?それで安易に'を使用してしまったのですが…。

お礼日時:2002/12/13 16:18

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