ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/IMAPHandler/IMAPHandler.cpp
Revision: 108
Committed: 2003-03-31T20:49:38-08:00 (19 years, 8 months ago) by douglas
File size: 8047 byte(s)
Log Message:
Initial revision

File Contents

# User Rev Content
1 douglas 108 // IMAP Handler
2     //
3     // Douglas Thrift
4     //
5     // IMAPHandler.cpp
6    
7     #include "IMAPHandler.h"
8    
9     IMAPHandler::IMAPHandler(const string& server, bool tls)
10     {
11     this->tls = tls;
12     buffer = new char[BUFSIZ + 1];
13    
14     #ifdef _WIN32
15     if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
16     {
17     error(program + ": WSAStartup");
18     exit(1);
19     }
20     #endif // _WIN32
21    
22     if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
23     {
24     error(program + ": Socket");
25     exit(1);
26     }
27    
28     sockaddr_in address;
29     hostent* host;
30    
31     address.sin_family = AF_INET;
32    
33     if ((host = gethostbyname(server.c_str())) == NULL)
34     {
35     error(program + ": Host: " + server, true);
36     exit(1);
37     }
38    
39     address.sin_addr = *((in_addr*)*host->h_addr_list);
40     address.sin_port = htons(tls ? 993 : 143);
41    
42     if (connect(sock, (sockaddr*)&address, sizeof(sockaddr_in)) ==
43     SOCKET_ERROR)
44     {
45     error(program + ": Connect");
46     exit(1);
47     }
48    
49     if (tls)
50     {
51     SSL_load_error_strings();
52     SSL_library_init();
53    
54     char* seed = new char[BUFSIZ + 1];
55     time_t moment = time(NULL);
56     sprintf(seed, "froofy%sfoofoo", ctime(&moment));
57    
58     RAND_add(seed, strlen(seed), 0.007456);
59    
60     delete [] seed;
61    
62     ctx = SSL_CTX_new(TLSv1_client_method());
63     if (ctx == NULL)
64     {
65     cerr << program << ": SSL CTX New: " <<
66     ERR_reason_error_string(ERR_get_error()) << "\n";
67     exit(1);
68     }
69    
70     ssl = SSL_new(ctx);
71    
72     if (SSL_set_fd(ssl, sock) == 0)
73     {
74     cerr << program << ": SSL Set FD: " <<
75     ERR_reason_error_string(ERR_get_error()) << "\n";
76     exit(1);
77     }
78    
79     if (int code = SSL_connect(ssl) <= 0)
80     {
81     error(program + ": SSL Connect", code);
82     exit(1);
83     }
84     }
85    
86     string input = getline();
87     if (debug) cerr << input << "\n";
88     }
89    
90     IMAPHandler::~IMAPHandler()
91     {
92     if (tls)
93     {
94     SSL_shutdown(ssl);
95     SSL_free(ssl);
96     SSL_CTX_free(ctx);
97     }
98    
99     closesocket(sock);
100    
101     delete [] buffer;
102    
103     #ifdef _WIN32
104     WSACleanup();
105     #endif // _WIN32
106     }
107    
108     string IMAPHandler::starttls()
109     {
110     string answer = imap("STARTTLS");
111    
112     if (success)
113     {
114     //
115     }
116    
117     return answer;
118     }
119    
120     string IMAPHandler::imap(const string& imap)
121     {
122     string result;
123    
124     //
125    
126     return result;
127     }
128    
129     void IMAPHandler::putline(const string line)
130     {
131     sprintf(buffer, "%s\r\n", line.c_str());
132    
133     if (tls)
134     {
135     if (int code = SSL_write(ssl, buffer, strlen(buffer)) <= 0)
136     {
137     error(program + ": SSL Write", code);
138     exit(1);
139     }
140     }
141     else
142     {
143     if (send(sock, buffer, strlen(buffer), 0) == SOCKET_ERROR)
144     {
145     error(program + ": Send");
146     exit(1);
147     }
148     }
149     }
150    
151     string IMAPHandler::getline()
152     {
153     string line;
154     char byte;
155    
156     do
157     {
158     if (tls)
159     {
160     if (int code = SSL_read(ssl, &byte, 1) <= 0)
161     {
162     error(program + ": SSL Read", code);
163     exit(1);
164     }
165     }
166     else
167     {
168     if (recv(sock, &byte, 1, 0) == SOCKET_ERROR)
169     {
170     error(program + ": Recv");
171     exit(1);
172     }
173     }
174    
175     if (byte != '\r' && byte != '\n')
176     {
177     line += byte;
178     }
179     }
180     while (byte != '\n');
181    
182     return line;
183     }
184    
185     void IMAPHandler::error(const string& prefix, bool host)
186     {
187     #ifdef _WIN32
188     string error;
189    
190     switch (WSAGetLastError())
191     {
192     case WSAEACCES:
193     error = "Permission denied.";
194     break;
195     case WSAEADDRINUSE:
196     error = "Address already in use.";
197     break;
198     case WSAEADDRNOTAVAIL:
199     error = "Cannot assign requested address.";
200     break;
201     case WSAEAFNOSUPPORT:
202     error = "Address family not supported by protocol family.";
203     break;
204     case WSAEALREADY:
205     error = "Operation already in progress.";
206     break;
207     case WSAECONNABORTED:
208     error = "Software caused connection abort.";
209     break;
210     case WSAECONNREFUSED:
211     error = "Connection refused.";
212     break;
213     case WSAECONNRESET:
214     error = "Connection reset by peer.";
215     break;
216     case WSAEDESTADDRREQ:
217     error = "Destination address required.";
218     break;
219     case WSAEFAULT:
220     error = "Bad address.";
221     break;
222     case WSAEHOSTDOWN:
223     error = "Host is down.";
224     break;
225     case WSAEHOSTUNREACH:
226     error = "No route to host.";
227     break;
228     case WSAEINPROGRESS:
229     error = "Operation now in progress.";
230     break;
231     case WSAEINTR:
232     error = "Interrupted function call.";
233     break;
234     case WSAEINVAL:
235     error = "Invalid argument.";
236     break;
237     case WSAEISCONN:
238     error = "Socket is already connected.";
239     break;
240     case WSAEMFILE:
241     error = "Too many open files.";
242     break;
243     case WSAEMSGSIZE:
244     error = "Message too long.";
245     break;
246     case WSAENETDOWN:
247     error = "Network is down.";
248     break;
249     case WSAENETRESET:
250     error = "Network dropped connection on reset.";
251     break;
252     case WSAENETUNREACH:
253     error = "Network is unreachable.";
254     break;
255     case WSAENOBUFS:
256     error = "No buffer space available.";
257     break;
258     case WSAENOPROTOOPT:
259     error = "Bad protocol option.";
260     break;
261     case WSAENOTCONN:
262     error = "Socket is not connected.";
263     break;
264     case WSAENOTSOCK:
265     error = "Socket operation on non-socket.";
266     break;
267     case WSAEOPNOTSUPP:
268     error = "Operation not supported.";
269     break;
270     case WSAEPFNOSUPPORT:
271     error = "Protocol family not supported.";
272     break;
273     case WSAEPROCLIM:
274     error = "Too many processes.";
275     break;
276     case WSAEPROTONOSUPPORT:
277     error = "Protocol not supported.";
278     break;
279     case WSAEPROTOTYPE:
280     error = "Protocol wrong type for socket.";
281     break;
282     case WSAESHUTDOWN:
283     error = "Cannot send after socket shutdown.";
284     break;
285     case WSAESOCKTNOSUPPORT:
286     error = "Socket type not supported.";
287     break;
288     case WSAETIMEDOUT:
289     error = "Connection timed out.";
290     break;
291     case WSATYPE_NOT_FOUND:
292     error = "Class type not found.";
293     break;
294     case WSAEWOULDBLOCK:
295     error = "Resource temporarily unavailable.";
296     break;
297     case WSAHOST_NOT_FOUND:
298     error = "Host not found.";
299     break;
300     case WSA_INVALID_HANDLE:
301     error = "Specified event object handle is invalid.";
302     break;
303     case WSA_INVALID_PARAMETER:
304     error = "One or more parameters are invalid.";
305     break;
306     // case WSAINVALIDPROCTABLE:
307     // error = "Invalid procedure table from service provider.";
308     // break;
309     // case WSAINVALIDPROVIDER:
310     // error = "Invalid service provider version number.";
311     // break;
312     case WSA_IO_INCOMPLETE:
313     error = "Overlapped I/O event object not in signaled state.";
314     break;
315     case WSA_IO_PENDING:
316     error = "Overlapped operations will complete later.";
317     break;
318     case WSA_NOT_ENOUGH_MEMORY:
319     error = "Insufficient memory available.";
320     break;
321     case WSANOTINITIALISED:
322     error = "Successful WSAStartup not yet performed.";
323     break;
324     case WSANO_DATA:
325     error = "Valid name, no data record of requested type.";
326     break;
327     case WSANO_RECOVERY:
328     error = "This is a non-recoverable error.";
329     break;
330     // case WSAPROVIDERFAILEDINIT:
331     // error = "Unable to initialize a service provider.";
332     // break;
333     case WSASYSCALLFAILURE:
334     error = "System call failure.";
335     break;
336     case WSASYSNOTREADY:
337     error = "Network subsystem is unavailable.";
338     break;
339     case WSATRY_AGAIN:
340     error = "Non-authoritative host not found.";
341     break;
342     case WSAVERNOTSUPPORTED:
343     error = "WINSOCK.DLL version out of range.";
344     break;
345     case WSAEDISCON:
346     error = "Graceful shutdown in progress.";
347     break;
348     case WSA_OPERATION_ABORTED:
349     error = "Overlapped operation aborted.";
350     break;
351     default:
352     error = "Unknown error.";
353     break;
354     }
355    
356     cerr << prefix << ": " << error << "\n";
357     #else
358     if (host)
359     {
360     herror(prefix.c_str());
361     }
362     else
363     {
364     perror(prefix.c_str());
365     }
366     #endif // _WIN32
367     }
368    
369     void IMAPHandler::error(const string& prefix, int code)
370     {
371     string error;
372    
373     switch (SSL_get_error(ssl, code))
374     {
375     case SSL_ERROR_NONE:
376     error = "The TLS/SSL I/O operation completed.";
377     break;
378     case SSL_ERROR_ZERO_RETURN:
379     error = "The TLS/SSL connection has been closed.";
380     break;
381     case SSL_ERROR_WANT_READ:
382     case SSL_ERROR_WANT_WRITE:
383     case SSL_ERROR_WANT_CONNECT:
384     // case SSL_ERROR_WANT_ACCEPT:
385     case SSL_ERROR_WANT_X509_LOOKUP:
386     error = "The operation did not complete.";
387     break;
388     case SSL_ERROR_SYSCALL:
389     if (int err = ERR_get_error() != 0)
390     {
391     error = ERR_reason_error_string(err);
392     }
393     else
394     {
395     switch (code)
396     {
397     case 0:
398     error = "An EOF was observed that violates the protocol.";
399     break;
400     case -1:
401     this->error(prefix);
402     return;
403     default:
404     error = "Unknown error.";
405     break;
406     }
407     }
408     break;
409     case SSL_ERROR_SSL:
410     error = ERR_reason_error_string(ERR_get_error());
411     break;
412     default:
413     error = "Unknown error.";
414     break;
415     }
416    
417     cerr << prefix << ": " << error << "\n";
418     }