Browse Source

added MaxSize configuration variable

fixed --fast to work robustly without relying on the \Recent flag in
messages
Michael Elkins 24 năm trước cách đây
mục cha
commit
0527181f45
10 tập tin đã thay đổi với 348 bổ sung160 xóa
  1. 50 0
      ChangeLog
  2. 14 0
      NEWS
  3. 1 1
      configure.in
  4. 51 108
      imap.c
  5. 9 6
      isync.1
  6. 12 5
      isync.h
  7. 2 0
      isyncrc.sample
  8. 162 12
      maildir.c
  9. 13 6
      main.c
  10. 34 22
      sync.c

+ 50 - 0
ChangeLog

@@ -1,5 +1,55 @@
 2000-12-21  Michael Elkins  <me@sigipe.org>
 
+	* imap.c, isync.h, maildir.c, sync.c:
+	RFC822.PEEK is obsolete in RFC2060.  Use BODY.PEEK[] instead, which does
+	the same thing
+
+	keep track of the uidvalidity so isync can detect if the mailbox on the
+	server has changed since the last sync.
+
+	* NEWS: updated NEWS for 0.3 release
+
+	* Makefile.am, isync.spec:
+	added support for building RPMS
+
+	* Makefile.am, isync.1:
+	added target for creating html version of the man page
+
+	documented the imaps: prefix to the Host command
+
+	* imap.c, sync.c:
+	can't assume flag order when fetching a message.  just search for the
+	first `{' to find the message size.
+
+	* isync.1, sync.c:
+	added BUGS section to manpage detailing the fact that we break the
+	maildir(5) spec by parsing the filename
+
+	change message delivery to use the method described in maildir(5)
+
+	* configure.in, main.c, sync.c:
+	use getpass() to get the user's password
+
+	unlink the temp file if we are unable to fetch a new message from the
+	server.
+
+	update version to 0.3
+
+	* isync.1: fixed typo in man page for --verbose option
+
+	* Makefile.am, README, TODO, imap.c, isync.h, list.c:
+	added generic IMAP list parser and rewrote imap_exec() to handle
+	arbitrary data instead of hardcoded
+
+	* Makefile.am, README, configure.in, main.c:
+	fixes to compile cleanly under Solaris 2.7
+
+	* configure.in, imap.c, isync.1, isync.h, main.c:
+	added OpenSSL support
+
+	* ChangeLog, configure.in, main.c:
+	config options were not case insensitive
+
 	* imap.c, isync.h, maildir.c, main.c, sync.c:
 	don't fetch deleted messages when expunging
 

+ 14 - 0
NEWS

@@ -1,3 +1,17 @@
+[0.4]
+
+Added MaxSize configuration option to limit downloading of new messages from
+the server to less than some threshold.
+
+More robust --fast option works without using \Recent flags, so the previous
+problem with multiple accesses killing these flags is no longer a problem.
+
+RFC2060 obsoleted RFC822.PEEK, use BODY.PEEK[] instead which does the same
+job.
+
+Don't need to request UID in a FETCH when doing UID FETCH (RFC2060 states
+that its automatically returned).
+
 [0.3]
 
 Fixed to clean up temp maildir files when the fetch of a new message failed.

+ 1 - 1
configure.in

@@ -1,5 +1,5 @@
 AC_INIT(isync.h)
-AM_INIT_AUTOMAKE(isync,0.3)
+AM_INIT_AUTOMAKE(isync,0.4)
 AM_PROG_CC_STDC
 if test $CC = gcc; then
 	CFLAGS="$CFLAGS -pipe"

+ 51 - 108
imap.c

@@ -150,9 +150,13 @@ buffer_gets (buffer_t * b, char **s)
 }
 
 static int
-parse_fetch (imap_t * imap, list_t * list, message_t * cur)
+parse_fetch (imap_t * imap, list_t * list)
 {
     list_t *tmp;
+    unsigned int uid = 0;
+    unsigned int mask = 0;
+    unsigned int size = 0;
+    message_t *cur;
 
     if (!is_list (list))
 	return -1;
@@ -165,7 +169,14 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur)
 	    {
 		tmp = tmp->next;
 		if (is_atom (tmp))
-		    cur->uid = atoi (tmp->val);
+		{
+		    uid = atoi (tmp->val);
+		    if (uid < imap->minuid)
+		    {
+			/* already saw this message */
+			return 0;
+		    }
+		}
 		else
 		    puts ("Error, unable to parse UID");
 	    }
@@ -181,20 +192,17 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur)
 			if (is_atom (flags))
 			{
 			    if (!strcmp ("\\Seen", flags->val))
-				cur->flags |= D_SEEN;
+				mask |= D_SEEN;
 			    else if (!strcmp ("\\Flagged", flags->val))
-				cur->flags |= D_FLAGGED;
+				mask |= D_FLAGGED;
 			    else if (!strcmp ("\\Deleted", flags->val))
-			    {
-				cur->flags |= D_DELETED;
-				imap->deleted++;
-			    }
+				mask |= D_DELETED;
 			    else if (!strcmp ("\\Answered", flags->val))
-				cur->flags |= D_ANSWERED;
+				mask |= D_ANSWERED;
 			    else if (!strcmp ("\\Draft", flags->val))
-				cur->flags |= D_DRAFT;
+				mask |= D_DRAFT;
 			    else if (!strcmp ("\\Recent", flags->val))
-				cur->flags |= D_RECENT;
+				mask |= D_RECENT;
 			    else
 				printf ("Warning, unknown flag %s\n",
 					flags->val);
@@ -206,8 +214,26 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur)
 		else
 		    puts ("Error, unable to parse FLAGS");
 	    }
+	    else if (!strcmp ("RFC822.SIZE", tmp->val))
+	    {
+		tmp = tmp->next;
+		if (is_atom (tmp))
+		    size = atol (tmp->val);
+	    }
 	}
     }
+
+    cur = calloc (1, sizeof (message_t));
+    cur->next = imap->msgs;
+    imap->msgs = cur;
+
+    if (mask & D_DELETED)
+	imap->deleted++;
+
+    cur->uid = uid;
+    cur->flags = mask;
+    cur->size = size;
+
     return 0;
 }
 
@@ -246,8 +272,6 @@ imap_exec (imap_t * imap, const char *fmt, ...)
     char *cmd;
     char *arg;
     char *arg1;
-    message_t **cur = 0;
-    message_t **rec = 0;
 
     va_start (ap, fmt);
     vsnprintf (tmp, sizeof (tmp), fmt, ap);
@@ -281,22 +305,6 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 		imap->ns_other = parse_list (cmd, &cmd);
 		imap->ns_shared = parse_list (cmd, 0);
 	    }
-	    else if (!strcmp ("SEARCH", arg))
-	    {
-		if (!rec)
-		{
-		    rec = &imap->recent_msgs;
-		    while (*rec)
-			rec = &(*rec)->next;
-		}
-		/* parse rest of `cmd' */
-		while ((arg = next_arg (&cmd)))
-		{
-		    *rec = calloc (1, sizeof (message_t));
-		    (*rec)->uid = atoi (arg);
-		    rec = &(*rec)->next;
-		}
-	    }
 	    else if (!strcmp ("OK", arg) || !strcmp ("BAD", arg) ||
 		     !strcmp ("NO", arg) || !strcmp ("PREAUTH", arg) ||
 		     !strcmp ("BYE", arg))
