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

CGI勉強中です。
掲示板を作っているのですが、テキストエリア内でタグを使用できるようにするにはどうしたら良いのですか?

ってここに解答を書いていただいたらそれはそれでうれしいのですが、
「このサイトに詳しく載っているよ」の方が、自分のためにもなると思うので、そういったサイトをご存知だったら教えてください。

よろしくお願いいたします。

A 回答 (13件中1~10件)

タグを許可する時は「全てのタグをエスケープし、許可するもののみ戻す」という方法をとります。


以下、入力文字列が $val に入っているものとします。

タグのエスケープでは、
  $val =~ s/&/&/g;
  $val =~ s/</&lt;/g;
  $val =~ s/>/&gt;/g;
  $val =~ s/"/&quot;/g;
を行います。( & の変換は最初に行うこと)

属性のないタグは
  $val =~ s/&lt;(\/?b)&gt;/<$1>/gi;
という方法で元に戻します。
多くの掲示板でそうであるように、特殊な入力を強いる必要はありません。
(許可するタグの「閉じタグ」もこの方法で戻します。)

属性のあるタグは、タグを解析します。
正規表現で許可するタグを拾い、それぞれのタグ解析ルーチンから正常な属性文字列を取得してタグを戻します。
  #           ↓ここに許可するタグを書く
  while ($val =~ /&lt;(font|img)\s+(.*?)&gt;/gi) {
    my $tgt = quotemeta $&;       # 拾ったタグ全体
    my ($tag, $attr) = ($1, $2);
    $attr =~ s/&quot;/"/;        # 属性部をアンエスケープ
    $attr =~ s/&amp;/&/;
    my @attrs = split /\s+/, $attr;   # 属性を分解

    # それぞれのタグ解析ルーチンへ
    if  ($1 =~ /font/i) { $tag .= tag_font(@attrs); }
    elsif ($1 =~ /img/i) { $tag .= tag_img(@attrs); }

    # タグを戻す
    $val =~ s/$tgt/<$tag>/;
  }

例えば font タグ用の解析ルーチン tag_font は、次のようになります。
  sub tag_font {
    my $tag;
    foreach (@_) {
      my ($attr, $val) = split /=/;
      $val =~ tr/"'//d;

      # 許可する属性のみ $tag に追加する
      if (lc($attr) eq 'size') {
        # ±1~3 または 1~7 を許可
        if ($val =~ /^[+-][1-3]|[1-7]$/) {
          $tag .= qq{ $attr="$val"};
        }
      }
      elsif (lc($attr) eq 'color') {
        if ($val =~ /^#[A-Fa-f0-9]{6}|[A-Za-z]+$/) {
          $tag .= qq{ $attr="$val"};
        }
      }
    }
    return $tag;
  }

また、URLやメールアドレスの自動リンクについては、「Perlメモ(参考URL)」というサイトの「http URL の正規表現」や「メールアドレスの正規表現」の項にある正規表現が大変便利です。
各項の一番最後に書かれている $http_URL_regex と $mail_regex を使い、次のように書くことができます。

・メールアドレスの自動リンク
  $val =~ s/($mail_regex)/<a href="mailto:$1">$1<\/a>/g;

・URLの自動リンク
URLの自動リンクには注意が必要です。
なぜなら $http_URL_regex が、imgタグのsrc属性値までも対象としてしまうからです。
これを回避するためには、次のように書きます。
  while ($val =~ /($http_URL_regex)/g) {
    my $url = $1;
    # マッチした URL の後続文字列 $' の先頭を調べ、
    # img の src や変換済み URL を変換しないようにする
    if ($' !~ /^"|<\/a>/) {
      $val =~ s/$url/<a href="$url">$url<\/a>/;
    }
  }

以上を組み合わせれば、タグの許可および自動リンクが実現できます。

参考URL:http://www.din.or.jp/~ohzaki/perl.htm
    • good
    • 0
この回答へのお礼

詳しい説明ありがとうございます。

何とかなりそうです。
ホントCGIって難しいですね。まだまだ勉強が必要です。

お礼日時:2003/03/21 11:25

> 多くの掲示板でそうであるように、特殊な入力を強いる必要はありません。


どちらも一長一短ありますね。

(タグを多用することがあるかどうかは)掲示板のテーマしだいですが、タグ(の書き方)を記述するのに、「<div>」、「&lt;b&gt;」等と使い分けなきゃいけないのもどうかと思いますけど。すべて文字参照、というのはもっといやですね。

