Browse Source

broke config code into config.c

added support for uploading local messages with no UID to the IMAP server

added Expunge configuration option

added CopyDeletedTo configuration option
0.9
Michael Elkins 24 years ago
parent
commit
bcecbe5eeb
  1. 2
      Makefile.am
  2. 242
      config.c
  3. 181
      imap.c
  4. 13
      isync.1
  5. 12
      isync.h
  6. 8
      isyncrc.sample
  7. 226
      main.c
  8. 117
      sync.c

2
Makefile.am

@ -1,5 +1,5 @@
bin_PROGRAMS=isync bin_PROGRAMS=isync
isync_SOURCES=main.c imap.c sync.c maildir.c isync.h list.c cram.c isync_SOURCES=main.c imap.c sync.c maildir.c isync.h list.c cram.c config.c
man_MANS=isync.1 man_MANS=isync.1
EXTRA_DIST=sample.isyncrc $(man_MANS) EXTRA_DIST=sample.isyncrc $(man_MANS)
INCLUDES=$(RPM_OPT_FLAGS) INCLUDES=$(RPM_OPT_FLAGS)

242
config.c

@ -0,0 +1,242 @@
/* $Id$
*
* isync - IMAP4 to maildir mailbox synchronizer
* Copyright (C) 2000 Michael R. Elkins <me@mutt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
#include "isync.h"
static config_t *box = 0;
/* set defaults from the global configuration section */
void
config_defaults (config_t * conf)
{
conf->user = global.user;
conf->pass = global.pass;
conf->port = global.port;
conf->box = global.box;
conf->host = global.host;
conf->max_size = global.max_size;
conf->copy_deleted_to = global.copy_deleted_to;
conf->use_namespace = global.use_namespace;
conf->expunge = global.expunge;
#if HAVE_LIBSSL
conf->require_ssl = global.require_ssl;
conf->use_imaps = global.use_imaps;
conf->cert_file = global.cert_file;
conf->use_sslv2 = global.use_sslv2;
conf->use_sslv3 = global.use_sslv3;
conf->use_tlsv1 = global.use_tlsv1;
#endif
}
void
load_config (const char *where)
{
char path[_POSIX_PATH_MAX];
char buf[1024];
struct passwd *pw;
config_t **cur = &box;
int line = 0;
FILE *fp;
char *p, *cmd, *val;
if (!where)
{
pw = getpwuid (getuid ());
snprintf (path, sizeof (path), "%s/.isyncrc", pw->pw_dir);
where = path;
}
printf ("Reading %s\n", where);
fp = fopen (where, "r");
if (!fp)
{
if (errno != ENOENT)
{
perror ("fopen");
return;
}
}
buf[sizeof buf - 1] = 0;
while ((fgets (buf, sizeof (buf) - 1, fp)))
{
p = buf;
cmd = next_arg (&p);
val = next_arg (&p);
line++;
if (!cmd || *cmd == '#')
continue;
if (!strncasecmp ("mailbox", cmd, 7))
{
if (*cur)
cur = &(*cur)->next;
*cur = calloc (1, sizeof (config_t));
config_defaults (*cur);
(*cur)->path = strdup (val);
}
else if (!strncasecmp ("host", cmd, 4))
{
#if HAVE_LIBSSL
if (!strncasecmp ("imaps:", val, 6))
{
val += 6;
if (*cur)
{
(*cur)->use_imaps = 1;
(*cur)->port = 993;
}
else
{
global.use_imaps = 1;
global.port = 993;
}
}
#endif
if (*cur)
(*cur)->host = strdup (val);
else
global.host = strdup (val);
}
else if (!strncasecmp ("user", cmd, 4))
{
if (*cur)
(*cur)->user = strdup (val);
else
global.user = strdup (val);
}
else if (!strncasecmp ("pass", cmd, 4))
{
if (*cur)
(*cur)->pass = strdup (val);
else
global.pass = strdup (val);
}
else if (!strncasecmp ("port", cmd, 4))
{
if (*cur)
(*cur)->port = atoi (val);
else
global.port = atoi (val);
}
else if (!strncasecmp ("box", cmd, 3))
{
if (*cur)
(*cur)->box = strdup (val);
else
global.box = strdup (val);
}
else if (!strncasecmp ("alias", cmd, 5))
{
if (*cur)
(*cur)->alias = strdup (val);
}
else if (!strncasecmp ("maxsize", cmd, 7))
{
if (*cur)
(*cur)->max_size = atol (val);
else
global.max_size = atol (val);
}
else if (!strncasecmp ("UseNamespace", cmd, 12))
{
if (*cur)
(*cur)->use_namespace = (strcasecmp (val, "yes") == 0);
else
global.use_namespace = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("CopyDeletedTo", cmd, 13))
{
if (*cur)
(*cur)->copy_deleted_to = strdup (val);
else
global.copy_deleted_to = strdup (val);
}
else if (!strncasecmp ("Expunge", cmd, 7))
{
if (*cur)
(*cur)->expunge = (strcasecmp (val, "yes") == 0);
else
global.expunge = (strcasecmp (val, "yes") == 0);
}
#if HAVE_LIBSSL
else if (!strncasecmp ("CertificateFile", cmd, 15))
{
if (*cur)
(*cur)->cert_file = strdup (val);
else
global.cert_file = strdup (val);
}
else if (!strncasecmp ("RequireSSL", cmd, 10))
{
if (*cur)
(*cur)->require_ssl = (strcasecmp (val, "yes") == 0);
else
global.require_ssl = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseSSLv2", cmd, 8))
{
if (*cur)
(*cur)->use_sslv2 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv2 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseSSLv3", cmd, 8))
{
if (*cur)
(*cur)->use_sslv3 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv3 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseTLSv1", cmd, 8))
{
if (*cur)
(*cur)->use_tlsv1 = (strcasecmp (val, "yes") == 0);
else
global.use_tlsv1 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("RequireCRAM", cmd, 11))
{
if (*cur)
(*cur)->require_cram = (strcasecmp (val, "yes") == 0);
else
global.require_cram = (strcasecmp (val, "yes") == 0);
}
#endif
else if (buf[0])
printf ("%s:%d:unknown command:%s", path, line, cmd);
}
fclose (fp);
}
config_t *
find_box (const char *s)
{
config_t *p = box;
for (; p; p = p->next)
if (!strcmp (s, p->path) || (p->alias && !strcmp (s, p->alias)))
return p;
return 0;
}

181
imap.c

@ -701,7 +701,7 @@ imap_open (config_t * box, unsigned int minuid, imap_t * imap)
fputs ("Selecting mailbox... ", stdout); fputs ("Selecting mailbox... ", stdout);
fflush (stdout); fflush (stdout);
if ((ret = imap_exec (imap, "SELECT %s%s", ns_prefix, box->box))) if ((ret = imap_exec (imap, "SELECT \"%s%s\"", ns_prefix, box->box)))
break; break;
printf ("%d messages, %d recent\n", imap->count, imap->recent); printf ("%d messages, %d recent\n", imap->count, imap->recent);
@ -903,3 +903,182 @@ imap_expunge (imap_t * imap)
{ {
return imap_exec (imap, "EXPUNGE"); return imap_exec (imap, "EXPUNGE");
} }
int
imap_copy_message (imap_t * imap, unsigned int uid, const char *mailbox)
{
char *ns_prefix = "";
/* XXX for now assume personal namespace */
if (imap->box->use_namespace && is_list (imap->ns_personal) &&
is_list (imap->ns_personal->child) &&
is_atom (imap->ns_personal->child->child))
{
ns_prefix = imap->ns_personal->child->child->val;
}
return imap_exec (imap, "UID COPY %u \"%s%s\"", uid, ns_prefix, mailbox);
}
int
imap_append_message (imap_t * imap, int fd, message_t * msg)
{
char buf[1024];
size_t len;
size_t sofar = 0;
int lines = 0;
char flagstr[128];
char *s;
size_t i;
size_t start, end;
char *arg;
/* ugh, we need to count the number of newlines */
while (sofar < msg->size)
{
len = msg->size - sofar;
if (len > sizeof (buf))
len = sizeof (buf);
len = read (fd, buf, len);
if (len == (size_t) - 1)
{
perror ("read");
return -1;
}
for (i = 0; i < len; i++)
if (buf[i] == '\n')
lines++;
sofar += len;
}
flagstr[0] = 0;
if (msg->flags)
{
strcpy (flagstr, "(");
if (msg->flags & D_DELETED)
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), "%s\\Deleted",
flagstr[1] ? " " : "");
if (msg->flags & D_ANSWERED)
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), "%s\\Answered",
flagstr[1] ? " " : "");
if (msg->flags & D_SEEN)
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), "%s\\Seen",
flagstr[1] ? " " : "");
if (msg->flags & D_FLAGGED)
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), "%s\\Flagged",
flagstr[1] ? " " : "");
if (msg->flags & D_DRAFT)
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), "%s\\Draft",
flagstr[1] ? " " : "");
snprintf (flagstr + strlen (flagstr),
sizeof (flagstr) - strlen (flagstr), ") ");
}
snprintf (buf, sizeof (buf), "%d APPEND %s %s{%d}\r\n", ++Tag,
imap->box->box, flagstr, msg->size + lines);
socket_write (imap->sock, buf, strlen (buf));
if (Verbose)
fputs (buf, stdout);
if (buffer_gets (imap->buf, &s))
return -1;
if (Verbose)
puts (s);
if (*s != '+')
return -1;
/* rewind */
lseek (fd, 0, 0);
sofar = 0;
while (sofar < msg->size)
{
len = msg->size - sofar;
if (len > sizeof (buf))
len = sizeof (buf);
len = read (fd, buf, len);
if (len == (size_t) - 1)
return -1;
start = 0;
while (start < len)
{
end = start;
while (end < len && buf[end] != '\n')
end++;
if (start != end)
socket_write (imap->sock, buf + start, end - start);
/* if (Verbose)
{
buf[end] = 0;
puts (buf + start);
} */
socket_write (imap->sock, "\r\n", 2);
start = end + 1;
}
sofar += len;
}
socket_write (imap->sock, "\r\n", 2);
for (;;)
{
if (buffer_gets (imap->buf, &s))
return -1;
if (Verbose)
puts (s);
arg = next_arg (&s);
if (*arg == '*')
{
/* XXX just ignore it for now */
}
else if (atoi (arg) != Tag)
{
puts ("wrong tag");
return -1;
}
else
{
int uid;
arg = next_arg (&s);
if (strcmp (arg, "OK"))
return -1;
arg = next_arg (&s);
if (*arg != '[')
break;
arg++;
if (strcasecmp ("APPENDUID", arg))
{
puts ("Error, expected APPENDUID");
break;
}
arg = next_arg (&s);
if (!arg)
break;
if (atoi (arg) != imap->uidvalidity)
{
puts ("Error, UIDVALIDITY doesn't match APPENDUID");
return -1;
}
arg = next_arg (&s);
if (!arg)
break;
uid = strtol (arg, &s, 10);
if (*s != ']')
{
/* parse error */
break;
}
return uid;
}
}
return 0;
}

