Fixed #25283 -- Fixed collectstatic crash if a URL contains a fragment with a path.
A @font-face declaration may contain a fragment that looks like a relative path, e.g. @font-face { src: url('../fonts/font.svg#../path/like/fragment'); } In this case, an incorrect path was passed to the storage backend, which raised an error that caused collectstatic to crash.
This commit is contained in:
parent
ce4914eab4
commit
7624fdb9f8
|
@ -166,12 +166,15 @@ class HashedFilesMixin(object):
|
|||
name_parts = name.split(os.sep)
|
||||
# Using posix normpath here to remove duplicates
|
||||
url = posixpath.normpath(url)
|
||||
url_parts = url.split('/')
|
||||
parent_level, sub_level = url.count('..'), url.count('/')
|
||||
if url.startswith('/'):
|
||||
# Strip off the fragment so that a path-like fragment won't confuse
|
||||
# the lookup.
|
||||
url_path, fragment = urldefrag(url)
|
||||
url_parts = url_path.split('/')
|
||||
parent_level, sub_level = url_path.count('..'), url_path.count('/')
|
||||
if url_path.startswith('/'):
|
||||
sub_level -= 1
|
||||
url_parts = url_parts[1:]
|
||||
if parent_level or not url.startswith('/'):
|
||||
if parent_level or not url_path.startswith('/'):
|
||||
start, end = parent_level + 1, parent_level
|
||||
else:
|
||||
if sub_level:
|
||||
|
@ -183,7 +186,9 @@ class HashedFilesMixin(object):
|
|||
joined_result = '/'.join(name_parts[:-start] + url_parts[end:])
|
||||
hashed_url = self.url(unquote(joined_result), force=True)
|
||||
file_name = hashed_url.split('/')[-1:]
|
||||
relative_url = '/'.join(url.split('/')[:-1] + file_name)
|
||||
relative_url = '/'.join(url_path.split('/')[:-1] + file_name)
|
||||
if fragment:
|
||||
relative_url += '?#%s' % fragment if '?#' in url else '#%s' % fragment
|
||||
|
||||
# Return the hashed version to the file
|
||||
return template % unquote(relative_url)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@font-face {
|
||||
src: url('fonts/font.eot?#iefix') format('embedded-opentype'),
|
||||
url('fonts/font.svg#webfontIyfZbseF') format('svg');
|
||||
url('fonts/font.svg#../path/to/fonts/font.svg') format('svg');
|
||||
url('data:font/woff;charset=utf-8;base64,d09GRgABAAAAADJoAA0AAAAAR2QAAQAAAAAAAAAAAAA');
|
||||
}
|
||||
div {
|
||||
|
|
|
@ -85,11 +85,12 @@ class TestHashedFiles(object):
|
|||
|
||||
def test_path_with_querystring_and_fragment(self):
|
||||
relpath = self.hashed_file_path("cached/css/fragments.css")
|
||||
self.assertEqual(relpath, "cached/css/fragments.75433540b096.css")
|
||||
self.assertEqual(relpath, "cached/css/fragments.ef92012a8c16.css")
|
||||
with storage.staticfiles_storage.open(relpath) as relfile:
|
||||
content = relfile.read()
|
||||
self.assertIn(b'fonts/font.a4b0478549d0.eot?#iefix', content)
|
||||
self.assertIn(b'fonts/font.b8d603e42714.svg#webfontIyfZbseF', content)
|
||||
self.assertIn(b'fonts/font.b8d603e42714.svg#../path/to/fonts/font.svg', content)
|
||||
self.assertIn(b'data:font/woff;charset=utf-8;base64,d09GRgABAAAAADJoAA0AAAAAR2QAAQAAAAAAAAAAAAA', content)
|
||||
self.assertIn(b'#default#VML', content)
|
||||
|
||||
|
|
Loading…
Reference in New Issue