@@ -313,25 +321,15 @@ imap_exec (imap_t * imap, const char *fmt, ...)
 		{
 		    list_t *list;
 
-		    if (!cur)
-		    {
-			cur = &imap->msgs;
-			while (*cur)
-			    cur = &(*cur)->next;
-		    }
-
 		    list = parse_list (cmd, 0);
 
-		    *cur = calloc (1, sizeof (message_t));
-		    if (parse_fetch (imap, list, *cur))
+		    if (parse_fetch (imap, list))
 		    {
 			free_list (list);
 			return -1;
 		    }
 
 		    free_list (list);
-
-		    cur = &(*cur)->next;
 		}
 	    }
 	    else
@@ -357,66 +355,20 @@ imap_exec (imap_t * imap, const char *fmt, ...)
     /* not reached */
 }
 
-static int
-fetch_recent_flags (imap_t * imap)
-{
-    char buf[1024];
-    message_t **cur = &imap->recent_msgs;
-    message_t *tmp;
-    unsigned int start = -1;
-    unsigned int last = -1;
-    int ret = 0;
-
-    buf[0] = 0;
-    while (*cur)
-    {
-	tmp = *cur;
-
-	if (last == (unsigned int) -1)
-	{
-	    /* init */
-	    start = tmp->uid;
-	    last = tmp->uid;
-	}
-	else if (tmp->uid == last + 1)
-	    last++;
-	else
-	{
-	    /* out of sequence */
-	    if (start == last)
-		ret = imap_exec (imap, "UID FETCH %d (UID FLAGS)", start);
-	    else
-		ret =
-		    imap_exec (imap, "UID FETCH %d:%d (UID FLAGS)", start,
-			       last);
-	    start = tmp->uid;
-	    last = tmp->uid;
-	}
-	free (tmp);
-	*cur = (*cur)->next;
-    }
-
-    if (start != (unsigned int) -1)
-    {
-	if (start == last)
-	    ret = imap_exec (imap, "UID FETCH %d (UID FLAGS)", start);
-	else
-	    ret =
-		imap_exec (imap, "UID FETCH %d:%d (UID FLAGS)", start, last);
-    }
-
-    return ret;
-}
-
+/* `box' is the config info for the maildrop to sync.  `minuid' is the
+ * minimum UID to consider.  in normal mode this will be 1, but in --fast
+ * mode we only fetch messages newer than the last one seen in the local
+ * mailbox.
+ */
 imap_t *
