blob: c98290ce85e996f2e10516d88f94094e06c9a78f [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 '''
641 ssl_version = ssl.PROTOCOL_TLSv1
642
643 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
644 certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
645 self.keyfile = keyfile
646 self.certfile = certfile
647 self._prot_p = False
648 FTP.__init__(self, host, user, passwd, acct, timeout)
649
650 def login(self, user='', passwd='', acct='', secure=True):
651 if secure and not isinstance(self.sock, ssl.SSLSocket):
652 self.auth()
653 return FTP.login(self, user, passwd, acct)
654
655 def auth(self):
656 '''Set up secure control connection by using TLS/SSL.'''
657 if isinstance(self.sock, ssl.SSLSocket):
658 raise ValueError("Already using TLS")
659 if self.ssl_version == ssl.PROTOCOL_TLSv1:
660 resp = self.voidcmd('AUTH TLS')
661 else:
662 resp = self.voidcmd('AUTH SSL')
663 self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
664 ssl_version=self.ssl_version)
665 self.file = self.sock.makefile(mode='rb')
666 return resp
667
668 def prot_p(self):
669 '''Set up secure data connection.'''
670 # PROT defines whether or not the data channel is to be protected.
671 # Though RFC-2228 defines four possible protection levels,
672 # RFC-4217 only recommends two, Clear and Private.
673 # Clear (PROT C) means that no security is to be used on the
674 # data-channel, Private (PROT P) means that the data-channel
675 # should be protected by TLS.
676 # PBSZ command MUST still be issued, but must have a parameter of
677 # '0' to indicate that no buffering is taking place and the data
678 # connection should not be encapsulated.
679 self.voidcmd('PBSZ 0')
680 resp = self.voidcmd('PROT P')
681 self._prot_p = True
682 return resp
683
684 def prot_c(self):
685 '''Set up clear text data connection.'''
686 resp = self.voidcmd('PROT C')
687 self._prot_p = False
688 return resp
689
690 # --- Overridden FTP methods
691
692 def ntransfercmd(self, cmd, rest=None):
693 conn, size = FTP.ntransfercmd(self, cmd, rest)
694 if self._prot_p:
695 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
696 ssl_version=self.ssl_version)
697 return conn, size
698
699 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
700 self.voidcmd('TYPE I')
701 conn = self.transfercmd(cmd, rest)
702 try:
703 while 1:
704 data = conn.recv(blocksize)
705 if not data:
706 break
707 callback(data)
708 # shutdown ssl layer
709 if isinstance(conn, ssl.SSLSocket):
710 conn.unwrap()
711 finally:
712 conn.close()
713 return self.voidresp()
714
715 def retrlines(self, cmd, callback = None):
716 if callback is None: callback = print_line
717 resp = self.sendcmd('TYPE A')
718 conn = self.transfercmd(cmd)
719 fp = conn.makefile('rb')
720 try:
721 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300722 line = fp.readline(self.maxline + 1)
723 if len(line) > self.maxline:
724 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000725 if self.debugging > 2: print '*retr*', repr(line)
726 if not line:
727 break
728 if line[-2:] == CRLF:
729 line = line[:-2]
730 elif line[-1:] == '\n':
731 line = line[:-1]
732 callback(line)
733 # shutdown ssl layer
734 if isinstance(conn, ssl.SSLSocket):
735 conn.unwrap()
736 finally:
737 fp.close()
738 conn.close()
739 return self.voidresp()
740
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000741 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000742 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000743 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000744 try:
745 while 1:
746 buf = fp.read(blocksize)
747 if not buf: break
748 conn.sendall(buf)
749 if callback: callback(buf)
750 # shutdown ssl layer
751 if isinstance(conn, ssl.SSLSocket):
752 conn.unwrap()
753 finally:
754 conn.close()
755 return self.voidresp()
756
757 def storlines(self, cmd, fp, callback=None):
758 self.voidcmd('TYPE A')
759 conn = self.transfercmd(cmd)
760 try:
761 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300762 buf = fp.readline(self.maxline + 1)
763 if len(buf) > self.maxline:
764 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000765 if not buf: break
766 if buf[-2:] != CRLF:
767 if buf[-1] in CRLF: buf = buf[:-1]
768 buf = buf + CRLF
769 conn.sendall(buf)
770 if callback: callback(buf)
771 # shutdown ssl layer
772 if isinstance(conn, ssl.SSLSocket):
773 conn.unwrap()
774 finally:
775 conn.close()
776 return self.voidresp()
777
778 __all__.append('FTP_TLS')
779 all_errors = (Error, IOError, EOFError, ssl.SSLError)
780
781
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000782_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000783
784def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000785 '''Parse the '150' response for a RETR request.
786 Returns the expected transfer size or None; size is not guaranteed to
787 be present in the 150 message.
788 '''
789 if resp[:3] != '150':
790 raise error_reply, resp
791 global _150_re
792 if _150_re is None:
793 import re
794 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
795 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000796 if not m:
797 return None
798 s = m.group(1)
799 try:
800 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000801 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000802 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000803
804
Guido van Rossum70297d32001-08-17 17:24:29 +0000805_227_re = None
806
Guido van Rossumd2560b01996-05-28 23:41:25 +0000807def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000808 '''Parse the '227' response for a PASV request.
809 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
810 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000811
Tim Peters88869f92001-01-14 23:36:06 +0000812 if resp[:3] != '227':
813 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000814 global _227_re
815 if _227_re is None:
816 import re
817 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
818 m = _227_re.search(resp)
819 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000820 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000821 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000822 host = '.'.join(numbers[:4])
823 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000824 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000825
826
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000827def parse229(resp, peer):
828 '''Parse the '229' response for a EPSV request.
829 Raises error_proto if it does not contain '(|||port|)'
830 Return ('host.addr.as.numbers', port#) tuple.'''
831
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000832 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000833 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000834 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000835 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000836 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000837 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000838 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000839 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000840 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000841 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000842 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000843 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000844 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000845 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000846 return host, port
847
848
Guido van Rossumc567c601992-11-05 22:22:37 +0000849def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000850 '''Parse the '257' response for a MKD or PWD request.
851 This is a response to a MKD or PWD request: a directory name.
852 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000853
Tim Peters88869f92001-01-14 23:36:06 +0000854 if resp[:3] != '257':
855 raise error_reply, resp
856 if resp[3:5] != ' "':
857 return '' # Not compliant to RFC 959, but UNIX ftpd does this
858 dirname = ''
859 i = 5
860 n = len(resp)
861 while i < n:
862 c = resp[i]
863 i = i+1
864 if c == '"':
865 if i >= n or resp[i] != '"':
866 break
867 i = i+1
868 dirname = dirname + c
869 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000870
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000871
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000872def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000873 '''Default retrlines callback to print a line.'''
874 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000875
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000876
Guido van Rossumd2560b01996-05-28 23:41:25 +0000877def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000878 '''Copy file from one FTP-instance to another.'''
879 if not targetname: targetname = sourcename
880 type = 'TYPE ' + type
881 source.voidcmd(type)
882 target.voidcmd(type)
883 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
884 target.sendport(sourcehost, sourceport)
885 # RFC 959: the user must "listen" [...] BEFORE sending the
886 # transfer request.
887 # So: STOR before RETR, because here the target is a "user".
888 treply = target.sendcmd('STOR ' + targetname)
889 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
890 sreply = source.sendcmd('RETR ' + sourcename)
891 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
892 source.voidresp()
893 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000894
Tim Peters88869f92001-01-14 23:36:06 +0000895
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000896class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000897 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000898
Tim Peters88869f92001-01-14 23:36:06 +0000899 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000900
Tim Peters88869f92001-01-14 23:36:06 +0000901 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000902
Tim Peters88869f92001-01-14 23:36:06 +0000903 """
904 __defuser = None
905 __defpasswd = None
906 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000907
Tim Peters88869f92001-01-14 23:36:06 +0000908 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000909 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000910 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000911 filename = os.path.join(os.environ["HOME"],
912 ".netrc")
913 else:
914 raise IOError, \
915 "specify file to load or set $HOME"
916 self.__hosts = {}
917 self.__macros = {}
918 fp = open(filename, "r")
919 in_macro = 0
920 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300921 line = fp.readline(self.maxline + 1)
922 if len(line) > self.maxline:
923 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000924 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000925 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000926 macro_lines.append(line)
927 continue
928 elif in_macro:
929 self.__macros[macro_name] = tuple(macro_lines)
930 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000931 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000932 host = user = passwd = acct = None
933 default = 0
934 i = 0
935 while i < len(words):
936 w1 = words[i]
937 if i+1 < len(words):
938 w2 = words[i + 1]
939 else:
940 w2 = None
941 if w1 == 'default':
942 default = 1
943 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000944 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000945 i = i + 1
946 elif w1 == 'login' and w2:
947 user = w2
948 i = i + 1
949 elif w1 == 'password' and w2:
950 passwd = w2
951 i = i + 1
952 elif w1 == 'account' and w2:
953 acct = w2
954 i = i + 1
955 elif w1 == 'macdef' and w2:
956 macro_name = w2
957 macro_lines = []
958 in_macro = 1
959 break
960 i = i + 1
961 if default:
962 self.__defuser = user or self.__defuser
963 self.__defpasswd = passwd or self.__defpasswd
964 self.__defacct = acct or self.__defacct
965 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000966 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000967 ouser, opasswd, oacct = \
968 self.__hosts[host]
969 user = user or ouser
970 passwd = passwd or opasswd
971 acct = acct or oacct
972 self.__hosts[host] = user, passwd, acct
973 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000974
Tim Peters88869f92001-01-14 23:36:06 +0000975 def get_hosts(self):
976 """Return a list of hosts mentioned in the .netrc file."""
977 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000978
Tim Peters88869f92001-01-14 23:36:06 +0000979 def get_account(self, host):
980 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000981
Tim Peters88869f92001-01-14 23:36:06 +0000982 The return value is a triple containing userid,
983 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000984
Tim Peters88869f92001-01-14 23:36:06 +0000985 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000986 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000987 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000988 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000989 user, passwd, acct = self.__hosts[host]
990 user = user or self.__defuser
991 passwd = passwd or self.__defpasswd
992 acct = acct or self.__defacct
993 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +0000994
Tim Peters88869f92001-01-14 23:36:06 +0000995 def get_macros(self):
996 """Return a list of all defined macro names."""
997 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000998
Tim Peters88869f92001-01-14 23:36:06 +0000999 def get_macro(self, macro):
1000 """Return a sequence of lines which define a named macro."""
1001 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001002
Fred Drake475d51d1997-06-24 22:02:54 +00001003
Tim Peters88869f92001-01-14 23:36:06 +00001004
Guido van Rossum1115ab21992-11-04 15:51:30 +00001005def test():
Tim Peters88869f92001-01-14 23:36:06 +00001006 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001007 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1008
1009 -d dir
1010 -l list
1011 -p password
1012 '''
1013
1014 if len(sys.argv) < 2:
1015 print test.__doc__
1016 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001017
Tim Peters88869f92001-01-14 23:36:06 +00001018 debugging = 0
1019 rcfile = None
1020 while sys.argv[1] == '-d':
1021 debugging = debugging+1
1022 del sys.argv[1]
1023 if sys.argv[1][:2] == '-r':
1024 # get name of alternate ~/.netrc file:
1025 rcfile = sys.argv[1][2:]
1026 del sys.argv[1]
1027 host = sys.argv[1]
1028 ftp = FTP(host)
1029 ftp.set_debuglevel(debugging)
1030 userid = passwd = acct = ''
1031 try:
1032 netrc = Netrc(rcfile)
1033 except IOError:
1034 if rcfile is not None:
1035 sys.stderr.write("Could not open account file"
1036 " -- using anonymous login.")
1037 else:
1038 try:
1039 userid, passwd, acct = netrc.get_account(host)
1040 except KeyError:
1041 # no account for host
1042 sys.stderr.write(
1043 "No account -- using anonymous login.")
1044 ftp.login(userid, passwd, acct)
1045 for file in sys.argv[2:]:
1046 if file[:2] == '-l':
1047 ftp.dir(file[2:])
1048 elif file[:2] == '-d':
1049 cmd = 'CWD'
1050 if file[2:]: cmd = cmd + ' ' + file[2:]
1051 resp = ftp.sendcmd(cmd)
1052 elif file == '-p':
1053 ftp.set_pasv(not ftp.passiveserver)
1054 else:
1055 ftp.retrbinary('RETR ' + file, \
1056 sys.stdout.write, 1024)
1057 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001058
1059
1060if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001061 test()