Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core;
18
 
19
/**
20
 * HTMLPurifier test case
21
 *
22
 * @package    core
23
 * @category   test
24
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
25
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
class htmlpurifier_test extends \basic_testcase {
28
 
29
    /**
30
     * Verify _blank target is allowed.
31
     */
11 efrain 32
    public function test_allow_blank_target(): void {
1 efrain 33
        // See MDL-52651 for an explanation as to why the rel="noreferrer" attribute is expected here.
34
        // Also note we do not need to test links with an existing rel attribute as the HTML Purifier is configured to remove
35
        // the rel attribute.
36
        $text = '<a href="http://moodle.org" target="_blank">Some link</a>';
37
        $expected = '<a href="http://moodle.org" target="_blank" rel="noreferrer noopener">Some link</a>';
38
        $result = format_text($text, FORMAT_HTML);
39
        $this->assertSame($expected, $result);
40
 
41
        $result = format_text('<a href="http://moodle.org" target="some">Some link</a>', FORMAT_HTML);
42
        $this->assertSame('<a href="http://moodle.org">Some link</a>', $result);
43
    }
44
 
45
    /**
46
     * Verify our nolink tag accepted.
47
     */
11 efrain 48
    public function test_nolink(): void {
1 efrain 49
        // We can not use format text because nolink changes result.
50
        $text = '<nolink><div>no filters</div></nolink>';
51
        $result = purify_html($text, array());
52
        $this->assertSame($text, $result);
53
 
54
        $text = '<nolink>xxx<em>xx</em><div>xxx</div></nolink>';
55
        $result = purify_html($text, array());
56
        $this->assertSame($text, $result);
57
 
58
        // Ensure nolink doesn't force open tags to be closed, so can be virtually everywhere.
59
        $text = '<p><nolink><div>no filters</div></nolink></p>';
60
        $result = purify_html($text, array());
61
        $this->assertSame($text, $result);
62
    }
63
 
64
    /**
65
     * Verify our tex tag accepted.
66
     */
11 efrain 67
    public function test_tex(): void {
1 efrain 68
        $text = '<tex>a+b=c</tex>';
69
        $result = purify_html($text, array());
70
        $this->assertSame($text, $result);
71
    }
72
 
73
    /**
74
     * Verify our algebra tag accepted.
75
     */
11 efrain 76
    public function test_algebra(): void {
1 efrain 77
        $text = '<algebra>a+b=c</algebra>';
78
        $result = purify_html($text, array());
79
        $this->assertSame($text, $result);
80
    }
81
 
82
    /**
83
     * Verify our hacky multilang works.
84
     */
11 efrain 85
    public function test_multilang(): void {
1 efrain 86
        $text = '<lang lang="en">hmmm</lang><lang lang="anything">hm</lang>';
87
        $result = purify_html($text, array());
88
        $this->assertSame($text, $result);
89
 
90
        $text = '<span lang="en" class="multilang">hmmm</span><span lang="anything" class="multilang">hm</span>';
91
        $result = purify_html($text, array());
92
        $this->assertSame($text, $result);
93
 
94
        $text = '<span lang="en">hmmm</span>';
95
        $result = purify_html($text, array());
96
        $this->assertNotSame($text, $result);
97
 
98
        // Keep standard lang tags.
99
 
100
        $text = '<span lang="de_DU" class="multilang">asas</span>';
101
        $result = purify_html($text, array());
102
        $this->assertSame($text, $result);
103
 
104
        $text = '<lang lang="de_DU">xxxxxx</lang>';
105
        $result = purify_html($text, array());
106
        $this->assertSame($text, $result);
107
    }
108
 
109
    /**
110
     * Tests the 'allowid' option for format_text.
111
     */
11 efrain 112
    public function test_format_text_allowid(): void {
1 efrain 113
        // Start off by not allowing ids (default).
114
        $options = [
115
            'allowid' => false,
116
        ];
117
        $result = format_text('<div id="example">Frog</div>', FORMAT_HTML, $options);
118
        $this->assertSame('<div>Frog</div>', $result);
119
 
120
        // Now allow ids.
121
        $options['allowid'] = true;
122
        $result = format_text('<div id="example">Frog</div>', FORMAT_HTML, $options);
123
        $this->assertSame('<div id="example">Frog</div>', $result);
124
    }
