Skip to content

Commit

Permalink
Update ftplib to CPython 3.11.5
Browse files Browse the repository at this point in the history
  • Loading branch information
dvermd committed Oct 1, 2023
1 parent 9031a0a commit 0a76a9b
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 70 deletions.
55 changes: 32 additions & 23 deletions Lib/ftplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,17 @@ class error_proto(Error): pass # response does not begin with [1-5]

# The class itself
class FTP:

'''An FTP client class.
To create a connection, call the class using these arguments:
host, user, passwd, acct, timeout
host, user, passwd, acct, timeout, source_address, encoding
The first four arguments are all strings, and have default value ''.
timeout must be numeric and defaults to None if not passed,
meaning that no timeout will be set on any ftp socket(s)
The parameter ´timeout´ must be numeric and defaults to None if not
passed, meaning that no timeout will be set on any ftp socket(s).
If a timeout is passed, then this is now the default timeout for all ftp
socket operations for this instance.
The last parameter is the encoding of filenames, which defaults to utf-8.
Then use self.connect() with optional host and port argument.
Expand All @@ -102,15 +102,19 @@ class FTP:
sock = None
file = None
welcome = None
passiveserver = 1
encoding = "latin-1"
passiveserver = True
# Disables https://bugs.python.org/issue43285 security if set to True.
trust_server_pasv_ipv4_address = False

# Initialization method (called by class instantiation).
# Initialize host to localhost, port to standard ftp port
# Optional arguments are host (for connect()),
# and user, passwd, acct (for login())
def __init__(self, host='', user='', passwd='', acct='',
timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None, *,
encoding='utf-8'):
"""Initialization method (called by class instantiation).
Initialize host to localhost, port to standard ftp port.
Optional arguments are host (for connect()),
and user, passwd, acct (for login()).
"""
self.encoding = encoding
self.source_address = source_address
self.timeout = timeout
if host:
Expand Down Expand Up @@ -146,6 +150,8 @@ def connect(self, host='', port=0, timeout=-999, source_address=None):
self.port = port
if timeout != -999:
self.timeout = timeout
if self.timeout is not None and not self.timeout:
raise ValueError('Non-blocking socket (timeout=0) is not supported')
if source_address is not None:
self.source_address = source_address
sys.audit("ftplib.connect", self, self.host, self.port)
Expand Down Expand Up @@ -316,8 +322,13 @@ def makeport(self):
return sock

def makepasv(self):
"""Internal: Does the PASV or EPSV handshake -> (address, port)"""
if self.af == socket.AF_INET:
host, port = parse227(self.sendcmd('PASV'))
untrusted_host, port = parse227(self.sendcmd('PASV'))
if self.trust_server_pasv_ipv4_address:
host = untrusted_host
else:
host = self.sock.getpeername()[0]
else:
host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
return host, port
Expand Down Expand Up @@ -704,9 +715,10 @@ class FTP_TLS(FTP):
'''
ssl_version = ssl.PROTOCOL_TLS_CLIENT

def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
certfile=None, context=None,
timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
def __init__(self, host='', user='', passwd='', acct='',
keyfile=None, certfile=None, context=None,
timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None, *,
encoding='utf-8'):
if context is not None and keyfile is not None:
raise ValueError("context and keyfile arguments are mutually "
"exclusive")
Expand All @@ -725,12 +737,13 @@ def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
keyfile=keyfile)
self.context = context
self._prot_p = False
FTP.__init__(self, host, user, passwd, acct, timeout, source_address)
super().__init__(host, user, passwd, acct,
timeout, source_address, encoding=encoding)

def login(self, user='', passwd='', acct='', secure=True):
if secure and not isinstance(self.sock, ssl.SSLSocket):
self.auth()
return FTP.login(self, user, passwd, acct)
return super().login(user, passwd, acct)

def auth(self):
'''Set up secure control connection by using TLS/SSL.'''
Expand All @@ -740,8 +753,7 @@ def auth(self):
resp = self.voidcmd('AUTH TLS')
else:
resp = self.voidcmd('AUTH SSL')
self.sock = self.context.wrap_socket(self.sock,
server_hostname=self.host)
self.sock = self.context.wrap_socket(self.sock, server_hostname=self.host)
self.file = self.sock.makefile(mode='r', encoding=self.encoding)
return resp

Expand Down Expand Up @@ -778,7 +790,7 @@ def prot_c(self):
# --- Overridden FTP methods

def ntransfercmd(self, cmd, rest=None):
conn, size = FTP.ntransfercmd(self, cmd, rest)
conn, size = super().ntransfercmd(cmd, rest)
if self._prot_p:
conn = self.context.wrap_socket(conn,
server_hostname=self.host)
Expand Down Expand Up @@ -823,7 +835,6 @@ def parse227(resp):
'''Parse the '227' response for a PASV request.
Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
Return ('host.addr.as.numbers', port#) tuple.'''

if resp[:3] != '227':
raise error_reply(resp)
global _227_re
Expand All @@ -843,7 +854,6 @@ def parse229(resp, peer):
'''Parse the '229' response for an EPSV request.
Raises error_proto if it does not contain '(|||port|)'
Return ('host.addr.as.numbers', port#) tuple.'''

if resp[:3] != '229':
raise error_reply(resp)
left = resp.find('(')
Expand All @@ -865,7 +875,6 @@ def parse257(resp):
'''Parse the '257' response for a MKD or PWD request.
This is a response to a MKD or PWD request: a directory name.
Returns the directoryname in the 257 reply.'''

if resp[:3] != '257':
raise error_reply(resp)
if resp[3:5] != ' "':
Expand Down

0 comments on commit 0a76a9b

Please sign in to comment.