-imap_open (config_t * box, int fast)
+imap_open (config_t * box, unsigned int minuid)
 {
     int ret;
     imap_t *imap;
     int s;
     struct sockaddr_in sin;
     struct hostent *he;
-    char *ns_prefix = 0;
+    char *ns_prefix = "";
 #if HAVE_LIBSSL
     int use_ssl = 0;
 #endif
@@ -463,6 +415,7 @@ imap_open (config_t * box, int fast)
     imap->buf = calloc (1, sizeof (buffer_t));
     imap->buf->sock = imap->sock;
     imap->box = box;
+    imap->minuid = minuid;
 
 #if HAVE_LIBSSL
     if (!box->use_imaps)
@@ -520,28 +473,18 @@ imap_open (config_t * box, int fast)
     {
 	fputs ("Selecting mailbox... ", stdout);
 	fflush (stdout);
-	ret = imap_exec (imap, "SELECT %s%s",
-			 ns_prefix ? ns_prefix : "", box->box);
+	ret = imap_exec (imap, "SELECT %s%s", ns_prefix, box->box);
 	if (!ret)
 	    printf ("%d messages, %d recent\n", imap->count, imap->recent);
     }
 
     if (!ret)
     {
-	if (fast)
-	{
-	    if (imap->recent > 0)
-	    {
-		puts ("Fetching info for recent messages");
-		ret = imap_exec (imap, "UID SEARCH RECENT");
-		if (!ret)
-		    ret = fetch_recent_flags (imap);
-	    }
-	}
-	else if (imap->count > 0)
+	puts ("Reading IMAP mailbox index");
+	if (imap->count > 0)
 	{
-	    puts ("Reading IMAP mailbox index");
-	    ret = imap_exec (imap, "FETCH 1:%d (UID FLAGS)", imap->count);
+	    ret = imap_exec (imap, "UID FETCH %d:* (FLAGS RFC822.SIZE)",
+		    imap->minuid);
 	}
     }
 

+ 9 - 6
isync.1

@@ -66,12 +66,6 @@ Causes
 to skip the step of synchronzing message flags between the local maildir
 mailbox and the IMAP mailbox.  Only new messages existing on the server will
 be fetched into the local mailbox.
-.B NOTE:
-This command works by checking the \\Recent flag on messages in the IMAP
-mailbox.  If you access the IMAP mailbox from multiple locations, the
-\\Recent flag will be lost between sessions, so you must do a full
-synchronization to fetch the messages which do not exist in the local
-mailbox.
 .TP
 .B -h, --help
 Displays a summary of command line options
@@ -158,6 +152,15 @@ Defines an alias for the mailbox which can be used as a shortcut on the
 command line.
 ..
 .TP
+\fBMaxSize\fR \fIbytes\fR
+Sets a threshold for the maximum message size (in bytes) for which
+.B isync
+should fetch from the server.  This is useful for weeding out messages with
+large attachments.  If
+.I bytes
+is 0, the maximum file size is
+.B unlimited.
+.TP
 \fBRequireSSL\fR \fIyes|no\fR
 .B isync
 will abort the connection if a TLS/SSL session to the IMAP

+ 12 - 5
isync.h

@@ -54,6 +54,7 @@ struct config
     char *pass;
     char *box;
     char *alias;
+    unsigned int max_size;
     config_t *next;
 #if HAVE_LIBSSL
     char *cert_file;
@@ -69,7 +70,9 @@ struct mailbox
     message_t *msgs;
     unsigned int deleted;	/* # of deleted messages */
     unsigned int uidvalidity;
+    unsigned int maxuid;	/* largest uid we know about */
     unsigned int changed:1;
+    unsigned int maxuidchanged:1;
 };
 
 /* message dispositions */
