タグの閉じ忘れ防止の方法は?

[上に] [前に] [次に]
joe 1997/11/14(金) 23:29:57
現在、タグの使用を許可したBBSを置いてます。
スクリプトの出元はWeb裏技です。

タグを許可したことにより、タグの閉じ忘れ等のいたずらが増えてしまいました。
このスクリプトのタグ制限の仕方は、タグを許可し、そして制限するタグを記述する。
と言う感じですよね。
そこで、これを逆に、許可するタグだけを記述すると言う風には出来ないのでしょうか?
また、閉じ忘れ防止として、なにか良い方法は御座いませんでしょうか?

自力で頑張ってみたのですが、サッパリわかりませんでした。(^_^;)

どのようなスクリプトにすればいいのでしょうか?
どうぞ、よろしくおねがいします。

joe [E-Mail] 1997/11/14(金) 23:31:53
すみません。追記です。

スクリプトは、Web裏技のminibbs7.5です。

よろしくお願いします。

joe [E-Mail] 1997/11/14(金) 23:32:40
すみません。追記です。

スクリプトは、Web裏技のminibbs7.5です。

よろしくお願いします。

とほほ 1997/11/15(土) 03:23:36
許可するタグだけを・・・というのは、CGIスクリプトの改造で可能です。
ただし、perlなどに関する知識がちょいとばかり必要です。(^_^;)

あと、閉じ忘れに対処するために私は、個々の発言を
<TABLE><TR><TD>〜</TD></TR></TABLE>で囲み、さらに<HR>を追記し、
発言内の閉じ忘れが他の発言に極力影響を及ぼさないようにしています。
あと、入力した発言を一度プレビューモードで確認してから、[書き込み]
なんてできると、ミスは減るんでしょうね。

miyasiro [E-Mail] 1997/11/15(土) 23:36:00
うちも minibbs.cig V7.5 なので、ソースを見てみました。
許可したタグ以外のタグを書き込んだ場合にエラーにするには、
スクリプトの最初の方で %tags を例えば下記のように設定しておき、
--- new minibbs.cgi ---
# ↓許可するタグ(必ず小文字で書く)を設定する(値は1)
%tags = ( 'font', 1, 'br', 1, 'hr', 1, 'p', 1 );
-----------------------
下記の部分を、
--- old minibbs.cgi ---
if ($tag) { # 掲示板に書き込まれたくないタグを設定する…
    if ($value =~ /<table(.|\n)*>/i) { &error(tag); }
    if ($value =~ /<meta(.|\n)*>/i) { &error(tag); }
          :
          :
}
-----------------------
下記のように書き換えるというのではいかがでしょう?
--- new minibbs.cgi ---
if ($tag) { # 許可したタグ以外をエラーにする
    while ( $value =~ /<([A-Za-z!\-]+)/g ) {
        ( $elem = $1 ) =~ tr/A-Z/a-z/; # 小文字に統一
        if ( ! $tags{ $elem } ) { &error( 'tag' ); }
    }
}
--------------------
 でも、タグは一切許可しない方が面倒がないと思いますが…

joe 1997/11/15(土) 23:43:16
こんにちわ。joeです。

早速、レスをつけて頂き、ありがとう御座います。
閉じ忘れに対するタグ閉じは、minibbs.cgiが吐き出すソースを見たりして、
いろいろ発言する際に付け足したりしています。

>許可するタグだけを・・・というのは、CGIスクリプトの改造で可能です。
>ただし、perlなどに関する知識がちょいとばかり必要です。(^_^;)

