2000-12-21 00:30:53 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
* isync - IMAP4 to maildir mailbox synchronizer
|
2002-12-28 15:31:20 +00:00
|
|
|
* Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
|
|
|
|
* Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@users.sf.net>
|
2000-12-20 21:41:21 +00:00
|
|
|
*
|
|
|
|
* 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
|
2002-10-30 02:31:20 +00:00
|
|
|
*
|
|
|
|
* As a special exception, isync may be linked with the OpenSSL library,
|
|
|
|
* despite that library's more restrictive license.
|
2000-12-20 21:41:21 +00:00
|
|
|
*/
|
|
|
|
|
2003-05-07 00:06:37 +00:00
|
|
|
#include "isync.h"
|
|
|
|
|
2000-12-20 21:41:21 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
2000-12-21 18:16:44 +00:00
|
|
|
#include <errno.h>
|
2001-01-11 10:13:47 +00:00
|
|
|
#include <sys/stat.h>
|
2000-12-20 21:41:21 +00:00
|
|
|
|
|
|
|
static unsigned int MaildirCount = 0;
|
|
|
|
|
2000-12-22 07:14:32 +00:00
|
|
|
message_t *
|
2000-12-20 21:41:21 +00:00
|
|
|
find_msg (message_t * list, unsigned int uid)
|
|
|
|
{
|
|
|
|
for (; list; list = list->next)
|
|
|
|
if (list->uid == uid)
|
|
|
|
return list;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-01-16 21:43:58 +00:00
|
|
|
static int
|
2004-01-12 00:52:14 +00:00
|
|
|
set_uid (DB * db, const char *f, unsigned int uid)
|
2002-01-16 19:47:28 +00:00
|
|
|
{
|
|
|
|
char *s;
|
2004-01-12 00:52:14 +00:00
|
|
|
DBT key, val;
|
|
|
|
int ret;
|
2002-01-16 19:47:28 +00:00
|
|
|
|
2004-01-12 00:52:14 +00:00
|
|
|
memset (&key, 0, sizeof(key));
|
|
|
|
memset (&val, 0, sizeof(val));
|
|
|
|
key.data = (void *) f;
|
2002-01-16 21:22:43 +00:00
|
|
|
s = strchr (f, ':');
|
2004-01-12 00:52:14 +00:00
|
|
|
key.size = s ? (size_t) (s - f) : strlen (f);
|
|
|
|
val.data = (void *) &uid;
|
|
|
|
val.size = sizeof (uid);
|
|
|
|
ret = db->put (db, 0, &key, &val, 0);
|
|
|
|
if (ret < 0)
|
|
|
|
fprintf (stderr, "Unexpected error (%d) from db_put(%.*s, %d)\n",
|
|
|
|
ret, key.size, f, uid);
|
|
|
|
db->sync(db, 0);
|
2002-01-16 19:47:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-12-20 21:41:21 +00:00
|
|
|
int
|
2001-01-11 10:13:47 +00:00
|
|
|
sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
2001-11-15 23:59:27 +00:00
|
|
|
unsigned int max_size, unsigned int max_msgs)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
|
|
|
message_t *cur;
|
|
|
|
message_t *tmp;
|
|
|
|
char path[_POSIX_PATH_MAX];
|
|
|
|
char newpath[_POSIX_PATH_MAX];
|
2000-12-22 15:48:04 +00:00
|
|
|
char suffix[_POSIX_PATH_MAX];
|
2000-12-20 21:41:21 +00:00
|
|
|
char *p;
|
|
|
|
int fd;
|
2000-12-21 17:51:07 +00:00
|
|
|
int ret;
|
2000-12-31 22:37:36 +00:00
|
|
|
int fetched = 0;
|
2001-10-31 19:50:01 +00:00
|
|
|
int upload = 0;
|
2001-11-15 23:59:27 +00:00
|
|
|
unsigned int msg_count;
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2002-06-18 06:37:55 +00:00
|
|
|
if (mbox->uidseen)
|
2000-12-21 23:10:18 +00:00
|
|
|
{
|
|
|
|
if (mbox->uidvalidity != imap->uidvalidity)
|
|
|
|
{
|
|
|
|
/* if the UIDVALIDITY value has changed, it means all our
|
|
|
|
* local UIDs are invalid, so we can't sync.
|
|
|
|
*/
|
2003-02-27 18:43:16 +00:00
|
|
|
fprintf (stderr,
|
|
|
|
"ERROR: UIDVALIDITY of '%s' changed on server\n",
|
|
|
|
imap->box->box);
|
2000-12-21 23:10:18 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (maildir_set_uidvalidity (mbox, imap->uidvalidity))
|
|
|
|
{
|
2002-01-16 21:22:43 +00:00
|
|
|
fputs ("ERROR: unable to store UIDVALIDITY\n", stderr);
|
2000-12-21 23:10:18 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2000-12-22 19:30:01 +00:00
|
|
|
if (mbox->maxuid == 0 || imap->maxuid > mbox->maxuid)
|
2000-12-22 07:14:32 +00:00
|
|
|
{
|
|
|
|
mbox->maxuid = imap->maxuid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we are --fast mode, the mailbox wont have been loaded, so
|
|
|
|
* this next step is skipped.
|
|
|
|
*/
|
2000-12-20 21:41:21 +00:00
|
|
|
for (cur = mbox->msgs; cur; cur = cur->next)
|
|
|
|
{
|
|
|
|
tmp = find_msg (imap->msgs, cur->uid);
|
|
|
|
if (!tmp)
|
|
|
|
{
|
2001-01-11 10:13:47 +00:00
|
|
|
/* if this message wasn't fetched from the server, attempt to
|
|
|
|
* upload it
|
|
|
|
*/
|
|
|
|
if (cur->uid == (unsigned int) -1)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2001-01-11 10:13:47 +00:00
|
|
|
struct stat sb;
|
|
|
|
|
2002-06-19 02:31:07 +00:00
|
|
|
if ((cur->flags & D_DELETED) && (flags & SYNC_EXPUNGE))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This message is marked as deleted and we are
|
|
|
|
* expunging. Don't upload to the server.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
if (!upload)
|
|
|
|
info ("Uploading messages");
|
|
|
|
infoc ('.');
|
|
|
|
fflush (stdout);
|
|
|
|
upload++;
|
2001-10-31 19:50:01 +00:00
|
|
|
|
2001-01-11 10:13:47 +00:00
|
|
|
/* 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))
|
|
|
|
{
|
2002-01-16 21:22:43 +00:00
|
|
|
perror (path);
|
2001-01-11 10:13:47 +00:00
|
|
|
continue; /* not fatal */
|
|
|
|
}
|
2001-11-15 23:59:27 +00:00
|
|
|
if (imap->box->max_size > 0
|
|
|
|
&& sb.st_size > imap->box->max_size)
|
2001-01-11 10:13:47 +00:00
|
|
|
{
|
2004-01-18 02:22:17 +00:00
|
|
|
info ("Local message %s is too large (%lu), skipping...\n",
|
|
|
|
cur->file, (unsigned long) sb.st_size);
|
2001-01-11 10:13:47 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fd = open (path, O_RDONLY);
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
2004-02-01 16:27:28 +00:00
|
|
|
/* This can happen if the message was simply deleted (ok)
|
|
|
|
or the flags changed (not ok - maildir sucks). */
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
fprintf (stderr, "Error, unable to open %s: %s (errno %d)\n",
|
2001-01-11 10:13:47 +00:00
|
|
|
path, strerror (errno), errno);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur->size = sb.st_size;
|
2002-01-16 19:47:28 +00:00
|
|
|
cur->uid = imap_append_message (imap, fd, cur);
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
if (cur->uid != (unsigned int) -1) {
|
2002-12-28 04:12:07 +00:00
|
|
|
/* update the db */
|
2002-01-16 19:47:28 +00:00
|
|
|
set_uid (mbox->db, cur->file, cur->uid);
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
if (!cur->uid)
|
2004-01-18 02:22:17 +00:00
|
|
|
warn ("Warning: no UID for new messge %s\n", cur->file);
|
2002-12-28 04:12:07 +00:00
|
|
|
else if (cur->uid > mbox->maxuid)
|
|
|
|
mbox->maxuid = cur->uid;
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
}
|
2001-01-11 10:13:47 +00:00
|
|
|
|
|
|
|
close (fd);
|
|
|
|
}
|
2002-06-19 02:31:07 +00:00
|
|
|
/*
|
|
|
|
* message used to exist on server but no longer does (we know
|
|
|
|
* this beacause it has a UID associated with it).
|
|
|
|
*/
|
2001-10-31 19:50:01 +00:00
|
|
|
else if (flags & SYNC_DELETE)
|
2001-01-11 10:13:47 +00:00
|
|
|
{
|
2001-10-31 19:50:01 +00:00
|
|
|
cur->flags |= D_DELETED;
|
|
|
|
cur->dead = 1;
|
|
|
|
mbox->deleted++;
|
|
|
|
}
|
|
|
|
/* if the user doesn't want local msgs deleted when they don't
|
|
|
|
* exist on the server, warn that such messages exist.
|
|
|
|
*/
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
else
|
2004-01-18 02:22:17 +00:00
|
|
|
info ("Local message %u doesn't exist on server\n", cur->uid);
|
2000-12-20 21:41:21 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
tmp->processed = 1;
|
|
|
|
|
2001-01-11 10:13:47 +00:00
|
|
|
/* 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))
|
|
|
|
{
|
2002-01-16 21:43:58 +00:00
|
|
|
fprintf (stderr,
|
|
|
|
"ERROR: unable to copy deleted message to \"%s\"\n",
|
|
|
|
imap->box->copy_deleted_to);
|
2001-01-11 10:13:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-12-22 07:14:32 +00:00
|
|
|
/* check if local flags are different from server flags.
|
|
|
|
* ignore \Recent and \Draft
|
|
|
|
*/
|
|
|
|
if (cur->flags != (tmp->flags & ~(D_RECENT | D_DRAFT)))
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2000-12-22 07:14:32 +00:00
|
|
|
/* set local flags that don't exist on the server */
|
|
|
|
if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
|
|
|
|
imap->deleted++;
|
2001-01-11 10:13:47 +00:00
|
|
|
|
2000-12-22 07:14:32 +00:00
|
|
|
imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
|
|
|
|
|
|
|
|
/* update local flags */
|
2001-01-11 10:13:47 +00:00
|
|
|
if ((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
|
2000-12-22 07:14:32 +00:00
|
|
|
mbox->deleted++;
|
|
|
|
cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
|
2002-01-16 19:47:28 +00:00
|
|
|
|
2002-01-17 19:33:25 +00:00
|
|
|
/* don't bother renaming the file if we are just going to
|
|
|
|
* remove it later.
|
2002-01-16 19:47:28 +00:00
|
|
|
*/
|
2002-01-17 19:33:25 +00:00
|
|
|
if ((cur->flags & D_DELETED) == 0 || (flags & SYNC_EXPUNGE) == 0)
|
2002-01-16 22:13:19 +00:00
|
|
|
{
|
2003-02-27 18:43:16 +00:00
|
|
|
size_t sl;
|
|
|
|
|
2002-01-17 19:33:25 +00:00
|
|
|
/* generate old path */
|
|
|
|
snprintf (path, sizeof (path), "%s/%s/%s",
|
|
|
|
mbox->path, cur->new ? "new" : "cur", cur->file);
|
|
|
|
|
2003-02-27 18:43:16 +00:00
|
|
|
/* generate new path */
|
|
|
|
strcpy (newpath, path);
|
|
|
|
p = strchr (newpath, ':');
|
|
|
|
sl = p ? (size_t)(p - newpath) : strlen (newpath);
|
|
|
|
snprintf (newpath + sl, sizeof (newpath) - sl, ":2,%s%s%s%s",
|
|
|
|
(cur->flags & D_FLAGGED) ? "F" : "",
|
2002-01-17 19:33:25 +00:00
|
|
|
(cur->flags & D_ANSWERED) ? "R" : "",
|
|
|
|
(cur->flags & D_SEEN) ? "S" : "",
|
|
|
|
(cur->flags & D_DELETED) ? "T" : "");
|
|
|
|
|
|
|
|
if (rename (path, newpath))
|
|
|
|
{
|
2004-02-01 16:27:28 +00:00
|
|
|
perror ("Warning: cannot set flags on message");
|
2002-01-17 19:33:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* update the filename in the msg struct */
|
|
|
|
p = strrchr (newpath, '/');
|
|
|
|
free (cur->file);
|
|
|
|
cur->file = strdup (p + 1);
|
|
|
|
}
|
2002-01-16 22:13:19 +00:00
|
|
|
}
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-31 19:50:01 +00:00
|
|
|
if (upload)
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
info (" %d messages.\n", upload);
|
2001-10-31 19:50:01 +00:00
|
|
|
|
2001-11-15 23:59:27 +00:00
|
|
|
if (max_msgs == 0)
|
|
|
|
max_msgs = UINT_MAX;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* expire messages in excess of the max-count for this mailbox.
|
|
|
|
* flagged mails are considered sacrosant and not deleted.
|
|
|
|
* we have already done the upload to the server, so messing with
|
|
|
|
* the flags variable do not have remote side effects.
|
|
|
|
*/
|
|
|
|
for (cur = imap->msgs, msg_count = 0;
|
|
|
|
cur && msg_count < max_msgs; cur = cur->next, msg_count++)
|
|
|
|
{
|
|
|
|
tmp = find_msg (mbox->msgs, cur->uid);
|
|
|
|
if (tmp)
|
|
|
|
tmp->wanted = 1;
|
|
|
|
}
|
|
|
|
for (cur = mbox->msgs; cur; cur = cur->next)
|
|
|
|
{
|
|
|
|
if (!cur->wanted && !(cur->flags & D_FLAGGED))
|
|
|
|
{
|
|
|
|
cur->flags |= D_DELETED;
|
|
|
|
cur->dead = 1;
|
|
|
|
mbox->deleted++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cur = imap->msgs, msg_count = 0;
|
|
|
|
cur && msg_count < max_msgs; cur = cur->next, msg_count++)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
|
|
|
if (!cur->processed)
|
|
|
|
{
|
|
|
|
/* new message on server */
|
2000-12-21 00:30:53 +00:00
|
|
|
|
|
|
|
if ((flags & SYNC_EXPUNGE) && (cur->flags & D_DELETED))
|
|
|
|
{
|
|
|
|
/* this message has been marked for deletion and
|
|
|
|
* we are currently expunging a mailbox. don't
|
|
|
|
* bother downloading this message
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2000-12-22 07:14:32 +00:00
|
|
|
if (max_size && cur->size > max_size)
|
|
|
|
{
|
2004-01-18 02:22:17 +00:00
|
|
|
info ("Remote message %u skipped because it is too big (%u)\n",
|
|
|
|
cur->uid, cur->size);
|
2000-12-22 07:14:32 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2000-12-22 15:48:04 +00:00
|
|
|
/* construct the flags part of the file name. */
|
|
|
|
|
|
|
|
*suffix = 0;
|
2003-02-27 18:43:16 +00:00
|
|
|
if (cur->flags & ~(D_RECENT | D_DRAFT))
|
2000-12-22 15:48:04 +00:00
|
|
|
{
|
|
|
|
snprintf (suffix, sizeof (suffix), ":2,%s%s%s%s",
|
|
|
|
(cur->flags & D_FLAGGED) ? "F" : "",
|
|
|
|
(cur->flags & D_ANSWERED) ? "R" : "",
|
|
|
|
(cur->flags & D_SEEN) ? "S" : "",
|
|
|
|
(cur->flags & D_DELETED) ? "T" : "");
|
|
|
|
}
|
2001-01-11 10:13:47 +00:00
|
|
|
|
2000-12-21 18:16:44 +00:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* create new file */
|
2002-01-16 19:47:28 +00:00
|
|
|
snprintf (path, sizeof (path), "%s/tmp/%ld_%d.%d.%s%s",
|
2001-10-03 00:01:18 +00:00
|
|
|
mbox->path, time (0), MaildirCount++, getpid (),
|
2002-01-16 19:47:28 +00:00
|
|
|
Hostname, suffix);
|
2000-12-21 18:16:44 +00:00
|
|
|
|
2000-12-22 15:48:04 +00:00
|
|
|
if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) > 0)
|
|
|
|
break;
|
|
|
|
if (errno != EEXIST)
|
2000-12-21 18:16:44 +00:00
|
|
|
{
|
2002-01-16 19:47:28 +00:00
|
|
|
perror (path);
|
2000-12-22 15:48:04 +00:00
|
|
|
break;
|
2000-12-21 18:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sleep (2);
|
|
|
|
}
|
|
|
|
|
2000-12-22 15:48:04 +00:00
|
|
|
if (fd < 0)
|
|
|
|
continue;
|
2000-12-20 21:41:21 +00:00
|
|
|
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
/* give some visual feedback that something is happening */
|
2004-02-01 16:27:28 +00:00
|
|
|
if (!fetched)
|
|
|
|
info ("Fetching new messages");
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
infoc ('.');
|
|
|
|
fflush (stdout);
|
2000-12-31 22:37:36 +00:00
|
|
|
fetched++;
|
2000-12-21 00:30:53 +00:00
|
|
|
|
2000-12-21 17:51:07 +00:00
|
|
|
ret = imap_fetch_message (imap, cur->uid, fd);
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2001-10-03 00:01:18 +00:00
|
|
|
if (fsync (fd))
|
|
|
|
{
|
2001-11-15 23:59:27 +00:00
|
|
|
perror ("fsync");
|
2001-10-03 00:01:18 +00:00
|
|
|
close (fd);
|
|
|
|
}
|
|
|
|
else if (close (fd))
|
2000-12-21 19:11:02 +00:00
|
|
|
perror ("close");
|
|
|
|
else if (!ret)
|
2000-12-21 17:51:07 +00:00
|
|
|
{
|
|
|
|
p = strrchr (path, '/');
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2000-12-21 17:51:07 +00:00
|
|
|
snprintf (newpath, sizeof (newpath), "%s/%s%s", mbox->path,
|
2003-02-27 18:43:16 +00:00
|
|
|
(cur->flags & D_SEEN) ? "cur" : "new", p); /* hack: ignore \recent, use !\seen instead */
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2000-12-21 18:16:44 +00:00
|
|
|
/* its ok if this fails, the next time we sync the message
|
|
|
|
* will get pulled down
|
|
|
|
*/
|
|
|
|
if (link (path, newpath))
|
|
|
|
perror ("link");
|
2002-01-16 19:47:28 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* update the db with the UID mapping for this file */
|
2002-01-16 21:22:43 +00:00
|
|
|
set_uid (mbox->db, p + 1, cur->uid);
|
2002-12-28 04:12:07 +00:00
|
|
|
if (cur->uid > mbox->maxuid)
|
|
|
|
mbox->maxuid = cur->uid;
|
2002-01-16 19:47:28 +00:00
|
|
|
}
|
2000-12-21 17:51:07 +00:00
|
|
|
}
|
2000-12-21 18:16:44 +00:00
|
|
|
|
|
|
|
/* always remove the temp file */
|
|
|
|
unlink (path);
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
|
|
|
}
|
2001-10-31 19:50:01 +00:00
|
|
|
|
2004-02-01 16:27:28 +00:00
|
|
|
if (fetched)
|
|
|
|
info (" %d messages\n", fetched);
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2002-12-28 04:12:07 +00:00
|
|
|
if (maildir_update_maxuid (mbox))
|
|
|
|
return -1;
|
|
|
|
|
2000-12-20 21:41:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|