Perl/ActivePerl For UNIX/Linux/Windows
 
TryThe Homepage
初めてのCGI
CGI 研究室
ダイナミックCGI
ダウンロード
サービス
サーバ構築(Windows)
データベースアクセス
有料サービス
FAQ
お問い合わせ
このページを印刷
不正なタグの除去
本来、私個人としては掲示板にタグを許可する必要はないと考えています。 タグは、掲示板を華やかな物にしてくれる反面、恐ろしい機能も有しています。 そのため当サイトのフリーウェアでデフォルトでタグが使用できるスクリプトは存在しません。 しかしながら、大変多くの御要望を頂いておりますので、「タグ」の使用を考えてみましょう。
  1. 一般的なタグの除去
    現在公開されているスクリプトで、最も多く使用されているタグの除去法は、予め使用不可のタグを登録しておき、 本文中にそれらのタグが見つかれば、メッセージを表示するか書き込みをしないと言うシステムです。

    $tags[0] = '<img';
    $tags[1] = '<table';
    $tags[2] = '<!';
    $tags[3] = '<hr';
    foreach $tag (@tags) {
        if ($comment =~ /$tag/i) { error(bad_tag); }
    }

    この様な書式か、これの変形です。
    これには、いくつもの欠点が有ります。
    まず、タグが正常に閉じられているかがチェック出来ません。
    タグ綴じを忘れてしまったり、故意に閉じなかったりするとどのような現象が起こるでしょう?
    フォントタグを例に挙げて考えてみましょう。

    <font color=#0000FF size=5>これは、フォントサイズ5の文字を青色で書いています。</font>
    <font color=#FFFFFF>ここから後ろは真っ白です。

    このタグを実行すると、
    これは、フォントサイズ5の文字を青色で書いています。
    背景色が白なら、この以降に書き込まれた記事は他人の物まで文字色「白」で何も見えなくなります。

    これを回避するには、テーブルを使う方法が有りますが、これがまた厄介です。
    <table>タグは許可していませんので、使用する事は出来ませんが、スクリプトが自動でテーブルを作成している掲示板で、 </table>を入力されてしまうと一発で掲示板は破壊されます。
    それだけでなく、<td><tr>のセルを作成するタグも</td></tr>のようなセルを閉じるタグも 余分に入力されてしまうとおしまいです。
    それでは、
    $tags[4] = '</table';
    $tags[5] = '<td';
    $tags[6] = '<tr';
    $tags[7] = '</tr';
    $tags[8] = '</td';
    のように、禁止タグを増やせばいいとお考えかもしれませんが、これが最大の欠点です。
    ご存知のように、現在のインターネットは凄まじい勢いで発展しています。
    新しいブラウザが開発されるたびに大変多くのタグが追加されています。
    これらの中には、システムを制御できる恐ろしいタグも含まれています。あなたは200種類に及ぶすべてのタグをご存知ですか?
    管理者が新しいブラウザが開発されるたびに、すべてのタグを調べ、登録する事など不可能です。
    その度に、ダウンロード先に行きカスタマイズをし直しますか?  無意味です。

    まだ有りますが、このくらいにして次に進みましょう。

  2. 発想の転換
    それではどうすればタグを除去できるのでしょう?
    除去しようと考えるから駄目なのです。除去しません。有効なタグだけを生かしてやるのです。
    一度すべてのタグを無効にし、許可するタグだけを復活させるのです。
    この方法なら、いくら新しいタグが追加されたブラウザでも問題ありません。

    $value =~ s/</&lt;/g;
    $value =~ s/>/&gt;/g;
    このコードは、タグの始まりと終わりを示す「<」と、「>」を「&lt;」と、「&gt;」 という文字列に変換し、タグを無効にしています。
    (当サイトの掲示板は、すでにこのコードで無効になっています。)
    これで、フォームに入力されたタグはすべて無効で登録された訳です。
    これを、表示する時に許可されたタグだけを復活させます。

    <font size=5 color=#FFFF00>これは黄色</font>
    この様なタグを含む文字列が入力されたとします。
    掲示板はタグを無効にしますので、
    &lt;font size=5 color=#FFFF00&gtこれは黄色&lt;/font&:gt;
    と記録される訳ですから、perlのマッチ演算子を使って書式にマッチするかを調べ、 マッチすれば無効にした「<」と、 「>」を復活させてやればいいのです。

    s/(\&lt;(font.*)\&gt;(.*)\&lt;\/font\&gt;)/<$2>$3<\/font>/i;

    このコードは、<fontで始まり、>で閉じられ、いくつかの実際に表示する文字列が有り、
    <\/font>の綴じタグも忘れずに入力されている場合にだけ
    <font .*>?????????</font>に戻してやりなさいというコードです。
    大文字小文字、どちらでも受け付けるよう最後に「i」が付けられています。

    これでは十分ではありませんね。
    そうです、このコードなら、本文中のタグ1つしか変換出来ません。
    いくつ有っても変換できるようループにすると、

    1 while s/(.*)(\&lt;(font[\s\w\=\#\"\']+)\&gt;(.*)\&lt;\/font\&gt;)/$1<$3>$4<\/font>/i;

    と、なります。
    これと同じ要領で、許可するタグを登録するのです。
    イメージタグのように綴じタグを必要としないタグも有りますので、完成品をご覧ください。

    【完成品】
    sub tag_change {
        local($_) = $_[0];
        1 while s/(.*)(&lt;(img([!-:A-~\s\=]+))&gt;)/$1<img$4>/i;
        1 while s/(.*)(&lt;(font[\s\w\=\#\"\']+)\&gt;(.*)\&lt;\/font\&gt;)/$1<$3>$4<\/font>/i;
        1 while s/(.*)(&lt;(b)&gt;(.*)<\/b&gt;)/$1<b>$4<\/b>/i;
        1 while s/(.*)(&lt;(i)&gt;(.*)<\/i&gt;)/$1<i>$4<\/i>/i;
        $_;
    }
    これなら、閉じ忘れられたタグがあっても、最新のブラウザでタグが追加されても心配有りませんね。 サンプルでは、<font>フォントタグ、<img>イメージタグ、<b>ボールドタグ、<i>イタリックタグに限定しています。

  3. 使い方
    使い方は簡単です。上記の完成品をあなたのスクリプトの最後に追加します。
    (全角スペースは半角に変えてね。)
    変換したい文字列の格納されている変数を表示する前に、

    $comment = &tag_change($comment);

    のように、呼び出して変換すればいいだけです。
    tag_change()関数は、変換前の文字列を受け取り、変換後の文字列を返します。

    落書き帳のように、返信が付いてくる掲示板では、
    $com = &tag_change($com);
    という変数も使われています。

    $comment =~ s/\r/<br>/g; や、
    $com =~ s/\r/<br>/g; を検索してその下に追加して下さい。

    本来はこのように、ファイルにはタグ無効で記録し、アクセスされた時に変換するのがベストですが、
    今回のバージョンは、速度的に問題ですので、投稿された時に一度だけ変換して保存する方法にして下さい。

    記事を書き込むサブルーチン regist の最初で変換ルーチンを呼び出します。

    sub regist {
        $FORM{'comment'} = &tag_change($FORM{'comment'});

    と、なります。最近のスクリプトはフォームの連想配列に $QUERY を使用していますので、

    sub regist {
        $QUERY{'comment'} = &tag_change($QUERY{'comment'});

    にします。

Copyright 2004 Terra. All rights reserved. No reproduction or republication without written