ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/IMAPHandler.cpp
(Generate patch)

Comparing trunk/WinXPFAQPoll/IMAPHandler.cpp (file contents):
Revision 104 by douglas, 2003-03-31T20:18:26-08:00 vs.
Revision 107 by douglas, 2003-03-31T20:39:56-08:00

# Line 51 | Line 51
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 < #define PATH_SEPARATOR "\\"
61 < #define ENV_SEPARATOR ';'
62 < #else
63 < #define PATH_SEPARATOR "/"
64 < #define ENV_SEPARATOR ':'
65 < #endif
60 >        if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
61 >        {
62 >                error(program + ": WSAStartup");
63 >                exit(1);
64 >        }
65 > #endif // _WIN32
66  
67 < IMAPHandler::IMAPHandler(const string& host, unsigned port)
68 < {
69 <        setJarPath();
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 <        options[0].optionString = jarPath;
79 <        memset(&vm_args, 0, sizeof (vm_args));
80 <        vm_args.version = JNI_VERSION_1_2;
81 <        vm_args.nOptions = 1;
82 <        vm_args.options = options;
78 >        if ((host = gethostbyname(server.c_str())) == NULL)
79 >        {
80 >                error(program + ": Host: " + server, true);
81 >                exit(1);
82 >        }
83  
84 <        status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
84 >        address.sin_addr = *((in_addr*)*host->h_addr_list);
85 >        address.sin_port = htons(tls ? 993 : 143);
86  
87 <        if (status != JNI_ERR)
87 >        if (connect(sock, (sockaddr*)&address, sizeof(sockaddr_in)) ==
88 >                SOCKET_ERROR)
89          {
90 <                cls = env->FindClass("IMAPHandler");
90 >                error(program + ": Connect");
91 >                exit(1);
92 >        }
93  
94 <                if (cls != 0)
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 <                        mid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;IZ)V");
110 >                        cerr << program << ": SSL CTX New: " <<
111 >                                ERR_reason_error_string(ERR_get_error()) << "\n";
112 >                        exit(1);
113 >                }
114  
115 <                        if (mid != 0)
83 <                        {
84 <                                jstring hostJ = env->NewStringUTF(host.c_str());
85 <                                jint portJ = port;
86 < #ifdef _DEBUG
87 <                                jboolean debugJ = debug;
88 < #else
89 <                                jboolean debugJ = false;
90 < #endif
115 >                ssl = SSL_new(ctx);
116  
117 <                                obj = env->NewObject(cls, mid, hostJ, portJ, debugJ);
118 <                        }
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 (status != JNI_ERR)
137 >        if (tls)
138          {
139 <                jvm->DestroyJavaVM();
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 < bool IMAPHandler::successful()
153 > string IMAPHandler::starttls()
154   {
155 <        bool answer;
155 >        string answer = imap("STARTTLS");
156  
157 <        if (cls != 0)
157 >        if (success)
158          {
159 <                mid = env->GetMethodID(cls, "successful", "()Z");
113 <
114 <                if (mid != 0)
115 <                {
116 <                        jboolean answerJ = env->CallBooleanMethod(obj, mid);
117 <
118 <                        answer = answerJ != 0;
119 <                }
159 >                //
160          }
161  
162          return answer;
163   }
164  
165 < void IMAPHandler::setJarPath()
165 > string IMAPHandler::imap(const string& imap)
166   {
167 <        const string jarFile = "IMAPHandler.jar";
168 <        string jarFilePath = jarFile;
167 >        string result;
168 >
169 >        //
170 >
171 >        return result;
172 > }
173  
174 <        ifstream fin(jarFilePath.c_str());
175 <        if (!fin.is_open())
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 <                unsigned end = program.rfind(PATH_SEPARATOR);
134 <                if (end != string::npos)
188 >                if (send(sock, buffer, strlen(buffer), 0) == SOCKET_ERROR)
189                  {
190 <                        string path = program.substr(0, end);
190 >                        error(program + ": Send");
191 >                        exit(1);
192 >                }
193 >        }
194 > }
195  
196 <                        jarFilePath = path + PATH_SEPARATOR + jarFile;
196 > string IMAPHandler::getline()
197 > {
198 >        string line;
199 >        char byte;
200  
201 <                        fin.open(jarFilePath.c_str());
202 <                        if (!fin.is_open())
201 >        do
202 >        {
203 >                if (tls)
204 >                {
205 >                        if (int code = SSL_read(ssl, &byte, 1) <= 0)
206                          {
207 <                                cerr << program << ": Could not find required file: "
144 <                                        << jarFile << "\n";
207 >                                error(program + ": SSL Read", code);
208                                  exit(1);
209                          }
147                        else
148                        {
149                                fin.close();
150                        }
210                  }
211                  else
212                  {
213 <                        string envPath = getenv("PATH");
155 <
156 <                        if (debug) cerr << "envPath = " << envPath << "\n";
157 <
158 <                        unsigned begin = 0;
159 <                        do
213 >                        if (recv(sock, &byte, 1, 0) == SOCKET_ERROR)
214                          {
215 <                                unsigned end = envPath.find(ENV_SEPARATOR, begin);
162 <                                string path = envPath.substr(begin, end);
163 <
164 <                                if (debug) cerr << "path = " << path << "\n";
165 <
166 <                                jarFilePath = path + PATH_SEPARATOR + jarFile;
167 <
168 <                                fin.open(jarFilePath.c_str());
169 <                                if (fin.is_open())
170 <                                {
171 <                                        fin.close();
172 <                                        break;
173 <                                }
174 <
175 <                                begin = end != string::npos ? end + 1 : string::npos;
176 <                        }
177 <                        while (begin < envPath.length());
178 <
179 <                        if (begin == string::npos)
180 <                        {
181 <                                cerr << program << ": Could not find required file: "
182 <                                        << jarFile << "\n";
215 >                                error(program + ": Recv");
216                                  exit(1);
217                          }
218                  }
186        }
187        else
188        {
189                fin.close();
190        }
191
192        string jarPath = "-Djava.class.path=" + jarFilePath;
193
194        this->jarPath = new char[jarPath.length()];
195        strcpy(this->jarPath, jarPath.c_str());
196 }
219  
220 < string IMAPHandler::imap(char* imap)
199 < {
200 <        string result;
201 <
202 <        if (cls != 0)
203 <        {
204 <                mid = env->GetMethodID(cls, imap, "()Ljava/lang/String;");
205 <
206 <                if (mid != 0)
220 >                if (byte != '\r' && byte != '\n')
221                  {
222 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid);
209 <
210 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
211 <                        result = resultC;
212 <                        env->ReleaseStringUTFChars(resultJ, resultC);
222 >                        line += byte;
223                  }
224          }
225 +        while (byte != '\n');
226  
227 <        return result;
227 >        return line;
228   }
229  
230 < string IMAPHandler::imap(char* imap, const string& args)
230 > void IMAPHandler::error(const string& prefix, bool host)
231   {
232 <        string result;
232 > #ifdef _WIN32
233 >        string error;
234  
235 <        if (cls != 0)
235 >        switch (WSAGetLastError())
236          {
237 <                mid = env->GetMethodID(cls, imap,
238 <                        "(Ljava/lang/String;)Ljava/lang/String;");
239 <
240 <                if (mid != 0)
241 <                {
242 <                        jstring argsJ = env->NewStringUTF(args.c_str());
243 <
244 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid, argsJ);
245 <
246 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
247 <                        result = resultC;
248 <                        env->ReleaseStringUTFChars(resultJ, resultC);
249 <                }
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 <        return result;
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 < string IMAPHandler::imap(char* imap, const string& args, const string& message)
414 > void IMAPHandler::error(const string& prefix, int code)
415   {
416 <        string result;
416 >        string error;
417  
418 <        if (cls != 0)
418 >        switch (SSL_get_error(ssl, code))
419          {
420 <                mid = env->GetMethodID(cls, imap,
421 <                        "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
422 <
423 <                if (mid != 0)
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 <                        jstring argsJ = env->NewStringUTF(args.c_str());
255 <                        jstring messageJ = env->NewStringUTF(message.c_str());
256 <
257 <                        jstring resultJ = (jstring)env->CallObjectMethod(obj, mid, argsJ,
258 <                                messageJ);
259 <
260 <                        const char* resultC = env->GetStringUTFChars(resultJ, 0);
261 <                        result = resultC;
262 <                        env->ReleaseStringUTFChars(resultJ, resultC);
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 <        return result;
462 >        cerr << prefix << ": " << error << "\n";
463   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines