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 (22 years, 2 months ago) by douglas
File size: 8047 byte(s)
Log Message:
Initial revision

File Contents

# Content
1 // 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 }