From ebe889a6635ae4ee33186155912a8931bac1692d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gra=C3=B1a?= Date: Sat, 23 May 2015 20:50:30 -0300 Subject: [PATCH] Unquote request path before passing to FTPClient, it already escape paths --- scrapy/core/downloader/handlers/ftp.py | 4 ++-- tests/test_downloader_handlers.py | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/scrapy/core/downloader/handlers/ftp.py b/scrapy/core/downloader/handlers/ftp.py index d96e37fef..93fa0a3a7 100644 --- a/scrapy/core/downloader/handlers/ftp.py +++ b/scrapy/core/downloader/handlers/ftp.py @@ -30,7 +30,7 @@ In case of status 200 request, response.headers will come with two keys: import re from io import BytesIO -from six.moves.urllib.parse import urlparse +from six.moves.urllib.parse import urlparse, unquote from twisted.internet import reactor from twisted.protocols.ftp import FTPClient, CommandFailed @@ -73,7 +73,7 @@ class FTPDownloadHandler(object): request.meta["ftp_password"], passive=request.meta.get("ftp_passive", 1)) return creator.connectTCP(parsed_url.hostname, parsed_url.port or 21).addCallback(self.gotClient, - request, parsed_url.path) + request, unquote(parsed_url.path)) def gotClient(self, client, request, filepath): self.client = client diff --git a/tests/test_downloader_handlers.py b/tests/test_downloader_handlers.py index df038aa88..c814de307 100644 --- a/tests/test_downloader_handlers.py +++ b/tests/test_downloader_handlers.py @@ -511,7 +511,9 @@ class FTPTestCase(unittest.TestCase): os.mkdir(self.directory) userdir = os.path.join(self.directory, self.username) os.mkdir(userdir) - FilePath(userdir).child('file.txt').setContent("I have the power!") + fp = FilePath(userdir) + fp.child('file.txt').setContent("I have the power!") + fp.child('file with spaces.txt').setContent("Moooooooooo power!") # setup server realm = FTPRealm(anonymousRoot=self.directory, userHome=self.directory) @@ -547,6 +549,19 @@ class FTPTestCase(unittest.TestCase): self.assertEqual(r.headers, {'Local Filename': [''], 'Size': ['17']}) return self._add_test_callbacks(d, _test) + def test_ftp_download_path_with_spaces(self): + request = Request( + url="ftp://127.0.0.1:%s/file with spaces.txt" % self.portNum, + meta={"ftp_user": self.username, "ftp_password": self.password} + ) + d = self.download_handler.download_request(request, None) + + def _test(r): + self.assertEqual(r.status, 200) + self.assertEqual(r.body, 'Moooooooooo power!') + self.assertEqual(r.headers, {'Local Filename': [''], 'Size': ['18']}) + return self._add_test_callbacks(d, _test) + def test_ftp_download_notexist(self): request = Request(url="ftp://127.0.0.1:%s/notexist.txt" % self.portNum, meta={"ftp_user": self.username, "ftp_password": self.password})