13
isync.1

@ -155,6 +155,19 @@ Defines an alias for the mailbox which can be used as a shortcut on the
command line. command line.
.. ..
.TP .TP
\fBCopyDeletedTo\fR \fIstring\fR
Specifies the remote IMAP mailbox to copy deleted messages prior to
expunging (Default: none).
..
.TP
\fBExpunge\fR \fIyes|no\fR
Specifies whether deleted messages are expunged by default (Default: no).
\fBNOTE:\fR The
.I -e
command line option overrides this setting when set to
\fIno\fR.
..
.TP
\fBMaxSize\fR \fIbytes\fR \fBMaxSize\fR \fIbytes\fR
Sets a threshold for the maximum message size (in bytes) for which Sets a threshold for the maximum message size (in bytes) for which
.B isync .B isync

12
isync.h

@ -54,7 +54,8 @@ struct config
char *pass; char *pass;
char *box; char *box;
char *alias; char *alias;
unsigned int max_size; char *copy_deleted_to;
off_t max_size;
config_t *next; config_t *next;
#if HAVE_LIBSSL #if HAVE_LIBSSL
char *cert_file; char *cert_file;
@ -66,6 +67,7 @@ struct config
unsigned int require_cram:1; unsigned int require_cram:1;
#endif #endif
unsigned int use_namespace:1; unsigned int use_namespace:1;
unsigned int expunge:1;
}; };
/* struct representing local mailbox file */ /* struct representing local mailbox file */
@ -159,11 +161,17 @@ char *next_arg (char **);
int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int); int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int);
void config_defaults (config_t *);
void load_config (const char *);
config_t *find_box (const char *);
void imap_close (imap_t *); void imap_close (imap_t *);
int imap_copy_message (imap_t * imap, unsigned int uid, const char *mailbox);
int imap_fetch_message (imap_t *, unsigned int, int); int imap_fetch_message (imap_t *, unsigned int, int);
int imap_set_flags (imap_t *, unsigned int, unsigned int); int imap_set_flags (imap_t *, unsigned int, unsigned int);
int imap_expunge (imap_t *); int imap_expunge (imap_t *);
imap_t *imap_open (config_t *, unsigned int, imap_t *); imap_t *imap_open (config_t *, unsigned int, imap_t *);
int imap_append_message (imap_t *, int, message_t *);
mailbox_t *maildir_open (const char *, int fast); mailbox_t *maildir_open (const char *, int fast);
int maildir_expunge (mailbox_t *, int); int maildir_expunge (mailbox_t *, int);
@ -180,3 +188,5 @@ int is_atom (list_t *list);
int is_list (list_t *list); int is_list (list_t *list);
int is_nil (list_t *list); int is_nil (list_t *list);
void free_list (list_t *list); void free_list (list_t *list);
#define strfcpy(a,b,c) {strncpy(a,b,c);(a)[c-1]=0;}