@@ -86,6 +89,7 @@ struct message
     char *file;
     unsigned int uid;
     unsigned int flags;
+    unsigned int size;
     message_t *next;
     unsigned int processed:1;	/* message has already been evaluated */
     unsigned int new:1;		/* message is in the new/ subdir */
@@ -119,6 +123,8 @@ typedef struct
 				 */
     unsigned int deleted;	/* # of deleted messages */
     unsigned int uidvalidity;
+    unsigned int maxuid;
+    unsigned int minuid;
     /* NAMESPACE info */
     list_t *ns_personal;
     list_t *ns_other;
@@ -127,9 +133,8 @@ typedef struct
 imap_t;
 
 /* flags for sync_mailbox */
-#define SYNC_FAST	(1<<0)	/* don't sync flags, only fetch new msgs */
-#define	SYNC_DELETE	(1<<1)	/* delete local that don't exist on server */
-#define SYNC_EXPUNGE	(1<<2)	/* don't fetch deleted messages */
+#define	SYNC_DELETE	(1<<0)	/* delete local that don't exist on server */
+#define SYNC_EXPUNGE	(1<<1)	/* don't fetch deleted messages */
 
 extern config_t global;
 extern unsigned int Tag;
@@ -142,19 +147,21 @@ extern SSL_CTX *SSLContext;
 
 char *next_arg (char **);
 
-int sync_mailbox (mailbox_t *, imap_t *, int);
+int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int);
 
 void imap_close (imap_t *);
 int imap_fetch_message (imap_t *, unsigned int, int);
 int imap_set_flags (imap_t *, unsigned int, unsigned int);
 int imap_expunge (imap_t *);
-imap_t *imap_open (config_t *, int);
+imap_t *imap_open (config_t *, unsigned int);
 
 mailbox_t *maildir_open (const char *, int fast);
 int maildir_expunge (mailbox_t *, int);
 int maildir_sync (mailbox_t *);
 int maildir_set_uidvalidity (mailbox_t *, unsigned int uidvalidity);
 
+message_t * find_msg (message_t * list, unsigned int uid);
+
 /* parse an IMAP list construct */
 list_t * parse_list (char *s, char **end);
 int is_atom (list_t *list);

+ 2 - 0
isyncrc.sample

@@ -6,6 +6,8 @@
 User me
 #Port	143
 #Box	INBOX
+# don't download messages larger than 200K bytes
+MaxSize	200000
 
 ###
 ### work mailbox

