Fix id sanitization in filenames

Closes #415
This commit is contained in:
pukkandan 2021-06-17 02:15:57 +05:30
parent e858a9d6d3
commit 9fea350f0d
No known key found for this signature in database
GPG Key ID: 0F00D95A001F4698
3 changed files with 17 additions and 6 deletions

View File

@ -664,15 +664,15 @@ class TestYoutubeDL(unittest.TestCase):
} }
def test_prepare_outtmpl_and_filename(self): def test_prepare_outtmpl_and_filename(self):
def test(tmpl, expected, **params): def test(tmpl, expected, *, info=None, **params):
params['outtmpl'] = tmpl params['outtmpl'] = tmpl
ydl = YoutubeDL(params) ydl = YoutubeDL(params)
ydl._num_downloads = 1 ydl._num_downloads = 1
self.assertEqual(ydl.validate_outtmpl(tmpl), None) self.assertEqual(ydl.validate_outtmpl(tmpl), None)
outtmpl, tmpl_dict = ydl.prepare_outtmpl(tmpl, self.outtmpl_info) outtmpl, tmpl_dict = ydl.prepare_outtmpl(tmpl, info or self.outtmpl_info)
out = outtmpl % tmpl_dict out = outtmpl % tmpl_dict
fname = ydl.prepare_filename(self.outtmpl_info) fname = ydl.prepare_filename(info or self.outtmpl_info)
if callable(expected): if callable(expected):
self.assertTrue(expected(out)) self.assertTrue(expected(out))
@ -700,6 +700,15 @@ class TestYoutubeDL(unittest.TestCase):
test('%(width)06d.%%(ext)s', 'NA.%(ext)s') test('%(width)06d.%%(ext)s', 'NA.%(ext)s')
test('%%(width)06d.%(ext)s', '%(width)06d.mp4') test('%%(width)06d.%(ext)s', '%(width)06d.mp4')
# ID sanitization
test('%(id)s', '_abcd', info={'id': '_abcd'})
test('%(some_id)s', '_abcd', info={'some_id': '_abcd'})
test('%(formats.0.id)s', '_abcd', info={'formats': [{'id': '_abcd'}]})
test('%(id)s', '-abcd', info={'id': '-abcd'})
test('%(id)s', '.abcd', info={'id': '.abcd'})
test('%(id)s', 'ab__cd', info={'id': 'ab__cd'})
test('%(id)s', ('ab:cd', 'ab -cd'), info={'id': 'ab:cd'})
# Invalid templates # Invalid templates
self.assertTrue(isinstance(YoutubeDL.validate_outtmpl('%'), ValueError)) self.assertTrue(isinstance(YoutubeDL.validate_outtmpl('%'), ValueError))
self.assertTrue(isinstance(YoutubeDL.validate_outtmpl('%(title)'), ValueError)) self.assertTrue(isinstance(YoutubeDL.validate_outtmpl('%(title)'), ValueError))

View File

@ -934,7 +934,7 @@ class YoutubeDL(object):
fmt = outer_mobj.group('format') fmt = outer_mobj.group('format')
mobj = re.match(INTERNAL_FORMAT_RE, key) mobj = re.match(INTERNAL_FORMAT_RE, key)
if mobj is None: if mobj is None:
value, default = None, na value, default, mobj = None, na, {'fields': ''}
else: else:
mobj = mobj.groupdict() mobj = mobj.groupdict()
default = mobj['default'] if mobj['default'] is not None else na default = mobj['default'] if mobj['default'] is not None else na
@ -944,7 +944,6 @@ class YoutubeDL(object):
fmt = '0{:d}d'.format(field_size_compat_map[key]) fmt = '0{:d}d'.format(field_size_compat_map[key])
value = default if value is None else value value = default if value is None else value
key += '\0%s' % fmt
if fmt == 'c': if fmt == 'c':
value = compat_str(value) value = compat_str(value)
@ -962,7 +961,8 @@ class YoutubeDL(object):
# So we convert it to repr first # So we convert it to repr first
value, fmt = repr(value), '%ss' % fmt[:-1] value, fmt = repr(value), '%ss' % fmt[:-1]
if fmt[-1] in 'csr': if fmt[-1] in 'csr':
value = sanitize(key, value) value = sanitize(mobj['fields'].split('.')[-1], value)
key += '\0%s' % fmt
TMPL_DICT[key] = value TMPL_DICT[key] = value
return '%({key}){fmt}'.format(key=key, fmt=fmt) return '%({key}){fmt}'.format(key=key, fmt=fmt)

View File

@ -6241,6 +6241,8 @@ def traverse_obj(obj, keys, *, casesense=True, is_user_input=False, traverse_str
if is_user_input: if is_user_input:
key = (int_or_none(key) if ':' not in key key = (int_or_none(key) if ':' not in key
else slice(*map(int_or_none, key.split(':')))) else slice(*map(int_or_none, key.split(':'))))
if key is None:
return None
if not isinstance(obj, (list, tuple)): if not isinstance(obj, (list, tuple)):
if traverse_string: if traverse_string:
obj = compat_str(obj) obj = compat_str(obj)