125
 
11 efrain 126
    public function test_allowobjectembed(): void {
1 efrain 127
        global $CFG;
128
 
129
        $this->assertSame('0', $CFG->allowobjectembed);
130
 
131
        $text = '<object width="425" height="350">
132
<param name="movie" value="http://www.youtube.com/v/AyPzM5WK8ys" />
133
<param name="wmode" value="transparent" />
134
<embed src="http://www.youtube.com/v/AyPzM5WK8ys" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" />
135
</object>hmmm';
136
        $result = purify_html($text, array());
137
        $this->assertSame('hmmm', trim($result));
138
 
139
        $CFG->allowobjectembed = '1';
140
 
141
        $expected = '<object width="425" height="350" data="http://www.youtube.com/v/AyPzM5WK8ys" type="application/x-shockwave-flash">
142
<param name="allowScriptAccess" value="never" />
143
<param name="allowNetworking" value="internal" />
144
<param name="movie" value="http://www.youtube.com/v/AyPzM5WK8ys" />
145
<param name="wmode" value="transparent" />
146
<embed src="http://www.youtube.com/v/AyPzM5WK8ys" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350" allowscriptaccess="never" allownetworking="internal" />
147
</object>hmmm';
148
        $result = purify_html($text, array());
149
        $this->assertSame(str_replace("\n", '', $expected), str_replace("\n", '', $result));
150
 
151
        $CFG->allowobjectembed = '0';
152
 
153
        $result = purify_html($text, array());
154
        $this->assertSame('hmmm', trim($result));
155
    }
156
 
157
    /**
158
     * Test if linebreaks kept unchanged.
159
     */
11 efrain 160
    public function test_line_breaking(): void {
1 efrain 161
        $text = "\n\raa\rsss\nsss\r";
162
        $this->assertSame($text, purify_html($text));
163
    }
164
 
165
    /**
166
     * Test fixing of strict problems.
167
     */
11 efrain 168
    public function test_tidy(): void {
1 efrain 169
        $text = "<p>xx";
170
        $this->assertSame('<p>xx</p>', purify_html($text));
171
 
172
        $text = "<P>xx</P>";
173
        $this->assertSame('<p>xx</p>', purify_html($text));
174
 
175
        $text = "xx<br>";
176
        $this->assertSame('xx<br />', purify_html($text));
177
    }
178
 
179
    /**
180
     * Test nesting - this used to cause problems in earlier versions.
181
     */
11 efrain 182
    public function test_nested_lists(): void {
1 efrain 183
        $text = "<ul><li>One<ul><li>Two</li></ul></li><li>Three</li></ul>";
184
        $this->assertSame($text, purify_html($text));
185
    }
186
 
187
    /**
188
     * Test that XSS protection works, complete smoke tests are in htmlpurifier itself.
189
     */
11 efrain 190
    public function test_cleaning_nastiness(): void {
1 efrain 191
        $text = "x<SCRIPT>alert('XSS')</SCRIPT>x";
192
        $this->assertSame('xx', purify_html($text));
193
 
194
        $text = '<DIV STYLE="background-image:url(javascript:alert(\'XSS\'))">xx</DIV>';
195
        $this->assertSame('<div>xx</div>', purify_html($text));
196
 
197
        $text = '<DIV STYLE="width:expression(alert(\'XSS\'));">xx</DIV>';
198
        $this->assertSame('<div>xx</div>', purify_html($text));
199
 
200
        $text = 'x<IFRAME SRC="javascript:alert(\'XSS\');"></IFRAME>x';
201
        $this->assertSame('xx', purify_html($text));
202
 
203
        $text = 'x<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>x';
204
        $this->assertSame('xx', purify_html($text));
205
 
206
        $text = 'x<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>x';
207
        $this->assertSame('xx', purify_html($text));
208
 
209
        $text = 'x<form></form>x';
210
        $this->assertSame('xx', purify_html($text));
211
    }
212
 
213
    /**
214
     * Test internal function used for clean_text() speedup.
215
     */
