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
This commit is contained in:
parent
8944538399
commit
bcecbe5eeb
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
EXTRA_DIST=sample.isyncrc $(man_MANS)
|
||||
INCLUDES=$(RPM_OPT_FLAGS)
|
||||
|
|
242
config.c
Normal file
242
config.c
Normal file
|
@ -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
181
imap.c
|
@ -701,7 +701,7 @@ imap_open (config_t * box, unsigned int minuid, imap_t * imap)
|
|||
|
||||
fputs ("Selecting mailbox... ", 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;
|
||||
printf ("%d messages, %d recent\n", imap->count, imap->recent);
|
||||
|
||||
|
@ -903,3 +903,182 @@ imap_expunge (imap_t * imap)
|
|||
{
|
||||
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
13
isync.1
|
@ -155,6 +155,19 @@ Defines an alias for the mailbox which can be used as a shortcut on the
|
|||
command line.
|
||||
..
|
||||
.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
|
||||
Sets a threshold for the maximum message size (in bytes) for which
|
||||
.B isync
|
||||
|
|
12
isync.h
12
isync.h
|
@ -54,7 +54,8 @@ struct config
|
|||
char *pass;
|
||||
char *box;
|
||||
char *alias;
|
||||
unsigned int max_size;
|
||||
char *copy_deleted_to;
|
||||
off_t max_size;
|
||||
config_t *next;
|
||||
#if HAVE_LIBSSL
|
||||
char *cert_file;
|
||||
|
@ -66,6 +67,7 @@ struct config
|
|||
unsigned int require_cram:1;
|
||||
#endif
|
||||
unsigned int use_namespace:1;
|
||||
unsigned int expunge:1;
|
||||
};
|
||||
|
||||
/* struct representing local mailbox file */
|
||||
|
@ -159,11 +161,17 @@ char *next_arg (char **);
|
|||
|
||||
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 *);
|
||||
int imap_copy_message (imap_t * imap, unsigned int uid, const char *mailbox);
|
||||
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 *, unsigned int, imap_t *);
|
||||
int imap_append_message (imap_t *, int, message_t *);
|
||||
|
||||
mailbox_t *maildir_open (const char *, int fast);
|
||||
int maildir_expunge (mailbox_t *, int);
|
||||
|
@ -180,3 +188,5 @@ int is_atom (list_t *list);
|
|||
int is_list (list_t *list);
|
||||
int is_nil (list_t *list);
|
||||
void free_list (list_t *list);
|
||||
|
||||
#define strfcpy(a,b,c) {strncpy(a,b,c);(a)[c-1]=0;}
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
# Values here are used as defaults for any following Mailbox section that
|
||||
# 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
|
||||
User me
|
||||
#Port 143
|
||||
|
@ -18,6 +24,8 @@ Host work.host.com
|
|||
Pass xxxxxxxx
|
||||
# define a shortcut so I can just use "isync work" from the command line
|
||||
Alias work
|
||||
# don't auto expunge messages in this box (overridden by -e on command line)
|
||||
Expunge no
|
||||
|
||||
###
|
||||
### personal mailbox
|
||||
|
|
226
main.c
226
main.c
|
@ -50,7 +50,6 @@ struct option Opts[] = {
|
|||
|
||||
config_t global;
|
||||
unsigned int Tag = 0;
|
||||
static config_t *box = 0;
|
||||
char Hostname[256];
|
||||
int Verbose = 0;
|
||||
|
||||
|
@ -85,203 +84,6 @@ usage (void)
|
|||
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 *
|
||||
next_arg (char **s)
|
||||
{
|
||||
|
@ -298,13 +100,25 @@ next_arg (char **s)
|
|||
*s = 0;
|
||||
return 0;
|
||||
}
|
||||
ret = *s;
|
||||
while (**s && !isspace ((unsigned char) **s))
|
||||
(*s)++;
|
||||
if (**s)
|
||||
*(*s)++ = 0;
|
||||
if (!**s)
|
||||
*s = 0;
|
||||
if (**s == '"')
|
||||
{
|
||||
++*s;
|
||||
ret = *s;
|
||||
*s = strchr (*s, '"');
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = *s;
|
||||
while (**s && !isspace ((unsigned char) **s))
|
||||
(*s)++;
|
||||
}
|
||||
if (*s)
|
||||
{
|
||||
if (**s)
|
||||
*(*s)++ = 0;
|
||||
if (!**s)
|
||||
*s = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -441,7 +255,7 @@ main (int argc, char **argv)
|
|||
|
||||
puts ("Synchronizing");
|
||||
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))
|
||||
exit (1);
|
||||
|
||||
|
|
117
sync.c
117
sync.c
|
@ -26,6 +26,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include "isync.h"
|
||||
|
||||
static unsigned int MaildirCount = 0;
|
||||
|
@ -40,7 +41,8 @@ find_msg (message_t * list, unsigned int uid)
|
|||
}
|
||||
|
||||
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 *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);
|
||||
if (!tmp)
|
||||
{
|
||||
printf ("Warning, uid %d doesn't exist on server\n", cur->uid);
|
||||
if (flags & SYNC_DELETE)
|
||||
/* if this message wasn't fetched from the server, attempt to
|
||||
* upload it
|
||||
*/
|
||||
if (cur->uid == (unsigned int) -1)
|
||||
{
|
||||
cur->flags |= D_DELETED;
|
||||
cur->dead = 1;
|
||||
mbox->deleted++;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
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;
|
||||
}
|
||||
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.
|
||||
* 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 */
|
||||
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))
|
||||
if ((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
|
||||
mbox->deleted++;
|
||||
cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
|
||||
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)
|
||||
{
|
||||
printf ("Warning, message skipped because it is too big (%u)\n",
|
||||
cur->size);
|
||||
printf
|
||||
("Warning, message skipped because it is too big (%u)\n",
|
||||
cur->size);
|
||||
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_DELETED) ? "T" : "");
|
||||
}
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* create new file */
|
||||
snprintf (path, sizeof (path), "%s/tmp/%s.%ld_%d.%d,U=%d%s",
|
||||
mbox->path, Hostname, time (0), MaildirCount++,
|
||||
getpid (), cur->uid, suffix);
|
||||
mbox->path, Hostname, time (0), MaildirCount++,
|
||||
getpid (), cur->uid, suffix);
|
||||
|
||||
if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) > 0)
|
||||
break;
|
||||
|
@ -184,7 +275,7 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
|
|||
p = strrchr (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
|
||||
* will get pulled down
|
||||
|
|
Loading…
Reference in New Issue
Block a user