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

# User Rev Content
1 douglas 104 /* ============================================================================
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 douglas 107 IMAPHandler::IMAPHandler(const string& server, bool tls)
55     {
56     this->tls = tls;
57     buffer = new char[BUFSIZ + 1];
58    
59 douglas 104 #ifdef _WIN32
60 douglas 107 if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
61     {
62     error(program + ": WSAStartup");
63     exit(1);
64     }
65     #endif // _WIN32
66 douglas 104
67 douglas 107 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 douglas 104
76 douglas 107 address.sin_family = AF_INET;
77 douglas 104
78 douglas 107 if ((host = gethostbyname(server.c_str())) == NULL)
79     {
80     error(program + ": Host: " + server, true);
81     exit(1);
82     }
83 douglas 104
84 douglas 107 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 douglas 104 {
90 douglas 107 error(program + ": Connect");
91     exit(1);
92     }
93 douglas 104
94 douglas 107 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 douglas 104 {
110 douglas 107 cerr << program << ": SSL CTX New: " <<
111     ERR_reason_error_string(ERR_get_error()) << "\n";
112     exit(1);
113     }
114 douglas 104
115 douglas 107 ssl = SSL_new(ctx);
116 douglas 104
117 douglas 107 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 douglas 104 }
123 douglas 107
124     if (int code = SSL_connect(ssl) <= 0)
125     {
126     error(program + ": SSL Connect", code);
127     exit(1);
128     }
129 douglas 104 }
130 douglas 107
131     string input = getline();
132     if (debug) cerr << input << "\n";
133 douglas 104 }
134    
135     IMAPHandler::~IMAPHandler()
136     {
137 douglas 107 if (tls)
138 douglas 104 {
139 douglas 107 SSL_shutdown(ssl);
140     SSL_free(ssl);
141     SSL_CTX_free(ctx);
142 douglas 104 }
143 douglas 107
144     closesocket(sock);
145    
146     delete [] buffer;
147    
148     #ifdef _WIN32
149     WSACleanup();
150     #endif // _WIN32
151 douglas 104 }
152    
153 douglas 107 string IMAPHandler::starttls()
154 douglas 104 {
155 douglas 107 string answer = imap("STARTTLS");
156 douglas 104
157 douglas 107 if (success)
158 douglas 104 {
159 douglas 107 //
160 douglas 104 }
161    
162     return answer;
163     }
164    
165 douglas 107 string IMAPHandler::imap(const string& imap)
166 douglas 104 {
167 douglas 107 string result;
168 douglas 104
169 douglas 107 //
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 douglas 104 {
180 douglas 107 if (int code = SSL_write(ssl, buffer, strlen(buffer)) <= 0)
181 douglas 104 {
182 douglas 107 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 douglas 104
196 douglas 107 string IMAPHandler::getline()
197     {
198     string line;
199     char byte;
200 douglas 104
201 douglas 107 do
202     {
203     if (tls)
204     {
205     if (int code = SSL_read(ssl, &byte, 1) <= 0)
206 douglas 104 {
207 douglas 107 error(program + ": SSL Read", code);
208 douglas 104 exit(1);
209     }
210     }
211     else
212     {
213 douglas 107 if (recv(sock, &byte, 1, 0) == SOCKET_ERROR)
214 douglas 104 {
215 douglas 107 error(program + ": Recv");
216 douglas 104 exit(1);
217     }
218     }
219    
220 douglas 107 if (byte != '\r' && byte != '\n')
221 douglas 104 {
222 douglas 107 line += byte;
223 douglas 104 }
224     }
225 douglas 107 while (byte != '\n');
226 douglas 104
227 douglas 107 return line;
228 douglas 104 }
229    
230 douglas 107 void IMAPHandler::error(const string& prefix, bool host)
231 douglas 104 {
232 douglas 107 #ifdef _WIN32
233     string error;
234 douglas 104
235 douglas 107 switch (WSAGetLastError())
236 douglas 104 {
237 douglas 107 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 douglas 104
401 douglas 107 cerr << prefix << ": " << error << "\n";
402     #else
403     if (host)
404     {
405     herror(prefix.c_str());
406 douglas 104 }
407 douglas 107 else
408     {
409     perror(prefix.c_str());
410     }
411     #endif // _WIN32
412 douglas 104 }
413    
414 douglas 107 void IMAPHandler::error(const string& prefix, int code)
415 douglas 104 {
416 douglas 107 string error;
417 douglas 104
418 douglas 107 switch (SSL_get_error(ssl, code))
419 douglas 104 {
420 douglas 107 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 douglas 104 {
436 douglas 107 error = ERR_reason_error_string(err);
437 douglas 104 }
438 douglas 107 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 douglas 104 }
461    
462 douglas 107 cerr << prefix << ": " << error << "\n";
463 douglas 104 }