blob: 6644554792791bdd5357882214db150820784014 [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):
Dong-hee Nae5eae472017-07-27 00:50:36 +0900174 if '\r' in line or '\n' in line:
175 raise ValueError('an illegal newline character should not be contained')
Tim Peters88869f92001-01-14 23:36:06 +0000176 line = line + CRLF
177 if self.debugging > 1: print '*put*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000178 self.sock.sendall(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000179
Tim Peters88869f92001-01-14 23:36:06 +0000180 # Internal: send one command to the server (through putline())
181 def putcmd(self, line):
182 if self.debugging: print '*cmd*', self.sanitize(line)
183 self.putline(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000184
Tim Peters88869f92001-01-14 23:36:06 +0000185 # Internal: return one line from the server, stripping CRLF.
186 # Raise EOFError if the connection is closed
187 def getline(self):
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300188 line = self.file.readline(self.maxline + 1)
189 if len(line) > self.maxline:
190 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000191 if self.debugging > 1:
192 print '*get*', self.sanitize(line)
193 if not line: raise EOFError
194 if line[-2:] == CRLF: line = line[:-2]
195 elif line[-1:] in CRLF: line = line[:-1]
196 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000197
Tim Peters88869f92001-01-14 23:36:06 +0000198 # Internal: get a response from the server, which may possibly
199 # consist of multiple lines. Return a single string with no
200 # trailing CRLF. If the response consists of multiple lines,
201 # these are separated by '\n' characters in the string
202 def getmultiline(self):
203 line = self.getline()
204 if line[3:4] == '-':
205 code = line[:3]
206 while 1:
207 nextline = self.getline()
208 line = line + ('\n' + nextline)
209 if nextline[:3] == code and \
210 nextline[3:4] != '-':
211 break
212 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000213
Tim Peters88869f92001-01-14 23:36:06 +0000214 # Internal: get a response from the server.
215 # Raise various errors if the response indicates an error
216 def getresp(self):
217 resp = self.getmultiline()
218 if self.debugging: print '*resp*', self.sanitize(resp)
219 self.lastresp = resp[:3]
220 c = resp[:1]
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000221 if c in ('1', '2', '3'):
222 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000223 if c == '4':
224 raise error_temp, resp
225 if c == '5':
226 raise error_perm, resp
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000227 raise error_proto, resp
Guido van Rossum1115ab21992-11-04 15:51:30 +0000228
Tim Peters88869f92001-01-14 23:36:06 +0000229 def voidresp(self):
230 """Expect a response beginning with '2'."""
231 resp = self.getresp()
Georg Brandl50ba6e12009-04-05 10:48:47 +0000232 if resp[:1] != '2':
Tim Peters88869f92001-01-14 23:36:06 +0000233 raise error_reply, resp
234 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000235
Tim Peters88869f92001-01-14 23:36:06 +0000236 def abort(self):
237 '''Abort a file transfer. Uses out-of-band data.
238 This does not follow the procedure from the RFC to send Telnet
239 IP and Synch; that doesn't seem to work with the servers I've
240 tried. Instead, just send the ABOR command as OOB data.'''
241 line = 'ABOR' + CRLF
242 if self.debugging > 1: print '*put urgent*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000243 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000244 resp = self.getmultiline()
Giampaolo Rodolàcf445fc2010-04-18 12:55:03 +0000245 if resp[:3] not in ('426', '225', '226'):
Tim Peters88869f92001-01-14 23:36:06 +0000246 raise error_proto, resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000247
Tim Peters88869f92001-01-14 23:36:06 +0000248 def sendcmd(self, cmd):
249 '''Send a command and return the response.'''
250 self.putcmd(cmd)
251 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000252
Tim Peters88869f92001-01-14 23:36:06 +0000253 def voidcmd(self, cmd):
254 """Send a command and expect a response beginning with '2'."""
255 self.putcmd(cmd)
256 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000257
Tim Peters88869f92001-01-14 23:36:06 +0000258 def sendport(self, host, port):
259 '''Send a PORT command with the current host and the given
260 port number.
261 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000262 hbytes = host.split('.')
Benjamin Petersondee0b172008-09-27 22:08:12 +0000263 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000264 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000265 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000266 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000267
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000268 def sendeprt(self, host, port):
Martin Panterb362f752015-11-02 03:37:02 +0000269 '''Send an EPRT command with the current host and the given port number.'''
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000270 af = 0
271 if self.af == socket.AF_INET:
272 af = 1
273 if self.af == socket.AF_INET6:
274 af = 2
275 if af == 0:
276 raise error_proto, 'unsupported address family'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000277 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000278 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000279 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000280
Tim Peters88869f92001-01-14 23:36:06 +0000281 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000282 '''Create a new socket and send a PORT command for it.'''
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100283 err = None
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000284 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000285 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
286 af, socktype, proto, canonname, sa = res
287 try:
288 sock = socket.socket(af, socktype, proto)
289 sock.bind(sa)
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100290 except socket.error, err:
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000291 if sock:
292 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000293 sock = None
294 continue
295 break
Giampaolo Rodola'c2a81692012-12-17 14:30:48 +0100296 if sock is None:
297 if err is not None:
298 raise err
299 else:
300 raise socket.error("getaddrinfo returns an empty list")
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000301 sock.listen(1)
302 port = sock.getsockname()[1] # Get proper port
303 host = self.sock.getsockname()[0] # Get proper host
304 if self.af == socket.AF_INET:
305 resp = self.sendport(host, port)
306 else:
307 resp = self.sendeprt(host, port)
Giampaolo Rodolà607f7c02010-04-19 21:46:28 +0000308 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
309 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000310 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000311
312 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000313 if self.af == socket.AF_INET:
314 host, port = parse227(self.sendcmd('PASV'))
315 else:
316 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
317 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000318
Tim Peters88869f92001-01-14 23:36:06 +0000319 def ntransfercmd(self, cmd, rest=None):
320 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000321
Tim Peters88869f92001-01-14 23:36:06 +0000322 If the transfer is active, send a port command and the
323 transfer command, and accept the connection. If the server is
324 passive, send a pasv command, connect to it, and start the
325 transfer command. Either way, return the socket for the
326 connection and the expected size of the transfer. The
327 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000328
Tim Peters88869f92001-01-14 23:36:06 +0000329 Optional `rest' argument can be a string that is sent as the
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000330 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000331 marker used to tell the server to skip over any data up to the
332 given marker.
333 """
334 size = None
335 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000336 host, port = self.makepasv()
Facundo Batista92493122007-06-06 15:13:37 +0000337 conn = socket.create_connection((host, port), self.timeout)
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200338 try:
339 if rest is not None:
340 self.sendcmd("REST %s" % rest)
341 resp = self.sendcmd(cmd)
342 # Some servers apparently send a 200 reply to
343 # a LIST or STOR command, before the 150 reply
344 # (and way before the 226 reply). This seems to
345 # be in violation of the protocol (which only allows
346 # 1xx or error messages for LIST), so we just discard
347 # this response.
348 if resp[0] == '2':
349 resp = self.getresp()
350 if resp[0] != '1':
351 raise error_reply, resp
352 except:
353 conn.close()
354 raise
Tim Peters88869f92001-01-14 23:36:06 +0000355 else:
356 sock = self.makeport()
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200357 try:
358 if rest is not None:
359 self.sendcmd("REST %s" % rest)
360 resp = self.sendcmd(cmd)
361 # See above.
362 if resp[0] == '2':
363 resp = self.getresp()
364 if resp[0] != '1':
365 raise error_reply, resp
366 conn, sockaddr = sock.accept()
367 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
368 conn.settimeout(self.timeout)
369 finally:
370 sock.close()
Tim Peters88869f92001-01-14 23:36:06 +0000371 if resp[:3] == '150':
372 # this is conditional in case we received a 125
373 size = parse150(resp)
374 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000375
Tim Peters88869f92001-01-14 23:36:06 +0000376 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000377 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000378 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000379
Tim Peters88869f92001-01-14 23:36:06 +0000380 def login(self, user = '', passwd = '', acct = ''):
381 '''Login, default anonymous.'''
382 if not user: user = 'anonymous'
383 if not passwd: passwd = ''
384 if not acct: acct = ''
385 if user == 'anonymous' and passwd in ('', '-'):
Tim Peterse4418602002-02-16 07:34:19 +0000386 # If there is no anonymous ftp password specified
387 # then we'll just use anonymous@
388 # We don't send any other thing because:
389 # - We want to remain anonymous
390 # - We want to stop SPAM
391 # - We don't want to let ftp sites to discriminate by the user,
392 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000393 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000394 resp = self.sendcmd('USER ' + user)
395 if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
396 if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
397 if resp[0] != '2':
398 raise error_reply, resp
399 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000400
Tim Peters88869f92001-01-14 23:36:06 +0000401 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000402 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000403
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000404 Args:
405 cmd: A RETR command.
406 callback: A single parameter callable to be called on each
407 block of data read.
408 blocksize: The maximum number of bytes to read from the
409 socket at one time. [default: 8192]
410 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000411
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000412 Returns:
413 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000414 """
415 self.voidcmd('TYPE I')
416 conn = self.transfercmd(cmd, rest)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300417 try:
418 while 1:
419 data = conn.recv(blocksize)
420 if not data:
421 break
422 callback(data)
423 finally:
424 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000425 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000426
Tim Peters88869f92001-01-14 23:36:06 +0000427 def retrlines(self, cmd, callback = None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000428 """Retrieve data in line mode. A new port is created for you.
429
430 Args:
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000431 cmd: A RETR, LIST, NLST, or MLSD command.
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000432 callback: An optional single parameter callable that is called
433 for each line with the trailing CRLF stripped.
434 [default: print_line()]
435
436 Returns:
437 The response code.
438 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000439 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000440 resp = self.sendcmd('TYPE A')
441 conn = self.transfercmd(cmd)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300442 fp = None
443 try:
444 fp = conn.makefile('rb')
445 while 1:
446 line = fp.readline(self.maxline + 1)
447 if len(line) > self.maxline:
448 raise Error("got more than %d bytes" % self.maxline)
449 if self.debugging > 2: print '*retr*', repr(line)
450 if not line:
451 break
452 if line[-2:] == CRLF:
453 line = line[:-2]
454 elif line[-1:] == '\n':
455 line = line[:-1]
456 callback(line)
457 finally:
458 if fp:
459 fp.close()
460 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000461 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000462
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000463 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000464 """Store a file in binary mode. A new port is created for you.
465
466 Args:
467 cmd: A STOR command.
468 fp: A file-like object with a read(num_bytes) method.
469 blocksize: The maximum data size to read from fp and send over
470 the connection at once. [default: 8192]
471 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400472 each block of data after it is sent. [default: None]
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000473 rest: Passed to transfercmd(). [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000474
475 Returns:
476 The response code.
477 """
Tim Peters88869f92001-01-14 23:36:06 +0000478 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000479 conn = self.transfercmd(cmd, rest)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300480 try:
481 while 1:
482 buf = fp.read(blocksize)
483 if not buf: break
484 conn.sendall(buf)
485 if callback: callback(buf)
486 finally:
487 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000488 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000489
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000490 def storlines(self, cmd, fp, callback=None):
491 """Store a file in line mode. A new port is created for you.
492
493 Args:
494 cmd: A STOR command.
495 fp: A file-like object with a readline() method.
496 callback: An optional single parameter callable that is called on
Terry Jan Reedya70f60a2013-03-11 17:56:17 -0400497 each line after it is sent. [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000498
499 Returns:
500 The response code.
501 """
Tim Peters88869f92001-01-14 23:36:06 +0000502 self.voidcmd('TYPE A')
503 conn = self.transfercmd(cmd)
Ivan Mokeevd64146c2017-04-03 14:06:34 +0300504 try:
505 while 1:
506 buf = fp.readline(self.maxline + 1)
507 if len(buf) > self.maxline:
508 raise Error("got more than %d bytes" % self.maxline)
509 if not buf: break
510 if buf[-2:] != CRLF:
511 if buf[-1] in CRLF: buf = buf[:-1]
512 buf = buf + CRLF
513 conn.sendall(buf)
514 if callback: callback(buf)
515 finally:
516 conn.close()
Tim Peters88869f92001-01-14 23:36:06 +0000517 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000518
Tim Peters88869f92001-01-14 23:36:06 +0000519 def acct(self, password):
520 '''Send new account name.'''
521 cmd = 'ACCT ' + password
522 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000523
Tim Peters88869f92001-01-14 23:36:06 +0000524 def nlst(self, *args):
525 '''Return a list of files in a given directory (default the current).'''
526 cmd = 'NLST'
527 for arg in args:
528 cmd = cmd + (' ' + arg)
529 files = []
530 self.retrlines(cmd, files.append)
531 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000532
Tim Peters88869f92001-01-14 23:36:06 +0000533 def dir(self, *args):
534 '''List a directory in long form.
535 By default list current directory to stdout.
536 Optional last argument is callback function; all
537 non-empty arguments before it are concatenated to the
538 LIST command. (This *should* only be used for a pathname.)'''
539 cmd = 'LIST'
540 func = None
541 if args[-1:] and type(args[-1]) != type(''):
542 args, func = args[:-1], args[-1]
543 for arg in args:
544 if arg:
545 cmd = cmd + (' ' + arg)
546 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000547
Tim Peters88869f92001-01-14 23:36:06 +0000548 def rename(self, fromname, toname):
549 '''Rename a file.'''
550 resp = self.sendcmd('RNFR ' + fromname)
551 if resp[0] != '3':
552 raise error_reply, resp
553 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000554
Tim Peters88869f92001-01-14 23:36:06 +0000555 def delete(self, filename):
556 '''Delete a file.'''
557 resp = self.sendcmd('DELE ' + filename)
558 if resp[:3] in ('250', '200'):
559 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000560 else:
561 raise error_reply, resp
Guido van Rossum02cf5821993-05-17 08:00:02 +0000562
Tim Peters88869f92001-01-14 23:36:06 +0000563 def cwd(self, dirname):
564 '''Change to a directory.'''
565 if dirname == '..':
566 try:
567 return self.voidcmd('CDUP')
568 except error_perm, msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000569 if msg.args[0][:3] != '500':
570 raise
Tim Peters88869f92001-01-14 23:36:06 +0000571 elif dirname == '':
572 dirname = '.' # does nothing, but could return error
573 cmd = 'CWD ' + dirname
574 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000575
Tim Peters88869f92001-01-14 23:36:06 +0000576 def size(self, filename):
577 '''Retrieve the size of a file.'''
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000578 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000579 resp = self.sendcmd('SIZE ' + filename)
580 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000581 s = resp[3:].strip()
582 try:
583 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000584 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000585 return long(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000586
Tim Peters88869f92001-01-14 23:36:06 +0000587 def mkd(self, dirname):
588 '''Make a directory, return its full pathname.'''
589 resp = self.sendcmd('MKD ' + dirname)
590 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000591
Tim Peters88869f92001-01-14 23:36:06 +0000592 def rmd(self, dirname):
593 '''Remove a directory.'''
594 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000595
Tim Peters88869f92001-01-14 23:36:06 +0000596 def pwd(self):
597 '''Return current working directory.'''
598 resp = self.sendcmd('PWD')
599 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000600
Tim Peters88869f92001-01-14 23:36:06 +0000601 def quit(self):
602 '''Quit, and close the connection.'''
603 resp = self.voidcmd('QUIT')
604 self.close()
605 return resp
606
607 def close(self):
608 '''Close the connection without assuming anything about it.'''
Serhiy Storchaka1aa2c0f2015-04-10 13:24:10 +0300609 try:
610 file = self.file
611 self.file = None
612 if file is not None:
613 file.close()
614 finally:
615 sock = self.sock
616 self.sock = None
617 if sock is not None:
618 sock.close()
Guido van Rossumc567c601992-11-05 22:22:37 +0000619
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000620try:
621 import ssl
622except ImportError:
623 pass
624else:
625 class FTP_TLS(FTP):
626 '''A FTP subclass which adds TLS support to FTP as described
627 in RFC-4217.
628
629 Connect as usual to port 21 implicitly securing the FTP control
630 connection before authenticating.
631
632 Securing the data connection requires user to explicitly ask
633 for it by calling prot_p() method.
634
635 Usage example:
636 >>> from ftplib import FTP_TLS
637 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200638 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000639 '230 Guest login ok, access restrictions apply.'
640 >>> ftps.prot_p() # switch to secure data connection
641 '200 Protection level set to P'
642 >>> ftps.retrlines('LIST') # list directory content securely
643 total 9
644 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
645 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
646 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
647 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
648 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
649 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
650 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
651 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
652 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
653 '226 Transfer complete.'
654 >>> ftps.quit()
655 '221 Goodbye.'
656 >>>
657 '''
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600658 ssl_version = ssl.PROTOCOL_SSLv23
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000659
660 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600661 certfile=None, context=None,
662 timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
663 if context is not None and keyfile is not None:
664 raise ValueError("context and keyfile arguments are mutually "
665 "exclusive")
666 if context is not None and certfile is not None:
667 raise ValueError("context and certfile arguments are mutually "
668 "exclusive")
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000669 self.keyfile = keyfile
670 self.certfile = certfile
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600671 if context is None:
672 context = ssl._create_stdlib_context(self.ssl_version,
673 certfile=certfile,
674 keyfile=keyfile)
675 self.context = context
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000676 self._prot_p = False
677 FTP.__init__(self, host, user, passwd, acct, timeout)
678
679 def login(self, user='', passwd='', acct='', secure=True):
680 if secure and not isinstance(self.sock, ssl.SSLSocket):
681 self.auth()
682 return FTP.login(self, user, passwd, acct)
683
684 def auth(self):
685 '''Set up secure control connection by using TLS/SSL.'''
686 if isinstance(self.sock, ssl.SSLSocket):
687 raise ValueError("Already using TLS")
Benjamin Peterson9fe67ce2015-01-04 10:20:16 -0600688 if self.ssl_version >= ssl.PROTOCOL_SSLv23:
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000689 resp = self.voidcmd('AUTH TLS')
690 else:
691 resp = self.voidcmd('AUTH SSL')
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600692 self.sock = self.context.wrap_socket(self.sock,
693 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000694 self.file = self.sock.makefile(mode='rb')
695 return resp
696
697 def prot_p(self):
698 '''Set up secure data connection.'''
699 # PROT defines whether or not the data channel is to be protected.
700 # Though RFC-2228 defines four possible protection levels,
701 # RFC-4217 only recommends two, Clear and Private.
702 # Clear (PROT C) means that no security is to be used on the
703 # data-channel, Private (PROT P) means that the data-channel
704 # should be protected by TLS.
705 # PBSZ command MUST still be issued, but must have a parameter of
706 # '0' to indicate that no buffering is taking place and the data
707 # connection should not be encapsulated.
708 self.voidcmd('PBSZ 0')
709 resp = self.voidcmd('PROT P')
710 self._prot_p = True
711 return resp
712
713 def prot_c(self):
714 '''Set up clear text data connection.'''
715 resp = self.voidcmd('PROT C')
716 self._prot_p = False
717 return resp
718
719 # --- Overridden FTP methods
720
721 def ntransfercmd(self, cmd, rest=None):
722 conn, size = FTP.ntransfercmd(self, cmd, rest)
723 if self._prot_p:
Benjamin Peterson7b4b2842015-01-04 15:36:31 -0600724 conn = self.context.wrap_socket(conn,
725 server_hostname=self.host)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000726 return conn, size
727
728 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
729 self.voidcmd('TYPE I')
730 conn = self.transfercmd(cmd, rest)
731 try:
732 while 1:
733 data = conn.recv(blocksize)
734 if not data:
735 break
736 callback(data)
737 # shutdown ssl layer
738 if isinstance(conn, ssl.SSLSocket):
739 conn.unwrap()
740 finally:
741 conn.close()
742 return self.voidresp()
743
744 def retrlines(self, cmd, callback = None):
745 if callback is None: callback = print_line
746 resp = self.sendcmd('TYPE A')
747 conn = self.transfercmd(cmd)
748 fp = conn.makefile('rb')
749 try:
750 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300751 line = fp.readline(self.maxline + 1)
752 if len(line) > self.maxline:
753 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000754 if self.debugging > 2: print '*retr*', repr(line)
755 if not line:
756 break
757 if line[-2:] == CRLF:
758 line = line[:-2]
759 elif line[-1:] == '\n':
760 line = line[:-1]
761 callback(line)
762 # shutdown ssl layer
763 if isinstance(conn, ssl.SSLSocket):
764 conn.unwrap()
765 finally:
766 fp.close()
767 conn.close()
768 return self.voidresp()
769
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000770 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000771 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000772 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000773 try:
774 while 1:
775 buf = fp.read(blocksize)
776 if not buf: break
777 conn.sendall(buf)
778 if callback: callback(buf)
779 # shutdown ssl layer
780 if isinstance(conn, ssl.SSLSocket):
781 conn.unwrap()
782 finally:
783 conn.close()
784 return self.voidresp()
785
786 def storlines(self, cmd, fp, callback=None):
787 self.voidcmd('TYPE A')
788 conn = self.transfercmd(cmd)
789 try:
790 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300791 buf = fp.readline(self.maxline + 1)
792 if len(buf) > self.maxline:
793 raise Error("got more than %d bytes" % self.maxline)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000794 if not buf: break
795 if buf[-2:] != CRLF:
796 if buf[-1] in CRLF: buf = buf[:-1]
797 buf = buf + CRLF
798 conn.sendall(buf)
799 if callback: callback(buf)
800 # shutdown ssl layer
801 if isinstance(conn, ssl.SSLSocket):
802 conn.unwrap()
803 finally:
804 conn.close()
805 return self.voidresp()
806
807 __all__.append('FTP_TLS')
808 all_errors = (Error, IOError, EOFError, ssl.SSLError)
809
810
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000811_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000812
813def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000814 '''Parse the '150' response for a RETR request.
815 Returns the expected transfer size or None; size is not guaranteed to
816 be present in the 150 message.
817 '''
818 if resp[:3] != '150':
819 raise error_reply, resp
820 global _150_re
821 if _150_re is None:
822 import re
823 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
824 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000825 if not m:
826 return None
827 s = m.group(1)
828 try:
829 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000830 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000831 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000832
833
Guido van Rossum70297d32001-08-17 17:24:29 +0000834_227_re = None
835
Guido van Rossumd2560b01996-05-28 23:41:25 +0000836def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000837 '''Parse the '227' response for a PASV request.
838 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
839 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000840
Tim Peters88869f92001-01-14 23:36:06 +0000841 if resp[:3] != '227':
842 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000843 global _227_re
844 if _227_re is None:
845 import re
846 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
847 m = _227_re.search(resp)
848 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000849 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000850 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000851 host = '.'.join(numbers[:4])
852 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000853 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000854
855
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000856def parse229(resp, peer):
Martin Panterb362f752015-11-02 03:37:02 +0000857 '''Parse the '229' response for an EPSV request.
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000858 Raises error_proto if it does not contain '(|||port|)'
859 Return ('host.addr.as.numbers', port#) tuple.'''
860
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000861 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000862 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000863 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000864 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000865 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000866 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000867 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000868 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000869 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000870 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000871 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000872 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000873 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000874 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000875 return host, port
876
877
Guido van Rossumc567c601992-11-05 22:22:37 +0000878def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000879 '''Parse the '257' response for a MKD or PWD request.
880 This is a response to a MKD or PWD request: a directory name.
881 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000882
Tim Peters88869f92001-01-14 23:36:06 +0000883 if resp[:3] != '257':
884 raise error_reply, resp
885 if resp[3:5] != ' "':
886 return '' # Not compliant to RFC 959, but UNIX ftpd does this
887 dirname = ''
888 i = 5
889 n = len(resp)
890 while i < n:
891 c = resp[i]
892 i = i+1
893 if c == '"':
894 if i >= n or resp[i] != '"':
895 break
896 i = i+1
897 dirname = dirname + c
898 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000899
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000900
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000901def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000902 '''Default retrlines callback to print a line.'''
903 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000904
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000905
Guido van Rossumd2560b01996-05-28 23:41:25 +0000906def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000907 '''Copy file from one FTP-instance to another.'''
908 if not targetname: targetname = sourcename
909 type = 'TYPE ' + type
910 source.voidcmd(type)
911 target.voidcmd(type)
912 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
913 target.sendport(sourcehost, sourceport)
914 # RFC 959: the user must "listen" [...] BEFORE sending the
915 # transfer request.
916 # So: STOR before RETR, because here the target is a "user".
917 treply = target.sendcmd('STOR ' + targetname)
918 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
919 sreply = source.sendcmd('RETR ' + sourcename)
920 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
921 source.voidresp()
922 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000923
Tim Peters88869f92001-01-14 23:36:06 +0000924
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000925class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000926 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000927
Tim Peters88869f92001-01-14 23:36:06 +0000928 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000929
Tim Peters88869f92001-01-14 23:36:06 +0000930 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000931
Tim Peters88869f92001-01-14 23:36:06 +0000932 """
933 __defuser = None
934 __defpasswd = None
935 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000936
Tim Peters88869f92001-01-14 23:36:06 +0000937 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000938 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000939 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000940 filename = os.path.join(os.environ["HOME"],
941 ".netrc")
942 else:
943 raise IOError, \
944 "specify file to load or set $HOME"
945 self.__hosts = {}
946 self.__macros = {}
947 fp = open(filename, "r")
948 in_macro = 0
949 while 1:
Serhiy Storchaka2585e1e2013-10-20 16:57:07 +0300950 line = fp.readline(self.maxline + 1)
951 if len(line) > self.maxline:
952 raise Error("got more than %d bytes" % self.maxline)
Tim Peters88869f92001-01-14 23:36:06 +0000953 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000954 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000955 macro_lines.append(line)
956 continue
957 elif in_macro:
958 self.__macros[macro_name] = tuple(macro_lines)
959 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000960 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000961 host = user = passwd = acct = None
962 default = 0
963 i = 0
964 while i < len(words):
965 w1 = words[i]
966 if i+1 < len(words):
967 w2 = words[i + 1]
968 else:
969 w2 = None
970 if w1 == 'default':
971 default = 1
972 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000973 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000974 i = i + 1
975 elif w1 == 'login' and w2:
976 user = w2
977 i = i + 1
978 elif w1 == 'password' and w2:
979 passwd = w2
980 i = i + 1
981 elif w1 == 'account' and w2:
982 acct = w2
983 i = i + 1
984 elif w1 == 'macdef' and w2:
985 macro_name = w2
986 macro_lines = []
987 in_macro = 1
988 break
989 i = i + 1
990 if default:
991 self.__defuser = user or self.__defuser
992 self.__defpasswd = passwd or self.__defpasswd
993 self.__defacct = acct or self.__defacct
994 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000995 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000996 ouser, opasswd, oacct = \
997 self.__hosts[host]
998 user = user or ouser
999 passwd = passwd or opasswd
1000 acct = acct or oacct
1001 self.__hosts[host] = user, passwd, acct
1002 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001003
Tim Peters88869f92001-01-14 23:36:06 +00001004 def get_hosts(self):
1005 """Return a list of hosts mentioned in the .netrc file."""
1006 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001007
Tim Peters88869f92001-01-14 23:36:06 +00001008 def get_account(self, host):
1009 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001010
Tim Peters88869f92001-01-14 23:36:06 +00001011 The return value is a triple containing userid,
1012 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +00001013
Tim Peters88869f92001-01-14 23:36:06 +00001014 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +00001015 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +00001016 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +00001017 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +00001018 user, passwd, acct = self.__hosts[host]
1019 user = user or self.__defuser
1020 passwd = passwd or self.__defpasswd
1021 acct = acct or self.__defacct
1022 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +00001023
Tim Peters88869f92001-01-14 23:36:06 +00001024 def get_macros(self):
1025 """Return a list of all defined macro names."""
1026 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +00001027
Tim Peters88869f92001-01-14 23:36:06 +00001028 def get_macro(self, macro):
1029 """Return a sequence of lines which define a named macro."""
1030 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +00001031
Fred Drake475d51d1997-06-24 22:02:54 +00001032
Tim Peters88869f92001-01-14 23:36:06 +00001033
Guido van Rossum1115ab21992-11-04 15:51:30 +00001034def test():
Tim Peters88869f92001-01-14 23:36:06 +00001035 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +00001036 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
1037
1038 -d dir
1039 -l list
1040 -p password
1041 '''
1042
1043 if len(sys.argv) < 2:
1044 print test.__doc__
1045 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +00001046
Tim Peters88869f92001-01-14 23:36:06 +00001047 debugging = 0
1048 rcfile = None
1049 while sys.argv[1] == '-d':
1050 debugging = debugging+1
1051 del sys.argv[1]
1052 if sys.argv[1][:2] == '-r':
1053 # get name of alternate ~/.netrc file:
1054 rcfile = sys.argv[1][2:]
1055 del sys.argv[1]
1056 host = sys.argv[1]
1057 ftp = FTP(host)
1058 ftp.set_debuglevel(debugging)
1059 userid = passwd = acct = ''
1060 try:
1061 netrc = Netrc(rcfile)
1062 except IOError:
1063 if rcfile is not None:
1064 sys.stderr.write("Could not open account file"
1065 " -- using anonymous login.")
1066 else:
1067 try:
1068 userid, passwd, acct = netrc.get_account(host)
1069 except KeyError:
1070 # no account for host
1071 sys.stderr.write(
1072 "No account -- using anonymous login.")
1073 ftp.login(userid, passwd, acct)
1074 for file in sys.argv[2:]:
1075 if file[:2] == '-l':
1076 ftp.dir(file[2:])
1077 elif file[:2] == '-d':
1078 cmd = 'CWD'
1079 if file[2:]: cmd = cmd + ' ' + file[2:]
1080 resp = ftp.sendcmd(cmd)
1081 elif file == '-p':
1082 ftp.set_pasv(not ftp.passiveserver)
1083 else:
1084 ftp.retrbinary('RETR ' + file, \
1085 sys.stdout.write, 1024)
1086 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001087
1088
1089if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001090 test()