diff -U 3 -r Python-Dev.original/Doc/library/nntplib.rst Python-Dev/Doc/library/nntplib.rst --- Python-Dev.original/Doc/library/nntplib.rst 2008-01-24 23:27:26.000000000 -0500 +++ Python-Dev/Doc/library/nntplib.rst 2008-01-25 15:33:15.000000000 -0500 @@ -69,6 +69,26 @@ .. versionchanged:: 2.4 *usenetrc* argument added. +.. class:: NNTP_SSL(host[, port [, keyfile [, certfile [, user[, password [, readermode [, usenetrc]]]]]]]) + + Return a new instance of the :class:`NNTP_SSL` class. :class:`NNTP_SSL` + objects have the same methods as :class:`NNTP` objects. If *port* is + omitted, port 563 (NNTPS) is used. *keyfile* and *certfile* are also + optional, and can contain a PEM formatted private key and certificate + chain file for the SSL connection. All other parameters behave the same + as for :class:`NNTP`. + +.. class:: NNTPBase(host, sock [, user[, password [, readermode [, usenetrc]]]]) + + Return a new instance of the :class:`NNTPBase` class. :class:`NNTPBase` + objects have the same methods as :class:`NNTP` objects. *host* is the + hostname, and is used here to retrieve credentials if *user* and *password* + are not specified. *sock* is an already connected socket or SSL wrapper. + All other parameters behave the same as for :class:`NNTP`. + + This class is made available for callers that wish to use non-default + parameters for the SSL wrapper. It is the base class for both :class:`NNTP` + and :class:`NNTP_SSL`. .. exception:: NNTPError diff -U 3 -r Python-Dev.original/Lib/nntplib.py Python-Dev/Lib/nntplib.py --- Python-Dev.original/Lib/nntplib.py 2008-01-24 23:28:01.000000000 -0500 +++ Python-Dev/Lib/nntplib.py 2008-01-25 14:28:37.000000000 -0500 @@ -32,7 +32,7 @@ import re import socket -__all__ = ["NNTP","NNTPReplyError","NNTPTemporaryError", +__all__ = ["NNTPBase","NNTP","NNTP_SSL","NNTPReplyError","NNTPTemporaryError", "NNTPPermanentError","NNTPProtocolError","NNTPDataError", "error_reply","error_temp","error_perm","error_proto", "error_data",] @@ -78,6 +78,7 @@ # Standard port used by NNTP servers NNTP_PORT = 119 +NNTP_SSL_PORT = 563 # Response numbers that are followed by additional text (e.g. article) @@ -90,12 +91,12 @@ # The class itself -class NNTP: - def __init__(self, host, port=NNTP_PORT, user=None, password=None, +class NNTPBase: + def __init__(self, host, sock, user=None, password=None, readermode=None, usenetrc=True): """Initialize an instance. Arguments: - - host: hostname to connect to - - port: port to connect to (default the standard NNTP port) + - host: hostname connected to + - sock: already-connected socket or socket-like object - user: username to authenticate with - password: password to use with username - readermode: if true, send 'mode reader' command after @@ -107,10 +108,7 @@ unexpected NNTPPermanentErrors, you might need to set readermode. """ - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((self.host, self.port)) + self.sock = sock self.file = self.sock.makefile('rb') self.debugging = 0 self.welcome = self.getresp() @@ -603,6 +601,74 @@ del self.file, self.sock return resp +# Plaintext version of NNTP class +class NNTP(NNTPBase): + def __init__(self, host, port=NNTP_PORT, user=None, password=None, + readermode=None, usenetrc=True): + """Initialize an instance. Arguments: + - host: hostname to connect to + - port: port to connect to (default the standard NNTP port) + - user: username to authenticate with + - password: password to use with username + - readermode: if true, send 'mode reader' command after + connecting. + + readermode is sometimes necessary if you are connecting to an + NNTP server on the local machine and intend to call + reader-specific comamnds, such as `group'. If you get + unexpected NNTPPermanentErrors, you might need to set + readermode. + """ + self.host = host + self.port = port + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + NNTPBase.__init__(self, host, sock, user, password, readermode, usenetrc) + +# SSL-enabled version of NNTP class +try: + import ssl +except ImportError: + pass +else: + class NNTP_SSL(NNTPBase): + def __init__(self, host, port=NNTP_SSL_PORT, + keyfile=None, certfile=None, + user=None, password=None, + readermode=None, usenetrc=True): + """Initialize an instance. Arguments: + - host: hostname to connect to + - port: port to connect to (default the standard NNTPS port) + - keyfile: PEM formatted file that countains your private key + - certfile: PEM formatted certificate chain file + - user: username to authenticate with + - password: password to use with username + - readermode: if true, send 'mode reader' command after + connecting. + + readermode is sometimes necessary if you are connecting to an + NNTP server on the local machine and intend to call + reader-specific comamnds, such as `group'. If you get + unexpected NNTPPermanentErrors, you might need to set + readermode. + """ + self.host = host + self.port = port + self.keyfile = keyfile + self.certfile = certfile + self.real_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.real_sock.connect((self.host, self.port)) + sock = ssl.wrap_socket(self.real_sock, keyfile, certfile) + NNTPBase.__init__(self, host, sock, user, password, readermode, usenetrc) + + def quit(self): + """Process a QUIT command and close the socket. Returns: + - resp: server response if successful""" + + resp = NNTPBase.quit(self) + self.real_sock.close() + del self.real_sock + return resp # Test retrieval when run as a script. # Assumption: if there's a local news server, it's called 'news'.