blob: 5e75e6d4227affec98b7e8f205ef352e0c19d727 [file] [log] [blame]
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +00001"""An FTP client class and some helper functions.
2
Barry Warsaw100d81e2000-09-01 06:09:23 +00003Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds
Guido van Rossum1115ab21992-11-04 15:51:30 +00004
Guido van Rossumd2560b01996-05-28 23:41:25 +00005Example:
6
7>>> from ftplib import FTP
8>>> ftp = FTP('ftp.python.org') # connect to host, default port
Guido van Rossum24a64342001-12-28 20:54:55 +00009>>> ftp.login() # default, i.e.: user anonymous, passwd anonymous@
Guido van Rossum2f3941d1997-10-07 14:49:56 +000010'230 Guest login ok, access restrictions apply.'
Guido van Rossumd2560b01996-05-28 23:41:25 +000011>>> ftp.retrlines('LIST') # list directory contents
12total 9
13drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
14drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
15drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
16drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
17d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
18drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
19drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
20drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
21-rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
Guido van Rossum2f3941d1997-10-07 14:49:56 +000022'226 Transfer complete.'
Guido van Rossumd2560b01996-05-28 23:41:25 +000023>>> ftp.quit()
Guido van Rossum2f3941d1997-10-07 14:49:56 +000024'221 Goodbye.'
Tim Peters88869f92001-01-14 23:36:06 +000025>>>
Guido van Rossumd2560b01996-05-28 23:41:25 +000026
27A nice test that reveals some of the network dialogue would be:
28python ftplib.py -d localhost -l -p -l
Guido van Rossum4b8c6ea2000-02-04 15:39:30 +000029"""
Guido van Rossumc567c601992-11-05 22:22:37 +000030
Tim Peters88869f92001-01-14 23:36:06 +000031#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000032# Changes and improvements suggested by Steve Majewski.
33# Modified by Jack to work on the mac.
34# Modified by Siebren to support docstrings and PASV.
Christian Heimes1af737c2008-01-23 08:24:23 +000035# Modified by Phil Schwartz to add storbinary and storlines callbacks.
Antoine Pitrouf988cd02009-11-17 20:21:14 +000036# Modified by Giampaolo Rodola' to add TLS support.
Guido van Rossum98d9fd32000-02-28 15:12:25 +000037#
Guido van Rossumc567c601992-11-05 22:22:37 +000038
Guido van Rossum1115ab21992-11-04 15:51:30 +000039import os
40import sys
Giampaolo RodolĂ 6545ed62010-08-21 20:34:37 +000041import socket
Georg Brandlf78e02b2008-06-10 17:40:04 +000042from socket import _GLOBAL_DEFAULT_TIMEOUT
Guido van Rossumb6775db1994-08-01 11:34:53 +000043
Skip Montanaroeccd02a2001-01-20 23:34:12 +000044__all__ = ["FTP","Netrc"]
Guido van Rossum1115ab21992-11-04 15:51:30 +000045
Guido van Rossumd3166071993-05-24 14:16:22 +000046# Magic number from <socket.h>
Tim Peters88869f92001-01-14 23:36:06 +000047MSG_OOB = 0x1 # Process data out of band
Guido van Rossumd3166071993-05-24 14:16:22 +000048
49
Guido van Rossumc567c601992-11-05 22:22:37 +000050# The standard FTP server control port
Guido van Rossum1115ab21992-11-04 15:51:30 +000051FTP_PORT = 21
Serhiy Storchakac30b1782013-10-20 16:58:27 +030052# The sizehint parameter passed to readline() calls
53MAXLINE = 8192
Guido van Rossum1115ab21992-11-04 15:51:30 +000054
55
Guido van Rossum21974791992-11-06 13:34:17 +000056# Exception raised when an error or invalid response is received
Fred Drake227b1202000-08-17 05:06:49 +000057class Error(Exception): pass
Tim Peters88869f92001-01-14 23:36:06 +000058class error_reply(Error): pass # unexpected [123]xx reply
59class error_temp(Error): pass # 4xx errors
60class error_perm(Error): pass # 5xx errors
61class error_proto(Error): pass # response does not begin with [1-5]
Guido van Rossum1115ab21992-11-04 15:51:30 +000062
63
Guido van Rossum21974791992-11-06 13:34:17 +000064# All exceptions (hopefully) that may be raised here and that aren't
65# (always) programming errors on our side
Christian Heimes33fe8092008-04-13 13:53:33 +000066all_errors = (Error, IOError, EOFError)
Guido van Rossum21974791992-11-06 13:34:17 +000067
68
Guido van Rossum1115ab21992-11-04 15:51:30 +000069# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
70CRLF = '\r\n'
Benjamin Petersonbe17a112008-09-27 21:49:47 +000071B_CRLF = b'\r\n'
Guido van Rossum1115ab21992-11-04 15:51:30 +000072
Guido van Rossum1115ab21992-11-04 15:51:30 +000073# The class itself
74class FTP:
75
Tim Peters88869f92001-01-14 23:36:06 +000076 '''An FTP client class.
Guido van Rossumd2560b01996-05-28 23:41:25 +000077
Guido van Rossumd8faa362007-04-27 19:54:29 +000078 To create a connection, call the class using these arguments:
79 host, user, passwd, acct, timeout
80
81 The first four arguments are all strings, and have default value ''.
82 timeout must be numeric and defaults to None if not passed,
83 meaning that no timeout will be set on any ftp socket(s)
84 If a timeout is passed, then this is now the default timeout for all ftp
85 socket operations for this instance.
86
Tim Peters88869f92001-01-14 23:36:06 +000087 Then use self.connect() with optional host and port argument.
Guido van Rossumd2560b01996-05-28 23:41:25 +000088
Tim Peters88869f92001-01-14 23:36:06 +000089 To download a file, use ftp.retrlines('RETR ' + filename),
90 or ftp.retrbinary() with slightly different arguments.
91 To upload a file, use ftp.storlines() or ftp.storbinary(),
92 which have an open file as argument (see their definitions
93 below for details).
94 The download/upload functions first issue appropriate TYPE
95 and PORT or PASV commands.
Guido van Rossum52b89762007-07-17 20:45:57 +000096 '''
Guido van Rossumd2560b01996-05-28 23:41:25 +000097
Fred Drake9c98a422001-02-28 21:46:37 +000098 debugging = 0
99 host = ''
100 port = FTP_PORT
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300101 maxline = MAXLINE
Fred Drake9c98a422001-02-28 21:46:37 +0000102 sock = None
103 file = None
104 welcome = None
105 passiveserver = 1
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000106 encoding = "latin-1"
Fred Drake9c98a422001-02-28 21:46:37 +0000107
Tim Peters88869f92001-01-14 23:36:06 +0000108 # Initialization method (called by class instantiation).
109 # Initialize host to localhost, port to standard ftp port
110 # Optional arguments are host (for connect()),
111 # and user, passwd, acct (for login())
Georg Brandlf78e02b2008-06-10 17:40:04 +0000112 def __init__(self, host='', user='', passwd='', acct='',
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000113 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
114 self.source_address = source_address
Guido van Rossumd8faa362007-04-27 19:54:29 +0000115 self.timeout = timeout
Tim Peters88869f92001-01-14 23:36:06 +0000116 if host:
Fred Drake9c98a422001-02-28 21:46:37 +0000117 self.connect(host)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000118 if user:
119 self.login(user, passwd, acct)
Guido van Rossum52fc1f61993-06-17 12:38:10 +0000120
Giampaolo RodolĂ bd576b72010-05-10 14:53:29 +0000121 def __enter__(self):
122 return self
123
124 # Context management protocol: try to quit() if active
125 def __exit__(self, *args):
126 if self.sock is not None:
127 try:
128 self.quit()
129 except (socket.error, EOFError):
130 pass
131 finally:
132 if self.sock is not None:
133 self.close()
134
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000135 def connect(self, host='', port=0, timeout=-999, source_address=None):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000136 '''Connect to host. Arguments are:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137 - host: hostname to connect to (string, default previous host)
138 - port: port to connect to (integer, default previous port)
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000139 - source_address: a 2-tuple (host, port) for the socket to bind
140 to as its source address before connecting.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000141 '''
142 if host != '':
143 self.host = host
144 if port > 0:
145 self.port = port
Georg Brandlf78e02b2008-06-10 17:40:04 +0000146 if timeout != -999:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000147 self.timeout = timeout
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000148 if source_address is not None:
149 self.source_address = source_address
150 self.sock = socket.create_connection((self.host, self.port), self.timeout,
151 source_address=self.source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000152 self.af = self.sock.family
Guido van Rossum52b89762007-07-17 20:45:57 +0000153 self.file = self.sock.makefile('r', encoding=self.encoding)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000154 self.welcome = self.getresp()
155 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000156
Tim Peters88869f92001-01-14 23:36:06 +0000157 def getwelcome(self):
158 '''Get the welcome message from the server.
159 (this is read and squirreled away by connect())'''
160 if self.debugging:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000161 print('*welcome*', self.sanitize(self.welcome))
Tim Peters88869f92001-01-14 23:36:06 +0000162 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000163
Tim Peters88869f92001-01-14 23:36:06 +0000164 def set_debuglevel(self, level):
165 '''Set the debugging level.
166 The required argument level means:
167 0: no debugging output (default)
168 1: print commands and responses but not body text etc.
169 2: also print raw lines read and sent before stripping CR/LF'''
170 self.debugging = level
171 debug = set_debuglevel
Guido van Rossum1115ab21992-11-04 15:51:30 +0000172
Tim Peters88869f92001-01-14 23:36:06 +0000173 def set_pasv(self, val):
174 '''Use passive or active mode for data transfers.
175 With a false argument, use the normal PORT mode,
176 With a true argument, use the PASV command.'''
177 self.passiveserver = val
Guido van Rossumd2560b01996-05-28 23:41:25 +0000178
Tim Peters88869f92001-01-14 23:36:06 +0000179 # Internal: "sanitize" a string for printing
180 def sanitize(self, s):
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200181 if s[:5] in {'pass ', 'PASS '}:
182 i = len(s.rstrip('\r\n'))
Tim Peters88869f92001-01-14 23:36:06 +0000183 s = s[:5] + '*'*(i-5) + s[i:]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000184 return repr(s)
Guido van Rossumebaf1041995-05-05 15:54:14 +0000185
Tim Peters88869f92001-01-14 23:36:06 +0000186 # Internal: send one line to the server, appending CRLF
187 def putline(self, line):
188 line = line + CRLF
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000189 if self.debugging > 1: print('*put*', self.sanitize(line))
Guido van Rossum52b89762007-07-17 20:45:57 +0000190 self.sock.sendall(line.encode(self.encoding))
Guido van Rossum1115ab21992-11-04 15:51:30 +0000191
Tim Peters88869f92001-01-14 23:36:06 +0000192 # Internal: send one command to the server (through putline())
193 def putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000194 if self.debugging: print('*cmd*', self.sanitize(line))
Tim Peters88869f92001-01-14 23:36:06 +0000195 self.putline(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000196
Tim Peters88869f92001-01-14 23:36:06 +0000197 # Internal: return one line from the server, stripping CRLF.
198 # Raise EOFError if the connection is closed
199 def getline(self):
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300200 line = self.file.readline(self.maxline + 1)
201 if len(line) > self.maxline:
202 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000203 if self.debugging > 1:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000204 print('*get*', self.sanitize(line))
Tim Peters88869f92001-01-14 23:36:06 +0000205 if not line: raise EOFError
206 if line[-2:] == CRLF: line = line[:-2]
207 elif line[-1:] in CRLF: line = line[:-1]
208 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000209
Tim Peters88869f92001-01-14 23:36:06 +0000210 # Internal: get a response from the server, which may possibly
211 # consist of multiple lines. Return a single string with no
212 # trailing CRLF. If the response consists of multiple lines,
213 # these are separated by '\n' characters in the string
214 def getmultiline(self):
215 line = self.getline()
216 if line[3:4] == '-':
217 code = line[:3]
218 while 1:
219 nextline = self.getline()
220 line = line + ('\n' + nextline)
221 if nextline[:3] == code and \
222 nextline[3:4] != '-':
223 break
224 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000225
Tim Peters88869f92001-01-14 23:36:06 +0000226 # Internal: get a response from the server.
227 # Raise various errors if the response indicates an error
228 def getresp(self):
229 resp = self.getmultiline()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000230 if self.debugging: print('*resp*', self.sanitize(resp))
Tim Peters88869f92001-01-14 23:36:06 +0000231 self.lastresp = resp[:3]
232 c = resp[:1]
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000233 if c in {'1', '2', '3'}:
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000234 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000235 if c == '4':
Collin Winterce36ad82007-08-30 01:19:48 +0000236 raise error_temp(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000237 if c == '5':
Collin Winterce36ad82007-08-30 01:19:48 +0000238 raise error_perm(resp)
239 raise error_proto(resp)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000240
Tim Peters88869f92001-01-14 23:36:06 +0000241 def voidresp(self):
242 """Expect a response beginning with '2'."""
243 resp = self.getresp()
Benjamin Petersond23f8222009-04-05 19:13:16 +0000244 if resp[:1] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000245 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000246 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000247
Tim Peters88869f92001-01-14 23:36:06 +0000248 def abort(self):
249 '''Abort a file transfer. Uses out-of-band data.
250 This does not follow the procedure from the RFC to send Telnet
251 IP and Synch; that doesn't seem to work with the servers I've
252 tried. Instead, just send the ABOR command as OOB data.'''
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200253 line = b'ABOR' + B_CRLF
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000254 if self.debugging > 1: print('*put urgent*', self.sanitize(line))
Martin v. Löwise12454f2002-02-16 23:06:19 +0000255 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000256 resp = self.getmultiline()
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000257 if resp[:3] not in {'426', '225', '226'}:
Collin Winterce36ad82007-08-30 01:19:48 +0000258 raise error_proto(resp)
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200259 return resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000260
Tim Peters88869f92001-01-14 23:36:06 +0000261 def sendcmd(self, cmd):
262 '''Send a command and return the response.'''
263 self.putcmd(cmd)
264 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000265
Tim Peters88869f92001-01-14 23:36:06 +0000266 def voidcmd(self, cmd):
267 """Send a command and expect a response beginning with '2'."""
268 self.putcmd(cmd)
269 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000270
Tim Peters88869f92001-01-14 23:36:06 +0000271 def sendport(self, host, port):
272 '''Send a PORT command with the current host and the given
273 port number.
274 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000275 hbytes = host.split('.')
Benjamin Peterson3a53fbb2008-09-27 22:04:16 +0000276 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000277 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000278 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000279 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000280
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000281 def sendeprt(self, host, port):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000282 '''Send a EPRT command with the current host and the given port number.'''
283 af = 0
284 if self.af == socket.AF_INET:
285 af = 1
286 if self.af == socket.AF_INET6:
287 af = 2
288 if af == 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000289 raise error_proto('unsupported address family')
Walter Dörwald70a6b492004-02-12 17:35:32 +0000290 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000291 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000292 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000293
Tim Peters88869f92001-01-14 23:36:06 +0000294 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000295 '''Create a new socket and send a PORT command for it.'''
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100296 err = None
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000297 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000298 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
299 af, socktype, proto, canonname, sa = res
300 try:
301 sock = socket.socket(af, socktype, proto)
302 sock.bind(sa)
Giampaolo Rodola'57f34872012-12-17 20:46:16 +0100303 except socket.error as _:
304 err = _
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000305 if sock:
306 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000307 sock = None
308 continue
309 break
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100310 if sock is None:
311 if err is not None:
312 raise err
313 else:
314 raise socket.error("getaddrinfo returns an empty list")
Collin Winterce36ad82007-08-30 01:19:48 +0000315 raise socket.error(msg)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000316 sock.listen(1)
317 port = sock.getsockname()[1] # Get proper port
318 host = self.sock.getsockname()[0] # Get proper host
319 if self.af == socket.AF_INET:
320 resp = self.sendport(host, port)
321 else:
322 resp = self.sendeprt(host, port)
Giampaolo RodolĂ 5fb313b2010-04-19 22:05:54 +0000323 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
324 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000325 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000326
327 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000328 if self.af == socket.AF_INET:
329 host, port = parse227(self.sendcmd('PASV'))
330 else:
331 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
332 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000333
Tim Peters88869f92001-01-14 23:36:06 +0000334 def ntransfercmd(self, cmd, rest=None):
335 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000336
Tim Peters88869f92001-01-14 23:36:06 +0000337 If the transfer is active, send a port command and the
338 transfer command, and accept the connection. If the server is
339 passive, send a pasv command, connect to it, and start the
340 transfer command. Either way, return the socket for the
341 connection and the expected size of the transfer. The
342 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000343
Tim Peters88869f92001-01-14 23:36:06 +0000344 Optional `rest' argument can be a string that is sent as the
Christian Heimes1af737c2008-01-23 08:24:23 +0000345 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000346 marker used to tell the server to skip over any data up to the
347 given marker.
348 """
349 size = None
350 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000351 host, port = self.makepasv()
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000352 conn = socket.create_connection((host, port), self.timeout,
353 source_address=self.source_address)
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200354 try:
355 if rest is not None:
356 self.sendcmd("REST %s" % rest)
357 resp = self.sendcmd(cmd)
358 # Some servers apparently send a 200 reply to
359 # a LIST or STOR command, before the 150 reply
360 # (and way before the 226 reply). This seems to
361 # be in violation of the protocol (which only allows
362 # 1xx or error messages for LIST), so we just discard
363 # this response.
364 if resp[0] == '2':
365 resp = self.getresp()
366 if resp[0] != '1':
367 raise error_reply(resp)
368 except:
369 conn.close()
370 raise
Tim Peters88869f92001-01-14 23:36:06 +0000371 else:
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100372 with self.makeport() as sock:
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200373 if rest is not None:
374 self.sendcmd("REST %s" % rest)
375 resp = self.sendcmd(cmd)
376 # See above.
377 if resp[0] == '2':
378 resp = self.getresp()
379 if resp[0] != '1':
380 raise error_reply(resp)
381 conn, sockaddr = sock.accept()
382 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
383 conn.settimeout(self.timeout)
Tim Peters88869f92001-01-14 23:36:06 +0000384 if resp[:3] == '150':
385 # this is conditional in case we received a 125
386 size = parse150(resp)
387 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000388
Tim Peters88869f92001-01-14 23:36:06 +0000389 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000390 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000391 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000392
Tim Peters88869f92001-01-14 23:36:06 +0000393 def login(self, user = '', passwd = '', acct = ''):
394 '''Login, default anonymous.'''
395 if not user: user = 'anonymous'
396 if not passwd: passwd = ''
397 if not acct: acct = ''
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000398 if user == 'anonymous' and passwd in {'', '-'}:
Tim Peterse4418602002-02-16 07:34:19 +0000399 # If there is no anonymous ftp password specified
400 # then we'll just use anonymous@
401 # We don't send any other thing because:
402 # - We want to remain anonymous
403 # - We want to stop SPAM
404 # - We don't want to let ftp sites to discriminate by the user,
405 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000406 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000407 resp = self.sendcmd('USER ' + user)
408 if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
409 if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
410 if resp[0] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000411 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000412 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000413
Tim Peters88869f92001-01-14 23:36:06 +0000414 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000415 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000416
Christian Heimes1af737c2008-01-23 08:24:23 +0000417 Args:
418 cmd: A RETR command.
419 callback: A single parameter callable to be called on each
420 block of data read.
421 blocksize: The maximum number of bytes to read from the
422 socket at one time. [default: 8192]
423 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000424
Christian Heimes1af737c2008-01-23 08:24:23 +0000425 Returns:
426 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000427 """
428 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000429 with self.transfercmd(cmd, rest) as conn:
430 while 1:
431 data = conn.recv(blocksize)
432 if not data:
433 break
434 callback(data)
Tim Peters88869f92001-01-14 23:36:06 +0000435 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000436
Tim Peters88869f92001-01-14 23:36:06 +0000437 def retrlines(self, cmd, callback = None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000438 """Retrieve data in line mode. A new port is created for you.
439
440 Args:
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200441 cmd: A RETR, LIST, or NLST command.
Christian Heimes1af737c2008-01-23 08:24:23 +0000442 callback: An optional single parameter callable that is called
443 for each line with the trailing CRLF stripped.
444 [default: print_line()]
445
446 Returns:
447 The response code.
448 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000449 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000450 resp = self.sendcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000451 with self.transfercmd(cmd) as conn, \
452 conn.makefile('r', encoding=self.encoding) as fp:
453 while 1:
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300454 line = fp.readline(self.maxline + 1)
455 if len(line) > self.maxline:
456 raise Error("got more than %d bytes" % self.maxline)
Benjamin Petersona8071372010-10-31 18:21:16 +0000457 if self.debugging > 2: print('*retr*', repr(line))
458 if not line:
459 break
460 if line[-2:] == CRLF:
461 line = line[:-2]
462 elif line[-1:] == '\n':
463 line = line[:-1]
464 callback(line)
Tim Peters88869f92001-01-14 23:36:06 +0000465 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000466
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000467 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000468 """Store a file in binary mode. A new port is created for you.
469
470 Args:
471 cmd: A STOR command.
472 fp: A file-like object with a read(num_bytes) method.
473 blocksize: The maximum data size to read from fp and send over
474 the connection at once. [default: 8192]
475 callback: An optional single parameter callable that is called on
Terry Jan Reedyc30b7b12013-03-11 17:57:08 -0400476 each block of data after it is sent. [default: None]
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000477 rest: Passed to transfercmd(). [default: None]
Christian Heimes1af737c2008-01-23 08:24:23 +0000478
479 Returns:
480 The response code.
481 """
Tim Peters88869f92001-01-14 23:36:06 +0000482 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000483 with self.transfercmd(cmd, rest) as conn:
484 while 1:
485 buf = fp.read(blocksize)
486 if not buf: break
487 conn.sendall(buf)
488 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000489 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000490
Christian Heimes1af737c2008-01-23 08:24:23 +0000491 def storlines(self, cmd, fp, callback=None):
492 """Store a file in line mode. A new port is created for you.
493
494 Args:
495 cmd: A STOR command.
496 fp: A file-like object with a readline() method.
497 callback: An optional single parameter callable that is called on
Terry Jan Reedyc30b7b12013-03-11 17:57:08 -0400498 each line after it is sent. [default: None]
Christian Heimes1af737c2008-01-23 08:24:23 +0000499
500 Returns:
501 The response code.
502 """
Tim Peters88869f92001-01-14 23:36:06 +0000503 self.voidcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000504 with self.transfercmd(cmd) as conn:
505 while 1:
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300506 buf = fp.readline(self.maxline + 1)
507 if len(buf) > self.maxline:
508 raise Error("got more than %d bytes" % self.maxline)
Benjamin Petersona8071372010-10-31 18:21:16 +0000509 if not buf: break
510 if buf[-2:] != B_CRLF:
511 if buf[-1] in B_CRLF: buf = buf[:-1]
512 buf = buf + B_CRLF
513 conn.sendall(buf)
514 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000515 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000516
Tim Peters88869f92001-01-14 23:36:06 +0000517 def acct(self, password):
518 '''Send new account name.'''
519 cmd = 'ACCT ' + password
520 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000521
Tim Peters88869f92001-01-14 23:36:06 +0000522 def nlst(self, *args):
523 '''Return a list of files in a given directory (default the current).'''
524 cmd = 'NLST'
525 for arg in args:
526 cmd = cmd + (' ' + arg)
527 files = []
528 self.retrlines(cmd, files.append)
529 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000530
Tim Peters88869f92001-01-14 23:36:06 +0000531 def dir(self, *args):
532 '''List a directory in long form.
533 By default list current directory to stdout.
534 Optional last argument is callback function; all
535 non-empty arguments before it are concatenated to the
536 LIST command. (This *should* only be used for a pathname.)'''
537 cmd = 'LIST'
538 func = None
539 if args[-1:] and type(args[-1]) != type(''):
540 args, func = args[:-1], args[-1]
541 for arg in args:
542 if arg:
543 cmd = cmd + (' ' + arg)
544 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000545
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200546 def mlsd(self, path="", facts=[]):
547 '''List a directory in a standardized format by using MLSD
548 command (RFC-3659). If path is omitted the current directory
549 is assumed. "facts" is a list of strings representing the type
550 of information desired (e.g. ["type", "size", "perm"]).
551
552 Return a generator object yielding a tuple of two elements
553 for every file found in path.
554 First element is the file name, the second one is a dictionary
555 including a variable number of "facts" depending on the server
556 and whether "facts" argument has been provided.
557 '''
558 if facts:
559 self.sendcmd("OPTS MLST " + ";".join(facts) + ";")
560 if path:
561 cmd = "MLSD %s" % path
562 else:
563 cmd = "MLSD"
564 lines = []
565 self.retrlines(cmd, lines.append)
566 for line in lines:
567 facts_found, _, name = line.rstrip(CRLF).partition(' ')
568 entry = {}
569 for fact in facts_found[:-1].split(";"):
570 key, _, value = fact.partition("=")
571 entry[key.lower()] = value
572 yield (name, entry)
573
Tim Peters88869f92001-01-14 23:36:06 +0000574 def rename(self, fromname, toname):
575 '''Rename a file.'''
576 resp = self.sendcmd('RNFR ' + fromname)
577 if resp[0] != '3':
Collin Winterce36ad82007-08-30 01:19:48 +0000578 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000579 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000580
Tim Peters88869f92001-01-14 23:36:06 +0000581 def delete(self, filename):
582 '''Delete a file.'''
583 resp = self.sendcmd('DELE ' + filename)
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000584 if resp[:3] in {'250', '200'}:
Tim Peters88869f92001-01-14 23:36:06 +0000585 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000586 else:
Collin Winterce36ad82007-08-30 01:19:48 +0000587 raise error_reply(resp)
Guido van Rossum02cf5821993-05-17 08:00:02 +0000588
Tim Peters88869f92001-01-14 23:36:06 +0000589 def cwd(self, dirname):
590 '''Change to a directory.'''
591 if dirname == '..':
592 try:
593 return self.voidcmd('CDUP')
Guido van Rossumb940e112007-01-10 16:19:56 +0000594 except error_perm as msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000595 if msg.args[0][:3] != '500':
596 raise
Tim Peters88869f92001-01-14 23:36:06 +0000597 elif dirname == '':
598 dirname = '.' # does nothing, but could return error
599 cmd = 'CWD ' + dirname
600 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000601
Tim Peters88869f92001-01-14 23:36:06 +0000602 def size(self, filename):
603 '''Retrieve the size of a file.'''
Christian Heimes1af737c2008-01-23 08:24:23 +0000604 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000605 resp = self.sendcmd('SIZE ' + filename)
606 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000607 s = resp[3:].strip()
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200608 return int(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000609
Tim Peters88869f92001-01-14 23:36:06 +0000610 def mkd(self, dirname):
611 '''Make a directory, return its full pathname.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000612 resp = self.voidcmd('MKD ' + dirname)
613 # fix around non-compliant implementations such as IIS shipped
614 # with Windows server 2003
615 if not resp.startswith('257'):
616 return ''
Tim Peters88869f92001-01-14 23:36:06 +0000617 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000618
Tim Peters88869f92001-01-14 23:36:06 +0000619 def rmd(self, dirname):
620 '''Remove a directory.'''
621 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000622
Tim Peters88869f92001-01-14 23:36:06 +0000623 def pwd(self):
624 '''Return current working directory.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000625 resp = self.voidcmd('PWD')
626 # fix around non-compliant implementations such as IIS shipped
627 # with Windows server 2003
628 if not resp.startswith('257'):
629 return ''
Tim Peters88869f92001-01-14 23:36:06 +0000630 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000631
Tim Peters88869f92001-01-14 23:36:06 +0000632 def quit(self):
633 '''Quit, and close the connection.'''
634 resp = self.voidcmd('QUIT')
635 self.close()
636 return resp
637
638 def close(self):
639 '''Close the connection without assuming anything about it.'''
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000640 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000641 self.file.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000642 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000643 self.sock.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000644 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000645
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000646try:
647 import ssl
648except ImportError:
649 pass
650else:
651 class FTP_TLS(FTP):
652 '''A FTP subclass which adds TLS support to FTP as described
653 in RFC-4217.
654
655 Connect as usual to port 21 implicitly securing the FTP control
656 connection before authenticating.
657
658 Securing the data connection requires user to explicitly ask
659 for it by calling prot_p() method.
660
661 Usage example:
662 >>> from ftplib import FTP_TLS
663 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti4969f702011-03-15 05:59:46 +0200664 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000665 '230 Guest login ok, access restrictions apply.'
666 >>> ftps.prot_p() # switch to secure data connection
667 '200 Protection level set to P'
668 >>> ftps.retrlines('LIST') # list directory content securely
669 total 9
670 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
671 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
672 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
673 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
674 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
675 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
676 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
677 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
678 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
679 '226 Transfer complete.'
680 >>> ftps.quit()
681 '221 Goodbye.'
682 >>>
683 '''
684 ssl_version = ssl.PROTOCOL_TLSv1
685
686 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000687 certfile=None, context=None,
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000688 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000689 if context is not None and keyfile is not None:
690 raise ValueError("context and keyfile arguments are mutually "
691 "exclusive")
692 if context is not None and certfile is not None:
693 raise ValueError("context and certfile arguments are mutually "
694 "exclusive")
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000695 self.keyfile = keyfile
696 self.certfile = certfile
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000697 self.context = context
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000698 self._prot_p = False
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000699 FTP.__init__(self, host, user, passwd, acct, timeout, source_address)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000700
701 def login(self, user='', passwd='', acct='', secure=True):
702 if secure and not isinstance(self.sock, ssl.SSLSocket):
703 self.auth()
704 return FTP.login(self, user, passwd, acct)
705
706 def auth(self):
707 '''Set up secure control connection by using TLS/SSL.'''
708 if isinstance(self.sock, ssl.SSLSocket):
709 raise ValueError("Already using TLS")
710 if self.ssl_version == ssl.PROTOCOL_TLSv1:
711 resp = self.voidcmd('AUTH TLS')
712 else:
713 resp = self.voidcmd('AUTH SSL')
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000714 if self.context is not None:
715 self.sock = self.context.wrap_socket(self.sock)
716 else:
717 self.sock = ssl.wrap_socket(self.sock, self.keyfile,
718 self.certfile,
719 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000720 self.file = self.sock.makefile(mode='r', encoding=self.encoding)
721 return resp
722
Giampaolo Rodola'096dcb12011-06-27 11:17:51 +0200723 def ccc(self):
724 '''Switch back to a clear-text control connection.'''
725 if not isinstance(self.sock, ssl.SSLSocket):
726 raise ValueError("not using TLS")
727 resp = self.voidcmd('CCC')
728 self.sock = self.sock.unwrap()
729 return resp
730
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000731 def prot_p(self):
732 '''Set up secure data connection.'''
733 # PROT defines whether or not the data channel is to be protected.
734 # Though RFC-2228 defines four possible protection levels,
735 # RFC-4217 only recommends two, Clear and Private.
736 # Clear (PROT C) means that no security is to be used on the
737 # data-channel, Private (PROT P) means that the data-channel
738 # should be protected by TLS.
739 # PBSZ command MUST still be issued, but must have a parameter of
740 # '0' to indicate that no buffering is taking place and the data
741 # connection should not be encapsulated.
742 self.voidcmd('PBSZ 0')
743 resp = self.voidcmd('PROT P')
744 self._prot_p = True
745 return resp
746
747 def prot_c(self):
748 '''Set up clear text data connection.'''
749 resp = self.voidcmd('PROT C')
750 self._prot_p = False
751 return resp
752
753 # --- Overridden FTP methods
754
755 def ntransfercmd(self, cmd, rest=None):
756 conn, size = FTP.ntransfercmd(self, cmd, rest)
757 if self._prot_p:
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000758 if self.context is not None:
759 conn = self.context.wrap_socket(conn)
760 else:
761 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
762 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000763 return conn, size
764
765 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
766 self.voidcmd('TYPE I')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100767 with self.transfercmd(cmd, rest) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000768 while 1:
769 data = conn.recv(blocksize)
770 if not data:
771 break
772 callback(data)
773 # shutdown ssl layer
774 if isinstance(conn, ssl.SSLSocket):
775 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000776 return self.voidresp()
777
778 def retrlines(self, cmd, callback = None):
779 if callback is None: callback = print_line
780 resp = self.sendcmd('TYPE A')
781 conn = self.transfercmd(cmd)
782 fp = conn.makefile('r', encoding=self.encoding)
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100783 with fp, conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000784 while 1:
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300785 line = fp.readline(self.maxline + 1)
786 if len(line) > self.maxline:
787 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000788 if self.debugging > 2: print('*retr*', repr(line))
789 if not line:
790 break
791 if line[-2:] == CRLF:
792 line = line[:-2]
793 elif line[-1:] == '\n':
794 line = line[:-1]
795 callback(line)
796 # shutdown ssl layer
797 if isinstance(conn, ssl.SSLSocket):
798 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000799 return self.voidresp()
800
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000801 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000802 self.voidcmd('TYPE I')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100803 with self.transfercmd(cmd, rest) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000804 while 1:
805 buf = fp.read(blocksize)
806 if not buf: break
807 conn.sendall(buf)
808 if callback: callback(buf)
809 # shutdown ssl layer
810 if isinstance(conn, ssl.SSLSocket):
811 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000812 return self.voidresp()
813
814 def storlines(self, cmd, fp, callback=None):
815 self.voidcmd('TYPE A')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100816 with self.transfercmd(cmd) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000817 while 1:
Serhiy Storchakac30b1782013-10-20 16:58:27 +0300818 buf = fp.readline(self.maxline + 1)
819 if len(buf) > self.maxline:
820 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000821 if not buf: break
Giampaolo RodolĂ f96482e2010-08-04 10:36:18 +0000822 if buf[-2:] != B_CRLF:
823 if buf[-1] in B_CRLF: buf = buf[:-1]
824 buf = buf + B_CRLF
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000825 conn.sendall(buf)
826 if callback: callback(buf)
827 # shutdown ssl layer
828 if isinstance(conn, ssl.SSLSocket):
829 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000830 return self.voidresp()
831
Giampaolo Rodola'24befa82011-05-07 19:09:34 +0200832 def abort(self):
833 # overridden as we can't pass MSG_OOB flag to sendall()
834 line = b'ABOR' + B_CRLF
835 self.sock.sendall(line)
836 resp = self.getmultiline()
837 if resp[:3] not in {'426', '225', '226'}:
838 raise error_proto(resp)
839 return resp
840
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000841 __all__.append('FTP_TLS')
842 all_errors = (Error, IOError, EOFError, ssl.SSLError)
843
844
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000845_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000846
847def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000848 '''Parse the '150' response for a RETR request.
849 Returns the expected transfer size or None; size is not guaranteed to
850 be present in the 150 message.
851 '''
852 if resp[:3] != '150':
Collin Winterce36ad82007-08-30 01:19:48 +0000853 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000854 global _150_re
855 if _150_re is None:
856 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000857 _150_re = re.compile(
858 "150 .* \((\d+) bytes\)", re.IGNORECASE | re.ASCII)
Tim Peters88869f92001-01-14 23:36:06 +0000859 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000860 if not m:
861 return None
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200862 return int(m.group(1))
Fred Drake4de02d91997-01-10 18:26:09 +0000863
864
Guido van Rossum70297d32001-08-17 17:24:29 +0000865_227_re = None
866
Guido van Rossumd2560b01996-05-28 23:41:25 +0000867def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000868 '''Parse the '227' response for a PASV request.
869 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
870 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000871
Tim Peters88869f92001-01-14 23:36:06 +0000872 if resp[:3] != '227':
Collin Winterce36ad82007-08-30 01:19:48 +0000873 raise error_reply(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000874 global _227_re
875 if _227_re is None:
876 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000877 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)', re.ASCII)
Guido van Rossum70297d32001-08-17 17:24:29 +0000878 m = _227_re.search(resp)
879 if not m:
Collin Winterce36ad82007-08-30 01:19:48 +0000880 raise error_proto(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000881 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000882 host = '.'.join(numbers[:4])
883 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000884 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000885
886
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000887def parse229(resp, peer):
888 '''Parse the '229' response for a EPSV request.
889 Raises error_proto if it does not contain '(|||port|)'
890 Return ('host.addr.as.numbers', port#) tuple.'''
891
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000892 if resp[:3] != '229':
Collin Winterce36ad82007-08-30 01:19:48 +0000893 raise error_reply(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000894 left = resp.find('(')
Collin Winterce36ad82007-08-30 01:19:48 +0000895 if left < 0: raise error_proto(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000896 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000897 if right < 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000898 raise error_proto(resp) # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000899 if resp[left + 1] != resp[right - 1]:
Collin Winterce36ad82007-08-30 01:19:48 +0000900 raise error_proto(resp)
Walter Dörwalda401ae42002-06-03 10:41:45 +0000901 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000902 if len(parts) != 5:
Collin Winterce36ad82007-08-30 01:19:48 +0000903 raise error_proto(resp)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000904 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000905 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000906 return host, port
907
908
Guido van Rossumc567c601992-11-05 22:22:37 +0000909def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000910 '''Parse the '257' response for a MKD or PWD request.
911 This is a response to a MKD or PWD request: a directory name.
912 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000913
Tim Peters88869f92001-01-14 23:36:06 +0000914 if resp[:3] != '257':
Collin Winterce36ad82007-08-30 01:19:48 +0000915 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000916 if resp[3:5] != ' "':
917 return '' # Not compliant to RFC 959, but UNIX ftpd does this
918 dirname = ''
919 i = 5
920 n = len(resp)
921 while i < n:
922 c = resp[i]
923 i = i+1
924 if c == '"':
925 if i >= n or resp[i] != '"':
926 break
927 i = i+1
928 dirname = dirname + c
929 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000930
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000931
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000932def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000933 '''Default retrlines callback to print a line.'''
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000934 print(line)
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000935
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000936
Guido van Rossumd2560b01996-05-28 23:41:25 +0000937def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000938 '''Copy file from one FTP-instance to another.'''
939 if not targetname: targetname = sourcename
940 type = 'TYPE ' + type
941 source.voidcmd(type)
942 target.voidcmd(type)
943 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
944 target.sendport(sourcehost, sourceport)
945 # RFC 959: the user must "listen" [...] BEFORE sending the
946 # transfer request.
947 # So: STOR before RETR, because here the target is a "user".
948 treply = target.sendcmd('STOR ' + targetname)
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000949 if treply[:3] not in {'125', '150'}: raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000950 sreply = source.sendcmd('RETR ' + sourcename)
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000951 if sreply[:3] not in {'125', '150'}: raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000952 source.voidresp()
953 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000954
Tim Peters88869f92001-01-14 23:36:06 +0000955
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000956class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000957 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000958
Tim Peters88869f92001-01-14 23:36:06 +0000959 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000960
Tim Peters88869f92001-01-14 23:36:06 +0000961 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000962
Tim Peters88869f92001-01-14 23:36:06 +0000963 """
964 __defuser = None
965 __defpasswd = None
966 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000967
Tim Peters88869f92001-01-14 23:36:06 +0000968 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000969 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000970 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000971 filename = os.path.join(os.environ["HOME"],
972 ".netrc")
973 else:
Collin Winterce36ad82007-08-30 01:19:48 +0000974 raise IOError("specify file to load or set $HOME")
Tim Peters88869f92001-01-14 23:36:06 +0000975 self.__hosts = {}
976 self.__macros = {}
977 fp = open(filename, "r")
978 in_macro = 0
979 while 1:
980 line = fp.readline()
981 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000982 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000983 macro_lines.append(line)
984 continue
985 elif in_macro:
986 self.__macros[macro_name] = tuple(macro_lines)
987 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000988 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000989 host = user = passwd = acct = None
990 default = 0
991 i = 0
992 while i < len(words):
993 w1 = words[i]
994 if i+1 < len(words):
995 w2 = words[i + 1]
996 else:
997 w2 = None
998 if w1 == 'default':
999 default = 1
1000 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001001 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001002 i = i + 1
1003 elif w1 == 'login' and w2:
1004 user = w2
1005 i = i + 1
1006 elif w1 == 'password' and w2:
1007 passwd = w2
1008 i = i + 1
1009 elif w1 == 'account' and w2:
1010 acct = w2
1011 i = i + 1
1012 elif w1 == 'macdef' and w2:
1013 macro_name = w2
1014 macro_lines = []
1015 in_macro = 1
1016 break
1017 i = i + 1
1018 if default:
1019 self.__defuser = user or self.__defuser
1020 self.__defpasswd = passwd or self.__defpasswd
1021 self.__defacct = acct or self.__defacct
1022 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001023 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001024 ouser, opasswd, oacct = \
1025 self.__hosts[host]
1026 user = user or ouser
1027 passwd = passwd or opasswd
1028 acct = acct or oacct
1029 self.__hosts[host] = user, passwd, acct
1030 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001031
Tim Peters88869f92001-01-14 23:36:06 +00001032 def get_hosts(self):
1033 """Return a list of hosts mentioned in the .netrc file."""
1034 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001035
Tim Peters88869f92001-01-14 23:36:06 +00001036 def get_account(self, host):
1037 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001038
Tim Peters88869f92001-01-14 23:36:06 +00001039 The return value is a triple containing userid,
1040 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001041
Tim Peters88869f92001-01-14 23:36:06 +00001042 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001043 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001044 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001045 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001046 user, passwd, acct = self.__hosts[host]
1047 user = user or self.__defuser
1048 passwd = passwd or self.__defpasswd
1049 acct = acct or self.__defacct
1050 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001051
Tim Peters88869f92001-01-14 23:36:06 +00001052 def get_macros(self):
1053 """Return a list of all defined macro names."""
1054 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001055
Tim Peters88869f92001-01-14 23:36:06 +00001056 def get_macro(self, macro):
1057 """Return a sequence of lines which define a named macro."""
1058 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001059
Fred Drake475d51d1997-06-24 22:02:54 +00001060
Tim Peters88869f92001-01-14 23:36:06 +00001061
Guido van Rossum1115ab21992-11-04 15:51:30 +00001062def test():
Tim Peters88869f92001-01-14 23:36:06 +00001063 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001064 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1065
1066 -d dir
1067 -l list
1068 -p password
1069 '''
1070
1071 if len(sys.argv) < 2:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001072 print(test.__doc__)
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001073 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001074
Tim Peters88869f92001-01-14 23:36:06 +00001075 debugging = 0
1076 rcfile = None
1077 while sys.argv[1] == '-d':
1078 debugging = debugging+1
1079 del sys.argv[1]
1080 if sys.argv[1][:2] == '-r':
1081 # get name of alternate ~/.netrc file:
1082 rcfile = sys.argv[1][2:]
1083 del sys.argv[1]
1084 host = sys.argv[1]
1085 ftp = FTP(host)
1086 ftp.set_debuglevel(debugging)
1087 userid = passwd = acct = ''
1088 try:
1089 netrc = Netrc(rcfile)
1090 except IOError:
1091 if rcfile is not None:
1092 sys.stderr.write("Could not open account file"
1093 " -- using anonymous login.")
1094 else:
1095 try:
1096 userid, passwd, acct = netrc.get_account(host)
1097 except KeyError:
1098 # no account for host
1099 sys.stderr.write(
1100 "No account -- using anonymous login.")
1101 ftp.login(userid, passwd, acct)
1102 for file in sys.argv[2:]:
1103 if file[:2] == '-l':
1104 ftp.dir(file[2:])
1105 elif file[:2] == '-d':
1106 cmd = 'CWD'
1107 if file[2:]: cmd = cmd + ' ' + file[2:]
1108 resp = ftp.sendcmd(cmd)
1109 elif file == '-p':
1110 ftp.set_pasv(not ftp.passiveserver)
1111 else:
1112 ftp.retrbinary('RETR ' + file, \
1113 sys.stdout.write, 1024)
1114 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001115
1116
1117if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001118 test()