+ 162 - 12
maildir.c

@@ -25,8 +25,38 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
 #include "isync.h"
 
+static int
+do_lock (int fd, int flag)
+{
+    struct flock lck;
+    struct stat sb;
+
+    if (fstat (fd, &sb))
+    {
+	perror ("fstat");
+	return -1;
+    }
+
+    memset (&lck, 0, sizeof (lck));
+    lck.l_type = flag;
+    lck.l_whence = SEEK_SET;
+    lck.l_start = 0;
+    lck.l_len = sb.st_size;
+
+    if (fcntl (fd, F_SETLK, &lck))
+    {
+	perror ("fcntl");
+	close (fd);
+	return -1;
+    }
+
+    return 0;
+}
+
 /* 2,<flags> */
 static void
 parse_info (message_t * m, char *s)
@@ -49,6 +79,45 @@ parse_info (message_t * m, char *s)
     }
 }
 
+static unsigned int
+read_uid (const char *path, const char *file)
+{
+    char full[_POSIX_PATH_MAX];
+    int fd;
+    int ret;
+    int len;
+    char buf[64];
+    unsigned int uid = 0;
+
+    snprintf (full, sizeof (full), "%s/%s", path, file);
+    fd = open (full, O_RDONLY);
+    if (fd == -1)
+    {
+	if (errno != ENOENT)
+	{
+	    perror ("open");
+	    return -1;
+	}
+	return 0;	/* doesn't exist */
+    }
+    ret = do_lock (fd, F_RDLCK);
+    if (!ret)
+    {
+	len = read (fd, buf, sizeof (buf) - 1);
+	if (len == -1)
+	    ret = -1;
+	else
+	{
+	    buf[len] = 0;
+	    uid = atol (buf);
+	}
+    }
+    ret |= do_lock (fd, F_UNLCK);
+    close (fd);
+    return ret ? ret : uid;
+
+}
+
 /* open a maildir mailbox.  if `fast' is nonzero, we just check to make
  * sure its a valid mailbox and don't actually parse it.  any IMAP messages
  * with the \Recent flag set are guaranteed not to be in the mailbox yet,
@@ -66,7 +135,6 @@ maildir_open (const char *path, int fast)
     mailbox_t *m;
     char *s;
     int count = 0;
-    FILE *fp;
 
     /* check to make sure this looks like a valid maildir box */
     snprintf (buf, sizeof (buf), "%s/new", path);
@@ -84,16 +152,22 @@ maildir_open (const char *path, int fast)
 
     m = calloc (1, sizeof (mailbox_t));
     m->path = strdup (path);
-    m->uidvalidity = -1;
 
     /* check for the uidvalidity value */
-    snprintf (buf, sizeof (buf), "%s/isyncuidvalidity", path);
-    if ((fp = fopen (buf, "r")))
+    m->uidvalidity = read_uid (path, "isyncuidvalidity");
+    if (m->uidvalidity == (unsigned int) -1)
     {
-	buf[sizeof (buf) - 1] = 0;
-	if (fgets (buf, sizeof (buf) - 1, fp))
-	    m->uidvalidity = atol (buf);
-	fclose (fp);
+	free (m->path);
+	free (m);
+	return NULL;
+    }
+
+    /* load the current maxuid */
+    if ((m->maxuid = read_uid (path, "isyncmaxuid")) == (unsigned int) -1)
+    {
+	free (m->path);
+	free (m);
+	return NULL;
     }
 
     if (fast)
@@ -108,6 +182,8 @@ maildir_open (const char *path, int fast)
 	d = opendir (buf);
 	if (!d)
 	{
+	    free (m->path);
+	    free (m);
 	    perror ("opendir");
 	    return 0;
 	}
@@ -130,10 +206,15 @@ maildir_open (const char *path, int fast)
 	     */
 	    s = strstr (p->file, "UID");
 	    if (!s)
