NAME

DwNntpClient -- Class for handling the client side of an NNTP session

SYNOPSIS

class DW_EXPORT DwNntpClient : public DwProtocolClient {

public:

    enum {
        kCmdNoCommand=0,
        kCmdArticle,
        kCmdBody,
        kCmdHead,
        kCmdStat,
        kCmdGroup,
        kCmdHelp,
        kCmdIhave,
        kCmdLast,
        kCmdList,
        kCmdNewgroups,
        kCmdNewnews,
        kCmdNext,
        kCmdPost,
        kCmdQuit,
        kCmdSlave
    };
    DwNntpClient();
    virtual ~DwNntpClient();
    virtual int Open(const char* aServer, DwUint16 aPort=119);
    DwObserver* SetObserver(DwObserver* aObserver);
    int ReplyCode() const;
    const DwString& StatusResponse() const;
    const DwString& TextResponse() const;
    int Article(int aNumber=(-1));
    int Article(const char* aMsgid);
    int Body(int aNumber=(-1));
    int Body(const char* aMsgid);
    int Head(int aNumber=(-1));
    int Head(const char* aMsgid);
    int Stat(int aNumber=(-1));
    int Stat(const char* aMsgid);
    int Group(const char* aNewsgroupName);
    int Help();
    int Ihave(const char* aMsgId);
    int Last();
    int List();
    int Newgroups(const char* aDate, const char* aTime,
        DwBool aIsGmt=DwFalse, const char* aDistributions=0);
    int Newnews(const char* aNewsgroups, const char* aDate,
        const char* aTime, DwBool aIsGmt=DwFalse, const char* aDistribution=0);
    int Next();
    int Post();
    int Quit();
    int Slave();
    int SendData(const DwString& aStr);
    int SendData(const char* aBuf, int aBufLen);
};

DESCRIPTION

DwNntpClient is a class that handles the client side of an NNTP session. Specifically, DwNntpClient provides facilities for opening a connection to an NNTP server, sending commands and data to the server, receiving responses and data from the server, and closing the connection. The protocol implemented is the Network News Transport Protocol, as specified in RFC-977.

DwNntpClient is derived from DwProtocolClient. For information about inherited member functions, especially member functions for detecting failures or errors, see the man page for DwProtocolClient.

In an NNTP session, the client sends commands to the server and receives responses from the server. A client command consists of a command word and zero or more argument words. A server response consists of a status line and possibly some additional lines of text. The status line consists of a three-digit numeric reply code followed by additional information. The reply code indicates a success or failure condition. In some cases, the server sends lines of text immediately after the status line. DwNntpClient provides facilities for you to send commands to the server and receive responses from the server.

DwNntpClient has only a default constructor. On Win32 platforms, it is possible for the constructor to fail. (It calls WSAStartup().) You should verify that the constructor succeeded by calling the inherited member function DwProtocolClient::LastError() and checking for a zero return value.

To open a connection to the server, call the member function Open() with the name of the server as an argument. Open() accepts an optional argument that specifies the TCP port that the server listens to. The default port is the standard NNTP port (119). Open() may fail, so you should check the return value to verify that it succeeded. To close the connection, call the inherited member function DwProtocolClient::Close(). To check if a connection is open, call the inherited member function DwProtocolClient::IsOpen(). IsOpen() returns a boolean value that indicates whether or not a call to Open() was successful; it will not detect failure in the network or a close operation by the remote host.

For each NNTP command, DwNntpClient has a member function that sends that command and receives the server's response. If the command takes any arguments, then those arguments are passed as function arguments to the command function. The command functions return the numeric value of the three-digit reply code returned by the server. Your program must check the reply code to determine whether or not the command was accepted and performed by the server. In some cases, because of a communications error or some other error, it is not possible for the command function to send the command or receive the response. When this happens, the command function will return 0. You can determine the precise error or failure by calling the inherited member functions DwProtocolClient::LastError() or DwProtocolClient::LastFailure().

After each command is sent, DwNntpClient receives the server's response and remembers it. The member function ReplyCode() returns the numeric value of the reply code received in response to the last command. StatusResponse() returns the entire status response from the server, including the reply code. If no status response is received, possibly because of a communications error or failure, ReplyCode() returns zero and StatusResponse() returns an empty string.

