challenge 一部のHTMLタグを通すフィルタ

ユーザが入力した文字列から、一部のタグだけを許可して他をエスケープするコードを書いてください。要件は次のようになります。
  • 通すタグはAとBRとSTRONGのみ。大文字小文字は区別しない。
  • それ以外のタグとして意味を持ちうる文字列は<を&lt;に変換することで無効化する(削除するのではない。>は変換してもしなくてもよい)
  • Aタグのhrefとname以外の属性は削除する。BRやSTRONGの属性はすべて削除する。

このお題はperezvonさんの提案を元にしています。ありがとうございました。 ただ、いきなりだと難しいかと思ったので、肝の部分以外を先に出題しました。このお題は続編で徐々に難しくなっていきます。

追記:属性に<や>が含まれてしまうケースに漏れのある解答が多いようなのでテストケースを追加します。
これは「この出力なら十分」という意味です。この出力の通りでなければいけないという意味ではありません。

<script foo="<script>alert('bar')</script>">alert('foo')</script>
&lt;script foo="&lt;script&gt;alert('bar')&lt;/script&gt;"&gt;alert('foo')&lt;/script&gt;


<script foo="<a href='link'>link</a>">alert('foo')</script>
&lt;script foo="&lt;a href='link'&gt;link&lt;/a&gt;"&gt;alert('foo')&lt;/script&gt;

<a href='www.g>oogle.com'>link</a>

<a href="./www.g%3Eoogle.com">link</a>

Posted feedbacks - Scheme

Gauche で書いてみました。まず、 HTML を HtmlPrag を使って SXML 形式に変換し、その上で属性のフィルタリングをします。タグの < や > を &lt;、 &gt; に変換するのは正規表現を使っています。ひとつのタグが複数行に分けて書かれている場合には対応していません。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(load "htmlprag")

(use util.list)
(use sxml.serializer)
(use sxml.sxpath)
(use sxml.tools)
(use sxml.tree-trans)

(define (filter-html shtml)
  (pre-post-order shtml
    `((*default* . ,(lambda c c))
      (*text* . ,(lambda (_ c) c))
      (br . ,(lambda br
               (sxml:change-attrlist! br '())
               br))
      (strong . ,(lambda strong
                   (sxml:change-attrlist! strong '())
                   strong))
      (a . ,(lambda a
              (sxml:change-attrlist! a
                                     (cond-list
                                      (((if-car-sxpath "./@href") a) => values)
                                      (((if-car-sxpath "./@name") a) => values)))
              a)))))

(define (main args)
  (display
   (call-with-input-file (cadr args)
     (lambda (iport)
       (regexp-replace-all
        #/<((?!\/?a\b|\/?br\b|\/?strong\b|!--)[^>]*(?!--))>/
        (srl:sxml->xml (filter-html (html->sxml iport)))
        "&lt;\\1&gt;")))))

Index

Feed

Other

Link

Pathtraq

loading...