8
isyncrc.sample

@ -2,6 +2,12 @@
# Values here are used as defaults for any following Mailbox section that # Values here are used as defaults for any following Mailbox section that
# doesn't specify it. # doesn't specify it.
# by default, expunge deleted messages (same as -e on command line)
Expunge yes
# copy deleted messages to the IMAP "Trash" folder
CopyDeletedTo "Trash"
# my default username, if different from the local username # my default username, if different from the local username
User me User me
#Port 143 #Port 143
@ -18,6 +24,8 @@ Host work.host.com
Pass xxxxxxxx Pass xxxxxxxx
# define a shortcut so I can just use "isync work" from the command line # define a shortcut so I can just use "isync work" from the command line
Alias work Alias work
# don't auto expunge messages in this box (overridden by -e on command line)
Expunge no
### ###
### personal mailbox ### personal mailbox

226
main.c

@ -50,7 +50,6 @@ struct option Opts[] = {
config_t global; config_t global;
unsigned int Tag = 0; unsigned int Tag = 0;
static config_t *box = 0;
char Hostname[256]; char Hostname[256];
int Verbose = 0; int Verbose = 0;
@ -85,203 +84,6 @@ usage (void)
exit (0); exit (0);
} }
/* set defaults from the global configuration section */
static void
config_defaults (config_t * conf)
{
conf->user = global.user;
conf->pass = global.pass;
conf->port = global.port;
conf->box = global.box;
conf->host = global.host;
conf->max_size = global.max_size;
conf->use_namespace = global.use_namespace;
#if HAVE_LIBSSL
conf->require_ssl = global.require_ssl;
conf->use_imaps = global.use_imaps;
conf->cert_file = global.cert_file;
conf->use_sslv2 = global.use_sslv2;
conf->use_sslv3 = global.use_sslv3;
conf->use_tlsv1 = global.use_tlsv1;
#endif
}
static void
load_config (char *where)
{
char path[_POSIX_PATH_MAX];
char buf[1024];
struct passwd *pw;
config_t **cur = &box;
int line = 0;
FILE *fp;
char *p, *cmd, *val;
if (!where)
{
pw = getpwuid (getuid ());
snprintf (path, sizeof (path), "%s/.isyncrc", pw->pw_dir);
where = path;
}
printf ("Reading %s\n", where);
fp = fopen (where, "r");
if (!fp)
{
if (errno != ENOENT)
{
perror ("fopen");
return;
}
}
buf[sizeof buf - 1] = 0;
while ((fgets (buf, sizeof (buf) - 1, fp)))
{
p = buf;
cmd = next_arg (&p);
val = next_arg (&p);
line++;
if (!cmd || *cmd == '#')
continue;
if (!strncasecmp ("mailbox", cmd, 7))
{
if (*cur)
cur = &(*cur)->next;
*cur = calloc (1, sizeof (config_t));
config_defaults (*cur);
(*cur)->path = strdup (val);
}
else if (!strncasecmp ("host", cmd, 4))
{
#if HAVE_LIBSSL
if (!strncasecmp ("imaps:", val, 6))
{
val += 6;
if (*cur)
{
(*cur)->use_imaps = 1;
(*cur)->port = 993;
}
else
{
global.use_imaps = 1;
global.port = 993;
}
}
#endif
if (*cur)
(*cur)->host = strdup (val);
else
global.host = strdup (val);
}
else if (!strncasecmp ("user", cmd, 4))
{
if (*cur)
(*cur)->user = strdup (val);
else
global.user = strdup (val);
}
else if (!strncasecmp ("pass", cmd, 4))
{
if (*cur)
(*cur)->pass = strdup (val);
else
global.pass = strdup (val);
}
else if (!strncasecmp ("port", cmd, 4))
{
if (*cur)
(*cur)->port = atoi (val);
else
global.port = atoi (val);
}
else if (!strncasecmp ("box", cmd, 3))
{
if (*cur)
(*cur)->box = strdup (val);
else
global.box = strdup (val);
}
else if (!strncasecmp ("alias", cmd, 5))
{
if (*cur)
(*cur)->alias = strdup (val);
}
else if (!strncasecmp ("maxsize", cmd, 7))
{
if (*cur)
(*cur)->max_size = atol (val);
else
global.max_size = atol (val);
}
else if (!strncasecmp ("UseNamespace", cmd, 12))
{
if (*cur)
(*cur)->use_namespace = (strcasecmp (val, "yes") == 0);
else
global.use_namespace = (strcasecmp (val, "yes") == 0);
}
#if HAVE_LIBSSL
else if (!strncasecmp ("CertificateFile", cmd, 15))
{
if (*cur)
(*cur)->cert_file = strdup (val);
else
global.cert_file = strdup (val);
}
else if (!strncasecmp ("RequireSSL", cmd, 10))
{
if (*cur)
(*cur)->require_ssl = (strcasecmp (val, "yes") == 0);
else
global.require_ssl = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseSSLv2", cmd, 8))
{
if (*cur)
(*cur)->use_sslv2 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv2 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseSSLv3", cmd, 8))
{
if (*cur)
(*cur)->use_sslv3 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv3 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("UseTLSv1", cmd, 8))
{
if (*cur)
(*cur)->use_tlsv1 = (strcasecmp (val, "yes") == 0);
else
global.use_tlsv1 = (strcasecmp (val, "yes") == 0);
}
else if (!strncasecmp ("RequireCRAM", cmd, 11))
{
if (*cur)
(*cur)->require_cram = (strcasecmp (val, "yes") == 0);
else
global.require_cram = (strcasecmp (val, "yes") == 0);
}
#endif
else if (buf[0])
printf ("%s:%d:unknown command:%s", path, line, cmd);
}
fclose (fp);
}
static config_t *
find_box (const char *s)
{
config_t *p = box;
for (; p; p = p->next)
if (!strcmp (s, p->path) || (p->alias && !strcmp (s, p->alias)))
return p;
return 0;
}
char * char *
next_arg (char **s) next_arg (char **s)
{ {
@ -298,13 +100,25 @@ next_arg (char **s)
*s = 0; *s = 0;
return 0; return 0;
} }
ret = *s; if (**s == '"')
while (**s && !isspace ((unsigned char) **s)) {
(*s)++; ++*s;
if (**s) ret = *s;
*(*s)++ = 0; *s = strchr (*s, '"');
if (!**s) }
*s = 0; else
{
ret = *s;
while (**s && !isspace ((unsigned char) **s))
(*s)++;
}
if (*s)
{
if (**s)
*(*s)++ = 0;
if (!**s)
*s = 0;
}
return ret; return ret;
} }
@ -441,7 +255,7 @@ main (int argc, char **argv)
puts ("Synchronizing"); puts ("Synchronizing");
i = delete ? SYNC_DELETE : 0; i = delete ? SYNC_DELETE : 0;
i |= expunge ? SYNC_EXPUNGE : 0; i |= (expunge || box->expunge) ? SYNC_EXPUNGE : 0;
if (sync_mailbox (mail, imap, i, box->max_size)) if (sync_mailbox (mail, imap, i, box->max_size))
exit (1); exit (1);

