summaryrefslogtreecommitdiffstats
path: root/mimelib/mimelib/pop.h
blob: b5627e4d0a38f6d300d62188a672974ae59f60c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
//=============================================================================
// File:       pop.h
// Contents:   Declarations for DwPopClient
// Maintainer: Doug Sauder <dwsauder@fwb.gulf.net>
// WWW:        http://www.fwb.gulf.net/~dwsauder/mimepp.html
//
// Copyright (c) 1996, 1997 Douglas W. Sauder
// All rights reserved.
// 
// IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT,
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSETQUENTIAL DAMAGES ARISING OUT OF
// THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER
// HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
// NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
// BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
//=============================================================================

#ifndef DW_POP_H
#define DW_POP_H

#include <stdio.h>

#ifndef DW_CONFIG_H
#include <mimelib/config.h>
#endif

#ifndef DW_PROTOCOL_H
#include <mimelib/protocol.h>
#endif

#ifndef DW_STRING_H
#include <mimelib/string.h>
#endif


//=============================================================================
//+ Name DwPopClient -- Class for handling the client side of a POP session
//+ Description
//. {\tt DwPopClient} is a class that handles the client side of a POP
//. session.  Specifically, {\tt DwPopClient} provides facilities for
//. opening a connection to a POP server, sending commands to the server,
//. receiving responses from the server, and closing the connection. The
//. protocol implemented is the Post Office Protocol version 3, as specified
//. in RFC-1939.
//.
//. {\tt DwPopClient} is derived from {\tt DwProtocolClient}. For information
//. about inherited member functions, especially member functions for detecting
//. failures or errors, see the man page for {\tt DwProtocolClient}.
//.
//. In a POP 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 single
//. line status response, which may be followed immediately by a multi-line
//. response. The first word of the status response is either +OK or -ERR,
//. indicating the success or failure of the command. The status line may
//. also contain other information requested by the client.
//.
//. {\tt DwPopClient} 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 {\tt DwProtocolClient::LastError()} and checking for a zero
//. return value.
//.
//. To open a connection to the server, call the member function {\tt Open()}
//. with the name of the server as an argument. {\tt Open()} accepts an
//. optional argument that specifies the TCP port that the server listens to.
//. The default port is the standard POP port (110). {\tt Open()} may fail,
//. so you should check the return value to verify that it succeeded. To
//. close the connection, call the inherited member function
//. {\tt DwProtocolClient::Close()}. To check if a connection is open, call
//. the inherited member function {\tt DwProtocolClient::IsOpen()}.
//. {\tt IsOpen()} returns a boolean value that indicates whether or not
//. a call to {\tt Open()} was successful; it will not detect failure in
//. the network or a close operation by the remote host.
//.
//. For each POP command, {\tt DwPopClient} 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 first character
//. of the server's response, which will be '+' if the command succeeded
//. or '-' if the command failed.
//. 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 {\tt DwProtocolClient::LastError()} or
//. {\tt DwProtocolClient::LastFailure()}.
//.
//. After each command is sent, {\tt DwPopClient} receives the server's
//. response and remembers it. The member function {\tt StatusCode()}
//. returns the first character of the server's status response; it will be
//. '+' or '-', indicating success or failure, or zero if no response was
//. received from the server. {\tt SingleLineResponse()} returns the entire
//. single line status response from the server, including the initial
//. "+OK" or "-ERR" status word.
//.
//. The server sends a single-line response, including a status code, for all
//. POP commands. For some commands, such as when the client requests a
//. mail message, the server sends a multi-line text response immediately
//. following the single-line status response. Multi-line text responses
//. can be received in either of two ways. The simplest way is to call
//. the member function {\tt MultiLineResponse()} 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 multi-line
//. response is retrieved. An alternative method allows your program to
//. retrieve the multi-line response one line at a time as it is received.
//. To use this method, you must define a subclass of {\tt DwObserver}
//. and assign an object of that class to the {\tt DwPopClient} object
//. using the member function {\tt SetObserver()}. {\tt DwObserver} is an
//. abstract class, declared in protocol.h, that has just one pure virtual
//. member function {\tt Notify()}. After each line of the multi-line response
//. is received, {\tt DwPopClient} will call the {\tt Notify()} member
//. function of its assigned {\tt DwObserver} object. Each invocation of
//. {\tt Notify()} should call the {\tt DwPopClient} member function
//. {\tt MultiLineResponse()} 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, {\tt MultiLineResponse()} returns only the last
//. line received, not the entire multi-line response.
//=============================================================================

//+ Noentry ~DwPopClient


class DW_EXPORT DwPopClient : public DwProtocolClient {

public:

    enum {
        kCmdNoCommand=0,
        kCmdUser,
        kCmdPass,
        kCmdQuit,
        kCmdStat,
        kCmdList,
        kCmdRetr,
        kCmdDele,
        kCmdNoop,
        kCmdRset,
        kCmdApop,
        kCmdTop,
        kCmdUidl
    };

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

