blob: fcd4b148c32b39166fab493fa48054fbf8331397 [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 Rodola'11a9bd62013-04-26 15:23:43 +0200137 - timeout: the timeout to set against the ftp socket(s)
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000138 - source_address: a 2-tuple (host, port) for the socket to bind
139 to as its source address before connecting.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140 '''
141 if host != '':
142 self.host = host
143 if port > 0:
144 self.port = port
Georg Brandlf78e02b2008-06-10 17:40:04 +0000145 if timeout != -999:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000146 self.timeout = timeout
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000147 if source_address is not None:
148 self.source_address = source_address
149 self.sock = socket.create_connection((self.host, self.port), self.timeout,
150 source_address=self.source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000151 self.af = self.sock.family
Guido van Rossum52b89762007-07-17 20:45:57 +0000152 self.file = self.sock.makefile('r', encoding=self.encoding)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000153 self.welcome = self.getresp()
154 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000155
Tim Peters88869f92001-01-14 23:36:06 +0000156 def getwelcome(self):
157 '''Get the welcome message from the server.
158 (this is read and squirreled away by connect())'''
159 if self.debugging:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000160 print('*welcome*', self.sanitize(self.welcome))
Tim Peters88869f92001-01-14 23:36:06 +0000161 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000162
Tim Peters88869f92001-01-14 23:36:06 +0000163 def set_debuglevel(self, level):
164 '''Set the debugging level.
165 The required argument level means:
166 0: no debugging output (default)
167 1: print commands and responses but not body text etc.
168 2: also print raw lines read and sent before stripping CR/LF'''
169 self.debugging = level
170 debug = set_debuglevel
Guido van Rossum1115ab21992-11-04 15:51:30 +0000171
Tim Peters88869f92001-01-14 23:36:06 +0000172 def set_pasv(self, val):
173 '''Use passive or active mode for data transfers.
174 With a false argument, use the normal PORT mode,
175 With a true argument, use the PASV command.'''
176 self.passiveserver = val
Guido van Rossumd2560b01996-05-28 23:41:25 +0000177
Tim Peters88869f92001-01-14 23:36:06 +0000178 # Internal: "sanitize" a string for printing
179 def sanitize(self, s):
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200180 if s[:5] in {'pass ', 'PASS '}:
181 i = len(s.rstrip('\r\n'))
Tim Peters88869f92001-01-14 23:36:06 +0000182 s = s[:5] + '*'*(i-5) + s[i:]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000183 return repr(s)
Guido van Rossumebaf1041995-05-05 15:54:14 +0000184
Tim Peters88869f92001-01-14 23:36:06 +0000185 # Internal: send one line to the server, appending CRLF
186 def putline(self, line):
187 line = line + CRLF
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100188 if self.debugging > 1:
189 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):
200 line = self.file.readline()
201 if self.debugging > 1:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000202 print('*get*', self.sanitize(line))
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100203 if not line:
204 raise EOFError
205 if line[-2:] == CRLF:
206 line = line[:-2]
207 elif line[-1:] in CRLF:
208 line = line[:-1]
Tim Peters88869f92001-01-14 23:36:06 +0000209 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000210
Tim Peters88869f92001-01-14 23:36:06 +0000211 # Internal: get a response from the server, which may possibly
212 # consist of multiple lines. Return a single string with no
213 # trailing CRLF. If the response consists of multiple lines,
214 # these are separated by '\n' characters in the string
215 def getmultiline(self):
216 line = self.getline()
217 if line[3:4] == '-':
218 code = line[:3]
219 while 1:
220 nextline = self.getline()
221 line = line + ('\n' + nextline)
222 if nextline[:3] == code and \
223 nextline[3:4] != '-':
224 break
225 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000226
Tim Peters88869f92001-01-14 23:36:06 +0000227 # Internal: get a response from the server.
228 # Raise various errors if the response indicates an error
229 def getresp(self):
230 resp = self.getmultiline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100231 if self.debugging:
232 print('*resp*', self.sanitize(resp))
Tim Peters88869f92001-01-14 23:36:06 +0000233 self.lastresp = resp[:3]
234 c = resp[:1]
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000235 if c in {'1', '2', '3'}:
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000236 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000237 if c == '4':
Collin Winterce36ad82007-08-30 01:19:48 +0000238 raise error_temp(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000239 if c == '5':
Collin Winterce36ad82007-08-30 01:19:48 +0000240 raise error_perm(resp)
241 raise error_proto(resp)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000242
Tim Peters88869f92001-01-14 23:36:06 +0000243 def voidresp(self):
244 """Expect a response beginning with '2'."""
245 resp = self.getresp()
Benjamin Petersond23f8222009-04-05 19:13:16 +0000246 if resp[:1] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000247 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000248 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000249
Tim Peters88869f92001-01-14 23:36:06 +0000250 def abort(self):
251 '''Abort a file transfer. Uses out-of-band data.
252 This does not follow the procedure from the RFC to send Telnet
253 IP and Synch; that doesn't seem to work with the servers I've
254 tried. Instead, just send the ABOR command as OOB data.'''
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200255 line = b'ABOR' + B_CRLF
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100256 if self.debugging > 1:
257 print('*put urgent*', self.sanitize(line))
Martin v. Löwise12454f2002-02-16 23:06:19 +0000258 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000259 resp = self.getmultiline()
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000260 if resp[:3] not in {'426', '225', '226'}:
Collin Winterce36ad82007-08-30 01:19:48 +0000261 raise error_proto(resp)
Giampaolo Rodola'0b5c21f2011-05-07 19:03:47 +0200262 return resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000263
Tim Peters88869f92001-01-14 23:36:06 +0000264 def sendcmd(self, cmd):
265 '''Send a command and return the response.'''
266 self.putcmd(cmd)
267 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000268
Tim Peters88869f92001-01-14 23:36:06 +0000269 def voidcmd(self, cmd):
270 """Send a command and expect a response beginning with '2'."""
271 self.putcmd(cmd)
272 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000273
Tim Peters88869f92001-01-14 23:36:06 +0000274 def sendport(self, host, port):
275 '''Send a PORT command with the current host and the given
276 port number.
277 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000278 hbytes = host.split('.')
Benjamin Peterson3a53fbb2008-09-27 22:04:16 +0000279 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000280 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000281 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000282 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000283
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000284 def sendeprt(self, host, port):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000285 '''Send a EPRT command with the current host and the given port number.'''
286 af = 0
287 if self.af == socket.AF_INET:
288 af = 1
289 if self.af == socket.AF_INET6:
290 af = 2
291 if af == 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000292 raise error_proto('unsupported address family')
Walter Dörwald70a6b492004-02-12 17:35:32 +0000293 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000294 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000295 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000296
Tim Peters88869f92001-01-14 23:36:06 +0000297 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000298 '''Create a new socket and send a PORT command for it.'''
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100299 err = None
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000300 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000301 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
302 af, socktype, proto, canonname, sa = res
303 try:
304 sock = socket.socket(af, socktype, proto)
305 sock.bind(sa)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200306 except OSError as _:
Giampaolo Rodola'57f34872012-12-17 20:46:16 +0100307 err = _
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000308 if sock:
309 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000310 sock = None
311 continue
312 break
Giampaolo Rodola'fc327882012-12-17 14:20:27 +0100313 if sock is None:
314 if err is not None:
315 raise err
316 else:
Andrew Svetlov0832af62012-12-18 23:10:48 +0200317 raise OSError("getaddrinfo returns an empty list")
318 raise OSError(msg)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000319 sock.listen(1)
320 port = sock.getsockname()[1] # Get proper port
321 host = self.sock.getsockname()[0] # Get proper host
322 if self.af == socket.AF_INET:
323 resp = self.sendport(host, port)
324 else:
325 resp = self.sendeprt(host, port)
Giampaolo RodolĂ 5fb313b2010-04-19 22:05:54 +0000326 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
327 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000328 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000329
330 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000331 if self.af == socket.AF_INET:
332 host, port = parse227(self.sendcmd('PASV'))
333 else:
334 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
335 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000336
Tim Peters88869f92001-01-14 23:36:06 +0000337 def ntransfercmd(self, cmd, rest=None):
338 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000339
Tim Peters88869f92001-01-14 23:36:06 +0000340 If the transfer is active, send a port command and the
341 transfer command, and accept the connection. If the server is
342 passive, send a pasv command, connect to it, and start the
343 transfer command. Either way, return the socket for the
344 connection and the expected size of the transfer. The
345 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000346
Tim Peters88869f92001-01-14 23:36:06 +0000347 Optional `rest' argument can be a string that is sent as the
Christian Heimes1af737c2008-01-23 08:24:23 +0000348 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000349 marker used to tell the server to skip over any data up to the
350 given marker.
351 """
352 size = None
353 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000354 host, port = self.makepasv()
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000355 conn = socket.create_connection((host, port), self.timeout,
356 source_address=self.source_address)
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200357 try:
358 if rest is not None:
359 self.sendcmd("REST %s" % rest)
360 resp = self.sendcmd(cmd)
361 # Some servers apparently send a 200 reply to
362 # a LIST or STOR command, before the 150 reply
363 # (and way before the 226 reply). This seems to
364 # be in violation of the protocol (which only allows
365 # 1xx or error messages for LIST), so we just discard
366 # this response.
367 if resp[0] == '2':
368 resp = self.getresp()
369 if resp[0] != '1':
370 raise error_reply(resp)
371 except:
372 conn.close()
373 raise
Tim Peters88869f92001-01-14 23:36:06 +0000374 else:
Giampaolo Rodola'836e9aa2011-12-10 21:25:04 +0100375 with self.makeport() as sock:
Nadeem Vawda08f5f7a2011-07-23 14:03:00 +0200376 if rest is not None:
377 self.sendcmd("REST %s" % rest)
378 resp = self.sendcmd(cmd)
379 # See above.
380 if resp[0] == '2':
381 resp = self.getresp()
382 if resp[0] != '1':
383 raise error_reply(resp)
384 conn, sockaddr = sock.accept()
385 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
386 conn.settimeout(self.timeout)
Tim Peters88869f92001-01-14 23:36:06 +0000387 if resp[:3] == '150':
388 # this is conditional in case we received a 125
389 size = parse150(resp)
390 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000391
Tim Peters88869f92001-01-14 23:36:06 +0000392 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000393 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000394 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000395
Tim Peters88869f92001-01-14 23:36:06 +0000396 def login(self, user = '', passwd = '', acct = ''):
397 '''Login, default anonymous.'''
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100398 if not user:
399 user = 'anonymous'
400 if not passwd:
401 passwd = ''
402 if not acct:
403 acct = ''
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000404 if user == 'anonymous' and passwd in {'', '-'}:
Tim Peterse4418602002-02-16 07:34:19 +0000405 # If there is no anonymous ftp password specified
406 # then we'll just use anonymous@
407 # We don't send any other thing because:
408 # - We want to remain anonymous
409 # - We want to stop SPAM
410 # - We don't want to let ftp sites to discriminate by the user,
411 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000412 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000413 resp = self.sendcmd('USER ' + user)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100414 if resp[0] == '3':
415 resp = self.sendcmd('PASS ' + passwd)
416 if resp[0] == '3':
417 resp = self.sendcmd('ACCT ' + acct)
Tim Peters88869f92001-01-14 23:36:06 +0000418 if resp[0] != '2':
Collin Winterce36ad82007-08-30 01:19:48 +0000419 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000420 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000421
Tim Peters88869f92001-01-14 23:36:06 +0000422 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000423 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000424
Christian Heimes1af737c2008-01-23 08:24:23 +0000425 Args:
426 cmd: A RETR command.
427 callback: A single parameter callable to be called on each
428 block of data read.
429 blocksize: The maximum number of bytes to read from the
430 socket at one time. [default: 8192]
431 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000432
Christian Heimes1af737c2008-01-23 08:24:23 +0000433 Returns:
434 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000435 """
436 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000437 with self.transfercmd(cmd, rest) as conn:
438 while 1:
439 data = conn.recv(blocksize)
440 if not data:
441 break
442 callback(data)
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100443 # shutdown ssl layer
Giampaolo Rodola'a77d7a52013-03-18 09:59:15 +0100444 if _SSLSocket is not None and isinstance(conn, _SSLSocket):
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100445 conn.unwrap()
Tim Peters88869f92001-01-14 23:36:06 +0000446 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000447
Tim Peters88869f92001-01-14 23:36:06 +0000448 def retrlines(self, cmd, callback = None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000449 """Retrieve data in line mode. A new port is created for you.
450
451 Args:
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200452 cmd: A RETR, LIST, or NLST command.
Christian Heimes1af737c2008-01-23 08:24:23 +0000453 callback: An optional single parameter callable that is called
454 for each line with the trailing CRLF stripped.
455 [default: print_line()]
456
457 Returns:
458 The response code.
459 """
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100460 if callback is None:
461 callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000462 resp = self.sendcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000463 with self.transfercmd(cmd) as conn, \
464 conn.makefile('r', encoding=self.encoding) as fp:
465 while 1:
466 line = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100467 if self.debugging > 2:
468 print('*retr*', repr(line))
Benjamin Petersona8071372010-10-31 18:21:16 +0000469 if not line:
470 break
471 if line[-2:] == CRLF:
472 line = line[:-2]
473 elif line[-1:] == '\n':
474 line = line[:-1]
475 callback(line)
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100476 # shutdown ssl layer
Giampaolo Rodola'a77d7a52013-03-18 09:59:15 +0100477 if _SSLSocket is not None and isinstance(conn, _SSLSocket):
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100478 conn.unwrap()
Tim Peters88869f92001-01-14 23:36:06 +0000479 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000480
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000481 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Christian Heimes1af737c2008-01-23 08:24:23 +0000482 """Store a file in binary mode. A new port is created for you.
483
484 Args:
485 cmd: A STOR command.
486 fp: A file-like object with a read(num_bytes) method.
487 blocksize: The maximum data size to read from fp and send over
488 the connection at once. [default: 8192]
489 callback: An optional single parameter callable that is called on
Terry Jan Reedyc30b7b12013-03-11 17:57:08 -0400490 each block of data after it is sent. [default: None]
Antoine Pitrou648bcd72009-11-27 13:23:26 +0000491 rest: Passed to transfercmd(). [default: None]
Christian Heimes1af737c2008-01-23 08:24:23 +0000492
493 Returns:
494 The response code.
495 """
Tim Peters88869f92001-01-14 23:36:06 +0000496 self.voidcmd('TYPE I')
Benjamin Petersona8071372010-10-31 18:21:16 +0000497 with self.transfercmd(cmd, rest) as conn:
498 while 1:
499 buf = fp.read(blocksize)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100500 if not buf:
501 break
Benjamin Petersona8071372010-10-31 18:21:16 +0000502 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100503 if callback:
504 callback(buf)
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100505 # shutdown ssl layer
Giampaolo Rodola'a77d7a52013-03-18 09:59:15 +0100506 if _SSLSocket is not None and isinstance(conn, _SSLSocket):
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100507 conn.unwrap()
Tim Peters88869f92001-01-14 23:36:06 +0000508 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000509
Christian Heimes1af737c2008-01-23 08:24:23 +0000510 def storlines(self, cmd, fp, callback=None):
511 """Store a file in line mode. A new port is created for you.
512
513 Args:
514 cmd: A STOR command.
515 fp: A file-like object with a readline() method.
516 callback: An optional single parameter callable that is called on
Terry Jan Reedyc30b7b12013-03-11 17:57:08 -0400517 each line after it is sent. [default: None]
Christian Heimes1af737c2008-01-23 08:24:23 +0000518
519 Returns:
520 The response code.
521 """
Tim Peters88869f92001-01-14 23:36:06 +0000522 self.voidcmd('TYPE A')
Benjamin Petersona8071372010-10-31 18:21:16 +0000523 with self.transfercmd(cmd) as conn:
524 while 1:
525 buf = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100526 if not buf:
527 break
Benjamin Petersona8071372010-10-31 18:21:16 +0000528 if buf[-2:] != B_CRLF:
529 if buf[-1] in B_CRLF: buf = buf[:-1]
530 buf = buf + B_CRLF
531 conn.sendall(buf)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100532 if callback:
533 callback(buf)
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100534 # shutdown ssl layer
Giampaolo Rodola'a77d7a52013-03-18 09:59:15 +0100535 if _SSLSocket is not None and isinstance(conn, _SSLSocket):
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100536 conn.unwrap()
Tim Peters88869f92001-01-14 23:36:06 +0000537 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000538
Tim Peters88869f92001-01-14 23:36:06 +0000539 def acct(self, password):
540 '''Send new account name.'''
541 cmd = 'ACCT ' + password
542 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000543
Tim Peters88869f92001-01-14 23:36:06 +0000544 def nlst(self, *args):
545 '''Return a list of files in a given directory (default the current).'''
546 cmd = 'NLST'
547 for arg in args:
548 cmd = cmd + (' ' + arg)
549 files = []
550 self.retrlines(cmd, files.append)
551 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000552
Tim Peters88869f92001-01-14 23:36:06 +0000553 def dir(self, *args):
554 '''List a directory in long form.
555 By default list current directory to stdout.
556 Optional last argument is callback function; all
557 non-empty arguments before it are concatenated to the
558 LIST command. (This *should* only be used for a pathname.)'''
559 cmd = 'LIST'
560 func = None
561 if args[-1:] and type(args[-1]) != type(''):
562 args, func = args[:-1], args[-1]
563 for arg in args:
564 if arg:
565 cmd = cmd + (' ' + arg)
566 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000567
Giampaolo Rodola'd78def92011-05-06 19:49:08 +0200568 def mlsd(self, path="", facts=[]):
569 '''List a directory in a standardized format by using MLSD
570 command (RFC-3659). If path is omitted the current directory
571 is assumed. "facts" is a list of strings representing the type
572 of information desired (e.g. ["type", "size", "perm"]).
573
574 Return a generator object yielding a tuple of two elements
575 for every file found in path.
576 First element is the file name, the second one is a dictionary
577 including a variable number of "facts" depending on the server
578 and whether "facts" argument has been provided.
579 '''
580 if facts:
581 self.sendcmd("OPTS MLST " + ";".join(facts) + ";")
582 if path:
583 cmd = "MLSD %s" % path
584 else:
585 cmd = "MLSD"
586 lines = []
587 self.retrlines(cmd, lines.append)
588 for line in lines:
589 facts_found, _, name = line.rstrip(CRLF).partition(' ')
590 entry = {}
591 for fact in facts_found[:-1].split(";"):
592 key, _, value = fact.partition("=")
593 entry[key.lower()] = value
594 yield (name, entry)
595
Tim Peters88869f92001-01-14 23:36:06 +0000596 def rename(self, fromname, toname):
597 '''Rename a file.'''
598 resp = self.sendcmd('RNFR ' + fromname)
599 if resp[0] != '3':
Collin Winterce36ad82007-08-30 01:19:48 +0000600 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000601 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000602
Tim Peters88869f92001-01-14 23:36:06 +0000603 def delete(self, filename):
604 '''Delete a file.'''
605 resp = self.sendcmd('DELE ' + filename)
Raymond Hettingerd5825cc2010-09-05 23:15:06 +0000606 if resp[:3] in {'250', '200'}:
Tim Peters88869f92001-01-14 23:36:06 +0000607 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000608 else:
Collin Winterce36ad82007-08-30 01:19:48 +0000609 raise error_reply(resp)
Guido van Rossum02cf5821993-05-17 08:00:02 +0000610
Tim Peters88869f92001-01-14 23:36:06 +0000611 def cwd(self, dirname):
612 '''Change to a directory.'''
613 if dirname == '..':
614 try:
615 return self.voidcmd('CDUP')
Guido van Rossumb940e112007-01-10 16:19:56 +0000616 except error_perm as msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000617 if msg.args[0][:3] != '500':
618 raise
Tim Peters88869f92001-01-14 23:36:06 +0000619 elif dirname == '':
620 dirname = '.' # does nothing, but could return error
621 cmd = 'CWD ' + dirname
622 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000623
Tim Peters88869f92001-01-14 23:36:06 +0000624 def size(self, filename):
625 '''Retrieve the size of a file.'''
Christian Heimes1af737c2008-01-23 08:24:23 +0000626 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000627 resp = self.sendcmd('SIZE ' + filename)
628 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000629 s = resp[3:].strip()
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200630 return int(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000631
Tim Peters88869f92001-01-14 23:36:06 +0000632 def mkd(self, dirname):
633 '''Make a directory, return its full pathname.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000634 resp = self.voidcmd('MKD ' + dirname)
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 Rossum98245091998-02-19 21:15:44 +0000640
Tim Peters88869f92001-01-14 23:36:06 +0000641 def rmd(self, dirname):
642 '''Remove a directory.'''
643 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000644
Tim Peters88869f92001-01-14 23:36:06 +0000645 def pwd(self):
646 '''Return current working directory.'''
Giampaolo RodolĂ bbc47822010-08-23 22:10:32 +0000647 resp = self.voidcmd('PWD')
648 # fix around non-compliant implementations such as IIS shipped
649 # with Windows server 2003
650 if not resp.startswith('257'):
651 return ''
Tim Peters88869f92001-01-14 23:36:06 +0000652 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000653
Tim Peters88869f92001-01-14 23:36:06 +0000654 def quit(self):
655 '''Quit, and close the connection.'''
656 resp = self.voidcmd('QUIT')
657 self.close()
658 return resp
659
660 def close(self):
661 '''Close the connection without assuming anything about it.'''
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000662 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000663 self.file.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000664 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000665 self.sock.close()
Giampaolo RodolĂ d6868482011-02-22 19:24:33 +0000666 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000667
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000668try:
669 import ssl
Brett Cannoncd171c82013-07-04 17:43:24 -0400670except ImportError:
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100671 _SSLSocket = None
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000672else:
Giampaolo Rodola'3ff5e752013-03-07 14:03:27 +0100673 _SSLSocket = ssl.SSLSocket
674
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000675 class FTP_TLS(FTP):
676 '''A FTP subclass which adds TLS support to FTP as described
677 in RFC-4217.
678
679 Connect as usual to port 21 implicitly securing the FTP control
680 connection before authenticating.
681
682 Securing the data connection requires user to explicitly ask
683 for it by calling prot_p() method.
684
685 Usage example:
686 >>> from ftplib import FTP_TLS
687 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti4969f702011-03-15 05:59:46 +0200688 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000689 '230 Guest login ok, access restrictions apply.'
690 >>> ftps.prot_p() # switch to secure data connection
691 '200 Protection level set to P'
692 >>> ftps.retrlines('LIST') # list directory content securely
693 total 9
694 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
695 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
696 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
697 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
698 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
699 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
700 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
701 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
702 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
703 '226 Transfer complete.'
704 >>> ftps.quit()
705 '221 Goodbye.'
706 >>>
707 '''
708 ssl_version = ssl.PROTOCOL_TLSv1
709
710 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000711 certfile=None, context=None,
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000712 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000713 if context is not None and keyfile is not None:
714 raise ValueError("context and keyfile arguments are mutually "
715 "exclusive")
716 if context is not None and certfile is not None:
717 raise ValueError("context and certfile arguments are mutually "
718 "exclusive")
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000719 self.keyfile = keyfile
720 self.certfile = certfile
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000721 self.context = context
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000722 self._prot_p = False
Giampaolo RodolĂ 396ff062011-02-28 19:19:51 +0000723 FTP.__init__(self, host, user, passwd, acct, timeout, source_address)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000724
725 def login(self, user='', passwd='', acct='', secure=True):
726 if secure and not isinstance(self.sock, ssl.SSLSocket):
727 self.auth()
728 return FTP.login(self, user, passwd, acct)
729
730 def auth(self):
731 '''Set up secure control connection by using TLS/SSL.'''
732 if isinstance(self.sock, ssl.SSLSocket):
733 raise ValueError("Already using TLS")
734 if self.ssl_version == ssl.PROTOCOL_TLSv1:
735 resp = self.voidcmd('AUTH TLS')
736 else:
737 resp = self.voidcmd('AUTH SSL')
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000738 if self.context is not None:
739 self.sock = self.context.wrap_socket(self.sock)
740 else:
741 self.sock = ssl.wrap_socket(self.sock, self.keyfile,
742 self.certfile,
743 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000744 self.file = self.sock.makefile(mode='r', encoding=self.encoding)
745 return resp
746
Giampaolo Rodola'096dcb12011-06-27 11:17:51 +0200747 def ccc(self):
748 '''Switch back to a clear-text control connection.'''
749 if not isinstance(self.sock, ssl.SSLSocket):
750 raise ValueError("not using TLS")
751 resp = self.voidcmd('CCC')
752 self.sock = self.sock.unwrap()
753 return resp
754
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000755 def prot_p(self):
756 '''Set up secure data connection.'''
757 # PROT defines whether or not the data channel is to be protected.
758 # Though RFC-2228 defines four possible protection levels,
759 # RFC-4217 only recommends two, Clear and Private.
760 # Clear (PROT C) means that no security is to be used on the
761 # data-channel, Private (PROT P) means that the data-channel
762 # should be protected by TLS.
763 # PBSZ command MUST still be issued, but must have a parameter of
764 # '0' to indicate that no buffering is taking place and the data
765 # connection should not be encapsulated.
766 self.voidcmd('PBSZ 0')
767 resp = self.voidcmd('PROT P')
768 self._prot_p = True
769 return resp
770
771 def prot_c(self):
772 '''Set up clear text data connection.'''
773 resp = self.voidcmd('PROT C')
774 self._prot_p = False
775 return resp
776
777 # --- Overridden FTP methods
778
779 def ntransfercmd(self, cmd, rest=None):
780 conn, size = FTP.ntransfercmd(self, cmd, rest)
781 if self._prot_p:
Giampaolo RodolĂ a67299e2010-05-26 18:06:04 +0000782 if self.context is not None:
783 conn = self.context.wrap_socket(conn)
784 else:
785 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
786 ssl_version=self.ssl_version)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000787 return conn, size
788
Giampaolo Rodola'24befa82011-05-07 19:09:34 +0200789 def abort(self):
790 # overridden as we can't pass MSG_OOB flag to sendall()
791 line = b'ABOR' + B_CRLF
792 self.sock.sendall(line)
793 resp = self.getmultiline()
794 if resp[:3] not in {'426', '225', '226'}:
795 raise error_proto(resp)
796 return resp
797
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000798 __all__.append('FTP_TLS')
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200799 all_errors = (Error, OSError, EOFError, ssl.SSLError)
Antoine Pitrouf988cd02009-11-17 20:21:14 +0000800
801
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000802_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000803
804def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000805 '''Parse the '150' response for a RETR request.
806 Returns the expected transfer size or None; size is not guaranteed to
807 be present in the 150 message.
808 '''
809 if resp[:3] != '150':
Collin Winterce36ad82007-08-30 01:19:48 +0000810 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000811 global _150_re
812 if _150_re is None:
813 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000814 _150_re = re.compile(
815 "150 .* \((\d+) bytes\)", re.IGNORECASE | re.ASCII)
Tim Peters88869f92001-01-14 23:36:06 +0000816 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000817 if not m:
818 return None
Florent Xicluna2bb96f52011-10-23 22:11:00 +0200819 return int(m.group(1))
Fred Drake4de02d91997-01-10 18:26:09 +0000820
821
Guido van Rossum70297d32001-08-17 17:24:29 +0000822_227_re = None
823
Guido van Rossumd2560b01996-05-28 23:41:25 +0000824def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000825 '''Parse the '227' response for a PASV request.
826 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
827 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000828
Tim Peters88869f92001-01-14 23:36:06 +0000829 if resp[:3] != '227':
Collin Winterce36ad82007-08-30 01:19:48 +0000830 raise error_reply(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000831 global _227_re
832 if _227_re is None:
833 import re
Antoine Pitroufd036452008-08-19 17:56:33 +0000834 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)', re.ASCII)
Guido van Rossum70297d32001-08-17 17:24:29 +0000835 m = _227_re.search(resp)
836 if not m:
Collin Winterce36ad82007-08-30 01:19:48 +0000837 raise error_proto(resp)
Guido van Rossum70297d32001-08-17 17:24:29 +0000838 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000839 host = '.'.join(numbers[:4])
840 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000841 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000842
843
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000844def parse229(resp, peer):
845 '''Parse the '229' response for a EPSV request.
846 Raises error_proto if it does not contain '(|||port|)'
847 Return ('host.addr.as.numbers', port#) tuple.'''
848
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000849 if resp[:3] != '229':
Collin Winterce36ad82007-08-30 01:19:48 +0000850 raise error_reply(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000851 left = resp.find('(')
Collin Winterce36ad82007-08-30 01:19:48 +0000852 if left < 0: raise error_proto(resp)
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000853 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000854 if right < 0:
Collin Winterce36ad82007-08-30 01:19:48 +0000855 raise error_proto(resp) # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000856 if resp[left + 1] != resp[right - 1]:
Collin Winterce36ad82007-08-30 01:19:48 +0000857 raise error_proto(resp)
Walter Dörwalda401ae42002-06-03 10:41:45 +0000858 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000859 if len(parts) != 5:
Collin Winterce36ad82007-08-30 01:19:48 +0000860 raise error_proto(resp)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000861 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000862 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000863 return host, port
864
865
Guido van Rossumc567c601992-11-05 22:22:37 +0000866def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000867 '''Parse the '257' response for a MKD or PWD request.
868 This is a response to a MKD or PWD request: a directory name.
869 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000870
Tim Peters88869f92001-01-14 23:36:06 +0000871 if resp[:3] != '257':
Collin Winterce36ad82007-08-30 01:19:48 +0000872 raise error_reply(resp)
Tim Peters88869f92001-01-14 23:36:06 +0000873 if resp[3:5] != ' "':
874 return '' # Not compliant to RFC 959, but UNIX ftpd does this
875 dirname = ''
876 i = 5
877 n = len(resp)
878 while i < n:
879 c = resp[i]
880 i = i+1
881 if c == '"':
882 if i >= n or resp[i] != '"':
883 break
884 i = i+1
885 dirname = dirname + c
886 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000887
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000888
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000889def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000890 '''Default retrlines callback to print a line.'''
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000891 print(line)
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000892
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000893
Guido van Rossumd2560b01996-05-28 23:41:25 +0000894def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000895 '''Copy file from one FTP-instance to another.'''
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100896 if not targetname:
897 targetname = sourcename
Tim Peters88869f92001-01-14 23:36:06 +0000898 type = 'TYPE ' + type
899 source.voidcmd(type)
900 target.voidcmd(type)
901 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
902 target.sendport(sourcehost, sourceport)
903 # RFC 959: the user must "listen" [...] BEFORE sending the
904 # transfer request.
905 # So: STOR before RETR, because here the target is a "user".
906 treply = target.sendcmd('STOR ' + targetname)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100907 if treply[:3] not in {'125', '150'}:
908 raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000909 sreply = source.sendcmd('RETR ' + sourcename)
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100910 if sreply[:3] not in {'125', '150'}:
911 raise error_proto # RFC 959
Tim Peters88869f92001-01-14 23:36:06 +0000912 source.voidresp()
913 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000914
Tim Peters88869f92001-01-14 23:36:06 +0000915
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000916class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000917 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000918
Tim Peters88869f92001-01-14 23:36:06 +0000919 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000920
Tim Peters88869f92001-01-14 23:36:06 +0000921 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000922
Tim Peters88869f92001-01-14 23:36:06 +0000923 """
924 __defuser = None
925 __defpasswd = None
926 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000927
Tim Peters88869f92001-01-14 23:36:06 +0000928 def __init__(self, filename=None):
R David Murray87632f12013-02-19 18:32:28 -0500929 warnings.warn("This class is deprecated, use the netrc module instead",
930 DeprecationWarning, 2)
Raymond Hettinger094662a2002-06-01 01:29:16 +0000931 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000932 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000933 filename = os.path.join(os.environ["HOME"],
934 ".netrc")
935 else:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200936 raise OSError("specify file to load or set $HOME")
Tim Peters88869f92001-01-14 23:36:06 +0000937 self.__hosts = {}
938 self.__macros = {}
939 fp = open(filename, "r")
940 in_macro = 0
941 while 1:
942 line = fp.readline()
Giampaolo Rodola'94c56a12013-03-07 13:51:20 +0100943 if not line:
944 break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000945 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000946 macro_lines.append(line)
947 continue
948 elif in_macro:
949 self.__macros[macro_name] = tuple(macro_lines)
950 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000951 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000952 host = user = passwd = acct = None
953 default = 0
954 i = 0
955 while i < len(words):
956 w1 = words[i]
957 if i+1 < len(words):
958 w2 = words[i + 1]
959 else:
960 w2 = None
961 if w1 == 'default':
962 default = 1
963 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000964 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000965 i = i + 1
966 elif w1 == 'login' and w2:
967 user = w2
968 i = i + 1
969 elif w1 == 'password' and w2:
970 passwd = w2
971 i = i + 1
972 elif w1 == 'account' and w2:
973 acct = w2
974 i = i + 1
975 elif w1 == 'macdef' and w2:
976 macro_name = w2
977 macro_lines = []
978 in_macro = 1
979 break
980 i = i + 1
981 if default:
982 self.__defuser = user or self.__defuser
983 self.__defpasswd = passwd or self.__defpasswd
984 self.__defacct = acct or self.__defacct
985 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000986 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000987 ouser, opasswd, oacct = \
988 self.__hosts[host]
989 user = user or ouser
990 passwd = passwd or opasswd
991 acct = acct or oacct
992 self.__hosts[host] = user, passwd, acct
993 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000994
Tim Peters88869f92001-01-14 23:36:06 +0000995 def get_hosts(self):
996 """Return a list of hosts mentioned in the .netrc file."""
997 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000998
Tim Peters88869f92001-01-14 23:36:06 +0000999 def get_account(self, host):
1000 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001001
Tim Peters88869f92001-01-14 23:36:06 +00001002 The return value is a triple containing userid,
1003 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001004
Tim Peters88869f92001-01-14 23:36:06 +00001005 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001006 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001007 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001008 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001009 user, passwd, acct = self.__hosts[host]
1010 user = user or self.__defuser
1011 passwd = passwd or self.__defpasswd
1012 acct = acct or self.__defacct
1013 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001014
Tim Peters88869f92001-01-14 23:36:06 +00001015 def get_macros(self):
1016 """Return a list of all defined macro names."""
1017 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001018
Tim Peters88869f92001-01-14 23:36:06 +00001019 def get_macro(self, macro):
1020 """Return a sequence of lines which define a named macro."""
1021 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001022
Fred Drake475d51d1997-06-24 22:02:54 +00001023
Tim Peters88869f92001-01-14 23:36:06 +00001024
Guido van Rossum1115ab21992-11-04 15:51:30 +00001025def test():
Tim Peters88869f92001-01-14 23:36:06 +00001026 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001027 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1028
1029 -d dir
1030 -l list
1031 -p password
1032 '''
1033
1034 if len(sys.argv) < 2:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001035 print(test.__doc__)
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001036 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001037
Tim Peters88869f92001-01-14 23:36:06 +00001038 debugging = 0
1039 rcfile = None
1040 while sys.argv[1] == '-d':
1041 debugging = debugging+1
1042 del sys.argv[1]
1043 if sys.argv[1][:2] == '-r':
1044 # get name of alternate ~/.netrc file:
1045 rcfile = sys.argv[1][2:]
1046 del sys.argv[1]
1047 host = sys.argv[1]
1048 ftp = FTP(host)
1049 ftp.set_debuglevel(debugging)
1050 userid = passwd = acct = ''
1051 try:
1052 netrc = Netrc(rcfile)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001053 except OSError:
Tim Peters88869f92001-01-14 23:36:06 +00001054 if rcfile is not None:
1055 sys.stderr.write("Could not open account file"
1056 " -- using anonymous login.")
1057 else:
1058 try:
1059 userid, passwd, acct = netrc.get_account(host)
1060 except KeyError:
1061 # no account for host
1062 sys.stderr.write(
1063 "No account -- using anonymous login.")
1064 ftp.login(userid, passwd, acct)
1065 for file in sys.argv[2:]:
1066 if file[:2] == '-l':
1067 ftp.dir(file[2:])
1068 elif file[:2] == '-d':
1069 cmd = 'CWD'
1070 if file[2:]: cmd = cmd + ' ' + file[2:]
1071 resp = ftp.sendcmd(cmd)
1072 elif file == '-p':
1073 ftp.set_pasv(not ftp.passiveserver)
1074 else:
1075 ftp.retrbinary('RETR ' + file, \
1076 sys.stdout.write, 1024)
1077 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001078
1079
1080if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001081 test()