Fix handling of multi-line FTP responses

This commit is contained in:
David Shea 2018-08-02 10:24:00 -04:00
parent 1ea8cbf335
commit c74375273f
5 changed files with 173 additions and 2 deletions

View File

@ -0,0 +1,22 @@
diff -purN requests-ftp-0.3.1.orig/requests_ftp/ftp.py requests-ftp-0.3.1/requests_ftp/ftp.py
--- requests-ftp-0.3.1.orig/requests_ftp/ftp.py 2015-08-13 16:57:27.000000000 -0400
+++ requests-ftp-0.3.1/requests_ftp/ftp.py 2018-08-02 10:13:15.801731787 -0400
@@ -99,7 +99,7 @@ def build_text_response(request, data, c
def build_binary_response(request, data, code):
'''Build a response for data whose encoding is unknown.'''
- return build_response(request, data, code, None)
+ return build_response(request, data, code, None)
def build_response(request, data, code, encoding):
@@ -113,7 +113,8 @@ def build_response(request, data, code,
response.raw = data
response.url = request.url
response.request = request
- response.status_code = int(code.split()[0])
+ last_valid_line_from_code = [line for line in code.split('\n') if line][-1]
+ response.status_code = int(last_valid_line_from_code.split()[0])
if hasattr(data, "content_len"):
response.headers['Content-Length'] = str(data.content_len)

View File

@ -0,0 +1,58 @@
diff -purN requests-ftp-0.3.1.orig/requests_ftp/ftp.py requests-ftp-0.3.1/requests_ftp/ftp.py
--- requests-ftp-0.3.1.orig/requests_ftp/ftp.py 2018-08-02 10:13:15.801731787 -0400
+++ requests-ftp-0.3.1/requests_ftp/ftp.py 2018-08-02 10:14:20.633933095 -0400
@@ -9,6 +9,7 @@ from io import BytesIO
import cgi
import os
import socket
+import logging
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
from requests.exceptions import RequestException
@@ -102,6 +103,35 @@ def build_binary_response(request, data,
return build_response(request, data, code, None)
+def get_status_code_from_code_response(code):
+ '''
+ The idea is to handle complicated code response (even multi lines).
+ We get the status code in two ways:
+ - extracting the code from the last valid line in the response
+ - getting it from the 3first digits in the code
+ After a comparaison between the two values,
+ we can safely set the code or raise a warning.
+
+ Examples:
+ - get_code('200 Welcome') == 200
+
+ - multi_line_code = '226-File successfully transferred\n226 0.000 seconds'
+ get_code(multi_line_code) == 226
+
+ - multi_line_with_code_conflits = '200-File successfully transferred\n226 0.000 seconds'
+ get_code(multi_line_with_code_conflits) == 226
+ '''
+ last_valid_line_from_code = [line for line in code.split('\n') if line][-1]
+ status_code_from_last_line = int(last_valid_line_from_code.split()[0])
+ status_code_from_first_digits = int(code[:3])
+ if status_code_from_last_line != status_code_from_first_digits:
+ logging.warning(
+ 'Status code seems to be non consistant.\n'
+ 'Code received: %d, extracted: %d and %d' % (
+ code, status_code_from_last_line, status_code_from_first_digits))
+ return status_code_from_last_line
+
+
def build_response(request, data, code, encoding):
'''Builds a response object from the data returned by ftplib, using the
specified encoding.'''
@@ -113,8 +143,8 @@ def build_response(request, data, code,
response.raw = data
response.url = request.url
response.request = request
- last_valid_line_from_code = [line for line in code.split('\n') if line][-1]
- response.status_code = int(last_valid_line_from_code.split()[0])
+ response.status_code = get_status_code_from_code_response(code)
+
if hasattr(data, "content_len"):
response.headers['Content-Length'] = str(data.content_len)

View File

@ -0,0 +1,48 @@
diff -purN requests-ftp-0.3.1.orig/requests_ftp/ftp.py requests-ftp-0.3.1/requests_ftp/ftp.py
--- requests-ftp-0.3.1.orig/requests_ftp/ftp.py 2018-08-02 10:14:20.633933095 -0400
+++ requests-ftp-0.3.1/requests_ftp/ftp.py 2018-08-02 10:15:20.491042199 -0400
@@ -108,26 +108,36 @@ def get_status_code_from_code_response(c
The idea is to handle complicated code response (even multi lines).
We get the status code in two ways:
- extracting the code from the last valid line in the response
- - getting it from the 3first digits in the code
- After a comparaison between the two values,
+ - getting it from the 3 first digits in the code
+ After a comparison between the two values,
we can safely set the code or raise a warning.
Examples:
- - get_code('200 Welcome') == 200
+ - get_status_code_from_code_response('200 Welcome') == 200
- multi_line_code = '226-File successfully transferred\n226 0.000 seconds'
- get_code(multi_line_code) == 226
+ get_status_code_from_code_response(multi_line_code) == 226
- - multi_line_with_code_conflits = '200-File successfully transferred\n226 0.000 seconds'
- get_code(multi_line_with_code_conflits) == 226
+ - multi_line_with_code_conflicts = '200-File successfully transferred\n226 0.000 seconds'
+ get_status_code_from_code_response(multi_line_with_code_conflicts) == 226
+
+ For more detail see RFC 959, page 36, on multi-line responses:
+ https://www.ietf.org/rfc/rfc959.txt
+
+ "Thus the format for multi-line replies is that the first line
+ will begin with the exact required reply code, followed
+ immediately by a Hyphen, "-" (also known as Minus), followed by
+ text. The last line will begin with the same code, followed
+ immediately by Space <SP>, optionally some text, and the Telnet
+ end-of-line code."
'''
last_valid_line_from_code = [line for line in code.split('\n') if line][-1]
status_code_from_last_line = int(last_valid_line_from_code.split()[0])
status_code_from_first_digits = int(code[:3])
if status_code_from_last_line != status_code_from_first_digits:
logging.warning(
- 'Status code seems to be non consistant.\n'
- 'Code received: %d, extracted: %d and %d' % (
+ 'FTP response status code seems to be inconsistent.\n'
+ 'Code received: {0}, extracted: {1} and {2}'.format(
code, status_code_from_last_line, status_code_from_first_digits))
return status_code_from_last_line

View File

@ -0,0 +1,28 @@
diff -purN requests-ftp-0.3.1.orig/requests_ftp/ftp.py requests-ftp-0.3.1/requests_ftp/ftp.py
--- requests-ftp-0.3.1.orig/requests_ftp/ftp.py 2018-08-02 10:15:20.491042199 -0400
+++ requests-ftp-0.3.1/requests_ftp/ftp.py 2018-08-02 10:16:16.588081626 -0400
@@ -44,6 +44,7 @@ class FTPSession(requests.Session):
'''Sends an FTP SIZE. Returns a decimal number.'''
return self.request('SIZE', url, **kwargs)
+log = logging.getLogger(__name__)
def monkeypatch_session():
'''Monkeypatch Requests Sessions to provide all the helper
@@ -135,10 +136,13 @@ def get_status_code_from_code_response(c
status_code_from_last_line = int(last_valid_line_from_code.split()[0])
status_code_from_first_digits = int(code[:3])
if status_code_from_last_line != status_code_from_first_digits:
- logging.warning(
+ log.warning(
'FTP response status code seems to be inconsistent.\n'
- 'Code received: {0}, extracted: {1} and {2}'.format(
- code, status_code_from_last_line, status_code_from_first_digits))
+ 'Code received: %s, extracted: %s and %s',
+ code,
+ status_code_from_last_line,
+ status_code_from_first_digits
+ )
return status_code_from_last_line

View File

@ -16,7 +16,7 @@
Name: python-%{srcname}
Version: 0.3.1
Release: 12%{?dist}
Release: 13%{?dist}
Summary: FTP transport adapter for python-requests
License: ASL 2.0
@ -25,6 +25,18 @@ Source0: https://pypi.python.org/packages/source/r/%{srcname}/%{srcname}-
BuildArch: noarch
# from https://github.com/Lukasa/requests-ftp/pull/28, handle multi-line responses
# from 4090846
Patch1: PR28-01-Adding-2-tests-and-updated-statud_code-build.patch
# from 4f6a9f5
Patch2: PR28-02-Adding-code-3-to-retr4ieve-status_code.patch
# from 3fb2700
Patch3: PR28-03-fix-warning-in-interpreting-ftp-status-codes-minor-d.patch
# 2caa427 is only test updates, tests not in pypi tarball
# from 7321ab3
Patch5: PR28-05-Improve-logging-in-status-code-extraction.patch
%description
Requests-FTP is an implementation of a very stupid FTP transport adapter for
use with the awesome Requests Python library.
@ -64,7 +76,7 @@ This is the Python 3 version of the transport adapter module.
%endif
%prep
%autosetup -n %{srcname}-%{version}
%autosetup -n %{srcname}-%{version} -p1
rm -rf requests_ftp.egg-info
%build
@ -102,6 +114,9 @@ rm -rf requests_ftp.egg-info
%endif
%changelog
* Thu Aug 2 2018 David Shea <dshea@redhat.com> - 0.3.1-13
- Fix handling of multi-line FTP responses
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.1-12
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild