Changeset 391 for python/trunk/Lib/ftplib.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/ftplib.py
r2 r391 34 34 # Modified by Siebren to support docstrings and PASV. 35 35 # Modified by Phil Schwartz to add storbinary and storlines callbacks. 36 # Modified by Giampaolo Rodola' to add TLS support. 36 37 # 37 38 … … 55 56 # The standard FTP server control port 56 57 FTP_PORT = 21 58 # The sizehint parameter passed to readline() calls 59 MAXLINE = 8192 57 60 58 61 … … 101 104 host = '' 102 105 port = FTP_PORT 106 maxline = MAXLINE 103 107 sock = None 104 108 file = None … … 180 184 # Raise EOFError if the connection is closed 181 185 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) 183 189 if self.debugging > 1: 184 190 print '*get*', self.sanitize(line) … … 235 241 self.sock.sendall(line, MSG_OOB) 236 242 resp = self.getmultiline() 237 if resp[:3] not in ('426', '22 6'):243 if resp[:3] not in ('426', '225', '226'): 238 244 raise error_proto, resp 239 245 … … 273 279 def makeport(self): 274 280 '''Create a new socket and send a PORT command for it.''' 275 msg = "getaddrinfo returns an empty list"281 err = None 276 282 sock = None 277 283 for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): … … 280 286 sock = socket.socket(af, socktype, proto) 281 287 sock.bind(sa) 282 except socket.error, msg:288 except socket.error, err: 283 289 if sock: 284 290 sock.close() … … 286 292 continue 287 293 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") 290 299 sock.listen(1) 291 300 port = sock.getsockname()[1] # Get proper port … … 295 304 else: 296 305 resp = self.sendeprt(host, port) 306 if self.timeout is not _GLOBAL_DEFAULT_TIMEOUT: 307 sock.settimeout(self.timeout) 297 308 return sock 298 309 … … 323 334 host, port = self.makepasv() 324 335 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 338 353 else: 339 354 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() 349 369 if resp[:3] == '150': 350 370 # this is conditional in case we received a 125 … … 418 438 fp = conn.makefile('rb') 419 439 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) 421 443 if self.debugging > 2: print '*retr*', repr(line) 422 444 if not line: … … 431 453 return self.voidresp() 432 454 433 def storbinary(self, cmd, fp, blocksize=8192, callback=None ):455 def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None): 434 456 """Store a file in binary mode. A new port is created for you. 435 457 … … 440 462 the connection at once. [default: 8192] 441 463 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] 443 466 444 467 Returns: … … 446 469 """ 447 470 self.voidcmd('TYPE I') 448 conn = self.transfercmd(cmd )471 conn = self.transfercmd(cmd, rest) 449 472 while 1: 450 473 buf = fp.read(blocksize) … … 462 485 fp: A file-like object with a readline() method. 463 486 callback: An optional single parameter callable that is called on 464 oneach line after it is sent. [default: None]487 each line after it is sent. [default: None] 465 488 466 489 Returns: … … 470 493 conn = self.transfercmd(cmd) 471 494 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) 473 498 if not buf: break 474 499 if buf[-2:] != CRLF: … … 570 595 def close(self): 571 596 '''Close the connection without assuming anything about it.''' 572 if self.file :597 if self.file is not None: 573 598 self.file.close() 599 if self.sock is not None: 574 600 self.sock.close() 575 self.file = self.sock = None 601 self.file = self.sock = None 602 603 try: 604 import ssl 605 except ImportError: 606 pass 607 else: 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) 576 780 577 781 … … 715 919 in_macro = 0 716 920 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) 718 924 if not line: break 719 925 if in_macro and line.strip():
Note:
See TracChangeset
for help on using the changeset viewer.