home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 1.5)
-
- """An FTP client class, and some helper functions.
- Based on RFC 959: File Transfer Protocol
- (FTP), by J. Postel and J. Reynolds
-
- Changes and improvements suggested by Steve Majewski.
- Modified by Jack to work on the mac.
- Modified by Siebren to support docstrings and PASV.
-
-
- Example:
-
- >>> from ftplib import FTP
- >>> ftp = FTP('ftp.python.org') # connect to host, default port
- >>> ftp.login() # default, i.e.: user anonymous, passwd user@hostname
- '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
- import string
-
- try:
- import SOCKS
- socket = SOCKS
- except ImportError:
- import socket
-
- MSG_OOB = 1
- FTP_PORT = 21
- error_reply = 'ftplib.error_reply'
- error_temp = 'ftplib.error_temp'
- error_perm = 'ftplib.error_perm'
- error_proto = 'ftplib.error_proto'
- all_errors = (error_reply, error_temp, error_perm, error_proto, socket.error, IOError, EOFError)
- CRLF = '\r\n'
-
- class FTP:
- """An FTP client class.
-
- \tTo create a connection, call the class using these argument:
- \t\thost, user, passwd, acct
- \tThese are all strings, and have default value ''.
- \tThen use self.connect() with optional host and port argument.
-
- \tTo download a file, use ftp.retrlines('RETR ' + filename),
- \tor ftp.retrbinary() with slightly different arguments.
- \tTo upload a file, use ftp.storlines() or ftp.storbinary(),
- \twhich have an open file as argument (see their definitions
- \tbelow for details).
- \tThe download/upload functions first issue appropriate TYPE
- \tand PORT or PASV commands.
- """
-
- def __init__(self, host = '', user = '', passwd = '', acct = ''):
- self.debugging = 0
- self.host = ''
- self.port = FTP_PORT
- self.sock = None
- self.file = None
- self.welcome = None
- resp = None
- if host:
- resp = self.connect(host)
- if user:
- resp = self.login(user, passwd, acct)
-
-
-
-
- def connect(self, host = '', port = 0):
- '''Connect to host. Arguments are:
- \t\t- host: hostname to connect to (string, default previous host)
- \t\t- port: port to connect to (integer, default previous port)'''
- if host:
- self.host = host
-
- if port:
- self.port = port
-
- self.passiveserver = 0
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.connect(self.host, self.port)
- self.file = self.sock.makefile('rb')
- self.welcome = self.getresp()
- return self.welcome
-
-
- def getwelcome(self):
- '''Get the welcome message from the server.
- \t\t(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.
- \t\tThe required argument level means:
- \t\t0: no debugging output (default)
- \t\t1: print commands and responses but not body text etc.
- \t\t2: 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.
- \t\tWith a false argument, use the normal PORT mode,
- \t\tWith 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 `s`
-
-
- def putline(self, line):
- line = line + CRLF
- if self.debugging > 1:
- print '*put*', self.sanitize(line)
-
- self.sock.send(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 1:
- nextline = self.getline()
- line = line + '\n' + nextline
- if nextline[:3] == code and nextline[3:4] != '-':
- break
-
-
- 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.
- \t\tThis does not follow the procedure from the RFC to send Telnet
- \t\tIP and Synch; that doesn't seem to work with the servers I've
- \t\ttried. Instead, just send the ABOR command as OOB data."""
- line = 'ABOR' + CRLF
- if self.debugging > 1:
- print '*put urgent*', self.sanitize(line)
-
- self.sock.send(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 = string.splitfields(host, '.')
- pbytes = [
- `port / 256`,
- `port % 256`]
- bytes = hbytes + pbytes
- cmd = 'PORT ' + string.joinfields(bytes, ',')
- return self.voidcmd(cmd)
-
-
- def makeport(self):
- '''Create a new socket and send a PORT command for it.'''
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('', 0))
- sock.listen(1)
- (dummyhost, port) = sock.getsockname()
- (host, dummyport) = self.sock.getsockname()
- resp = self.sendport(host, port)
- return sock
-
-
- def ntransfercmd(self, cmd):
- '''Initiate a transfer over the data connection.
- \t\tIf the transfer is active, send a port command and
- \t\tthe transfer command, and accept the connection.
- \t\tIf the server is passive, send a pasv command, connect
- \t\tto it, and start the transfer command.
- \t\tEither way, return the socket for the connection and
- \t\tthe expected size of the transfer. The expected size
- \t\tmay be None if it could not be determined.'''
- size = None
- if self.passiveserver:
- (host, port) = parse227(self.sendcmd('PASV'))
- conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- conn.connect(host, port)
- resp = self.sendcmd(cmd)
- if resp[0] != '1':
- raise error_reply, resp
-
- else:
- sock = self.makeport()
- 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):
- '''Initiate a transfer over the data connection. Returns
- \t\tthe socket for the connection. See also ntransfercmd().'''
- return self.ntransfercmd(cmd)[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 ('', '-'):
- thishost = socket.gethostname()
- if not ('.' in thishost):
- thisaddr = socket.gethostbyname(thishost)
- (firstname, names, unused) = socket.gethostbyaddr(thisaddr)
- names.insert(0, firstname)
- for name in names:
- pass
-
-
-
- try:
- if os.environ.has_key('LOGNAME'):
- realuser = os.environ['LOGNAME']
- elif os.environ.has_key('USER'):
- realuser = os.environ['USER']
- else:
- realuser = 'anonymous'
- except AttributeError:
- realuser = 'anonymous'
-
- passwd = passwd + realuser + '@' + thishost
-
- 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):
- '''Retrieve data in binary mode.
- \t\tThe argument is a RETR command.
- \t\tThe callback function is called for each block.
- \t\tThis creates a new port for you'''
- self.voidcmd('TYPE I')
- conn = self.transfercmd(cmd)
- while 1:
- data = conn.recv(blocksize)
- if not data:
- break
-
- callback(data)
- conn.close()
- return self.voidresp()
-
-
- def retrlines(self, cmd, callback = None):
- '''Retrieve data in line mode.
- \t\tThe argument is a RETR or LIST command.
- \t\tThe callback function (2nd argument) is called for each line,
- \t\twith trailing CRLF stripped. This creates a new port for you.
- \t\tprint_lines is the default callback.'''
- if not callback:
- callback = print_line
-
- resp = self.sendcmd('TYPE A')
- conn = self.transfercmd(cmd)
- fp = conn.makefile('rb')
- while 1:
- line = fp.readline()
- if self.debugging > 2:
- print '*retr*', `line`
-
- if not line:
- break
-
- if line[-2:] == CRLF:
- line = line[:-2]
- elif line[-1:] == '\n':
- line = line[:-1]
-
- callback(line)
- fp.close()
- conn.close()
- return self.voidresp()
-
-
- def storbinary(self, cmd, fp, blocksize):
- '''Store a file in binary mode.'''
- self.voidcmd('TYPE I')
- conn = self.transfercmd(cmd)
- while 1:
- buf = fp.read(blocksize)
- if not buf:
- break
-
- conn.send(buf)
- 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 1:
- buf = fp.readline()
- if not buf:
- break
-
- if buf[-2:] != CRLF:
- if buf[-1] in CRLF:
- buf = buf[:-1]
-
- buf = buf + CRLF
-
- conn.send(buf)
- 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.
- \t\tBy default list current directory to stdout.
- \t\tOptional last argument is callback function; all
- \t\tnon-empty arguments before it are concatenated to the
- \t\tLIST command. (This *should* only be used for a pathname.)'''
- cmd = 'LIST'
- func = None
- if args[-1:] and type(args[-1]) != type(''):
- (args, func) = (args[:-1], args[-1])
-
- for arg in args:
- pass
-
- 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[:3] != '500':
- raise error_perm, msg
-
- except:
- msg[:3] != '500'
-
-
- 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':
- return string.atoi(string.strip(resp[3:]))
-
-
-
- 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.'''
- self.file.close()
- self.sock.close()
- del self.file
- del self.sock
-
-
- _150_re = None
-
- def parse150(resp):
- """Parse the '150' response for a RETR request.
- \tReturns the expected transfer size or None; size is not guaranteed to
- \tbe present in the 150 message.
- \t"""
- 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 m:
- return string.atoi(m.group(1))
-
- return None
-
-
- def parse227(resp):
- """Parse the '227' response for a PASV request.
- \tRaises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
- \tReturn ('host.addr.as.numbers', port#) tuple."""
- if resp[:3] != '227':
- raise error_reply, resp
-
- left = string.find(resp, '(')
- if left < 0:
- raise error_proto, resp
-
- right = string.find(resp, ')', left + 1)
- if right < 0:
- raise error_proto, resp
-
- numbers = string.split(resp[left + 1:right], ',')
- if len(numbers) != 6:
- raise error_proto, resp
-
- host = string.join(numbers[:4], '.')
- port = (string.atoi(numbers[4]) << 8) + string.atoi(numbers[5])
- return (host, port)
-
-
- def parse257(resp):
- """Parse the '257' response for a MKD or PWD request.
- \tThis is a response to a MKD or PWD request: a directory name.
- \tReturns 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.
-
- \tSee the netrc(4) man page for information on the file format.
-
- \tWARNING: This class is obsolete -- use module netrc instead.
-
- \t"""
- __defuser = None
- __defpasswd = None
- __defacct = None
-
- def __init__(self, filename = None):
- if not filename:
- if os.environ.has_key('HOME'):
- 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 1:
- line = fp.readline()
- if not line:
- break
-
- if in_macro and string.strip(line):
- macro_lines.append(line)
- continue
- elif in_macro:
- self._Netrc__macros[macro_name] = tuple(macro_lines)
- in_macro = 0
-
- words = string.split(line)
- host = user = passwd = 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 = string.lower(w2)
- 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 self._Netrc__hosts.has_key(host):
- (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)
-
- 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.
-
- \t\tThe return value is a triple containing userid,
- \t\tpassword, and the accounting field.
-
- \t\t'''
- host = string.lower(host)
- user = passwd = acct = None
- if self._Netrc__hosts.has_key(host):
- (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.
- \tUsage: 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:])
- elif file[:2] == '-d':
- cmd = 'CWD'
- if file[2:]:
- cmd = cmd + ' ' + file[2:]
-
- resp = ftp.sendcmd(cmd)
- elif file == '-p':
- ftp.set_pasv(not (ftp.passiveserver))
- else:
- ftp.retrbinary('RETR ' + file, sys.stdout.write, 1024)
-
- ftp.quit()
-
- if __name__ == '__main__':
- test()
-
-