117
sync.c

@ -26,6 +26,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h>
#include "isync.h" #include "isync.h"
static unsigned int MaildirCount = 0; static unsigned int MaildirCount = 0;
@ -40,7 +41,8 @@ find_msg (message_t * list, unsigned int uid)
} }
int int
sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size) sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
unsigned int max_size)
{ {
message_t *cur; message_t *cur;
message_t *tmp; message_t *tmp;
@ -83,17 +85,104 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
tmp = find_msg (imap->msgs, cur->uid); tmp = find_msg (imap->msgs, cur->uid);
if (!tmp) if (!tmp)
{ {
printf ("Warning, uid %d doesn't exist on server\n", cur->uid); /* if this message wasn't fetched from the server, attempt to
if (flags & SYNC_DELETE) * upload it
*/
if (cur->uid == (unsigned int) -1)
{ {
cur->flags |= D_DELETED; struct stat sb;
cur->dead = 1; int fd;
mbox->deleted++; int uid;
/* upload the message if its not too big */
snprintf (path, sizeof (path), "%s/%s/%s", mbox->path,
cur->new ? "new" : "cur", cur->file);
if (stat (path, &sb))
{
printf ("Error, unable to stat %s: %s (errno %d)\n",
path, strerror (errno), errno);
continue; /* not fatal */
}
if (sb.st_size > imap->box->max_size)
{
printf
("Warning, local message is too large (%ld), skipping...\n",
sb.st_size);
continue;
}
fd = open (path, O_RDONLY);
if (fd == -1)
{
printf ("Error, unable to open %s: %s (errno %d)\n",
path, strerror (errno), errno);
continue;
}
cur->size = sb.st_size;
uid = imap_append_message (imap, fd, cur);
close (fd);
/* if the server gave us back a uid, rename the file so
* we remember for next time
*/
if (uid != -1)
{
char newpath[_POSIX_PATH_MAX];
char *p;
strfcpy (newpath, path, sizeof (newpath));
/* kill :info field */
p = strchr (newpath, ':');
if (p)
*p = 0;
/* XXX not quite right, should really always put the
* msg in "cur/", but i'm too tired right now.
*/
snprintf (newpath + strlen (newpath),
sizeof (newpath) - strlen (newpath),
",U=%d:2,%s%s%s%s", uid,
(cur->flags & D_FLAGGED) ? "F" : "",
(cur->flags & D_ANSWERED) ? "R" : "",
(cur->flags & D_SEEN) ? "S" : "",
(cur->flags & D_DELETED) ? "T" : "");
if (rename (path, newpath))
perror ("rename");
}
}
else
{
printf ("Warning, uid %u doesn't exist on server\n",
cur->uid);
if (flags & SYNC_DELETE)
{
cur->flags |= D_DELETED;
cur->dead = 1;
mbox->deleted++;
}
} }
continue; continue;
} }
tmp->processed = 1; tmp->processed = 1;
/* if the message is deleted, and CopyDeletedTo is set, and we
* are expunging, make a copy of the message now.
*/
if (((cur->flags | tmp->flags) & D_DELETED) != 0 &&
(flags & SYNC_EXPUNGE) && imap->box->copy_deleted_to)
{
if (imap_copy_message (imap, cur->uid,
imap->box->copy_deleted_to))
{
printf ("Error, unable to copy deleted message to \"%s\"\n",
imap->box->copy_deleted_to);
return -1;
}
}
/* check if local flags are different from server flags. /* check if local flags are different from server flags.
* ignore \Recent and \Draft * ignore \Recent and \Draft
*/ */
@ -102,10 +191,11 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
/* set local flags that don't exist on the server */ /* set local flags that don't exist on the server */
if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED)) if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
imap->deleted++; imap->deleted++;
imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags); imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
/* update local flags */ /* update local flags */
if((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED)) if ((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
mbox->deleted++; mbox->deleted++;
cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT)); cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
cur->changed = 1; cur->changed = 1;
@ -132,8 +222,9 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
if (max_size && cur->size > max_size) if (max_size && cur->size > max_size)
{ {
printf ("Warning, message skipped because it is too big (%u)\n", printf
cur->size); ("Warning, message skipped because it is too big (%u)\n",
cur->size);
continue; continue;
} }
@ -148,13 +239,13 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
(cur->flags & D_SEEN) ? "S" : "", (cur->flags & D_SEEN) ? "S" : "",
(cur->flags & D_DELETED) ? "T" : ""); (cur->flags & D_DELETED) ? "T" : "");
} }
for (;;) for (;;)
{ {
/* create new file */ /* create new file */
snprintf (path, sizeof (path), "%s/tmp/%s.%ld_%d.%d,U=%d%s", snprintf (path, sizeof (path), "%s/tmp/%s.%ld_%d.%d,U=%d%s",
mbox->path, Hostname, time (0), MaildirCount++, mbox->path, Hostname, time (0), MaildirCount++,
getpid (), cur->uid, suffix); getpid (), cur->uid, suffix);
if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) > 0) if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) > 0)
break; break;
@ -184,7 +275,7 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
p = strrchr (path, '/'); p = strrchr (path, '/');
snprintf (newpath, sizeof (newpath), "%s/%s%s", mbox->path, snprintf (newpath, sizeof (newpath), "%s/%s%s", mbox->path,
(cur->flags & D_SEEN) ? "cur" : "new", p); cur->flags ? "cur" : "new", p);
/* its ok if this fails, the next time we sync the message /* its ok if this fails, the next time we sync the message
* will get pulled down * will get pulled down

Loading…
Cancel
Save