The server sends a status response, including a reply code, for all all NNTP commands. For some commands, such as when the client requests an article body, the server sends a multi-line text response immediately following the status response. Multi-line text responses can be received in either of two ways. The simplest way is to call the member function TextResponse() after a command completes successfully. This simple method works fine for non-interactive applications. It can be a problem in interactive applications, however, because there is no data to display to a user until the entire text response is retrieved. An alternative method allows your program to retrieve the text response one line at a time as it is received. To use this method, you must define a subclass of DwObserver and assign an object of that class to the DwNntpClient object using the member function SetObserver(). DwObserver is an abstract class, declared in protocol.h, that has just one pure virtual member function Notify(). After each line of the text response is received, DwNntpClient will call the Notify() member function of its assigned DwObserver object. Each invocation of Notify() should call the DwNntpClient member function TextResponse() to retrieve the next line of the text response. Note that you cannot use both of these methods at the same time: if an observer is assigned, TextResponse() returns only the last line received, not the entire multi-line text response.

Certain NNTP commands, such as the POST command, require the NNTP client to send multiple lines of text to the server. To perform this bulk data transfer, DwNntpClient provides the member function SendData(). In the current implementation, SendData() does not convert end of line characters, so it is your responsibility to convert the end of line characters to CR LF, if necessary. (You may use the utility function DwToCrLfEol() to do the conversion.) SendData() will perform the character stuffing to protect '.' at the beginning of a line, and it will append the final [CR LF] '.' CR LF. It is possible to divide data and make multiple calls to SendData(); however, if you do so, please note the following paragraph.

Note: Because of a feature (some might say bug) in the current implementation, SendData() will not detect a '.' at the beginning of a line if the CR LF '.' sequence is split between two calls to SendData(). This problem will probably be resolved in a future version, but be aware that such a change will require a change in DwNntpClient's interface.

Public Member Functions

DwNntpClient()

Initializes the DwNntpClient object. It is possible for the constructor to fail. To verify that the constructor succeeded, call the member function LastError() and check that it returns zero. (In the Win32 implementation, the constructor calls the Winsock function WSAStartup(), which may fail.)

virtual int Open(const char* aServer, DwUint16 aPort=119)

Opens a TCP connection to the server aServer at port aPort. aServer may be either a host name, such as "news.acme.com" or an IP number in dotted decimal format, such as "147.81.64.60". The default value for aPort is 119, the well-known port for NNTP assigned by the Internet Assigned Numbers Authority (IANA).

If the connection attempt succeeds, the server sends a response. Open() returns the server's numeric reply code. The full response from the server can be retrieved by calling StatusResponse().

If the connection attempt fails, Open() returns 0. To determine what error occurred when a connection attempt fails, call the inherited member function DwProtocolClient::LastError(). To determine if a failure also occurred, call the inherited member function DwProtocolClient::LastFailure().

DwObserver* SetObserver(DwObserver* aObserver)

Sets the observer object that interacts with the DwNntpClient object to retrieve a multi-line text response. If an observer is set, DwNntpClient will call the observer's Notify() method after each line of the text response is received. To remove an observer, call SetObserver() with a NULL argument. SetObserver() returns the previously set observer, or NULL if no observer was previously set.

int ReplyCode() const

Returns the numeric value of the three-digit reply code received from the server in response to the last client command. If no response was received, ReplyCode() returns zero.

const DwString& StatusResponse() const

Returns the entire status response last received from the server. If no response was received, perhaps because of a communications failure, StatusResponse() returns an empty string.

const DwString& TextResponse() const

If no observer is set for this object, TextResponse() returns a string that comprises the entire sequence of lines received from the server. Otherwise, if an observer is set for this object, TextResponse() returns only the most recent line received.

int Article(int aNumber=(-1))
int Article(const char* aMsgid)

Sends the NNTP ARTICLE command and returns the reply code received from the server. If no response is received, the function returns zero. The optional argument aNumber specifies the number of an article to retrieve. If Article() is called with the default argument, the ARTICLE command is sent to the server with no argument. aMsgId specifies the message id of an article to retrieve.

