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.
This commit is contained in:
Michael Elkins 2000-12-21 23:10:18 +00:00
parent 145e4ef84d
commit a8f9af4296
4 changed files with 112 additions and 6 deletions

38
imap.c
View File

@ -196,7 +196,8 @@ parse_fetch (imap_t * imap, list_t * list, message_t *cur)
else if (!strcmp ("\\Recent", flags->val))
cur->flags |= D_RECENT;
else
printf ("Warning, unknown flag %s\n",flags->val);
printf ("Warning, unknown flag %s\n",
flags->val);
}
else
puts ("Error, unable to parse FLAGS list");
@ -210,6 +211,32 @@ parse_fetch (imap_t * imap, list_t * list, message_t *cur)
return 0;
}
static void
parse_response_code (imap_t * imap, char *s)
{
char *arg;
if (*s != '[')
return; /* no response code */
s++;
arg = next_arg (&s);
if (!strcmp ("UIDVALIDITY", arg))
{
arg = next_arg (&s);
imap->uidvalidity = atol (arg);
}
else if (!strcmp ("ALERT", arg))
{
/* RFC2060 says that these messages MUST be displayed
* to the user
*/
fputs ("***ALERT*** ", stdout);
puts (s);
}
}
static int
imap_exec (imap_t * imap, const char *fmt, ...)
{
@ -270,6 +297,12 @@ imap_exec (imap_t * imap, const char *fmt, ...)
rec = &(*rec)->next;
}
}
else if (!strcmp ("OK", arg) || !strcmp ("BAD", arg) ||
!strcmp ("NO", arg) || !strcmp ("PREAUTH", arg) ||
!strcmp ("BYE", arg))
{
parse_response_code (imap, cmd);
}
else if ((arg1 = next_arg (&cmd)))
{
if (!strcmp ("EXISTS", arg1))
@ -315,6 +348,7 @@ imap_exec (imap_t * imap, const char *fmt, ...)
else
{
arg = next_arg (&cmd);
parse_response_code (imap, cmd);
if (!strcmp ("OK", arg))
return 0;
return -1;
@ -575,7 +609,7 @@ imap_fetch_message (imap_t * imap, unsigned int uid, int fd)
size_t n;
char buf[1024];
send_server (imap->sock, "UID FETCH %d (RFC822.PEEK)", uid);
send_server (imap->sock, "UID FETCH %d BODY.PEEK[]", uid);
for (;;)
{

View File

@ -68,6 +68,7 @@ struct mailbox
char *path;
message_t *msgs;
unsigned int deleted; /* # of deleted messages */
unsigned int uidvalidity;
unsigned int changed:1;
};
@ -117,6 +118,7 @@ typedef struct
* UID to be used in a FETCH FLAGS command
*/
unsigned int deleted; /* # of deleted messages */
unsigned int uidvalidity;
/* NAMESPACE info */
list_t *ns_personal;
list_t *ns_other;
@ -151,6 +153,7 @@ imap_t *imap_open (config_t *, 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);
/* parse an IMAP list construct */
list_t * parse_list (char *s, char **end);

View File

@ -66,6 +66,7 @@ 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);
@ -80,8 +81,20 @@ maildir_open (const char *path, int fast)
perror ("access");
return 0;
}
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")))
{
buf[sizeof (buf) - 1] = 0;
if (fgets (buf, sizeof (buf) - 1, fp))
m->uidvalidity = atol (buf);
fclose (fp);
}
if (fast)
return m;
@ -208,3 +221,42 @@ maildir_sync (mailbox_t * mbox)
}
return 0;
}
int
maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
{
char path[_POSIX_PATH_MAX];
char buf[16];
int fd;
int ret;
snprintf (path, sizeof (path), "%s/isyncuidvalidity", mbox->path);
fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd == -1)
{
perror ("open");
return -1;
}
snprintf (buf, sizeof (buf), "%u\n", uidvalidity);
ret = write (fd, buf, strlen (buf));
if (ret == -1)
perror("write");
else if ((size_t) ret != strlen (buf))
ret = -1;
else
ret = 0;
if (close (fd))
{
perror("close");
ret = -1;
}
if (ret)
if (unlink (path))
perror ("unlink");
return (ret);
}

17
sync.c
View File

@ -52,6 +52,23 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
int ret;
struct stat sb;
if (mbox->uidvalidity != (unsigned int) -1)
{
if (mbox->uidvalidity != imap->uidvalidity)
{
/* if the UIDVALIDITY value has changed, it means all our
* local UIDs are invalid, so we can't sync.
*/
puts ("Error, UIDVALIDITY changed on server (fatal)");
return -1;
}
}
else if (maildir_set_uidvalidity (mbox, imap->uidvalidity))
{
puts ("Error, unable to store UIDVALIDITY");
return -1;
}
for (cur = mbox->msgs; cur; cur = cur->next)
{
tmp = find_msg (imap->msgs, cur->uid);