--- /opt/Python3/lib/python3.2/nntplib.py 2010-11-03 11:15:09.308473998 +0800 +++ ./nntpslib.py 2010-11-04 09:08:07.414638060 +0800 @@ -109,8 +109,9 @@ pass -# Standard port used by NNTP servers +# Standard port used by NNTP/S servers NNTP_PORT = 119 +NNTPS_PORT = 563 # Response numbers that are followed by additional text (e.g. article) @@ -910,9 +911,10 @@ class NNTP(_NNTPBase): - def __init__(self, host, port=NNTP_PORT, user=None, password=None, + def __init__(self, host, port=None, user=None, password=None, readermode=None, usenetrc=True, - timeout=_GLOBAL_DEFAULT_TIMEOUT): + timeout=_GLOBAL_DEFAULT_TIMEOUT, + ssl_context=None): """Initialize an instance. Arguments: - host: hostname to connect to - port: port to connect to (default the standard NNTP port) @@ -923,6 +925,9 @@ - usenetrc: allow loading username and password from ~/.netrc file if not specified explicitly - timeout: timeout (in seconds) used for socket connections + - ssl_context: An OPTIONAL SSLContext class to be used for an SSL + connection. If not defined a normal + connection is used. readermode is sometimes necessary if you are connecting to an NNTP server on the local machine and intend to call @@ -930,10 +935,24 @@ unexpected NNTPPermanentErrors, you might need to set readermode. """ + + if not port: + if not ssl_context: + port = NNTP_PORT + else: + port = NNTPS_PORT + self.host = host self.port = port self.sock = socket.create_connection((host, port), timeout) + + # Make sure we can actually use ssl if its attempted. + if ssl_context: + self.sslcontext = ssl_context + self.sock = self.sslcontext.wrap_socket(self.sock) + file = self.sock.makefile("rwb") + _NNTPBase.__init__(self, file, host, user, password, readermode, usenetrc, timeout) @@ -947,21 +966,52 @@ # Test retrieval when run as a script. if __name__ == '__main__': import argparse - from email.utils import parsedate + + DefaultNNTP = 'news.gmane.org' + DefaultNNTPS = 'snews.gmane.org' + SSLv2 = 'SSLv2' + SSLv23 = 'SSLv23' + SSLv3 = 'SSLv3' + TLSv1 = 'TLSv1' parser = argparse.ArgumentParser(description="""\ nntplib built-in demo - display the latest articles in a newsgroup""") parser.add_argument('-g', '--group', default='gmane.comp.python.general', help='group to fetch messages from (default: %(default)s)') - parser.add_argument('-s', '--server', default='news.gmane.org', - help='NNTP server hostname (default: %(default)s)') - parser.add_argument('-p', '--port', default=NNTP_PORT, type=int, - help='NNTP port number (default: %(default)s)') + parser.add_argument('-s', '--server', default=None, + help='NNTP server hostname (default: '+DefaultNNTP+') (SSL default: '+DefaultNNTPS+')') + parser.add_argument('-p', '--port', default=None, type=int, + help='NNTP port number (default: '+str(NNTP_PORT)+') (SSL default: '+str(NNTPS_PORT)+')') parser.add_argument('-n', '--nb-articles', default=10, type=int, help='number of articles to fetch (default: %(default)s)') + parser.add_argument('--SSL', default=None, choices=[SSLv2, SSLv23, SSLv3, TLSv1], + help='Use OPTIONAL SSL Connection type (default: %(default)s)') + parser.add_argument('--source', default=None, + help='OPTIONAL Source Address to use (default: %(default)s)') args = parser.parse_args() - s = NNTP(host=args.server, port=args.port) + SSLContext=None + nntphost = args.server + nntpport = args.port + + if args.SSL: + if not nntphost: + nntphost = DefaultNNTPS + + try: + import ssl + except ImportError as ie: + raise ie + else: + sslprotocols = {SSLv2:ssl.PROTOCOL_SSLv2, SSLv23:ssl.PROTOCOL_SSLv23, SSLv3:ssl.PROTOCOL_SSLv3, TLSv1:ssl.PROTOCOL_TLSv1} + print('Attempting ', ssl.get_protocol_name(sslprotocols[args.SSL]), 'Connection') + SSLContext = ssl.SSLContext(sslprotocols[args.SSL]) + + else: + if not nntphost: + nntphost = DefaultNNTP + + s = NNTP(host=nntphost, port=nntpport, ssl_context=SSLContext) resp, count, first, last, name = s.group(args.group) print('Group', name, 'has', count, 'articles, range', first, 'to', last)