Bug #79572
closedFix relative URL Path in CSS may fail if svg data inside url()
Added by René Rossi almost 8 years ago. Updated 4 months ago.
0%
Description
Hi,
if there is some SVG Date inside of an background the regexp in line 631 on ResourceCompressor.php seems to fail.
So if there are some thing like:
background-image:url("data:image/svg+xml;charset=utf8,%3Csvg
width='396' height='348' viewBox='0 0 396 348'
xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Csvg
id='application_avi' data-name='Layer 1' viewBox='0 0 48 48'
width='48' height='48' x='348'
y='144'%3E%3Cdefs%3E%3Cstyle%3E.aacls-1%7Bfill:none%7D.aacls-2%7Bclip-path:url('%23aaclip-path')%7D.aacls-3%7Bfill:%23f6f6f6%7D.aacls-4%7Bfill:%23e0e0e0%7D.aacls-5%7Bclip-path:url('%23aaclip-path-2')%7D.aacls-6%7Bfill:%234c8fc3%7D.aacls-7%7Bclip-path:url('%23aaclip-path-3')");
the regular expression only returns the inner urls and prepends them.
compare here http://www.phpliveregex.com/p/iLr
i think something like this should work better here: http://www.phpliveregex.com/p/iMl
Files
Updated by Riccardo De Contardi over 6 years ago
This issue is still present in 9.4-dev (latest master);
My test procedure:
- include the css attached in TS Setup:
page.includeCSS{ file1 = fileadmin/test.css }
Results:¶
1) with
config{ config.concatenateCss = 0 config.compressCss = 0 }
the svg background is visible
2) Using either config.concatenateCss = 1
or config.compressCss = 1
the background svg is altered in this way and becomes invisible:
data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url('../../../fileadmin/%23gradient')' x='0' y='0' width='100%' height='100%'/></svg>
the problem is the "transformation" of url('../../../fileadmin/%23gradient')
Updated by Markus Klein over 6 years ago
The suggested regex is way too greedy.
The current regex /url(\\(\\s*["']?(?!\\/)([^"']+)["']?\\s*\\))/iU
is tailored to detect non-absolute paths.
It has never been constructed for data-values and even less for "recursive" usage of "url()".
Updated by Markus Klein over 6 years ago
- Category changed from Caching to Backend API
- Status changed from New to Accepted
- Priority changed from Must have to Should have
- Complexity set to medium
Updated by René Rossi over 6 years ago
Sure it´s to greedy?
i think it is applied to the data url only.
At the moment i use this little override to fix the problem.
class ResourceCompressor extends \TYPO3\CMS\Core\Resource\ResourceCompressor {
/**
* PIX: Fixes the relative paths inside of url() references in CSS files
* respecting inner data of url()
*
* @author René Rossi<rossi@pixelproduction.de>
* @param string $contents Data to process
* @param string $oldDir Directory of the original file, relative to TYPO3_mainDir
* @return string Processed data
*/
protected function cssFixRelativeUrlPaths($contents, $oldDir)
{
$mainDir = TYPO3_MODE === 'BE' ? TYPO3_mainDir : '';
$newDir = '../../' . $mainDir . $oldDir;
// Replace "url()" paths
if (stripos($contents, 'url') !== false) {
$regex = "/[\s:]?url\(\s*([\"']?(.*)[\"']?)\s*\)/i";
$contents = $this->findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, '(\'|\')');
}
// Replace "@import" paths
if (stripos($contents, '@import') !== false) {
$regex = '/@import\\s*(["\']?(?!\\/)([^"\']+)["\']?)/i';
$contents = $this->findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, '"|"');
}
return $contents;
}
}
Updated by Markus Timtner over 5 years ago
- Priority changed from Should have to Must have
- Estimated time set to 1.00 h
- TYPO3 Version changed from 7 to 9
THe problem ist still present in v9.5.5,
it also affects inline anchors in the clip-path property like:
.clip-me {
/* referencing path from an inline SVG <clipPath> */
clip-path: url(#c1);
}
(see https://css-tricks.com/almanac/properties/c/clip/ for details)
Updated by Markus Klein over 5 years ago
René Rossi wrote:
Sure it´s to greedy?
i think it is applied to the data url only.
At the moment i use this little override to fix the problem.
[...]
The regex is applied on the complete CSS content. So you dot-star in the middle is the greedy point, where the regex extends way beyond its scope.
One example: Try this single line with your regex background-image: url("https://mdn.mozillademos.org/files/11991/startransparent.gif"),url("https://mdn.mozillademos.org/files/7693/catfront.png");
The regex swallows the second url() of course.
Updated by René Rossi over 5 years ago
Markus Klein wrote:
René Rossi wrote:
Sure it´s to greedy?
i think it is applied to the data url only.
At the moment i use this little override to fix the problem.
[...]
The regex is applied on the complete CSS content. So you dot-star in the middle is the greedy point, where the regex extends way beyond its scope.
One example: Try this single line with your regexbackground-image: url("https://mdn.mozillademos.org/files/11991/startransparent.gif"),url("https://mdn.mozillademos.org/files/7693/catfront.png");
The regex swallows the second url() of course.
Wow, this bug report is over 2 years old and original applied to T3 V7.6.
Im sure the provided solution is not the optimal solution at all, but...
Your example above does'nt work with the current expression also, as only the first url seems to be noticed.
array(3
0 => url("https://mdn.mozillademos.org/files/11991/startransparent.gif")
1 => ("https://mdn.mozillademos.org/files/11991/startransparent.gif")
2 => https://mdn.mozillademos.org/files/11991/startransparent.gif
)
But i'm sure you be able to replace the .* by a [^\)]+ to get the same as before but that does'nt fit to the whole needs.
If I had the time to solve this problem with all its variants, then I would have done it.
So it's a bug report to (may be the author of the functionality) to see what we get.
And one more, the last question is'nt initiated by me.
Updated by Ge Rie over 2 years ago
- TYPO3 Version changed from 9 to 11
Markus Timtner wrote in #note-7:
THe problem ist still present in v9.5.5,
it also affects inline anchors in the clip-path property like:[...]
(see https://css-tricks.com/almanac/properties/c/clip/ for details)
This is still a problem in TYPO3 11.
The output from something like this:
clip-path: url(#c1);
Is translated to:
clip-path: url('../../../typo3conf/ext/myextension/Resources/Public/css/#c1');
So inline SVG can't be used. It works when you link to a svg file though
clip-path: url(/typo3conf/ext/myextension/Resources/Public/svg/imageclipform.svg#c1);
Updated by Thomas Helmrich about 2 years ago
hi,
there is an check in RelativeCssPathFixer.php:71
that seems like it should prevent this issue.
// we must not rewrite paths containing ":" or "url(", e.g. data URIs (see RFC 2397)
if (!str_contains($match, ':') && !preg_match('/url\\s*\\(/i', $match)) {
I did some debugging, in case of background: url("data:image/... fill='url('%23a')'...
the $match
is just %23a
, so it proceeds with 'fixing' to a relative path.
Updated by Timo Klinge over 1 year ago
Hi,
I encountered the same problem, when I implemented an inline-svg-filter on our website.
filter: url(#rounded-box-filter);
<svg style="visibility: hidden; position: absolute;" width="0" height="0">
<defs>
<filter id="rounded-box-filter">
...
</filter>
</defs>
</svg>
While everything worked on our test- and staging-server, on the liveserver the URL was converted from url(#rounded-box-filter)
to url(../../../typo3conf/ext/{package}/Resources/Public/CSS/#rounded-box-filter)
.
It turned out that the problem only occurs when concatenateCss = 1
or compressCss = 1
is set.
My workaround was to use a Typo3-AssetCollector directly in the html-file instead. For me it is not clear why this bug is still existent in Typo3-v11.
<f:asset.css identifier="rounded-box-style" priority="true">
...
filter: url(#rounded-box-filter);
...
</f:asset.css>
Updated by Garvin Hicking 4 months ago
- Status changed from Accepted to Closed
Following along the reason to close #75127 I would like to ask if you agree that we could close this issue, too.
Todays recommendation is to try to not rely on compression/concatenation through these TypoScript options, but either use distinct bundlers or rely on HTTP/2 multiplexing. There are several edge-case scenarios at play here, which did not really gain traction to be fixed in the many years now, so it's unlikely moving forward this would change.
I hope you can understand the reasoning of this and an team discussion about this and agree. If not, please let me know and we'll see how to proceed with this. :-)