[Core] Cleanup temp files in add_torrent_url

Temporary torrent files are not deleted by add_torrent_url. Not as big a
problem as with tracker icons pages but should be removed after use.

Fixed by updating the method to use async and a try..finally cleanup
block.

Perhaps could be refactored to not require temporary files and instead
store the downloaded torrent as object for passing to add_torrent_file.

Trac: https://dev.deluge-torrent.org/ticket/3167
This commit is contained in:
Calum Lind 2022-05-01 14:48:16 +01:00
parent 68c75ccc05
commit 7f0a380576
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
2 changed files with 20 additions and 19 deletions

View File

@ -518,7 +518,8 @@ class Core(component.Component):
return task.deferLater(reactor, 0, add_torrents) return task.deferLater(reactor, 0, add_torrents)
@export @export
def add_torrent_url( @maybe_coroutine
async def add_torrent_url(
self, url: str, options: dict, headers: dict = None self, url: str, options: dict, headers: dict = None
) -> 'defer.Deferred[Optional[str]]': ) -> 'defer.Deferred[Optional[str]]':
"""Adds a torrent from a URL. Deluge will attempt to fetch the torrent """Adds a torrent from a URL. Deluge will attempt to fetch the torrent
@ -534,26 +535,24 @@ class Core(component.Component):
""" """
log.info('Attempting to add URL %s', url) log.info('Attempting to add URL %s', url)
def on_download_success(filename): tmp_fd, tmp_file = tempfile.mkstemp(prefix='deluge_url.', suffix='.torrent')
# We got the file, so add it to the session try:
filename = await download_file(
url, tmp_file, headers=headers, force_filename=True
)
except Exception:
log.error('Failed to add torrent from URL %s', url)
raise
else:
with open(filename, 'rb') as _file: with open(filename, 'rb') as _file:
data = _file.read() data = _file.read()
try:
os.remove(filename)
except OSError as ex:
log.warning('Could not remove temp file: %s', ex)
return self.add_torrent_file(filename, b64encode(data), options) return self.add_torrent_file(filename, b64encode(data), options)
finally:
def on_download_fail(failure): try:
# Log the error and pass the failure onto the client
log.error('Failed to add torrent from URL %s', url)
return failure
tmp_fd, tmp_file = tempfile.mkstemp(prefix='deluge_url.', suffix='.torrent')
os.close(tmp_fd) os.close(tmp_fd)
d = download_file(url, tmp_file, headers=headers, force_filename=True) os.remove(tmp_file)
d.addCallbacks(on_download_success, on_download_fail) except OSError as ex:
return d log.warning(f'Unable to delete temp file {tmp_file}: , {ex}')
@export @export
def add_torrent_magnet(self, uri: str, options: dict) -> str: def add_torrent_magnet(self, uri: str, options: dict) -> str:

View File

@ -4,6 +4,7 @@
# See LICENSE for more details. # See LICENSE for more details.
# #
import os
from base64 import b64encode from base64 import b64encode
from hashlib import sha1 as sha from hashlib import sha1 as sha
@ -175,7 +176,7 @@ class TestCore(BaseTestCase):
self.core.add_torrent_file(filename, False, options) self.core.add_torrent_file(filename, False, options)
@pytest_twisted.inlineCallbacks @pytest_twisted.inlineCallbacks
def test_add_torrent_url(self): def test_add_torrent_url(self, mock_mkstemp):
url = ( url = (
'http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent' 'http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent'
% self.listen_port % self.listen_port
@ -185,6 +186,7 @@ class TestCore(BaseTestCase):
torrent_id = yield self.core.add_torrent_url(url, options) torrent_id = yield self.core.add_torrent_url(url, options)
assert torrent_id == info_hash assert torrent_id == info_hash
assert not os.path.isfile(mock_mkstemp[1])
@pytest_twisted.ensureDeferred @pytest_twisted.ensureDeferred
async def test_add_torrent_url_with_cookie(self): async def test_add_torrent_url_with_cookie(self):