From 7b755a41a1046e031015130971c9b9cc8885176e Mon Sep 17 00:00:00 2001 From: Pengyu Chen Date: Tue, 6 Aug 2019 15:18:59 +0100 Subject: [PATCH] Added: Properly handling quoted passwords in FEED_URI for FTP --- scrapy/extensions/feedexport.py | 4 ++-- tests/test_feedexport.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/scrapy/extensions/feedexport.py b/scrapy/extensions/feedexport.py index d35551fdd..ce2846eba 100644 --- a/scrapy/extensions/feedexport.py +++ b/scrapy/extensions/feedexport.py @@ -11,7 +11,7 @@ import posixpath from tempfile import NamedTemporaryFile from datetime import datetime import six -from six.moves.urllib.parse import urlparse +from six.moves.urllib.parse import urlparse, unquote from ftplib import FTP from zope.interface import Interface, implementer @@ -162,7 +162,7 @@ class FTPFeedStorage(BlockingFeedStorage): self.host = u.hostname self.port = int(u.port or '21') self.username = u.username - self.password = u.password + self.password = unquote(u.password) self.path = u.path self.use_active_mode = use_active_mode diff --git a/tests/test_feedexport.py b/tests/test_feedexport.py index c5063253a..f32ac2a4b 100644 --- a/tests/test_feedexport.py +++ b/tests/test_feedexport.py @@ -6,7 +6,8 @@ import warnings from io import BytesIO import tempfile import shutil -from six.moves.urllib.parse import urljoin, urlparse +import string +from six.moves.urllib.parse import urljoin, urlparse, quote from six.moves.urllib.request import pathname2url from zope.interface.verify import verifyObject @@ -98,6 +99,12 @@ class FTPFeedStorageTest(unittest.TestCase): verifyObject(IFeedStorage, st) return self._assert_stores(st, path) + def test_uri_auth_quote(self): + # RFC3986: 3.2.1. User Information + pw_quoted = quote(string.punctuation, safe='') + st = FTPFeedStorage('ftp://foo:%s@example.com/some_path' % pw_quoted) + self.assertEqual(st.password, string.punctuation) + @defer.inlineCallbacks def _assert_stores(self, storage, path): spider = self.get_test_spider()