249021a83263a4eca1e4192d8c4a8b40b8b33901
[yaffs-website] / web / core / modules / filter / src / Tests / FilterHtmlImageSecureTest.php
1 <?php
2
3 namespace Drupal\filter\Tests;
4
5 use Drupal\comment\Tests\CommentTestTrait;
6 use Drupal\Core\StreamWrapper\PublicStream;
7 use Drupal\simpletest\WebTestBase;
8 use Drupal\filter\Entity\FilterFormat;
9
10 /**
11  * Tests restriction of IMG tags in HTML input.
12  *
13  * @group filter
14  */
15 class FilterHtmlImageSecureTest extends WebTestBase {
16
17   use CommentTestTrait;
18
19   /**
20    * Modules to enable.
21    *
22    * @var array
23    */
24   public static $modules = ['filter', 'node', 'comment'];
25
26   /**
27    * An authenticated user.
28    *
29    * @var \Drupal\user\UserInterface
30    */
31   protected $webUser;
32
33   protected function setUp() {
34     parent::setUp();
35
36     // Setup Filtered HTML text format.
37     $filtered_html_format = FilterFormat::create([
38       'format' => 'filtered_html',
39       'name' => 'Filtered HTML',
40       'filters' => [
41         'filter_html' => [
42           'status' => 1,
43           'settings' => [
44             'allowed_html' => '<img src testattribute> <a>',
45           ],
46         ],
47         'filter_autop' => [
48           'status' => 1,
49         ],
50         'filter_html_image_secure' => [
51           'status' => 1,
52         ],
53       ],
54     ]);
55     $filtered_html_format->save();
56
57     // Setup users.
58     $this->webUser = $this->drupalCreateUser([
59       'access content',
60       'access comments',
61       'post comments',
62       'skip comment approval',
63       $filtered_html_format->getPermissionName(),
64     ]);
65     $this->drupalLogin($this->webUser);
66
67     // Setup a node to comment and test on.
68     $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
69     // Add a comment field.
70     $this->addDefaultCommentField('node', 'page');
71     $this->node = $this->drupalCreateNode();
72   }
73
74   /**
75    * Tests removal of images having a non-local source.
76    */
77   public function testImageSource() {
78     global $base_url;
79
80     $public_files_path = PublicStream::basePath();
81
82     $http_base_url = preg_replace('/^https?/', 'http', $base_url);
83     $https_base_url = preg_replace('/^https?/', 'https', $base_url);
84     $files_path = base_path() . $public_files_path;
85     $csrf_path = $public_files_path . '/' . implode('/', array_fill(0, substr_count($public_files_path, '/') + 1, '..'));
86
87     $druplicon = 'core/misc/druplicon.png';
88     $red_x_image = base_path() . 'core/misc/icons/e32700/error.svg';
89     $alt_text = t('Image removed.');
90     $title_text = t('This image has been removed. For security reasons, only images from the local domain are allowed.');
91
92     // Put a test image in the files directory.
93     $test_images = $this->drupalGetTestFiles('image');
94     $test_image = $test_images[0]->filename;
95
96     // Put a test image in the files directory with special filename.
97     $special_filename = 'tést fïle nàme.png';
98     $special_image = rawurlencode($special_filename);
99     $special_uri = str_replace($test_images[0]->filename, $special_filename, $test_images[0]->uri);
100     file_unmanaged_copy($test_images[0]->uri, $special_uri);
101
102     // Create a list of test image sources.
103     // The keys become the value of the IMG 'src' attribute, the values are the
104     // expected filter conversions.
105     $host = \Drupal::request()->getHost();
106     $host_pattern = '|^http\://' . $host . '(\:[0-9]{0,5})|';
107     $images = [
108       $http_base_url . '/' . $druplicon => base_path() . $druplicon,
109       $https_base_url . '/' . $druplicon => base_path() . $druplicon,
110       // Test a url that includes a port.
111       preg_replace($host_pattern, 'http://' . $host . ':', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
112       preg_replace($host_pattern, 'http://' . $host . ':80', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
113       preg_replace($host_pattern, 'http://' . $host . ':443', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
114       preg_replace($host_pattern, 'http://' . $host . ':8080', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
115       base_path() . $druplicon => base_path() . $druplicon,
116       $files_path . '/' . $test_image => $files_path . '/' . $test_image,
117       $http_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
118       $https_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
119       $http_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image,
120       $https_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image,
121       $files_path . '/example.png' => $red_x_image,
122       'http://example.com/' . $druplicon => $red_x_image,
123       'https://example.com/' . $druplicon => $red_x_image,
124       'javascript:druplicon.png' => $red_x_image,
125       $csrf_path . '/logout' => $red_x_image,
126     ];
127     $comment = [];
128     foreach ($images as $image => $converted) {
129       // Output the image source as plain text for debugging.
130       $comment[] = $image . ':';
131       // Hash the image source in a custom test attribute, because it might
132       // contain characters that confuse XPath.
133       $comment[] = '<img src="' . $image . '" testattribute="' . hash('sha256', $image) . '" />';
134     }
135     $edit = [
136       'comment_body[0][value]' => implode("\n", $comment),
137     ];
138     $this->drupalPostForm('node/' . $this->node->id(), $edit, t('Save'));
139     foreach ($images as $image => $converted) {
140       $found = FALSE;
141       foreach ($this->xpath('//img[@testattribute="' . hash('sha256', $image) . '"]') as $element) {
142         $found = TRUE;
143         if ($converted == $red_x_image) {
144           $this->assertEqual((string) $element['src'], $red_x_image);
145           $this->assertEqual((string) $element['alt'], $alt_text);
146           $this->assertEqual((string) $element['title'], $title_text);
147           $this->assertEqual((string) $element['height'], '16');
148           $this->assertEqual((string) $element['width'], '16');
149         }
150         else {
151           $this->assertEqual((string) $element['src'], $converted);
152         }
153       }
154       $this->assertTrue($found, format_string('@image was found.', ['@image' => $image]));
155     }
156   }
157
158 }