blob: 153647ba758ee0d710d1e0ec18c23dbdfd4580e6 [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 Panterb362f752015-11-02 03:37:02 +0000267 '''Send an EPRT command with the current host and the given port number.'''
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000268 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)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300415 try:
416 while 1:
417 data = conn.recv(blocksize)
418 if not data:
419 break
420 callback(data)
421 finally:
422 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000423 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000424
Tim Peters88869f92001-01-14 23:36:06 +0000425 def retrlines(self, cmd, callback = None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000426 """Retrieve data in line mode. A new port is created for you.
427
428 Args:
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000429 cmd: A RETR, LIST, NLST, or MLSD command.
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000430 callback: An optional single parameter callable that is called
431 for each line with the trailing CRLF stripped.
432 [default: print_line()]
433
434 Returns:
435 The response code.
436 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000437 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000438 resp = self.sendcmd('TYPE A')
439 conn = self.transfercmd(cmd)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300440 fp = None
441 try:
442 fp = conn.makefile('rb')
443 while 1:
444 line = fp.readline(self.maxline + 1)
445 if len(line) > self.maxline:
446 raise Error("got more than %d bytes" % self.maxline)
447 if self.debugging > 2: print '*retr*', repr(line)
448 if not line:
449 break
450 if line[-2:] == CRLF:
451 line = line[:-2]
452 elif line[-1:] == '\n':
453 line = line[:-1]
454 callback(line)
455 finally:
456 if fp:
457 fp.close()
458 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000459 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000460
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000461 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000462 """Store a file in binary mode. A new port is created for you.
463
464 Args:
465 cmd: A STOR command.
466 fp: A file-like object with a read(num_bytes) method.
467 blocksize: The maximum data size to read from fp and send over
468 the connection at once. [default: 8192]
469 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400470 each block of data after it is sent. [default: None]
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000471 rest: Passed to transfercmd(). [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000472
473 Returns:
474 The response code.
475 """
Tim Peters88869f92001-01-14 23:36:06 +0000476 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000477 conn = self.transfercmd(cmd, rest)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300478 try:
479 while 1:
480 buf = fp.read(blocksize)
481 if not buf: break
482 conn.sendall(buf)
483 if callback: callback(buf)
484 finally:
485 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000486 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000487
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000488 def storlines(self, cmd, fp, callback=None):
489 """Store a file in line mode. A new port is created for you.
490
491 Args:
492 cmd: A STOR command.
493 fp: A file-like object with a readline() method.
494 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400495 each line after it is sent. [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000496
497 Returns:
498 The response code.
499 """
Tim Peters88869f92001-01-14 23:36:06 +0000500 self.voidcmd('TYPE A')
501 conn = self.transfercmd(cmd)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300502 try:
503 while 1:
504 buf = fp.readline(self.maxline + 1)
505 if len(buf) > self.maxline:
506 raise Error("got more than %d bytes" % self.maxline)
507 if not buf: break
508 if buf[-2:] != CRLF:
509 if buf[-1] in CRLF: buf = buf[:-1]
510 buf = buf + CRLF
511 conn.sendall(buf)
512 if callback: callback(buf)
513 finally:
514 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000515 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000516
Tim Peters88869f92001-01-14 23:36:06 +0000517 def acct(self, password):
518 '''Send new account name.'''
519 cmd = 'ACCT ' + password
520 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000521
Tim Peters88869f92001-01-14 23:36:06 +0000522 def nlst(self, *args):
523 '''Return a list of files in a given directory (default the current).'''
524 cmd = 'NLST'
525 for arg in args:
526 cmd = cmd + (' ' + arg)
527 files = []
528 self.retrlines(cmd, files.append)
529 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000530
Tim Peters88869f92001-01-14 23:36:06 +0000531 def dir(self, *args):
532 '''List a directory in long form.
533 By default list current directory to stdout.
534 Optional last argument is callback function; all
535 non-empty arguments before it are concatenated to the
536 LIST command. (This *should* only be used for a pathname.)'''
537 cmd = 'LIST'
538 func = None
539 if args[-1:] and type(args[-1]) != type(''):
540 args, func = args[:-1], args[-1]
541 for arg in args:
542 if arg:
543 cmd = cmd + (' ' + arg)
544 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000545
Tim Peters88869f92001-01-14 23:36:06 +0000546 def rename(self, fromname, toname):
547 '''Rename a file.'''
548 resp = self.sendcmd('RNFR ' + fromname)
549 if resp[0] != '3':
550 raise error_reply, resp
551 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000552
Tim Peters88869f92001-01-14 23:36:06 +0000553 def delete(self, filename):
554 '''Delete a file.'''
555 resp = self.sendcmd('DELE ' + filename)
556 if resp[:3] in ('250', '200'):
557 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000558 else:
559 raise error_reply, resp
Guido van Rossum02cf5821993-05-17 08:00:02 +0000560
Tim Peters88869f92001-01-14 23:36:06 +0000561 def cwd(self, dirname):
562 '''Change to a directory.'''
563 if dirname == '..':
564 try:
565 return self.voidcmd('CDUP')
566 except error_perm, msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000567 if msg.args[0][:3] != '500':
568 raise
Tim Peters88869f92001-01-14 23:36:06 +0000569 elif dirname == '':
570 dirname = '.' # does nothing, but could return error
571 cmd = 'CWD ' + dirname
572 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000573
Tim Peters88869f92001-01-14 23:36:06 +0000574 def size(self, filename):
575 '''Retrieve the size of a file.'''
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000576 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000577 resp = self.sendcmd('SIZE ' + filename)
578 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000579 s = resp[3:].strip()
580 try:
581 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000582 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000583 return long(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000584
Tim Peters88869f92001-01-14 23:36:06 +0000585 def mkd(self, dirname):
586 '''Make a directory, return its full pathname.'''
587 resp = self.sendcmd('MKD ' + dirname)
588 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000589
Tim Peters88869f92001-01-14 23:36:06 +0000590 def rmd(self, dirname):
591 '''Remove a directory.'''
592 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000593
Tim Peters88869f92001-01-14 23:36:06 +0000594 def pwd(self):
595 '''Return current working directory.'''
596 resp = self.sendcmd('PWD')
597 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000598
Tim Peters88869f92001-01-14 23:36:06 +0000599 def quit(self):
600 '''Quit, and close the connection.'''
601 resp = self.voidcmd('QUIT')
602 self.close()
603 return resp
604
605 def close(self):
606 '''Close the connection without assuming anything about it.'''
Serhiy Storchaka1aa2c0f2015-04-10 13:24:10 +0300607 try:
608 file = self.file
609 self.file = None
610 if file is not None:
611 file.close()
612 finally:
613 sock = self.sock
614 self.sock = None
615 if sock is not None:
616 sock.close()
Guido van Rossumc567c601992-11-05 22:22:37 +0000617
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000618try:
619 import ssl
620except ImportError:
621 pass
622else:
623 class FTP_TLS(FTP):
624 '''A FTP subclass which adds TLS support to FTP as described
625 in RFC-4217.
626
627 Connect as usual to port 21 implicitly securing the FTP control
628 connection before authenticating.
629
630 Securing the data connection requires user to explicitly ask
631 for it by calling prot_p() method.
632
633 Usage example:
634 >>> from ftplib import FTP_TLS
635 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200636 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000637 '230 Guest login ok, access restrictions apply.'
638 >>> ftps.prot_p() # switch to secure data connection
639 '200 Protection level set to P'
640 >>> ftps.retrlines('LIST') # list directory content securely
641 total 9
642 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
643 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
644 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
645 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
646 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
647 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
648 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
649 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
650 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
651 '226 Transfer complete.'
652 >>> ftps.quit()
653 '221 Goodbye.'
654 >>>
655 '''
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600656 ssl_version = ssl.PROTOCOL_SSLv23
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000657
658 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600659 certfile=None, context=None,
660 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
661 if context is not None and keyfile is not None:
662 raise ValueError("context and keyfile arguments are mutually "
663 "exclusive")
664 if context is not None and certfile is not None:
665 raise ValueError("context and certfile arguments are mutually "
666 "exclusive")
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000667 self.keyfile = keyfile
668 self.certfile = certfile
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600669 if context is None:
670 context = ssl._create_stdlib_context(self.ssl_version,
671 certfile=certfile,
672 keyfile=keyfile)
673 self.context = context
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000674 self._prot_p = False
675 FTP.__init__(self, host, user, passwd, acct, timeout)
676
677 def login(self, user='', passwd='', acct='', secure=True):
678 if secure and not isinstance(self.sock, ssl.SSLSocket):
679 self.auth()
680 return FTP.login(self, user, passwd, acct)
681
682 def auth(self):
683 '''Set up secure control connection by using TLS/SSL.'''
684 if isinstance(self.sock, ssl.SSLSocket):
685 raise ValueError("Already using TLS")
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600686 if self.ssl_version >= ssl.PROTOCOL_SSLv23:
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000687 resp = self.voidcmd('AUTH TLS')
688 else:
689 resp = self.voidcmd('AUTH SSL')
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600690 self.sock = self.context.wrap_socket(self.sock,
691 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000692 self.file = self.sock.makefile(mode='rb')
693 return resp
694
695 def prot_p(self):
696 '''Set up secure data connection.'''
697 # PROT defines whether or not the data channel is to be protected.
698 # Though RFC-2228 defines four possible protection levels,
699 # RFC-4217 only recommends two, Clear and Private.
700 # Clear (PROT C) means that no security is to be used on the
701 # data-channel, Private (PROT P) means that the data-channel
702 # should be protected by TLS.
703 # PBSZ command MUST still be issued, but must have a parameter of
704 # '0' to indicate that no buffering is taking place and the data
705 # connection should not be encapsulated.
706 self.voidcmd('PBSZ 0')
707 resp = self.voidcmd('PROT P')
708 self._prot_p = True
709 return resp
710
711 def prot_c(self):
712 '''Set up clear text data connection.'''
713 resp = self.voidcmd('PROT C')
714 self._prot_p = False
715 return resp
716
717 # --- Overridden FTP methods
718
719 def ntransfercmd(self, cmd, rest=None):
720 conn, size = FTP.ntransfercmd(self, cmd, rest)
721 if self._prot_p:
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600722 conn = self.context.wrap_socket(conn,
723 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000724 return conn, size
725
726 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
727 self.voidcmd('TYPE I')
728 conn = self.transfercmd(cmd, rest)
729 try:
730 while 1:
731 data = conn.recv(blocksize)
732 if not data:
733 break
734 callback(data)
735 # shutdown ssl layer
736 if isinstance(conn, ssl.SSLSocket):
737 conn.unwrap()
738 finally:
739 conn.close()
740 return self.voidresp()
741
742 def retrlines(self, cmd, callback = None):
743 if callback is None: callback = print_line
744 resp = self.sendcmd('TYPE A')
745 conn = self.transfercmd(cmd)
746 fp = conn.makefile('rb')
747 try:
748 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300749 line = fp.readline(self.maxline + 1)
750 if len(line) > self.maxline:
751 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000752 if self.debugging > 2: print '*retr*', repr(line)
753 if not line:
754 break
755 if line[-2:] == CRLF:
756 line = line[:-2]
757 elif line[-1:] == '\n':
758 line = line[:-1]
759 callback(line)
760 # shutdown ssl layer
761 if isinstance(conn, ssl.SSLSocket):
762 conn.unwrap()
763 finally:
764 fp.close()
765 conn.close()
766 return self.voidresp()
767
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000768 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000769 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000770 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000771 try:
772 while 1:
773 buf = fp.read(blocksize)
774 if not buf: break
775 conn.sendall(buf)
776 if callback: callback(buf)
777 # shutdown ssl layer
778 if isinstance(conn, ssl.SSLSocket):
779 conn.unwrap()
780 finally:
781 conn.close()
782 return self.voidresp()
783
784 def storlines(self, cmd, fp, callback=None):
785 self.voidcmd('TYPE A')
786 conn = self.transfercmd(cmd)
787 try:
788 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300789 buf = fp.readline(self.maxline + 1)
790 if len(buf) > self.maxline:
791 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000792 if not buf: break
793 if buf[-2:] != CRLF:
794 if buf[-1] in CRLF: buf = buf[:-1]
795 buf = buf + CRLF
796 conn.sendall(buf)
797 if callback: callback(buf)
798 # shutdown ssl layer
799 if isinstance(conn, ssl.SSLSocket):
800 conn.unwrap()
801 finally:
802 conn.close()
803 return self.voidresp()
804
805 __all__.append('FTP_TLS')
806 all_errors = (Error, IOError, EOFError, ssl.SSLError)
807
808
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000809_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000810
811def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000812 '''Parse the '150' response for a RETR request.
813 Returns the expected transfer size or None; size is not guaranteed to
814 be present in the 150 message.
815 '''
816 if resp[:3] != '150':
817 raise error_reply, resp
818 global _150_re
819 if _150_re is None:
820 import re
821 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
822 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000823 if not m:
824 return None
825 s = m.group(1)
826 try:
827 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000828 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000829 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000830
831
Guido van Rossum70297d32001-08-17 17:24:29 +0000832_227_re = None
833
Guido van Rossumd2560b01996-05-28 23:41:25 +0000834def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000835 '''Parse the '227' response for a PASV request.
836 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
837 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000838
Tim Peters88869f92001-01-14 23:36:06 +0000839 if resp[:3] != '227':
840 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000841 global _227_re
842 if _227_re is None:
843 import re
844 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
845 m = _227_re.search(resp)
846 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000847 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000848 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000849 host = '.'.join(numbers[:4])
850 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000851 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000852
853
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000854def parse229(resp, peer):
Martin Panterb362f752015-11-02 03:37:02 +0000855 '''Parse the '229' response for an EPSV request.
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000856 Raises error_proto if it does not contain '(|||port|)'
857 Return ('host.addr.as.numbers', port#) tuple.'''
858
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000859 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000860 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000861 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000862 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000863 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000864 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000865 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000866 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000867 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000868 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000869 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000870 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000871 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000872 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000873 return host, port
874
875
Guido van Rossumc567c601992-11-05 22:22:37 +0000876def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000877 '''Parse the '257' response for a MKD or PWD request.
878 This is a response to a MKD or PWD request: a directory name.
879 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000880
Tim Peters88869f92001-01-14 23:36:06 +0000881 if resp[:3] != '257':
882 raise error_reply, resp
883 if resp[3:5] != ' "':
884 return '' # Not compliant to RFC 959, but UNIX ftpd does this
885 dirname = ''
886 i = 5
887 n = len(resp)
888 while i < n:
889 c = resp[i]
890 i = i+1
891 if c == '"':
892 if i >= n or resp[i] != '"':
893 break
894 i = i+1
895 dirname = dirname + c
896 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000897
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000898
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000899def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000900 '''Default retrlines callback to print a line.'''
901 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000902
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000903
Guido van Rossumd2560b01996-05-28 23:41:25 +0000904def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000905 '''Copy file from one FTP-instance to another.'''
906 if not targetname: targetname = sourcename
907 type = 'TYPE ' + type
908 source.voidcmd(type)
909 target.voidcmd(type)
910 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
911 target.sendport(sourcehost, sourceport)
912 # RFC 959: the user must "listen" [...] BEFORE sending the
913 # transfer request.
914 # So: STOR before RETR, because here the target is a "user".
915 treply = target.sendcmd('STOR ' + targetname)
916 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
917 sreply = source.sendcmd('RETR ' + sourcename)
918 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
919 source.voidresp()
920 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000921
Tim Peters88869f92001-01-14 23:36:06 +0000922
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000923class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000924 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000925
Tim Peters88869f92001-01-14 23:36:06 +0000926 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000927
Tim Peters88869f92001-01-14 23:36:06 +0000928 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000929
Tim Peters88869f92001-01-14 23:36:06 +0000930 """
931 __defuser = None
932 __defpasswd = None
933 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000934
Tim Peters88869f92001-01-14 23:36:06 +0000935 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000936 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000937 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000938 filename = os.path.join(os.environ["HOME"],
939 ".netrc")
940 else:
941 raise IOError, \
942 "specify file to load or set $HOME"
943 self.__hosts = {}
944 self.__macros = {}
945 fp = open(filename, "r")
946 in_macro = 0
947 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300948 line = fp.readline(self.maxline + 1)
949 if len(line) > self.maxline:
950 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000951 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000952 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000953 macro_lines.append(line)
954 continue
955 elif in_macro:
956 self.__macros[macro_name] = tuple(macro_lines)
957 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000958 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000959 host = user = passwd = acct = None
960 default = 0
961 i = 0
962 while i < len(words):
963 w1 = words[i]
964 if i+1 < len(words):
965 w2 = words[i + 1]
966 else:
967 w2 = None
968 if w1 == 'default':
969 default = 1
970 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000971 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000972 i = i + 1
973 elif w1 == 'login' and w2:
974 user = w2
975 i = i + 1
976 elif w1 == 'password' and w2:
977 passwd = w2
978 i = i + 1
979 elif w1 == 'account' and w2:
980 acct = w2
981 i = i + 1
982 elif w1 == 'macdef' and w2:
983 macro_name = w2
984 macro_lines = []
985 in_macro = 1
986 break
987 i = i + 1
988 if default:
989 self.__defuser = user or self.__defuser
990 self.__defpasswd = passwd or self.__defpasswd
991 self.__defacct = acct or self.__defacct
992 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000993 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000994 ouser, opasswd, oacct = \
995 self.__hosts[host]
996 user = user or ouser
997 passwd = passwd or opasswd
998 acct = acct or oacct
999 self.__hosts[host] = user, passwd, acct
1000 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001001
Tim Peters88869f92001-01-14 23:36:06 +00001002 def get_hosts(self):
1003 """Return a list of hosts mentioned in the .netrc file."""
1004 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001005
Tim Peters88869f92001-01-14 23:36:06 +00001006 def get_account(self, host):
1007 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001008
Tim Peters88869f92001-01-14 23:36:06 +00001009 The return value is a triple containing userid,
1010 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001011
Tim Peters88869f92001-01-14 23:36:06 +00001012 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001013 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001014 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001015 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001016 user, passwd, acct = self.__hosts[host]
1017 user = user or self.__defuser
1018 passwd = passwd or self.__defpasswd
1019 acct = acct or self.__defacct
1020 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001021
Tim Peters88869f92001-01-14 23:36:06 +00001022 def get_macros(self):
1023 """Return a list of all defined macro names."""
1024 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001025
Tim Peters88869f92001-01-14 23:36:06 +00001026 def get_macro(self, macro):
1027 """Return a sequence of lines which define a named macro."""
1028 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001029
Fred Drake475d51d1997-06-24 22:02:54 +00001030
Tim Peters88869f92001-01-14 23:36:06 +00001031
Guido van Rossum1115ab21992-11-04 15:51:30 +00001032def test():
Tim Peters88869f92001-01-14 23:36:06 +00001033 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001034 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1035
1036 -d dir
1037 -l list
1038 -p password
1039 '''
1040
1041 if len(sys.argv) < 2:
1042 print test.__doc__
1043 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001044
Tim Peters88869f92001-01-14 23:36:06 +00001045 debugging = 0
1046 rcfile = None
1047 while sys.argv[1] == '-d':
1048 debugging = debugging+1
1049 del sys.argv[1]
1050 if sys.argv[1][:2] == '-r':
1051 # get name of alternate ~/.netrc file:
1052 rcfile = sys.argv[1][2:]
1053 del sys.argv[1]
1054 host = sys.argv[1]
1055 ftp = FTP(host)
1056 ftp.set_debuglevel(debugging)
1057 userid = passwd = acct = ''
1058 try:
1059 netrc = Netrc(rcfile)
1060 except IOError:
1061 if rcfile is not None:
1062 sys.stderr.write("Could not open account file"
1063 " -- using anonymous login.")
1064 else:
1065 try:
1066 userid, passwd, acct = netrc.get_account(host)
1067 except KeyError:
1068 # no account for host
1069 sys.stderr.write(
1070 "No account -- using anonymous login.")
1071 ftp.login(userid, passwd, acct)
1072 for file in sys.argv[2:]:
1073 if file[:2] == '-l':
1074 ftp.dir(file[2:])
1075 elif file[:2] == '-d':
1076 cmd = 'CWD'
1077 if file[2:]: cmd = cmd + ' ' + file[2:]
1078 resp = ftp.sendcmd(cmd)
1079 elif file == '-p':
1080 ftp.set_pasv(not ftp.passiveserver)
1081 else:
1082 ftp.retrbinary('RETR ' + file, \
1083 sys.stdout.write, 1024)
1084 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001085
1086
1087if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001088 test()