特殊な入力とはいっても、工夫さえすれば問題ないと思いますよ。
これも、#6で紹介したphpBBで採られていた方法をいただいたのですが、マウスクリックまたはメタキーでサイクリックに入力できるので、直接書くよりは楽です。

あとは、質問者さんの好みで決めればいいのではないでしょうか。
    • good
    • 0

またまたすみませんです。

補足を意味を取り違えておりました。

> <a hreh>はhttpで始まるものは自動でリンクに変換(よく見かけますよね)のほうが良いのでは?この方法はどうしたらいいでしょうか?

いいかどうかはポリシー、ページのテーマにもよると思います。
例えばここですが、解説のために例示した架空のURLがリンクになっては困りますよね。
個人的には明示的に入力する方を選びます。

やり方は #6,#10および#10のURLを参考にガンバッテください。
    • good
    • 0
この回答へのお礼

ありがとうございます。
とりあえずがんばってみます。

お礼日時:2003/03/19 14:01

> <a hreh>はhttpで始まるものは自動でリンクに変換(よく見かけますよね)のほうが良いのでは?この方法はどうしたらいいでしょうか?



> あとの問題は、<font>と<img>。<>内に語句が入るため> |**|では対応できないですよね。何か良い方法無いでしょうか?

#6に回答が書いてありますよ?
あれを、perlに書き換えるだけです。perlの場合、「/」をエスケープする必要があるかも分かりません。

