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