Edgewall Software

source: branches/0.12-stable/trac/util/tests/html.py

Last change on this file was 12321, checked in by Jun Omae, 10 years ago

0.12.6dev: avoid double escape of warning messages if smtp_from and smtp_replyto in [notification] are empty and added trac.util.html:to_fragment utility (fixed #11369)

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1# -*- coding: utf-8 -*-
2
3import unittest
4from genshi.builder import Element, Fragment, tag
5from genshi.input import HTML
6
7from trac.core import TracError
8from trac.util.html import TracHTMLSanitizer, to_fragment
9from trac.util.translation import gettext, tgettext
10
11
12class TracHTMLSanitizerTestCase(unittest.TestCase):
13 def test_expression(self):
14 html = HTML(r'<div style="top:expression(alert())">XSS</div>')
15 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
16
17 def test_capital_expression(self):
18 html = HTML(r'<div style="top:EXPRESSION(alert())">XSS</div>')
19 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
20
21 def test_expression_with_comments(self):
22 html = HTML(r'<div style="top:exp/**/ression(alert())">XSS</div>')
23 self.assertEqual('<div style="top:exp ression(alert())">XSS</div>',
24 unicode(html | TracHTMLSanitizer()))
25 html = HTML(r'<div style="top:exp//**/**/ression(alert())">XSS</div>')
26 self.assertEqual(
27 '<div style="top:exp/ **/ression(alert())">XSS</div>',
28 unicode(html | TracHTMLSanitizer()))
29 html = HTML(r'<div style="top:ex/*p*/ression(alert())">XSS</div>')
30 self.assertEqual('<div style="top:ex ression(alert())">XSS</div>',
31 unicode(html | TracHTMLSanitizer()))
32
33 def test_url_with_javascript(self):
34 html = HTML('<div style="background-image:url(javascript:alert())">'
35 'XSS</div>')
36 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
37
38 def test_capital_url_with_javascript(self):
39 html = HTML('<div style="background-image:URL(javascript:alert())">'
40 'XSS</div>')
41 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
42
43 def test_unicode_escapes(self):
44 html = HTML(r'<div style="top:exp\72 ess\000069 on(alert())">'
45 r'XSS</div>')
46 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
47 # escaped backslash
48 html = HTML(r'<div style="top:exp\5c ression(alert())">XSS</div>')
49 self.assertEqual(r'<div style="top:exp\\ression(alert())">XSS</div>',
50 unicode(html | TracHTMLSanitizer()))
51 html = HTML(r'<div style="top:exp\5c 72 ession(alert())">XSS</div>')
52 self.assertEqual(r'<div style="top:exp\\72 ession(alert())">XSS</div>',
53 unicode(html | TracHTMLSanitizer()))
54 # escaped control characters
55 html = HTML(r'<div style="top:exp\000000res\1f sion(alert())">'
56 r'XSS</div>')
57 self.assertEqual('<div style="top:exp res sion(alert())">XSS</div>',
58 unicode(html | TracHTMLSanitizer()))
59
60 def test_backslash_without_hex(self):
61 html = HTML(r'<div style="top:e\xp\ression(alert())">XSS</div>')
62 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
63 html = HTML(r'<div style="top:e\\xp\\ression(alert())">XSS</div>')
64 self.assertEqual(r'<div style="top:e\\xp\\ression(alert())">'
65 'XSS</div>',
66 unicode(html | TracHTMLSanitizer()))
67
68 def test_unsafe_props(self):
69 html = HTML('<div style="POSITION:RELATIVE">XSS</div>')
70 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
71 html = HTML('<div style="position:STATIC">safe</div>')
72 self.assertEqual('<div style="position:STATIC">safe</div>',
73 unicode(html | TracHTMLSanitizer()))
74
75 html = HTML('<div style="behavior:url(test.htc)">XSS</div>')
76 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
77
78 html = HTML('<div style="-ms-behavior:url(test.htc) url(#obj)">'
79 'XSS</div>')
80 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
81
82 html = HTML("""<div style="-o-link:'javascript:alert(1)';"""
83 """-o-link-source:current">XSS</div>""")
84 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
85
86 html = HTML("""<div style="-moz-binding:url(xss.xbl)">XSS</div>""")
87 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
88
89 def test_nagative_margin(self):
90 html = HTML('<div style="margin-top:-9999px">XSS</div>')
91 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
92 html = HTML('<div style="margin:0 -9999px">XSS</div>')
93 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
94
95 def test_css_hack(self):
96 html = HTML('<div style="*position:static">XSS</div>')
97 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
98
99 html = HTML('<div style="_margin:-10px">XSS</div>')
100 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
101
102 def test_property_name(self):
103 html = HTML('<div style="display:none;border-left-color:red;'
104 'user_defined:1;-moz-user-selct:-moz-all">prop</div>')
105 self.assertEqual('<div style="display:none; border-left-color:red'
106 '">prop</div>',
107 unicode(html | TracHTMLSanitizer()))
108
109 def test_unicode_expression(self):
110 # Fullwidth small letters
111 html = HTML(u'<div style="top:expression(alert())">'
112 u'XSS</div>')
113 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
114 # Fullwidth capital letters
115 html = HTML(u'<div style="top:EXPRESSION(alert())">'
116 u'XSS</div>')
117 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
118 # IPA extensions
119 html = HTML(u'<div style="top:expʀessɪoɴ(alert())">'
120 u'XSS</div>')
121 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
122
123 def test_unicode_url(self):
124 # IPA extensions
125 html = HTML(u'<div style="background-image:uʀʟ(javascript:alert())">'
126 u'XSS</div>')
127 self.assertEqual('<div>XSS</div>', unicode(html | TracHTMLSanitizer()))
128
129
130class ToFragmentTestCase(unittest.TestCase):
131
132 def test_unicode(self):
133 rv = to_fragment('blah')
134 self.assertEqual(Fragment, type(rv))
135 self.assertEqual('blah', unicode(rv))
136
137 def test_fragment(self):
138 rv = to_fragment(tag('blah'))
139 self.assertEqual(Fragment, type(rv))
140 self.assertEqual('blah', unicode(rv))
141
142 def test_element(self):
143 rv = to_fragment(tag.p('blah'))
144 self.assertEqual(Element, type(rv))
145 self.assertEqual('<p>blah</p>', unicode(rv))
146
147 def test_tracerror(self):
148 rv = to_fragment(TracError('blah'))
149 self.assertEqual(Fragment, type(rv))
150 self.assertEqual('blah', unicode(rv))
151
152 def test_tracerror_with_fragment(self):
153 message = tag('Powered by ',
154 tag.a('Trac', href='http://trac.edgewall.org/'))
155 rv = to_fragment(TracError(message))
156 self.assertEqual(Fragment, type(rv))
157 self.assertEqual('Powered by <a href="http://trac.edgewall.org/">Trac'
158 '</a>', unicode(rv))
159
160 def test_tracerror_with_element(self):
161 message = tag.p('Powered by ',
162 tag.a('Trac', href='http://trac.edgewall.org/'))
163 rv = to_fragment(TracError(message))
164 self.assertEqual(Element, type(rv))
165 self.assertEqual('<p>Powered by <a href="http://trac.edgewall.org/">'
166 'Trac</a></p>', unicode(rv))
167
168 def test_error(self):
169 rv = to_fragment(ValueError('invalid literal for int(): blah'))
170 self.assertEqual(Fragment, type(rv))
171 self.assertEqual('invalid literal for int(): blah', unicode(rv))
172
173 def test_gettext(self):
174 rv = to_fragment(gettext('%(size)s bytes', size=0))
175 self.assertEqual(Fragment, type(rv))
176 self.assertEqual('0 bytes', unicode(rv))
177
178 def test_tgettext(self):
179 rv = to_fragment(tgettext('Back to %(parent)s',
180 parent=tag.a('WikiStart',
181 href='http://localhost/')))
182 self.assertEqual(Fragment, type(rv))
183 self.assertEqual('Back to <a href="http://localhost/">WikiStart</a>',
184 unicode(rv))
185
186 def test_tracerror_with_gettext(self):
187 e = TracError(gettext('%(size)s bytes', size=0))
188 rv = to_fragment(e)
189 self.assertEqual(Fragment, type(rv))
190 self.assertEqual('0 bytes', unicode(rv))
191
192 def test_tracerror_with_tgettext(self):
193 e = TracError(tgettext('Back to %(parent)s',
194 parent=tag.a('WikiStart',
195 href='http://localhost/')))
196 rv = to_fragment(e)
197 self.assertEqual(Fragment, type(rv))
198 self.assertEqual('Back to <a href="http://localhost/">WikiStart</a>',
199 unicode(rv))
200
201
202def suite():
203 suite = unittest.TestSuite()
204 suite.addTest(unittest.makeSuite(TracHTMLSanitizerTestCase, 'test'))
205 suite.addTest(unittest.makeSuite(ToFragmentTestCase, 'test'))
206 return suite
207
208if __name__ == '__main__':
209 unittest.main(defaultTest='suite')
Note: See TracBrowser for help on using the repository browser.