1 /* -*- Mode: C++-C -*-
2 *
3 *
4 * Copyright 1994 Christopher B. Liebman
5 *
6 * Permission to use, copy, modify, distribute, and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and that
9 * both that copyright notice and this permission notice appear in
10 * supporting documentation, and that the name Christopher B. Liebman not
11 * be used in advertising or publicity pertaining to distribution of this
12 * software without specific, written prior permission.
13 *
14 * THIS SOFTWARE IS PROVIDED `AS-IS'. CHRISTOPHER B. LIEBMAN, DISCLAIMS
15 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
16 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17 * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL CHRISTOPHER
18 * B. LIEBMAN, BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING SPECIAL,
19 * INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, OR
20 * PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
21 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF
22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 *
25 *
26 * Author : Chris Liebman
27 * Created On : Sat Feb 5 20:08:55 1994
28 * Last Modified By: Chris Liebman
29 * Last Modified On: Sat Feb 5 22:14:20 1994
30 * Update Count : 39
31 * Status : Released.
32 *
33 * HISTORY
34 *
35 * PURPOSE
36 * Support for reading POP mailboxes.
37 */
38
39 #ifndef lint
40 static char* RCSid = "$Id: pop_check.c,v 1.5 1994/02/13 22:33:30 liebman Exp $";
41 #endif
42
43 #include "faces.h"
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <netdb.h>
48
49 FILE* input = NULL;
50 FILE* output = NULL;
51
52 static char* buffer = NULL;
53 static int buffer_size = 0;
54
55 static int
PopReadLine(stripcr)56 PopReadLine(stripcr)
57 int stripcr;
58 {
59 int c;
60 int len = 0;
61
62 if (buffer == NULL)
63 {
64 buffer_size = 1024;
65 buffer = XtMalloc(buffer_size);
66 }
67
68 while((c = fgetc(input)) != EOF)
69 {
70 if (len >= (buffer_size - 1))
71 {
72 buffer_size += 1024;
73 buffer = XtRealloc(buffer, buffer_size);
74 }
75
76 /*
77 * Dont save CR if asked.
78 */
79
80 if (!stripcr || (c != '\r'))
81 {
82 buffer[len++] = c;
83 }
84
85 if (c == '\n')
86 {
87 break;
88 }
89 }
90
91 buffer[len] = '\0';
92
93 #ifdef POP_DEBUG
94 fprintf(stderr, "PopReadLine:%d:%s", len, buffer);
95 #endif
96 return len;
97 }
98
99 static int
PopResponce()100 PopResponce()
101 {
102 /*
103 * Flush any putput.
104 */
105
106 fflush(output);
107 /*
108 * Get the responce.
109 */
110
111 if (!PopReadLine(0))
112 {
113 return 0;
114 }
115
116 if (buffer[0] != '+')
117 {
118 return 0;
119 }
120
121 return 1;
122 }
123
124 static int
PopCreate(hostname)125 PopCreate(hostname)
126 char* hostname;
127 {
128 int fd1, fd2;
129 struct sockaddr_in sa ;
130 struct hostent* hp;
131 long addr;
132
133 #ifdef POP_DEBUG
134 fprintf(stderr, "PopConnect: %s\n", hostname);
135 #endif
136
137 bzero(&sa, sizeof(sa));
138
139 /*
140 * This will allow 192.xx.x.xxx format for the hostname.
141 */
142
143 if ((addr = inet_addr(hostname)) != -1)
144 {
145 /*
146 * Is Internet addr in octet notation
147 */
148
149 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr));
150 sa.sin_family = AF_INET ;
151 }
152 else
153 {
154 /*
155 * Lookup the host.
156 */
157
158 if ((hp = gethostbyname(hostname)) == NULL)
159 {
160 fprintf(stderr, "unknown hosts: %s\n", hostname);
161 return 0;
162 }
163
164 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length);
165 sa.sin_family = hp->h_addrtype;
166 }
167
168 sa.sin_port = htons(TheFacesResources.pop_port);
169
170 fd1 = socket(sa.sin_family, SOCK_STREAM, 0);
171
172 if (fd1 < 0)
173 {
174 /*
175 * Failed to create socket.
176 */
177
178 perror("socket:");
179 return 0;
180 }
181
182 if (connect(fd1, (struct sockaddr *)&sa, sizeof(sa)) < 0)
183 {
184 /*
185 * Failed to connect.
186 */
187
188 perror("connect:");
189 close(fd1);
190 return 0;
191 }
192
193 /*
194 * Make a second file descripter.
195 */
196
197 fd2 = dup(fd1);
198
199 if (fd2 < 0)
200 {
201 perror("dup:");
202 close(fd1);
203 return 0;
204 }
205
206 /*
207 * Make stdio files from these things.
208 */
209
210 input = fdopen(fd1, "r");
211 if (input == NULL)
212 {
213 close(fd1);
214 close(fd2);
215 fprintf(stderr, "fdopen failed!\n");
216 return 0;
217 }
218
219 output = fdopen(fd2, "w");
220 if (output == NULL)
221 {
222 fclose(input);
223 close(fd2);
224 fprintf(stderr, "fdopen failed!\n");
225 return 0;
226 }
227
228 if (!PopResponce())
229 {
230 fclose(input);
231 fclose(output);
232 fprintf(stderr, "failed to read greeting!\n");
233 return 0;
234 }
235
236 return 1;
237 }
238
239 static int
PopQuit()240 PopQuit()
241 {
242 #ifdef POP_DEBUG
243 fprintf(stderr, "PopQuit()\n");
244 #endif
245 fprintf(output, "QUIT\r\n");
246
247 if (!PopResponce())
248 {
249 fprintf(stderr, "PopQuit: failed: <%s>\n", buffer);
250 }
251
252 fclose(input);
253 fclose(output);
254
255 return 1;
256 }
257
258
259 static int
PopStat(nmsgs,nbytes)260 PopStat(nmsgs, nbytes)
261 int* nmsgs;
262 int* nbytes;
263 {
264 *nmsgs = 0;
265 *nbytes = 0;
266
267 #ifdef POP_DEBUG
268 fprintf(stderr, "PopStat()\n");
269 #endif
270 fprintf(output, "STAT\r\n");
271
272 if (!PopResponce())
273 {
274 return 0;
275 }
276
277 sscanf(buffer, "+OK %d %d", nmsgs, nbytes);
278
279 return 1;
280 }
281
282 static int
PopUser(user)283 PopUser(user)
284 char* user;
285 {
286 #ifdef POP_DEBUG
287 fprintf(stderr, "PopUser(%s)\n", user);
288 #endif
289 fprintf(output, "USER %s\r\n", user);
290
291 if (!PopResponce())
292 {
293 return 0;
294 }
295
296 return 1;
297 }
298
299 static int
PopPass(pass)300 PopPass(pass)
301 char* pass;
302 {
303 #ifdef POP_DEBUG
304 fprintf(stderr, "PopPass(%s)\n", pass);
305 #endif
306 fprintf(output, "PASS %s\r\n", pass);
307
308 if (!PopResponce())
309 {
310 return 0;
311 }
312
313 return 1;
314 }
315
316
317 static int
PopList(item,size)318 PopList(item, size)
319 int item;
320 int *size;
321 {
322 int ret_item;
323
324 #ifdef POP_DEBUG
325 fprintf(stderr, "PopList(%d)\n", item);
326 #endif
327 fprintf(output, "LIST %d\r\n", item);
328
329 if (!PopResponce())
330 {
331 return 0;
332 }
333
334 sscanf(buffer, "+OK %d %d", &ret_item, size);
335
336 if (item != ret_item)
337 {
338 return 0;
339 }
340
341 return 1;
342 }
343
344 static char*
PopRetr(item)345 PopRetr(item)
346 int item;
347 {
348 int msg_size;
349 int got = 0;
350 int len;
351 char* msg;
352
353 if (!PopList(item, &msg_size))
354 {
355 return NULL;
356 }
357
358 msg = XtMalloc(msg_size+1);
359 msg[0] = '\0';
360
361 #ifdef POP_DEBUG
362 fprintf(stderr, "PopRetr(%d)\n", item);
363 #endif
364
365 fprintf(output, "RETR %d\r\n", item);
366
367 if (!PopResponce())
368 {
369 return NULL;
370 }
371
372 for(len = PopReadLine(1);
373 strcmp(buffer, ".\n") != 0;
374 len = PopReadLine(1))
375 {
376 strcpy(&msg[got], buffer);
377 got += len;
378 }
379
380 #ifdef POP_DEBUG
381 fprintf(stderr, "got: %d\n", got);
382 #endif
383
384 return msg;
385 }
386
387 int
PopAuthInfo(user,pass)388 PopAuthInfo(user, pass)
389 char** user;
390 char** pass;
391 {
392 FILE* auth;
393 FILE* saved_in;
394 int len;
395 char** data;
396
397 auth = fopen(TheFacesResources.pop_auth_file, "r");
398
399 if (auth == NULL)
400 {
401 return 0;
402 }
403
404 saved_in = input;
405 input = auth;
406
407 len = PopReadLine();
408
409 input = saved_in;
410 fclose(auth);
411
412 data = StringParse(buffer, " \t\n");
413
414 if (!data[0] || !data[1] || data[2])
415 {
416 bzero(buffer, buffer_size);
417 XtFree((char*)data);
418 return 0;
419 }
420
421 *user = XtNewString(data[0]);
422 *pass = XtNewString(data[1]);
423 bzero(buffer, buffer_size);
424 XtFree((char*)data);
425
426 return 1;
427 }
428
429 void
PopCheck()430 PopCheck()
431 {
432 MailHeader* headers;
433 char* user;
434 char* pass;
435 int mbox_count;
436 int mbox_size;
437 int i;
438
439 /*
440 * Read in the pop login and passwd.
441 */
442
443 if (!PopAuthInfo(&user, &pass))
444 {
445 return;
446 }
447
448 if (!PopCreate(TheFacesResources.pop_host))
449 {
450 bzero(user, strlen(user));
451 bzero(pass, strlen(pass));
452 XtFree(user);
453 XtFree(pass);
454 return;
455 }
456
457 if (!PopUser(user))
458 {
459 bzero(user, strlen(user));
460 bzero(pass, strlen(pass));
461 XtFree(user);
462 XtFree(pass);
463 PopQuit();
464 return;
465 }
466
467 if (!PopPass(pass))
468 {
469 bzero(user, strlen(user));
470 bzero(pass, strlen(pass));
471 XtFree(user);
472 XtFree(pass);
473 PopQuit();
474 return;
475 }
476
477 bzero(user, strlen(user));
478 bzero(pass, strlen(pass));
479 XtFree(user);
480 XtFree(pass);
481
482 if (!PopStat(&mbox_count, &mbox_size))
483 {
484 PopQuit();
485 return;
486 }
487
488 for(i = 0; i < mbox_count; ++i)
489 {
490 char* msg;
491
492 msg = PopRetr(i+1);
493
494 if (!msg)
495 {
496 PopQuit();
497 return;
498 }
499
500 /*
501 * Stuff the message as unread mail data.
502 */
503
504 MailFileUnReadString(msg);
505
506 /*
507 * Parse headers!
508 */
509
510 headers = MailHeaderListRead();
511
512 /*
513 * Create item.
514 */
515
516 MailItemCreate(headers);
517
518 XtFree(msg);
519 }
520
521 PopQuit();
522 }
523