blob: c8964330bfcfb9262c568513f5655488be6a1269 [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
Guido van Rossum1115ab21992-11-04 15:51:30 +000058
59
Guido van Rossum21974791992-11-06 13:34:17 +000060# Exception raised when an error or invalid response is received
Fred Drake227b1202000-08-17 05:06:49 +000061class Error(Exception): pass
Tim Peters88869f92001-01-14 23:36:06 +000062class error_reply(Error): pass # unexpected [123]xx reply
63class error_temp(Error): pass # 4xx errors
64class error_perm(Error): pass # 5xx errors
65class error_proto(Error): pass # response does not begin with [1-5]
Guido van Rossum1115ab21992-11-04 15:51:30 +000066
67
Guido van Rossum21974791992-11-06 13:34:17 +000068# All exceptions (hopefully) that may be raised here and that aren't
69# (always) programming errors on our side
Gregory P. Smithe6c03032008-04-12 22:24:04 +000070all_errors = (Error, IOError, EOFError)
Guido van Rossum21974791992-11-06 13:34:17 +000071
72
Guido van Rossum1115ab21992-11-04 15:51:30 +000073# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
74CRLF = '\r\n'
75
Guido van Rossum1115ab21992-11-04 15:51:30 +000076# The class itself
77class FTP:
78
Tim Peters88869f92001-01-14 23:36:06 +000079 '''An FTP client class.
Guido van Rossumd2560b01996-05-28 23:41:25 +000080
Facundo Batista3f100992007-03-26 20:56:09 +000081 To create a connection, call the class using these arguments:
82 host, user, passwd, acct, timeout
83
84 The first four arguments are all strings, and have default value ''.
85 timeout must be numeric and defaults to None if not passed,
86 meaning that no timeout will be set on any ftp socket(s)
87 If a timeout is passed, then this is now the default timeout for all ftp
88 socket operations for this instance.
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000089
Tim Peters88869f92001-01-14 23:36:06 +000090 Then use self.connect() with optional host and port argument.
Guido van Rossumd2560b01996-05-28 23:41:25 +000091
Tim Peters88869f92001-01-14 23:36:06 +000092 To download a file, use ftp.retrlines('RETR ' + filename),
93 or ftp.retrbinary() with slightly different arguments.
94 To upload a file, use ftp.storlines() or ftp.storbinary(),
95 which have an open file as argument (see their definitions
96 below for details).
97 The download/upload functions first issue appropriate TYPE
98 and PORT or PASV commands.
Guido van Rossumd2560b01996-05-28 23:41:25 +000099'''
100
Fred Drake9c98a422001-02-28 21:46:37 +0000101 debugging = 0
102 host = ''
103 port = FTP_PORT
104 sock = None
105 file = None
106 welcome = None
107 passiveserver = 1
108
Tim Peters88869f92001-01-14 23:36:06 +0000109 # Initialization method (called by class instantiation).
110 # Initialize host to localhost, port to standard ftp port
111 # Optional arguments are host (for connect()),
112 # and user, passwd, acct (for login())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000113 def __init__(self, host='', user='', passwd='', acct='',
114 timeout=_GLOBAL_DEFAULT_TIMEOUT):
Facundo Batista3f100992007-03-26 20:56:09 +0000115 self.timeout = timeout
Tim Peters88869f92001-01-14 23:36:06 +0000116 if host:
Fred Drake9c98a422001-02-28 21:46:37 +0000117 self.connect(host)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000118 if user:
Facundo Batista3f100992007-03-26 20:56:09 +0000119 self.login(user, passwd, acct)
Guido van Rossum52fc1f61993-06-17 12:38:10 +0000120
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000121 def connect(self, host='', port=0, timeout=-999):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000122 '''Connect to host. Arguments are:
Facundo Batista3f100992007-03-26 20:56:09 +0000123 - host: hostname to connect to (string, default previous host)
124 - port: port to connect to (integer, default previous port)
125 '''
126 if host != '':
127 self.host = host
128 if port > 0:
129 self.port = port
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000130 if timeout != -999:
Facundo Batista93c33682007-03-30 13:00:35 +0000131 self.timeout = timeout
Facundo Batista3f100992007-03-26 20:56:09 +0000132 self.sock = socket.create_connection((self.host, self.port), self.timeout)
133 self.af = self.sock.family
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000134 self.file = self.sock.makefile('rb')
135 self.welcome = self.getresp()
136 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000137
Tim Peters88869f92001-01-14 23:36:06 +0000138 def getwelcome(self):
139 '''Get the welcome message from the server.
140 (this is read and squirreled away by connect())'''
141 if self.debugging:
142 print '*welcome*', self.sanitize(self.welcome)
143 return self.welcome
Guido van Rossum1115ab21992-11-04 15:51:30 +0000144
Tim Peters88869f92001-01-14 23:36:06 +0000145 def set_debuglevel(self, level):
146 '''Set the debugging level.
147 The required argument level means:
148 0: no debugging output (default)
149 1: print commands and responses but not body text etc.
150 2: also print raw lines read and sent before stripping CR/LF'''
151 self.debugging = level
152 debug = set_debuglevel
Guido van Rossum1115ab21992-11-04 15:51:30 +0000153
Tim Peters88869f92001-01-14 23:36:06 +0000154 def set_pasv(self, val):
155 '''Use passive or active mode for data transfers.
156 With a false argument, use the normal PORT mode,
157 With a true argument, use the PASV command.'''
158 self.passiveserver = val
Guido van Rossumd2560b01996-05-28 23:41:25 +0000159
Tim Peters88869f92001-01-14 23:36:06 +0000160 # Internal: "sanitize" a string for printing
161 def sanitize(self, s):
162 if s[:5] == 'pass ' or s[:5] == 'PASS ':
163 i = len(s)
164 while i > 5 and s[i-1] in '\r\n':
165 i = i-1
166 s = s[:5] + '*'*(i-5) + s[i:]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000167 return repr(s)
Guido van Rossumebaf1041995-05-05 15:54:14 +0000168
Tim Peters88869f92001-01-14 23:36:06 +0000169 # Internal: send one line to the server, appending CRLF
170 def putline(self, line):
171 line = line + CRLF
172 if self.debugging > 1: print '*put*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000173 self.sock.sendall(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000174
Tim Peters88869f92001-01-14 23:36:06 +0000175 # Internal: send one command to the server (through putline())
176 def putcmd(self, line):
177 if self.debugging: print '*cmd*', self.sanitize(line)
178 self.putline(line)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000179
Tim Peters88869f92001-01-14 23:36:06 +0000180 # Internal: return one line from the server, stripping CRLF.
181 # Raise EOFError if the connection is closed
182 def getline(self):
183 line = self.file.readline()
184 if self.debugging > 1:
185 print '*get*', self.sanitize(line)
186 if not line: raise EOFError
187 if line[-2:] == CRLF: line = line[:-2]
188 elif line[-1:] in CRLF: line = line[:-1]
189 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000190
Tim Peters88869f92001-01-14 23:36:06 +0000191 # Internal: get a response from the server, which may possibly
192 # consist of multiple lines. Return a single string with no
193 # trailing CRLF. If the response consists of multiple lines,
194 # these are separated by '\n' characters in the string
195 def getmultiline(self):
196 line = self.getline()
197 if line[3:4] == '-':
198 code = line[:3]
199 while 1:
200 nextline = self.getline()
201 line = line + ('\n' + nextline)
202 if nextline[:3] == code and \
203 nextline[3:4] != '-':
204 break
205 return line
Guido van Rossum1115ab21992-11-04 15:51:30 +0000206
Tim Peters88869f92001-01-14 23:36:06 +0000207 # Internal: get a response from the server.
208 # Raise various errors if the response indicates an error
209 def getresp(self):
210 resp = self.getmultiline()
211 if self.debugging: print '*resp*', self.sanitize(resp)
212 self.lastresp = resp[:3]
213 c = resp[:1]
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000214 if c in ('1', '2', '3'):
215 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000216 if c == '4':
217 raise error_temp, resp
218 if c == '5':
219 raise error_perm, resp
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000220 raise error_proto, resp
Guido van Rossum1115ab21992-11-04 15:51:30 +0000221
Tim Peters88869f92001-01-14 23:36:06 +0000222 def voidresp(self):
223 """Expect a response beginning with '2'."""
224 resp = self.getresp()
Georg Brandl50ba6e12009-04-05 10:48:47 +0000225 if resp[:1] != '2':
Tim Peters88869f92001-01-14 23:36:06 +0000226 raise error_reply, resp
227 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000228
Tim Peters88869f92001-01-14 23:36:06 +0000229 def abort(self):
230 '''Abort a file transfer. Uses out-of-band data.
231 This does not follow the procedure from the RFC to send Telnet
232 IP and Synch; that doesn't seem to work with the servers I've
233 tried. Instead, just send the ABOR command as OOB data.'''
234 line = 'ABOR' + CRLF
235 if self.debugging > 1: print '*put urgent*', self.sanitize(line)
Martin v. Löwise12454f2002-02-16 23:06:19 +0000236 self.sock.sendall(line, MSG_OOB)
Tim Peters88869f92001-01-14 23:36:06 +0000237 resp = self.getmultiline()
Giampaolo Rodolàcf445fc2010-04-18 12:55:03 +0000238 if resp[:3] not in ('426', '225', '226'):
Tim Peters88869f92001-01-14 23:36:06 +0000239 raise error_proto, resp
Guido van Rossumd3166071993-05-24 14:16:22 +0000240
Tim Peters88869f92001-01-14 23:36:06 +0000241 def sendcmd(self, cmd):
242 '''Send a command and return the response.'''
243 self.putcmd(cmd)
244 return self.getresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000245
Tim Peters88869f92001-01-14 23:36:06 +0000246 def voidcmd(self, cmd):
247 """Send a command and expect a response beginning with '2'."""
248 self.putcmd(cmd)
249 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000250
Tim Peters88869f92001-01-14 23:36:06 +0000251 def sendport(self, host, port):
252 '''Send a PORT command with the current host and the given
253 port number.
254 '''
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000255 hbytes = host.split('.')
Benjamin Petersondee0b172008-09-27 22:08:12 +0000256 pbytes = [repr(port//256), repr(port%256)]
Tim Peters88869f92001-01-14 23:36:06 +0000257 bytes = hbytes + pbytes
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000258 cmd = 'PORT ' + ','.join(bytes)
Tim Peters88869f92001-01-14 23:36:06 +0000259 return self.voidcmd(cmd)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000260
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000261 def sendeprt(self, host, port):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000262 '''Send a EPRT command with the current host and the given port number.'''
263 af = 0
264 if self.af == socket.AF_INET:
265 af = 1
266 if self.af == socket.AF_INET6:
267 af = 2
268 if af == 0:
269 raise error_proto, 'unsupported address family'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000270 fields = ['', repr(af), host, repr(port), '']
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000271 cmd = 'EPRT ' + '|'.join(fields)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000272 return self.voidcmd(cmd)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000273
Tim Peters88869f92001-01-14 23:36:06 +0000274 def makeport(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000275 '''Create a new socket and send a PORT command for it.'''
Martin v. Löwis2ad25692001-07-31 08:40:21 +0000276 msg = "getaddrinfo returns an empty list"
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000277 sock = None
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000278 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
279 af, socktype, proto, canonname, sa = res
280 try:
281 sock = socket.socket(af, socktype, proto)
282 sock.bind(sa)
283 except socket.error, msg:
Martin v. Löwis322c0d12001-10-07 08:53:32 +0000284 if sock:
285 sock.close()
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000286 sock = None
287 continue
288 break
289 if not sock:
290 raise socket.error, msg
291 sock.listen(1)
292 port = sock.getsockname()[1] # Get proper port
293 host = self.sock.getsockname()[0] # Get proper host
294 if self.af == socket.AF_INET:
295 resp = self.sendport(host, port)
296 else:
297 resp = self.sendeprt(host, port)
Giampaolo Rodolà607f7c02010-04-19 21:46:28 +0000298 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
299 sock.settimeout(self.timeout)
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000300 return sock
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000301
302 def makepasv(self):
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000303 if self.af == socket.AF_INET:
304 host, port = parse227(self.sendcmd('PASV'))
305 else:
306 host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
307 return host, port
Guido van Rossum1115ab21992-11-04 15:51:30 +0000308
Tim Peters88869f92001-01-14 23:36:06 +0000309 def ntransfercmd(self, cmd, rest=None):
310 """Initiate a transfer over the data connection.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000311
Tim Peters88869f92001-01-14 23:36:06 +0000312 If the transfer is active, send a port command and the
313 transfer command, and accept the connection. If the server is
314 passive, send a pasv command, connect to it, and start the
315 transfer command. Either way, return the socket for the
316 connection and the expected size of the transfer. The
317 expected size may be None if it could not be determined.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000318
Tim Peters88869f92001-01-14 23:36:06 +0000319 Optional `rest' argument can be a string that is sent as the
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000320 argument to a REST command. This is essentially a server
Tim Peters88869f92001-01-14 23:36:06 +0000321 marker used to tell the server to skip over any data up to the
322 given marker.
323 """
324 size = None
325 if self.passiveserver:
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000326 host, port = self.makepasv()
Facundo Batista92493122007-06-06 15:13:37 +0000327 conn = socket.create_connection((host, port), self.timeout)
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200328 try:
329 if rest is not None:
330 self.sendcmd("REST %s" % rest)
331 resp = self.sendcmd(cmd)
332 # Some servers apparently send a 200 reply to
333 # a LIST or STOR command, before the 150 reply
334 # (and way before the 226 reply). This seems to
335 # be in violation of the protocol (which only allows
336 # 1xx or error messages for LIST), so we just discard
337 # this response.
338 if resp[0] == '2':
339 resp = self.getresp()
340 if resp[0] != '1':
341 raise error_reply, resp
342 except:
343 conn.close()
344 raise
Tim Peters88869f92001-01-14 23:36:06 +0000345 else:
346 sock = self.makeport()
Nadeem Vawdab42c53e2011-07-23 15:51:16 +0200347 try:
348 if rest is not None:
349 self.sendcmd("REST %s" % rest)
350 resp = self.sendcmd(cmd)
351 # See above.
352 if resp[0] == '2':
353 resp = self.getresp()
354 if resp[0] != '1':
355 raise error_reply, resp
356 conn, sockaddr = sock.accept()
357 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
358 conn.settimeout(self.timeout)
359 finally:
360 sock.close()
Tim Peters88869f92001-01-14 23:36:06 +0000361 if resp[:3] == '150':
362 # this is conditional in case we received a 125
363 size = parse150(resp)
364 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000365
Tim Peters88869f92001-01-14 23:36:06 +0000366 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000367 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000368 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000369
Tim Peters88869f92001-01-14 23:36:06 +0000370 def login(self, user = '', passwd = '', acct = ''):
371 '''Login, default anonymous.'''
372 if not user: user = 'anonymous'
373 if not passwd: passwd = ''
374 if not acct: acct = ''
375 if user == 'anonymous' and passwd in ('', '-'):
Tim Peterse4418602002-02-16 07:34:19 +0000376 # If there is no anonymous ftp password specified
377 # then we'll just use anonymous@
378 # We don't send any other thing because:
379 # - We want to remain anonymous
380 # - We want to stop SPAM
381 # - We don't want to let ftp sites to discriminate by the user,
382 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000383 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000384 resp = self.sendcmd('USER ' + user)
385 if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
386 if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
387 if resp[0] != '2':
388 raise error_reply, resp
389 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000390
Tim Peters88869f92001-01-14 23:36:06 +0000391 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000392 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000393
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000394 Args:
395 cmd: A RETR command.
396 callback: A single parameter callable to be called on each
397 block of data read.
398 blocksize: The maximum number of bytes to read from the
399 socket at one time. [default: 8192]
400 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000401
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000402 Returns:
403 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000404 """
405 self.voidcmd('TYPE I')
406 conn = self.transfercmd(cmd, rest)
407 while 1:
408 data = conn.recv(blocksize)
409 if not data:
410 break
411 callback(data)
412 conn.close()
413 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000414
Tim Peters88869f92001-01-14 23:36:06 +0000415 def retrlines(self, cmd, callback = None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000416 """Retrieve data in line mode. A new port is created for you.
417
418 Args:
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000419 cmd: A RETR, LIST, NLST, or MLSD command.
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000420 callback: An optional single parameter callable that is called
421 for each line with the trailing CRLF stripped.
422 [default: print_line()]
423
424 Returns:
425 The response code.
426 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000427 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000428 resp = self.sendcmd('TYPE A')
429 conn = self.transfercmd(cmd)
430 fp = conn.makefile('rb')
431 while 1:
432 line = fp.readline()
Walter Dörwald70a6b492004-02-12 17:35:32 +0000433 if self.debugging > 2: print '*retr*', repr(line)
Tim Peters88869f92001-01-14 23:36:06 +0000434 if not line:
435 break
436 if line[-2:] == CRLF:
437 line = line[:-2]
438 elif line[-1:] == '\n':
439 line = line[:-1]
440 callback(line)
441 fp.close()
442 conn.close()
443 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000444
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000445 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000446 """Store a file in binary mode. A new port is created for you.
447
448 Args:
449 cmd: A STOR command.
450 fp: A file-like object with a read(num_bytes) method.
451 blocksize: The maximum data size to read from fp and send over
452 the connection at once. [default: 8192]
453 callback: An optional single parameter callable that is called on
454 on each block of data after it is sent. [default: None]
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000455 rest: Passed to transfercmd(). [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000456
457 Returns:
458 The response code.
459 """
Tim Peters88869f92001-01-14 23:36:06 +0000460 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000461 conn = self.transfercmd(cmd, rest)
Tim Peters88869f92001-01-14 23:36:06 +0000462 while 1:
463 buf = fp.read(blocksize)
464 if not buf: break
Martin v. Löwise12454f2002-02-16 23:06:19 +0000465 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000466 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000467 conn.close()
468 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000469
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000470 def storlines(self, cmd, fp, callback=None):
471 """Store a file in line mode. A new port is created for you.
472
473 Args:
474 cmd: A STOR command.
475 fp: A file-like object with a readline() method.
476 callback: An optional single parameter callable that is called on
477 on each line after it is sent. [default: None]
478
479 Returns:
480 The response code.
481 """
Tim Peters88869f92001-01-14 23:36:06 +0000482 self.voidcmd('TYPE A')
483 conn = self.transfercmd(cmd)
484 while 1:
485 buf = fp.readline()
486 if not buf: break
487 if buf[-2:] != CRLF:
488 if buf[-1] in CRLF: buf = buf[:-1]
489 buf = buf + CRLF
Martin v. Löwise12454f2002-02-16 23:06:19 +0000490 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000491 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000492 conn.close()
493 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000494
Tim Peters88869f92001-01-14 23:36:06 +0000495 def acct(self, password):
496 '''Send new account name.'''
497 cmd = 'ACCT ' + password
498 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000499
Tim Peters88869f92001-01-14 23:36:06 +0000500 def nlst(self, *args):
501 '''Return a list of files in a given directory (default the current).'''
502 cmd = 'NLST'
503 for arg in args:
504 cmd = cmd + (' ' + arg)
505 files = []
506 self.retrlines(cmd, files.append)
507 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000508
Tim Peters88869f92001-01-14 23:36:06 +0000509 def dir(self, *args):
510 '''List a directory in long form.
511 By default list current directory to stdout.
512 Optional last argument is callback function; all
513 non-empty arguments before it are concatenated to the
514 LIST command. (This *should* only be used for a pathname.)'''
515 cmd = 'LIST'
516 func = None
517 if args[-1:] and type(args[-1]) != type(''):
518 args, func = args[:-1], args[-1]
519 for arg in args:
520 if arg:
521 cmd = cmd + (' ' + arg)
522 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000523
Tim Peters88869f92001-01-14 23:36:06 +0000524 def rename(self, fromname, toname):
525 '''Rename a file.'''
526 resp = self.sendcmd('RNFR ' + fromname)
527 if resp[0] != '3':
528 raise error_reply, resp
529 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000530
Tim Peters88869f92001-01-14 23:36:06 +0000531 def delete(self, filename):
532 '''Delete a file.'''
533 resp = self.sendcmd('DELE ' + filename)
534 if resp[:3] in ('250', '200'):
535 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000536 else:
537 raise error_reply, resp
Guido van Rossum02cf5821993-05-17 08:00:02 +0000538
Tim Peters88869f92001-01-14 23:36:06 +0000539 def cwd(self, dirname):
540 '''Change to a directory.'''
541 if dirname == '..':
542 try:
543 return self.voidcmd('CDUP')
544 except error_perm, msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000545 if msg.args[0][:3] != '500':
546 raise
Tim Peters88869f92001-01-14 23:36:06 +0000547 elif dirname == '':
548 dirname = '.' # does nothing, but could return error
549 cmd = 'CWD ' + dirname
550 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000551
Tim Peters88869f92001-01-14 23:36:06 +0000552 def size(self, filename):
553 '''Retrieve the size of a file.'''
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000554 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000555 resp = self.sendcmd('SIZE ' + filename)
556 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000557 s = resp[3:].strip()
558 try:
559 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000560 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000561 return long(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000562
Tim Peters88869f92001-01-14 23:36:06 +0000563 def mkd(self, dirname):
564 '''Make a directory, return its full pathname.'''
565 resp = self.sendcmd('MKD ' + dirname)
566 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000567
Tim Peters88869f92001-01-14 23:36:06 +0000568 def rmd(self, dirname):
569 '''Remove a directory.'''
570 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000571
Tim Peters88869f92001-01-14 23:36:06 +0000572 def pwd(self):
573 '''Return current working directory.'''
574 resp = self.sendcmd('PWD')
575 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000576
Tim Peters88869f92001-01-14 23:36:06 +0000577 def quit(self):
578 '''Quit, and close the connection.'''
579 resp = self.voidcmd('QUIT')
580 self.close()
581 return resp
582
583 def close(self):
584 '''Close the connection without assuming anything about it.'''
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700585 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000586 self.file.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700587 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000588 self.sock.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700589 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000590
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000591try:
592 import ssl
593except ImportError:
594 pass
595else:
596 class FTP_TLS(FTP):
597 '''A FTP subclass which adds TLS support to FTP as described
598 in RFC-4217.
599
600 Connect as usual to port 21 implicitly securing the FTP control
601 connection before authenticating.
602
603 Securing the data connection requires user to explicitly ask
604 for it by calling prot_p() method.
605
606 Usage example:
607 >>> from ftplib import FTP_TLS
608 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200609 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000610 '230 Guest login ok, access restrictions apply.'
611 >>> ftps.prot_p() # switch to secure data connection
612 '200 Protection level set to P'
613 >>> ftps.retrlines('LIST') # list directory content securely
614 total 9
615 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
616 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
617 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
618 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
619 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
620 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
621 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
622 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
623 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
624 '226 Transfer complete.'
625 >>> ftps.quit()
626 '221 Goodbye.'
627 >>>
628 '''
629 ssl_version = ssl.PROTOCOL_TLSv1
630
631 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
632 certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
633 self.keyfile = keyfile
634 self.certfile = certfile
635 self._prot_p = False
636 FTP.__init__(self, host, user, passwd, acct, timeout)
637
638 def login(self, user='', passwd='', acct='', secure=True):
639 if secure and not isinstance(self.sock, ssl.SSLSocket):
640 self.auth()
641 return FTP.login(self, user, passwd, acct)
642
643 def auth(self):
644 '''Set up secure control connection by using TLS/SSL.'''
645 if isinstance(self.sock, ssl.SSLSocket):
646 raise ValueError("Already using TLS")
647 if self.ssl_version == ssl.PROTOCOL_TLSv1:
648 resp = self.voidcmd('AUTH TLS')
649 else:
650 resp = self.voidcmd('AUTH SSL')
651 self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
652 ssl_version=self.ssl_version)
653 self.file = self.sock.makefile(mode='rb')
654 return resp
655
656 def prot_p(self):
657 '''Set up secure data connection.'''
658 # PROT defines whether or not the data channel is to be protected.
659 # Though RFC-2228 defines four possible protection levels,
660 # RFC-4217 only recommends two, Clear and Private.
661 # Clear (PROT C) means that no security is to be used on the
662 # data-channel, Private (PROT P) means that the data-channel
663 # should be protected by TLS.
664 # PBSZ command MUST still be issued, but must have a parameter of
665 # '0' to indicate that no buffering is taking place and the data
666 # connection should not be encapsulated.
667 self.voidcmd('PBSZ 0')
668 resp = self.voidcmd('PROT P')
669 self._prot_p = True
670 return resp
671
672 def prot_c(self):
673 '''Set up clear text data connection.'''
674 resp = self.voidcmd('PROT C')
675 self._prot_p = False
676 return resp
677
678 # --- Overridden FTP methods
679
680 def ntransfercmd(self, cmd, rest=None):
681 conn, size = FTP.ntransfercmd(self, cmd, rest)
682 if self._prot_p:
683 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
684 ssl_version=self.ssl_version)
685 return conn, size
686
687 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
688 self.voidcmd('TYPE I')
689 conn = self.transfercmd(cmd, rest)
690 try:
691 while 1:
692 data = conn.recv(blocksize)
693 if not data:
694 break
695 callback(data)
696 # shutdown ssl layer
697 if isinstance(conn, ssl.SSLSocket):
698 conn.unwrap()
699 finally:
700 conn.close()
701 return self.voidresp()
702
703 def retrlines(self, cmd, callback = None):
704 if callback is None: callback = print_line
705 resp = self.sendcmd('TYPE A')
706 conn = self.transfercmd(cmd)
707 fp = conn.makefile('rb')
708 try:
709 while 1:
710 line = fp.readline()
711 if self.debugging > 2: print '*retr*', repr(line)
712 if not line:
713 break
714 if line[-2:] == CRLF:
715 line = line[:-2]
716 elif line[-1:] == '\n':
717 line = line[:-1]
718 callback(line)
719 # shutdown ssl layer
720 if isinstance(conn, ssl.SSLSocket):
721 conn.unwrap()
722 finally:
723 fp.close()
724 conn.close()
725 return self.voidresp()
726
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000727 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000728 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000729 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000730 try:
731 while 1:
732 buf = fp.read(blocksize)
733 if not buf: break
734 conn.sendall(buf)
735 if callback: callback(buf)
736 # shutdown ssl layer
737 if isinstance(conn, ssl.SSLSocket):
738 conn.unwrap()
739 finally:
740 conn.close()
741 return self.voidresp()
742
743 def storlines(self, cmd, fp, callback=None):
744 self.voidcmd('TYPE A')
745 conn = self.transfercmd(cmd)
746 try:
747 while 1:
748 buf = fp.readline()
749 if not buf: break
750 if buf[-2:] != CRLF:
751 if buf[-1] in CRLF: buf = buf[:-1]
752 buf = buf + CRLF
753 conn.sendall(buf)
754 if callback: callback(buf)
755 # shutdown ssl layer
756 if isinstance(conn, ssl.SSLSocket):
757 conn.unwrap()
758 finally:
759 conn.close()
760 return self.voidresp()
761
762 __all__.append('FTP_TLS')
763 all_errors = (Error, IOError, EOFError, ssl.SSLError)
764
765
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000766_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000767
768def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000769 '''Parse the '150' response for a RETR request.
770 Returns the expected transfer size or None; size is not guaranteed to
771 be present in the 150 message.
772 '''
773 if resp[:3] != '150':
774 raise error_reply, resp
775 global _150_re
776 if _150_re is None:
777 import re
778 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
779 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000780 if not m:
781 return None
782 s = m.group(1)
783 try:
784 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000785 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000786 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000787
788
Guido van Rossum70297d32001-08-17 17:24:29 +0000789_227_re = None
790
Guido van Rossumd2560b01996-05-28 23:41:25 +0000791def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000792 '''Parse the '227' response for a PASV request.
793 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
794 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000795
Tim Peters88869f92001-01-14 23:36:06 +0000796 if resp[:3] != '227':
797 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000798 global _227_re
799 if _227_re is None:
800 import re
801 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
802 m = _227_re.search(resp)
803 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000804 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000805 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000806 host = '.'.join(numbers[:4])
807 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000808 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000809
810
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000811def parse229(resp, peer):
812 '''Parse the '229' response for a EPSV request.
813 Raises error_proto if it does not contain '(|||port|)'
814 Return ('host.addr.as.numbers', port#) tuple.'''
815
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000816 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000817 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000818 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000819 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000820 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000821 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000822 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000823 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000824 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000825 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000826 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000827 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000828 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000829 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000830 return host, port
831
832
Guido van Rossumc567c601992-11-05 22:22:37 +0000833def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000834 '''Parse the '257' response for a MKD or PWD request.
835 This is a response to a MKD or PWD request: a directory name.
836 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000837
Tim Peters88869f92001-01-14 23:36:06 +0000838 if resp[:3] != '257':
839 raise error_reply, resp
840 if resp[3:5] != ' "':
841 return '' # Not compliant to RFC 959, but UNIX ftpd does this
842 dirname = ''
843 i = 5
844 n = len(resp)
845 while i < n:
846 c = resp[i]
847 i = i+1
848 if c == '"':
849 if i >= n or resp[i] != '"':
850 break
851 i = i+1
852 dirname = dirname + c
853 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000854
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000855
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000856def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000857 '''Default retrlines callback to print a line.'''
858 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000859
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000860
Guido van Rossumd2560b01996-05-28 23:41:25 +0000861def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000862 '''Copy file from one FTP-instance to another.'''
863 if not targetname: targetname = sourcename
864 type = 'TYPE ' + type
865 source.voidcmd(type)
866 target.voidcmd(type)
867 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
868 target.sendport(sourcehost, sourceport)
869 # RFC 959: the user must "listen" [...] BEFORE sending the
870 # transfer request.
871 # So: STOR before RETR, because here the target is a "user".
872 treply = target.sendcmd('STOR ' + targetname)
873 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
874 sreply = source.sendcmd('RETR ' + sourcename)
875 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
876 source.voidresp()
877 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000878
Tim Peters88869f92001-01-14 23:36:06 +0000879
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000880class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000881 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000882
Tim Peters88869f92001-01-14 23:36:06 +0000883 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000884
Tim Peters88869f92001-01-14 23:36:06 +0000885 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000886
Tim Peters88869f92001-01-14 23:36:06 +0000887 """
888 __defuser = None
889 __defpasswd = None
890 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000891
Tim Peters88869f92001-01-14 23:36:06 +0000892 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000893 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000894 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000895 filename = os.path.join(os.environ["HOME"],
896 ".netrc")
897 else:
898 raise IOError, \
899 "specify file to load or set $HOME"
900 self.__hosts = {}
901 self.__macros = {}
902 fp = open(filename, "r")
903 in_macro = 0
904 while 1:
905 line = fp.readline()
906 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000907 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000908 macro_lines.append(line)
909 continue
910 elif in_macro:
911 self.__macros[macro_name] = tuple(macro_lines)
912 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000913 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000914 host = user = passwd = acct = None
915 default = 0
916 i = 0
917 while i < len(words):
918 w1 = words[i]
919 if i+1 < len(words):
920 w2 = words[i + 1]
921 else:
922 w2 = None
923 if w1 == 'default':
924 default = 1
925 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000926 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000927 i = i + 1
928 elif w1 == 'login' and w2:
929 user = w2
930 i = i + 1
931 elif w1 == 'password' and w2:
932 passwd = w2
933 i = i + 1
934 elif w1 == 'account' and w2:
935 acct = w2
936 i = i + 1
937 elif w1 == 'macdef' and w2:
938 macro_name = w2
939 macro_lines = []
940 in_macro = 1
941 break
942 i = i + 1
943 if default:
944 self.__defuser = user or self.__defuser
945 self.__defpasswd = passwd or self.__defpasswd
946 self.__defacct = acct or self.__defacct
947 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000948 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000949 ouser, opasswd, oacct = \
950 self.__hosts[host]
951 user = user or ouser
952 passwd = passwd or opasswd
953 acct = acct or oacct
954 self.__hosts[host] = user, passwd, acct
955 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000956
Tim Peters88869f92001-01-14 23:36:06 +0000957 def get_hosts(self):
958 """Return a list of hosts mentioned in the .netrc file."""
959 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000960
Tim Peters88869f92001-01-14 23:36:06 +0000961 def get_account(self, host):
962 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000963
Tim Peters88869f92001-01-14 23:36:06 +0000964 The return value is a triple containing userid,
965 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000966
Tim Peters88869f92001-01-14 23:36:06 +0000967 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000968 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000969 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000970 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000971 user, passwd, acct = self.__hosts[host]
972 user = user or self.__defuser
973 passwd = passwd or self.__defpasswd
974 acct = acct or self.__defacct
975 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +0000976
Tim Peters88869f92001-01-14 23:36:06 +0000977 def get_macros(self):
978 """Return a list of all defined macro names."""
979 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000980
Tim Peters88869f92001-01-14 23:36:06 +0000981 def get_macro(self, macro):
982 """Return a sequence of lines which define a named macro."""
983 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000984
Fred Drake475d51d1997-06-24 22:02:54 +0000985
Tim Peters88869f92001-01-14 23:36:06 +0000986
Guido van Rossum1115ab21992-11-04 15:51:30 +0000987def test():
Tim Peters88869f92001-01-14 23:36:06 +0000988 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000989 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
990
991 -d dir
992 -l list
993 -p password
994 '''
995
996 if len(sys.argv) < 2:
997 print test.__doc__
998 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +0000999
Tim Peters88869f92001-01-14 23:36:06 +00001000 debugging = 0
1001 rcfile = None
1002 while sys.argv[1] == '-d':
1003 debugging = debugging+1
1004 del sys.argv[1]
1005 if sys.argv[1][:2] == '-r':
1006 # get name of alternate ~/.netrc file:
1007 rcfile = sys.argv[1][2:]
1008 del sys.argv[1]
1009 host = sys.argv[1]
1010 ftp = FTP(host)
1011 ftp.set_debuglevel(debugging)
1012 userid = passwd = acct = ''
1013 try:
1014 netrc = Netrc(rcfile)
1015 except IOError:
1016 if rcfile is not None:
1017 sys.stderr.write("Could not open account file"
1018 " -- using anonymous login.")
1019 else:
1020 try:
1021 userid, passwd, acct = netrc.get_account(host)
1022 except KeyError:
1023 # no account for host
1024 sys.stderr.write(
1025 "No account -- using anonymous login.")
1026 ftp.login(userid, passwd, acct)
1027 for file in sys.argv[2:]:
1028 if file[:2] == '-l':
1029 ftp.dir(file[2:])
1030 elif file[:2] == '-d':
1031 cmd = 'CWD'
1032 if file[2:]: cmd = cmd + ' ' + file[2:]
1033 resp = ftp.sendcmd(cmd)
1034 elif file == '-p':
1035 ftp.set_pasv(not ftp.passiveserver)
1036 else:
1037 ftp.retrbinary('RETR ' + file, \
1038 sys.stdout.write, 1024)
1039 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001040
1041
1042if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001043 test()