-		puts ("warning, no uid for message");
+		puts ("Warning, no uid for message");
 	    else
 	    {
 		p->uid = strtol (s + 3, &s, 10);
+		if (p->uid > m->maxuid)
+		{
+		    m->maxuid = p->uid;
+		    m->maxuidchanged = 1;
+		}
 		if (*s && *s != ':')
 		{
 		    puts ("warning, unable to parse uid");
@@ -183,6 +264,70 @@ maildir_expunge (mailbox_t * mbox, int dead)
     return 0;
 }
 
+static int
+update_maxuid (mailbox_t * mbox)
+{
+    int fd;
+    char buf[64];
+    size_t len;
+    unsigned int uid;
+    char path[_POSIX_PATH_MAX];
+    int ret = 0;
+
+    snprintf (path, sizeof (path), "%s/isyncmaxuid", mbox->path);
+    fd = open (path, O_RDWR | O_CREAT, 0600);
+    if (fd == -1)
+    {
+	perror ("open");
+	return -1;
+    }
+
+    /* lock the file */
+    if (do_lock (fd, F_WRLCK))
+    {
+	close (fd);
+	return -1;
+    }
+
+    /* read the file again just to make sure it wasn't updated while
+     * we were doing something else
+     */
+    len = read (fd, buf, sizeof (buf) - 1);
+    buf[len] = 0;
+    uid = atol (buf);
+    if (uid > mbox->maxuid)
+    {
+	puts ("Error, maxuid is now higher (fatal)");
+	ret = -1;
+    }
+
+    if (!ret)
+    {
+	/* rewind */
+	lseek (fd, 0, SEEK_SET);
+
+	/* write out the file */
+	snprintf (buf, sizeof (buf), "%u\n", mbox->maxuid);
+	len = write (fd, buf, strlen (buf));
+	if (len == (size_t) - 1)
+	{
+	    perror ("write");
+	    ret = -1;
+	}
+	else
+	{
+	    ret = ftruncate (fd, len);
+	    if (ret)
+		perror ("ftruncate");
+	}
+    }
+
+    ret |= do_lock (fd, F_UNLCK);
+    ret |= close (fd);
+
+    return ret;
+}
+
 int
 maildir_sync (mailbox_t * mbox)
 {
@@ -190,6 +335,7 @@ maildir_sync (mailbox_t * mbox)
     char path[_POSIX_PATH_MAX];
     char oldpath[_POSIX_PATH_MAX];
     char *p;
+    int ret = 0;
 
     if (mbox->changed)
     {
@@ -219,7 +365,11 @@ maildir_sync (mailbox_t * mbox)
 	    }
 	}
     }
-    return 0;
+
+    if (mbox->maxuidchanged)
+	ret = update_maxuid (mbox);
+
+    return ret;
 }
 
 int
@@ -242,7 +392,7 @@ maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
     ret = write (fd, buf, strlen (buf));
 
     if (ret == -1)
-	perror("write");
+	perror ("write");
     else if ((size_t) ret != strlen (buf))
 	ret = -1;
     else
@@ -250,7 +400,7 @@ maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
 
     if (close (fd))
     {
-	perror("close");
+	perror ("close");
 	ret = -1;
     }
 

+ 13 - 6
main.c

@@ -95,6 +95,7 @@ config_defaults (config_t * conf)
     conf->port = global.port;
     conf->box = global.box;
     conf->host = global.host;
+    conf->max_size = global.max_size;
 #if HAVE_LIBSSL
     conf->require_ssl = global.require_ssl;
     conf->use_imaps = global.use_imaps;
@@ -206,6 +207,13 @@ load_config (char *where)
 	    if (*cur)
 		(*cur)->alias = strdup (p);
 	}