そうですよね。(^^;
そこで、どういった所から勉強すればいいでしょうか?
出来ることなら、そのソースを教えて頂ければ幸いなんですが、
そうも行きませんよね。(^^;;
いろいろこちらからのリンクも辿ったりしてますが、
なかなか難しいもんですね。(^-^;)
分かりやすい本とか、そう言うのってご存知でしょうか?
一切が独学の為、一度躓くと、そのままコケてしまいそうです。(苦笑)

わがまま言って、申し訳ないのですが、よろしくお願いいたします。

joe 1997/11/15(土) 23:49:57
>miyasiroさん

ありがとうございます。
そうですね、タグは使わない様にするのが一番の解決方法かも。(苦笑)
うちのも、始めからそうしていれば、それで済んだのかもしれません。
今では、タグが使えるのでみんなが来てくれている様なもんです。(^^;;

今、教えていただいたのをそのまま頂いて、早速やってみようと思います。
なにぶん、cgiを書く程の知識がないもので。。。
これからも、cgi等いろいろと勉強いて行こうと思っています。

本当にありがとうございました。「感謝!」

miyasiro 1997/11/16(日) 18:24:26
 あっ、カットアンドペーストで使っても基本的には問題ないとは思いますが、
上のサンプルは行頭のタブやスペースが消えてしまってるので、{ と } の
対応等には注意して下さい。
 それから、<!-- で始まるコメントタグに関しては、手抜きしてます。
つまり、%tags に ('!--', 1 ) を追加してコメントを許可しても
<!-- の直後から間を置かずに半角英字でコメントを書くと
許可されないタグとしてエラーでハネられてしまいます(苦笑)。

joe 1997/11/17(月) 00:33:39
ひとつ解決しました。(^-^)
ありがとうございます。

それと、この場合ですと閉じ忘れの回避はどうすればいいのでしょうか?
リンクの場合でも、最後に</a>を忘れると全部に適応されちゃいますよね。
これは、また別なんでしょうか?(^-^;)

最後になってしまいましたが、タグの逆制限は、カンペキに動いてます。

miyasiro 1997/11/17(月) 02:59:41
 閉じタグを完全にチェックすることは実質的に不可能だと思います
(ちゃんとやろうとすると、HTML の構文解析になってしまう)。
 ただ、先の例で許可したタグが存在した場合に、その後ろに閉じタグが
あるかどうかくらいはチェックできないことはありません。
 たとえば、%tags の設定を下のように変えます。
--- new minibbs.cgi ---
# ↓許可するタグ(必ず小文字で書く)とその閉じタグの組を列挙する
#  ただし、閉じタグがない場合には、ダミーの '-' をセットする
%tags = ( 'a', '</a>', 'font', '</font>', 'br', '-', 'hr', '-' );
-----------------------
 また、本体も下のようにします。(ただし、行頭にはインデントのために
全角空白を入れてるのでコピーする場合は半角空白かタブに置換してください)
--- new minibbs.cgi ---
if ($tag) { # 許可したタグ以外をエラーにする
  $str = $value;
  while ( $str =~ /<([A-Za-z!\-]+)(.*)$/ ) {
    ( $elem = $1 ) =~ tr/A-Z/a-z/;
    $str = $2;
    if ( $tags{ $elem } ) { # 許可したタグがあった場合
      if ( $tags{ $elem } ne '-' && $str !~ /$tags{ $elem }/i ) {
        &error( 'tag' ); # 閉じタグがなかった場合
      }
    }
    else { &error( 'tag' ); } # 許可しないタグがあった場合
  }
}
--------------------

 という訳で、行きがかり上、ちょっと書いてみたんですが、
これはかなりヒドイですね(苦笑)。
 このチェックを通ったからといって、閉じタグの間違いがないとは
全く保証されません。また、例えば </FONT  > などのように > の前に
空白がある閉じタグがあってもエラーにしてしまいます。
 そんな訳で、あまりお勧めはしませんが…

joe 1997/11/18(火) 06:08:45
[[解決]]
>miyasiroさん

幾度となく、お世話かけてしまってすみませんです。
</font >と言う、スペースの入ったタグもあるんですか!(@@;
いやはや、全く存じませんでした。(^^;;
まだまだ勉強不足なのですね。(苦笑)

しかし、お陰様でようやく思っていたように出来上がりました。
わがままの連発で、申し訳ない限りです。(^_^;)
これからも、自分自身スキルアップに専念しようと思います。
教えて君で終らない為にも。。。(^^;;

ほんとうにありがとうございました。

miyasiro 1997/11/18(火) 21:11:49
></font >と言う、スペースの入ったタグもあるんですか!(@@;

 いや、タグとして正しいかどうかは別にして、</font の後にゴミが
あったとしてもブラウザは許容するだろうと思って試してみたら、
うちでは有効だったというだけのことです。
 あと、上のスクリプトの問題は、例えば複数の <a> タグに対して
</a> の閉じタグは1個でも済むとか、悪意でなら <a href="</a>">
などとすることにより誤魔化すこともできるというのがあります。

>これからも、自分自身スキルアップに専念しようと思います。
>教えて君で終らない為にも。。。(^^;;

 perl の本というと「Perlプログラミング」(ソフトバンク)が原典って
ことになってますが、入門用には「初めてのPerl」(ソフトバンク)がよく
紹介されているようですね(こっちは読んでませんが…)。
 ガンバって下さい。

joe 1997/11/19(水) 02:24:21
>miyasiroさん

こんばんわ。
ちょうど今日、その「初めてのPerl」と言うのを買ってました。(笑)
ナイスな選択だったみたいで、よかったです。(^^;
Perlプログラミングと言うのも買って来ようと思います。
しかし、一冊あたりの値段にビックリしました。
今日、他の雑誌とかと合わせて9,000円程使ってしまいました。(笑)
これで後には引き返せないと、自分にプレッシャーかけれそうです。(^^;

いろいろ努力してみます。
なにからなにまで、ご面倒おかけしました。

Yosh [E-Mail] [HomePage] 1998/01/12(月) 00:24:33
とりあえず、なにやら興味深そうな内容なので投稿します。

自動で閉じタグを生成するのは当チャットでやっております。上記のリンクがチャットリンク先です。
今の所、当チャットで閉じ忘れたタグに関してのバグは『ほぼ』ありません。お試し下さい。

まず、私の所ではCGIにPerlを使用しております。
そして、まずすべきは、<>で囲まれたタグを正規表現を用い探索する。その探索をすると下記の変数にそれぞれの
結果が入る。
『$`』正規表現によって探索された以前の文字列が入る
『$&』正規表現によって探索された文字列が入る
『$'』正規表現によって探索された以後の文字列が入る
※例として、『あああ<BLINK>ええええ</BLINK>おおお』を探索すると
『$`』=あああ
『$&』=<BLINK>
『$'』=ええええ</BLINK>おおお
が入ります。この時注意すべきは、初めて検索された文字がそれぞれに入ると
いう事です。あとは、その探索したタグに閉じるタグが存在するかチェック(<FONT>や<B>は閉じタグがあって、<IMG>は閉じタグがないなど)
し、それ相応の閉じタグと文字列に挿入するって所です。
あとは自力でやってみて下さい!

とほほ 1998/01/12(月) 02:24:14
あと、タグの閉じ忘れ以外に、ダブルクォーテーション( " )の閉じ忘れも
あるので、泣かされものです。

miyasiro 1998/01/12(月) 03:48:25
> 閉じタグを完全にチェックすることは実質的に不可能だと思います
と書きましたが、実際にやってらっしゃる方がいるんですね。失礼しました(陳謝)。
仰るように、タグを文字列の先頭から順に切り出して行けば可能です。それから、
『$`』や『$'』も、すっかり忘れてました(苦笑)。$'を使えば/....(.*)$/の最後の
カッコなんかも不要ですね。

>し、それ相応の閉じタグと文字列に挿入するって所です。
げっ、閉じタグの検査だけでなく、挿入もやってらっしゃるんですか?
う〜ん、私はそこまでの根性はなさそうです。

ダブルクォーテーションも厄介そうですね。

Yosh [E-Mail] [HomePage] 1998/01/12(月) 23:58:39
どもです。まさか投稿されてからかなり年月がたってたんで、リプライなんてないと思ってました。

>あと、タグの閉じ忘れ以外に、ダブルクォーテーション( " )の閉じ忘れも
一応、各タグで用いられるダブルクォーテーションは指定した場合、認識しないようにしてます。
まぁ、HTML文法からすれば違法なんですが、これを考慮するとこれまたソースが膨大になりますので、諦めました(というより面倒)

>げっ、閉じタグの検査だけでなく、挿入もやってらっしゃるんですか?
そですね。やり方としては、閉じタグのあるタグをFIFO形式で配列化しておき、閉じタグが見つかった所から順に配列をシフトしてます。
それで、サーチされた閉じタグとその配列の閉じタグがアンマッチとなった場合に、それ相応の閉じタグを挿入してます。
つまり、、、、
『あああ<BLINK><FONT SIZE=4>いいい</BLINK>』の場合、
閉じタグ配列に("</BLINK>","</FONT>")という配列を作っておきます。</BLINK>が見つかった所で、本来</FONT>とアンマッチな為、ここで</BLINK>の前に</FONT>を挿入します。
こんな所ですねぇ。。。。

P.S:チャット開発にあたり、とほほさんの所で、JavaScript勉強させて頂きました!有り難うございます!成果はバッチリです!

miyasiro 1998/01/13(火) 00:50:17
>それで、サーチされた閉じタグとその配列の閉じタグがアンマッチとなった場合に、
>それ相応の閉じタグを挿入してます。
すいません、そうですよね。
あの後、私も気がついて下のスクリプトを作ってみました。
閉じタグは、配列の代わりに再帰を使ってチェックしますが、
基本的には同じことですよね。

>そですね。やり方としては、閉じタグのあるタグをFIFO形式で配列化しておき、
あれ、FILO形式では?

# タグ処理のサンプルスクリプト(行頭にタブの代わりに全角空白を使ってます)
# 以下の処理を省略してるので、実用には使えません。
# ◎ コメントタグの処理は省略してます。
# ◎ < と > の対応は正確であると仮定してます。
# ◎ "" 内に < や > はないものと仮定してます。
# ◎ " と " の対応も無視してます。
$value = 'a<I>b<A HREF="a.html">c<B>d</B><BR>e</I>f<B>g</B>h'; # 処理する文字列例
$Debug = 1;
%tags = ('A', '</A>', 'I', '</I>', 'B', '</B>', 'BR', '-');
print "開始 :$value\n";
$value = &check_tag( $value );
print "結果 :$value\n";
sub check_tag {
  local( $str,   $mstr ) = @_;
  do {
    while ( $str =~ m|^([^<]*)(</\w+>)| ) { # 無効な閉じタグの削除
      $mstr .= $1; $str = $';
      print "閉じタグ削除 : $2 :$str\n" if $Debug;
    }
    &find_tag();
  } while ( $str =~ m|^[^<]*</\w| );
  $mstr .= $str;
}
sub find_tag {
  while ( $str =~ m/^[^<]*<(\w+)[^>]*>/ ) { # 前に閉じタグがあってはならない
    $mstr .= $&; $str = $';
    ($elem = $1) =~ tr/a-z/A-Z/;
    if ( $tags{ $elem } ) { # 許可タグ
      if ( $tags{ $elem } ne '-' ) { # 開きタグ発見
        print "開きタグ発見 : <$elem> :$str\n" if $Debug;
        &find_closure( $tags{ $elem } );
      } # これ以外は単独タグ
      else { print "単独タグ発見 : <$elem> :$str\n" if $Debug; }
    }
    else { &error( "<$elem>" ); }
  }
}
sub find_closure {
  local( $closure,   $elem ) = @_;
  &find_tag() if $str =~ m|^[^<]*<[^/]|; # 入れ子の開きタグは再帰処理
  if ( $str =~ m|</\w+>|) { # 閉じタグの処理
    ($elem = $&) =~ tr/a-z/A-Z/;
    if ( $elem eq $closure ) {# 閉じタグ発見
      $mstr .= $` . $&; $str = $';
      print "閉じタグ発見 : $closure :$str\n" if $Debug;
    }
    else { # 閉じタグ追加
      $mstr .= $` . $closure; $str = $& . $';
      print "閉じタグ追加 : $closure :$str\n" if $Debug;
    }
  }
  else { # 末尾に閉じタグ追加
    $mstr .= $str . $closure; $str = '';
    print "閉じタグ追加 : $closure :$str\n" if $Debug;
  }
}
sub error { print "不許可タグ: $_[0]\n"; exit; }

Yosh [E-Mail] [HomePage] 1998/01/13(火) 23:28:41
>あれ、FILO形式では?

う〜ん、LIFOは聞いた事がありますが、FILOは聞いた事ありませんねぇ。
しかしよく考えると、同じ事だったりもしますが、、、、(笑)。結局FIFOとLILOも同じ事かな

そですね。LIFO(こっちを私は使います)ですね。配列から、popして配列をかじっていくやり方です。

ちなみにうちのチャットでは、以下のようにはなりません。
『aaa<BLINK><FONT SIZE=2>bbb</BLINK>ccc</FONT>』を
『aaa<BLINK><FONT SIZE=2>bbbccc</BLINK></FONT>』と意図的に行う事は出来ません。
結局『aaa<BLINK><FONT SIZE=2>bbb</FONT></BLINK>ccc</FONT>』となり</FONT>は余分になります。
ま、このくらいええでしょ。

miyasiro 1998/01/14(水) 00:21:33
>う〜ん、LIFOは聞いた事がありますが、FILOは聞いた事ありませんねぇ。
あちゃっ!
すいません、LIFOの間違いです。「最初に入れたものを最後に出す」より
「最後に入れたものを最初に出す」の方が分かりやすいですよね。

>『aaa<BLINK><FONT SIZE=2>bbbccc</BLINK></FONT>』と意図的に行う事は出来ません。
閉じタグの順序を直せないのは、上のサンプルでも同じです。
 開始 :aaa<BLINK><FONT SIZE=2>bbb</BLINK>ccc</FONT>
 開きタグ発見 : <BLINK> :<FONT SIZE=2>bbb</BLINK>ccc</FONT>
 開きタグ発見 : <FONT> :bbb</BLINK>ccc</FONT>
 閉じタグ追加 : </FONT> :</BLINK>ccc</FONT>
 閉じタグ発見 : </BLINK> :ccc</FONT>
 閉じタグ削除 : </FONT> :
 結果 :aaa<BLINK><FONT SIZE=2>bbb</FONT></BLINK>ccc
ということで、</BLINK>を見つけた段階で</FONT>を追加してしまいます。

あと、上のサンプルで問題なのは、<P>タグのように閉じタグ</P>があったり
なかったりするタグはうまく処理できません。
それから、<TABLE>タグ内の<TD>タグなどのように入れ子にならないタグも、
閉じタグをちゃんと挿入できません。例えば「<TR><TD>a<TD>b</TD></TR>」のように
最初の<TD>の</TD>を忘れた場合、</TR>の直前に</TD>を付加してしまいます。

ぎゃぎゅぎょ 1998/01/14(水) 21:38:22
あとは、コメント <!--  -->や、<XMP>や<PLAINTEXT>の扱いなどが課題でしょうか。
とほほさんの、<TABLE><TR><TD>〜</TD></TR></TABLE> で囲んじゃうってのは楽でいいですね。
今やってみたところ、<FONT SIZE=7 COLOR=red> や <B> の閉じ忘れは、次の発言に影響をおよぼしませんでした。
HTML文法的には問題があるのでしょうけれども・・・・・

miyasiro 1998/01/15(木) 00:32:31
なるほど、<XMP>や<PLAINTEXT>なんてのもありました。
しかし、<XMP>とかを閉じ忘れた場合、どこに閉じタグを挿入したらいいのか
判断できないですね。
しかも、試しに<XMP>を閉じずに書き加えてみると、めちゃくちゃ強力だ!
これは使用禁止ですね!(^^;

Yosh [E-Mail] [HomePage] 1998/01/15(木) 01:21:57
なにやら、私の1発言がこんなに波紋を呼ぶとは、、、、

[上に] [前に] [次に]