home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.4)
-
- """An FTP client class and some helper functions.
-
- Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds
-
- Example:
-
- >>> from ftplib import FTP
- >>> ftp = FTP('ftp.python.org') # connect to host, default port
- >>> ftp.login() # default, i.e.: user anonymous, passwd anonymous@
- '230 Guest login ok, access restrictions apply.'
- >>> ftp.retrlines('LIST') # list directory contents
- total 9
- drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .
- drwxr-xr-x 8 root wheel 1024 Jan 3 1994 ..
- drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin
- drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc
- d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming
- drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib
- drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub
- drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr
- -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
- '226 Transfer complete.'
- >>> ftp.quit()
- '221 Goodbye.'
- >>>
-
- A nice test that reveals some of the network dialogue would be:
- python ftplib.py -d localhost -l -p -l
- """
- import os
- import sys
-
- try:
- import SOCKS
- socket = SOCKS
- del SOCKS
- from socket import getfqdn
- socket.getfqdn = getfqdn
- del getfqdn
- except ImportError:
- import socket
-
- __all__ = [
- 'FTP',
- 'Netrc']
- MSG_OOB = 1
- FTP_PORT = 21
-
- class Error(Exception):
- pass
-
-
- class error_reply(Error):
- pass
-
-
- class error_temp(Error):
- pass
-
-
- class error_perm(Error):
- pass
-
-
- class error_proto(Error):
- pass
-
- all_errors = (Error, socket.error, IOError, EOFError)
- CRLF = '\r\n'
-
- class FTP:
- """An FTP client class.
-
- To create a connection, call the class using these argument:
- host, user, passwd, acct
- These are all strings, and have default value ''.
- Then use self.connect() with optional host and port argument.
-
- To download a file, use ftp.retrlines('RETR ' + filename),
- or ftp.retrbinary() with slightly different arguments.
- To upload a file, use ftp.storlines() or ftp.storbinary(),
- which have an open file as argument (see their definitions
- below for details).
- The download/upload functions first issue appropriate TYPE
- and PORT or PASV commands.
- """
- debugging = 0
- host = ''
- port = FTP_PORT
- sock = None
- file = None
- welcome = None
- passiveserver = 1
-
- def __init__(self, host = '', user = '', passwd = '', acct = ''):
- if host:
- self.connect(host)
- if user:
- self.login(user, passwd, acct)
-
-
-
-
- def connect(self, host = '', port = 0):
- '''Connect to host. Arguments are:
- - host: hostname to connect to (string, default previous host)
- - port: port to connect to (integer, default previous port)'''
- if host:
- self.host = host
-
- if port:
- self.port = port
-
- msg = 'getaddrinfo returns an empty list'
- for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
- (af, socktype, proto, canonname, sa) = res
-
- try:
- self.sock = socket.socket(af, socktype, proto)
- self.sock.connect(sa)
- except socket.error:
- msg = None
- if self.sock:
- self.sock.close()
-
- self.sock = None
- continue
-
-
- if not self.sock:
- raise socket.error, msg
-
- self.af = af
- self.file = self.sock.makefile('rb')
- self.welcome = self.getresp()
- return self.welcome
-
-
- def getwelcome(self):
- '''Get the welcome message from the server.
- (this is read and squirreled away by connect())'''
- if self.debugging:
- print '*welcome*', self.sanitize(self.welcome)
-
- return self.welcome
-
-
- def set_debuglevel(self, level):
- '''Set the debugging level.
- The required argument level means:
- 0: no debugging output (default)
- 1: print commands and responses but not body text etc.
- 2: also print raw lines read and sent before stripping CR/LF'''
- self.debugging = level
-
- debug = set_debuglevel
-
- def set_pasv(self, val):
- '''Use passive or active mode for data transfers.
- With a false argument, use the normal PORT mode,
- With a true argument, use the PASV command.'''
- self.passiveserver = val
-
-
- def sanitize(self, s):
- if s[:5] == 'pass ' or s[:5] == 'PASS ':
- i = len(s)
- while i > 5 and s[i - 1] in '\r\n':
- i = i - 1
- s = s[:5] + '*' * (i - 5) + s[i:]
-
- return repr(s)
-
-
- def putline(self, line):
- line = line + CRLF
- if self.debugging > 1:
- print '*put*', self.sanitize(line)
-
- self.sock.sendall(line)
-
-
- def putcmd(self, line):
- if self.debugging:
- print '*cmd*', self.sanitize(line)
-
- self.putline(line)
-
-
- def getline(self):
- line = self.file.readline()
- if self.debugging > 1:
- print '*get*', self.sanitize(line)
-
- if not line:
- raise EOFError
-
- if line[-2:] == CRLF:
- line = line[:-2]
- elif line[-1:] in CRLF:
- line = line[:-1]
-
- return line
-
-
- def getmultiline(self):
- line = self.getline()
- if line[3:4] == '-':
- code = line[:3]
- while None:
- nextline = self.getline()
- line = line + '\n' + nextline
- if nextline[:3] == code and nextline[3:4] != '-':
- break
- continue
-
- return line
-
-
- def getresp(self):
- resp = self.getmultiline()
- if self.debugging:
- print '*resp*', self.sanitize(resp)
-
- self.lastresp = resp[:3]
- c = resp[:1]
- if c == '4':
- raise error_temp, resp
-
- if c == '5':
- raise error_perm, resp
-
- if c not in '123':
- raise error_proto, resp
-
- return resp
-
-
- def voidresp(self):
- """Expect a response beginning with '2'."""
- resp = self.getresp()
- if resp[0] != '2':
- raise error_reply, resp
-
- return resp
-
-
- def abort(self):
- """Abort a file transfer. Uses out-of-band data.
- This does not follow the procedure from the RFC to send Telnet
- IP and Synch; that doesn't seem to work with the servers I've
- tried. Instead, just send the ABOR command as OOB data."""
- line = 'ABOR' + CRLF
- if self.debugging > 1:
- print '*put urgent*', self.sanitize(line)
-
- self.sock.sendall(line, MSG_OOB)
- resp = self.getmultiline()
- if resp[:3] not in ('426', '226'):
- raise error_proto, resp
-
-
-
- def sendcmd(self, cmd):
- '''Send a command and return the response.'''
- self.putcmd(cmd)
- return self.getresp()
-
-
- def voidcmd(self, cmd):
- """Send a command and expect a response beginning with '2'."""
- self.putcmd(cmd)
- return self.voidresp()
-
-
- def sendport(self, host, port):
- '''Send a PORT command with the current host and the given
- port number.
- '''
- hbytes = host.split('.')
- pbytes = [
- repr(port / 256),
- repr(port % 256)]
- bytes = hbytes + pbytes
- cmd = 'PORT ' + ','.join(bytes)
- return self.voidcmd(cmd)
-
-
- def sendeprt(self, host, port):
- '''Send a EPRT command with the current host and the given port number.'''
- af = 0
- if self.af == socket.AF_INET:
- af = 1
-
- if self.af == socket.AF_INET6:
- af = 2
-
- if af == 0:
- raise error_proto, 'unsupported address family'
-
- fields = [
- '',
- repr(af),
- host,
- repr(port),
- '']
- cmd = 'EPRT ' + '|'.join(fields)
- return self.voidcmd(cmd)
-
-
- def makeport(self):
- '''Create a new socket and send a PORT command for it.'''
- msg = 'getaddrinfo returns an empty list'
- sock = None
- for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
- (af, socktype, proto, canonname, sa) = res
-
- try:
- sock = socket.socket(af, socktype, proto)
- sock.bind(sa)
- except socket.error:
- msg = None
- if sock:
- sock.close()
-
- sock = None
- continue
-
-
- if not sock:
- raise socket.error, msg
-
- sock.listen(1)
- port = sock.getsockname()[1]
- host = self.sock.getsockname()[0]
- if self.af == socket.AF_INET:
- resp = self.sendport(host, port)
- else:
- resp = self.sendeprt(host, port)
- return sock
-
-
- def makepasv(self):
- if self.af == socket.AF_INET:
- (host, port) = parse227(self.sendcmd('PASV'))
- else:
- (host, port) = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
- return (host, port)
-
-
- def ntransfercmd(self, cmd, rest = None):
- """Initiate a transfer over the data connection.
-
- If the transfer is active, send a port command and the
- transfer command, and accept the connection. If the server is
- passive, send a pasv command, connect to it, and start the
- transfer command. Either way, return the socket for the
- connection and the expected size of the transfer. The
- expected size may be None if it could not be determined.
-
- Optional `rest' argument can be a string that is sent as the
- argument to a RESTART command. This is essentially a server
- marker used to tell the server to skip over any data up to the
- given marker.
- """
- size = None
- if self.passiveserver:
- (host, port) = self.makepasv()
- (af, socktype, proto, canon, sa) = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0]
- conn = socket.socket(af, socktype, proto)
- conn.connect(sa)
- if rest is not None:
- self.sendcmd('REST %s' % rest)
-
- resp = self.sendcmd(cmd)
- if resp[0] != '1':
- raise error_reply, resp
-
- else:
- sock = self.makeport()
- if rest is not None:
- self.sendcmd('REST %s' % rest)
-
- resp = self.sendcmd(cmd)
- if resp[0] != '1':
- raise error_reply, resp
-
- (conn, sockaddr) = sock.accept()
- if resp[:3] == '150':
- size = parse150(resp)
-
- return (conn, size)
-
-
- def transfercmd(self, cmd, rest = None):
- '''Like ntransfercmd() but returns only the socket.'''
- return self.ntransfercmd(cmd, rest)[0]
-
-
- def login(self, user = '', passwd = '', acct = ''):
- '''Login, default anonymous.'''
- if not user:
- user = 'anonymous'
-
- if not passwd:
- passwd = ''
-
- if not acct:
- acct = ''
-
- if user == 'anonymous' and passwd in ('', '-'):
- passwd = passwd + 'anonymous@'
-
- resp = self.sendcmd('USER ' + user)
- if resp[0] == '3':
- resp = self.sendcmd('PASS ' + passwd)
-
- if resp[0] == '3':
- resp = self.sendcmd('ACCT ' + acct)
-
- if resp[0] != '2':
- raise error_reply, resp
-
- return resp
-
-
- def retrbinary(self, cmd, callback, blocksize = 8192, rest = None):
- """Retrieve data in binary mode.
-
- `cmd' is a RETR command. `callback' is a callback function is
- called for each block. No more than `blocksize' number of
- bytes will be read from the socket. Optional `rest' is passed
- to transfercmd().
-
- A new port is created for you. Return the response code.
- """
- self.voidcmd('TYPE I')
- conn = self.transfercmd(cmd, rest)
- while None:
- data = conn.recv(blocksize)
- if not data:
- break
-
- conn.close()
- return self.voidresp()
-
-
- def retrlines(self, cmd, callback = None):
- '''Retrieve data in line mode.
- The argument is a RETR or LIST command.
- The callback function (2nd argument) is called for each line,
- with trailing CRLF stripped. This creates a new port for you.
- print_line() is the default callback.'''
- if callback is None:
- callback = print_line
-
- resp = self.sendcmd('TYPE A')
- conn = self.transfercmd(cmd)
- fp = conn.makefile('rb')
- while None:
- line = fp.readline()
- if self.debugging > 2:
- print '*retr*', repr(line)
-
- if not line:
- break
-
- if line[-2:] == CRLF:
- line = line[:-2]
- elif line[-1:] == '\n':
- line = line[:-1]
-
- fp.close()
- conn.close()
- return self.voidresp()
-
-
- def storbinary(self, cmd, fp, blocksize = 8192):
- '''Store a file in binary mode.'''
- self.voidcmd('TYPE I')
- conn = self.transfercmd(cmd)
- while None:
- buf = fp.read(blocksize)
- if not buf:
- break
-
- conn.close()
- return self.voidresp()
-
-
- def storlines(self, cmd, fp):
- '''Store a file in line mode.'''
- self.voidcmd('TYPE A')
- conn = self.transfercmd(cmd)
- while None:
- buf = fp.readline()
- if not buf:
- break
-
- if buf[-2:] != CRLF:
- if buf[-1] in CRLF:
- buf = buf[:-1]
-
- buf = buf + CRLF
-
- conn.close()
- return self.voidresp()
-
-
- def acct(self, password):
- '''Send new account name.'''
- cmd = 'ACCT ' + password
- return self.voidcmd(cmd)
-
-
- def nlst(self, *args):
- '''Return a list of files in a given directory (default the current).'''
- cmd = 'NLST'
- for arg in args:
- cmd = cmd + ' ' + arg
-
- files = []
- self.retrlines(cmd, files.append)
- return files
-
-
- def dir(self, *args):
- '''List a directory in long form.
- By default list current directory to stdout.
- Optional last argument is callback function; all
- non-empty arguments before it are concatenated to the
- LIST command. (This *should* only be used for a pathname.)'''
- cmd = 'LIST'
- func = None
- if args[-1:] and type(args[-1]) != type(''):
- args = args[:-1]
- func = args[-1]
-
- for arg in args:
- if arg:
- cmd = cmd + ' ' + arg
- continue
-
- self.retrlines(cmd, func)
-
-
- def rename(self, fromname, toname):
- '''Rename a file.'''
- resp = self.sendcmd('RNFR ' + fromname)
- if resp[0] != '3':
- raise error_reply, resp
-
- return self.voidcmd('RNTO ' + toname)
-
-
- def delete(self, filename):
- '''Delete a file.'''
- resp = self.sendcmd('DELE ' + filename)
- if resp[:3] in ('250', '200'):
- return resp
- elif resp[:1] == '5':
- raise error_perm, resp
- else:
- raise error_reply, resp
-
-
- def cwd(self, dirname):
- '''Change to a directory.'''
- if dirname == '..':
-
- try:
- return self.voidcmd('CDUP')
- except error_perm:
- msg = None
- if msg.args[0][:3] != '500':
- raise
-
- except:
- msg.args[0][:3] != '500'
-
-
- None<EXCEPTION MATCH>error_perm
- if dirname == '':
- dirname = '.'
-
- cmd = 'CWD ' + dirname
- return self.voidcmd(cmd)
-
-
- def size(self, filename):
- '''Retrieve the size of a file.'''
- resp = self.sendcmd('SIZE ' + filename)
- if resp[:3] == '213':
- s = resp[3:].strip()
-
- try:
- return int(s)
- except (OverflowError, ValueError):
- return long(s)
- except:
- None<EXCEPTION MATCH>(OverflowError, ValueError)
-
-
- None<EXCEPTION MATCH>(OverflowError, ValueError)
-
-
- def mkd(self, dirname):
- '''Make a directory, return its full pathname.'''
- resp = self.sendcmd('MKD ' + dirname)
- return parse257(resp)
-
-
- def rmd(self, dirname):
- '''Remove a directory.'''
- return self.voidcmd('RMD ' + dirname)
-
-
- def pwd(self):
- '''Return current working directory.'''
- resp = self.sendcmd('PWD')
- return parse257(resp)
-
-
- def quit(self):
- '''Quit, and close the connection.'''
- resp = self.voidcmd('QUIT')
- self.close()
- return resp
-
-
- def close(self):
- '''Close the connection without assuming anything about it.'''
- if self.file:
- self.file.close()
- self.sock.close()
- self.file = None
- self.sock = None
-
-
-
- _150_re = None
-
- def parse150(resp):
- """Parse the '150' response for a RETR request.
- Returns the expected transfer size or None; size is not guaranteed to
- be present in the 150 message.
- """
- global _150_re
- if resp[:3] != '150':
- raise error_reply, resp
-
- if _150_re is None:
- import re
- _150_re = re.compile('150 .* \\((\\d+) bytes\\)', re.IGNORECASE)
-
- m = _150_re.match(resp)
- if not m:
- return None
-
- s = m.group(1)
-
- try:
- return int(s)
- except (OverflowError, ValueError):
- return long(s)
-
-
- _227_re = None
-
- def parse227(resp):
- """Parse the '227' response for a PASV request.
- Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
- Return ('host.addr.as.numbers', port#) tuple."""
- global _227_re
- if resp[:3] != '227':
- raise error_reply, resp
-
- if _227_re is None:
- import re
- _227_re = re.compile('(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)')
-
- m = _227_re.search(resp)
- if not m:
- raise error_proto, resp
-
- numbers = m.groups()
- host = '.'.join(numbers[:4])
- port = (int(numbers[4]) << 8) + int(numbers[5])
- return (host, port)
-
-
- def parse229(resp, peer):
- """Parse the '229' response for a EPSV request.
- Raises error_proto if it does not contain '(|||port|)'
- Return ('host.addr.as.numbers', port#) tuple."""
- if resp[:3] != '229':
- raise error_reply, resp
-
- left = resp.find('(')
- if left < 0:
- raise error_proto, resp
-
- right = resp.find(')', left + 1)
- if right < 0:
- raise error_proto, resp
-
- if resp[left + 1] != resp[right - 1]:
- raise error_proto, resp
-
- parts = resp[left + 1:right].split(resp[left + 1])
- if len(parts) != 5:
- raise error_proto, resp
-
- host = peer[0]
- port = int(parts[3])
- return (host, port)
-
-
- def parse257(resp):
- """Parse the '257' response for a MKD or PWD request.
- This is a response to a MKD or PWD request: a directory name.
- Returns the directoryname in the 257 reply."""
- if resp[:3] != '257':
- raise error_reply, resp
-
- if resp[3:5] != ' "':
- return ''
-
- dirname = ''
- i = 5
- n = len(resp)
- while i < n:
- c = resp[i]
- i = i + 1
- if c == '"':
- if i >= n or resp[i] != '"':
- break
-
- i = i + 1
-
- dirname = dirname + c
- return dirname
-
-
- def print_line(line):
- '''Default retrlines callback to print a line.'''
- print line
-
-
- def ftpcp(source, sourcename, target, targetname = '', type = 'I'):
- '''Copy file from one FTP-instance to another.'''
- if not targetname:
- targetname = sourcename
-
- type = 'TYPE ' + type
- source.voidcmd(type)
- target.voidcmd(type)
- (sourcehost, sourceport) = parse227(source.sendcmd('PASV'))
- target.sendport(sourcehost, sourceport)
- treply = target.sendcmd('STOR ' + targetname)
- if treply[:3] not in ('125', '150'):
- raise error_proto
-
- sreply = source.sendcmd('RETR ' + sourcename)
- if sreply[:3] not in ('125', '150'):
- raise error_proto
-
- source.voidresp()
- target.voidresp()
-
-
- class Netrc:
- """Class to parse & provide access to 'netrc' format files.
-
- See the netrc(4) man page for information on the file format.
-
- WARNING: This class is obsolete -- use module netrc instead.
-
- """
- __defuser = None
- __defpasswd = None
- __defacct = None
-
- def __init__(self, filename = None):
- if filename is None:
- if 'HOME' in os.environ:
- filename = os.path.join(os.environ['HOME'], '.netrc')
- else:
- raise IOError, 'specify file to load or set $HOME'
-
- self._Netrc__hosts = { }
- self._Netrc__macros = { }
- fp = open(filename, 'r')
- in_macro = 0
- while None:
- line = fp.readline()
- if not line:
- break
-
- if in_macro and line.strip():
- macro_lines.append(line)
- continue
- elif in_macro:
- self._Netrc__macros[macro_name] = tuple(macro_lines)
- in_macro = 0
-
- words = line.split()
- host = None
- user = None
- passwd = None
- acct = None
- default = 0
- i = 0
- while i < len(words):
- w1 = words[i]
- if i + 1 < len(words):
- w2 = words[i + 1]
- else:
- w2 = None
- if w1 == 'default':
- default = 1
- elif w1 == 'machine' and w2:
- host = w2.lower()
- i = i + 1
- elif w1 == 'login' and w2:
- user = w2
- i = i + 1
- elif w1 == 'password' and w2:
- passwd = w2
- i = i + 1
- elif w1 == 'account' and w2:
- acct = w2
- i = i + 1
- elif w1 == 'macdef' and w2:
- macro_name = w2
- macro_lines = []
- in_macro = 1
- break
-
- i = i + 1
- if default:
- if not user:
- pass
- self._Netrc__defuser = self._Netrc__defuser
- if not passwd:
- pass
- self._Netrc__defpasswd = self._Netrc__defpasswd
- if not acct:
- pass
- self._Netrc__defacct = self._Netrc__defacct
-
- if host:
- if host in self._Netrc__hosts:
- (ouser, opasswd, oacct) = self._Netrc__hosts[host]
- if not user:
- pass
- user = ouser
- if not passwd:
- pass
- passwd = opasswd
- if not acct:
- pass
- acct = oacct
-
- self._Netrc__hosts[host] = (user, passwd, acct)
- continue
- fp.close()
-
-
- def get_hosts(self):
- '''Return a list of hosts mentioned in the .netrc file.'''
- return self._Netrc__hosts.keys()
-
-
- def get_account(self, host):
- '''Returns login information for the named host.
-
- The return value is a triple containing userid,
- password, and the accounting field.
-
- '''
- host = host.lower()
- user = None
- passwd = None
- acct = None
- if host in self._Netrc__hosts:
- (user, passwd, acct) = self._Netrc__hosts[host]
-
- if not user:
- pass
- user = self._Netrc__defuser
- if not passwd:
- pass
- passwd = self._Netrc__defpasswd
- if not acct:
- pass
- acct = self._Netrc__defacct
- return (user, passwd, acct)
-
-
- def get_macros(self):
- '''Return a list of all defined macro names.'''
- return self._Netrc__macros.keys()
-
-
- def get_macro(self, macro):
- '''Return a sequence of lines which define a named macro.'''
- return self._Netrc__macros[macro]
-
-
-
- def test():
- '''Test program.
- Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ...'''
- debugging = 0
- rcfile = None
- while sys.argv[1] == '-d':
- debugging = debugging + 1
- del sys.argv[1]
- if sys.argv[1][:2] == '-r':
- rcfile = sys.argv[1][2:]
- del sys.argv[1]
-
- host = sys.argv[1]
- ftp = FTP(host)
- ftp.set_debuglevel(debugging)
- userid = passwd = acct = ''
-
- try:
- netrc = Netrc(rcfile)
- except IOError:
- if rcfile is not None:
- sys.stderr.write('Could not open account file -- using anonymous login.')
-
- except:
- rcfile is not None
-
-
- try:
- (userid, passwd, acct) = netrc.get_account(host)
- except KeyError:
- sys.stderr.write('No account -- using anonymous login.')
-
- ftp.login(userid, passwd, acct)
- for file in sys.argv[2:]:
- if file[:2] == '-l':
- ftp.dir(file[2:])
- continue
- if file[:2] == '-d':
- cmd = 'CWD'
- if file[2:]:
- cmd = cmd + ' ' + file[2:]
-
- resp = ftp.sendcmd(cmd)
- continue
- if file == '-p':
- ftp.set_pasv(not (ftp.passiveserver))
- continue
- ftp.retrbinary('RETR ' + file, sys.stdout.write, 1024)
-
- ftp.quit()
-
- if __name__ == '__main__':
- test()
-
-