ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/IMAPHandler.cpp
Revision: 107
Committed: 2003-03-31T20:39:56-08:00 (22 years, 2 months ago) by douglas
File size: 10508 byte(s)
Log Message:
Oops, I guess I need to finish fixing IMAPHandler first.

File Contents

# Content
1 /* ============================================================================
2 * Douglas Thrift's Web Contact License
3 *
4 * Copyright (C) 2002, Douglas Thrift. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment:
18 *
19 * "This product includes software developed by Douglas Thrift
20 * (http://computers.douglasthrift.net/webcontact.html)."
21 *
22 * Alternately, this acknowledgment may appear in the software itself, if
23 * and wherever such third-party acknowledgments normally appear.
24 *
25 * 4. The names "Douglas Thrift" and "Douglas Thrift's Web Contact" must not be
26 * used to endorse or promote products derived from this software without
27 * specific prior written permission. For written permission, please visit
28 * http://www.douglasthrift.net/contact.html for contact information.
29 *
30 * 5. Products derived from this software may not be called "Douglas Thrift's
31 * Web Contact", nor may "Douglas Thrift's Web Contact" appear in their
32 * name, without prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
40 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
43 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 * ============================================================================
45 */
46 // Windows XP FAQ Poll
47 //
48 // Douglas Thrift
49 //
50 // IMAPHandler.cpp
51
52 #include "IMAPHandler.h"
53
54 IMAPHandler::IMAPHandler(const string& server, bool tls)
55 {
56 this->tls = tls;
57 buffer = new char[BUFSIZ + 1];
58
59 #ifdef _WIN32
60 if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
61 {
62 error(program + ": WSAStartup");
63 exit(1);
64 }
65 #endif // _WIN32
66
67 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
68 {
69 error(program + ": Socket");
70 exit(1);
71 }
72
73 sockaddr_in address;
74 hostent* host;
75
76 address.sin_family = AF_INET;
77
78 if ((host = gethostbyname(server.c_str())) == NULL)
79 {
80 error(program + ": Host: " + server, true);
81 exit(1);
82 }
83
84 address.sin_addr = *((in_addr*)*host->h_addr_list);
85 address.sin_port = htons(tls ? 993 : 143);
86
87 if (connect(sock, (sockaddr*)&address, sizeof(sockaddr_in)) ==
88 SOCKET_ERROR)
89 {
90 error(program + ": Connect");
91 exit(1);
92 }
93
94 if (tls)
95 {
96 SSL_load_error_strings();
97 SSL_library_init();
98
99 char* seed = new char[BUFSIZ + 1];
100 time_t moment = time(NULL);
101 sprintf(seed, "froofy%sfoofoo", ctime(&moment));
102
103 RAND_add(seed, strlen(seed), 0.007456);
104
105 delete [] seed;
106
107 ctx = SSL_CTX_new(TLSv1_client_method());
108 if (ctx == NULL)
109 {
110 cerr << program << ": SSL CTX New: " <<
111 ERR_reason_error_string(ERR_get_error()) << "\n";
112 exit(1);
113 }
114
115 ssl = SSL_new(ctx);
116
117 if (SSL_set_fd(ssl, sock) == 0)
118 {
119 cerr << program << ": SSL Set FD: " <<
120 ERR_reason_error_string(ERR_get_error()) << "\n";
121 exit(1);
122 }
123
124 if (int code = SSL_connect(ssl) <= 0)
125 {
126 error(program + ": SSL Connect", code);
127 exit(1);
128 }
129 }
130
131 string input = getline();
132 if (debug) cerr << input << "\n";
133 }
134
135 IMAPHandler::~IMAPHandler()
136 {
137 if (tls)
138 {
139 SSL_shutdown(ssl);
140 SSL_free(ssl);
141 SSL_CTX_free(ctx);
142 }
143
144 closesocket(sock);
145
146 delete [] buffer;
147
148 #ifdef _WIN32
149 WSACleanup();
150 #endif // _WIN32
151 }
152
153 string IMAPHandler::starttls()
154 {
155 string answer = imap("STARTTLS");
156
157 if (success)
158 {
159 //
160 }
161
162 return answer;
163 }
164
165 string IMAPHandler::imap(const string& imap)
166 {
167 string result;
168
169 //
170
171 return result;
172 }
173
174 void IMAPHandler::putline(const string line)
175 {
176 sprintf(buffer, "%s\r\n", line.c_str());
177
178 if (tls)
179 {
180 if (int code = SSL_write(ssl, buffer, strlen(buffer)) <= 0)
181 {
182 error(program + ": SSL Write", code);
183 exit(1);
184 }
185 }
186 else
187 {
188 if (send(sock, buffer, strlen(buffer), 0) == SOCKET_ERROR)
189 {
190 error(program + ": Send");
191 exit(1);
192 }
193 }
194 }
195
196 string IMAPHandler::getline()
197 {
198 string line;
199 char byte;
200
201 do
202 {
203 if (tls)
204 {
205 if (int code = SSL_read(ssl, &byte, 1) <= 0)
206 {
207 error(program + ": SSL Read", code);
208 exit(1);
209 }
210 }
211 else
212 {
213 if (recv(sock, &byte, 1, 0) == SOCKET_ERROR)
214 {
215 error(program + ": Recv");
216 exit(1);
217 }
218 }
219
220 if (byte != '\r' && byte != '\n')
221 {
222 line += byte;
223 }
224 }
225 while (byte != '\n');
226
227 return line;
228 }
229
230 void IMAPHandler::error(const string& prefix, bool host)
231 {
232 #ifdef _WIN32
233 string error;
234
235 switch (WSAGetLastError())
236 {
237 case WSAEACCES:
238 error = "Permission denied.";
239 break;
240 case WSAEADDRINUSE:
241 error = "Address already in use.";
242 break;
243 case WSAEADDRNOTAVAIL:
244 error = "Cannot assign requested address.";
245 break;
246 case WSAEAFNOSUPPORT:
247 error = "Address family not supported by protocol family.";
248 break;
249 case WSAEALREADY:
250 error = "Operation already in progress.";
251 break;
252 case WSAECONNABORTED:
253 error = "Software caused connection abort.";
254 break;
255 case WSAECONNREFUSED:
256 error = "Connection refused.";
257 break;
258 case WSAECONNRESET:
259 error = "Connection reset by peer.";
260 break;
261 case WSAEDESTADDRREQ:
262 error = "Destination address required.";
263 break;
264 case WSAEFAULT:
265 error = "Bad address.";
266 break;
267 case WSAEHOSTDOWN:
268 error = "Host is down.";
269 break;
270 case WSAEHOSTUNREACH:
271 error = "No route to host.";
272 break;
273 case WSAEINPROGRESS:
274 error = "Operation now in progress.";
275 break;
276 case WSAEINTR:
277 error = "Interrupted function call.";
278 break;
279 case WSAEINVAL:
280 error = "Invalid argument.";
281 break;
282 case WSAEISCONN:
283 error = "Socket is already connected.";
284 break;
285 case WSAEMFILE:
286 error = "Too many open files.";
287 break;
288 case WSAEMSGSIZE:
289 error = "Message too long.";
290 break;
291 case WSAENETDOWN:
292 error = "Network is down.";
293 break;
294 case WSAENETRESET:
295 error = "Network dropped connection on reset.";
296 break;
297 case WSAENETUNREACH:
298 error = "Network is unreachable.";
299 break;
300 case WSAENOBUFS:
301 error = "No buffer space available.";
302 break;
303 case WSAENOPROTOOPT:
304 error = "Bad protocol option.";
305 break;
306 case WSAENOTCONN:
307 error = "Socket is not connected.";
308 break;
309 case WSAENOTSOCK:
310 error = "Socket operation on non-socket.";
311 break;
312 case WSAEOPNOTSUPP:
313 error = "Operation not supported.";
314 break;
315 case WSAEPFNOSUPPORT:
316 error = "Protocol family not supported.";
317 break;
318 case WSAEPROCLIM:
319 error = "Too many processes.";
320 break;
321 case WSAEPROTONOSUPPORT:
322 error = "Protocol not supported.";
323 break;
324 case WSAEPROTOTYPE:
325 error = "Protocol wrong type for socket.";
326 break;
327 case WSAESHUTDOWN:
328 error = "Cannot send after socket shutdown.";
329 break;
330 case WSAESOCKTNOSUPPORT:
331 error = "Socket type not supported.";
332 break;
333 case WSAETIMEDOUT:
334 error = "Connection timed out.";
335 break;
336 case WSATYPE_NOT_FOUND:
337 error = "Class type not found.";
338 break;
339 case WSAEWOULDBLOCK:
340 error = "Resource temporarily unavailable.";
341 break;
342 case WSAHOST_NOT_FOUND:
343 error = "Host not found.";
344 break;
345 case WSA_INVALID_HANDLE:
346 error = "Specified event object handle is invalid.";
347 break;
348 case WSA_INVALID_PARAMETER:
349 error = "One or more parameters are invalid.";
350 break;
351 // case WSAINVALIDPROCTABLE:
352 // error = "Invalid procedure table from service provider.";
353 // break;
354 // case WSAINVALIDPROVIDER:
355 // error = "Invalid service provider version number.";
356 // break;
357 case WSA_IO_INCOMPLETE:
358 error = "Overlapped I/O event object not in signaled state.";
359 break;
360 case WSA_IO_PENDING:
361 error = "Overlapped operations will complete later.";
362 break;
363 case WSA_NOT_ENOUGH_MEMORY:
364 error = "Insufficient memory available.";
365 break;
366 case WSANOTINITIALISED:
367 error = "Successful WSAStartup not yet performed.";
368 break;
369 case WSANO_DATA:
370 error = "Valid name, no data record of requested type.";
371 break;
372 case WSANO_RECOVERY:
373 error = "This is a non-recoverable error.";
374 break;
375 // case WSAPROVIDERFAILEDINIT:
376 // error = "Unable to initialize a service provider.";
377 // break;
378 case WSASYSCALLFAILURE:
379 error = "System call failure.";
380 break;
381 case WSASYSNOTREADY:
382 error = "Network subsystem is unavailable.";
383 break;
384 case WSATRY_AGAIN:
385 error = "Non-authoritative host not found.";
386 break;
387 case WSAVERNOTSUPPORTED:
388 error = "WINSOCK.DLL version out of range.";
389 break;
390 case WSAEDISCON:
391 error = "Graceful shutdown in progress.";
392 break;
393 case WSA_OPERATION_ABORTED:
394 error = "Overlapped operation aborted.";
395 break;
396 default:
397 error = "Unknown error.";
398 break;
399 }
400
401 cerr << prefix << ": " << error << "\n";
402 #else
403 if (host)
404 {
405 herror(prefix.c_str());
406 }
407 else
408 {
409 perror(prefix.c_str());
410 }
411 #endif // _WIN32
412 }
413
414 void IMAPHandler::error(const string& prefix, int code)
415 {
416 string error;
417
418 switch (SSL_get_error(ssl, code))
419 {
420 case SSL_ERROR_NONE:
421 error = "The TLS/SSL I/O operation completed.";
422 break;
423 case SSL_ERROR_ZERO_RETURN:
424 error = "The TLS/SSL connection has been closed.";
425 break;
426 case SSL_ERROR_WANT_READ:
427 case SSL_ERROR_WANT_WRITE:
428 case SSL_ERROR_WANT_CONNECT:
429 // case SSL_ERROR_WANT_ACCEPT:
430 case SSL_ERROR_WANT_X509_LOOKUP:
431 error = "The operation did not complete.";
432 break;
433 case SSL_ERROR_SYSCALL:
434 if (int err = ERR_get_error() != 0)
435 {
436 error = ERR_reason_error_string(err);
437 }
438 else
439 {
440 switch (code)
441 {
442 case 0:
443 error = "An EOF was observed that violates the protocol.";
444 break;
445 case -1:
446 this->error(prefix);
447 return;
448 default:
449 error = "Unknown error.";
450 break;
451 }
452 }
453 break;
454 case SSL_ERROR_SSL:
455 error = ERR_reason_error_string(ERR_get_error());
456 break;
457 default:
458 error = "Unknown error.";
459 break;
460 }
461
462 cerr << prefix << ": " << error << "\n";
463 }