+	else if (!strncasecmp ("maxsize", buf, 7))
+	{
+	    if (*cur)
+		(*cur)->max_size = atol (p);
+	    else
+		global.max_size = atol (p);
+	}
 #if HAVE_LIBSSL
 	else if (!strncasecmp ("CertificateFile", buf, 15))
 	{
@@ -285,6 +293,7 @@ main (int argc, char **argv)
     global.port = 143;
     global.box = "INBOX";
     global.user = strdup (pw->pw_name);
+    global.max_size = 100000;
 #if HAVE_LIBSSL
     /* this will probably annoy people, but its the best default just in
      * case people forget to turn it on
@@ -380,16 +389,14 @@ main (int argc, char **argv)
 	exit (1);
     }
 
-    imap = imap_open (box, fast);
+    imap = imap_open (box, fast ? mail->maxuid + 1 : 1);
     if (!imap)
 	exit (1);
 
     puts ("Synchronizing");
-    i = 0;
-    i |= (fast) ? SYNC_FAST : 0;
-    i |= (delete) ? SYNC_DELETE : 0;
-    i |= (expunge) ? SYNC_EXPUNGE : 0;
-    if (sync_mailbox (mail, imap, i))
+    i = delete ? SYNC_DELETE : 0;
+    i |= expunge ? SYNC_EXPUNGE : 0;
+    if (sync_mailbox (mail, imap, i, box->max_size))
 	exit (1);
 
     if (!fast)

+ 34 - 22
sync.c

@@ -31,7 +31,7 @@
 
 static unsigned int MaildirCount = 0;
 
-static message_t *
+message_t *
 find_msg (message_t * list, unsigned int uid)
 {
     for (; list; list = list->next)
@@ -41,7 +41,7 @@ find_msg (message_t * list, unsigned int uid)
 }
 
 int
-sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
+sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
 {
     message_t *cur;
     message_t *tmp;
@@ -69,12 +69,21 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
 	return -1;
     }
 
+    if (mbox->maxuid == (unsigned int) -1 || imap->maxuid > mbox->maxuid)
+    {
+	mbox->maxuid = imap->maxuid;
+	mbox->maxuidchanged = 1;
+    }
+
+    /* if we are --fast mode, the mailbox wont have been loaded, so
+     * this next step is skipped.
+     */
     for (cur = mbox->msgs; cur; cur = cur->next)
     {
 	tmp = find_msg (imap->msgs, cur->uid);
 	if (!tmp)
 	{
-	    printf ("warning, uid %d doesn't exist on server\n", cur->uid);
+	    printf ("Warning, uid %d doesn't exist on server\n", cur->uid);
 	    if (flags & SYNC_DELETE)
 	    {
 		cur->flags |= D_DELETED;
@@ -85,25 +94,22 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
 	}
 	tmp->processed = 1;
 
-	if (!(flags & SYNC_FAST))
+	/* check if local flags are different from server flags.
+	 * ignore \Recent and \Draft
+	 */
+	if (cur->flags != (tmp->flags & ~(D_RECENT | D_DRAFT)))
 	{
-	    /* check if local flags are different from server flags.
-	     * ignore \Recent and \Draft
-	     */
-	    if (cur->flags != (tmp->flags & ~(D_RECENT | D_DRAFT)))
-	    {
-		/* set local flags that don't exist on the server */
-		if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
-		    imap->deleted++;
-		imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
-
-		/* update local flags */
-		if((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
-		    mbox->deleted++;
-		cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
-		cur->changed = 1;
-		mbox->changed = 1;
-	    }
+	    /* set local flags that don't exist on the server */
+	    if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
+		imap->deleted++;
+	    imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
+
+	    /* update local flags */
+	    if((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
+		mbox->deleted++;
+	    cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
+	    cur->changed = 1;
+	    mbox->changed = 1;
 	}
     }
 
@@ -124,6 +130,13 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
 		continue;
 	    }
 
+	    if (max_size && cur->size > max_size)
+	    {
+		printf ("Warning, message skipped because it is too big (%u)\n",
+			cur->size);
+		continue;
+	    }
+
 	    for (;;)
 	    {
 		/* create new file */
@@ -150,7 +163,6 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
 			  (cur->flags & D_ANSWERED) ? "R" : "",
 			  (cur->flags & D_SEEN) ? "S" : "",
 			  (cur->flags & D_DELETED) ? "T" : "");
-
 	    }
 
 	    /* give some visual feedback that something is happening */