function FilterHtmlImageSecureTest::testImageSource

Same name and namespace in other branches
  1. 8.9.x core/modules/filter/tests/src/Functional/FilterHtmlImageSecureTest.php \Drupal\Tests\filter\Functional\FilterHtmlImageSecureTest::testImageSource()
  2. 10 core/modules/filter/tests/src/Functional/FilterHtmlImageSecureTest.php \Drupal\Tests\filter\Functional\FilterHtmlImageSecureTest::testImageSource()
  3. 11.x core/modules/filter/tests/src/Functional/FilterHtmlImageSecureTest.php \Drupal\Tests\filter\Functional\FilterHtmlImageSecureTest::testImageSource()

Tests removal of images having a non-local source.

File

core/modules/filter/tests/src/Functional/FilterHtmlImageSecureTest.php, line 80

Class

FilterHtmlImageSecureTest
Tests restriction of IMG tags in HTML input.

Namespace

Drupal\Tests\filter\Functional

Code

public function testImageSource() {
    global $base_url;
    $node = $this->drupalCreateNode();
    $public_files_path = PublicStream::basePath();
    $http_base_url = preg_replace('/^https?/', 'http', $base_url);
    $https_base_url = preg_replace('/^https?/', 'https', $base_url);
    $files_path = base_path() . $public_files_path;
    $csrf_path = $public_files_path . '/' . implode('/', array_fill(0, substr_count($public_files_path, '/') + 1, '..'));
    $druplicon = 'core/misc/druplicon.png';
    $red_x_image = base_path() . 'core/misc/icons/e32700/error.svg';
    // Put a test image in the files directory.
    $test_images = $this->getTestFiles('image');
    $test_image = $test_images[0]->filename;
    // Put a test image in the files directory with special filename.
    // cspell:ignore tést fïle nàme
    $special_filename = 'tést fïle nàme.png';
    $special_image = rawurlencode($special_filename);
    $special_uri = str_replace($test_images[0]->filename, $special_filename, $test_images[0]->uri);
    \Drupal::service('file_system')->copy($test_images[0]->uri, $special_uri);
    // Create a list of test image sources.
    // The keys become the value of the IMG 'src' attribute, the values are the
    // expected filter conversions.
    $host = \Drupal::request()->getHost();
    $host_pattern = '|^http\\://' . $host . '(\\:[0-9]{0,5})|';
    $images = [
        $http_base_url . '/' . $druplicon => base_path() . $druplicon,
        $https_base_url . '/' . $druplicon => base_path() . $druplicon,
        // Test a URL that includes a port.
preg_replace($host_pattern, 'http://' . $host . ':', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
        preg_replace($host_pattern, 'http://' . $host . ':80', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
        preg_replace($host_pattern, 'http://' . $host . ':443', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
        preg_replace($host_pattern, 'http://' . $host . ':8080', $http_base_url . '/' . $druplicon) => base_path() . $druplicon,
        base_path() . $druplicon => base_path() . $druplicon,
        $files_path . '/' . $test_image => $files_path . '/' . $test_image,
        $http_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
        $https_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image,
        $http_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image,
        $https_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image,
        $files_path . '/example.png' => $red_x_image,
        'http://example.com/' . $druplicon => $red_x_image,
        'https://example.com/' . $druplicon => $red_x_image,
        'javascript:druplicon.png' => $red_x_image,
        $csrf_path . '/logout' => $red_x_image,
    ];
    $comment = [];
    foreach ($images as $image => $converted) {
        // Output the image source as plain text for debugging.
        $comment[] = $image . ':';
        // Hash the image source in a custom test attribute, because it might
        // contain characters that confuse XPath.
        $comment[] = '<img src="' . $image . '" testattribute="' . hash('sha256', $image) . '" />';
    }
    $edit = [
        'comment_body[0][value]' => implode("\n", $comment),
    ];
    $this->drupalGet('node/' . $node->id());
    $this->submitForm($edit, 'Save');
    foreach ($images as $image => $converted) {
        $found = FALSE;
        foreach ($this->xpath('//img[@testattribute="' . hash('sha256', $image) . '"]') as $element) {
            $found = TRUE;
            if ($converted == $red_x_image) {
                $this->assertEquals($red_x_image, $element->getAttribute('src'));
                $this->assertEquals('Image removed.', $element->getAttribute('alt'));
                $this->assertEquals('This image has been removed. For security reasons, only images from the local domain are allowed.', $element->getAttribute('title'));
                $this->assertEquals('16', $element->getAttribute('height'));
                $this->assertEquals('16', $element->getAttribute('width'));
            }
            else {
                $this->assertEquals($converted, $element->getAttribute('src'));
            }
        }
        $this->assertTrue($found, new FormattableMarkup('@image was found.', [
            '@image' => $image,
        ]));
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.