Merge branch 'isync_1_2_branch'
Conflicts: configure.ac src/drv_imap.c
This commit is contained in:
commit
bcd43e2c66
2
README
2
README
|
@ -61,7 +61,7 @@ isync executable still exists; it is a compatibility wrapper around mbsync.
|
||||||
|
|
||||||
* Requirements
|
* Requirements
|
||||||
|
|
||||||
Berkley DB 4.2+ (optional)
|
Berkeley DB 4.1+ (optional)
|
||||||
OpenSSL for TLS/SSL support (optional)
|
OpenSSL for TLS/SSL support (optional)
|
||||||
|
|
||||||
* Installation
|
* Installation
|
||||||
|
|
3
TODO
3
TODO
|
@ -3,9 +3,6 @@ f{,data}sync() usage could be optimized by batching the calls.
|
||||||
add some marker about message being already [remotely] trashed.
|
add some marker about message being already [remotely] trashed.
|
||||||
real transactions would be certainly not particularly useful ...
|
real transactions would be certainly not particularly useful ...
|
||||||
|
|
||||||
make sync_chans() aware of servers, so a bad server (e.g., wrong password)
|
|
||||||
won't cause the same error message for every attached store.
|
|
||||||
|
|
||||||
make SSL (connect) timeouts produce a bit more than "Unidentified socket error".
|
make SSL (connect) timeouts produce a bit more than "Unidentified socket error".
|
||||||
|
|
||||||
uidvalidity lock timeout handling would be a good idea.
|
uidvalidity lock timeout handling would be a good idea.
|
||||||
|
|
24
configure.ac
24
configure.ac
|
@ -139,26 +139,36 @@ if test "x$ob_cv_with_sasl" != xno; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST(SASL_LIBS)
|
AC_SUBST(SASL_LIBS)
|
||||||
|
|
||||||
AC_CACHE_CHECK([for Berkley DB >= 4.2], ac_cv_berkdb4,
|
AC_CACHE_CHECK([for Berkeley DB >= 4.1], ac_cv_berkdb4,
|
||||||
[ac_cv_berkdb4=no
|
[ac_cv_berkdb4=no
|
||||||
|
sav_LDFLAGS=$LDFLAGS
|
||||||
|
LDFLAGS="$LDFLAGS -ldb"
|
||||||
AC_TRY_LINK([#include <db.h>],
|
AC_TRY_LINK([#include <db.h>],
|
||||||
[DB *db;
|
[DB *db;
|
||||||
|
db_create(&db, 0, 0);
|
||||||
db->truncate(db, 0, 0, 0);
|
db->truncate(db, 0, 0, 0);
|
||||||
db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0)],
|
db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0)],
|
||||||
[ac_cv_berkdb4=yes])])
|
[ac_cv_berkdb4=yes])
|
||||||
|
LDFLAGS=$sav_LDFLAGS
|
||||||
|
])
|
||||||
if test "x$ac_cv_berkdb4" = xyes; then
|
if test "x$ac_cv_berkdb4" = xyes; then
|
||||||
AC_SUBST([DB_LIBS], ["-ldb"])
|
AC_SUBST([DB_LIBS], ["-ldb"])
|
||||||
AC_DEFINE(USE_DB, 1, [if Berkley DB should be used])
|
AC_DEFINE(USE_DB, 1, [if Berkeley DB should be used])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
have_zlib=
|
have_zlib=
|
||||||
AC_CHECK_LIB([z], [deflate],
|
AC_ARG_WITH(zlib,
|
||||||
|
AS_HELP_STRING([--with-zlib], [use zlib [detect]]),
|
||||||
|
[ob_cv_with_zlib=$withval])
|
||||||
|
if test "x$ob_cv_with_zlib" != xno; then
|
||||||
|
AC_CHECK_LIB([z], [deflate],
|
||||||
[AC_CHECK_HEADER(zlib.h,
|
[AC_CHECK_HEADER(zlib.h,
|
||||||
[have_zlib=1
|
[have_zlib=1
|
||||||
AC_SUBST([Z_LIBS], ["-lz"])
|
AC_SUBST([Z_LIBS], ["-lz"])
|
||||||
AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])]
|
AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])]
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(compat,
|
AC_ARG_ENABLE(compat,
|
||||||
AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
|
AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
|
||||||
|
@ -189,8 +199,8 @@ else
|
||||||
AC_MSG_RESULT([Not using zlib])
|
AC_MSG_RESULT([Not using zlib])
|
||||||
fi
|
fi
|
||||||
if test "x$ac_cv_berkdb4" = xyes; then
|
if test "x$ac_cv_berkdb4" = xyes; then
|
||||||
AC_MSG_RESULT([Using Berkley DB])
|
AC_MSG_RESULT([Using Berkeley DB])
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([Not using Berkley DB])
|
AC_MSG_RESULT([Not using Berkeley DB])
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT()
|
AC_MSG_RESULT()
|
||||||
|
|
102
src/drv_imap.c
102
src/drv_imap.c
|
@ -267,7 +267,7 @@ done_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, int response )
|
||||||
free( cmd );
|
free( cmd );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
{
|
{
|
||||||
int bufl, litplus, iovcnt = 1;
|
int bufl, litplus, iovcnt = 1;
|
||||||
|
@ -313,8 +313,7 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
iov[2].takeOwn = KeepOwn;
|
iov[2].takeOwn = KeepOwn;
|
||||||
iovcnt = 3;
|
iovcnt = 3;
|
||||||
}
|
}
|
||||||
if (socket_write( &ctx->conn, iov, iovcnt ) < 0)
|
socket_write( &ctx->conn, iov, iovcnt );
|
||||||
goto bail;
|
|
||||||
if (cmd->param.to_trash && ctx->trashnc == TrashUnknown)
|
if (cmd->param.to_trash && ctx->trashnc == TrashUnknown)
|
||||||
ctx->trashnc = TrashChecking;
|
ctx->trashnc = TrashChecking;
|
||||||
cmd->next = 0;
|
cmd->next = 0;
|
||||||
|
@ -322,15 +321,10 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
ctx->in_progress_append = &cmd->next;
|
ctx->in_progress_append = &cmd->next;
|
||||||
ctx->num_in_progress++;
|
ctx->num_in_progress++;
|
||||||
socket_expect_read( &ctx->conn, 1 );
|
socket_expect_read( &ctx->conn, 1 );
|
||||||
return 0;
|
|
||||||
|
|
||||||
bail:
|
|
||||||
done_imap_cmd( ctx, cmd, RESP_CANCEL );
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_submittable( imap_store_t *ctx, struct imap_cmd *cmd )
|
cmd_sendable( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
{
|
{
|
||||||
struct imap_cmd *cmdp;
|
struct imap_cmd *cmdp;
|
||||||
|
|
||||||
|
@ -343,18 +337,16 @@ cmd_submittable( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
ctx->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress;
|
ctx->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
flush_imap_cmds( imap_store_t *ctx )
|
flush_imap_cmds( imap_store_t *ctx )
|
||||||
{
|
{
|
||||||
struct imap_cmd *cmd;
|
struct imap_cmd *cmd;
|
||||||
|
|
||||||
while ((cmd = ctx->pending) && cmd_submittable( ctx, cmd )) {
|
if ((cmd = ctx->pending) && cmd_sendable( ctx, cmd )) {
|
||||||
if (!(ctx->pending = cmd->next))
|
if (!(ctx->pending = cmd->next))
|
||||||
ctx->pending_append = &ctx->pending;
|
ctx->pending_append = &ctx->pending;
|
||||||
if (send_imap_cmd( ctx, cmd ) < 0)
|
send_imap_cmd( ctx, cmd );
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -370,7 +362,7 @@ cancel_pending_imap_cmds( imap_store_t *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cancel_submitted_imap_cmds( imap_store_t *ctx )
|
cancel_sent_imap_cmds( imap_store_t *ctx )
|
||||||
{
|
{
|
||||||
struct imap_cmd *cmd;
|
struct imap_cmd *cmd;
|
||||||
|
|
||||||
|
@ -382,7 +374,7 @@ cancel_submitted_imap_cmds( imap_store_t *ctx )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
{
|
{
|
||||||
assert( ctx );
|
assert( ctx );
|
||||||
|
@ -390,7 +382,7 @@ submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
assert( cmd );
|
assert( cmd );
|
||||||
assert( cmd->param.done );
|
assert( cmd->param.done );
|
||||||
|
|
||||||
if ((ctx->pending && !cmd->param.high_prio) || !cmd_submittable( ctx, cmd )) {
|
if ((ctx->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) {
|
||||||
if (ctx->pending && cmd->param.high_prio) {
|
if (ctx->pending && cmd->param.high_prio) {
|
||||||
cmd->next = ctx->pending;
|
cmd->next = ctx->pending;
|
||||||
ctx->pending = cmd;
|
ctx->pending = cmd;
|
||||||
|
@ -399,10 +391,9 @@ submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||||
*ctx->pending_append = cmd;
|
*ctx->pending_append = cmd;
|
||||||
ctx->pending_append = &cmd->next;
|
ctx->pending_append = &cmd->next;
|
||||||
}
|
}
|
||||||
return 0;
|
} else {
|
||||||
|
send_imap_cmd( ctx, cmd );
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_imap_cmd( ctx, cmd );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Minimal printf() replacement that supports an %\s format sequence to print backslash-escaped
|
/* Minimal printf() replacement that supports an %\s format sequence to print backslash-escaped
|
||||||
|
@ -487,7 +478,7 @@ imap_vprintf( const char *fmt, va_list ap )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
imap_exec( imap_store_t *ctx, struct imap_cmd *cmdp,
|
imap_exec( imap_store_t *ctx, struct imap_cmd *cmdp,
|
||||||
void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response ),
|
void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response ),
|
||||||
const char *fmt, ... )
|
const char *fmt, ... )
|
||||||
|
@ -500,7 +491,7 @@ imap_exec( imap_store_t *ctx, struct imap_cmd *cmdp,
|
||||||
va_start( ap, fmt );
|
va_start( ap, fmt );
|
||||||
cmdp->cmd = imap_vprintf( fmt, ap );
|
cmdp->cmd = imap_vprintf( fmt, ap );
|
||||||
va_end( ap );
|
va_end( ap );
|
||||||
return submit_imap_cmd( ctx, cmdp );
|
submit_imap_cmd( ctx, cmdp );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1337,8 +1328,7 @@ imap_socket_read( void *aux )
|
||||||
iov[1].buf = "\r\n";
|
iov[1].buf = "\r\n";
|
||||||
iov[1].len = 2;
|
iov[1].len = 2;
|
||||||
iov[1].takeOwn = KeepOwn;
|
iov[1].takeOwn = KeepOwn;
|
||||||
if (socket_write( &ctx->conn, iov, 2 ) < 0)
|
socket_write( &ctx->conn, iov, 2 );
|
||||||
return;
|
|
||||||
} else if (cmdp->param.cont) {
|
} else if (cmdp->param.cont) {
|
||||||
if (cmdp->param.cont( ctx, cmdp, cmd ))
|
if (cmdp->param.cont( ctx, cmdp, cmd ))
|
||||||
return;
|
return;
|
||||||
|
@ -1376,9 +1366,8 @@ imap_socket_read( void *aux )
|
||||||
cmd2->orig_cmd = cmdp;
|
cmd2->orig_cmd = cmdp;
|
||||||
cmd2->gen.param.high_prio = 1;
|
cmd2->gen.param.high_prio = 1;
|
||||||
p = strchr( cmdp->cmd, '"' );
|
p = strchr( cmdp->cmd, '"' );
|
||||||
if (imap_exec( ctx, &cmd2->gen, get_cmd_result_p2,
|
imap_exec( ctx, &cmd2->gen, get_cmd_result_p2,
|
||||||
"CREATE %.*s", imap_strchr( p + 1, '"' ) - p + 1, p ) < 0)
|
"CREATE %.*s", imap_strchr( p + 1, '"' ) - p + 1, p );
|
||||||
return;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
resp = RESP_NO;
|
resp = RESP_NO;
|
||||||
|
@ -1387,7 +1376,11 @@ imap_socket_read( void *aux )
|
||||||
} else /*if (!strcmp( "BAD", arg ))*/
|
} else /*if (!strcmp( "BAD", arg ))*/
|
||||||
resp = RESP_CANCEL;
|
resp = RESP_CANCEL;
|
||||||
error( "IMAP command '%s' returned an error: %s %s\n",
|
error( "IMAP command '%s' returned an error: %s %s\n",
|
||||||
!starts_with( cmdp->cmd, -1, "LOGIN", 5 ) ? cmdp->cmd : "LOGIN <user> <pass>",
|
starts_with( cmdp->cmd, -1, "LOGIN", 5 ) ?
|
||||||
|
"LOGIN <user> <pass>" :
|
||||||
|
starts_with( cmdp->cmd, -1, "AUTHENTICATE PLAIN", 18 ) ?
|
||||||
|
"AUTHENTICATE PLAIN <authdata>" :
|
||||||
|
cmdp->cmd,
|
||||||
arg, cmd ? cmd : "" );
|
arg, cmd ? cmd : "" );
|
||||||
}
|
}
|
||||||
doresp:
|
doresp:
|
||||||
|
@ -1405,8 +1398,7 @@ imap_socket_read( void *aux )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flush_imap_cmds( ctx ) < 0)
|
flush_imap_cmds( ctx );
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
imap_invoke_bad_callback( ctx );
|
imap_invoke_bad_callback( ctx );
|
||||||
}
|
}
|
||||||
|
@ -1440,7 +1432,7 @@ imap_cancel_store( store_t *gctx )
|
||||||
sasl_dispose( &ctx->sasl );
|
sasl_dispose( &ctx->sasl );
|
||||||
#endif
|
#endif
|
||||||
socket_close( &ctx->conn );
|
socket_close( &ctx->conn );
|
||||||
cancel_submitted_imap_cmds( ctx );
|
cancel_sent_imap_cmds( ctx );
|
||||||
cancel_pending_imap_cmds( ctx );
|
cancel_pending_imap_cmds( ctx );
|
||||||
free_generic_messages( ctx->gen.msgs );
|
free_generic_messages( ctx->gen.msgs );
|
||||||
free_string_list( ctx->gen.boxes );
|
free_string_list( ctx->gen.boxes );
|
||||||
|
@ -1603,7 +1595,7 @@ imap_open_store( store_conf_t *conf, const char *label,
|
||||||
|
|
||||||
socket_init( &ctx->conn, &srvc->sconf,
|
socket_init( &ctx->conn, &srvc->sconf,
|
||||||
(void (*)( void * ))imap_invoke_bad_callback,
|
(void (*)( void * ))imap_invoke_bad_callback,
|
||||||
imap_socket_read, (int (*)(void *))flush_imap_cmds, ctx );
|
imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx );
|
||||||
socket_connect( &ctx->conn, imap_open_store_connected );
|
socket_connect( &ctx->conn, imap_open_store_connected );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1929,7 +1921,8 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char *
|
||||||
iov[iovcnt].len = 2;
|
iov[iovcnt].len = 2;
|
||||||
iov[iovcnt].takeOwn = KeepOwn;
|
iov[iovcnt].takeOwn = KeepOwn;
|
||||||
iovcnt++;
|
iovcnt++;
|
||||||
return socket_write( &ctx->conn, iov, iovcnt );
|
socket_write( &ctx->conn, iov, iovcnt );
|
||||||
|
return 0;
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
imap_open_store_bail( ctx, FAIL_FINAL );
|
imap_open_store_bail( ctx, FAIL_FINAL );
|
||||||
|
@ -2289,7 +2282,7 @@ imap_prepare_load_box( store_t *gctx, int opts )
|
||||||
gctx->opts = opts;
|
gctx->opts = opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imap_submit_load( imap_store_t *, const char *, int, struct imap_cmd_refcounted_state * );
|
static void imap_submit_load( imap_store_t *, const char *, int, struct imap_cmd_refcounted_state * );
|
||||||
|
|
||||||
static void
|
static void
|
||||||
imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int *excs, int nexcs,
|
imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int *excs, int nexcs,
|
||||||
|
@ -2316,16 +2309,14 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int *excs, int
|
||||||
if (i != j)
|
if (i != j)
|
||||||
bl += sprintf( buf + bl, ":%d", excs[i] );
|
bl += sprintf( buf + bl, ":%d", excs[i] );
|
||||||
}
|
}
|
||||||
if (imap_submit_load( ctx, buf, 0, sts ) < 0)
|
imap_submit_load( ctx, buf, 0, sts );
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
if (maxuid == INT_MAX)
|
if (maxuid == INT_MAX)
|
||||||
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 1000000000;
|
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 1000000000;
|
||||||
if (maxuid >= minuid) {
|
if (maxuid >= minuid) {
|
||||||
if ((ctx->gen.opts & OPEN_FIND) && minuid < newuid) {
|
if ((ctx->gen.opts & OPEN_FIND) && minuid < newuid) {
|
||||||
sprintf( buf, "%d:%d", minuid, newuid - 1 );
|
sprintf( buf, "%d:%d", minuid, newuid - 1 );
|
||||||
if (imap_submit_load( ctx, buf, 0, sts ) < 0)
|
imap_submit_load( ctx, buf, 0, sts );
|
||||||
goto done;
|
|
||||||
if (newuid > maxuid)
|
if (newuid > maxuid)
|
||||||
goto done;
|
goto done;
|
||||||
sprintf( buf, "%d:%d", newuid, maxuid );
|
sprintf( buf, "%d:%d", newuid, maxuid );
|
||||||
|
@ -2340,10 +2331,10 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int *excs, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
imap_submit_load( imap_store_t *ctx, const char *buf, int tuids, struct imap_cmd_refcounted_state *sts )
|
imap_submit_load( imap_store_t *ctx, const char *buf, int tuids, struct imap_cmd_refcounted_state *sts )
|
||||||
{
|
{
|
||||||
return imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||||
"UID FETCH %s (UID%s%s%s)", buf,
|
"UID FETCH %s (UID%s%s%s)", buf,
|
||||||
(ctx->gen.opts & OPEN_FLAGS) ? " FLAGS" : "",
|
(ctx->gen.opts & OPEN_FLAGS) ? " FLAGS" : "",
|
||||||
(ctx->gen.opts & OPEN_SIZE) ? " RFC822.SIZE" : "",
|
(ctx->gen.opts & OPEN_SIZE) ? " RFC822.SIZE" : "",
|
||||||
|
@ -2404,14 +2395,14 @@ imap_make_flags( int flags, char *buf )
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags,
|
imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags,
|
||||||
struct imap_cmd_refcounted_state *sts )
|
struct imap_cmd_refcounted_state *sts )
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
buf[imap_make_flags( flags, buf )] = 0;
|
buf[imap_make_flags( flags, buf )] = 0;
|
||||||
return imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_set_flags_p2,
|
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_set_flags_p2,
|
||||||
"UID STORE %d %cFLAGS.SILENT %s", uid, what, buf );
|
"UID STORE %d %cFLAGS.SILENT %s", uid, what, buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2430,8 +2421,10 @@ imap_set_msg_flags( store_t *gctx, message_t *msg, int uid, int add, int del,
|
||||||
}
|
}
|
||||||
if (add || del) {
|
if (add || del) {
|
||||||
struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux );
|
struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux );
|
||||||
if ((add && imap_flags_helper( ctx, uid, '+', add, sts ) < 0) ||
|
if (add)
|
||||||
(del && imap_flags_helper( ctx, uid, '-', del, sts ) < 0)) {}
|
imap_flags_helper( ctx, uid, '+', add, sts );
|
||||||
|
if (del)
|
||||||
|
imap_flags_helper( ctx, uid, '-', del, sts );
|
||||||
imap_refcounted_done( sts );
|
imap_refcounted_done( sts );
|
||||||
} else {
|
} else {
|
||||||
cb( DRV_OK, aux );
|
cb( DRV_OK, aux );
|
||||||
|
@ -2482,9 +2475,8 @@ imap_close_box( store_t *gctx,
|
||||||
}
|
}
|
||||||
if (!bl)
|
if (!bl)
|
||||||
break;
|
break;
|
||||||
if (imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||||
"UID EXPUNGE %s", buf ) < 0)
|
"UID EXPUNGE %s", buf );
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
imap_refcounted_done( sts );
|
imap_refcounted_done( sts );
|
||||||
} else {
|
} else {
|
||||||
|
@ -2625,13 +2617,12 @@ imap_list_store( store_t *gctx, int flags,
|
||||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||||
struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux );
|
struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux );
|
||||||
|
|
||||||
if (((flags & LIST_PATH) && (!(flags & LIST_INBOX) || !is_inbox( ctx, ctx->prefix, -1 )) &&
|
if ((flags & LIST_PATH) && (!(flags & LIST_INBOX) || !is_inbox( ctx, ctx->prefix, -1 )))
|
||||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||||
"LIST \"\" \"%\\s*\"", ctx->prefix ) < 0) ||
|
"LIST \"\" \"%\\s*\"", ctx->prefix );
|
||||||
((flags & LIST_INBOX) && (!(flags & LIST_PATH) || *ctx->prefix) &&
|
if ((flags & LIST_INBOX) && (!(flags & LIST_PATH) || *ctx->prefix))
|
||||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||||
"LIST \"\" INBOX*" ) < 0))
|
"LIST \"\" INBOX*" );
|
||||||
{}
|
|
||||||
imap_refcounted_done( sts );
|
imap_refcounted_done( sts );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2695,8 +2686,9 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
/* Legacy SSL options */
|
/* Legacy SSL options */
|
||||||
int require_ssl = -1, use_imaps = -1;
|
int require_ssl = -1, use_imaps = -1;
|
||||||
int use_sslv2 = -1, use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1;
|
int use_sslv2 = -1, use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1;
|
||||||
int require_cram = -1;
|
|
||||||
#endif
|
#endif
|
||||||
|
/* Legacy SASL option */
|
||||||
|
int require_cram = -1;
|
||||||
|
|
||||||
if (!strcasecmp( "IMAPAccount", cfg->cmd )) {
|
if (!strcasecmp( "IMAPAccount", cfg->cmd )) {
|
||||||
server = nfcalloc( sizeof(*server) );
|
server = nfcalloc( sizeof(*server) );
|
||||||
|
@ -2829,6 +2821,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
use_tlsv11 = parse_bool( cfg );
|
use_tlsv11 = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseTLSv1.2", cfg->cmd ))
|
else if (!strcasecmp( "UseTLSv1.2", cfg->cmd ))
|
||||||
use_tlsv12 = parse_bool( cfg );
|
use_tlsv12 = parse_bool( cfg );
|
||||||
|
#endif
|
||||||
else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
|
else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
|
||||||
!strcasecmp( "AuthMechs", cfg->cmd )) {
|
!strcasecmp( "AuthMechs", cfg->cmd )) {
|
||||||
arg = cfg->val;
|
arg = cfg->val;
|
||||||
|
@ -2837,7 +2830,6 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
while ((arg = get_arg( cfg, ARG_OPTIONAL, 0 )));
|
while ((arg = get_arg( cfg, ARG_OPTIONAL, 0 )));
|
||||||
} else if (!strcasecmp( "RequireCRAM", cfg->cmd ))
|
} else if (!strcasecmp( "RequireCRAM", cfg->cmd ))
|
||||||
require_cram = parse_bool( cfg );
|
require_cram = parse_bool( cfg );
|
||||||
#endif
|
|
||||||
else if (!strcasecmp( "Tunnel", cfg->cmd ))
|
else if (!strcasecmp( "Tunnel", cfg->cmd ))
|
||||||
server->sconf.tunnel = nfstrdup( cfg->val );
|
server->sconf.tunnel = nfstrdup( cfg->val );
|
||||||
else if (store) {
|
else if (store) {
|
||||||
|
@ -2917,7 +2909,6 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
server->ssl_type = server->sconf.tunnel ? SSL_None : SSL_STARTTLS;
|
server->ssl_type = server->sconf.tunnel ? SSL_None : SSL_STARTTLS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBSSL
|
|
||||||
if (require_cram >= 0) {
|
if (require_cram >= 0) {
|
||||||
if (server->auth_mechs) {
|
if (server->auth_mechs) {
|
||||||
error( "%s '%s': The deprecated RequireCRAM option is mutually exlusive with AuthMech.\n", type, name );
|
error( "%s '%s': The deprecated RequireCRAM option is mutually exlusive with AuthMech.\n", type, name );
|
||||||
|
@ -2928,7 +2919,6 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
if (require_cram)
|
if (require_cram)
|
||||||
add_string_list(&server->auth_mechs, "CRAM-MD5");
|
add_string_list(&server->auth_mechs, "CRAM-MD5");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!server->auth_mechs)
|
if (!server->auth_mechs)
|
||||||
add_string_list( &server->auth_mechs, "*" );
|
add_string_list( &server->auth_mechs, "*" );
|
||||||
if (!server->sconf.port)
|
if (!server->sconf.port)
|
||||||
|
|
96
src/mbsync.1
96
src/mbsync.1
|
@ -192,17 +192,17 @@ See \fBRECOMMENDATIONS\fR and \fBINHERENT PROBLEMS\fR below.
|
||||||
(Default: none)
|
(Default: none)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBTrashNewOnly\fR \fIyes\fR|\fIno\fR
|
\fBTrashNewOnly\fR \fByes\fR|\fBno\fR
|
||||||
When trashing, copy only not yet propagated messages. This makes sense if the
|
When trashing, copy only not yet propagated messages. This makes sense if the
|
||||||
remote Store has a \fBTrash\fR as well (with \fBTrashNewOnly\fR \fIno\fR).
|
remote Store has a \fBTrash\fR as well (with \fBTrashNewOnly\fR \fBno\fR).
|
||||||
(Default: \fIno\fR)
|
(Default: \fBno\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBTrashRemoteNew\fR \fIyes\fR|\fIno\fR
|
\fBTrashRemoteNew\fR \fByes\fR|\fBno\fR
|
||||||
When expunging the remote Store, copy not yet propagated messages to this
|
When expunging the remote Store, copy not yet propagated messages to this
|
||||||
Store's \fBTrash\fR. When using this, the remote Store does not need an own
|
Store's \fBTrash\fR. When using this, the remote Store does not need an own
|
||||||
\fBTrash\fR at all, yet all messages are archived.
|
\fBTrash\fR at all, yet all messages are archived.
|
||||||
(Default: \fIno\fR)
|
(Default: \fBno\fR)
|
||||||
..
|
..
|
||||||
.SS Maildir Stores
|
.SS Maildir Stores
|
||||||
The reference point for relative \fBPath\fRs is the current working directory.
|
The reference point for relative \fBPath\fRs is the current working directory.
|
||||||
|
@ -237,11 +237,11 @@ Use \fBmdconvert\fR to convert mailboxes from one scheme to the other.
|
||||||
Define the Maildir Store \fIname\fR, opening a section for its parameters.
|
Define the Maildir Store \fIname\fR, opening a section for its parameters.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBAltMap\fR \fIyes\fR|\fIno\fR
|
\fBAltMap\fR \fByes\fR|\fBno\fR
|
||||||
Use the \fBalternative\fR UID storage scheme for mailboxes in this Store.
|
Use the \fBalternative\fR UID storage scheme for mailboxes in this Store.
|
||||||
This does not affect mailboxes that do already have a UID storage scheme;
|
This does not affect mailboxes that do already have a UID storage scheme;
|
||||||
use \fBmdconvert\fR to change it.
|
use \fBmdconvert\fR to change it.
|
||||||
(Default: \fIno\fR)
|
(Default: \fBno\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBInbox\fR \fIpath\fR
|
\fBInbox\fR \fIpath\fR
|
||||||
|
@ -286,7 +286,7 @@ Define the IMAP4 Account \fIname\fR, opening a section for its parameters.
|
||||||
Specify the DNS name or IP address of the IMAP server.
|
Specify the DNS name or IP address of the IMAP server.
|
||||||
.br
|
.br
|
||||||
If \fBTunnel\fR is used, this setting is needed only if \fBSSLType\fR is
|
If \fBTunnel\fR is used, this setting is needed only if \fBSSLType\fR is
|
||||||
not \fINone\fR and \fBCertificateFile\fR is not used,
|
not \fBNone\fR and \fBCertificateFile\fR is not used,
|
||||||
in which case the host name is used for certificate subject verification.
|
in which case the host name is used for certificate subject verification.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
|
@ -309,7 +309,7 @@ Specify the login name on the IMAP server.
|
||||||
.TP
|
.TP
|
||||||
\fBPass\fR \fIpassword\fR
|
\fBPass\fR \fIpassword\fR
|
||||||
Specify the password for \fIusername\fR on the IMAP server.
|
Specify the password for \fIusername\fR on the IMAP server.
|
||||||
Note that this option is \fBNOT\fR required.
|
Note that this option is \fInot\fR required.
|
||||||
If neither a password nor a password command is specified in the
|
If neither a password nor a password command is specified in the
|
||||||
configuration file, \fBmbsync\fR will prompt you for a password.
|
configuration file, \fBmbsync\fR will prompt you for a password.
|
||||||
..
|
..
|
||||||
|
@ -341,21 +341,21 @@ of this list, the list supplied by the server, and the installed SASL modules.
|
||||||
(Default: \fB*\fR)
|
(Default: \fB*\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBSSLType\fR {\fINone\fR|\fISTARTTLS\fR|\fIIMAPS\fR}
|
\fBSSLType\fR {\fBNone\fR|\fBSTARTTLS\fR|\fBIMAPS\fR}
|
||||||
Select the connection security/encryption method:
|
Select the connection security/encryption method:
|
||||||
.br
|
.br
|
||||||
\fINone\fR - no security.
|
\fBNone\fR - no security.
|
||||||
This is the default when \fBTunnel\fR is set, as tunnels are usually secure.
|
This is the default when \fBTunnel\fR is set, as tunnels are usually secure.
|
||||||
.br
|
.br
|
||||||
\fISTARTTLS\fR - security is established via the STARTTLS extension
|
\fBSTARTTLS\fR - security is established via the STARTTLS extension
|
||||||
after connecting the regular IMAP port 143. Most servers support this,
|
after connecting the regular IMAP port 143. Most servers support this,
|
||||||
so it is the default (unless a tunnel is used).
|
so it is the default (unless a tunnel is used).
|
||||||
.br
|
.br
|
||||||
\fIIMAPS\fR - security is established by starting SSL/TLS negotiation
|
\fBIMAPS\fR - security is established by starting SSL/TLS negotiation
|
||||||
right after connecting the secure IMAP port 993.
|
right after connecting the secure IMAP port 993.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBSSLVersions\fR [\fISSLv2\fR] [\fISSLv3\fR] [\fITLSv1\fR] [\fITLSv1.1\fR] [\fITLSv1.2\fR]
|
\fBSSLVersions\fR [\fBSSLv2\fR] [\fBSSLv3\fR] [\fBTLSv1\fR] [\fBTLSv1.1\fR] [\fBTLSv1.2\fR]
|
||||||
Select the acceptable SSL/TLS versions.
|
Select the acceptable SSL/TLS versions.
|
||||||
Use of SSLv2 is strongly discouraged for security reasons, but might be the
|
Use of SSLv2 is strongly discouraged for security reasons, but might be the
|
||||||
only option on some very old servers.
|
only option on some very old servers.
|
||||||
|
@ -363,9 +363,9 @@ Generally, the newest TLS version is recommended, but as this confuses some
|
||||||
servers, \fBTLSv1\fR is the default.
|
servers, \fBTLSv1\fR is the default.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBSystemCertificates\fR \fIyes\fR|\fIno\fR
|
\fBSystemCertificates\fR \fByes\fR|\fBno\fR
|
||||||
Whether the system's default root cerificate store should be loaded.
|
Whether the system's default root cerificate store should be loaded.
|
||||||
(Default: \fIyes\fR)
|
(Default: \fByes\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBCertificateFile\fR \fIpath\fR
|
\fBCertificateFile\fR \fIpath\fR
|
||||||
|
@ -407,18 +407,18 @@ directly in the Store's section - this makes sense if an Account is used for
|
||||||
one Store only anyway.
|
one Store only anyway.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBUseNamespace\fR \fIyes\fR|\fIno\fR
|
\fBUseNamespace\fR \fByes\fR|\fBno\fR
|
||||||
Selects whether the server's first "personal" NAMESPACE should be prefixed to
|
Selects whether the server's first "personal" NAMESPACE should be prefixed to
|
||||||
mailbox names. Disabling this makes sense for some broken IMAP servers.
|
mailbox names. Disabling this makes sense for some broken IMAP servers.
|
||||||
This option is meaningless if a \fBPath\fR was specified.
|
This option is meaningless if a \fBPath\fR was specified.
|
||||||
(Default: \fIyes\fR)
|
(Default: \fByes\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBPathDelimiter\fR \fIdelim\fR
|
\fBPathDelimiter\fR \fIdelim\fR
|
||||||
Specify the server's hierarchy delimiter.
|
Specify the server's hierarchy delimiter.
|
||||||
(Default: taken from the server's first "personal" NAMESPACE)
|
(Default: taken from the server's first "personal" NAMESPACE)
|
||||||
.br
|
.br
|
||||||
Do \fBNOT\fR abuse this to re-interpret the hierarchy.
|
Do \fInot\fR abuse this to re-interpret the hierarchy.
|
||||||
Use \fBFlatten\fR instead.
|
Use \fBFlatten\fR instead.
|
||||||
..
|
..
|
||||||
.SS Channels
|
.SS Channels
|
||||||
|
@ -471,56 +471,56 @@ If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
|
||||||
(Default: \fI0\fR).
|
(Default: \fI0\fR).
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBExpireUnread\fR \fIyes\fR|\fIno\fR
|
\fBExpireUnread\fR \fByes\fR|\fBno\fR
|
||||||
Selects whether unread messages should be affected by \fBMaxMessages\fR.
|
Selects whether unread messages should be affected by \fBMaxMessages\fR.
|
||||||
Normally, unread messages are considered important and thus never expired.
|
Normally, unread messages are considered important and thus never expired.
|
||||||
This ensures that you never miss new messages even after an extended absence.
|
This ensures that you never miss new messages even after an extended absence.
|
||||||
However, if your archive contains large amounts of unread messages by design,
|
However, if your archive contains large amounts of unread messages by design,
|
||||||
treating them as important would practically defeat \fBMaxMessages\fR. In this
|
treating them as important would practically defeat \fBMaxMessages\fR. In this
|
||||||
case you need to enable this option.
|
case you need to enable this option.
|
||||||
(Default: \fIno\fR).
|
(Default: \fBno\fR).
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBSync\fR {\fINone\fR|[\fIPull\fR] [\fIPush\fR] [\fINew\fR] [\fIReNew\fR] [\fIDelete\fR] [\fIFlags\fR]|\fIAll\fR}
|
\fBSync\fR {\fBNone\fR|[\fBPull\fR] [\fBPush\fR] [\fBNew\fR] [\fBReNew\fR] [\fBDelete\fR] [\fBFlags\fR]|\fBAll\fR}
|
||||||
Select the synchronization operation(s) to perform:
|
Select the synchronization operation(s) to perform:
|
||||||
.br
|
.br
|
||||||
\fIPull\fR - propagate changes from Master to Slave.
|
\fBPull\fR - propagate changes from Master to Slave.
|
||||||
.br
|
.br
|
||||||
\fIPush\fR - propagate changes from Slave to Master.
|
\fBPush\fR - propagate changes from Slave to Master.
|
||||||
.br
|
.br
|
||||||
\fINew\fR - propagate newly appeared messages.
|
\fBNew\fR - propagate newly appeared messages.
|
||||||
.br
|
.br
|
||||||
\fIReNew\fR - previously refused messages are re-evaluated for propagation.
|
\fBReNew\fR - previously refused messages are re-evaluated for propagation.
|
||||||
Useful after flagging affected messages in the source Store or enlarging
|
Useful after flagging affected messages in the source Store or enlarging
|
||||||
MaxSize in the destination Store.
|
MaxSize in the destination Store.
|
||||||
.br
|
.br
|
||||||
\fIDelete\fR - propagate message deletions. This applies only to messages that
|
\fBDelete\fR - propagate message deletions. This applies only to messages that
|
||||||
are actually gone, i.e., were expunged. The affected messages in the remote
|
are actually gone, i.e., were expunged. The affected messages in the remote
|
||||||
Store are marked as deleted only, i.e., they won't be really deleted until
|
Store are marked as deleted only, i.e., they won't be really deleted until
|
||||||
that Store is expunged.
|
that Store is expunged.
|
||||||
.br
|
.br
|
||||||
\fIFlags\fR - propagate flag changes. Note that Deleted/Trashed is a flag as
|
\fBFlags\fR - propagate flag changes. Note that Deleted/Trashed is a flag as
|
||||||
well; this is particularly interesting if you use \fBmutt\fR with the
|
well; this is particularly interesting if you use \fBmutt\fR with the
|
||||||
maildir_trash option.
|
maildir_trash option.
|
||||||
.br
|
.br
|
||||||
\fIAll\fR (\fB--full\fR on the command line) - all of the above.
|
\fBAll\fR (\fB--full\fR on the command line) - all of the above.
|
||||||
This is the global default.
|
This is the global default.
|
||||||
.br
|
.br
|
||||||
\fINone\fR (\fB--noop\fR on the command line) - don't propagate anything.
|
\fBNone\fR (\fB--noop\fR on the command line) - don't propagate anything.
|
||||||
Useful if you want to expunge only.
|
Useful if you want to expunge only.
|
||||||
.IP
|
.IP
|
||||||
\fIPull\fR and \fIPush\fR are direction flags, while \fINew\fR, \fIReNew\fR,
|
\fBPull\fR and \fBPush\fR are direction flags, while \fBNew\fR, \fBReNew\fR,
|
||||||
\fIDelete\fR and \fIFlags\fR are type flags. The two flag classes make up a
|
\fBDelete\fR and \fBFlags\fR are type flags. The two flag classes make up a
|
||||||
two-dimensional matrix (a table). Its cells are the individual actions to
|
two-dimensional matrix (a table). Its cells are the individual actions to
|
||||||
perform. There are two styles of asserting the cells:
|
perform. There are two styles of asserting the cells:
|
||||||
.br
|
.br
|
||||||
In the first style, the flags select entire rows/colums in the matrix. Only
|
In the first style, the flags select entire rows/colums in the matrix. Only
|
||||||
the cells which are selected both horizontally and vertically are asserted.
|
the cells which are selected both horizontally and vertically are asserted.
|
||||||
Specifying no flags from a class is like specifying all flags from this class.
|
Specifying no flags from a class is like specifying all flags from this class.
|
||||||
For example, "\fBSync\fR\ \fIPull\fR\ \fINew\fR\ \fIFlags\fR" will propagate
|
For example, "\fBSync\fR\ \fBPull\fR\ \fBNew\fR\ \fBFlags\fR" will propagate
|
||||||
new messages and flag changes from the Master to the Slave,
|
new messages and flag changes from the Master to the Slave,
|
||||||
"\fBSync\fR\ \fINew\fR\ \fIDelete\fR" will propagate message arrivals and
|
"\fBSync\fR\ \fBNew\fR\ \fBDelete\fR" will propagate message arrivals and
|
||||||
deletions both ways, and "\fBSync\fR\ \fIPush\fR" will propagate all changes
|
deletions both ways, and "\fBSync\fR\ \fBPush\fR" will propagate all changes
|
||||||
from the Slave to the Master.
|
from the Slave to the Master.
|
||||||
.br
|
.br
|
||||||
In the second style, direction flags are concatenated with type flags; every
|
In the second style, direction flags are concatenated with type flags; every
|
||||||
|
@ -528,22 +528,22 @@ compound flag immediately asserts a cell in the matrix. In addition to at least
|
||||||
one compound flag, the individual flags can be used as well, but as opposed to
|
one compound flag, the individual flags can be used as well, but as opposed to
|
||||||
the first style, they immediately assert all cells in their respective
|
the first style, they immediately assert all cells in their respective
|
||||||
row/column. For example,
|
row/column. For example,
|
||||||
"\fBSync\fR\ \fIPullNew\fR\ \fIPullDelete\fR\ \fIPush\fR" will propagate
|
"\fBSync\fR\ \fBPullNew\fR\ \fBPullDelete\fR\ \fBPush\fR" will propagate
|
||||||
message arrivals and deletions from the Master to the Slave and any changes
|
message arrivals and deletions from the Master to the Slave and any changes
|
||||||
from the Slave to the Master.
|
from the Slave to the Master.
|
||||||
Note that it is not allowed to assert a cell in two ways, e.g.
|
Note that it is not allowed to assert a cell in two ways, e.g.
|
||||||
"\fBSync\fR\ \fIPullNew\fR\ \fIPull\fR" and
|
"\fBSync\fR\ \fBPullNew\fR\ \fBPull\fR" and
|
||||||
"\fBSync\fR\ \fIPullNew\fR\ \fIDelete\fR\ \fIPush\fR" induce error messages.
|
"\fBSync\fR\ \fBPullNew\fR\ \fBDelete\fR\ \fBPush\fR" induce error messages.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBCreate\fR {\fINone\fR|\fIMaster\fR|\fISlave\fR|\fIBoth\fR}
|
\fBCreate\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR}
|
||||||
Automatically create missing mailboxes [on the Master/Slave].
|
Automatically create missing mailboxes [on the Master/Slave].
|
||||||
Otherwise print an error message and skip that mailbox pair if a mailbox
|
Otherwise print an error message and skip that mailbox pair if a mailbox
|
||||||
and the corresponding sync state does not exist.
|
and the corresponding sync state does not exist.
|
||||||
(Global default: \fINone\fR)
|
(Global default: \fBNone\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBRemove\fR {\fINone\fR|\fIMaster\fR|\fISlave\fR|\fIBoth\fR}
|
\fBRemove\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR}
|
||||||
Propagate mailbox deletions [to the Master/Slave].
|
Propagate mailbox deletions [to the Master/Slave].
|
||||||
Otherwise print an error message and skip that mailbox pair if a mailbox
|
Otherwise print an error message and skip that mailbox pair if a mailbox
|
||||||
does not exist but the corresponding sync state does.
|
does not exist but the corresponding sync state does.
|
||||||
|
@ -553,23 +553,23 @@ mark them as deleted. This ensures compatibility with \fBSyncState *\fR.
|
||||||
.br
|
.br
|
||||||
Note that for safety, non-empty mailboxes are never deleted.
|
Note that for safety, non-empty mailboxes are never deleted.
|
||||||
.br
|
.br
|
||||||
(Global default: \fINone\fR)
|
(Global default: \fBNone\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBExpunge\fR {\fINone\fR|\fIMaster\fR|\fISlave\fR|\fIBoth\fR}
|
\fBExpunge\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR}
|
||||||
Permanently remove all messages [on the Master/Slave] marked for deletion.
|
Permanently remove all messages [on the Master/Slave] marked for deletion.
|
||||||
See \fBRECOMMENDATIONS\fR below.
|
See \fBRECOMMENDATIONS\fR below.
|
||||||
(Global default: \fINone\fR)
|
(Global default: \fBNone\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBCopyArrivalDate\fR {\fIyes\fR|\fIno\fR}
|
\fBCopyArrivalDate\fR {\fByes\fR|\fBno\fR}
|
||||||
Selects whether their arrival time should be propagated together with
|
Selects whether their arrival time should be propagated together with
|
||||||
the messages.
|
the messages.
|
||||||
Enabling this makes sense in order to keep the time stamp based message
|
Enabling this makes sense in order to keep the time stamp based message
|
||||||
sorting intact.
|
sorting intact.
|
||||||
Note that IMAP does not guarantee that the time stamp (termed \fBinternal
|
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.
|
date\fR) is actually the arrival time, but it is usually close enough.
|
||||||
(Default: \fIno\fR)
|
(Default: \fBno\fR)
|
||||||
..
|
..
|
||||||
.P
|
.P
|
||||||
\fBSync\fR, \fBCreate\fR, \fBRemove\fR, \fBExpunge\fR,
|
\fBSync\fR, \fBCreate\fR, \fBRemove\fR, \fBExpunge\fR,
|
||||||
|
@ -615,7 +615,7 @@ times within a Group.
|
||||||
..
|
..
|
||||||
.SS Global Options
|
.SS Global Options
|
||||||
.TP
|
.TP
|
||||||
\fBFSync\fR \fIyes\fR|\fIno\fR
|
\fBFSync\fR \fByes\fR|\fBno\fR
|
||||||
.br
|
.br
|
||||||
Selects whether \fBmbsync\fR performs forced flushing, which determines
|
Selects whether \fBmbsync\fR performs forced flushing, which determines
|
||||||
the level of data safety after system crashes and power outages.
|
the level of data safety after system crashes and power outages.
|
||||||
|
@ -624,7 +624,7 @@ data=ordered mode.
|
||||||
Enabling it is a wise choice for file systems mounted with data=writeback,
|
Enabling it is a wise choice for file systems mounted with data=writeback,
|
||||||
in particular modern systems like ext4, btrfs and xfs. The performance impact
|
in particular modern systems like ext4, btrfs and xfs. The performance impact
|
||||||
on older file systems may be disproportionate.
|
on older file systems may be disproportionate.
|
||||||
(Default: \fIyes\fR)
|
(Default: \fByes\fR)
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBFieldDelimiter\fR \fIdelim\fR
|
\fBFieldDelimiter\fR \fIdelim\fR
|
||||||
|
|
35
src/socket.c
35
src/socket.c
|
@ -80,7 +80,7 @@ ssl_return( const char *func, conn_t *conn, int ret )
|
||||||
/* Callers take the short path out, so signal higher layers from here. */
|
/* Callers take the short path out, so signal higher layers from here. */
|
||||||
conn->state = SCK_EOF;
|
conn->state = SCK_EOF;
|
||||||
conn->read_callback( conn->callback_aux );
|
conn->read_callback( conn->callback_aux );
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
sys_error( "Socket error: secure %s %s", func, conn->name );
|
sys_error( "Socket error: secure %s %s", func, conn->name );
|
||||||
} else {
|
} else {
|
||||||
|
@ -771,6 +771,7 @@ do_queued_write( conn_t *conn )
|
||||||
return -1;
|
return -1;
|
||||||
if (n != len) {
|
if (n != len) {
|
||||||
conn->write_offset += n;
|
conn->write_offset += n;
|
||||||
|
conn->writing = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
conn->write_offset = 0;
|
conn->write_offset = 0;
|
||||||
|
@ -780,7 +781,9 @@ do_queued_write( conn_t *conn )
|
||||||
if (conn->ssl && SSL_pending( conn->ssl ))
|
if (conn->ssl && SSL_pending( conn->ssl ))
|
||||||
conf_wakeup( &conn->ssl_fake, 0 );
|
conf_wakeup( &conn->ssl_fake, 0 );
|
||||||
#endif
|
#endif
|
||||||
return conn->write_callback( conn->callback_aux );
|
conn->writing = 0;
|
||||||
|
conn->write_callback( conn->callback_aux );
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -803,6 +806,8 @@ do_flush( conn_t *conn )
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
if (conn->out_z) {
|
if (conn->out_z) {
|
||||||
int buf_avail = conn->append_avail;
|
int buf_avail = conn->append_avail;
|
||||||
|
if (!conn->z_written)
|
||||||
|
return;
|
||||||
do {
|
do {
|
||||||
if (!bc) {
|
if (!bc) {
|
||||||
buf_avail = WRITE_CHUNK_SIZE;
|
buf_avail = WRITE_CHUNK_SIZE;
|
||||||
|
@ -828,6 +833,7 @@ do_flush( conn_t *conn )
|
||||||
} while (!conn->out_z->avail_out);
|
} while (!conn->out_z->avail_out);
|
||||||
conn->append_buf = bc;
|
conn->append_buf = bc;
|
||||||
conn->append_avail = buf_avail;
|
conn->append_avail = buf_avail;
|
||||||
|
conn->z_written = 0;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (bc) {
|
if (bc) {
|
||||||
|
@ -839,15 +845,15 @@ do_flush( conn_t *conn )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
{
|
{
|
||||||
int i, buf_avail, len, offset = 0, total = 0;
|
int i, buf_avail, len, offset = 0, total = 0;
|
||||||
buff_chunk_t *bc, *exwb = conn->write_buf;
|
buff_chunk_t *bc;
|
||||||
|
|
||||||
for (i = 0; i < iovcnt; i++)
|
for (i = 0; i < iovcnt; i++)
|
||||||
total += iov[i].len;
|
total += iov[i].len;
|
||||||
if (total >= WRITE_CHUNK_SIZE && pending_wakeup( &conn->fd_fake )) {
|
if (total >= WRITE_CHUNK_SIZE) {
|
||||||
/* If the new data is too big, queue the pending buffer to avoid latency. */
|
/* If the new data is too big, queue the pending buffer to avoid latency. */
|
||||||
do_flush( conn );
|
do_flush( conn );
|
||||||
}
|
}
|
||||||
|
@ -886,6 +892,7 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
bc->len = (char *)conn->out_z->next_out - bc->data;
|
bc->len = (char *)conn->out_z->next_out - bc->data;
|
||||||
buf_avail = conn->out_z->avail_out;
|
buf_avail = conn->out_z->avail_out;
|
||||||
len -= conn->out_z->avail_in;
|
len -= conn->out_z->avail_in;
|
||||||
|
conn->z_written = 1;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -914,17 +921,7 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
conn->append_avail = buf_avail;
|
conn->append_avail = buf_avail;
|
||||||
#endif
|
#endif
|
||||||
/* Queue the pending write once the main loop goes idle. */
|
conf_wakeup( &conn->fd_fake, 0 );
|
||||||
conf_wakeup( &conn->fd_fake,
|
|
||||||
#ifdef HAVE_LIBZ
|
|
||||||
/* Always give zlib a chance to flush its internal buffer. */
|
|
||||||
conn->out_z ||
|
|
||||||
#endif
|
|
||||||
bc ? 0 : -1 );
|
|
||||||
/* If no writes were queued before, ensure that flushing commences. */
|
|
||||||
if (!exwb)
|
|
||||||
return do_queued_write( conn );
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -979,10 +976,10 @@ socket_fake_cb( void *aux )
|
||||||
{
|
{
|
||||||
conn_t *conn = (conn_t *)aux;
|
conn_t *conn = (conn_t *)aux;
|
||||||
|
|
||||||
buff_chunk_t *exwb = conn->write_buf;
|
/* Ensure that a pending write gets queued. */
|
||||||
do_flush( conn );
|
do_flush( conn );
|
||||||
/* If no writes were queued before, ensure that flushing commences. */
|
/* If no writes are ongoing, start writing now. */
|
||||||
if (!exwb)
|
if (!conn->writing)
|
||||||
do_queued_write( conn );
|
do_queued_write( conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,12 @@ typedef struct {
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
z_streamp in_z, out_z;
|
z_streamp in_z, out_z;
|
||||||
wakeup_t z_fake;
|
wakeup_t z_fake;
|
||||||
|
int z_written;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
|
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
|
||||||
void (*read_callback)( void *aux ); /* data available for reading */
|
void (*read_callback)( void *aux ); /* data available for reading */
|
||||||
int (*write_callback)( void *aux ); /* all *queued* data was sent */
|
void (*write_callback)( void *aux ); /* all *queued* data was sent */
|
||||||
union {
|
union {
|
||||||
void (*connect)( int ok, void *aux );
|
void (*connect)( int ok, void *aux );
|
||||||
void (*starttls)( int ok, void *aux );
|
void (*starttls)( int ok, void *aux );
|
||||||
|
@ -102,6 +103,7 @@ typedef struct {
|
||||||
/* writing */
|
/* writing */
|
||||||
buff_chunk_t *append_buf; /* accumulating buffer */
|
buff_chunk_t *append_buf; /* accumulating buffer */
|
||||||
buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
|
buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
|
||||||
|
int writing;
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
int append_avail; /* space left in accumulating buffer */
|
int append_avail; /* space left in accumulating buffer */
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,7 +125,7 @@ static INLINE void socket_init( conn_t *conn,
|
||||||
const server_conf_t *conf,
|
const server_conf_t *conf,
|
||||||
void (*bad_callback)( void *aux ),
|
void (*bad_callback)( void *aux ),
|
||||||
void (*read_callback)( void *aux ),
|
void (*read_callback)( void *aux ),
|
||||||
int (*write_callback)( void *aux ),
|
void (*write_callback)( void *aux ),
|
||||||
void *aux )
|
void *aux )
|
||||||
{
|
{
|
||||||
conn->conf = conf;
|
conn->conf = conf;
|
||||||
|
@ -148,6 +150,6 @@ typedef struct conn_iovec {
|
||||||
int len;
|
int len;
|
||||||
ownership_t takeOwn;
|
ownership_t takeOwn;
|
||||||
} conn_iovec_t;
|
} conn_iovec_t;
|
||||||
int socket_write( conn_t *sock, conn_iovec_t *iov, int iovcnt );
|
void socket_write( conn_t *sock, conn_iovec_t *iov, int iovcnt );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user