blob: 449ce718cfb31b2c9c4a14c14860ec76577a10c5 [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.'''
Serhiy Storchaka1aa2c0f2015-04-10 13:24:10 +0300597 try:
598 file = self.file
599 self.file = None
600 if file is not None:
601 file.close()
602 finally:
603 sock = self.sock
604 self.sock = None
605 if sock is not None:
606 sock.close()
Guido van Rossumc567c601992-11-05 22:22:37 +0000607
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000608try:
609 import ssl
610except ImportError:
611 pass
612else:
613 class FTP_TLS(FTP):
614 '''A FTP subclass which adds TLS support to FTP as described
615 in RFC-4217.
616
617 Connect as usual to port 21 implicitly securing the FTP control
618 connection before authenticating.
619
620 Securing the data connection requires user to explicitly ask
621 for it by calling prot_p() method.
622
623 Usage example:
624 >>> from ftplib import FTP_TLS
625 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200626 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000627 '230 Guest login ok, access restrictions apply.'
628 >>> ftps.prot_p() # switch to secure data connection
629 '200 Protection level set to P'
630 >>> ftps.retrlines('LIST') # list directory content securely
631 total 9
632 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
633 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
634 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
635 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
636 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
637 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
638 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
639 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
640 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
641 '226 Transfer complete.'
642 >>> ftps.quit()
643 '221 Goodbye.'
644 >>>
645 '''
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600646 ssl_version = ssl.PROTOCOL_SSLv23
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000647
648 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600649 certfile=None, context=None,
650 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
651 if context is not None and keyfile is not None:
652 raise ValueError("context and keyfile arguments are mutually "
653 "exclusive")
654 if context is not None and certfile is not None:
655 raise ValueError("context and certfile arguments are mutually "
656 "exclusive")
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000657 self.keyfile = keyfile
658 self.certfile = certfile
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600659 if context is None:
660 context = ssl._create_stdlib_context(self.ssl_version,
661 certfile=certfile,
662 keyfile=keyfile)
663 self.context = context
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000664 self._prot_p = False
665 FTP.__init__(self, host, user, passwd, acct, timeout)
666
667 def login(self, user='', passwd='', acct='', secure=True):
668 if secure and not isinstance(self.sock, ssl.SSLSocket):
669 self.auth()
670 return FTP.login(self, user, passwd, acct)
671
672 def auth(self):
673 '''Set up secure control connection by using TLS/SSL.'''
674 if isinstance(self.sock, ssl.SSLSocket):
675 raise ValueError("Already using TLS")
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600676 if self.ssl_version >= ssl.PROTOCOL_SSLv23:
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000677 resp = self.voidcmd('AUTH TLS')
678 else:
679 resp = self.voidcmd('AUTH SSL')
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600680 self.sock = self.context.wrap_socket(self.sock,
681 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000682 self.file = self.sock.makefile(mode='rb')
683 return resp
684
685 def prot_p(self):
686 '''Set up secure data connection.'''
687 # PROT defines whether or not the data channel is to be protected.
688 # Though RFC-2228 defines four possible protection levels,
689 # RFC-4217 only recommends two, Clear and Private.
690 # Clear (PROT C) means that no security is to be used on the
691 # data-channel, Private (PROT P) means that the data-channel
692 # should be protected by TLS.
693 # PBSZ command MUST still be issued, but must have a parameter of
694 # '0' to indicate that no buffering is taking place and the data
695 # connection should not be encapsulated.
696 self.voidcmd('PBSZ 0')
697 resp = self.voidcmd('PROT P')
698 self._prot_p = True
699 return resp
700
701 def prot_c(self):
702 '''Set up clear text data connection.'''
703 resp = self.voidcmd('PROT C')
704 self._prot_p = False
705 return resp
706
707 # --- Overridden FTP methods
708
709 def ntransfercmd(self, cmd, rest=None):
710 conn, size = FTP.ntransfercmd(self, cmd, rest)
711 if self._prot_p:
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600712 conn = self.context.wrap_socket(conn,
713 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000714 return conn, size
715
716 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
717 self.voidcmd('TYPE I')
718 conn = self.transfercmd(cmd, rest)
719 try:
720 while 1:
721 data = conn.recv(blocksize)
722 if not data:
723 break
724 callback(data)
725 # shutdown ssl layer
726 if isinstance(conn, ssl.SSLSocket):
727 conn.unwrap()
728 finally:
729 conn.close()
730 return self.voidresp()
731
732 def retrlines(self, cmd, callback = None):
733 if callback is None: callback = print_line
734 resp = self.sendcmd('TYPE A')
735 conn = self.transfercmd(cmd)
736 fp = conn.makefile('rb')
737 try:
738 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300739 line = fp.readline(self.maxline + 1)
740 if len(line) > self.maxline:
741 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000742 if self.debugging > 2: print '*retr*', repr(line)
743 if not line:
744 break
745 if line[-2:] == CRLF:
746 line = line[:-2]
747 elif line[-1:] == '\n':
748 line = line[:-1]
749 callback(line)
750 # shutdown ssl layer
751 if isinstance(conn, ssl.SSLSocket):
752 conn.unwrap()
753 finally:
754 fp.close()
755 conn.close()
756 return self.voidresp()
757
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000758 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000759 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000760 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000761 try:
762 while 1:
763 buf = fp.read(blocksize)
764 if not buf: break
765 conn.sendall(buf)
766 if callback: callback(buf)
767 # shutdown ssl layer
768 if isinstance(conn, ssl.SSLSocket):
769 conn.unwrap()
770 finally:
771 conn.close()
772 return self.voidresp()
773
774 def storlines(self, cmd, fp, callback=None):
775 self.voidcmd('TYPE A')
776 conn = self.transfercmd(cmd)
777 try:
778 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300779 buf = fp.readline(self.maxline + 1)
780 if len(buf) > self.maxline:
781 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000782 if not buf: break
783 if buf[-2:] != CRLF:
784 if buf[-1] in CRLF: buf = buf[:-1]
785 buf = buf + CRLF
786 conn.sendall(buf)
787 if callback: callback(buf)
788 # shutdown ssl layer
789 if isinstance(conn, ssl.SSLSocket):
790 conn.unwrap()
791 finally:
792 conn.close()
793 return self.voidresp()
794
795 __all__.append('FTP_TLS')
796 all_errors = (Error, IOError, EOFError, ssl.SSLError)
797
798
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000799_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000800
801def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000802 '''Parse the '150' response for a RETR request.
803 Returns the expected transfer size or None; size is not guaranteed to
804 be present in the 150 message.
805 '''
806 if resp[:3] != '150':
807 raise error_reply, resp
808 global _150_re
809 if _150_re is None:
810 import re
811 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
812 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000813 if not m:
814 return None
815 s = m.group(1)
816 try:
817 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000818 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000819 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000820
821
Guido van Rossum70297d32001-08-17 17:24:29 +0000822_227_re = None
823
Guido van Rossumd2560b01996-05-28 23:41:25 +0000824def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000825 '''Parse the '227' response for a PASV request.
826 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
827 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000828
Tim Peters88869f92001-01-14 23:36:06 +0000829 if resp[:3] != '227':
830 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000831 global _227_re
832 if _227_re is None:
833 import re
834 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
835 m = _227_re.search(resp)
836 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000837 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000838 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000839 host = '.'.join(numbers[:4])
840 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000841 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000842
843
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000844def parse229(resp, peer):
845 '''Parse the '229' response for a EPSV request.
846 Raises error_proto if it does not contain '(|||port|)'
847 Return ('host.addr.as.numbers', port#) tuple.'''
848
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000849 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000850 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000851 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000852 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000853 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000854 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000855 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000856 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000857 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000858 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000859 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000860 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000861 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000862 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000863 return host, port
864
865
Guido van Rossumc567c601992-11-05 22:22:37 +0000866def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000867 '''Parse the '257' response for a MKD or PWD request.
868 This is a response to a MKD or PWD request: a directory name.
869 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000870
Tim Peters88869f92001-01-14 23:36:06 +0000871 if resp[:3] != '257':
872 raise error_reply, resp
873 if resp[3:5] != ' "':
874 return '' # Not compliant to RFC 959, but UNIX ftpd does this
875 dirname = ''
876 i = 5
877 n = len(resp)
878 while i < n:
879 c = resp[i]
880 i = i+1
881 if c == '"':
882 if i >= n or resp[i] != '"':
883 break
884 i = i+1
885 dirname = dirname + c
886 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000887
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000888
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000889def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000890 '''Default retrlines callback to print a line.'''
891 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000892
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000893
Guido van Rossumd2560b01996-05-28 23:41:25 +0000894def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000895 '''Copy file from one FTP-instance to another.'''
896 if not targetname: targetname = sourcename
897 type = 'TYPE ' + type
898 source.voidcmd(type)
899 target.voidcmd(type)
900 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
901 target.sendport(sourcehost, sourceport)
902 # RFC 959: the user must "listen" [...] BEFORE sending the
903 # transfer request.
904 # So: STOR before RETR, because here the target is a "user".
905 treply = target.sendcmd('STOR ' + targetname)
906 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
907 sreply = source.sendcmd('RETR ' + sourcename)
908 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
909 source.voidresp()
910 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000911
Tim Peters88869f92001-01-14 23:36:06 +0000912
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000913class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000914 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000915
Tim Peters88869f92001-01-14 23:36:06 +0000916 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000917
Tim Peters88869f92001-01-14 23:36:06 +0000918 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000919
Tim Peters88869f92001-01-14 23:36:06 +0000920 """
921 __defuser = None
922 __defpasswd = None
923 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000924
Tim Peters88869f92001-01-14 23:36:06 +0000925 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000926 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000927 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000928 filename = os.path.join(os.environ["HOME"],
929 ".netrc")
930 else:
931 raise IOError, \
932 "specify file to load or set $HOME"
933 self.__hosts = {}
934 self.__macros = {}
935 fp = open(filename, "r")
936 in_macro = 0
937 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300938 line = fp.readline(self.maxline + 1)
939 if len(line) > self.maxline:
940 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000941 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000942 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000943 macro_lines.append(line)
944 continue
945 elif in_macro:
946 self.__macros[macro_name] = tuple(macro_lines)
947 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000948 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000949 host = user = passwd = acct = None
950 default = 0
951 i = 0
952 while i < len(words):
953 w1 = words[i]
954 if i+1 < len(words):
955 w2 = words[i + 1]
956 else:
957 w2 = None
958 if w1 == 'default':
959 default = 1
960 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000961 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000962 i = i + 1
963 elif w1 == 'login' and w2:
964 user = w2
965 i = i + 1
966 elif w1 == 'password' and w2:
967 passwd = w2
968 i = i + 1
969 elif w1 == 'account' and w2:
970 acct = w2
971 i = i + 1
972 elif w1 == 'macdef' and w2:
973 macro_name = w2
974 macro_lines = []
975 in_macro = 1
976 break
977 i = i + 1
978 if default:
979 self.__defuser = user or self.__defuser
980 self.__defpasswd = passwd or self.__defpasswd
981 self.__defacct = acct or self.__defacct
982 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000983 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000984 ouser, opasswd, oacct = \
985 self.__hosts[host]
986 user = user or ouser
987 passwd = passwd or opasswd
988 acct = acct or oacct
989 self.__hosts[host] = user, passwd, acct
990 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000991
Tim Peters88869f92001-01-14 23:36:06 +0000992 def get_hosts(self):
993 """Return a list of hosts mentioned in the .netrc file."""
994 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000995
Tim Peters88869f92001-01-14 23:36:06 +0000996 def get_account(self, host):
997 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000998
Tim Peters88869f92001-01-14 23:36:06 +0000999 The return value is a triple containing userid,
1000 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001001
Tim Peters88869f92001-01-14 23:36:06 +00001002 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001003 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001004 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001005 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001006 user, passwd, acct = self.__hosts[host]
1007 user = user or self.__defuser
1008 passwd = passwd or self.__defpasswd
1009 acct = acct or self.__defacct
1010 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001011
Tim Peters88869f92001-01-14 23:36:06 +00001012 def get_macros(self):
1013 """Return a list of all defined macro names."""
1014 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001015
Tim Peters88869f92001-01-14 23:36:06 +00001016 def get_macro(self, macro):
1017 """Return a sequence of lines which define a named macro."""
1018 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001019
Fred Drake475d51d1997-06-24 22:02:54 +00001020
Tim Peters88869f92001-01-14 23:36:06 +00001021
Guido van Rossum1115ab21992-11-04 15:51:30 +00001022def test():
Tim Peters88869f92001-01-14 23:36:06 +00001023 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001024 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1025
1026 -d dir
1027 -l list
1028 -p password
1029 '''
1030
1031 if len(sys.argv) < 2:
1032 print test.__doc__
1033 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001034
Tim Peters88869f92001-01-14 23:36:06 +00001035 debugging = 0
1036 rcfile = None
1037 while sys.argv[1] == '-d':
1038 debugging = debugging+1
1039 del sys.argv[1]
1040 if sys.argv[1][:2] == '-r':
1041 # get name of alternate ~/.netrc file:
1042 rcfile = sys.argv[1][2:]
1043 del sys.argv[1]
1044 host = sys.argv[1]
1045 ftp = FTP(host)
1046 ftp.set_debuglevel(debugging)
1047 userid = passwd = acct = ''
1048 try:
1049 netrc = Netrc(rcfile)
1050 except IOError:
1051 if rcfile is not None:
1052 sys.stderr.write("Could not open account file"
1053 " -- using anonymous login.")
1054 else:
1055 try:
1056 userid, passwd, acct = netrc.get_account(host)
1057 except KeyError:
1058 # no account for host
1059 sys.stderr.write(
1060 "No account -- using anonymous login.")
1061 ftp.login(userid, passwd, acct)
1062 for file in sys.argv[2:]:
1063 if file[:2] == '-l':
1064 ftp.dir(file[2:])
1065 elif file[:2] == '-d':
1066 cmd = 'CWD'
1067 if file[2:]: cmd = cmd + ' ' + file[2:]
1068 resp = ftp.sendcmd(cmd)
1069 elif file == '-p':
1070 ftp.set_pasv(not ftp.passiveserver)
1071 else:
1072 ftp.retrbinary('RETR ' + file, \
1073 sys.stdout.write, 1024)
1074 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001075
1076
1077if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001078 test()