11 efrain 216
    public function test_is_purify_html_necessary(): void {
1 efrain 217
        // First our shortcuts.
218
        $text = "";
219
        $this->assertFalse(is_purify_html_necessary($text));
220
        $this->assertSame($text, purify_html($text));
221
 
222
        $text = "666";
223
        $this->assertFalse(is_purify_html_necessary($text));
224
        $this->assertSame($text, purify_html($text));
225
 
226
        $text = "abc\ndef \" ' ";
227
        $this->assertFalse(is_purify_html_necessary($text));
228
        $this->assertSame($text, purify_html($text));
229
 
230
        $text = "abc\n<p>def</p>efg<p>hij</p>";
231
        $this->assertFalse(is_purify_html_necessary($text));
232
        $this->assertSame($text, purify_html($text));
233
 
234
        $text = "<br />abc\n<p>def<em>efg</em><strong>hi<br />j</strong></p>";
235
        $this->assertFalse(is_purify_html_necessary($text));
236
        $this->assertSame($text, purify_html($text));
237
 
238
        // Now failures.
239
        $text = "&nbsp;";
240
        $this->assertTrue(is_purify_html_necessary($text));
241
 
242
        $text = "Gin & Tonic";
243
        $this->assertTrue(is_purify_html_necessary($text));
244
 
245
        $text = "Gin > Tonic";
246
        $this->assertTrue(is_purify_html_necessary($text));
247
 
248
        $text = "Gin < Tonic";
249
        $this->assertTrue(is_purify_html_necessary($text));
250
 
251
        $text = "<div>abc</div>";
252
        $this->assertTrue(is_purify_html_necessary($text));
253
 
254
        $text = "<span>abc</span>";
255
        $this->assertTrue(is_purify_html_necessary($text));
256
 
257
        $text = "<br>abc";
258
        $this->assertTrue(is_purify_html_necessary($text));
259
 
260
        $text = "<p class='xxx'>abc</p>";
261
        $this->assertTrue(is_purify_html_necessary($text));
262
 
263
        $text = "<p>abc<em></p></em>";
264
        $this->assertTrue(is_purify_html_necessary($text));
265
 
266
        $text = "<p>abc";
267
        $this->assertTrue(is_purify_html_necessary($text));
268
    }
269
 
11 efrain 270
    public function test_allowed_schemes(): void {
1 efrain 271
        // First standard schemas.
272
        $text = '<a href="http://www.example.com/course/view.php?id=5">link</a>';
273
        $this->assertSame($text, purify_html($text));
274
 
275
        $text = '<a href="https://www.example.com/course/view.php?id=5">link</a>';
276
        $this->assertSame($text, purify_html($text));
277
 
278
        $text = '<a href="ftp://user@ftp.example.com/some/file.txt">link</a>';
279
        $this->assertSame($text, purify_html($text));
280
 
281
        $text = '<a href="nntp://example.com/group/123">link</a>';
282
        $this->assertSame($text, purify_html($text));
283
 
284
        $text = '<a href="news:groupname">link</a>';
285
        $this->assertSame($text, purify_html($text));
286
 
287
        $text = '<a href="mailto:user@example.com">link</a>';
288
        $this->assertSame($text, purify_html($text));
289
 
290
        // Extra schemes allowed in moodle.
291
        $text = '<a href="irc://irc.example.com/3213?pass">link</a>';
292
        $this->assertSame($text, purify_html($text));
293
 
294
        $text = '<a href="rtsp://www.example.com/movie.mov">link</a>';
295
        $this->assertSame($text, purify_html($text));
296
 
297
        $text = '<a href="rtmp://www.example.com/video.f4v">link</a>';
298
        $this->assertSame($text, purify_html($text));
299
 
300
        $text = '<a href="teamspeak://speak.example.com/?par=val?par2=val2">link</a>';
301
        $this->assertSame($text, purify_html($text));
302
 
303
        $text = '<a href="gopher://gopher.example.com/resource">link</a>';
304
        $this->assertSame($text, purify_html($text));
305
 
306
        $text = '<a href="mms://www.example.com/movie.mms">link</a>';
307
        $this->assertSame($text, purify_html($text));
308
 
309
        // Now some borked or dangerous schemes.
310
        $text = '<a href="javascript://www.example.com">link</a>';
311
        $this->assertSame('<a>link</a>', purify_html($text));
312
 
313
        $text = '<a href="hmmm://www.example.com">link</a>';
314
        $this->assertSame('<a>link</a>', purify_html($text));
315
    }
