Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/ftplib.py

    r2 r391  
    3434# Modified by Siebren to support docstrings and PASV.
    3535# Modified by Phil Schwartz to add storbinary and storlines callbacks.
     36# Modified by Giampaolo Rodola' to add TLS support.
    3637#
    3738
     
    5556# The standard FTP server control port
    5657FTP_PORT = 21
     58# The sizehint parameter passed to readline() calls
     59MAXLINE = 8192
    5760
    5861
     
    101104    host = ''
    102105    port = FTP_PORT
     106    maxline = MAXLINE
    103107    sock = None
    104108    file = None
     
    180184    # Raise EOFError if the connection is closed
    181185    def getline(self):
    182         line = self.file.readline()
     186        line = self.file.readline(self.maxline + 1)
     187        if len(line) > self.maxline:
     188            raise Error("got more than %d bytes" % self.maxline)
    183189        if self.debugging > 1:
    184190            print '*get*', self.sanitize(line)
     
    235241        self.sock.sendall(line, MSG_OOB)
    236242        resp = self.getmultiline()
    237         if resp[:3] not in ('426', '226'):
     243        if resp[:3] not in ('426', '225', '226'):
    238244            raise error_proto, resp
    239245
     
    273279    def makeport(self):
    274280        '''Create a new socket and send a PORT command for it.'''
    275         msg = "getaddrinfo returns an empty list"
     281        err = None
    276282        sock = None
    277283        for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
     
    280286                sock = socket.socket(af, socktype, proto)
    281287                sock.bind(sa)
    282             except socket.error, msg:
     288            except socket.error, err:
    283289                if sock:
    284290                    sock.close()
     
    286292                continue
    287293            break
    288         if not sock:
    289             raise socket.error, msg
     294        if sock is None:
     295            if err is not None:
     296                raise err
     297            else:
     298                raise socket.error("getaddrinfo returns an empty list")
    290299        sock.listen(1)
    291300        port = sock.getsockname()[1] # Get proper port
     
    295304        else:
    296305            resp = self.sendeprt(host, port)
     306        if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
     307            sock.settimeout(self.timeout)
    297308        return sock
    298309
     
    323334            host, port = self.makepasv()
    324335            conn = socket.create_connection((host, port), self.timeout)
    325             if rest is not None:
    326                 self.sendcmd("REST %s" % rest)
    327             resp = self.sendcmd(cmd)
    328             # Some servers apparently send a 200 reply to
    329             # a LIST or STOR command, before the 150 reply
    330             # (and way before the 226 reply). This seems to
    331             # be in violation of the protocol (which only allows
    332             # 1xx or error messages for LIST), so we just discard
    333             # this response.
    334             if resp[0] == '2':
    335                 resp = self.getresp()
    336             if resp[0] != '1':
    337                 raise error_reply, resp
     336            try:
     337                if rest is not None:
     338                    self.sendcmd("REST %s" % rest)
     339                resp = self.sendcmd(cmd)
     340                # Some servers apparently send a 200 reply to
     341                # a LIST or STOR command, before the 150 reply
     342                # (and way before the 226 reply). This seems to
     343                # be in violation of the protocol (which only allows
     344                # 1xx or error messages for LIST), so we just discard
     345                # this response.
     346                if resp[0] == '2':
     347                    resp = self.getresp()
     348                if resp[0] != '1':
     349                    raise error_reply, resp
     350            except:
     351                conn.close()
     352                raise
    338353        else:
    339354            sock = self.makeport()
    340             if rest is not None:
    341                 self.sendcmd("REST %s" % rest)
    342             resp = self.sendcmd(cmd)
    343             # See above.
    344             if resp[0] == '2':
    345                 resp = self.getresp()
    346             if resp[0] != '1':
    347                 raise error_reply, resp
    348             conn, sockaddr = sock.accept()
     355            try:
     356                if rest is not None:
     357                    self.sendcmd("REST %s" % rest)
     358                resp = self.sendcmd(cmd)
     359                # See above.
     360                if resp[0] == '2':
     361                    resp = self.getresp()
     362                if resp[0] != '1':
     363                    raise error_reply, resp
     364                conn, sockaddr = sock.accept()
     365                if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT:
     366                    conn.settimeout(self.timeout)
     367            finally:
     368                sock.close()
    349369        if resp[:3] == '150':
    350370            # this is conditional in case we received a 125
     
    418438        fp = conn.makefile('rb')
    419439        while 1:
    420             line = fp.readline()
     440            line = fp.readline(self.maxline + 1)
     441            if len(line) > self.maxline:
     442                raise Error("got more than %d bytes" % self.maxline)
    421443            if self.debugging > 2: print '*retr*', repr(line)
    422444            if not line:
     
    431453        return self.voidresp()
    432454
    433     def storbinary(self, cmd, fp, blocksize=8192, callback=None):
     455    def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
    434456        """Store a file in binary mode.  A new port is created for you.
    435457
     
    440462                     the connection at once.  [default: 8192]
    441463          callback: An optional single parameter callable that is called on
    442                     on each block of data after it is sent.  [default: None]
     464                    each block of data after it is sent.  [default: None]
     465          rest: Passed to transfercmd().  [default: None]
    443466
    444467        Returns:
     
    446469        """
    447470        self.voidcmd('TYPE I')
    448         conn = self.transfercmd(cmd)
     471        conn = self.transfercmd(cmd, rest)
    449472        while 1:
    450473            buf = fp.read(blocksize)
     
    462485          fp: A file-like object with a readline() method.
    463486          callback: An optional single parameter callable that is called on
    464                     on each line after it is sent.  [default: None]
     487                    each line after it is sent.  [default: None]
    465488
    466489        Returns:
     
    470493        conn = self.transfercmd(cmd)
    471494        while 1:
    472             buf = fp.readline()
     495            buf = fp.readline(self.maxline + 1)
     496            if len(buf) > self.maxline:
     497                raise Error("got more than %d bytes" % self.maxline)
    473498            if not buf: break
    474499            if buf[-2:] != CRLF:
     
    570595    def close(self):
    571596        '''Close the connection without assuming anything about it.'''
    572         if self.file:
     597        if self.file is not None:
    573598            self.file.close()
     599        if self.sock is not None:
    574600            self.sock.close()
    575             self.file = self.sock = None
     601        self.file = self.sock = None
     602
     603try:
     604    import ssl
     605except ImportError:
     606    pass
     607else:
     608    class FTP_TLS(FTP):
     609        '''A FTP subclass which adds TLS support to FTP as described
     610        in RFC-4217.
     611
     612        Connect as usual to port 21 implicitly securing the FTP control
     613        connection before authenticating.
     614
     615        Securing the data connection requires user to explicitly ask
     616        for it by calling prot_p() method.
     617
     618        Usage example:
     619        >>> from ftplib import FTP_TLS
     620        >>> ftps = FTP_TLS('ftp.python.org')
     621        >>> ftps.login()  # login anonymously previously securing control channel
     622        '230 Guest login ok, access restrictions apply.'
     623        >>> ftps.prot_p()  # switch to secure data connection
     624        '200 Protection level set to P'
     625        >>> ftps.retrlines('LIST')  # list directory content securely
     626        total 9
     627        drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
     628        drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
     629        drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
     630        drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
     631        d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
     632        drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
     633        drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
     634        drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
     635        -rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg
     636        '226 Transfer complete.'
     637        >>> ftps.quit()
     638        '221 Goodbye.'
     639        >>>
     640        '''
     641        ssl_version = ssl.PROTOCOL_TLSv1
     642
     643        def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
     644                     certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
     645            self.keyfile = keyfile
     646            self.certfile = certfile
     647            self._prot_p = False
     648            FTP.__init__(self, host, user, passwd, acct, timeout)
     649
     650        def login(self, user='', passwd='', acct='', secure=True):
     651            if secure and not isinstance(self.sock, ssl.SSLSocket):
     652                self.auth()
     653            return FTP.login(self, user, passwd, acct)
     654
     655        def auth(self):
     656            '''Set up secure control connection by using TLS/SSL.'''
     657            if isinstance(self.sock, ssl.SSLSocket):
     658                raise ValueError("Already using TLS")
     659            if self.ssl_version == ssl.PROTOCOL_TLSv1:
     660                resp = self.voidcmd('AUTH TLS')
     661            else:
     662                resp = self.voidcmd('AUTH SSL')
     663            self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
     664                                        ssl_version=self.ssl_version)
     665            self.file = self.sock.makefile(mode='rb')
     666            return resp
     667
     668        def prot_p(self):
     669            '''Set up secure data connection.'''
     670            # PROT defines whether or not the data channel is to be protected.
     671            # Though RFC-2228 defines four possible protection levels,
     672            # RFC-4217 only recommends two, Clear and Private.
     673            # Clear (PROT C) means that no security is to be used on the
     674            # data-channel, Private (PROT P) means that the data-channel
     675            # should be protected by TLS.
     676            # PBSZ command MUST still be issued, but must have a parameter of
     677            # '0' to indicate that no buffering is taking place and the data
     678            # connection should not be encapsulated.
     679            self.voidcmd('PBSZ 0')
     680            resp = self.voidcmd('PROT P')
     681            self._prot_p = True
     682            return resp
     683
     684        def prot_c(self):
     685            '''Set up clear text data connection.'''
     686            resp = self.voidcmd('PROT C')
     687            self._prot_p = False
     688            return resp
     689
     690        # --- Overridden FTP methods
     691
     692        def ntransfercmd(self, cmd, rest=None):
     693            conn, size = FTP.ntransfercmd(self, cmd, rest)
     694            if self._prot_p:
     695                conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
     696                                       ssl_version=self.ssl_version)
     697            return conn, size
     698
     699        def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
     700            self.voidcmd('TYPE I')
     701            conn = self.transfercmd(cmd, rest)
     702            try:
     703                while 1:
     704                    data = conn.recv(blocksize)
     705                    if not data:
     706                        break
     707                    callback(data)
     708                # shutdown ssl layer
     709                if isinstance(conn, ssl.SSLSocket):
     710                    conn.unwrap()
     711            finally:
     712                conn.close()
     713            return self.voidresp()
     714
     715        def retrlines(self, cmd, callback = None):
     716            if callback is None: callback = print_line
     717            resp = self.sendcmd('TYPE A')
     718            conn = self.transfercmd(cmd)
     719            fp = conn.makefile('rb')
     720            try:
     721                while 1:
     722                    line = fp.readline(self.maxline + 1)
     723                    if len(line) > self.maxline:
     724                        raise Error("got more than %d bytes" % self.maxline)
     725                    if self.debugging > 2: print '*retr*', repr(line)
     726                    if not line:
     727                        break
     728                    if line[-2:] == CRLF:
     729                        line = line[:-2]
     730                    elif line[-1:] == '\n':
     731                        line = line[:-1]
     732                    callback(line)
     733                # shutdown ssl layer
     734                if isinstance(conn, ssl.SSLSocket):
     735                    conn.unwrap()
     736            finally:
     737                fp.close()
     738                conn.close()
     739            return self.voidresp()
     740
     741        def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
     742            self.voidcmd('TYPE I')
     743            conn = self.transfercmd(cmd, rest)
     744            try:
     745                while 1:
     746                    buf = fp.read(blocksize)
     747                    if not buf: break
     748                    conn.sendall(buf)
     749                    if callback: callback(buf)
     750                # shutdown ssl layer
     751                if isinstance(conn, ssl.SSLSocket):
     752                    conn.unwrap()
     753            finally:
     754                conn.close()
     755            return self.voidresp()
     756
     757        def storlines(self, cmd, fp, callback=None):
     758            self.voidcmd('TYPE A')
     759            conn = self.transfercmd(cmd)
     760            try:
     761                while 1:
     762                    buf = fp.readline(self.maxline + 1)
     763                    if len(buf) > self.maxline:
     764                        raise Error("got more than %d bytes" % self.maxline)
     765                    if not buf: break
     766                    if buf[-2:] != CRLF:
     767                        if buf[-1] in CRLF: buf = buf[:-1]
     768                        buf = buf + CRLF
     769                    conn.sendall(buf)
     770                    if callback: callback(buf)
     771                # shutdown ssl layer
     772                if isinstance(conn, ssl.SSLSocket):
     773                    conn.unwrap()
     774            finally:
     775                conn.close()
     776            return self.voidresp()
     777
     778    __all__.append('FTP_TLS')
     779    all_errors = (Error, IOError, EOFError, ssl.SSLError)
    576780
    577781
     
    715919        in_macro = 0
    716920        while 1:
    717             line = fp.readline()
     921            line = fp.readline(self.maxline + 1)
     922            if len(line) > self.maxline:
     923                raise Error("got more than %d bytes" % self.maxline)
    718924            if not line: break
    719925            if in_macro and line.strip():
Note: See TracChangeset for help on using the changeset viewer.