commit a0e216fb23f41d5ec56c45cf63453bda10f65eb6
Author: Oswald Buddenhagen <[email protected]>
Date: Sun Jul 28 15:55:13 2013 +0200
added sync support for the arrival date of messages
initial patch by Marc Hoersken <[email protected]>
configure.ac | 17 +++++++++++++++++
src/config.c | 2 ++
src/drv_imap.c | 38 +++++++++++++++++++++++++++++++++-----
src/drv_maildir.c | 15 +++++++++++++++
src/isync.h | 2 ++
src/mbsync.1 | 10 ++++++++++
src/sync.c | 1 +
7 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index cd16883..0bfaa74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,23 @@ fi
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z,
+ [AC_TRY_RUN(
+[#include <time.h>
+#include <string.h>
+
+int main(void)
+{
+ time_t t = 0;
+ char buf[32];
+ strftime(buf, sizeof(buf), "%z", gmtime(&t));
+ return !!strcmp(buf, "+0000");
+}
+], [ob_cv_strftime_z=yes], [ob_cv_strftime_z=no], [ob_cv_strftime_z="yes
(assumed)"])])
+if test "x$ob_cv_strftime_z" = x"no"; then
+ AC_MSG_ERROR([libc lacks necessary feature])
+fi
+
AC_CHECK_HEADERS(sys/poll.h sys/select.h)
AC_CHECK_FUNCS(vasprintf memrchr)
diff --git a/src/config.c b/src/config.c
index ac8e0dc..124e1ee 100644
--- a/src/config.c
+++ b/src/config.c
@@ -362,6 +362,8 @@ load_config( const char *where, int pseudo )
max_size = parse_size( &cfile );
else if (!strcasecmp( "MaxMessages", cfile.cmd
))
channel->max_messages = parse_int(
&cfile );
+ else if (!strcasecmp( "CopyArrivalDate",
cfile.cmd ))
+ channel->use_internal_date =
parse_bool( &cfile );
else if (!strcasecmp( "Pattern", cfile.cmd ) ||
!strcasecmp( "Patterns", cfile.cmd ))
{
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 6951c0c..c8dca09 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -31,6 +31,7 @@
#include <limits.h>
#include <string.h>
#include <ctype.h>
+#include <time.h>
#include <sys/wait.h>
typedef struct imap_server_conf {
@@ -710,6 +711,8 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s
ATTR_UNUSED )
struct imap_cmd *cmdp;
int uid = 0, mask = 0, status = 0, size = 0;
unsigned i;
+ time_t date = 0;
+ struct tm datetime;
if (!is_list( list )) {
error( "IMAP error: bogus FETCH response\n" );
@@ -751,6 +754,15 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s
ATTR_UNUSED )
status |= M_FLAGS;
} else
error( "IMAP error: unable to parse
FLAGS\n" );
+ } else if (!strcmp( "INTERNALDATE", tmp->val )) {
+ tmp = tmp->next;
+ if (is_atom( tmp )) {
+ if (strptime( tmp->val, "%d-%b-%Y
%H:%M:%S %z", &datetime ))
+ date = mktime( &datetime );
+ else
+ error( "IMAP error: unable to
parse INTERNALDATE format\n" );
+ } else
+ error( "IMAP error: unable to parse
INTERNALDATE\n" );
} else if (!strcmp( "RFC822.SIZE", tmp->val )) {
tmp = tmp->next;
if (is_atom( tmp ))
@@ -794,6 +806,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s
ATTR_UNUSED )
msgdata = ((struct imap_cmd_fetch_msg *)cmdp)->msg_data;
msgdata->data = body;
msgdata->len = size;
+ msgdata->date = date;
if (status & M_FLAGS)
msgdata->flags = mask;
} else if (uid) { /* ignore async flag updates for now */
@@ -1738,8 +1751,9 @@ imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t
*data,
cmd->gen.gen.param.uid = msg->uid;
cmd->msg_data = data;
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_done_simple_msg,
- "UID FETCH %d (%sBODY.PEEK[])",
- msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " );
+ "UID FETCH %d (%s%sBODY.PEEK[])", msg->uid,
+ !(msg->status & M_FLAGS) ? "FLAGS " : "",
+ (data->date== -1) ? "INTERNALDATE " : "" );
}
/******************* imap_set_flags *******************/
@@ -1888,7 +1902,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int
to_trash,
imap_store_t *ctx = (imap_store_t *)gctx;
struct imap_cmd_out_uid *cmd;
int d;
- char flagstr[128], buf[1024];
+ char flagstr[128], datestr[64], buf[1024];
d = 0;
if (data->flags) {
@@ -1915,8 +1929,22 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int
to_trash,
return;
}
}
- imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
- "APPEND \"%s\" %s", buf, flagstr );
+ if (data->date) {
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat"
+ /* configure ensures that %z actually works. */
+#endif
+ strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z",
localtime( &data->date ) );
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+ imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
+ "APPEND \"%s\" %s\"%s\" ", buf, flagstr, datestr );
+ } else {
+ imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
+ "APPEND \"%s\" %s", buf, flagstr );
+ }
}
static void
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index ad3add7..27d5aec 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -36,6 +36,7 @@
#include <sys/file.h>
#include <errno.h>
#include <time.h>
+#include <utime.h>
#define USE_DB 1
#ifdef __linux__
@@ -1124,6 +1125,8 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg,
msg_data_t *data,
}
fstat( fd, &st );
data->len = st.st_size;
+ if (data->date == -1)
+ data->date = st.st_mtime;
data->data = nfmalloc( data->len );
if (read( fd, data->data, data->len ) != data->len) {
sys_error( "Maildir error: cannot read %s", buf );
@@ -1225,6 +1228,18 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int
to_trash,
cb( DRV_BOX_BAD, 0, aux );
return;
}
+
+ if (data->date) {
+ /* Set atime and mtime according to INTERNALDATE or mtime of
source message */
+ struct utimbuf utimebuf;
+ utimebuf.actime = utimebuf.modtime = data->date;
+ if (utime( buf, &utimebuf ) < 0) {
+ sys_error( "Maildir error: cannot set times for %s",
buf );
+ cb( DRV_BOX_BAD, 0, aux );
+ return;
+ }
+ }
+
/* Moving seen messages to cur/ is strictly speaking incorrect, but
makes mutt happy. */
nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%s%s", box,
subdirs[!(data->flags & F_SEEN)], base, fbuf );
if (rename( buf, nbuf )) {
diff --git a/src/isync.h b/src/isync.h
index 0fd196b..b6c7233 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -166,6 +166,7 @@ typedef struct channel_conf {
string_list_t *patterns;
int ops[2];
unsigned max_messages; /* for slave only */
+ unsigned use_internal_date:1;
} channel_conf_t;
typedef struct group_conf {
@@ -245,6 +246,7 @@ set_bad_callback( store_t *ctx, void (*cb)( void *aux ),
void *aux )
typedef struct {
char *data;
int len;
+ time_t date;
unsigned char flags;
} msg_data_t;
diff --git a/src/mbsync.1 b/src/mbsync.1
index 1816aa7..7925c69 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -477,6 +477,16 @@ a global effect. The global settings are overridden by
Channel-specific options,
which in turn are overridden by command line switches.
..
.TP
+\fBCopyArrivalDate\fR {\fIyes\fR|\fIno\fR}
+Selects whether their arrival time should be propagated together with
+the messages.
+Enabling this makes sense in order to keep the time stamp based message
+sorting intact.
+Note that IMAP does not guarantee that the time stamp (termed \fBinternal
+date\fR) is actually the arrival time, but it is usually close enough.
+(Default: \fIno\fR)
+..
+.TP
\fBSyncState\fR {\fB*\fR|\fIpath\fR}
Set the location of this Channel's synchronization state files. \fB*\fR means
that the state should be saved in a file named .mbsyncstate in the
diff --git a/src/sync.c b/src/sync.c
index 46b9333..d97d2c7 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -281,6 +281,7 @@ copy_msg( copy_vars_t *vars )
t ^= 1;
vars->data.flags = vars->msg->flags;
+ vars->data.date = svars->chan->use_internal_date ? -1 : 0;
DRIVER_CALL_RET(fetch_msg( svars->ctx[t], vars->msg, &vars->data,
msg_fetched, vars ));
}
------------------------------------------------------------------------------
Get your SQL database under version control now!
Version control is standard for application code, but databases havent
caught up. So what steps can you take to put your SQL databases under
version control? Why should you start doing it? Read more to find out.
http://pubads.g.doubleclick.net/gampad/clk?id=49501711&iu=/4140/ostg.clktrk
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel