blob: 8abf753b02d8e381d18be9499119c4d7eac6635c [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
R David Murray87632f12013-02-19 18:32:28 -050042import warnings
Georg Brandlf78e02b2008-06-10 17:40:04 +000043from socket import _GLOBAL_DEFAULT_TIMEOUT
Guido van Rossumb6775db1994-08-01 11:34:53 +000044
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +010045__all__ = ["FTP", "Netrc"]
Guido van Rossum1115ab21992-11-04 15:51:30 +000046
Guido van Rossumd3166071993-05-24 14:16:22 +000047# Magic number from <socket.h>
Tim Peters88869f92001-01-14 23:36:06 +000048MSG_OOB = 0x1 # Process data out of band
Guido van Rossumd3166071993-05-24 14:16:22 +000049
50
Guido van Rossumc567c601992-11-05 22:22:37 +000051# The standard FTP server control port
Guido van Rossum1115ab21992-11-04 15:51:30 +000052FTP_PORT = 21
Guido van Rossum1115ab21992-11-04 15:51:30 +000053
54
Guido van Rossum21974791992-11-06 13:34:17 +000055# Exception raised when an error or invalid response is received
Fred Drake227b1202000-08-17 05:06:49 +000056class Error(Exception): pass
Tim Peters88869f92001-01-14 23:36:06 +000057class error_reply(Error): pass # unexpected [123]xx reply
58class error_temp(Error): pass # 4xx errors
59class error_perm(Error): pass # 5xx errors
60class error_proto(Error): pass # response does not begin with [1-5]
Guido van Rossum1115ab21992-11-04 15:51:30 +000061
62
Guido van Rossum21974791992-11-06 13:34:17 +000063# All exceptions (hopefully) that may be raised here and that aren't
64# (always) programming errors on our side
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020065all_errors = (Error, OSError, EOFError)
Guido van Rossum21974791992-11-06 13:34:17 +000066
67
Guido van Rossum1115ab21992-11-04 15:51:30 +000068# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
69CRLF = '\r\n'
Benjamin Petersonbe17a112008-09-27 21:49:47 +000070B_CRLF = b'\r\n'
Guido van Rossum1115ab21992-11-04 15:51:30 +000071
Guido van Rossum1115ab21992-11-04 15:51:30 +000072# The class itself
73class FTP:
74
Tim Peters88869f92001-01-14 23:36:06 +000075 '''An FTP client class.
Guido van Rossumd2560b01996-05-28 23:41:25 +000076
Guido van Rossumd8faa362007-04-27 19:54:29 +000077 To create a connection, call the class using these arguments:
78 host, user, passwd, acct, timeout
79
80 The first four arguments are all strings, and have default value ''.
81 timeout must be numeric and defaults to None if not passed,
82 meaning that no timeout will be set on any ftp socket(s)
83 If a timeout is passed, then this is now the default timeout for all ftp
84 socket operations for this instance.
85
Tim Peters88869f92001-01-14 23:36:06 +000086 Then use self.connect() with optional host and port argument.
Guido van Rossumd2560b01996-05-28 23:41:25 +000087
Tim Peters88869f92001-01-14 23:36:06 +000088 To download a file, use ftp.retrlines('RETR ' + filename),
89 or ftp.retrbinary() with slightly different arguments.
90 To upload a file, use ftp.storlines() or ftp.storbinary(),
91 which have an open file as argument (see their definitions
92 below for details).
93 The download/upload functions first issue appropriate TYPE
94 and PORT or PASV commands.
Guido van Rossum52b89762007-07-17 20:45:57 +000095 '''
Guido van Rossumd2560b01996-05-28 23:41:25 +000096
Fred Drake9c98a422001-02-28 21:46:37 +000097 debugging = 0
98 host = ''
99 port = FTP_PORT
100 sock = None
101 file = None
102 welcome = None
103 passiveserver = 1
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000104 encoding = "latin-1"
Fred Drake9c98a422001-02-28 21:46:37 +0000105
Tim Peters88869f92001-01-14 23:36:06 +0000106 # Initialization method (called by class instantiation).
107 # Initialize host to localhost, port to standard ftp port
108 # Optional arguments are host (for connect()),
109 # and user, passwd, acct (for login())
Georg Brandlf78e02b2008-06-10 17:40:04 +0000110 def __init__(self, host='', user='', passwd='', acct='',
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000111 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
112 self.source_address = source_address
Guido van Rossumd8faa362007-04-27 19:54:29 +0000113 self.timeout = timeout
Tim Peters88869f92001-01-14 23:36:06 +0000114 if host:
Fred Drake9c98a422001-02-28 21:46:37 +0000115 self.connect(host)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000116 if user:
117 self.login(user, passwd, acct)
Guido van Rossum52fc1f61993-06-17 12:38:10 +0000118
Giampaolo RodolĂ bd576b72010-05-10 14:53:29 +0000119 def __enter__(self):
120 return self
121
122 # Context management protocol: try to quit() if active
123 def __exit__(self, *args):
124 if self.sock is not None:
125 try:
126 self.quit()
Andrew Svetlov0832af62012-12-18 23:10:48 +0200127 except (OSError, EOFError):
Giampaolo RodolĂ bd576b72010-05-10 14:53:29 +0000128 pass
129 finally:
130 if self.sock is not None:
131 self.close()
132
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000133 def connect(self, host='', port=0, timeout=-999, source_address=None):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000134 '''Connect to host. Arguments are:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000135 - host: hostname to connect to (string, default previous host)
136 - port: port to connect to (integer, default previous port)
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000137 - source_address: a 2-tuple (host, port) for the socket to bind
138 to as its source address before connecting.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000139 '''
140 if host != '':
141 self.host = host
142 if port > 0:
143 self.port = port
Georg Brandlf78e02b2008-06-10 17:40:04 +0000144 if timeout != -999:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145 self.timeout = timeout
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000146 if source_address is not None:
147 self.source_address = source_address
148 self.sock = socket.create_connection((self.host, self.port), self.timeout,
149 source_address=self.source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000150 self.af = self.sock.family
Guido van Rossum52b89762007-07-17 20:45:57 +0000151 self.file = self.sock.makefile('r', encoding=self.encoding)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000152 self.welcome = self.getresp()
153 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000154
Tim Peters88869f92001-01-14 23:36:06 +0000155 def getwelcome(self):
156 '''Get the welcome message from the server.
157 (this is read and squirreled away by connect())'''
158 if self.debugging:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000159 print('*welcome*', self.sanitize(self.welcome))
Tim Peters88869f92001-01-14 23:36:06 +0000160 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000161
Tim Peters88869f92001-01-14 23:36:06 +0000162 def set_debuglevel(self, level):
163 '''Set the debugging level.
164 The required argument level means:
165 0: no debugging output (default)
166 1: print commands and responses but not body text etc.
167 2: also print raw lines read and sent before stripping CR/LF'''
168 self.debugging = level
169 debug = set_debuglevel
Guido van Rossum1115ab21992-11-04 15:51:30 +0000170
Tim Peters88869f92001-01-14 23:36:06 +0000171 def set_pasv(self, val):
172 '''Use passive or active mode for data transfers.
173 With a false argument, use the normal PORT mode,
174 With a true argument, use the PASV command.'''
175 self.passiveserver = val
Guido van Rossumd2560b01996-05-28 23:41:25 +0000176
Tim Peters88869f92001-01-14 23:36:06 +0000177 # Internal: "sanitize" a string for printing
178 def sanitize(self, s):
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200179 if s[:5] in {'pass ', 'PASS '}:
180 i = len(s.rstrip('\r\n'))
Tim Peters88869f92001-01-14 23:36:06 +0000181 s = s[:5] + '*'*(i-5) + s[i:]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000182 return repr(s)
Guido van Rossumebaf1041995-05-05 15:54:14 +0000183
Tim Peters88869f92001-01-14 23:36:06 +0000184 # Internal: send one line to the server, appending CRLF
185 def putline(self, line):
186 line = line + CRLF
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100187 if self.debugging > 1:
188 print('*put*', self.sanitize(line))
Guido van Rossum52b89762007-07-17 20:45:57 +0000189 self.sock.sendall(line.encode(self.encoding))
Guido van Rossum1115ab21992-11-04 15:51:30 +0000190
Tim Peters88869f92001-01-14 23:36:06 +0000191 # Internal: send one command to the server (through putline())
192 def putcmd(self, line):
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000193 if self.debugging: print('*cmd*', self.sanitize(line))
Tim Peters88869f92001-01-14 23:36:06 +0000194 self.putline(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000195
Tim Peters88869f92001-01-14 23:36:06 +0000196 # Internal: return one line from the server, stripping CRLF.
197 # Raise EOFError if the connection is closed
198 def getline(self):
199 line = self.file.readline()
200 if self.debugging > 1:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000201 print('*get*', self.sanitize(line))
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100202 if not line:
203 raise EOFError
204 if line[-2:] == CRLF:
205 line = line[:-2]
206 elif line[-1:] in CRLF:
207 line = line[:-1]
Tim Peters88869f92001-01-14 23:36:06 +0000208 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()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100230 if self.debugging:
231 print('*resp*', self.sanitize(resp))
Tim Peters88869f92001-01-14 23:36:06 +0000232 self.lastresp = resp[:3]
233 c = resp[:1]
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000234 if c in {'1', '2', '3'}:
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000235 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000236 if c == '4':
Collin Winterce36ad82007-08-30 01:19:48 +0000237 raise error_temp(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000238 if c == '5':
Collin Winterce36ad82007-08-30 01:19:48 +0000239 raise error_perm(resp)
240 raise error_proto(resp)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000241
Tim Peters88869f92001-01-14 23:36:06 +0000242 def voidresp(self):
243 """Expect a response beginning with '2'."""
244 resp = self.getresp()
Benjamin Petersond23f8222009-04-05 19:13:16 +0000245 if resp[:1] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000246 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000247 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000248
Tim Peters88869f92001-01-14 23:36:06 +0000249 def abort(self):
250 '''Abort a file transfer. Uses out-of-band data.
251 This does not follow the procedure from the RFC to send Telnet
252 IP and Synch; that doesn't seem to work with the servers I've
253 tried. Instead, just send the ABOR command as OOB data.'''
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200254 line = b'ABOR' + B_CRLF
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100255 if self.debugging > 1:
256 print('*put urgent*', self.sanitize(line))
Martin v. Löwise12454f2002-02-16 23:06:19 +0000257 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000258 resp = self.getmultiline()
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000259 if resp[:3] not in {'426', '225', '226'}:
Collin Winterce36ad82007-08-30 01:19:48 +0000260 raise error_proto(resp)
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200261 return resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000262
Tim Peters88869f92001-01-14 23:36:06 +0000263 def sendcmd(self, cmd):
264 '''Send a command and return the response.'''
265 self.putcmd(cmd)
266 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000267
Tim Peters88869f92001-01-14 23:36:06 +0000268 def voidcmd(self, cmd):
269 """Send a command and expect a response beginning with '2'."""
270 self.putcmd(cmd)
271 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000272
Tim Peters88869f92001-01-14 23:36:06 +0000273 def sendport(self, host, port):
274 '''Send a PORT command with the current host and the given
275 port number.
276 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000277 hbytes = host.split('.')
Benjamin Peterson3a53fbb2008-09-27 22:04:16 +0000278 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000279 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000280 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000281 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000282
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000283 def sendeprt(self, host, port):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000284 '''Send a EPRT command with the current host and the given port number.'''
285 af = 0
286 if self.af == socket.AF_INET:
287 af = 1
288 if self.af == socket.AF_INET6:
289 af = 2
290 if af == 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000291 raise error_proto('unsupported address family')
Walter Dörwald70a6b492004-02-12 17:35:32 +0000292 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000293 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000294 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000295
Tim Peters88869f92001-01-14 23:36:06 +0000296 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000297 '''Create a new socket and send a PORT command for it.'''
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100298 err = None
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000299 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000300 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
301 af, socktype, proto, canonname, sa = res
302 try:
303 sock = socket.socket(af, socktype, proto)
304 sock.bind(sa)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200305 except OSError as _:
Giampaolo Rodola'57f34872012-12-17 20:46:16 +0100306 err = _
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000307 if sock:
308 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000309 sock = None
310 continue
311 break
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100312 if sock is None:
313 if err is not None:
314 raise err
315 else:
Andrew Svetlov0832af62012-12-18 23:10:48 +0200316 raise OSError("getaddrinfo returns an empty list")
317 raise OSError(msg)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000318 sock.listen(1)
319 port = sock.getsockname()[1] # Get proper port
320 host = self.sock.getsockname()[0] # Get proper host
321 if self.af == socket.AF_INET:
322 resp = self.sendport(host, port)
323 else:
324 resp = self.sendeprt(host, port)
Giampaolo RodolĂ 5fb313b2010-04-19 22:05:54 +0000325 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
326 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000327 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000328
329 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000330 if self.af == socket.AF_INET:
331 host, port = parse227(self.sendcmd('PASV'))
332 else:
333 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
334 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000335
Tim Peters88869f92001-01-14 23:36:06 +0000336 def ntransfercmd(self, cmd, rest=None):
337 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000338
Tim Peters88869f92001-01-14 23:36:06 +0000339 If the transfer is active, send a port command and the
340 transfer command, and accept the connection. If the server is
341 passive, send a pasv command, connect to it, and start the
342 transfer command. Either way, return the socket for the
343 connection and the expected size of the transfer. The
344 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000345
Tim Peters88869f92001-01-14 23:36:06 +0000346 Optional `rest' argument can be a string that is sent as the
Christian Heimes1af737c2008-01-23 08:24:23 +0000347 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000348 marker used to tell the server to skip over any data up to the
349 given marker.
350 """
351 size = None
352 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000353 host, port = self.makepasv()
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000354 conn = socket.create_connection((host, port), self.timeout,
355 source_address=self.source_address)
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200356 try:
357 if rest is not None:
358 self.sendcmd("REST %s" % rest)
359 resp = self.sendcmd(cmd)
360 # Some servers apparently send a 200 reply to
361 # a LIST or STOR command, before the 150 reply
362 # (and way before the 226 reply). This seems to
363 # be in violation of the protocol (which only allows
364 # 1xx or error messages for LIST), so we just discard
365 # this response.
366 if resp[0] == '2':
367 resp = self.getresp()
368 if resp[0] != '1':
369 raise error_reply(resp)
370 except:
371 conn.close()
372 raise
Tim Peters88869f92001-01-14 23:36:06 +0000373 else:
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100374 with self.makeport() as sock:
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200375 if rest is not None:
376 self.sendcmd("REST %s" % rest)
377 resp = self.sendcmd(cmd)
378 # See above.
379 if resp[0] == '2':
380 resp = self.getresp()
381 if resp[0] != '1':
382 raise error_reply(resp)
383 conn, sockaddr = sock.accept()
384 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
385 conn.settimeout(self.timeout)
Tim Peters88869f92001-01-14 23:36:06 +0000386 if resp[:3] == '150':
387 # this is conditional in case we received a 125
388 size = parse150(resp)
389 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000390
Tim Peters88869f92001-01-14 23:36:06 +0000391 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000392 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000393 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000394
Tim Peters88869f92001-01-14 23:36:06 +0000395 def login(self, user = '', passwd = '', acct = ''):
396 '''Login, default anonymous.'''
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100397 if not user:
398 user = 'anonymous'
399 if not passwd:
400 passwd = ''
401 if not acct:
402 acct = ''
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000403 if user == 'anonymous' and passwd in {'', '-'}:
Tim Peterse4418602002-02-16 07:34:19 +0000404 # If there is no anonymous ftp password specified
405 # then we'll just use anonymous@
406 # We don't send any other thing because:
407 # - We want to remain anonymous
408 # - We want to stop SPAM
409 # - We don't want to let ftp sites to discriminate by the user,
410 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000411 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000412 resp = self.sendcmd('USER ' + user)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100413 if resp[0] == '3':
414 resp = self.sendcmd('PASS ' + passwd)
415 if resp[0] == '3':
416 resp = self.sendcmd('ACCT ' + acct)
Tim Peters88869f92001-01-14 23:36:06 +0000417 if resp[0] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000418 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000419 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000420
Tim Peters88869f92001-01-14 23:36:06 +0000421 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000422 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000423
Christian Heimes1af737c2008-01-23 08:24:23 +0000424 Args:
425 cmd: A RETR command.
426 callback: A single parameter callable to be called on each
427 block of data read.
428 blocksize: The maximum number of bytes to read from the
429 socket at one time. [default: 8192]
430 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000431
Christian Heimes1af737c2008-01-23 08:24:23 +0000432 Returns:
433 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000434 """
435 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000436 with self.transfercmd(cmd, rest) as conn:
437 while 1:
438 data = conn.recv(blocksize)
439 if not data:
440 break
441 callback(data)
Tim Peters88869f92001-01-14 23:36:06 +0000442 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000443
Tim Peters88869f92001-01-14 23:36:06 +0000444 def retrlines(self, cmd, callback = None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000445 """Retrieve data in line mode. A new port is created for you.
446
447 Args:
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200448 cmd: A RETR, LIST, or NLST command.
Christian Heimes1af737c2008-01-23 08:24:23 +0000449 callback: An optional single parameter callable that is called
450 for each line with the trailing CRLF stripped.
451 [default: print_line()]
452
453 Returns:
454 The response code.
455 """
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100456 if callback is None:
457 callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000458 resp = self.sendcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000459 with self.transfercmd(cmd) as conn, \
460 conn.makefile('r', encoding=self.encoding) as fp:
461 while 1:
462 line = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100463 if self.debugging > 2:
464 print('*retr*', repr(line))
Benjamin Petersona8071372010-10-31 18:21:16 +0000465 if not line:
466 break
467 if line[-2:] == CRLF:
468 line = line[:-2]
469 elif line[-1:] == '\n':
470 line = line[:-1]
471 callback(line)
Tim Peters88869f92001-01-14 23:36:06 +0000472 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000473
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000474 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000475 """Store a file in binary mode. A new port is created for you.
476
477 Args:
478 cmd: A STOR command.
479 fp: A file-like object with a read(num_bytes) method.
480 blocksize: The maximum data size to read from fp and send over
481 the connection at once. [default: 8192]
482 callback: An optional single parameter callable that is called on
483 on each block of data after it is sent. [default: None]
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000484 rest: Passed to transfercmd(). [default: None]
Christian Heimes1af737c2008-01-23 08:24:23 +0000485
486 Returns:
487 The response code.
488 """
Tim Peters88869f92001-01-14 23:36:06 +0000489 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000490 with self.transfercmd(cmd, rest) as conn:
491 while 1:
492 buf = fp.read(blocksize)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100493 if not buf:
494 break
Benjamin Petersona8071372010-10-31 18:21:16 +0000495 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100496 if callback:
497 callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000498 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000499
Christian Heimes1af737c2008-01-23 08:24:23 +0000500 def storlines(self, cmd, fp, callback=None):
501 """Store a file in line mode. A new port is created for you.
502
503 Args:
504 cmd: A STOR command.
505 fp: A file-like object with a readline() method.
506 callback: An optional single parameter callable that is called on
507 on each line after it is sent. [default: None]
508
509 Returns:
510 The response code.
511 """
Tim Peters88869f92001-01-14 23:36:06 +0000512 self.voidcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000513 with self.transfercmd(cmd) as conn:
514 while 1:
515 buf = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100516 if not buf:
517 break
Benjamin Petersona8071372010-10-31 18:21:16 +0000518 if buf[-2:] != B_CRLF:
519 if buf[-1] in B_CRLF: buf = buf[:-1]
520 buf = buf + B_CRLF
521 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100522 if callback:
523 callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000524 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000525
Tim Peters88869f92001-01-14 23:36:06 +0000526 def acct(self, password):
527 '''Send new account name.'''
528 cmd = 'ACCT ' + password
529 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000530
Tim Peters88869f92001-01-14 23:36:06 +0000531 def nlst(self, *args):
532 '''Return a list of files in a given directory (default the current).'''
533 cmd = 'NLST'
534 for arg in args:
535 cmd = cmd + (' ' + arg)
536 files = []
537 self.retrlines(cmd, files.append)
538 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000539
Tim Peters88869f92001-01-14 23:36:06 +0000540 def dir(self, *args):
541 '''List a directory in long form.
542 By default list current directory to stdout.
543 Optional last argument is callback function; all
544 non-empty arguments before it are concatenated to the
545 LIST command. (This *should* only be used for a pathname.)'''
546 cmd = 'LIST'
547 func = None
548 if args[-1:] and type(args[-1]) != type(''):
549 args, func = args[:-1], args[-1]
550 for arg in args:
551 if arg:
552 cmd = cmd + (' ' + arg)
553 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000554
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200555 def mlsd(self, path="", facts=[]):
556 '''List a directory in a standardized format by using MLSD
557 command (RFC-3659). If path is omitted the current directory
558 is assumed. "facts" is a list of strings representing the type
559 of information desired (e.g. ["type", "size", "perm"]).
560
561 Return a generator object yielding a tuple of two elements
562 for every file found in path.
563 First element is the file name, the second one is a dictionary
564 including a variable number of "facts" depending on the server
565 and whether "facts" argument has been provided.
566 '''
567 if facts:
568 self.sendcmd("OPTS MLST " + ";".join(facts) + ";")
569 if path:
570 cmd = "MLSD %s" % path
571 else:
572 cmd = "MLSD"
573 lines = []
574 self.retrlines(cmd, lines.append)
575 for line in lines:
576 facts_found, _, name = line.rstrip(CRLF).partition(' ')
577 entry = {}
578 for fact in facts_found[:-1].split(";"):
579 key, _, value = fact.partition("=")
580 entry[key.lower()] = value
581 yield (name, entry)
582
Tim Peters88869f92001-01-14 23:36:06 +0000583 def rename(self, fromname, toname):
584 '''Rename a file.'''
585 resp = self.sendcmd('RNFR ' + fromname)
586 if resp[0] != '3':
Collin Winterce36ad82007-08-30 01:19:48 +0000587 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000588 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000589
Tim Peters88869f92001-01-14 23:36:06 +0000590 def delete(self, filename):
591 '''Delete a file.'''
592 resp = self.sendcmd('DELE ' + filename)
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000593 if resp[:3] in {'250', '200'}:
Tim Peters88869f92001-01-14 23:36:06 +0000594 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000595 else:
Collin Winterce36ad82007-08-30 01:19:48 +0000596 raise error_reply(resp)
Guido van Rossum02cf5821993-05-17 08:00:02 +0000597
Tim Peters88869f92001-01-14 23:36:06 +0000598 def cwd(self, dirname):
599 '''Change to a directory.'''
600 if dirname == '..':
601 try:
602 return self.voidcmd('CDUP')
Guido van Rossumb940e112007-01-10 16:19:56 +0000603 except error_perm as msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000604 if msg.args[0][:3] != '500':
605 raise
Tim Peters88869f92001-01-14 23:36:06 +0000606 elif dirname == '':
607 dirname = '.' # does nothing, but could return error
608 cmd = 'CWD ' + dirname
609 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000610
Tim Peters88869f92001-01-14 23:36:06 +0000611 def size(self, filename):
612 '''Retrieve the size of a file.'''
Christian Heimes1af737c2008-01-23 08:24:23 +0000613 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000614 resp = self.sendcmd('SIZE ' + filename)
615 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000616 s = resp[3:].strip()
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200617 return int(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000618
Tim Peters88869f92001-01-14 23:36:06 +0000619 def mkd(self, dirname):
620 '''Make a directory, return its full pathname.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000621 resp = self.voidcmd('MKD ' + dirname)
622 # fix around non-compliant implementations such as IIS shipped
623 # with Windows server 2003
624 if not resp.startswith('257'):
625 return ''
Tim Peters88869f92001-01-14 23:36:06 +0000626 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000627
Tim Peters88869f92001-01-14 23:36:06 +0000628 def rmd(self, dirname):
629 '''Remove a directory.'''
630 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000631
Tim Peters88869f92001-01-14 23:36:06 +0000632 def pwd(self):
633 '''Return current working directory.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000634 resp = self.voidcmd('PWD')
635 # fix around non-compliant implementations such as IIS shipped
636 # with Windows server 2003
637 if not resp.startswith('257'):
638 return ''
Tim Peters88869f92001-01-14 23:36:06 +0000639 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000640
Tim Peters88869f92001-01-14 23:36:06 +0000641 def quit(self):
642 '''Quit, and close the connection.'''
643 resp = self.voidcmd('QUIT')
644 self.close()
645 return resp
646
647 def close(self):
648 '''Close the connection without assuming anything about it.'''
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000649 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000650 self.file.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000651 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000652 self.sock.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000653 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000654
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000655try:
656 import ssl
657except ImportError:
658 pass
659else:
660 class FTP_TLS(FTP):
661 '''A FTP subclass which adds TLS support to FTP as described
662 in RFC-4217.
663
664 Connect as usual to port 21 implicitly securing the FTP control
665 connection before authenticating.
666
667 Securing the data connection requires user to explicitly ask
668 for it by calling prot_p() method.
669
670 Usage example:
671 >>> from ftplib import FTP_TLS
672 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti4969f702011-03-15 05:59:46 +0200673 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000674 '230 Guest login ok, access restrictions apply.'
675 >>> ftps.prot_p() # switch to secure data connection
676 '200 Protection level set to P'
677 >>> ftps.retrlines('LIST') # list directory content securely
678 total 9
679 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
680 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
681 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
682 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
683 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
684 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
685 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
686 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
687 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
688 '226 Transfer complete.'
689 >>> ftps.quit()
690 '221 Goodbye.'
691 >>>
692 '''
693 ssl_version = ssl.PROTOCOL_TLSv1
694
695 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000696 certfile=None, context=None,
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000697 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000698 if context is not None and keyfile is not None:
699 raise ValueError("context and keyfile arguments are mutually "
700 "exclusive")
701 if context is not None and certfile is not None:
702 raise ValueError("context and certfile arguments are mutually "
703 "exclusive")
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000704 self.keyfile = keyfile
705 self.certfile = certfile
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000706 self.context = context
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000707 self._prot_p = False
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000708 FTP.__init__(self, host, user, passwd, acct, timeout, source_address)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000709
710 def login(self, user='', passwd='', acct='', secure=True):
711 if secure and not isinstance(self.sock, ssl.SSLSocket):
712 self.auth()
713 return FTP.login(self, user, passwd, acct)
714
715 def auth(self):
716 '''Set up secure control connection by using TLS/SSL.'''
717 if isinstance(self.sock, ssl.SSLSocket):
718 raise ValueError("Already using TLS")
719 if self.ssl_version == ssl.PROTOCOL_TLSv1:
720 resp = self.voidcmd('AUTH TLS')
721 else:
722 resp = self.voidcmd('AUTH SSL')
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000723 if self.context is not None:
724 self.sock = self.context.wrap_socket(self.sock)
725 else:
726 self.sock = ssl.wrap_socket(self.sock, self.keyfile,
727 self.certfile,
728 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000729 self.file = self.sock.makefile(mode='r', encoding=self.encoding)
730 return resp
731
Giampaolo Rodola'096dcb12011-06-27 11:17:51 +0200732 def ccc(self):
733 '''Switch back to a clear-text control connection.'''
734 if not isinstance(self.sock, ssl.SSLSocket):
735 raise ValueError("not using TLS")
736 resp = self.voidcmd('CCC')
737 self.sock = self.sock.unwrap()
738 return resp
739
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000740 def prot_p(self):
741 '''Set up secure data connection.'''
742 # PROT defines whether or not the data channel is to be protected.
743 # Though RFC-2228 defines four possible protection levels,
744 # RFC-4217 only recommends two, Clear and Private.
745 # Clear (PROT C) means that no security is to be used on the
746 # data-channel, Private (PROT P) means that the data-channel
747 # should be protected by TLS.
748 # PBSZ command MUST still be issued, but must have a parameter of
749 # '0' to indicate that no buffering is taking place and the data
750 # connection should not be encapsulated.
751 self.voidcmd('PBSZ 0')
752 resp = self.voidcmd('PROT P')
753 self._prot_p = True
754 return resp
755
756 def prot_c(self):
757 '''Set up clear text data connection.'''
758 resp = self.voidcmd('PROT C')
759 self._prot_p = False
760 return resp
761
762 # --- Overridden FTP methods
763
764 def ntransfercmd(self, cmd, rest=None):
765 conn, size = FTP.ntransfercmd(self, cmd, rest)
766 if self._prot_p:
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000767 if self.context is not None:
768 conn = self.context.wrap_socket(conn)
769 else:
770 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
771 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000772 return conn, size
773
774 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
775 self.voidcmd('TYPE I')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100776 with self.transfercmd(cmd, rest) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000777 while 1:
778 data = conn.recv(blocksize)
779 if not data:
780 break
781 callback(data)
782 # shutdown ssl layer
783 if isinstance(conn, ssl.SSLSocket):
784 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000785 return self.voidresp()
786
787 def retrlines(self, cmd, callback = None):
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100788 if callback is None:
789 callback = print_line
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000790 resp = self.sendcmd('TYPE A')
791 conn = self.transfercmd(cmd)
792 fp = conn.makefile('r', encoding=self.encoding)
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100793 with fp, conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000794 while 1:
795 line = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100796 if self.debugging > 2:
797 print('*retr*', repr(line))
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000798 if not line:
799 break
800 if line[-2:] == CRLF:
801 line = line[:-2]
802 elif line[-1:] == '\n':
803 line = line[:-1]
804 callback(line)
805 # shutdown ssl layer
806 if isinstance(conn, ssl.SSLSocket):
807 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000808 return self.voidresp()
809
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000810 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000811 self.voidcmd('TYPE I')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100812 with self.transfercmd(cmd, rest) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000813 while 1:
814 buf = fp.read(blocksize)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100815 if not buf:
816 break
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000817 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100818 if callback:
819 callback(buf)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000820 # shutdown ssl layer
821 if isinstance(conn, ssl.SSLSocket):
822 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000823 return self.voidresp()
824
825 def storlines(self, cmd, fp, callback=None):
826 self.voidcmd('TYPE A')
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100827 with self.transfercmd(cmd) as conn:
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000828 while 1:
829 buf = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100830 if not buf:
831 break
Giampaolo RodolĂ f96482e2010-08-04 10:36:18 +0000832 if buf[-2:] != B_CRLF:
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100833 if buf[-1] in B_CRLF:
834 buf = buf[:-1]
Giampaolo RodolĂ f96482e2010-08-04 10:36:18 +0000835 buf = buf + B_CRLF
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000836 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100837 if callback:
838 callback(buf)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000839 # shutdown ssl layer
840 if isinstance(conn, ssl.SSLSocket):
841 conn.unwrap()
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000842 return self.voidresp()
843
Giampaolo Rodola'24befa82011-05-07 19:09:34 +0200844 def abort(self):
845 # overridden as we can't pass MSG_OOB flag to sendall()
846 line = b'ABOR' + B_CRLF
847 self.sock.sendall(line)
848 resp = self.getmultiline()
849 if resp[:3] not in {'426', '225', '226'}:
850 raise error_proto(resp)
851 return resp
852
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000853 __all__.append('FTP_TLS')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200854 all_errors = (Error, OSError, EOFError, ssl.SSLError)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000855
856
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000857_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000858
859def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000860 '''Parse the '150' response for a RETR request.
861 Returns the expected transfer size or None; size is not guaranteed to
862 be present in the 150 message.
863 '''
864 if resp[:3] != '150':
Collin Winterce36ad82007-08-30 01:19:48 +0000865 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000866 global _150_re
867 if _150_re is None:
868 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000869 _150_re = re.compile(
870 "150 .* \((\d+) bytes\)", re.IGNORECASE | re.ASCII)
Tim Peters88869f92001-01-14 23:36:06 +0000871 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000872 if not m:
873 return None
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200874 return int(m.group(1))
Fred Drake4de02d91997-01-10 18:26:09 +0000875
876
Guido van Rossum70297d32001-08-17 17:24:29 +0000877_227_re = None
878
Guido van Rossumd2560b01996-05-28 23:41:25 +0000879def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000880 '''Parse the '227' response for a PASV request.
881 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
882 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000883
Tim Peters88869f92001-01-14 23:36:06 +0000884 if resp[:3] != '227':
Collin Winterce36ad82007-08-30 01:19:48 +0000885 raise error_reply(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000886 global _227_re
887 if _227_re is None:
888 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000889 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)', re.ASCII)
Guido van Rossum70297d32001-08-17 17:24:29 +0000890 m = _227_re.search(resp)
891 if not m:
Collin Winterce36ad82007-08-30 01:19:48 +0000892 raise error_proto(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000893 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000894 host = '.'.join(numbers[:4])
895 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000896 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000897
898
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000899def parse229(resp, peer):
900 '''Parse the '229' response for a EPSV request.
901 Raises error_proto if it does not contain '(|||port|)'
902 Return ('host.addr.as.numbers', port#) tuple.'''
903
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000904 if resp[:3] != '229':
Collin Winterce36ad82007-08-30 01:19:48 +0000905 raise error_reply(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000906 left = resp.find('(')
Collin Winterce36ad82007-08-30 01:19:48 +0000907 if left < 0: raise error_proto(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000908 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000909 if right < 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000910 raise error_proto(resp) # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000911 if resp[left + 1] != resp[right - 1]:
Collin Winterce36ad82007-08-30 01:19:48 +0000912 raise error_proto(resp)
Walter Dörwalda401ae42002-06-03 10:41:45 +0000913 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000914 if len(parts) != 5:
Collin Winterce36ad82007-08-30 01:19:48 +0000915 raise error_proto(resp)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000916 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000917 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000918 return host, port
919
920
Guido van Rossumc567c601992-11-05 22:22:37 +0000921def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000922 '''Parse the '257' response for a MKD or PWD request.
923 This is a response to a MKD or PWD request: a directory name.
924 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000925
Tim Peters88869f92001-01-14 23:36:06 +0000926 if resp[:3] != '257':
Collin Winterce36ad82007-08-30 01:19:48 +0000927 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000928 if resp[3:5] != ' "':
929 return '' # Not compliant to RFC 959, but UNIX ftpd does this
930 dirname = ''
931 i = 5
932 n = len(resp)
933 while i < n:
934 c = resp[i]
935 i = i+1
936 if c == '"':
937 if i >= n or resp[i] != '"':
938 break
939 i = i+1
940 dirname = dirname + c
941 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000942
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000943
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000944def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000945 '''Default retrlines callback to print a line.'''
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000946 print(line)
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000947
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000948
Guido van Rossumd2560b01996-05-28 23:41:25 +0000949def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000950 '''Copy file from one FTP-instance to another.'''
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100951 if not targetname:
952 targetname = sourcename
Tim Peters88869f92001-01-14 23:36:06 +0000953 type = 'TYPE ' + type
954 source.voidcmd(type)
955 target.voidcmd(type)
956 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
957 target.sendport(sourcehost, sourceport)
958 # RFC 959: the user must "listen" [...] BEFORE sending the
959 # transfer request.
960 # So: STOR before RETR, because here the target is a "user".
961 treply = target.sendcmd('STOR ' + targetname)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100962 if treply[:3] not in {'125', '150'}:
963 raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000964 sreply = source.sendcmd('RETR ' + sourcename)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100965 if sreply[:3] not in {'125', '150'}:
966 raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000967 source.voidresp()
968 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000969
Tim Peters88869f92001-01-14 23:36:06 +0000970
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000971class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000972 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000973
Tim Peters88869f92001-01-14 23:36:06 +0000974 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000975
Tim Peters88869f92001-01-14 23:36:06 +0000976 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000977
Tim Peters88869f92001-01-14 23:36:06 +0000978 """
979 __defuser = None
980 __defpasswd = None
981 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000982
Tim Peters88869f92001-01-14 23:36:06 +0000983 def __init__(self, filename=None):
R David Murray87632f12013-02-19 18:32:28 -0500984 warnings.warn("This class is deprecated, use the netrc module instead",
985 DeprecationWarning, 2)
Raymond Hettinger094662a2002-06-01 01:29:16 +0000986 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000987 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000988 filename = os.path.join(os.environ["HOME"],
989 ".netrc")
990 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200991 raise OSError("specify file to load or set $HOME")
Tim Peters88869f92001-01-14 23:36:06 +0000992 self.__hosts = {}
993 self.__macros = {}
994 fp = open(filename, "r")
995 in_macro = 0
996 while 1:
997 line = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100998 if not line:
999 break
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001000 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +00001001 macro_lines.append(line)
1002 continue
1003 elif in_macro:
1004 self.__macros[macro_name] = tuple(macro_lines)
1005 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001006 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +00001007 host = user = passwd = acct = None
1008 default = 0
1009 i = 0
1010 while i < len(words):
1011 w1 = words[i]
1012 if i+1 < len(words):
1013 w2 = words[i + 1]
1014 else:
1015 w2 = None
1016 if w1 == 'default':
1017 default = 1
1018 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001019 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001020 i = i + 1
1021 elif w1 == 'login' and w2:
1022 user = w2
1023 i = i + 1
1024 elif w1 == 'password' and w2:
1025 passwd = w2
1026 i = i + 1
1027 elif w1 == 'account' and w2:
1028 acct = w2
1029 i = i + 1
1030 elif w1 == 'macdef' and w2:
1031 macro_name = w2
1032 macro_lines = []
1033 in_macro = 1
1034 break
1035 i = i + 1
1036 if default:
1037 self.__defuser = user or self.__defuser
1038 self.__defpasswd = passwd or self.__defpasswd
1039 self.__defacct = acct or self.__defacct
1040 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001041 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001042 ouser, opasswd, oacct = \
1043 self.__hosts[host]
1044 user = user or ouser
1045 passwd = passwd or opasswd
1046 acct = acct or oacct
1047 self.__hosts[host] = user, passwd, acct
1048 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001049
Tim Peters88869f92001-01-14 23:36:06 +00001050 def get_hosts(self):
1051 """Return a list of hosts mentioned in the .netrc file."""
1052 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001053
Tim Peters88869f92001-01-14 23:36:06 +00001054 def get_account(self, host):
1055 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001056
Tim Peters88869f92001-01-14 23:36:06 +00001057 The return value is a triple containing userid,
1058 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001059
Tim Peters88869f92001-01-14 23:36:06 +00001060 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001061 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001062 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001063 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001064 user, passwd, acct = self.__hosts[host]
1065 user = user or self.__defuser
1066 passwd = passwd or self.__defpasswd
1067 acct = acct or self.__defacct
1068 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001069
Tim Peters88869f92001-01-14 23:36:06 +00001070 def get_macros(self):
1071 """Return a list of all defined macro names."""
1072 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001073
Tim Peters88869f92001-01-14 23:36:06 +00001074 def get_macro(self, macro):
1075 """Return a sequence of lines which define a named macro."""
1076 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001077
Fred Drake475d51d1997-06-24 22:02:54 +00001078
Tim Peters88869f92001-01-14 23:36:06 +00001079
Guido van Rossum1115ab21992-11-04 15:51:30 +00001080def test():
Tim Peters88869f92001-01-14 23:36:06 +00001081 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001082 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1083
1084 -d dir
1085 -l list
1086 -p password
1087 '''
1088
1089 if len(sys.argv) < 2:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001090 print(test.__doc__)
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001091 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001092
Tim Peters88869f92001-01-14 23:36:06 +00001093 debugging = 0
1094 rcfile = None
1095 while sys.argv[1] == '-d':
1096 debugging = debugging+1
1097 del sys.argv[1]
1098 if sys.argv[1][:2] == '-r':
1099 # get name of alternate ~/.netrc file:
1100 rcfile = sys.argv[1][2:]
1101 del sys.argv[1]
1102 host = sys.argv[1]
1103 ftp = FTP(host)
1104 ftp.set_debuglevel(debugging)
1105 userid = passwd = acct = ''
1106 try:
1107 netrc = Netrc(rcfile)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001108 except OSError:
Tim Peters88869f92001-01-14 23:36:06 +00001109 if rcfile is not None:
1110 sys.stderr.write("Could not open account file"
1111 " -- using anonymous login.")
1112 else:
1113 try:
1114 userid, passwd, acct = netrc.get_account(host)
1115 except KeyError:
1116 # no account for host
1117 sys.stderr.write(
1118 "No account -- using anonymous login.")
1119 ftp.login(userid, passwd, acct)
1120 for file in sys.argv[2:]:
1121 if file[:2] == '-l':
1122 ftp.dir(file[2:])
1123 elif file[:2] == '-d':
1124 cmd = 'CWD'
1125 if file[2:]: cmd = cmd + ' ' + file[2:]
1126 resp = ftp.sendcmd(cmd)
1127 elif file == '-p':
1128 ftp.set_pasv(not ftp.passiveserver)
1129 else:
1130 ftp.retrbinary('RETR ' + file, \
1131 sys.stdout.write, 1024)
1132 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001133
1134
1135if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001136 test()