diff --git a/nyaa/backend.py b/nyaa/backend.py index 5257f28..87caf00 100644 --- a/nyaa/backend.py +++ b/nyaa/backend.py @@ -100,7 +100,9 @@ def handle_torrent_upload(upload_form, uploading_user=None, fromAPI=False): for directory in path_parts: current_directory = current_directory.setdefault(directory, {}) - current_directory[filename] = file_dict['length'] + # Don't add empty filenames (BitComet directory) + if filename: + current_directory[filename] = file_dict['length'] parsed_file_tree = utils.sorted_pathdict(parsed_file_tree) diff --git a/nyaa/forms.py b/nyaa/forms.py index 09bef8d..0f0e073 100644 --- a/nyaa/forms.py +++ b/nyaa/forms.py @@ -280,7 +280,7 @@ class TorrentFileData(object): def _validate_trackers(torrent_dict, tracker_to_check_for=None): announce = torrent_dict.get('announce') - announce_string = _validate_bytes(announce, 'announce', 'utf-8') + announce_string = _validate_bytes(announce, 'announce', test_decode='utf-8') tracker_found = tracker_to_check_for and ( announce_string.lower() == tracker_to_check_for.lower()) or False @@ -292,7 +292,7 @@ def _validate_trackers(torrent_dict, tracker_to_check_for=None): for announce in announce_list: _validate_list(announce, 'announce-list item') - announce_string = _validate_bytes(announce[0], 'announce-list item url', 'utf-8') + announce_string = _validate_bytes(announce[0], 'announce-list item url', test_decode='utf-8') if tracker_to_check_for and announce_string.lower() == tracker_to_check_for.lower(): tracker_found = True @@ -308,7 +308,7 @@ def _validate_torrent_metadata(torrent_dict): assert isinstance(info_dict, dict), 'info is not a dict' encoding_bytes = torrent_dict.get('encoding', b'utf-8') - encoding = _validate_bytes(encoding_bytes, 'encoding', 'utf-8').lower() + encoding = _validate_bytes(encoding_bytes, 'encoding', test_decode='utf-8').lower() name = info_dict.get('name') _validate_bytes(name, 'name', test_decode=encoding) @@ -330,17 +330,21 @@ def _validate_torrent_metadata(torrent_dict): path_list = file_dict.get('path') _validate_list(path_list, 'path') - for path_part in path_list: + # Validate possible directory names + for path_part in path_list[:-1]: _validate_bytes(path_part, 'path part', test_decode=encoding) + # Validate actual filename, allow b'' to specify an empty directory + _validate_bytes(path_list[-1], 'filename', check_empty=False, test_decode=encoding) else: length = info_dict.get('length') _validate_number(length, 'length', check_positive=True) -def _validate_bytes(value, name='value', test_decode=None): +def _validate_bytes(value, name='value', check_empty=True, test_decode=None): assert isinstance(value, bytes), name + ' is not bytes' - assert len(value) > 0, name + ' is empty' + if check_empty: + assert len(value) > 0, name + ' is empty' if test_decode: try: return value.decode(test_decode)