int Body(int aNumber=(-1))
int Body(const char* aMsgid)

Sends the NNTP BODY command and returns the reply code received from the server. If no response is received, the function returns zero. The optional argument aNumber specifies the number of an article whose body should be retrieved. If Body() is called with the default argument, the BODY command is sent to the server with no argument. aMsgId specifies the message id of the article to access.

int Head(int aNumber=(-1))
int Head(const char* aMsgid)

Sends the NNTP HEAD command and returns the reply code received from the server. If no response is received, the function returns zero. The optional argument aNumber specifies the number of an article whose header lines should be retrieved. If Head() is called with the default argument, the HEAD command is sent to the server with no argument. aMsgId specifies the message id of the article to access.

int Stat(int aNumber=(-1))
int Stat(const char* aMsgid)

Sends the NNTP STAT command and returns the reply code received from the server. If no response is received, the function returns zero. The optional argument aNumber specifies the number of an article to access. If Stat() is called with the default argument, the STAT command is sent to the server with no argument. aMsgId specifies the message id of the article to access.

int Group(const char* aNewsgroupName)

Sends the NNTP GROUP command and returns the reply code received from the server. The argument aNewsgroupName specifies the newgroup to be selected. If no response is received, the function returns zero.

int Help()

Sends the NNTP HELP command and returns the reply code received from the server. If no response is received, the function returns zero.

int Ihave(const char* aMsgId)

Sends the NNTP IHAVE command and returns the reply code received from the server. aMsgId specifies the message id of the article to be sent. If no response is received, the function returns zero.

int Last()

Sends the NNTP LAST command and returns the reply code received from the server. If no response is received, the function returns zero.

int List()

Sends the NNTP LIST command and returns the reply code received from the server. If no response is received, the function returns zero.

int Newgroups(const char* aDate, const char* aTime, DwBool aIsGmt=DwFalse, const char* aDistributions=0)

Sends the NNTP NEWGROUPS command and returns the reply code received from the server. If no response is received, the function returns zero. aDate is the date in the form YYMMDD, where YY is the two digit year, MM is the month, and DD is the day of the month. aTime is the time in the form HHMMSS, where HH is hours, MM is minutes, and SS is seconds. If aIsGmt is true, the optional GMT argument will be sent. aDistributions specifies the optional list of distribution groups.

int Newnews(const char* aNewsgroups, const char* aDate, const char* aTime, DwBool aIsGmt=DwFalse, const char* aDistribution=0)

Sends the NNTP NEWNEWS command and returns the reply code received from the server. If no response is received, the function returns zero. aNewsgroups is the newsgroups argument for the command. aDate is the date in the form YYMMDD, where YY is the two digit year, MM is the month, and DD is the day of the month. aTime is the time in the form HHMMSS, where HH is hours, MM is minutes, and SS is seconds. If aIsGmt is true, the optional GMT argument will be sent. aDistributions specifies the optional list of distribution groups.

int Next()

Sends the NNTP NEXT command and returns the reply code received from the server. If no response is received, perhaps because of an error, the function returns zero.

int Post()

Sends the NNTP POST command and returns the reply code received from the server. If no response is received, perhaps because of an error, the function returns zero.

int Quit()

Sends the NNTP TQUIT command and returns the reply code received from the server. If no response is received, perhaps because of an error, the function returns zero.

int Slave()

Sends the NNTP SLAVE command and returns the reply code received from the server. If no response is received, perhaps because of an error, the function returns zero.

int SendData(const DwString& aStr)
int SendData(const char* aBuf, int aBufLen)

Sends bulk data to the server and returns the reply code received. A bulk data transfer follows a POST or IHAVE command and is used to send a complete article to the server.

In the current implementation, SendData() does not convert end of line characters, so it is your responsibility to convert the end of line characters to CR LF, if necessary. (You may use the utility function DwToCrLfEol() to do the conversion.) SendData() will perform the character stuffing to protect '.' at the beginning of a line, and it will append the final [CR LF] '.' CR LF. It is possible to divide the data and make multiple calls to SendData(); however, this may cause problems in the current implementation if a CR LF '.' sequence is split between calls.