Sophie

Sophie

distrib > Mandriva > current > i586 > media > contrib-release-src > by-pkgid > 90c9005a4bb57466c505c03118434402 > files > 3

popa3d-1.0.2-5mdv2009.0.src.rpm

--- Makefile	Tue Nov 26 06:38:18 2002
+++ Makefile	Mon Dec 16 20:08:43 2002
@@ -35,7 +35,7 @@
 	virtual.o \
 	auth_passwd.o auth_shadow.o auth_pam.o \
 	pop_root.o pop_auth.o pop_trans.o \
-	protocol.o database.o mailbox.o \
+	protocol.o database.o mailbox.o maildir.o \
 	misc.o \
 	md5/md5.o
 
--- database.h	Tue Nov 26 06:38:18 2002
+++ database.h	Tue Nov 26 06:32:42 2002
@@ -7,6 +7,8 @@
 
 #include "params.h"
 
+#include <sys/time.h>
+
 /*
  * Message flags.
  */
@@ -30,6 +32,10 @@
 	unsigned long data_offset;	/* Just the message itself */
 	unsigned long data_size;
 	unsigned char hash[16];		/* MD5 hash, to be used for UIDL */
+#if POP_MAILDIR
+	time_t mtime;
+	char *filename;
+#endif
 };
 
 struct db_main {
--- maildir.c	Thu Jan  1 00:00:00 1970
+++ maildir.c	Mon Dec 16 20:57:07 2002
@@ -0,0 +1,275 @@
+/*
+ * Maildir access
+ */
+
+#include "params.h"
+
+#if POP_MAILDIR
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+#include <time.h>
+
+#include "md5/md5.h"
+
+#include "misc.h"
+#include "protocol.h"
+#include "database.h"
+#include "maildir.h"
+
+int maildir_msgcmp(const void *p1, const void *p2)
+{
+        struct db_message *m1, *m2;
+
+        m1 = *(struct db_message **) p1;
+        m2 = *(struct db_message **) p2;
+
+        if (m1->mtime < m2->mtime)
+                return -1;
+        else if (m1->mtime == m2->mtime)
+                return 0;
+        else
+                return 1;
+}
+
+int maildir_close(void)
+{
+	struct db_message *msg;
+	unsigned int i;
+	char *p, *pathname;
+
+	for (i = 0; i < db.total_count; i++) {
+		msg = db.array[i];
+
+/*
+ * Move all messages from new/ to cur/ and add info
+ * to them, currently only :2,. Maybe later we'll also
+ * add S to RETR'd messages, but the database doesn't
+ * keep track of RETR's.
+ *
+ * (see info: http://cr.yp.to/proto/maildir.html)
+ */
+
+		if (strncmp(msg->filename, "new/", 4)) continue;
+		if (!(p = strchr(msg->filename, '/'))) continue;
+
+		pathname = malloc(strlen(msg->filename) + strlen(":2,") + 1);
+
+		if (!pathname) return 1;
+
+		strcpy(pathname, msg->filename);
+
+		memcpy(pathname, "cur/", 4);
+		strcat(pathname, ":2,");
+/*
+ * This method was suggested by                          
+ * Peter van Dijk <peter@dataloss.nl>                    
+ * http://www.dataloss.nl/docs/maildir/
+ */                                   
+		if (link(msg->filename, pathname)) {
+			free(pathname);
+			continue;
+		}
+
+		if (unlink(msg->filename)) {
+			db.flags |= DB_STALE;
+			free(pathname);
+			continue;
+		}
+
+		free(msg->filename);
+		msg->filename = pathname;
+	}
+
+	return 0;
+}
+
+static int maildir_changed(void)
+{
+	struct stat stat;
+	unsigned int i;
+	struct db_message *msg;
+
+	for (i = 0; i < db.total_count; i++) {
+		msg = db.array[i];
+
+		if (lstat(msg->filename, &stat) ||
+		    stat.st_mtime != msg->mtime ||
+		    stat.st_size != msg->size) {
+			db.flags |= DB_STALE;
+			return 1;
+		}
+
+		if (time(NULL) == msg->mtime)
+		if (sleep_select(1, 0)) return 1;
+	}
+
+	return 0;
+}
+
+int maildir_get(struct db_message *msg, int lines)
+{
+	int fd;
+	struct stat stat, stat_after;
+
+	if (maildir_changed()) return POP_CRASH_SERVER;
+
+	if (lstat(msg->filename, &stat)) return POP_CRASH_SERVER;
+	
+	if (!S_ISREG(stat.st_mode)) return POP_CRASH_SERVER;
+
+	if (!stat.st_size) return POP_CRASH_SERVER;
+
+	if ((fd = open(msg->filename, O_RDONLY | O_NOCTTY | O_NONBLOCK)) < 0)
+		return POP_CRASH_SERVER;
+
+	if (fstat(fd, &stat_after) < 0) return POP_CRASH_SERVER;
+	if (stat.st_mode != stat_after.st_mode ||
+	    stat.st_ino != stat_after.st_ino ||
+	    stat.st_dev != stat_after.st_dev) return POP_CRASH_SERVER;
+
+	if (pop_reply_multiline(fd, msg->size, lines)) {
+		close(fd);
+		return POP_CRASH_NETFAIL;
+	}
+
+	close(fd);
+
+	if (maildir_changed()) return POP_CRASH_SERVER;
+
+	if (pop_reply_terminate()) return POP_CRASH_NETFAIL;
+
+	return POP_OK;
+}
+
+int maildir_update(void)
+{
+	unsigned int i;
+	struct db_message *msg;
+
+	for (i = 0; i < db.total_count; i++) {
+		msg = db.array[i];
+
+		if (msg->flags & MSG_DELETED)
+		{
+			if (unlink(msg->filename) < 0) {
+				if (errno == ENOENT)
+					continue;
+
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int maildir_scandir(char *dir)
+{
+	char *pathname;
+	DIR *dirp;
+	struct dirent *de;
+	struct db_message msg;
+	MD5_CTX hash;
+	struct stat stat;
+	char *p, *uidl;
+
+	dirp = opendir(dir);
+
+	if (!dirp) return 1;
+
+	while ((de = readdir(dirp))) {
+		if (de->d_name[0] == '.') continue;
+
+		pathname = malloc(strlen(dir) + strlen(de->d_name) + 2);
+		if (!pathname) return 1;
+
+		sprintf(pathname, "%s/%s", dir, de->d_name);
+
+		if (lstat(pathname, &stat)) {
+			free(pathname);
+			continue;
+		}
+
+		if (!S_ISREG(stat.st_mode)) {
+			free(pathname);
+			continue;
+		}
+
+		if (!stat.st_size) {
+			free(pathname);
+			continue;
+		}
+
+		memset(&msg, 0, sizeof(msg));
+
+		msg.size = stat.st_size;
+		msg.mtime = stat.st_mtime;
+		msg.filename = pathname;
+/*
+ * According to RFC1939 the message uidl can be from 1 to 70 characters
+ * in the range 0x21 to 0x7E. If your MTA generates valid unique filenames
+ * you could just as well use the filename instead of a md5 hash.
+ */
+
+/* We use the basename of pathname as hash data. */
+
+		if (!(p = strrchr(pathname, '/'))) return 1;
+
+		uidl = strdup(p);
+
+/* We trim any trailing * maildir info that might exist. */
+
+		if ((p = strrchr(uidl, ':'))) *p = '\0';
+
+		MD5_Init(&hash);
+		MD5_Update(&hash, uidl, strlen(uidl));
+		MD5_Final(msg.hash, &hash);
+
+		free(uidl);
+
+		if (db_add(&msg)) {
+			closedir(dirp);
+			return 1;
+		}
+	}
+
+	closedir(dirp);
+
+	return 0;
+}
+
+int maildir_open(char *spool, char *mailbox)
+{
+	char *pathname;
+
+	pathname = malloc(strlen(spool) + strlen(mailbox) + 2);
+
+	if (!pathname) return 1;
+
+	sprintf(pathname, "%s/%s", spool, mailbox);
+
+	if (chdir(pathname) == -1) {
+		free(pathname);
+		return 1;
+	}
+
+	free(pathname);
+
+	if (maildir_scandir("new"))
+		return 1;
+	if (maildir_scandir("cur"))
+		return 1;
+
+	return 0;
+}
+
+#endif
--- maildir.h	Thu Jan  1 00:00:00 1970
+++ maildir.h	Tue Nov 26 07:40:49 2002
@@ -0,0 +1,35 @@
+/*
+ * Maildir access.
+ */
+
+#ifndef _POP_MAILDIR_H
+#define _POP_MAILDIR_H
+
+/*
+ * Opens the maildir, filling in the maildir database. Returns a non-zero
+ * value on error.
+ */
+extern int maildir_open(char *spool, char *mailbox);
+
+/*
+ * Sends (first lines of) a message to the POP client. Returns one of the
+ * POP_* event codes.
+ */
+extern int maildir_get(struct db_message *msg, int lines);
+
+/*
+ * Move new messages to cur/ and clean out tmp.
+ */
+extern int maildir_close(void);
+
+/*
+ * Updates the maildir according to flags in the database.
+ */
+extern int maildir_update(void);
+
+/*
+ * Compares the modified timestamp of two maildir messages
+ */
+extern int maildir_msgcmp(const void *p1, const void *p2);
+
+#endif
Common subdirectories: popa3d-0.5.9/md5 and popa3d-0.5.9-maildir/md5
--- params.h	Tue Nov 26 06:38:18 2002
+++ params.h	Mon Dec 16 20:12:37 2002
@@ -59,6 +59,12 @@
 #endif
 
 /*
+ * Maildir support by Hallgrimur H. Gunnarsson <hhg@data.is>
+ * Improvements by Cory Visi <cory@visi.name>       
+ */
+#define POP_MAILDIR			1
+
+/*
  * Do we want to support virtual domains?
  */
 #define POP_VIRTUAL			0
--- pop_trans.c	Tue Nov 26 06:38:18 2002
+++ pop_trans.c	Tue Nov 26 07:38:42 2002
@@ -3,12 +3,14 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <syslog.h>
 
 #include "params.h"
 #include "protocol.h"
 #include "database.h"
 #include "mailbox.h"
+#include "maildir.h"
 
 static int pop_trans_quit(char *params)
 {
@@ -104,7 +106,11 @@
 	if (number < 1 || number > db.total_count || params) return POP_ERROR;
 	msg = db.array[number - 1];
 	if (msg->flags & MSG_DELETED) return POP_ERROR;
+#if POP_MAILDIR
+	if ((event = maildir_get(msg, -1)) != POP_OK) return event;
+#else
 	if ((event = mailbox_get(msg, -1)) != POP_OK) return event;
+#endif
 #if POP_SUPPORT_LAST
 	if (number > db.last) db.last = number;
 #endif
@@ -123,7 +129,11 @@
 	if (lines < 0 || params) return POP_ERROR;
 	msg = db.array[number - 1];
 	if (msg->flags & MSG_DELETED) return POP_ERROR;
+#if POP_MAILDIR
+	if ((event = maildir_get(msg, lines)) != POP_OK) return event;
+#else
 	if ((event = mailbox_get(msg, lines)) != POP_OK) return event;
+#endif
 	return POP_QUIET;
 }
 
@@ -192,13 +202,25 @@
 {
 	db_init();
 
+#if POP_MAILDIR
+	if (maildir_open(spool, mailbox)) return 1;
+#else
 	if (mailbox_open(spool, mailbox)) return 1;
+#endif
 
 	if (db_fix()) {
+#if POP_MAILDIR
+		maildir_close();
+#else
 		mailbox_close();
+#endif
 		return 1;
 	}
 
+#if POP_MAILDIR
+	qsort(&db.array[0], db.total_count, sizeof(db.array[0]), maildir_msgcmp);
+#endif
+
 	return 0;
 }
 
@@ -225,7 +247,11 @@
 	else
 	switch ((result = pop_handle_state(pop_trans_commands))) {
 	case POP_STATE:
+#if POP_MAILDIR
+		if (maildir_update()) {
+#else
 		if (mailbox_update()) {
+#endif
 			if (db.flags & DB_STALE) break;
 			syslog(SYSLOG_PRI_ERROR,
 				"Failed to update %s/%s",
@@ -258,7 +284,11 @@
 			"Server failure accessing %s/%s",
 			spool, mailbox);
 
+#if POP_MAILDIR
+	maildir_close();
+#else
 	mailbox_close();
+#endif
 
 	return 0;
 }