316
 
317
    /**
318
     * Test non-ascii domain names
319
     */
11 efrain 320
    public function test_idn(): void {
1 efrain 321
 
322
        // Example of domain that gives the same result in IDNA2003 and IDNA2008 .
323
        $text = '<a href="http://правительство.рф">правительство.рф</a>';
324
        $expected = '<a href="http://xn--80aealotwbjpid2k.xn--p1ai">правительство.рф</a>';
325
        $this->assertSame($expected, purify_html($text));
326
 
327
        // Examples of deviations from http://www.unicode.org/reports/tr46/#Table_Deviation_Characters .
328
        $text = '<a href="http://teßt.de">teßt.de</a>';
329
        $expected = '<a href="http://xn--tet-6ka.de">teßt.de</a>';
330
        $this->assertSame($expected, purify_html($text));
331
 
332
        $text = '<a href="http://βόλος.com">http://βόλος.com</a>';
333
        $expected = '<a href="http://xn--nxasmm1c.com">http://βόλος.com</a>';
334
        $this->assertSame($expected, purify_html($text));
335
 
336
        $text = '<a href="http://نامه‌ای.com">http://نامه‌ای.com</a>';
337
        $expected = '<a href="http://xn--mgba3gch31f060k.com">http://نامه‌ای.com</a>';
338
        $this->assertSame($expected, purify_html($text));
339
    }
340
 
341
    /**
342
     * Tests media tags.
343
     *
344
     * @dataProvider media_tags_provider
345
     * @param string $mediatag HTML media tag
346
     * @param string $expected expected result
347
     */
11 efrain 348
    public function test_media_tags($mediatag, $expected): void {
1 efrain 349
        $actual = format_text($mediatag, FORMAT_MOODLE, ['filter' => false]);
350
        $this->assertEquals($expected, $actual);
351
    }
352
 
353
    /**
354
     * Test cases for the test_media_tags test.
355
     */
