diff --git a/core/includes/file.inc b/core/includes/file.inc index f576781379a340e566963c0ffb47ad7f80c2b9ee..78fdbfa0042850180c7ec7e171072d2a09de3f0a 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -276,18 +276,22 @@ function file_stream_wrapper_get_class($scheme) { /** * Returns the scheme of a URI (e.g. a stream). * - * @param $uri - * A stream, referenced as "scheme://target". + * @param string $uri + * A stream, referenced as "scheme://target" or "data:target". * - * @return + * @return string * A string containing the name of the scheme, or FALSE if none. For example, * the URI "public://example.txt" would return "public". * * @see file_uri_target() */ function file_uri_scheme($uri) { - $position = strpos($uri, '://'); - return $position ? substr($uri, 0, $position) : FALSE; + if (preg_match('/^([\w\-]+):\/\/|^(data):/', $uri, $matches)) { + // The scheme will always be the last element in the matches array. + return array_pop($matches); + } + + return FALSE; } /** @@ -312,10 +316,10 @@ function file_stream_wrapper_valid_scheme($scheme) { /** * Returns the part of a URI after the schema. * - * @param $uri - * A stream, referenced as "scheme://target". + * @param string $uri + * A stream, referenced as "scheme://target" or "data:target". * - * @return + * @return string|bool * A string containing the target (path), or FALSE if none. * For example, the URI "public://sample/test.txt" would return * "sample/test.txt". @@ -323,10 +327,12 @@ function file_stream_wrapper_valid_scheme($scheme) { * @see file_uri_scheme() */ function file_uri_target($uri) { - $data = explode('://', $uri, 2); + // Remove the scheme from the URI and remove erroneous leading or trailing, + // forward-slashes and backslashes. + $target = trim(preg_replace('/^[\w\-]+:\/\/|^data:/', '', $uri), '\/'); - // Remove erroneous leading or trailing, forward-slashes and backslashes. - return count($data) == 2 ? trim($data[1], '\/') : FALSE; + // If nothing was replaced, the URI doesn't have a valid scheme. + return $target !== $uri ? $target : FALSE; } /** @@ -439,11 +445,11 @@ function file_stream_wrapper_get_instance_by_scheme($scheme) { * - "shipped files", i.e. those outside of the files directory, which ship as * part of Drupal core or contributed modules or themes. * - * @param $uri + * @param string $uri * The URI to a file for which we need an external URL, or the path to a * shipped file. * - * @return + * @return string * A string containing a URL that may be used to access the file. * If the provided string already contains a preceding 'http', 'https', or * '/', nothing is done and the same string is returned. If a stream wrapper @@ -476,9 +482,9 @@ function file_create_url($uri) { return $GLOBALS['base_url'] . '/' . UrlHelper::encodePath($uri); } } - elseif ($scheme == 'http' || $scheme == 'https') { - // Check for HTTP so that we don't have to implement getExternalUrl() for - // the HTTP wrapper. + elseif ($scheme == 'http' || $scheme == 'https' || $scheme == 'data') { + // Check for HTTP and data URI-encoded URLs so that we don't have to + // implement getExternalUrl() for the HTTP and data schemes. return $uri; } else { diff --git a/core/modules/file/src/Tests/DownloadTest.php b/core/modules/file/src/Tests/DownloadTest.php index 92ba74046ddc5a182ca0a25bb2cbf7010712359d..9b585990b55c8edaee9d47de3badb86520536f2c 100644 --- a/core/modules/file/src/Tests/DownloadTest.php +++ b/core/modules/file/src/Tests/DownloadTest.php @@ -126,6 +126,7 @@ function testFileCreateUrl() { $this->checkUrl('public', '', $basename, $base_path . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); $this->checkUrl('private', '', $basename, $base_path . '/' . $script_path . 'system/files/' . $basename_encoded); } + $this->assertEqual(file_create_url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Generated URL matches expected URL.')); } /** diff --git a/core/modules/system/src/Tests/File/StreamWrapperTest.php b/core/modules/system/src/Tests/File/StreamWrapperTest.php index 755e98864ea8d9f97c12c66008fbab8dd72ec105..0c9721423c598a5f48f2f489f0c99378538f1ab6 100644 --- a/core/modules/system/src/Tests/File/StreamWrapperTest.php +++ b/core/modules/system/src/Tests/File/StreamWrapperTest.php @@ -72,7 +72,10 @@ function testUriFunctions() { // Test file_uri_target(). $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', 'Got a valid stream target from public://foo/bar.txt.'); + $this->assertEqual(file_uri_target('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Got a valid stream target from a data URI.')); $this->assertFalse(file_uri_target('foo/bar.txt'), 'foo/bar.txt is not a valid stream.'); + $this->assertFalse(file_uri_target('public://'), 'public:// has no target.'); + $this->assertFalse(file_uri_target('data:'), 'data: has no target.'); // Test file_build_uri() and // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath(). @@ -88,6 +91,8 @@ function testUriFunctions() { */ function testGetValidStreamScheme() { $this->assertEqual('foo', file_uri_scheme('foo://pork//chops'), 'Got the correct scheme from foo://asdf'); + $this->assertEqual('data', file_uri_scheme('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'Got the correct scheme from a data URI.'); + $this->assertFalse(file_uri_scheme('foo/bar.txt'), 'foo/bar.txt is not a valid stream.'); $this->assertTrue(file_stream_wrapper_valid_scheme(file_uri_scheme('public://asdf')), 'Got a valid stream scheme from public://asdf'); $this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), 'Did not get a valid stream scheme from foo://asdf'); } diff --git a/core/modules/system/src/Tests/Theme/FunctionsTest.php b/core/modules/system/src/Tests/Theme/FunctionsTest.php index aac2533bc601a268c8587dc1ed21a8210b12a299..c9705535798d31510131190bd828a8419a878545 100644 --- a/core/modules/system/src/Tests/Theme/FunctionsTest.php +++ b/core/modules/system/src/Tests/Theme/FunctionsTest.php @@ -382,4 +382,17 @@ function testDrupalPreRenderLinks() { $this->assertIdentical(strpos($parent_html, 'First child link'), FALSE, '"First child link" link not found.'); $this->assertIdentical(strpos($parent_html, 'Third child link'), FALSE, '"Third child link" link not found.'); } + + /** + * Tests theme_image(). + */ + function testImage() { + // Test that data URIs work with theme_image(). + $variables = array(); + $variables['uri'] = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='; + $variables['alt'] = 'Data URI image of a red dot'; + $expected = 'Data URI image of a red dot' . "\n"; + $this->assertThemeOutput('image', $variables, $expected); + } + }