diff -uN popa3d-0.5.9/Makefile popa3d-0.5.9-maildir/Makefile --- popa3d-0.5.9/Makefile Sun Nov 10 07:02:31 2002 +++ popa3d-0.5.9-maildir/Makefile Sun Nov 10 07:03:17 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 diff -uN popa3d-0.5.9/database.h popa3d-0.5.9-maildir/database.h --- popa3d-0.5.9/database.h Sun Nov 10 07:02:31 2002 +++ popa3d-0.5.9-maildir/database.h Sun Nov 10 06:50:15 2002 @@ -7,6 +7,8 @@ #include "params.h" +#include + /* * 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 { diff -uN popa3d-0.5.9/maildir.c popa3d-0.5.9-maildir/maildir.c --- popa3d-0.5.9/maildir.c Thu Jan 1 00:00:00 1970 +++ popa3d-0.5.9-maildir/maildir.c Sun Nov 10 17:54:49 2002 @@ -0,0 +1,177 @@ +/* + * Maildir access + */ + +#include "params.h" + +#if POP_MAILDIR + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "md5/md5.h" + +#include "misc.h" +#include "protocol.h" +#include "database.h" + +static int 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; +} + +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) { + db.flags |= DB_STALE; + return 1; + } + } + + return 0; +} + +int maildir_get(struct db_message *msg, int lines) +{ + int fd; + + if (maildir_changed()) return POP_CRASH_SERVER; + + if ((fd = open(msg->filename, O_RDONLY)) < 0) + 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_open(char *spool, char *mailbox) +{ + char *pathname; + DIR *dirp; + struct dirent *de; + struct db_message msg; + MD5_CTX hash; + struct stat stat; + + pathname = malloc(strlen(spool) + strlen(mailbox) + 3); + if (!pathname) return 1; + sprintf(pathname, "%s/%s/", spool, mailbox); + + if (lstat(pathname, &stat)) { + free(pathname); + return errno != ENOENT; + } + + if (!S_ISDIR(stat.st_mode)) { + free(pathname); + return 1; + } + + dirp = opendir(pathname); + + if (!dirp) return 1; + + while ((de = readdir(dirp))) { + if (de->d_name[0] == '.') continue; + + pathname = malloc(strlen(spool) + strlen(mailbox) + strlen(de->d_name) + 3); + if (!pathname) return 1; + + sprintf(pathname, "%s/%s/%s", spool, mailbox, 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. + */ + MD5_Init(&hash); + MD5_Update(&hash, pathname, strlen(pathname)); + MD5_Final(msg.hash, &hash); + + if (db_add(&msg)) return 1; + } + + qsort(&db.array, db.total_count, sizeof(db.array[0]), msgcmp); + + return 0; +} + +#endif diff -uN popa3d-0.5.9/maildir.h popa3d-0.5.9-maildir/maildir.h --- popa3d-0.5.9/maildir.h Thu Jan 1 00:00:00 1970 +++ popa3d-0.5.9-maildir/maildir.h Sun Nov 10 06:50:15 2002 @@ -0,0 +1,25 @@ +/* + * 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 *maildir); + +/* + * 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); + +/* + * Updates the maildir according to flags in the database. + */ +extern int maildir_update(void); + +#endif Common subdirectories: popa3d-0.5.9/md5 and popa3d-0.5.9-maildir/md5 diff -uN popa3d-0.5.9/params.h popa3d-0.5.9-maildir/params.h --- popa3d-0.5.9/params.h Sun Nov 10 07:02:32 2002 +++ popa3d-0.5.9-maildir/params.h Sun Nov 10 07:03:28 2002 @@ -58,6 +58,11 @@ #endif + /* + * Maildir support by Hallgrimur H. Gunnarsson + */ +#define POP_MAILDIR 0 + /* * Do we want to support virtual domains? */ diff -uN popa3d-0.5.9/pop_trans.c popa3d-0.5.9-maildir/pop_trans.c --- popa3d-0.5.9/pop_trans.c Sun Nov 10 07:02:32 2002 +++ popa3d-0.5.9-maildir/pop_trans.c Sun Nov 10 06:50:16 2002 @@ -9,6 +9,7 @@ #include "protocol.h" #include "database.h" #include "mailbox.h" +#include "maildir.h" static int pop_trans_quit(char *params) { @@ -104,7 +105,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 +128,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,10 +201,16 @@ { 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 mailbox_close(); +#endif return 1; } @@ -225,7 +240,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 +277,9 @@ "Server failure accessing %s/%s", spool, mailbox); +#if !POP_MAILDIR mailbox_close(); +#endif return 0; }