added sync support for the arrival date of messages
initial patch by Marc Hoersken <info@marc-hoersken.de>
This commit is contained in:
parent
6577bf3e61
commit
eb1f10762f
17
configure.ac
17
configure.ac
|
@ -11,6 +11,23 @@ fi
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
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_HEADERS(sys/poll.h sys/select.h)
|
||||||
AC_CHECK_FUNCS(vasprintf memrchr)
|
AC_CHECK_FUNCS(vasprintf memrchr)
|
||||||
|
|
||||||
|
|
|
@ -362,6 +362,8 @@ load_config( const char *where, int pseudo )
|
||||||
max_size = parse_size( &cfile );
|
max_size = parse_size( &cfile );
|
||||||
else if (!strcasecmp( "MaxMessages", cfile.cmd ))
|
else if (!strcasecmp( "MaxMessages", cfile.cmd ))
|
||||||
channel->max_messages = parse_int( &cfile );
|
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 ) ||
|
else if (!strcasecmp( "Pattern", cfile.cmd ) ||
|
||||||
!strcasecmp( "Patterns", cfile.cmd ))
|
!strcasecmp( "Patterns", cfile.cmd ))
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
typedef struct imap_server_conf {
|
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;
|
struct imap_cmd *cmdp;
|
||||||
int uid = 0, mask = 0, status = 0, size = 0;
|
int uid = 0, mask = 0, status = 0, size = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
time_t date = 0;
|
||||||
|
struct tm datetime;
|
||||||
|
|
||||||
if (!is_list( list )) {
|
if (!is_list( list )) {
|
||||||
error( "IMAP error: bogus FETCH response\n" );
|
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;
|
status |= M_FLAGS;
|
||||||
} else
|
} else
|
||||||
error( "IMAP error: unable to parse FLAGS\n" );
|
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 )) {
|
} else if (!strcmp( "RFC822.SIZE", tmp->val )) {
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
if (is_atom( tmp ))
|
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 = ((struct imap_cmd_fetch_msg *)cmdp)->msg_data;
|
||||||
msgdata->data = body;
|
msgdata->data = body;
|
||||||
msgdata->len = size;
|
msgdata->len = size;
|
||||||
|
msgdata->date = date;
|
||||||
if (status & M_FLAGS)
|
if (status & M_FLAGS)
|
||||||
msgdata->flags = mask;
|
msgdata->flags = mask;
|
||||||
} else if (uid) { /* ignore async flag updates for now */
|
} 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->gen.gen.param.uid = msg->uid;
|
||||||
cmd->msg_data = data;
|
cmd->msg_data = data;
|
||||||
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_done_simple_msg,
|
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_done_simple_msg,
|
||||||
"UID FETCH %d (%sBODY.PEEK[])",
|
"UID FETCH %d (%s%sBODY.PEEK[])", msg->uid,
|
||||||
msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " );
|
!(msg->status & M_FLAGS) ? "FLAGS " : "",
|
||||||
|
(data->date== -1) ? "INTERNALDATE " : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************* imap_set_flags *******************/
|
/******************* 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;
|
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||||
struct imap_cmd_out_uid *cmd;
|
struct imap_cmd_out_uid *cmd;
|
||||||
int d;
|
int d;
|
||||||
char flagstr[128], buf[1024];
|
char flagstr[128], datestr[64], buf[1024];
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
if (data->flags) {
|
if (data->flags) {
|
||||||
|
@ -1915,8 +1929,22 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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,
|
imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
|
||||||
"APPEND \"%s\" %s", buf, flagstr );
|
"APPEND \"%s\" %s", buf, flagstr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <utime.h>
|
||||||
|
|
||||||
#define USE_DB 1
|
#define USE_DB 1
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -1124,6 +1125,8 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
||||||
}
|
}
|
||||||
fstat( fd, &st );
|
fstat( fd, &st );
|
||||||
data->len = st.st_size;
|
data->len = st.st_size;
|
||||||
|
if (data->date == -1)
|
||||||
|
data->date = st.st_mtime;
|
||||||
data->data = nfmalloc( data->len );
|
data->data = nfmalloc( data->len );
|
||||||
if (read( fd, data->data, data->len ) != data->len) {
|
if (read( fd, data->data, data->len ) != data->len) {
|
||||||
sys_error( "Maildir error: cannot read %s", buf );
|
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 );
|
cb( DRV_BOX_BAD, 0, aux );
|
||||||
return;
|
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. */
|
/* 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 );
|
nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%s%s", box, subdirs[!(data->flags & F_SEEN)], base, fbuf );
|
||||||
if (rename( buf, nbuf )) {
|
if (rename( buf, nbuf )) {
|
||||||
|
|
|
@ -166,6 +166,7 @@ typedef struct channel_conf {
|
||||||
string_list_t *patterns;
|
string_list_t *patterns;
|
||||||
int ops[2];
|
int ops[2];
|
||||||
unsigned max_messages; /* for slave only */
|
unsigned max_messages; /* for slave only */
|
||||||
|
unsigned use_internal_date:1;
|
||||||
} channel_conf_t;
|
} channel_conf_t;
|
||||||
|
|
||||||
typedef struct group_conf {
|
typedef struct group_conf {
|
||||||
|
@ -245,6 +246,7 @@ set_bad_callback( store_t *ctx, void (*cb)( void *aux ), void *aux )
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *data;
|
char *data;
|
||||||
int len;
|
int len;
|
||||||
|
time_t date;
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
} msg_data_t;
|
} msg_data_t;
|
||||||
|
|
||||||
|
|
10
src/mbsync.1
10
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.
|
which in turn are overridden by command line switches.
|
||||||
..
|
..
|
||||||
.TP
|
.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}
|
\fBSyncState\fR {\fB*\fR|\fIpath\fR}
|
||||||
Set the location of this Channel's synchronization state files. \fB*\fR means
|
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
|
that the state should be saved in a file named .mbsyncstate in the
|
||||||
|
|
|
@ -281,6 +281,7 @@ copy_msg( copy_vars_t *vars )
|
||||||
|
|
||||||
t ^= 1;
|
t ^= 1;
|
||||||
vars->data.flags = vars->msg->flags;
|
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 ));
|
DRIVER_CALL_RET(fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user