Comment detail

一部のHTMLタグを通すフィルタ (Nested Flatten)

This comment is reply for 2720 ocean: htmlって曖昧だから、あまり自信なし。...(一部のHTMLタグを通すフィルタ). Go to thread root.

属性値の中の">"が考慮されていませんね。

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

というようなケースで

<a>oogle.com'>link</a>

となってしまいます。
なるほど、そんな場合があるのか・・・というわけで修正版です。

属性をパースする正規表現が二度出てくるのが美しくないですが・・・このあたりをPythonでうまく処理する方法ってあるのかな。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re

def filter(html):
    def repl(m):
        beg_slash, tag_name, attrs, _, end_slash = m.groups()
        def combine(*names):
            s = "<" + beg_slash + tag_name
            for m in re.finditer(r"""(\w+)\s*=\s*(["']).+?\2""", attrs, re.S):
                if m.group(1).lower() in names:
                    s += " " + m.group(0)
            return s + end_slash + ">"
        if tag_name.lower() == 'a':
            return combine("href", "name")
        elif tag_name.lower() in ('br', 'strong'):
            return combine()
        else:
            return "&lt;" + m.group(0)[1:]
    return re.compile(r"""<(/?)(\w+)((?:\s*\w+\s*=\s*(["']).+?\4)*)\s*(/?)>""", re.S).sub(repl, html)

def main():
    print filter("""<a href='www.google.com'>link</a> <blink>and</blink> <strong onClick='alert("NG")'>click<br/>me!</strong>""")

if __name__ == '__main__':
    main()
oceanさんのコードで確かめたのでここにぶら下げますが、他のポストにも同じ問題があるかもしれません。

入力文字列が次のようなものだとまずいのでは:

  <z foo='<script>alert("Boo")</script>'>
なるほど、タグを無効化した場合、属性に含まれる < を放置すると今度はそちらがタグとみなされるということですか。

というわけで再修正パッチです。でもきっとまだあるな・・・
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
--- a.py.orig	Fri Aug 31 16:20:21 2007
+++ a.py	Fri Aug 31 16:20:35 2007
@@ -14,11 +14,12 @@
         elif tag_name.lower() in ('br', 'strong'):
             return combine()
         else:
-            return "&lt;" + m.group(0)[1:]
+            return m.group(0).replace("<", "&lt;")
     return re.compile(r"""<(/?)(\w+)((?:\s*\w+\s*=\s*(["']).+?\4)*)\s*(/?)>""", re.S).sub(repl, html)
 
 def main():
     print filter("""<a href='www.google.com'>link</a> <blink>and</blink> <strong onClick='alert("NG")'>click<br/>me!</strong>""")
+    print filter(""" <z foo='<script>alert("Boo")</script>'>""")
 
 if __name__ == '__main__':
     main()

Index

Feed

Other

Link

Pathtraq

loading...