356
    public function media_tags_provider() {
357
        // Takes an array of attributes, then generates a test for each of them.
358
        $generatetestcases = function($prefix, array $attrs, array $templates) {
359
            return array_reduce($attrs, function($carry, $attr) use ($prefix, $templates) {
360
                $testcase = [$prefix . '/' . $attr => [
361
                    sprintf($templates[0], $attr),
362
                    sprintf($templates[1], $attr)
363
                ]];
364
                return empty(array_values($carry)[0]) ? $testcase : $carry + $testcase;
365
            }, [[]]);
366
        };
367
 
368
        $audioattrs = [
369
            'preload="auto"', 'autoplay=""', 'loop=""', 'muted=""', 'controls=""',
370
            'crossorigin="anonymous"', 'crossorigin="use-credentials"'
371
        ];
372
        $videoattrs = [
373
            'crossorigin="anonymous"', 'crossorigin="use-credentials"',
374
            'poster="https://upload.wikimedia.org/wikipedia/en/1/14/Space_jam.jpg"',
375
            'preload="auto"', 'autoplay=""', 'playsinline=""', 'loop=""', 'muted=""',
376
            'controls=""', 'width="420"', 'height="69"'
377
        ];
378
        return $generatetestcases('Plain audio', $audioattrs + ['src="http://example.com/jam.wav"'], [
379
                '<audio %1$s>Looks like you can\'t slam the jams.</audio>',
380
                '<div class="text_to_html"><audio %1$s>Looks like you can\'t slam the jams.</audio></div>'
381
            ]) + $generatetestcases('Audio with one source', $audioattrs, [
382
                '<audio %1$s><source src="http://example.com/getup.wav">No tasty jams for you.</audio>',
383
                '<div class="text_to_html">' .
384
                    '<audio %1$s>' .
385
                        '<source src="http://example.com/getup.wav" />' .
386
                        'No tasty jams for you.' .
387
                    '</audio>' .
388
                '</div>'
389
            ]) + $generatetestcases('Audio with multiple sources', $audioattrs, [
390
                '<audio %1$s>' .
391
                    '<source src="http://example.com/getup.wav" type="audio/wav">' .
392
                    '<source src="http://example.com/getup.mp3" type="audio/mpeg">' .
393
                    '<source src="http://example.com/getup.ogg" type="audio/ogg">' .
394
                    'No tasty jams for you.' .
395
                '</audio>',
396
                '<div class="text_to_html">' .
397
                    '<audio %1$s>' .
398
                        '<source src="http://example.com/getup.wav" type="audio/wav" />' .
399
                        '<source src="http://example.com/getup.mp3" type="audio/mpeg" />' .
400
                        '<source src="http://example.com/getup.ogg" type="audio/ogg" />' .
401
                        'No tasty jams for you.' .
402
                    '</audio>' .
403
                '</div>'
404
            ]) + $generatetestcases('Audio with sources and tracks', $audioattrs, [
405
                '<audio %1$s>' .
406
                    '<source src="http://example.com/getup.wav" type="audio/wav">' .
407
                    '<track kind="subtitles" src="http://example.com/subtitles_en.vtt" label="English" srclang="en">' .
408
                    '<track kind="subtitles" src="http://example.com/subtitles_es.vtt" label="Espanol" srclang="es">' .
409
                    'No tasty jams for you.' .
410
                '</audio>',
411
                '<div class="text_to_html">' .
412
                    '<audio %1$s>' .
413
                        '<source src="http://example.com/getup.wav" type="audio/wav" />' .
414
                        '<track kind="subtitles" src="http://example.com/subtitles_en.vtt" label="English" srclang="en" />' .
415
                        '<track kind="subtitles" src="http://example.com/subtitles_es.vtt" label="Espanol" srclang="es" />' .
416
                        'No tasty jams for you.' .
417
                    '</audio>' .
418
                '</div>'
419
            ]) + $generatetestcases('Plain video', $videoattrs + ['src="http://example.com/prettygood.mp4'], [
420
                '<video %1$s>Oh, that\'s pretty bad 😦</video>',
421
                '<div class="text_to_html"><video %1$s>Oh, that\'s pretty bad 😦</video></div>'
422
            ]) + $generatetestcases('Video with illegal subtag', $videoattrs + ['src="http://example.com/prettygood.mp4'], [
423
                '<video %1$s><subtag></subtag>Oh, that\'s pretty bad 😦</video>',
424
                '<div class="text_to_html"><video %1$s>Oh, that\'s pretty bad 😦</video></div>'
425
            ]) + $generatetestcases('Video with legal subtag', $videoattrs + ['src="http://example.com/prettygood.mp4'], [
426
                '<video %1$s>Did not work <a href="http://example.com/prettygood.mp4">click here to download</a></video>',
427
                '<div class="text_to_html"><video %1$s>Did not work <a href="http://example.com/prettygood.mp4">' .
428
                'click here to download</a></video></div>'
429
            ]) + $generatetestcases('Video inside an inline tag', $videoattrs + ['src="http://example.com/prettygood.mp4'], [
430
                '<em><video %1$s>Oh, that\'s pretty bad 😦</video></em>',
431
                '<div class="text_to_html"><em><video %1$s>Oh, that\'s pretty bad 😦</video></em></div>'
432
            ]) + $generatetestcases('Video inside a block tag', $videoattrs + ['src="http://example.com/prettygood.mp4'], [
433
                '<p><video %1$s>Oh, that\'s pretty bad 😦</video></p>',
434
                '<div class="text_to_html"><p><video %1$s>Oh, that\'s pretty bad 😦</video></p></div>'
435
            ]) + $generatetestcases('Source tag without video or audio', $videoattrs, [
436
                'some text <source src="http://example.com/getup.wav" type="audio/wav"> the end',
437
                '<div class="text_to_html">some text  the end</div>'
438
            ]) + $generatetestcases('Video with one source', $videoattrs, [
439
                '<video %1$s><source src="http://example.com/prettygood.mp4">Oh, that\'s pretty bad 😦</video>',
440
                '<div class="text_to_html">' .
441
                    '<video %1$s>' .
442
                        '<source src="http://example.com/prettygood.mp4" />' .
443
                        'Oh, that\'s pretty bad 😦' .
444
                    '</video>' .
445
                '</div>'
446
            ]) + $generatetestcases('Video with multiple sources', $videoattrs, [
447
                '<video %1$s>' .
448
                    '<source src="http://example.com/prettygood.mp4" type="video/mp4">' .
449
                    '<source src="http://example.com/eljefe.mp4" type="video/mp4">' .
450
                    '<source src="http://example.com/turnitup.mov" type="video/mov">' .
451
                    'Oh, that\'s pretty bad 😦' .
452
                '</video>',
453
                '<div class="text_to_html">' .
454
                    '<video %1$s>' .
455
                        '<source src="http://example.com/prettygood.mp4" type="video/mp4" />' .
456
                        '<source src="http://example.com/eljefe.mp4" type="video/mp4" />' .
457
                        '<source src="http://example.com/turnitup.mov" type="video/mov" />' .
458
                        'Oh, that\'s pretty bad 😦' .
459
                    '</video>' .
460
                '</div>'
461
            ]) + $generatetestcases('Video with sources and tracks', $audioattrs, [
462
                '<video %1$s>' .
463
                    '<source src="http://example.com/getup.wav" type="audio/wav">' .
464
                    '<track kind="subtitles" src="http://example.com/subtitles_en.vtt" label="English" srclang="en">' .
465
                    '<track kind="subtitles" src="http://example.com/subtitles_es.vtt" label="Espanol" srclang="es">' .
466
                    'No tasty jams for you.' .
467
                '</video>',
468
                '<div class="text_to_html">' .
469
                    '<video %1$s>' .
470
                        '<source src="http://example.com/getup.wav" type="audio/wav" />' .
471
                        '<track kind="subtitles" src="http://example.com/subtitles_en.vtt" label="English" srclang="en" />' .
472
                        '<track kind="subtitles" src="http://example.com/subtitles_es.vtt" label="Espanol" srclang="es" />' .
473
                    'No tasty jams for you.' .
474
                    '</video>' .
475
                '</div>'
476
            ]) + ['Video with invalid crossorigin' => [
477
                    '<video src="http://example.com/turnitup.mov" crossorigin="can i pls hab?">' .
478
                        'Oh, that\'s pretty bad 😦' .
479
                    '</video>',
480
                    '<div class="text_to_html">' .
481
                        '<video src="http://example.com/turnitup.mov">' .
482
                           'Oh, that\'s pretty bad 😦' .
483
                        '</video>' .
484
                    '</div>'
485
            ]] + ['Audio with invalid crossorigin' => [
486
                    '<audio src="http://example.com/getup.wav" crossorigin="give me. the jams.">' .
487
                        'nyemnyemnyem' .
488
                    '</audio>',
489
                    '<div class="text_to_html">' .
490
                        '<audio src="http://example.com/getup.wav">' .
491
                            'nyemnyemnyem' .
492
                        '</audio>' .
493
                    '</div>'
494
            ]] + ['Other attributes' => [
495
                '<video src="http://example.com/turnitdown.mov" class="nofilter" data-something="data attribute" someattribute="somevalue" onclick="boom">' .
496
                    '<source src="http://example.com/getup.wav" type="audio/wav" class="shouldberemoved" data-sourcedata="source data" onmouseover="kill session" />' .
497
                    '<track src="http://example.com/subtitles_en.vtt" class="shouldberemoved" data-trackdata="track data" onmouseover="removeme" />' .
498
                    'Do not remove attribute class but remove other attributes' .
499
                '</video>',
500
                '<div class="text_to_html">' .
501
                    '<video src="http://example.com/turnitdown.mov" class="nofilter">' .
502
                        '<source src="http://example.com/getup.wav" type="audio/wav" />' .
503
                        '<track src="http://example.com/subtitles_en.vtt" />' .
504
                        'Do not remove attribute class but remove other attributes' .
505
                    '</video>' .
506
                '</div>'
507
            ]];
508
    }
509
}