blob: e1c3d99d1e3973bf29f70c859456a9ec11cc2292 [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.
Gregory P. Smithc64386b2008-01-22 00:19:41 +000035# Modified by Phil Schwartz to add storbinary and storlines callbacks.
Antoine Pitrouccd5e022009-11-15 17:22:09 +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
Guido van Rossum1115ab21992-11-04 15:51:30 +000041
Guido van Rossumb6775db1994-08-01 11:34:53 +000042# Import SOCKS module if it exists, else standard socket module socket
43try:
Tim Peters88869f92001-01-14 23:36:06 +000044 import SOCKS; socket = SOCKS; del SOCKS # import SOCKS as socket
45 from socket import getfqdn; socket.getfqdn = getfqdn; del getfqdn
Guido van Rossumb6775db1994-08-01 11:34:53 +000046except ImportError:
Tim Peters88869f92001-01-14 23:36:06 +000047 import socket
Facundo Batista4f1b1ed2008-05-29 16:39:26 +000048from socket import _GLOBAL_DEFAULT_TIMEOUT
Guido van Rossumb6775db1994-08-01 11:34:53 +000049
Skip Montanaroeccd02a2001-01-20 23:34:12 +000050__all__ = ["FTP","Netrc"]
Guido van Rossum1115ab21992-11-04 15:51:30 +000051
Guido van Rossumd3166071993-05-24 14:16:22 +000052# Magic number from <socket.h>
Tim Peters88869f92001-01-14 23:36:06 +000053MSG_OOB = 0x1 # Process data out of band
Guido van Rossumd3166071993-05-24 14:16:22 +000054
55
Guido van Rossumc567c601992-11-05 22:22:37 +000056# The standard FTP server control port
Guido van Rossum1115ab21992-11-04 15:51:30 +000057FTP_PORT = 21
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +030058# The sizehint parameter passed to readline() calls
59MAXLINE = 8192
Guido van Rossum1115ab21992-11-04 15:51:30 +000060
61
Guido van Rossum21974791992-11-06 13:34:17 +000062# Exception raised when an error or invalid response is received
Fred Drake227b1202000-08-17 05:06:49 +000063class Error(Exception): pass
Tim Peters88869f92001-01-14 23:36:06 +000064class error_reply(Error): pass # unexpected [123]xx reply
65class error_temp(Error): pass # 4xx errors
66class error_perm(Error): pass # 5xx errors
67class error_proto(Error): pass # response does not begin with [1-5]
Guido van Rossum1115ab21992-11-04 15:51:30 +000068
69
Guido van Rossum21974791992-11-06 13:34:17 +000070# All exceptions (hopefully) that may be raised here and that aren't
71# (always) programming errors on our side
Gregory P. Smithe6c03032008-04-12 22:24:04 +000072all_errors = (Error, IOError, EOFError)
Guido van Rossum21974791992-11-06 13:34:17 +000073
74
Guido van Rossum1115ab21992-11-04 15:51:30 +000075# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
76CRLF = '\r\n'
77
Guido van Rossum1115ab21992-11-04 15:51:30 +000078# The class itself
79class FTP:
80
Tim Peters88869f92001-01-14 23:36:06 +000081 '''An FTP client class.
Guido van Rossumd2560b01996-05-28 23:41:25 +000082
Facundo Batista3f100992007-03-26 20:56:09 +000083 To create a connection, call the class using these arguments:
84 host, user, passwd, acct, timeout
85
86 The first four arguments are all strings, and have default value ''.
87 timeout must be numeric and defaults to None if not passed,
88 meaning that no timeout will be set on any ftp socket(s)
89 If a timeout is passed, then this is now the default timeout for all ftp
90 socket operations for this instance.
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000091
Tim Peters88869f92001-01-14 23:36:06 +000092 Then use self.connect() with optional host and port argument.
Guido van Rossumd2560b01996-05-28 23:41:25 +000093
Tim Peters88869f92001-01-14 23:36:06 +000094 To download a file, use ftp.retrlines('RETR ' + filename),
95 or ftp.retrbinary() with slightly different arguments.
96 To upload a file, use ftp.storlines() or ftp.storbinary(),
97 which have an open file as argument (see their definitions
98 below for details).
99 The download/upload functions first issue appropriate TYPE
100 and PORT or PASV commands.
Guido van Rossumd2560b01996-05-28 23:41:25 +0000101'''
102
Fred Drake9c98a422001-02-28 21:46:37 +0000103 debugging = 0
104 host = ''
105 port = FTP_PORT
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300106 maxline = MAXLINE
Fred Drake9c98a422001-02-28 21:46:37 +0000107 sock = None
108 file = None
109 welcome = None
110 passiveserver = 1
111
Tim Peters88869f92001-01-14 23:36:06 +0000112 # Initialization method (called by class instantiation).
113 # Initialize host to localhost, port to standard ftp port
114 # Optional arguments are host (for connect()),
115 # and user, passwd, acct (for login())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000116 def __init__(self, host='', user='', passwd='', acct='',
117 timeout=_GLOBAL_DEFAULT_TIMEOUT):
Facundo Batista3f100992007-03-26 20:56:09 +0000118 self.timeout = timeout
Tim Peters88869f92001-01-14 23:36:06 +0000119 if host:
Fred Drake9c98a422001-02-28 21:46:37 +0000120 self.connect(host)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000121 if user:
Facundo Batista3f100992007-03-26 20:56:09 +0000122 self.login(user, passwd, acct)
Guido van Rossum52fc1f61993-06-17 12:38:10 +0000123
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000124 def connect(self, host='', port=0, timeout=-999):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000125 '''Connect to host. Arguments are:
Facundo Batista3f100992007-03-26 20:56:09 +0000126 - host: hostname to connect to (string, default previous host)
127 - port: port to connect to (integer, default previous port)
128 '''
129 if host != '':
130 self.host = host
131 if port > 0:
132 self.port = port
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000133 if timeout != -999:
Facundo Batista93c33682007-03-30 13:00:35 +0000134 self.timeout = timeout
Facundo Batista3f100992007-03-26 20:56:09 +0000135 self.sock = socket.create_connection((self.host, self.port), self.timeout)
136 self.af = self.sock.family
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000137 self.file = self.sock.makefile('rb')
138 self.welcome = self.getresp()
139 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000140
Tim Peters88869f92001-01-14 23:36:06 +0000141 def getwelcome(self):
142 '''Get the welcome message from the server.
143 (this is read and squirreled away by connect())'''
144 if self.debugging:
145 print '*welcome*', self.sanitize(self.welcome)
146 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000147
Tim Peters88869f92001-01-14 23:36:06 +0000148 def set_debuglevel(self, level):
149 '''Set the debugging level.
150 The required argument level means:
151 0: no debugging output (default)
152 1: print commands and responses but not body text etc.
153 2: also print raw lines read and sent before stripping CR/LF'''
154 self.debugging = level
155 debug = set_debuglevel
Guido van Rossum1115ab21992-11-04 15:51:30 +0000156
Tim Peters88869f92001-01-14 23:36:06 +0000157 def set_pasv(self, val):
158 '''Use passive or active mode for data transfers.
159 With a false argument, use the normal PORT mode,
160 With a true argument, use the PASV command.'''
161 self.passiveserver = val
Guido van Rossumd2560b01996-05-28 23:41:25 +0000162
Tim Peters88869f92001-01-14 23:36:06 +0000163 # Internal: "sanitize" a string for printing
164 def sanitize(self, s):
165 if s[:5] == 'pass ' or s[:5] == 'PASS ':
166 i = len(s)
167 while i > 5 and s[i-1] in '\r\n':
168 i = i-1
169 s = s[:5] + '*'*(i-5) + s[i:]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000170 return repr(s)
Guido van Rossumebaf1041995-05-05 15:54:14 +0000171
Tim Peters88869f92001-01-14 23:36:06 +0000172 # Internal: send one line to the server, appending CRLF
173 def putline(self, line):
174 line = line + CRLF
175 if self.debugging > 1: print '*put*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000176 self.sock.sendall(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000177
Tim Peters88869f92001-01-14 23:36:06 +0000178 # Internal: send one command to the server (through putline())
179 def putcmd(self, line):
180 if self.debugging: print '*cmd*', self.sanitize(line)
181 self.putline(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000182
Tim Peters88869f92001-01-14 23:36:06 +0000183 # Internal: return one line from the server, stripping CRLF.
184 # Raise EOFError if the connection is closed
185 def getline(self):
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300186 line = self.file.readline(self.maxline + 1)
187 if len(line) > self.maxline:
188 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000189 if self.debugging > 1:
190 print '*get*', self.sanitize(line)
191 if not line: raise EOFError
192 if line[-2:] == CRLF: line = line[:-2]
193 elif line[-1:] in CRLF: line = line[:-1]
194 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000195
Tim Peters88869f92001-01-14 23:36:06 +0000196 # Internal: get a response from the server, which may possibly
197 # consist of multiple lines. Return a single string with no
198 # trailing CRLF. If the response consists of multiple lines,
199 # these are separated by '\n' characters in the string
200 def getmultiline(self):
201 line = self.getline()
202 if line[3:4] == '-':
203 code = line[:3]
204 while 1:
205 nextline = self.getline()
206 line = line + ('\n' + nextline)
207 if nextline[:3] == code and \
208 nextline[3:4] != '-':
209 break
210 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000211
Tim Peters88869f92001-01-14 23:36:06 +0000212 # Internal: get a response from the server.
213 # Raise various errors if the response indicates an error
214 def getresp(self):
215 resp = self.getmultiline()
216 if self.debugging: print '*resp*', self.sanitize(resp)
217 self.lastresp = resp[:3]
218 c = resp[:1]
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000219 if c in ('1', '2', '3'):
220 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000221 if c == '4':
222 raise error_temp, resp
223 if c == '5':
224 raise error_perm, resp
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000225 raise error_proto, resp
Guido van Rossum1115ab21992-11-04 15:51:30 +0000226
Tim Peters88869f92001-01-14 23:36:06 +0000227 def voidresp(self):
228 """Expect a response beginning with '2'."""
229 resp = self.getresp()
Georg Brandl50ba6e12009-04-05 10:48:47 +0000230 if resp[:1] != '2':
Tim Peters88869f92001-01-14 23:36:06 +0000231 raise error_reply, resp
232 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000233
Tim Peters88869f92001-01-14 23:36:06 +0000234 def abort(self):
235 '''Abort a file transfer. Uses out-of-band data.
236 This does not follow the procedure from the RFC to send Telnet
237 IP and Synch; that doesn't seem to work with the servers I've
238 tried. Instead, just send the ABOR command as OOB data.'''
239 line = 'ABOR' + CRLF
240 if self.debugging > 1: print '*put urgent*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000241 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000242 resp = self.getmultiline()
Giampaolo Rodolàcf445fc2010-04-18 12:55:03 +0000243 if resp[:3] not in ('426', '225', '226'):
Tim Peters88869f92001-01-14 23:36:06 +0000244 raise error_proto, resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000245
Tim Peters88869f92001-01-14 23:36:06 +0000246 def sendcmd(self, cmd):
247 '''Send a command and return the response.'''
248 self.putcmd(cmd)
249 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000250
Tim Peters88869f92001-01-14 23:36:06 +0000251 def voidcmd(self, cmd):
252 """Send a command and expect a response beginning with '2'."""
253 self.putcmd(cmd)
254 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000255
Tim Peters88869f92001-01-14 23:36:06 +0000256 def sendport(self, host, port):
257 '''Send a PORT command with the current host and the given
258 port number.
259 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000260 hbytes = host.split('.')
Benjamin Petersondee0b172008-09-27 22:08:12 +0000261 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000262 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000263 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000264 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000265
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000266 def sendeprt(self, host, port):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000267 '''Send a EPRT command with the current host and the given port number.'''
268 af = 0
269 if self.af == socket.AF_INET:
270 af = 1
271 if self.af == socket.AF_INET6:
272 af = 2
273 if af == 0:
274 raise error_proto, 'unsupported address family'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000275 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000276 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000277 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000278
Tim Peters88869f92001-01-14 23:36:06 +0000279 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000280 '''Create a new socket and send a PORT command for it.'''
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100281 err = None
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000282 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000283 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
284 af, socktype, proto, canonname, sa = res
285 try:
286 sock = socket.socket(af, socktype, proto)
287 sock.bind(sa)
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100288 except socket.error, err:
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000289 if sock:
290 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000291 sock = None
292 continue
293 break
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100294 if sock is None:
295 if err is not None:
296 raise err
297 else:
298 raise socket.error("getaddrinfo returns an empty list")
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000299 sock.listen(1)
300 port = sock.getsockname()[1] # Get proper port
301 host = self.sock.getsockname()[0] # Get proper host
302 if self.af == socket.AF_INET:
303 resp = self.sendport(host, port)
304 else:
305 resp = self.sendeprt(host, port)
Giampaolo Rodolà607f7c02010-04-19 21:46:28 +0000306 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
307 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000308 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000309
310 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000311 if self.af == socket.AF_INET:
312 host, port = parse227(self.sendcmd('PASV'))
313 else:
314 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
315 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000316
Tim Peters88869f92001-01-14 23:36:06 +0000317 def ntransfercmd(self, cmd, rest=None):
318 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000319
Tim Peters88869f92001-01-14 23:36:06 +0000320 If the transfer is active, send a port command and the
321 transfer command, and accept the connection. If the server is
322 passive, send a pasv command, connect to it, and start the
323 transfer command. Either way, return the socket for the
324 connection and the expected size of the transfer. The
325 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000326
Tim Peters88869f92001-01-14 23:36:06 +0000327 Optional `rest' argument can be a string that is sent as the
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000328 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000329 marker used to tell the server to skip over any data up to the
330 given marker.
331 """
332 size = None
333 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000334 host, port = self.makepasv()
Facundo Batista92493122007-06-06 15:13:37 +0000335 conn = socket.create_connection((host, port), self.timeout)
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200336 try:
337 if rest is not None:
338 self.sendcmd("REST %s" % rest)
339 resp = self.sendcmd(cmd)
340 # Some servers apparently send a 200 reply to
341 # a LIST or STOR command, before the 150 reply
342 # (and way before the 226 reply). This seems to
343 # be in violation of the protocol (which only allows
344 # 1xx or error messages for LIST), so we just discard
345 # this response.
346 if resp[0] == '2':
347 resp = self.getresp()
348 if resp[0] != '1':
349 raise error_reply, resp
350 except:
351 conn.close()
352 raise
Tim Peters88869f92001-01-14 23:36:06 +0000353 else:
354 sock = self.makeport()
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200355 try:
356 if rest is not None:
357 self.sendcmd("REST %s" % rest)
358 resp = self.sendcmd(cmd)
359 # See above.
360 if resp[0] == '2':
361 resp = self.getresp()
362 if resp[0] != '1':
363 raise error_reply, resp
364 conn, sockaddr = sock.accept()
365 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
366 conn.settimeout(self.timeout)
367 finally:
368 sock.close()
Tim Peters88869f92001-01-14 23:36:06 +0000369 if resp[:3] == '150':
370 # this is conditional in case we received a 125
371 size = parse150(resp)
372 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000373
Tim Peters88869f92001-01-14 23:36:06 +0000374 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000375 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000376 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000377
Tim Peters88869f92001-01-14 23:36:06 +0000378 def login(self, user = '', passwd = '', acct = ''):
379 '''Login, default anonymous.'''
380 if not user: user = 'anonymous'
381 if not passwd: passwd = ''
382 if not acct: acct = ''
383 if user == 'anonymous' and passwd in ('', '-'):
Tim Peterse4418602002-02-16 07:34:19 +0000384 # If there is no anonymous ftp password specified
385 # then we'll just use anonymous@
386 # We don't send any other thing because:
387 # - We want to remain anonymous
388 # - We want to stop SPAM
389 # - We don't want to let ftp sites to discriminate by the user,
390 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000391 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000392 resp = self.sendcmd('USER ' + user)
393 if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
394 if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
395 if resp[0] != '2':
396 raise error_reply, resp
397 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000398
Tim Peters88869f92001-01-14 23:36:06 +0000399 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000400 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000401
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000402 Args:
403 cmd: A RETR command.
404 callback: A single parameter callable to be called on each
405 block of data read.
406 blocksize: The maximum number of bytes to read from the
407 socket at one time. [default: 8192]
408 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000409
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000410 Returns:
411 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000412 """
413 self.voidcmd('TYPE I')
414 conn = self.transfercmd(cmd, rest)
415 while 1:
416 data = conn.recv(blocksize)
417 if not data:
418 break
419 callback(data)
420 conn.close()
421 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000422
Tim Peters88869f92001-01-14 23:36:06 +0000423 def retrlines(self, cmd, callback = None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000424 """Retrieve data in line mode. A new port is created for you.
425
426 Args:
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000427 cmd: A RETR, LIST, NLST, or MLSD command.
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000428 callback: An optional single parameter callable that is called
429 for each line with the trailing CRLF stripped.
430 [default: print_line()]
431
432 Returns:
433 The response code.
434 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000435 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000436 resp = self.sendcmd('TYPE A')
437 conn = self.transfercmd(cmd)
438 fp = conn.makefile('rb')
439 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300440 line = fp.readline(self.maxline + 1)
441 if len(line) > self.maxline:
442 raise Error("got more than %d bytes" % self.maxline)
Walter Dörwald70a6b492004-02-12 17:35:32 +0000443 if self.debugging > 2: print '*retr*', repr(line)
Tim Peters88869f92001-01-14 23:36:06 +0000444 if not line:
445 break
446 if line[-2:] == CRLF:
447 line = line[:-2]
448 elif line[-1:] == '\n':
449 line = line[:-1]
450 callback(line)
451 fp.close()
452 conn.close()
453 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000454
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000455 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000456 """Store a file in binary mode. A new port is created for you.
457
458 Args:
459 cmd: A STOR command.
460 fp: A file-like object with a read(num_bytes) method.
461 blocksize: The maximum data size to read from fp and send over
462 the connection at once. [default: 8192]
463 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400464 each block of data after it is sent. [default: None]
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000465 rest: Passed to transfercmd(). [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000466
467 Returns:
468 The response code.
469 """
Tim Peters88869f92001-01-14 23:36:06 +0000470 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000471 conn = self.transfercmd(cmd, rest)
Tim Peters88869f92001-01-14 23:36:06 +0000472 while 1:
473 buf = fp.read(blocksize)
474 if not buf: break
Martin v. Löwise12454f2002-02-16 23:06:19 +0000475 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000476 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000477 conn.close()
478 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000479
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000480 def storlines(self, cmd, fp, callback=None):
481 """Store a file in line mode. A new port is created for you.
482
483 Args:
484 cmd: A STOR command.
485 fp: A file-like object with a readline() method.
486 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400487 each line after it is sent. [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000488
489 Returns:
490 The response code.
491 """
Tim Peters88869f92001-01-14 23:36:06 +0000492 self.voidcmd('TYPE A')
493 conn = self.transfercmd(cmd)
494 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300495 buf = fp.readline(self.maxline + 1)
496 if len(buf) > self.maxline:
497 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000498 if not buf: break
499 if buf[-2:] != CRLF:
500 if buf[-1] in CRLF: buf = buf[:-1]
501 buf = buf + CRLF
Martin v. Löwise12454f2002-02-16 23:06:19 +0000502 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000503 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000504 conn.close()
505 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000506
Tim Peters88869f92001-01-14 23:36:06 +0000507 def acct(self, password):
508 '''Send new account name.'''
509 cmd = 'ACCT ' + password
510 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000511
Tim Peters88869f92001-01-14 23:36:06 +0000512 def nlst(self, *args):
513 '''Return a list of files in a given directory (default the current).'''
514 cmd = 'NLST'
515 for arg in args:
516 cmd = cmd + (' ' + arg)
517 files = []
518 self.retrlines(cmd, files.append)
519 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000520
Tim Peters88869f92001-01-14 23:36:06 +0000521 def dir(self, *args):
522 '''List a directory in long form.
523 By default list current directory to stdout.
524 Optional last argument is callback function; all
525 non-empty arguments before it are concatenated to the
526 LIST command. (This *should* only be used for a pathname.)'''
527 cmd = 'LIST'
528 func = None
529 if args[-1:] and type(args[-1]) != type(''):
530 args, func = args[:-1], args[-1]
531 for arg in args:
532 if arg:
533 cmd = cmd + (' ' + arg)
534 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000535
Tim Peters88869f92001-01-14 23:36:06 +0000536 def rename(self, fromname, toname):
537 '''Rename a file.'''
538 resp = self.sendcmd('RNFR ' + fromname)
539 if resp[0] != '3':
540 raise error_reply, resp
541 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000542
Tim Peters88869f92001-01-14 23:36:06 +0000543 def delete(self, filename):
544 '''Delete a file.'''
545 resp = self.sendcmd('DELE ' + filename)
546 if resp[:3] in ('250', '200'):
547 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000548 else:
549 raise error_reply, resp
Guido van Rossum02cf5821993-05-17 08:00:02 +0000550
Tim Peters88869f92001-01-14 23:36:06 +0000551 def cwd(self, dirname):
552 '''Change to a directory.'''
553 if dirname == '..':
554 try:
555 return self.voidcmd('CDUP')
556 except error_perm, msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000557 if msg.args[0][:3] != '500':
558 raise
Tim Peters88869f92001-01-14 23:36:06 +0000559 elif dirname == '':
560 dirname = '.' # does nothing, but could return error
561 cmd = 'CWD ' + dirname
562 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000563
Tim Peters88869f92001-01-14 23:36:06 +0000564 def size(self, filename):
565 '''Retrieve the size of a file.'''
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000566 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000567 resp = self.sendcmd('SIZE ' + filename)
568 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000569 s = resp[3:].strip()
570 try:
571 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000572 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000573 return long(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000574
Tim Peters88869f92001-01-14 23:36:06 +0000575 def mkd(self, dirname):
576 '''Make a directory, return its full pathname.'''
577 resp = self.sendcmd('MKD ' + dirname)
578 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000579
Tim Peters88869f92001-01-14 23:36:06 +0000580 def rmd(self, dirname):
581 '''Remove a directory.'''
582 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000583
Tim Peters88869f92001-01-14 23:36:06 +0000584 def pwd(self):
585 '''Return current working directory.'''
586 resp = self.sendcmd('PWD')
587 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000588
Tim Peters88869f92001-01-14 23:36:06 +0000589 def quit(self):
590 '''Quit, and close the connection.'''
591 resp = self.voidcmd('QUIT')
592 self.close()
593 return resp
594
595 def close(self):
596 '''Close the connection without assuming anything about it.'''
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700597 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000598 self.file.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700599 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000600 self.sock.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700601 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000602
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000603try:
604 import ssl
605except ImportError:
606 pass
607else:
608 class FTP_TLS(FTP):
609 '''A FTP subclass which adds TLS support to FTP as described
610 in RFC-4217.
611
612 Connect as usual to port 21 implicitly securing the FTP control
613 connection before authenticating.
614
615 Securing the data connection requires user to explicitly ask
616 for it by calling prot_p() method.
617
618 Usage example:
619 >>> from ftplib import FTP_TLS
620 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200621 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000622 '230 Guest login ok, access restrictions apply.'
623 >>> ftps.prot_p() # switch to secure data connection
624 '200 Protection level set to P'
625 >>> ftps.retrlines('LIST') # list directory content securely
626 total 9
627 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
628 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
629 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
630 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
631 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
632 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
633 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
634 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
635 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
636 '226 Transfer complete.'
637 >>> ftps.quit()
638 '221 Goodbye.'
639 >>>
640 '''
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600641 ssl_version = ssl.PROTOCOL_SSLv23
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000642
643 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600644 certfile=None, context=None,
645 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
646 if context is not None and keyfile is not None:
647 raise ValueError("context and keyfile arguments are mutually "
648 "exclusive")
649 if context is not None and certfile is not None:
650 raise ValueError("context and certfile arguments are mutually "
651 "exclusive")
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000652 self.keyfile = keyfile
653 self.certfile = certfile
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600654 if context is None:
655 context = ssl._create_stdlib_context(self.ssl_version,
656 certfile=certfile,
657 keyfile=keyfile)
658 self.context = context
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000659 self._prot_p = False
660 FTP.__init__(self, host, user, passwd, acct, timeout)
661
662 def login(self, user='', passwd='', acct='', secure=True):
663 if secure and not isinstance(self.sock, ssl.SSLSocket):
664 self.auth()
665 return FTP.login(self, user, passwd, acct)
666
667 def auth(self):
668 '''Set up secure control connection by using TLS/SSL.'''
669 if isinstance(self.sock, ssl.SSLSocket):
670 raise ValueError("Already using TLS")
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600671 if self.ssl_version >= ssl.PROTOCOL_SSLv23:
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000672 resp = self.voidcmd('AUTH TLS')
673 else:
674 resp = self.voidcmd('AUTH SSL')
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600675 self.sock = self.context.wrap_socket(self.sock,
676 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000677 self.file = self.sock.makefile(mode='rb')
678 return resp
679
680 def prot_p(self):
681 '''Set up secure data connection.'''
682 # PROT defines whether or not the data channel is to be protected.
683 # Though RFC-2228 defines four possible protection levels,
684 # RFC-4217 only recommends two, Clear and Private.
685 # Clear (PROT C) means that no security is to be used on the
686 # data-channel, Private (PROT P) means that the data-channel
687 # should be protected by TLS.
688 # PBSZ command MUST still be issued, but must have a parameter of
689 # '0' to indicate that no buffering is taking place and the data
690 # connection should not be encapsulated.
691 self.voidcmd('PBSZ 0')
692 resp = self.voidcmd('PROT P')
693 self._prot_p = True
694 return resp
695
696 def prot_c(self):
697 '''Set up clear text data connection.'''
698 resp = self.voidcmd('PROT C')
699 self._prot_p = False
700 return resp
701
702 # --- Overridden FTP methods
703
704 def ntransfercmd(self, cmd, rest=None):
705 conn, size = FTP.ntransfercmd(self, cmd, rest)
706 if self._prot_p:
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600707 conn = self.context.wrap_socket(conn,
708 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000709 return conn, size
710
711 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
712 self.voidcmd('TYPE I')
713 conn = self.transfercmd(cmd, rest)
714 try:
715 while 1:
716 data = conn.recv(blocksize)
717 if not data:
718 break
719 callback(data)
720 # shutdown ssl layer
721 if isinstance(conn, ssl.SSLSocket):
722 conn.unwrap()
723 finally:
724 conn.close()
725 return self.voidresp()
726
727 def retrlines(self, cmd, callback = None):
728 if callback is None: callback = print_line
729 resp = self.sendcmd('TYPE A')
730 conn = self.transfercmd(cmd)
731 fp = conn.makefile('rb')
732 try:
733 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300734 line = fp.readline(self.maxline + 1)
735 if len(line) > self.maxline:
736 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000737 if self.debugging > 2: print '*retr*', repr(line)
738 if not line:
739 break
740 if line[-2:] == CRLF:
741 line = line[:-2]
742 elif line[-1:] == '\n':
743 line = line[:-1]
744 callback(line)
745 # shutdown ssl layer
746 if isinstance(conn, ssl.SSLSocket):
747 conn.unwrap()
748 finally:
749 fp.close()
750 conn.close()
751 return self.voidresp()
752
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000753 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000754 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000755 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000756 try:
757 while 1:
758 buf = fp.read(blocksize)
759 if not buf: break
760 conn.sendall(buf)
761 if callback: callback(buf)
762 # shutdown ssl layer
763 if isinstance(conn, ssl.SSLSocket):
764 conn.unwrap()
765 finally:
766 conn.close()
767 return self.voidresp()
768
769 def storlines(self, cmd, fp, callback=None):
770 self.voidcmd('TYPE A')
771 conn = self.transfercmd(cmd)
772 try:
773 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300774 buf = fp.readline(self.maxline + 1)
775 if len(buf) > self.maxline:
776 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000777 if not buf: break
778 if buf[-2:] != CRLF:
779 if buf[-1] in CRLF: buf = buf[:-1]
780 buf = buf + CRLF
781 conn.sendall(buf)
782 if callback: callback(buf)
783 # shutdown ssl layer
784 if isinstance(conn, ssl.SSLSocket):
785 conn.unwrap()
786 finally:
787 conn.close()
788 return self.voidresp()
789
790 __all__.append('FTP_TLS')
791 all_errors = (Error, IOError, EOFError, ssl.SSLError)
792
793
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000794_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000795
796def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000797 '''Parse the '150' response for a RETR request.
798 Returns the expected transfer size or None; size is not guaranteed to
799 be present in the 150 message.
800 '''
801 if resp[:3] != '150':
802 raise error_reply, resp
803 global _150_re
804 if _150_re is None:
805 import re
806 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
807 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000808 if not m:
809 return None
810 s = m.group(1)
811 try:
812 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000813 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000814 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000815
816
Guido van Rossum70297d32001-08-17 17:24:29 +0000817_227_re = None
818
Guido van Rossumd2560b01996-05-28 23:41:25 +0000819def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000820 '''Parse the '227' response for a PASV request.
821 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
822 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000823
Tim Peters88869f92001-01-14 23:36:06 +0000824 if resp[:3] != '227':
825 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000826 global _227_re
827 if _227_re is None:
828 import re
829 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
830 m = _227_re.search(resp)
831 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000832 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000833 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000834 host = '.'.join(numbers[:4])
835 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000836 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000837
838
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000839def parse229(resp, peer):
840 '''Parse the '229' response for a EPSV request.
841 Raises error_proto if it does not contain '(|||port|)'
842 Return ('host.addr.as.numbers', port#) tuple.'''
843
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000844 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000845 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000846 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000847 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000848 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000849 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000850 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000851 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000852 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000853 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000854 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000855 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000856 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000857 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000858 return host, port
859
860
Guido van Rossumc567c601992-11-05 22:22:37 +0000861def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000862 '''Parse the '257' response for a MKD or PWD request.
863 This is a response to a MKD or PWD request: a directory name.
864 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000865
Tim Peters88869f92001-01-14 23:36:06 +0000866 if resp[:3] != '257':
867 raise error_reply, resp
868 if resp[3:5] != ' "':
869 return '' # Not compliant to RFC 959, but UNIX ftpd does this
870 dirname = ''
871 i = 5
872 n = len(resp)
873 while i < n:
874 c = resp[i]
875 i = i+1
876 if c == '"':
877 if i >= n or resp[i] != '"':
878 break
879 i = i+1
880 dirname = dirname + c
881 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000882
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000883
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000884def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000885 '''Default retrlines callback to print a line.'''
886 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000887
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000888
Guido van Rossumd2560b01996-05-28 23:41:25 +0000889def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000890 '''Copy file from one FTP-instance to another.'''
891 if not targetname: targetname = sourcename
892 type = 'TYPE ' + type
893 source.voidcmd(type)
894 target.voidcmd(type)
895 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
896 target.sendport(sourcehost, sourceport)
897 # RFC 959: the user must "listen" [...] BEFORE sending the
898 # transfer request.
899 # So: STOR before RETR, because here the target is a "user".
900 treply = target.sendcmd('STOR ' + targetname)
901 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
902 sreply = source.sendcmd('RETR ' + sourcename)
903 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
904 source.voidresp()
905 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000906
Tim Peters88869f92001-01-14 23:36:06 +0000907
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000908class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000909 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000910
Tim Peters88869f92001-01-14 23:36:06 +0000911 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000912
Tim Peters88869f92001-01-14 23:36:06 +0000913 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000914
Tim Peters88869f92001-01-14 23:36:06 +0000915 """
916 __defuser = None
917 __defpasswd = None
918 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000919
Tim Peters88869f92001-01-14 23:36:06 +0000920 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000921 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000922 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000923 filename = os.path.join(os.environ["HOME"],
924 ".netrc")
925 else:
926 raise IOError, \
927 "specify file to load or set $HOME"
928 self.__hosts = {}
929 self.__macros = {}
930 fp = open(filename, "r")
931 in_macro = 0
932 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300933 line = fp.readline(self.maxline + 1)
934 if len(line) > self.maxline:
935 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000936 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000937 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000938 macro_lines.append(line)
939 continue
940 elif in_macro:
941 self.__macros[macro_name] = tuple(macro_lines)
942 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000943 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000944 host = user = passwd = acct = None
945 default = 0
946 i = 0
947 while i < len(words):
948 w1 = words[i]
949 if i+1 < len(words):
950 w2 = words[i + 1]
951 else:
952 w2 = None
953 if w1 == 'default':
954 default = 1
955 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000956 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000957 i = i + 1
958 elif w1 == 'login' and w2:
959 user = w2
960 i = i + 1
961 elif w1 == 'password' and w2:
962 passwd = w2
963 i = i + 1
964 elif w1 == 'account' and w2:
965 acct = w2
966 i = i + 1
967 elif w1 == 'macdef' and w2:
968 macro_name = w2
969 macro_lines = []
970 in_macro = 1
971 break
972 i = i + 1
973 if default:
974 self.__defuser = user or self.__defuser
975 self.__defpasswd = passwd or self.__defpasswd
976 self.__defacct = acct or self.__defacct
977 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000978 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000979 ouser, opasswd, oacct = \
980 self.__hosts[host]
981 user = user or ouser
982 passwd = passwd or opasswd
983 acct = acct or oacct
984 self.__hosts[host] = user, passwd, acct
985 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000986
Tim Peters88869f92001-01-14 23:36:06 +0000987 def get_hosts(self):
988 """Return a list of hosts mentioned in the .netrc file."""
989 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000990
Tim Peters88869f92001-01-14 23:36:06 +0000991 def get_account(self, host):
992 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000993
Tim Peters88869f92001-01-14 23:36:06 +0000994 The return value is a triple containing userid,
995 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000996
Tim Peters88869f92001-01-14 23:36:06 +0000997 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000998 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000999 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001000 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001001 user, passwd, acct = self.__hosts[host]
1002 user = user or self.__defuser
1003 passwd = passwd or self.__defpasswd
1004 acct = acct or self.__defacct
1005 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001006
Tim Peters88869f92001-01-14 23:36:06 +00001007 def get_macros(self):
1008 """Return a list of all defined macro names."""
1009 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001010
Tim Peters88869f92001-01-14 23:36:06 +00001011 def get_macro(self, macro):
1012 """Return a sequence of lines which define a named macro."""
1013 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001014
Fred Drake475d51d1997-06-24 22:02:54 +00001015
Tim Peters88869f92001-01-14 23:36:06 +00001016
Guido van Rossum1115ab21992-11-04 15:51:30 +00001017def test():
Tim Peters88869f92001-01-14 23:36:06 +00001018 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001019 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1020
1021 -d dir
1022 -l list
1023 -p password
1024 '''
1025
1026 if len(sys.argv) < 2:
1027 print test.__doc__
1028 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001029
Tim Peters88869f92001-01-14 23:36:06 +00001030 debugging = 0
1031 rcfile = None
1032 while sys.argv[1] == '-d':
1033 debugging = debugging+1
1034 del sys.argv[1]
1035 if sys.argv[1][:2] == '-r':
1036 # get name of alternate ~/.netrc file:
1037 rcfile = sys.argv[1][2:]
1038 del sys.argv[1]
1039 host = sys.argv[1]
1040 ftp = FTP(host)
1041 ftp.set_debuglevel(debugging)
1042 userid = passwd = acct = ''
1043 try:
1044 netrc = Netrc(rcfile)
1045 except IOError:
1046 if rcfile is not None:
1047 sys.stderr.write("Could not open account file"
1048 " -- using anonymous login.")
1049 else:
1050 try:
1051 userid, passwd, acct = netrc.get_account(host)
1052 except KeyError:
1053 # no account for host
1054 sys.stderr.write(
1055 "No account -- using anonymous login.")
1056 ftp.login(userid, passwd, acct)
1057 for file in sys.argv[2:]:
1058 if file[:2] == '-l':
1059 ftp.dir(file[2:])
1060 elif file[:2] == '-d':
1061 cmd = 'CWD'
1062 if file[2:]: cmd = cmd + ' ' + file[2:]
1063 resp = ftp.sendcmd(cmd)
1064 elif file == '-p':
1065 ftp.set_pasv(not ftp.passiveserver)
1066 else:
1067 ftp.retrbinary('RETR ' + file, \
1068 sys.stdout.write, 1024)
1069 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001070
1071
1072if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001073 test()