    virtual ~DwPopClient();

    virtual int Open(const char* aServer, DwUint16 aPort=110);
    //. Opens a TCP connection to the server {\tt aServer} at port {\tt aPort}.
    //. {\tt 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 {\tt aPort} is 110, the well-known port for POP3
    //. assigned by the Internet Assigned Numbers Authority (IANA).
    //.
    //. If the connection attempt succeeds, the server sends a response.
    //. {\tt Open()} returns the server's status code ('+' or '-'). The full
    //. response from the server can be retrieved by calling
    //. {\tt SingleLineResponse()}.
    //.
    //. If the connection attempt fails, {\tt Open()} returns 0.  To determine
    //. what error occurred when a connection attempt fails, call the inherited
    //. member function {\tt DwProtocolClient::LastError()}.  To determine if
    //. a failure also occurred, call the inherited member function
    //. {\tt DwProtocolClient::LastFailure()}.

    DwObserver* SetObserver(DwObserver* aObserver);
    //. Sets the observer object that interacts with the {\tt DwPopClient}
    //. object to retrieve a multi-line response. If an observer is set,
    //. {\tt DwPopClient} will call the observer's {\tt Notify()} method
    //. after each line of the multi-line response is received.  To remove
    //. an observer, call {\tt SetObserver()} with a NULL argument.
    //. {\tt SetObserver()} returns the previously set observer, or NULL if
    //. no observer was previously set.

    int StatusCode() const;
    //. Returns the status code received from the server in response to the
    //. last client command. The status codes in POP3 are '+', indicating
    //. success, and '-', indicating failure. If no response was received,
    //. {\tt StatusCode()} returns zero.

    const DwString& SingleLineResponse() const;
    //. Returns the single line status response last received from the server.
    //. If no response was received, perhaps because of a communications
    //. failure, {\tt SingleLineResponse()} returns an empty string.

    const DwString& MultiLineResponse() const;
    //. If no observer is set for this object, {\tt MultiLineResponse()}
    //. returns a string that comprises the entire sequence of lines
    //. received from the server.  Otherwise, if an observer {\it is} set
    //. for this object, {\tt MultiLineResponse()} returns only the most
    //. recent line received.

    int User(const char* aName);
    //. Sends the USER command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aName} is the name of the user, which is sent in the command.

    int Pass(const char* aPasswd);
    //. Sends the PASS command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aPasswd} is the password, which is sent in the command.

    int Quit();
    //. Sends the TQUIT command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.

    int Stat();
    //. Sends the STAT command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.

    int List();
    int List(int aMsg);
    //. Sends the LIST command, with or without a message number, and
    //. returns the status code received from the server.  If no response
    //. is received, the function returns zero.

    int Retr(int aMsg);
    //. Sends the RETR command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aMsg} is the message number, which is sent in the command.

    int Dele(int aMsg);
    //. Sends the DELE command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aMsg} is the message number, which is sent in the command.

    int Noop();
    //. Sends the NOOP command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.

    int Rset();
    //. Sends the RSET command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.

    int Apop(const char* aName, const char* aDigest);
    //. Sends the APOP command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aName} is the name of the user, which is sent in the command.
    //. {\tt aDigest} is the digest argument for the command.

    int Top(int aMsg, int aNumLines);
    //. Sends the TOP command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.
    //. {\tt aMsg} is the message number.  {\tt aNumLines} is the number
    //. of lines to send.

    int Uidl();
    int Uidl(int aMsg);
    //. Sends the TOP command, with or without a message number, and
    //. returns the status code received from the server.  If no response
    //. is received, the function returns zero.

    int Last();
    //. Sends the LAST command and returns the status code received from
    //. the server.  If no response is received, the function returns zero.

private:

    char*       mSendBuffer;
    char*       mRecvBuffer;
    int         mNumRecvBufferChars;
    int         mRecvBufferPos;
    int         mStatusCode;
    DwString    mSingleLineResponse;
    DwString    mMultiLineResponse;
    DwObserver* mObserver;

    int PGetLine(char** aPtr, int* aLen);
    // Tries to get one complete line of input from the socket.  On success,
    // the function sets {\tt *aPtr} to point to the beginning of the line in
    // the object's internal buffer, sets {\tt *aLen} to the length of the
    // line, including the CR LF, and returns 0.  On failure, the function
    // returns -1.

    void PGetSingleLineResponse();
    // Gets a single line of input, assigns that line {\tt mSingleLineResponse}, and
    // sets {\tt mStatusCode}.  On failure, clears {\tt mSingleLineResonse}
    // and sets {\tt mStatusCode} to -1.

    void PGetMultiLineResponse();
    // Gets a complete multiline response and assigns it to {\tt mMultiLineResponse},
    // or interacts with the {\tt DwObserver} object to deliver a multiline response
    // one line at a time.
    // If an error occurs, its sets {\tt mStatusCode} to -1.

};

#endif