<a href=\"\\1\" target=\"_brank\">\\1</a>
の\\1が、正規表現に一致した内容、つまり、|url|,|/ulr|ではさまれたURLになります。
\\1の数字の部分が、「(」の出現順の番号です。\\2なら、httpかftpですね。

> htm(l)で終わる分は<a href></a>に変え[HOME]等を表示
気休めですが、[HOME]のような表示はやめて、URLをそのまま表示した方が、良いかと思います。

<img>は#6の正規表現をアレンジして最後に 「\.(gif|jpg|jpeg|png|)」を追加すればいいかな。

正規表現については、参考URLの「perl」に詳しい解説が有ります。

参考URL:http://tohoho.wakusei.ne.jp/www.htm
    • good
    • 0

補足です。


タグですが、入力を簡単にするため、許可したタグのボタンを全部ならべて、クリックでテキストエリアに入力するJavaScriptを組んであります。これなら、何が使用可能か一目瞭然です。

ところで、画像は具体的にどうしたいのでしょうね?

自由度が増すほど登録メンバーのみ投稿を許可などの制限を設けた方が良いと思います。
phpBBという高機能な掲示板がありまして、サーバ側で用意して選択させる方法、サイズを制限してアップロード可能な方法、画像へのリンク、いずれも出来るようになっており参考になりました。もちろんメンバー制です。
ソースはかなり複雑です。

#6のサンプルは、英数字、チルダ、ハイフン、スラッシュ、ドット以外の文字が含まれていたら変換しないようになってます。
(イメージは拡張子 gif, jpg, pngのみ許可。)


> ただ、<A>や<IMG>許可するようであれば、
> タグ全て許可と対して変わらないかもしれませんよ。
表示の問題もあるのでなるべく制限した方がいいでしょう。<table>など下手に使われると目茶苦茶になりますしね。
    • good
    • 0

たぶん、皆さんの発言で解決は出来ると思いますが、


質問するのでしたら、テキストエリア内でタグを利用できるように・・・
ではなく、
掲示板の投稿時、タグを反映させたいのですが・・・
でしたね。

タグの全て許可はたしかに危険ですが、
JavaScriptと、スタイルシートの許可さえしなければ、
いうほど危険もないかもしれません。
ただ、<A>や<IMG>許可するようであれば、
タグ全て許可と対して変わらないかもしれませんよ。
conconなんてのがあるし、<A>内にJavaScriptでなんでもありになりますから。

文字装飾だけの許可にしては?
URLのリンクは、#4さんがおっしゃるような形か、
URL部分を抜いておいて( 参照リンク )と言った形でリンクするとかね。

最後に、タグ閉じ忘れのケアレスミスにご注意を。

この回答への補足

回答ありがとうございます。
なにぶん初心者なので、どう説明したら良いのかがわからず、変な書き方しちゃいました。すみませんでした。

さて、問題の件ですが、リンクは#7でも書きましたが、自動変換で対応できないかと考えました。これでもダメですか?

<img>はやっぱり必要なんです。どうにかならないですかね…


……
でも、よく考えると、<img>使用するんだったら画像アップローダーが必要ですよね。
ただの画像表示(リンクのみ)だったらさっきの自動リンクで何とかならないですかね。
htm(l)で終わる分は<a href></a>に変え[HOME]等を表示、gif・jp(e)gは<img>に変換…
こんな都合いい事出来ないですか?

補足日時:2003/03/19 10:19
    • good
    • 0

#6 です。

すいません、また、違ってました。
ポストしたあと見たら書いたほど、厳密なチェックではありませんね。

やろうとしたのですが、
http://xxxx.yyy.zz/~abc/ddd.eee/index.html
なんてのまで考えると複雑になりすぎるので断念したのでした。

この回答への補足

いろいろとありがとうございます。
いろいろと弊害があるということがわかってきたので、ちょっとやり方を変えたいと思います。
<B>は「$value =~ s/|b|/<b>/g; 」で対応するとします。
<a hreh>はhttpで始まるものは自動でリンクに変換(よく見かけますよね)のほうが良いのでは?この方法はどうしたらいいでしょうか?

あとの問題は、<font>と<img>。<>内に語句が入るため|**|では対応できないですよね。何か良い方法無いでしょうか?

補足日時:2003/03/19 10:10
    • good
    • 0

> $value =~ s/</&lt;/g;


> $value =~ s/>/&gt;/g;
> $value =~ s/|b|/<b>/g;
> であってますか?

それで OKです。
ついでに、URLのやり方ですが、|url|http://~|/url|の形で入力して

$str = ereg_replace("|url|((http|ftp)://(([0-9a-zA-Z\-~_]+)\.)+([0-9a-zA-Z\-~_]+)([0-9a-zA-Z\-~_\./]*))|/url|","<a href=\"\\1\" target=\"_brank\">\\1</a>",$str);

とやってます。

PHPなので、perlとは違いますが、正規表現は使えるのではないでしょうか。

上記の正規表現は、URLの記述の正しさのチェックもおこなっています。
http://xxxx.yyyy.zzz
× http://xxx.yyy.zzz.
× http://xxx.yyy
という結果になるはずです。

# もっと簡単に書けるかもわかりませんが、//以下が必ず三つ以上のパートから構成されていて最後が2文字以上の英字でないとNG(変換されずにそのまま表示される)になるように厳密にチェックしています(..のつもりなんですが)。
いい加減に評価するならもっと簡単になります。
    • good
    • 0

#4です。

一箇所間違えました。
>修正機能をもたせる場合、&lt;は&amp;lt;と変換してテキストエリアに表示しないとタグが有効になってしまいます。

「&lt;を&amp;lt;と変換しないと、&lt; と表示されず < になる」に訂正します。
    • good
    • 0

 最近、限定タグのみ使用可能にした掲示板を完成させたばかりなので。



「テキストエリア」とは #1に書いてある通り、掲示板等で入力するためのエリア(質問をポストした時のあの入力するための領域のことです)なのでタグの効果は反映されません。
スタイルシートで色や文字の大きさを指定したりする程度のことが出来るのは#2の通りです。

で、私の場合、
1.<, >を&lt;, &gt;に変換してタグを無効化。
2.特別に決めた表現のみHTMLタグに変換。例えば、|b|等と表現した場合に<b>に変換。
というふうにやりました。

但し、URLなど、値が変わる場合、正規表現を使う必要がありますし、入力された文字の正当性を評価することも必要だと思います(URLが複数指定された場合を考慮すると、かなり複雑な正規表現になります)。

修正機能をもたせる場合、&lt;は&amp;lt;と変換してテキストエリアに表示しないとタグが有効になってしまいます。

全てのタグを許可するなら、なにもしなくてもOKですが、やめといた方が無難だと思います。
    • good
    • 0
この回答へのお礼

ありがとうございます。そのことが知りたかったんです。

sub Decode内に「$value =~ s/</&lt;/g;」と「$value =~ s/>/&gt;/g;」があったためコメントアウト「先頭に#」してタグが有効になるようにしました。
ただ、言われるとおりこのままだとすべてのタグが使用できてしまうんですよね。
<a href><B><font><img>のみ使用可能というCGIを見かけましたが、どうやっているのですか?DLして中を見てみたのですが、いまいちよくわからずです。

ちなみに、
>例えば、|b|等と表現した場合に<b>に変換。
は、
$value =~ s/</&lt;/g;
$value =~ s/>/&gt;/g;
$value =~ s/|b|/<b>/g;
であってますか?

お礼日時:2003/03/18 19:01

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