From fcc13f454b565552a6b62f278e1e32c225fd715c Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Wed, 13 Jul 2011 22:38:19 +0100 Subject: [PATCH] Fix torrent file and folder renaming issues Adds `sanitize_filepath` for use before passing to libtorrent rename_file --- deluge/core/torrent.py | 29 +++++++++++++++++++++++++++-- deluge/tests/test_core.py | 16 ++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index 22149dfe7..e5b71c6f6 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -51,6 +51,31 @@ TORRENT_STATE = deluge.common.TORRENT_STATE log = logging.getLogger(__name__) +def sanitize_filepath(filepath, folder=False): + """ + Returns a sanitized filepath to pass to libotorrent rename_file(). + The filepath will have backslashes substituted along with whitespace + padding and duplicate slashes stripped. If `folder` is True a trailing + slash is appended to the returned filepath. + """ + def clean_filename(filename): + filename = filename.strip() + if filename.replace('.', '') == '': + return '' + return filename + + if '\\' in filepath or '/' in filepath: + folderpath = filepath.replace('\\', '/').split('/') + folderpath = [clean_filename(x) for x in folderpath] + newfilepath = '/'.join(filter(None, folderpath)) + else: + newfilepath = clean_filename(filepath) + + if folder is True: + return newfilepath + '/' + else: + return newfilepath + class TorrentOptions(dict): def __init__(self): config = ConfigManager("core.conf").config @@ -955,6 +980,7 @@ class Torrent(object): """Renames files in the torrent. 'filenames' should be a list of (index, filename) pairs.""" for index, filename in filenames: + filename = sanitize_filepath(filename) self.handle.rename_file(index, filename.encode("utf-8")) def rename_folder(self, folder, new_folder): @@ -965,8 +991,7 @@ class Torrent(object): log.error("Attempting to rename a folder with an invalid folder name: %s", new_folder) return - # Make sure the new folder path is nice and has a trailing slash - new_folder = os.path.normpath(new_folder) + "/" + new_folder = sanitize_filepath(new_folder, folder=True) wait_on_folder = (folder, new_folder, []) for f in self.get_files(): diff --git a/deluge/tests/test_core.py b/deluge/tests/test_core.py index 751851325..4c4f16f51 100644 --- a/deluge/tests/test_core.py +++ b/deluge/tests/test_core.py @@ -185,3 +185,19 @@ class CoreTestCase(unittest.TestCase): d.addCallback(result) return d + + def test_sanitize_filepath(self): + pathlist = { + '\\backslash\\path\\' : 'backslash/path', + ' single_file ': 'single_file', + '..' : '', + '/../..../': '', + ' Def ////ad./ / . . /b d /file': 'Def/ad./. ./b d/file', + '/ test /\\.. /.file/': 'test/.file', + 'mytorrent/subfold/file1': 'mytorrent/subfold/file1', + 'Torrent/folder/': 'Torrent/folder', + } + + for key in pathlist: + self.assertEquals(deluge.core.torrent.sanitize_filepath(key, folder=False), pathlist[key]) + self.assertEquals(deluge.core.torrent.sanitize_filepath(key, folder=True), pathlist[key] + '/')