comparison genshi/filters/tests/html.py @ 902:09cc3627654c experimental-inline

Sync `experimental/inline` branch with [source:trunk@1126].
author cmlenz
date Fri, 23 Apr 2010 21:08:26 +0000
parents 1837f39efd6f
children
comparison
equal deleted inserted replaced
830:de82830f8816 902:09cc3627654c
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # 2 #
3 # Copyright (C) 2006-2008 Edgewall Software 3 # Copyright (C) 2006-2009 Edgewall Software
4 # All rights reserved. 4 # All rights reserved.
5 # 5 #
6 # This software is licensed as described in the file COPYING, which 6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms 7 # you should have received as part of this distribution. The terms
8 # are also available at http://genshi.edgewall.org/wiki/License. 8 # are also available at http://genshi.edgewall.org/wiki/License.
24 html = HTML("""<form><p> 24 html = HTML("""<form><p>
25 <input type="text" name="foo" /> 25 <input type="text" name="foo" />
26 </p></form>""") | HTMLFormFiller() 26 </p></form>""") | HTMLFormFiller()
27 self.assertEquals("""<form><p> 27 self.assertEquals("""<form><p>
28 <input type="text" name="foo"/> 28 <input type="text" name="foo"/>
29 </p></form>""", unicode(html)) 29 </p></form>""", html.render())
30 30
31 def test_fill_input_text_single_value(self): 31 def test_fill_input_text_single_value(self):
32 html = HTML("""<form><p> 32 html = HTML("""<form><p>
33 <input type="text" name="foo" /> 33 <input type="text" name="foo" />
34 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) 34 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
35 self.assertEquals("""<form><p> 35 self.assertEquals("""<form><p>
36 <input type="text" name="foo" value="bar"/> 36 <input type="text" name="foo" value="bar"/>
37 </p></form>""", unicode(html)) 37 </p></form>""", html.render())
38 38
39 def test_fill_input_text_multi_value(self): 39 def test_fill_input_text_multi_value(self):
40 html = HTML("""<form><p> 40 html = HTML("""<form><p>
41 <input type="text" name="foo" /> 41 <input type="text" name="foo" />
42 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) 42 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
43 self.assertEquals("""<form><p> 43 self.assertEquals("""<form><p>
44 <input type="text" name="foo" value="bar"/> 44 <input type="text" name="foo" value="bar"/>
45 </p></form>""", unicode(html)) 45 </p></form>""", html.render())
46 46
47 def test_fill_input_hidden_no_value(self): 47 def test_fill_input_hidden_no_value(self):
48 html = HTML("""<form><p> 48 html = HTML("""<form><p>
49 <input type="hidden" name="foo" /> 49 <input type="hidden" name="foo" />
50 </p></form>""") | HTMLFormFiller() 50 </p></form>""") | HTMLFormFiller()
51 self.assertEquals("""<form><p> 51 self.assertEquals("""<form><p>
52 <input type="hidden" name="foo"/> 52 <input type="hidden" name="foo"/>
53 </p></form>""", unicode(html)) 53 </p></form>""", html.render())
54 54
55 def test_fill_input_hidden_single_value(self): 55 def test_fill_input_hidden_single_value(self):
56 html = HTML("""<form><p> 56 html = HTML("""<form><p>
57 <input type="hidden" name="foo" /> 57 <input type="hidden" name="foo" />
58 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) 58 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
59 self.assertEquals("""<form><p> 59 self.assertEquals("""<form><p>
60 <input type="hidden" name="foo" value="bar"/> 60 <input type="hidden" name="foo" value="bar"/>
61 </p></form>""", unicode(html)) 61 </p></form>""", html.render())
62 62
63 def test_fill_input_hidden_multi_value(self): 63 def test_fill_input_hidden_multi_value(self):
64 html = HTML("""<form><p> 64 html = HTML("""<form><p>
65 <input type="hidden" name="foo" /> 65 <input type="hidden" name="foo" />
66 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) 66 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
67 self.assertEquals("""<form><p> 67 self.assertEquals("""<form><p>
68 <input type="hidden" name="foo" value="bar"/> 68 <input type="hidden" name="foo" value="bar"/>
69 </p></form>""", unicode(html)) 69 </p></form>""", html.render())
70 70
71 def test_fill_textarea_no_value(self): 71 def test_fill_textarea_no_value(self):
72 html = HTML("""<form><p> 72 html = HTML("""<form><p>
73 <textarea name="foo"></textarea> 73 <textarea name="foo"></textarea>
74 </p></form>""") | HTMLFormFiller() 74 </p></form>""") | HTMLFormFiller()
75 self.assertEquals("""<form><p> 75 self.assertEquals("""<form><p>
76 <textarea name="foo"/> 76 <textarea name="foo"/>
77 </p></form>""", unicode(html)) 77 </p></form>""", html.render())
78 78
79 def test_fill_textarea_single_value(self): 79 def test_fill_textarea_single_value(self):
80 html = HTML("""<form><p> 80 html = HTML("""<form><p>
81 <textarea name="foo"></textarea> 81 <textarea name="foo"></textarea>
82 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'}) 82 </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
83 self.assertEquals("""<form><p> 83 self.assertEquals("""<form><p>
84 <textarea name="foo">bar</textarea> 84 <textarea name="foo">bar</textarea>
85 </p></form>""", unicode(html)) 85 </p></form>""", html.render())
86 86
87 def test_fill_textarea_multi_value(self): 87 def test_fill_textarea_multi_value(self):
88 html = HTML("""<form><p> 88 html = HTML("""<form><p>
89 <textarea name="foo"></textarea> 89 <textarea name="foo"></textarea>
90 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']}) 90 </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
91 self.assertEquals("""<form><p> 91 self.assertEquals("""<form><p>
92 <textarea name="foo">bar</textarea> 92 <textarea name="foo">bar</textarea>
93 </p></form>""", unicode(html)) 93 </p></form>""", html.render())
94 94
95 def test_fill_input_checkbox_no_value(self): 95 def test_fill_input_checkbox_no_value(self):
96 html = HTML("""<form><p> 96 html = HTML("""<form><p>
97 <input type="checkbox" name="foo" /> 97 <input type="checkbox" name="foo" />
98 </p></form>""") | HTMLFormFiller() 98 </p></form>""") | HTMLFormFiller()
99 self.assertEquals("""<form><p> 99 self.assertEquals("""<form><p>
100 <input type="checkbox" name="foo"/> 100 <input type="checkbox" name="foo"/>
101 </p></form>""", unicode(html)) 101 </p></form>""", html.render())
102 102
103 def test_fill_input_checkbox_single_value_auto(self): 103 def test_fill_input_checkbox_single_value_auto(self):
104 html = HTML("""<form><p> 104 html = HTML("""<form><p>
105 <input type="checkbox" name="foo" /> 105 <input type="checkbox" name="foo" />
106 </p></form>""") 106 </p></form>""")
107 self.assertEquals("""<form><p> 107 self.assertEquals("""<form><p>
108 <input type="checkbox" name="foo"/> 108 <input type="checkbox" name="foo"/>
109 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ''}))) 109 </p></form>""", (html | HTMLFormFiller(data={'foo': ''})).render())
110 self.assertEquals("""<form><p> 110 self.assertEquals("""<form><p>
111 <input type="checkbox" name="foo" checked="checked"/> 111 <input type="checkbox" name="foo" checked="checked"/>
112 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': 'on'}))) 112 </p></form>""", (html | HTMLFormFiller(data={'foo': 'on'})).render())
113 113
114 def test_fill_input_checkbox_single_value_defined(self): 114 def test_fill_input_checkbox_single_value_defined(self):
115 html = HTML("""<form><p> 115 html = HTML("""<form><p>
116 <input type="checkbox" name="foo" value="1" /> 116 <input type="checkbox" name="foo" value="1" />
117 </p></form>""") 117 </p></form>""")
118 self.assertEquals("""<form><p> 118 self.assertEquals("""<form><p>
119 <input type="checkbox" name="foo" value="1" checked="checked"/> 119 <input type="checkbox" name="foo" value="1" checked="checked"/>
120 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'}))) 120 </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render())
121 self.assertEquals("""<form><p> 121 self.assertEquals("""<form><p>
122 <input type="checkbox" name="foo" value="1"/> 122 <input type="checkbox" name="foo" value="1"/>
123 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'}))) 123 </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render())
124 124
125 def test_fill_input_checkbox_multi_value_auto(self): 125 def test_fill_input_checkbox_multi_value_auto(self):
126 html = HTML("""<form><p> 126 html = HTML("""<form><p>
127 <input type="checkbox" name="foo" /> 127 <input type="checkbox" name="foo" />
128 </p></form>""") 128 </p></form>""")
129 self.assertEquals("""<form><p> 129 self.assertEquals("""<form><p>
130 <input type="checkbox" name="foo"/> 130 <input type="checkbox" name="foo"/>
131 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': []}))) 131 </p></form>""", (html | HTMLFormFiller(data={'foo': []})).render())
132 self.assertEquals("""<form><p> 132 self.assertEquals("""<form><p>
133 <input type="checkbox" name="foo" checked="checked"/> 133 <input type="checkbox" name="foo" checked="checked"/>
134 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['on']}))) 134 </p></form>""", (html | HTMLFormFiller(data={'foo': ['on']})).render())
135 135
136 def test_fill_input_checkbox_multi_value_defined(self): 136 def test_fill_input_checkbox_multi_value_defined(self):
137 html = HTML("""<form><p> 137 html = HTML("""<form><p>
138 <input type="checkbox" name="foo" value="1" /> 138 <input type="checkbox" name="foo" value="1" />
139 </p></form>""") 139 </p></form>""")
140 self.assertEquals("""<form><p> 140 self.assertEquals("""<form><p>
141 <input type="checkbox" name="foo" value="1" checked="checked"/> 141 <input type="checkbox" name="foo" value="1" checked="checked"/>
142 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']}))) 142 </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render())
143 self.assertEquals("""<form><p> 143 self.assertEquals("""<form><p>
144 <input type="checkbox" name="foo" value="1"/> 144 <input type="checkbox" name="foo" value="1"/>
145 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']}))) 145 </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render())
146 146
147 def test_fill_input_radio_no_value(self): 147 def test_fill_input_radio_no_value(self):
148 html = HTML("""<form><p> 148 html = HTML("""<form><p>
149 <input type="radio" name="foo" /> 149 <input type="radio" name="foo" />
150 </p></form>""") | HTMLFormFiller() 150 </p></form>""") | HTMLFormFiller()
151 self.assertEquals("""<form><p> 151 self.assertEquals("""<form><p>
152 <input type="radio" name="foo"/> 152 <input type="radio" name="foo"/>
153 </p></form>""", unicode(html)) 153 </p></form>""", html.render())
154 154
155 def test_fill_input_radio_single_value(self): 155 def test_fill_input_radio_single_value(self):
156 html = HTML("""<form><p> 156 html = HTML("""<form><p>
157 <input type="radio" name="foo" value="1" /> 157 <input type="radio" name="foo" value="1" />
158 </p></form>""") 158 </p></form>""")
159 self.assertEquals("""<form><p> 159 self.assertEquals("""<form><p>
160 <input type="radio" name="foo" value="1" checked="checked"/> 160 <input type="radio" name="foo" value="1" checked="checked"/>
161 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'}))) 161 </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render())
162 self.assertEquals("""<form><p> 162 self.assertEquals("""<form><p>
163 <input type="radio" name="foo" value="1"/> 163 <input type="radio" name="foo" value="1"/>
164 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'}))) 164 </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render())
165 165
166 def test_fill_input_radio_multi_value(self): 166 def test_fill_input_radio_multi_value(self):
167 html = HTML("""<form><p> 167 html = HTML("""<form><p>
168 <input type="radio" name="foo" value="1" /> 168 <input type="radio" name="foo" value="1" />
169 </p></form>""") 169 </p></form>""")
170 self.assertEquals("""<form><p> 170 self.assertEquals("""<form><p>
171 <input type="radio" name="foo" value="1" checked="checked"/> 171 <input type="radio" name="foo" value="1" checked="checked"/>
172 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']}))) 172 </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render())
173 self.assertEquals("""<form><p> 173 self.assertEquals("""<form><p>
174 <input type="radio" name="foo" value="1"/> 174 <input type="radio" name="foo" value="1"/>
175 </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']}))) 175 </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render())
176 176
177 def test_fill_select_no_value_auto(self): 177 def test_fill_select_no_value_auto(self):
178 html = HTML("""<form><p> 178 html = HTML("""<form><p>
179 <select name="foo"> 179 <select name="foo">
180 <option>1</option> 180 <option>1</option>
186 <select name="foo"> 186 <select name="foo">
187 <option>1</option> 187 <option>1</option>
188 <option>2</option> 188 <option>2</option>
189 <option>3</option> 189 <option>3</option>
190 </select> 190 </select>
191 </p></form>""", unicode(html)) 191 </p></form>""", html.render())
192 192
193 def test_fill_select_no_value_defined(self): 193 def test_fill_select_no_value_defined(self):
194 html = HTML("""<form><p> 194 html = HTML("""<form><p>
195 <select name="foo"> 195 <select name="foo">
196 <option value="1">1</option> 196 <option value="1">1</option>
202 <select name="foo"> 202 <select name="foo">
203 <option value="1">1</option> 203 <option value="1">1</option>
204 <option value="2">2</option> 204 <option value="2">2</option>
205 <option value="3">3</option> 205 <option value="3">3</option>
206 </select> 206 </select>
207 </p></form>""", unicode(html)) 207 </p></form>""", html.render())
208 208
209 def test_fill_select_single_value_auto(self): 209 def test_fill_select_single_value_auto(self):
210 html = HTML("""<form><p> 210 html = HTML("""<form><p>
211 <select name="foo"> 211 <select name="foo">
212 <option>1</option> 212 <option>1</option>
218 <select name="foo"> 218 <select name="foo">
219 <option selected="selected">1</option> 219 <option selected="selected">1</option>
220 <option>2</option> 220 <option>2</option>
221 <option>3</option> 221 <option>3</option>
222 </select> 222 </select>
223 </p></form>""", unicode(html)) 223 </p></form>""", html.render())
224 224
225 def test_fill_select_single_value_defined(self): 225 def test_fill_select_single_value_defined(self):
226 html = HTML("""<form><p> 226 html = HTML("""<form><p>
227 <select name="foo"> 227 <select name="foo">
228 <option value="1">1</option> 228 <option value="1">1</option>
234 <select name="foo"> 234 <select name="foo">
235 <option value="1" selected="selected">1</option> 235 <option value="1" selected="selected">1</option>
236 <option value="2">2</option> 236 <option value="2">2</option>
237 <option value="3">3</option> 237 <option value="3">3</option>
238 </select> 238 </select>
239 </p></form>""", unicode(html)) 239 </p></form>""", html.render())
240 240
241 def test_fill_select_multi_value_auto(self): 241 def test_fill_select_multi_value_auto(self):
242 html = HTML("""<form><p> 242 html = HTML("""<form><p>
243 <select name="foo" multiple> 243 <select name="foo" multiple>
244 <option>1</option> 244 <option>1</option>
250 <select name="foo" multiple="multiple"> 250 <select name="foo" multiple="multiple">
251 <option selected="selected">1</option> 251 <option selected="selected">1</option>
252 <option>2</option> 252 <option>2</option>
253 <option selected="selected">3</option> 253 <option selected="selected">3</option>
254 </select> 254 </select>
255 </p></form>""", unicode(html)) 255 </p></form>""", html.render())
256 256
257 def test_fill_select_multi_value_defined(self): 257 def test_fill_select_multi_value_defined(self):
258 html = HTML("""<form><p> 258 html = HTML("""<form><p>
259 <select name="foo" multiple> 259 <select name="foo" multiple>
260 <option value="1">1</option> 260 <option value="1">1</option>
266 <select name="foo" multiple="multiple"> 266 <select name="foo" multiple="multiple">
267 <option value="1" selected="selected">1</option> 267 <option value="1" selected="selected">1</option>
268 <option value="2">2</option> 268 <option value="2">2</option>
269 <option value="3" selected="selected">3</option> 269 <option value="3" selected="selected">3</option>
270 </select> 270 </select>
271 </p></form>""", unicode(html)) 271 </p></form>""", html.render())
272 272
273 def test_fill_option_segmented_text(self): 273 def test_fill_option_segmented_text(self):
274 html = MarkupTemplate("""<form> 274 html = MarkupTemplate("""<form>
275 <select name="foo"> 275 <select name="foo">
276 <option value="1">foo $x</option> 276 <option value="1">foo $x</option>
278 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': '1'}) 278 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': '1'})
279 self.assertEquals("""<form> 279 self.assertEquals("""<form>
280 <select name="foo"> 280 <select name="foo">
281 <option value="1" selected="selected">foo 1</option> 281 <option value="1" selected="selected">foo 1</option>
282 </select> 282 </select>
283 </form>""", unicode(html)) 283 </form>""", html.render())
284 284
285 def test_fill_option_segmented_text_no_value(self): 285 def test_fill_option_segmented_text_no_value(self):
286 html = MarkupTemplate("""<form> 286 html = MarkupTemplate("""<form>
287 <select name="foo"> 287 <select name="foo">
288 <option>foo $x bar</option> 288 <option>foo $x bar</option>
290 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': 'foo 1 bar'}) 290 </form>""").generate(x=1) | HTMLFormFiller(data={'foo': 'foo 1 bar'})
291 self.assertEquals("""<form> 291 self.assertEquals("""<form>
292 <select name="foo"> 292 <select name="foo">
293 <option selected="selected">foo 1 bar</option> 293 <option selected="selected">foo 1 bar</option>
294 </select> 294 </select>
295 </form>""", unicode(html)) 295 </form>""", html.render())
296 296
297 def test_fill_option_unicode_value(self): 297 def test_fill_option_unicode_value(self):
298 html = HTML(u"""<form> 298 html = HTML("""<form>
299 <select name="foo"> 299 <select name="foo">
300 <option value="&ouml;">foo</option> 300 <option value="&ouml;">foo</option>
301 </select> 301 </select>
302 </form>""") | HTMLFormFiller(data={'foo': u'ö'}) 302 </form>""") | HTMLFormFiller(data={'foo': u'ö'})
303 self.assertEquals(u"""<form> 303 self.assertEquals(u"""<form>
304 <select name="foo"> 304 <select name="foo">
305 <option value="ö" selected="selected">foo</option> 305 <option value="ö" selected="selected">foo</option>
306 </select> 306 </select>
307 </form>""", unicode(html)) 307 </form>""", html.render(encoding=None))
308
309 def test_fill_input_password_disabled(self):
310 html = HTML("""<form><p>
311 <input type="password" name="pass" />
312 </p></form>""") | HTMLFormFiller(data={'pass': 'bar'})
313 self.assertEquals("""<form><p>
314 <input type="password" name="pass"/>
315 </p></form>""", html.render())
316
317 def test_fill_input_password_enabled(self):
318 html = HTML("""<form><p>
319 <input type="password" name="pass" />
320 </p></form>""") | HTMLFormFiller(data={'pass': '1234'}, passwords=True)
321 self.assertEquals("""<form><p>
322 <input type="password" name="pass" value="1234"/>
323 </p></form>""", html.render())
308 324
309 325
310 class HTMLSanitizerTestCase(unittest.TestCase): 326 class HTMLSanitizerTestCase(unittest.TestCase):
311 327
312 def test_sanitize_unchanged(self): 328 def test_sanitize_unchanged(self):
313 html = HTML('<a href="#">fo<br />o</a>') 329 html = HTML('<a href="#">fo<br />o</a>')
314 self.assertEquals(u'<a href="#">fo<br/>o</a>', 330 self.assertEquals('<a href="#">fo<br/>o</a>',
315 unicode(html | HTMLSanitizer())) 331 (html | HTMLSanitizer()).render())
332 html = HTML('<a href="#with:colon">foo</a>')
333 self.assertEquals('<a href="#with:colon">foo</a>',
334 (html | HTMLSanitizer()).render())
316 335
317 def test_sanitize_escape_text(self): 336 def test_sanitize_escape_text(self):
318 html = HTML('<a href="#">fo&amp;</a>') 337 html = HTML('<a href="#">fo&amp;</a>')
319 self.assertEquals(u'<a href="#">fo&amp;</a>', 338 self.assertEquals('<a href="#">fo&amp;</a>',
320 unicode(html | HTMLSanitizer())) 339 (html | HTMLSanitizer()).render())
321 html = HTML('<a href="#">&lt;foo&gt;</a>') 340 html = HTML('<a href="#">&lt;foo&gt;</a>')
322 self.assertEquals(u'<a href="#">&lt;foo&gt;</a>', 341 self.assertEquals('<a href="#">&lt;foo&gt;</a>',
323 unicode(html | HTMLSanitizer())) 342 (html | HTMLSanitizer()).render())
324 343
325 def test_sanitize_entityref_text(self): 344 def test_sanitize_entityref_text(self):
326 html = HTML('<a href="#">fo&ouml;</a>') 345 html = HTML('<a href="#">fo&ouml;</a>')
327 self.assertEquals(u'<a href="#">foö</a>', 346 self.assertEquals(u'<a href="#">foö</a>',
328 unicode(html | HTMLSanitizer())) 347 (html | HTMLSanitizer()).render(encoding=None))
329 348
330 def test_sanitize_escape_attr(self): 349 def test_sanitize_escape_attr(self):
331 html = HTML('<div title="&lt;foo&gt;"></div>') 350 html = HTML('<div title="&lt;foo&gt;"></div>')
332 self.assertEquals(u'<div title="&lt;foo&gt;"/>', 351 self.assertEquals('<div title="&lt;foo&gt;"/>',
333 unicode(html | HTMLSanitizer())) 352 (html | HTMLSanitizer()).render())
334 353
335 def test_sanitize_close_empty_tag(self): 354 def test_sanitize_close_empty_tag(self):
336 html = HTML('<a href="#">fo<br>o</a>') 355 html = HTML('<a href="#">fo<br>o</a>')
337 self.assertEquals(u'<a href="#">fo<br/>o</a>', 356 self.assertEquals('<a href="#">fo<br/>o</a>',
338 unicode(html | HTMLSanitizer())) 357 (html | HTMLSanitizer()).render())
339 358
340 def test_sanitize_invalid_entity(self): 359 def test_sanitize_invalid_entity(self):
341 html = HTML('&junk;') 360 html = HTML('&junk;')
342 self.assertEquals('&amp;junk;', unicode(html | HTMLSanitizer())) 361 self.assertEquals('&amp;junk;', (html | HTMLSanitizer()).render())
343 362
344 def test_sanitize_remove_script_elem(self): 363 def test_sanitize_remove_script_elem(self):
345 html = HTML('<script>alert("Foo")</script>') 364 html = HTML('<script>alert("Foo")</script>')
346 self.assertEquals(u'', unicode(html | HTMLSanitizer())) 365 self.assertEquals('', (html | HTMLSanitizer()).render())
347 html = HTML('<SCRIPT SRC="http://example.com/"></SCRIPT>') 366 html = HTML('<SCRIPT SRC="http://example.com/"></SCRIPT>')
348 self.assertEquals(u'', unicode(html | HTMLSanitizer())) 367 self.assertEquals('', (html | HTMLSanitizer()).render())
349 self.assertRaises(ParseError, HTML, '<SCR\0IPT>alert("foo")</SCR\0IPT>') 368 self.assertRaises(ParseError, HTML, '<SCR\0IPT>alert("foo")</SCR\0IPT>')
350 self.assertRaises(ParseError, HTML, 369 self.assertRaises(ParseError, HTML,
351 '<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>') 370 '<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>')
352 371
353 def test_sanitize_remove_onclick_attr(self): 372 def test_sanitize_remove_onclick_attr(self):
354 html = HTML('<div onclick=\'alert("foo")\' />') 373 html = HTML('<div onclick=\'alert("foo")\' />')
355 self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer())) 374 self.assertEquals('<div/>', (html | HTMLSanitizer()).render())
375
376 def test_sanitize_remove_input_password(self):
377 html = HTML('<form><input type="password" /></form>')
378 self.assertEquals('<form/>', (html | HTMLSanitizer()).render())
356 379
357 def test_sanitize_remove_comments(self): 380 def test_sanitize_remove_comments(self):
358 html = HTML('''<div><!-- conditional comment crap --></div>''') 381 html = HTML('''<div><!-- conditional comment crap --></div>''')
359 self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer())) 382 self.assertEquals('<div/>', (html | HTMLSanitizer()).render())
360 383
361 def test_sanitize_remove_style_scripts(self): 384 def test_sanitize_remove_style_scripts(self):
362 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style'])) 385 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style']))
363 # Inline style with url() using javascript: scheme 386 # Inline style with url() using javascript: scheme
364 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>') 387 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>')
365 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 388 self.assertEquals('<div/>', (html | sanitizer).render())
366 # Inline style with url() using javascript: scheme, using control char 389 # Inline style with url() using javascript: scheme, using control char
367 html = HTML('<DIV STYLE=\'background: url(&#1;javascript:alert("foo"))\'>') 390 html = HTML('<DIV STYLE=\'background: url(&#1;javascript:alert("foo"))\'>')
368 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 391 self.assertEquals('<div/>', (html | sanitizer).render())
369 # Inline style with url() using javascript: scheme, in quotes 392 # Inline style with url() using javascript: scheme, in quotes
370 html = HTML('<DIV STYLE=\'background: url("javascript:alert(foo)")\'>') 393 html = HTML('<DIV STYLE=\'background: url("javascript:alert(foo)")\'>')
371 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 394 self.assertEquals('<div/>', (html | sanitizer).render())
372 # IE expressions in CSS not allowed 395 # IE expressions in CSS not allowed
373 html = HTML('<DIV STYLE=\'width: expression(alert("foo"));\'>') 396 html = HTML('<DIV STYLE=\'width: expression(alert("foo"));\'>')
374 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 397 self.assertEquals('<div/>', (html | sanitizer).render())
375 html = HTML('<DIV STYLE=\'width: e/**/xpression(alert("foo"));\'>') 398 html = HTML('<DIV STYLE=\'width: e/**/xpression(alert("foo"));\'>')
376 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 399 self.assertEquals('<div/>', (html | sanitizer).render())
377 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"));' 400 html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"));'
378 'color: #fff\'>') 401 'color: #fff\'>')
379 self.assertEquals(u'<div style="color: #fff"/>', 402 self.assertEquals('<div style="color: #fff"/>',
380 unicode(html | sanitizer)) 403 (html | sanitizer).render())
381 # Inline style with url() using javascript: scheme, using unicode 404 # Inline style with url() using javascript: scheme, using unicode
382 # escapes 405 # escapes
383 html = HTML('<DIV STYLE=\'background: \\75rl(javascript:alert("foo"))\'>') 406 html = HTML('<DIV STYLE=\'background: \\75rl(javascript:alert("foo"))\'>')
384 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 407 self.assertEquals('<div/>', (html | sanitizer).render())
385 html = HTML('<DIV STYLE=\'background: \\000075rl(javascript:alert("foo"))\'>') 408 html = HTML('<DIV STYLE=\'background: \\000075rl(javascript:alert("foo"))\'>')
386 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 409 self.assertEquals('<div/>', (html | sanitizer).render())
387 html = HTML('<DIV STYLE=\'background: \\75 rl(javascript:alert("foo"))\'>') 410 html = HTML('<DIV STYLE=\'background: \\75 rl(javascript:alert("foo"))\'>')
388 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 411 self.assertEquals('<div/>', (html | sanitizer).render())
389 html = HTML('<DIV STYLE=\'background: \\000075 rl(javascript:alert("foo"))\'>') 412 html = HTML('<DIV STYLE=\'background: \\000075 rl(javascript:alert("foo"))\'>')
390 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 413 self.assertEquals('<div/>', (html | sanitizer).render())
391 html = HTML('<DIV STYLE=\'background: \\000075\r\nrl(javascript:alert("foo"))\'>') 414 html = HTML('<DIV STYLE=\'background: \\000075\r\nrl(javascript:alert("foo"))\'>')
392 self.assertEquals(u'<div/>', unicode(html | sanitizer)) 415 self.assertEquals('<div/>', (html | sanitizer).render())
416
417 def test_sanitize_remove_style_phishing(self):
418 sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style']))
419 # The position property is not allowed
420 html = HTML('<div style="position:absolute;top:0"></div>')
421 self.assertEquals('<div style="top:0"/>', (html | sanitizer).render())
422 # Normal margins get passed through
423 html = HTML('<div style="margin:10px 20px"></div>')
424 self.assertEquals('<div style="margin:10px 20px"/>',
425 (html | sanitizer).render())
426 # But not negative margins
427 html = HTML('<div style="margin:-1000px 0 0"></div>')
428 self.assertEquals('<div/>', (html | sanitizer).render())
429 html = HTML('<div style="margin-left:-2000px 0 0"></div>')
430 self.assertEquals('<div/>', (html | sanitizer).render())
431 html = HTML('<div style="margin-left:1em 1em 1em -4000px"></div>')
432 self.assertEquals('<div/>', (html | sanitizer).render())
393 433
394 def test_sanitize_remove_src_javascript(self): 434 def test_sanitize_remove_src_javascript(self):
395 html = HTML('<img src=\'javascript:alert("foo")\'>') 435 html = HTML('<img src=\'javascript:alert("foo")\'>')
396 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 436 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
397 # Case-insensitive protocol matching 437 # Case-insensitive protocol matching
398 html = HTML('<IMG SRC=\'JaVaScRiPt:alert("foo")\'>') 438 html = HTML('<IMG SRC=\'JaVaScRiPt:alert("foo")\'>')
399 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 439 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
400 # Grave accents (not parsed) 440 # Grave accents (not parsed)
401 self.assertRaises(ParseError, HTML, 441 self.assertRaises(ParseError, HTML,
402 '<IMG SRC=`javascript:alert("RSnake says, \'foo\'")`>') 442 '<IMG SRC=`javascript:alert("RSnake says, \'foo\'")`>')
403 # Protocol encoded using UTF-8 numeric entities 443 # Protocol encoded using UTF-8 numeric entities
404 html = HTML('<IMG SRC=\'&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;' 444 html = HTML('<IMG SRC=\'&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;'
405 '&#112;&#116;&#58;alert("foo")\'>') 445 '&#112;&#116;&#58;alert("foo")\'>')
406 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 446 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
407 # Protocol encoded using UTF-8 numeric entities without a semicolon 447 # Protocol encoded using UTF-8 numeric entities without a semicolon
408 # (which is allowed because the max number of digits is used) 448 # (which is allowed because the max number of digits is used)
409 html = HTML('<IMG SRC=\'&#0000106&#0000097&#0000118&#0000097' 449 html = HTML('<IMG SRC=\'&#0000106&#0000097&#0000118&#0000097'
410 '&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116' 450 '&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116'
411 '&#0000058alert("foo")\'>') 451 '&#0000058alert("foo")\'>')
412 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 452 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
413 # Protocol encoded using UTF-8 numeric hex entities without a semicolon 453 # Protocol encoded using UTF-8 numeric hex entities without a semicolon
414 # (which is allowed because the max number of digits is used) 454 # (which is allowed because the max number of digits is used)
415 html = HTML('<IMG SRC=\'&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69' 455 html = HTML('<IMG SRC=\'&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69'
416 '&#x70&#x74&#x3A;alert("foo")\'>') 456 '&#x70&#x74&#x3A;alert("foo")\'>')
417 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 457 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
418 # Embedded tab character in protocol 458 # Embedded tab character in protocol
419 html = HTML('<IMG SRC=\'jav\tascript:alert("foo");\'>') 459 html = HTML('<IMG SRC=\'jav\tascript:alert("foo");\'>')
420 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 460 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
421 # Embedded tab character in protocol, but encoded this time 461 # Embedded tab character in protocol, but encoded this time
422 html = HTML('<IMG SRC=\'jav&#x09;ascript:alert("foo");\'>') 462 html = HTML('<IMG SRC=\'jav&#x09;ascript:alert("foo");\'>')
423 self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer())) 463 self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
424 464
425 465
426 def suite(): 466 def suite():
427 suite = unittest.TestSuite() 467 suite = unittest.TestSuite()
428 suite.addTest(doctest.DocTestSuite(HTMLFormFiller.__module__)) 468 suite.addTest(doctest.DocTestSuite(HTMLFormFiller.__module__))
429 suite.addTest(unittest.makeSuite(HTMLFormFillerTestCase, 'test')) 469 suite.addTest(unittest.makeSuite(HTMLFormFillerTestCase, 'test'))
430 suite.addTest(unittest.makeSuite(HTMLSanitizerTestCase, 'test')) 470 suite.addTest(unittest.makeSuite(HTMLSanitizerTestCase, 'test'))
431 return suite 471 return suite
432 472
473
433 if __name__ == '__main__': 474 if __name__ == '__main__':
434 unittest.main(defaultTest='suite') 475 unittest.main(defaultTest='suite')
Copyright (C) 2012-2017 Edgewall Software