blob: 8713e473a1642476cae55b4fb0a46d70eeb9b522 [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)
Tim Peters88869f92001-01-14 23:36:06 +0000328 if rest is not None:
329 self.sendcmd("REST %s" % rest)
330 resp = self.sendcmd(cmd)
Martin v. Löwis36cbc082006-11-12 18:48:13 +0000331 # Some servers apparently send a 200 reply to
332 # a LIST or STOR command, before the 150 reply
333 # (and way before the 226 reply). This seems to
334 # be in violation of the protocol (which only allows
335 # 1xx or error messages for LIST), so we just discard
336 # this response.
337 if resp[0] == '2':
Tim Petersf733abb2007-01-30 03:03:46 +0000338 resp = self.getresp()
Tim Peters88869f92001-01-14 23:36:06 +0000339 if resp[0] != '1':
340 raise error_reply, resp
341 else:
342 sock = self.makeport()
343 if rest is not None:
344 self.sendcmd("REST %s" % rest)
345 resp = self.sendcmd(cmd)
Martin v. Löwis36cbc082006-11-12 18:48:13 +0000346 # See above.
347 if resp[0] == '2':
Tim Petersf733abb2007-01-30 03:03:46 +0000348 resp = self.getresp()
Tim Peters88869f92001-01-14 23:36:06 +0000349 if resp[0] != '1':
350 raise error_reply, resp
351 conn, sockaddr = sock.accept()
Giampaolo Rodolà607f7c02010-04-19 21:46:28 +0000352 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
353 conn.settimeout(self.timeout)
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700354 sock.close()
Tim Peters88869f92001-01-14 23:36:06 +0000355 if resp[:3] == '150':
356 # this is conditional in case we received a 125
357 size = parse150(resp)
358 return conn, size
Fred Drake4de02d91997-01-10 18:26:09 +0000359
Tim Peters88869f92001-01-14 23:36:06 +0000360 def transfercmd(self, cmd, rest=None):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000361 """Like ntransfercmd() but returns only the socket."""
Tim Peters88869f92001-01-14 23:36:06 +0000362 return self.ntransfercmd(cmd, rest)[0]
Guido van Rossumc567c601992-11-05 22:22:37 +0000363
Tim Peters88869f92001-01-14 23:36:06 +0000364 def login(self, user = '', passwd = '', acct = ''):
365 '''Login, default anonymous.'''
366 if not user: user = 'anonymous'
367 if not passwd: passwd = ''
368 if not acct: acct = ''
369 if user == 'anonymous' and passwd in ('', '-'):
Tim Peterse4418602002-02-16 07:34:19 +0000370 # If there is no anonymous ftp password specified
371 # then we'll just use anonymous@
372 # We don't send any other thing because:
373 # - We want to remain anonymous
374 # - We want to stop SPAM
375 # - We don't want to let ftp sites to discriminate by the user,
376 # host or country.
Guido van Rossumc33e0772001-12-28 20:54:28 +0000377 passwd = passwd + 'anonymous@'
Tim Peters88869f92001-01-14 23:36:06 +0000378 resp = self.sendcmd('USER ' + user)
379 if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd)
380 if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct)
381 if resp[0] != '2':
382 raise error_reply, resp
383 return resp
Guido van Rossumc567c601992-11-05 22:22:37 +0000384
Tim Peters88869f92001-01-14 23:36:06 +0000385 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000386 """Retrieve data in binary mode. A new port is created for you.
Barry Warsaw100d81e2000-09-01 06:09:23 +0000387
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000388 Args:
389 cmd: A RETR command.
390 callback: A single parameter callable to be called on each
391 block of data read.
392 blocksize: The maximum number of bytes to read from the
393 socket at one time. [default: 8192]
394 rest: Passed to transfercmd(). [default: None]
Guido van Rossum1115ab21992-11-04 15:51:30 +0000395
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000396 Returns:
397 The response code.
Tim Peters88869f92001-01-14 23:36:06 +0000398 """
399 self.voidcmd('TYPE I')
400 conn = self.transfercmd(cmd, rest)
401 while 1:
402 data = conn.recv(blocksize)
403 if not data:
404 break
405 callback(data)
406 conn.close()
407 return self.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000408
Tim Peters88869f92001-01-14 23:36:06 +0000409 def retrlines(self, cmd, callback = None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000410 """Retrieve data in line mode. A new port is created for you.
411
412 Args:
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000413 cmd: A RETR, LIST, NLST, or MLSD command.
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000414 callback: An optional single parameter callable that is called
415 for each line with the trailing CRLF stripped.
416 [default: print_line()]
417
418 Returns:
419 The response code.
420 """
Raymond Hettingere874fc32002-05-12 05:53:51 +0000421 if callback is None: callback = print_line
Tim Peters88869f92001-01-14 23:36:06 +0000422 resp = self.sendcmd('TYPE A')
423 conn = self.transfercmd(cmd)
424 fp = conn.makefile('rb')
425 while 1:
426 line = fp.readline()
Walter Dörwald70a6b492004-02-12 17:35:32 +0000427 if self.debugging > 2: print '*retr*', repr(line)
Tim Peters88869f92001-01-14 23:36:06 +0000428 if not line:
429 break
430 if line[-2:] == CRLF:
431 line = line[:-2]
432 elif line[-1:] == '\n':
433 line = line[:-1]
434 callback(line)
435 fp.close()
436 conn.close()
437 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000438
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000439 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000440 """Store a file in binary mode. A new port is created for you.
441
442 Args:
443 cmd: A STOR command.
444 fp: A file-like object with a read(num_bytes) method.
445 blocksize: The maximum data size to read from fp and send over
446 the connection at once. [default: 8192]
447 callback: An optional single parameter callable that is called on
448 on each block of data after it is sent. [default: None]
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000449 rest: Passed to transfercmd(). [default: None]
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000450
451 Returns:
452 The response code.
453 """
Tim Peters88869f92001-01-14 23:36:06 +0000454 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000455 conn = self.transfercmd(cmd, rest)
Tim Peters88869f92001-01-14 23:36:06 +0000456 while 1:
457 buf = fp.read(blocksize)
458 if not buf: break
Martin v. Löwise12454f2002-02-16 23:06:19 +0000459 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000460 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000461 conn.close()
462 return self.voidresp()
Guido van Rossumc567c601992-11-05 22:22:37 +0000463
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000464 def storlines(self, cmd, fp, callback=None):
465 """Store a file in line mode. A new port is created for you.
466
467 Args:
468 cmd: A STOR command.
469 fp: A file-like object with a readline() method.
470 callback: An optional single parameter callable that is called on
471 on each line after it is sent. [default: None]
472
473 Returns:
474 The response code.
475 """
Tim Peters88869f92001-01-14 23:36:06 +0000476 self.voidcmd('TYPE A')
477 conn = self.transfercmd(cmd)
478 while 1:
479 buf = fp.readline()
480 if not buf: break
481 if buf[-2:] != CRLF:
482 if buf[-1] in CRLF: buf = buf[:-1]
483 buf = buf + CRLF
Martin v. Löwise12454f2002-02-16 23:06:19 +0000484 conn.sendall(buf)
Gregory P. Smithc64386b2008-01-22 00:19:41 +0000485 if callback: callback(buf)
Tim Peters88869f92001-01-14 23:36:06 +0000486 conn.close()
487 return self.voidresp()
Guido van Rossum0eaa74b1996-01-25 18:37:21 +0000488
Tim Peters88869f92001-01-14 23:36:06 +0000489 def acct(self, password):
490 '''Send new account name.'''
491 cmd = 'ACCT ' + password
492 return self.voidcmd(cmd)
Guido van Rossumc567c601992-11-05 22:22:37 +0000493
Tim Peters88869f92001-01-14 23:36:06 +0000494 def nlst(self, *args):
495 '''Return a list of files in a given directory (default the current).'''
496 cmd = 'NLST'
497 for arg in args:
498 cmd = cmd + (' ' + arg)
499 files = []
500 self.retrlines(cmd, files.append)
501 return files
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000502
Tim Peters88869f92001-01-14 23:36:06 +0000503 def dir(self, *args):
504 '''List a directory in long form.
505 By default list current directory to stdout.
506 Optional last argument is callback function; all
507 non-empty arguments before it are concatenated to the
508 LIST command. (This *should* only be used for a pathname.)'''
509 cmd = 'LIST'
510 func = None
511 if args[-1:] and type(args[-1]) != type(''):
512 args, func = args[:-1], args[-1]
513 for arg in args:
514 if arg:
515 cmd = cmd + (' ' + arg)
516 self.retrlines(cmd, func)
Guido van Rossumc567c601992-11-05 22:22:37 +0000517
Tim Peters88869f92001-01-14 23:36:06 +0000518 def rename(self, fromname, toname):
519 '''Rename a file.'''
520 resp = self.sendcmd('RNFR ' + fromname)
521 if resp[0] != '3':
522 raise error_reply, resp
523 return self.voidcmd('RNTO ' + toname)
Guido van Rossuma61bdeb1995-10-11 17:36:31 +0000524
Tim Peters88869f92001-01-14 23:36:06 +0000525 def delete(self, filename):
526 '''Delete a file.'''
527 resp = self.sendcmd('DELE ' + filename)
528 if resp[:3] in ('250', '200'):
529 return resp
Tim Peters88869f92001-01-14 23:36:06 +0000530 else:
531 raise error_reply, resp
Guido van Rossum02cf5821993-05-17 08:00:02 +0000532
Tim Peters88869f92001-01-14 23:36:06 +0000533 def cwd(self, dirname):
534 '''Change to a directory.'''
535 if dirname == '..':
536 try:
537 return self.voidcmd('CDUP')
538 except error_perm, msg:
Martin v. Löwisb5255112002-03-10 15:59:58 +0000539 if msg.args[0][:3] != '500':
540 raise
Tim Peters88869f92001-01-14 23:36:06 +0000541 elif dirname == '':
542 dirname = '.' # does nothing, but could return error
543 cmd = 'CWD ' + dirname
544 return self.voidcmd(cmd)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000545
Tim Peters88869f92001-01-14 23:36:06 +0000546 def size(self, filename):
547 '''Retrieve the size of a file.'''
Gregory P. Smith2230bcf2008-01-22 23:15:34 +0000548 # The SIZE command is defined in RFC-3659
Tim Peters88869f92001-01-14 23:36:06 +0000549 resp = self.sendcmd('SIZE ' + filename)
550 if resp[:3] == '213':
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000551 s = resp[3:].strip()
552 try:
553 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000554 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000555 return long(s)
Guido van Rossumc567c601992-11-05 22:22:37 +0000556
Tim Peters88869f92001-01-14 23:36:06 +0000557 def mkd(self, dirname):
558 '''Make a directory, return its full pathname.'''
559 resp = self.sendcmd('MKD ' + dirname)
560 return parse257(resp)
Guido van Rossum98245091998-02-19 21:15:44 +0000561
Tim Peters88869f92001-01-14 23:36:06 +0000562 def rmd(self, dirname):
563 '''Remove a directory.'''
564 return self.voidcmd('RMD ' + dirname)
Guido van Rossum1115ab21992-11-04 15:51:30 +0000565
Tim Peters88869f92001-01-14 23:36:06 +0000566 def pwd(self):
567 '''Return current working directory.'''
568 resp = self.sendcmd('PWD')
569 return parse257(resp)
Guido van Rossum17ed1ae1993-06-01 13:21:04 +0000570
Tim Peters88869f92001-01-14 23:36:06 +0000571 def quit(self):
572 '''Quit, and close the connection.'''
573 resp = self.voidcmd('QUIT')
574 self.close()
575 return resp
576
577 def close(self):
578 '''Close the connection without assuming anything about it.'''
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700579 if self.file is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000580 self.file.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700581 if self.sock is not None:
Fred Drake9c98a422001-02-28 21:46:37 +0000582 self.sock.close()
Senthil Kumarane4ef7262011-06-26 13:45:17 -0700583 self.file = self.sock = None
Guido van Rossumc567c601992-11-05 22:22:37 +0000584
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000585try:
586 import ssl
587except ImportError:
588 pass
589else:
590 class FTP_TLS(FTP):
591 '''A FTP subclass which adds TLS support to FTP as described
592 in RFC-4217.
593
594 Connect as usual to port 21 implicitly securing the FTP control
595 connection before authenticating.
596
597 Securing the data connection requires user to explicitly ask
598 for it by calling prot_p() method.
599
600 Usage example:
601 >>> from ftplib import FTP_TLS
602 >>> ftps = FTP_TLS('ftp.python.org')
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200603 >>> ftps.login() # login anonymously previously securing control channel
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000604 '230 Guest login ok, access restrictions apply.'
605 >>> ftps.prot_p() # switch to secure data connection
606 '200 Protection level set to P'
607 >>> ftps.retrlines('LIST') # list directory content securely
608 total 9
609 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
610 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
611 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
612 drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
613 d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
614 drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
615 drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
616 drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
617 -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
618 '226 Transfer complete.'
619 >>> ftps.quit()
620 '221 Goodbye.'
621 >>>
622 '''
623 ssl_version = ssl.PROTOCOL_TLSv1
624
625 def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
626 certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
627 self.keyfile = keyfile
628 self.certfile = certfile
629 self._prot_p = False
630 FTP.__init__(self, host, user, passwd, acct, timeout)
631
632 def login(self, user='', passwd='', acct='', secure=True):
633 if secure and not isinstance(self.sock, ssl.SSLSocket):
634 self.auth()
635 return FTP.login(self, user, passwd, acct)
636
637 def auth(self):
638 '''Set up secure control connection by using TLS/SSL.'''
639 if isinstance(self.sock, ssl.SSLSocket):
640 raise ValueError("Already using TLS")
641 if self.ssl_version == ssl.PROTOCOL_TLSv1:
642 resp = self.voidcmd('AUTH TLS')
643 else:
644 resp = self.voidcmd('AUTH SSL')
645 self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
646 ssl_version=self.ssl_version)
647 self.file = self.sock.makefile(mode='rb')
648 return resp
649
650 def prot_p(self):
651 '''Set up secure data connection.'''
652 # PROT defines whether or not the data channel is to be protected.
653 # Though RFC-2228 defines four possible protection levels,
654 # RFC-4217 only recommends two, Clear and Private.
655 # Clear (PROT C) means that no security is to be used on the
656 # data-channel, Private (PROT P) means that the data-channel
657 # should be protected by TLS.
658 # PBSZ command MUST still be issued, but must have a parameter of
659 # '0' to indicate that no buffering is taking place and the data
660 # connection should not be encapsulated.
661 self.voidcmd('PBSZ 0')
662 resp = self.voidcmd('PROT P')
663 self._prot_p = True
664 return resp
665
666 def prot_c(self):
667 '''Set up clear text data connection.'''
668 resp = self.voidcmd('PROT C')
669 self._prot_p = False
670 return resp
671
672 # --- Overridden FTP methods
673
674 def ntransfercmd(self, cmd, rest=None):
675 conn, size = FTP.ntransfercmd(self, cmd, rest)
676 if self._prot_p:
677 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
678 ssl_version=self.ssl_version)
679 return conn, size
680
681 def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
682 self.voidcmd('TYPE I')
683 conn = self.transfercmd(cmd, rest)
684 try:
685 while 1:
686 data = conn.recv(blocksize)
687 if not data:
688 break
689 callback(data)
690 # shutdown ssl layer
691 if isinstance(conn, ssl.SSLSocket):
692 conn.unwrap()
693 finally:
694 conn.close()
695 return self.voidresp()
696
697 def retrlines(self, cmd, callback = None):
698 if callback is None: callback = print_line
699 resp = self.sendcmd('TYPE A')
700 conn = self.transfercmd(cmd)
701 fp = conn.makefile('rb')
702 try:
703 while 1:
704 line = fp.readline()
705 if self.debugging > 2: print '*retr*', repr(line)
706 if not line:
707 break
708 if line[-2:] == CRLF:
709 line = line[:-2]
710 elif line[-1:] == '\n':
711 line = line[:-1]
712 callback(line)
713 # shutdown ssl layer
714 if isinstance(conn, ssl.SSLSocket):
715 conn.unwrap()
716 finally:
717 fp.close()
718 conn.close()
719 return self.voidresp()
720
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000721 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000722 self.voidcmd('TYPE I')
Antoine Pitrouacbe3bd2009-11-27 13:18:34 +0000723 conn = self.transfercmd(cmd, rest)
Antoine Pitrouccd5e022009-11-15 17:22:09 +0000724 try:
725 while 1:
726 buf = fp.read(blocksize)
727 if not buf: break
728 conn.sendall(buf)
729 if callback: callback(buf)
730 # shutdown ssl layer
731 if isinstance(conn, ssl.SSLSocket):
732 conn.unwrap()
733 finally:
734 conn.close()
735 return self.voidresp()
736
737 def storlines(self, cmd, fp, callback=None):
738 self.voidcmd('TYPE A')
739 conn = self.transfercmd(cmd)
740 try:
741 while 1:
742 buf = fp.readline()
743 if not buf: break
744 if buf[-2:] != CRLF:
745 if buf[-1] in CRLF: buf = buf[:-1]
746 buf = buf + CRLF
747 conn.sendall(buf)
748 if callback: callback(buf)
749 # shutdown ssl layer
750 if isinstance(conn, ssl.SSLSocket):
751 conn.unwrap()
752 finally:
753 conn.close()
754 return self.voidresp()
755
756 __all__.append('FTP_TLS')
757 all_errors = (Error, IOError, EOFError, ssl.SSLError)
758
759
Guido van Rossumacfb82a1997-10-22 20:49:52 +0000760_150_re = None
Fred Drake4de02d91997-01-10 18:26:09 +0000761
762def parse150(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000763 '''Parse the '150' response for a RETR request.
764 Returns the expected transfer size or None; size is not guaranteed to
765 be present in the 150 message.
766 '''
767 if resp[:3] != '150':
768 raise error_reply, resp
769 global _150_re
770 if _150_re is None:
771 import re
772 _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE)
773 m = _150_re.match(resp)
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000774 if not m:
775 return None
776 s = m.group(1)
777 try:
778 return int(s)
Guido van Rossum1f74cb32001-10-17 17:21:47 +0000779 except (OverflowError, ValueError):
Guido van Rossumb6aca6a2001-10-16 19:45:52 +0000780 return long(s)
Fred Drake4de02d91997-01-10 18:26:09 +0000781
782
Guido van Rossum70297d32001-08-17 17:24:29 +0000783_227_re = None
784
Guido van Rossumd2560b01996-05-28 23:41:25 +0000785def parse227(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000786 '''Parse the '227' response for a PASV request.
787 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
788 Return ('host.addr.as.numbers', port#) tuple.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000789
Tim Peters88869f92001-01-14 23:36:06 +0000790 if resp[:3] != '227':
791 raise error_reply, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000792 global _227_re
793 if _227_re is None:
794 import re
795 _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)')
796 m = _227_re.search(resp)
797 if not m:
Tim Peters88869f92001-01-14 23:36:06 +0000798 raise error_proto, resp
Guido van Rossum70297d32001-08-17 17:24:29 +0000799 numbers = m.groups()
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000800 host = '.'.join(numbers[:4])
801 port = (int(numbers[4]) << 8) + int(numbers[5])
Tim Peters88869f92001-01-14 23:36:06 +0000802 return host, port
Guido van Rossumd2560b01996-05-28 23:41:25 +0000803
804
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000805def parse229(resp, peer):
806 '''Parse the '229' response for a EPSV request.
807 Raises error_proto if it does not contain '(|||port|)'
808 Return ('host.addr.as.numbers', port#) tuple.'''
809
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000810 if resp[:3] != '229':
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000811 raise error_reply, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000812 left = resp.find('(')
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000813 if left < 0: raise error_proto, resp
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000814 right = resp.find(')', left + 1)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000815 if right < 0:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000816 raise error_proto, resp # should contain '(|||port|)'
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000817 if resp[left + 1] != resp[right - 1]:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000818 raise error_proto, resp
Walter Dörwalda401ae42002-06-03 10:41:45 +0000819 parts = resp[left + 1:right].split(resp[left+1])
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000820 if len(parts) != 5:
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000821 raise error_proto, resp
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000822 host = peer[0]
Neal Norwitz7ce734c2002-05-31 14:13:04 +0000823 port = int(parts[3])
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000824 return host, port
825
826
Guido van Rossumc567c601992-11-05 22:22:37 +0000827def parse257(resp):
Tim Peters88869f92001-01-14 23:36:06 +0000828 '''Parse the '257' response for a MKD or PWD request.
829 This is a response to a MKD or PWD request: a directory name.
830 Returns the directoryname in the 257 reply.'''
Guido van Rossumd2560b01996-05-28 23:41:25 +0000831
Tim Peters88869f92001-01-14 23:36:06 +0000832 if resp[:3] != '257':
833 raise error_reply, resp
834 if resp[3:5] != ' "':
835 return '' # Not compliant to RFC 959, but UNIX ftpd does this
836 dirname = ''
837 i = 5
838 n = len(resp)
839 while i < n:
840 c = resp[i]
841 i = i+1
842 if c == '"':
843 if i >= n or resp[i] != '"':
844 break
845 i = i+1
846 dirname = dirname + c
847 return dirname
Guido van Rossum1115ab21992-11-04 15:51:30 +0000848
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000849
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000850def print_line(line):
Tim Peters88869f92001-01-14 23:36:06 +0000851 '''Default retrlines callback to print a line.'''
852 print line
Guido van Rossumae3b3a31993-11-30 13:43:54 +0000853
Guido van Rossum2f3941d1997-10-07 14:49:56 +0000854
Guido van Rossumd2560b01996-05-28 23:41:25 +0000855def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
Tim Peters88869f92001-01-14 23:36:06 +0000856 '''Copy file from one FTP-instance to another.'''
857 if not targetname: targetname = sourcename
858 type = 'TYPE ' + type
859 source.voidcmd(type)
860 target.voidcmd(type)
861 sourcehost, sourceport = parse227(source.sendcmd('PASV'))
862 target.sendport(sourcehost, sourceport)
863 # RFC 959: the user must "listen" [...] BEFORE sending the
864 # transfer request.
865 # So: STOR before RETR, because here the target is a "user".
866 treply = target.sendcmd('STOR ' + targetname)
867 if treply[:3] not in ('125', '150'): raise error_proto # RFC 959
868 sreply = source.sendcmd('RETR ' + sourcename)
869 if sreply[:3] not in ('125', '150'): raise error_proto # RFC 959
870 source.voidresp()
871 target.voidresp()
Guido van Rossum1115ab21992-11-04 15:51:30 +0000872
Tim Peters88869f92001-01-14 23:36:06 +0000873
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000874class Netrc:
Tim Peters88869f92001-01-14 23:36:06 +0000875 """Class to parse & provide access to 'netrc' format files.
Fred Drake475d51d1997-06-24 22:02:54 +0000876
Tim Peters88869f92001-01-14 23:36:06 +0000877 See the netrc(4) man page for information on the file format.
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000878
Tim Peters88869f92001-01-14 23:36:06 +0000879 WARNING: This class is obsolete -- use module netrc instead.
Guido van Rossumc822a451998-12-22 16:49:16 +0000880
Tim Peters88869f92001-01-14 23:36:06 +0000881 """
882 __defuser = None
883 __defpasswd = None
884 __defacct = None
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000885
Tim Peters88869f92001-01-14 23:36:06 +0000886 def __init__(self, filename=None):
Raymond Hettinger094662a2002-06-01 01:29:16 +0000887 if filename is None:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000888 if "HOME" in os.environ:
Tim Peters88869f92001-01-14 23:36:06 +0000889 filename = os.path.join(os.environ["HOME"],
890 ".netrc")
891 else:
892 raise IOError, \
893 "specify file to load or set $HOME"
894 self.__hosts = {}
895 self.__macros = {}
896 fp = open(filename, "r")
897 in_macro = 0
898 while 1:
899 line = fp.readline()
900 if not line: break
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000901 if in_macro and line.strip():
Tim Peters88869f92001-01-14 23:36:06 +0000902 macro_lines.append(line)
903 continue
904 elif in_macro:
905 self.__macros[macro_name] = tuple(macro_lines)
906 in_macro = 0
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000907 words = line.split()
Tim Peters88869f92001-01-14 23:36:06 +0000908 host = user = passwd = acct = None
909 default = 0
910 i = 0
911 while i < len(words):
912 w1 = words[i]
913 if i+1 < len(words):
914 w2 = words[i + 1]
915 else:
916 w2 = None
917 if w1 == 'default':
918 default = 1
919 elif w1 == 'machine' and w2:
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000920 host = w2.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000921 i = i + 1
922 elif w1 == 'login' and w2:
923 user = w2
924 i = i + 1
925 elif w1 == 'password' and w2:
926 passwd = w2
927 i = i + 1
928 elif w1 == 'account' and w2:
929 acct = w2
930 i = i + 1
931 elif w1 == 'macdef' and w2:
932 macro_name = w2
933 macro_lines = []
934 in_macro = 1
935 break
936 i = i + 1
937 if default:
938 self.__defuser = user or self.__defuser
939 self.__defpasswd = passwd or self.__defpasswd
940 self.__defacct = acct or self.__defacct
941 if host:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000942 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000943 ouser, opasswd, oacct = \
944 self.__hosts[host]
945 user = user or ouser
946 passwd = passwd or opasswd
947 acct = acct or oacct
948 self.__hosts[host] = user, passwd, acct
949 fp.close()
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000950
Tim Peters88869f92001-01-14 23:36:06 +0000951 def get_hosts(self):
952 """Return a list of hosts mentioned in the .netrc file."""
953 return self.__hosts.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000954
Tim Peters88869f92001-01-14 23:36:06 +0000955 def get_account(self, host):
956 """Returns login information for the named host.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000957
Tim Peters88869f92001-01-14 23:36:06 +0000958 The return value is a triple containing userid,
959 password, and the accounting field.
Guido van Rossum8ca84201998-03-26 20:56:10 +0000960
Tim Peters88869f92001-01-14 23:36:06 +0000961 """
Eric S. Raymondc95bf692001-02-09 10:06:47 +0000962 host = host.lower()
Tim Peters88869f92001-01-14 23:36:06 +0000963 user = passwd = acct = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000964 if host in self.__hosts:
Tim Peters88869f92001-01-14 23:36:06 +0000965 user, passwd, acct = self.__hosts[host]
966 user = user or self.__defuser
967 passwd = passwd or self.__defpasswd
968 acct = acct or self.__defacct
969 return user, passwd, acct
Guido van Rossum8ca84201998-03-26 20:56:10 +0000970
Tim Peters88869f92001-01-14 23:36:06 +0000971 def get_macros(self):
972 """Return a list of all defined macro names."""
973 return self.__macros.keys()
Guido van Rossum8ca84201998-03-26 20:56:10 +0000974
Tim Peters88869f92001-01-14 23:36:06 +0000975 def get_macro(self, macro):
976 """Return a sequence of lines which define a named macro."""
977 return self.__macros[macro]
Guido van Rossum56d1e3a1997-03-14 04:16:54 +0000978
Fred Drake475d51d1997-06-24 22:02:54 +0000979
Tim Peters88869f92001-01-14 23:36:06 +0000980
Guido van Rossum1115ab21992-11-04 15:51:30 +0000981def test():
Tim Peters88869f92001-01-14 23:36:06 +0000982 '''Test program.
Raymond Hettingerc88a6c72005-04-05 04:31:09 +0000983 Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...
984
985 -d dir
986 -l list
987 -p password
988 '''
989
990 if len(sys.argv) < 2:
991 print test.__doc__
992 sys.exit(0)
Guido van Rossumd2560b01996-05-28 23:41:25 +0000993
Tim Peters88869f92001-01-14 23:36:06 +0000994 debugging = 0
995 rcfile = None
996 while sys.argv[1] == '-d':
997 debugging = debugging+1
998 del sys.argv[1]
999 if sys.argv[1][:2] == '-r':
1000 # get name of alternate ~/.netrc file:
1001 rcfile = sys.argv[1][2:]
1002 del sys.argv[1]
1003 host = sys.argv[1]
1004 ftp = FTP(host)
1005 ftp.set_debuglevel(debugging)
1006 userid = passwd = acct = ''
1007 try:
1008 netrc = Netrc(rcfile)
1009 except IOError:
1010 if rcfile is not None:
1011 sys.stderr.write("Could not open account file"
1012 " -- using anonymous login.")
1013 else:
1014 try:
1015 userid, passwd, acct = netrc.get_account(host)
1016 except KeyError:
1017 # no account for host
1018 sys.stderr.write(
1019 "No account -- using anonymous login.")
1020 ftp.login(userid, passwd, acct)
1021 for file in sys.argv[2:]:
1022 if file[:2] == '-l':
1023 ftp.dir(file[2:])
1024 elif file[:2] == '-d':
1025 cmd = 'CWD'
1026 if file[2:]: cmd = cmd + ' ' + file[2:]
1027 resp = ftp.sendcmd(cmd)
1028 elif file == '-p':
1029 ftp.set_pasv(not ftp.passiveserver)
1030 else:
1031 ftp.retrbinary('RETR ' + file, \
1032 sys.stdout.write, 1024)
1033 ftp.quit()
Guido van Rossum221ec0b1995-08-04 04:39:30 +00001034
1035
1036if __name__ == '__main__':
Tim Peters88869f92001-01-14 23:36:06 +00001037 test()