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
|
||||
|
||||
Berkley DB 4.2+ (optional)
|
||||
Berkeley DB 4.1+ (optional)
|
||||
OpenSSL for TLS/SSL support (optional)
|
||||
|
||||
* 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.
|
||||
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".
|
||||
|
||||
uidvalidity lock timeout handling would be a good idea.
|
||||
|
|
34
configure.ac
34
configure.ac
|
@ -139,26 +139,36 @@ if test "x$ob_cv_with_sasl" != xno; then
|
|||
fi
|
||||
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
|
||||
sav_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -ldb"
|
||||
AC_TRY_LINK([#include <db.h>],
|
||||
[DB *db;
|
||||
db_create(&db, 0, 0);
|
||||
db->truncate(db, 0, 0, 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
|
||||
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
|
||||
|
||||
have_zlib=
|
||||
AC_CHECK_LIB([z], [deflate],
|
||||
[AC_CHECK_HEADER(zlib.h,
|
||||
[have_zlib=1
|
||||
AC_SUBST([Z_LIBS], ["-lz"])
|
||||
AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])]
|
||||
)]
|
||||
)
|
||||
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,
|
||||
[have_zlib=1
|
||||
AC_SUBST([Z_LIBS], ["-lz"])
|
||||
AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])]
|
||||
)]
|
||||
)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(compat,
|
||||
AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
|
||||
|
@ -189,8 +199,8 @@ else
|
|||
AC_MSG_RESULT([Not using zlib])
|
||||
fi
|
||||
if test "x$ac_cv_berkdb4" = xyes; then
|
||||
AC_MSG_RESULT([Using Berkley DB])
|
||||
AC_MSG_RESULT([Using Berkeley DB])
|
||||
else
|
||||
AC_MSG_RESULT([Not using Berkley DB])
|
||||
AC_MSG_RESULT([Not using Berkeley DB])
|
||||
fi
|
||||
AC_MSG_RESULT()
|
||||
|
|
116
src/drv_imap.c
116
src/drv_imap.c
|
@ -267,7 +267,7 @@ done_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, int response )
|
|||
free( cmd );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
||||
{
|
||||
int bufl, litplus, iovcnt = 1;
|
||||
|
@ -313,8 +313,7 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
|||
iov[2].takeOwn = KeepOwn;
|
||||
iovcnt = 3;
|
||||
}
|
||||
if (socket_write( &ctx->conn, iov, iovcnt ) < 0)
|
||||
goto bail;
|
||||
socket_write( &ctx->conn, iov, iovcnt );
|
||||
if (cmd->param.to_trash && ctx->trashnc == TrashUnknown)
|
||||
ctx->trashnc = TrashChecking;
|
||||
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->num_in_progress++;
|
||||
socket_expect_read( &ctx->conn, 1 );
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
done_imap_cmd( ctx, cmd, RESP_CANCEL );
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
flush_imap_cmds( imap_store_t *ctx )
|
||||
{
|
||||
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))
|
||||
ctx->pending_append = &ctx->pending;
|
||||
if (send_imap_cmd( ctx, cmd ) < 0)
|
||||
return -1;
|
||||
send_imap_cmd( ctx, cmd );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -370,7 +362,7 @@ cancel_pending_imap_cmds( imap_store_t *ctx )
|
|||
}
|
||||
|
||||
static void
|
||||
cancel_submitted_imap_cmds( imap_store_t *ctx )
|
||||
cancel_sent_imap_cmds( imap_store_t *ctx )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
assert( ctx );
|
||||
|
@ -390,7 +382,7 @@ submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
|
|||
assert( cmd );
|
||||
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) {
|
||||
cmd->next = ctx->pending;
|
||||
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->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
|
||||
|
@ -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,
|
||||
void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response ),
|
||||
const char *fmt, ... )
|
||||
|
@ -500,7 +491,7 @@ imap_exec( imap_store_t *ctx, struct imap_cmd *cmdp,
|
|||
va_start( ap, fmt );
|
||||
cmdp->cmd = imap_vprintf( fmt, ap );
|
||||
va_end( ap );
|
||||
return submit_imap_cmd( ctx, cmdp );
|
||||
submit_imap_cmd( ctx, cmdp );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1337,8 +1328,7 @@ imap_socket_read( void *aux )
|
|||
iov[1].buf = "\r\n";
|
||||
iov[1].len = 2;
|
||||
iov[1].takeOwn = KeepOwn;
|
||||
if (socket_write( &ctx->conn, iov, 2 ) < 0)
|
||||
return;
|
||||
socket_write( &ctx->conn, iov, 2 );
|
||||
} else if (cmdp->param.cont) {
|
||||
if (cmdp->param.cont( ctx, cmdp, cmd ))
|
||||
return;
|
||||
|
@ -1376,9 +1366,8 @@ imap_socket_read( void *aux )
|
|||
cmd2->orig_cmd = cmdp;
|
||||
cmd2->gen.param.high_prio = 1;
|
||||
p = strchr( cmdp->cmd, '"' );
|
||||
if (imap_exec( ctx, &cmd2->gen, get_cmd_result_p2,
|
||||
"CREATE %.*s", imap_strchr( p + 1, '"' ) - p + 1, p ) < 0)
|
||||
return;
|
||||
imap_exec( ctx, &cmd2->gen, get_cmd_result_p2,
|
||||
"CREATE %.*s", imap_strchr( p + 1, '"' ) - p + 1, p );
|
||||
continue;
|
||||
}
|
||||
resp = RESP_NO;
|
||||
|
@ -1387,7 +1376,11 @@ imap_socket_read( void *aux )
|
|||
} else /*if (!strcmp( "BAD", arg ))*/
|
||||
resp = RESP_CANCEL;
|
||||
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 : "" );
|
||||
}
|
||||
doresp:
|
||||
|
@ -1405,8 +1398,7 @@ imap_socket_read( void *aux )
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (flush_imap_cmds( ctx ) < 0)
|
||||
return;
|
||||
flush_imap_cmds( ctx );
|
||||
}
|
||||
imap_invoke_bad_callback( ctx );
|
||||
}
|
||||
|
@ -1440,7 +1432,7 @@ imap_cancel_store( store_t *gctx )
|
|||
sasl_dispose( &ctx->sasl );
|
||||
#endif
|
||||
socket_close( &ctx->conn );
|
||||
cancel_submitted_imap_cmds( ctx );
|
||||
cancel_sent_imap_cmds( ctx );
|
||||
cancel_pending_imap_cmds( ctx );
|
||||
free_generic_messages( ctx->gen.msgs );
|
||||
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,
|
||||
(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 );
|
||||
}
|
||||
|
||||
|
@ -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].takeOwn = KeepOwn;
|
||||
iovcnt++;
|
||||
return socket_write( &ctx->conn, iov, iovcnt );
|
||||
socket_write( &ctx->conn, iov, iovcnt );
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
imap_open_store_bail( ctx, FAIL_FINAL );
|
||||
|
@ -2289,7 +2282,7 @@ imap_prepare_load_box( store_t *gctx, int 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
|
||||
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)
|
||||
bl += sprintf( buf + bl, ":%d", excs[i] );
|
||||
}
|
||||
if (imap_submit_load( ctx, buf, 0, sts ) < 0)
|
||||
goto done;
|
||||
imap_submit_load( ctx, buf, 0, sts );
|
||||
}
|
||||
if (maxuid == INT_MAX)
|
||||
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 1000000000;
|
||||
if (maxuid >= minuid) {
|
||||
if ((ctx->gen.opts & OPEN_FIND) && minuid < newuid) {
|
||||
sprintf( buf, "%d:%d", minuid, newuid - 1 );
|
||||
if (imap_submit_load( ctx, buf, 0, sts ) < 0)
|
||||
goto done;
|
||||
imap_submit_load( ctx, buf, 0, sts );
|
||||
if (newuid > maxuid)
|
||||
goto done;
|
||||
sprintf( buf, "%d:%d", newuid, maxuid );
|
||||
|
@ -2340,14 +2331,14 @@ 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 )
|
||||
{
|
||||
return imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"UID FETCH %s (UID%s%s%s)", buf,
|
||||
(ctx->gen.opts & OPEN_FLAGS) ? " FLAGS" : "",
|
||||
(ctx->gen.opts & OPEN_SIZE) ? " RFC822.SIZE" : "",
|
||||
tuids ? " BODY.PEEK[HEADER.FIELDS (X-TUID)]" : "");
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"UID FETCH %s (UID%s%s%s)", buf,
|
||||
(ctx->gen.opts & OPEN_FLAGS) ? " FLAGS" : "",
|
||||
(ctx->gen.opts & OPEN_SIZE) ? " RFC822.SIZE" : "",
|
||||
tuids ? " BODY.PEEK[HEADER.FIELDS (X-TUID)]" : "");
|
||||
}
|
||||
|
||||
/******************* imap_fetch_msg *******************/
|
||||
|
@ -2404,15 +2395,15 @@ imap_make_flags( int flags, char *buf )
|
|||
return d;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags,
|
||||
struct imap_cmd_refcounted_state *sts )
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
buf[imap_make_flags( flags, buf )] = 0;
|
||||
return imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_set_flags_p2,
|
||||
"UID STORE %d %cFLAGS.SILENT %s", uid, what, buf );
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_set_flags_p2,
|
||||
"UID STORE %d %cFLAGS.SILENT %s", uid, what, buf );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2430,8 +2421,10 @@ imap_set_msg_flags( store_t *gctx, message_t *msg, int uid, int add, int del,
|
|||
}
|
||||
if (add || del) {
|
||||
struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux );
|
||||
if ((add && imap_flags_helper( ctx, uid, '+', add, sts ) < 0) ||
|
||||
(del && imap_flags_helper( ctx, uid, '-', del, sts ) < 0)) {}
|
||||
if (add)
|
||||
imap_flags_helper( ctx, uid, '+', add, sts );
|
||||
if (del)
|
||||
imap_flags_helper( ctx, uid, '-', del, sts );
|
||||
imap_refcounted_done( sts );
|
||||
} else {
|
||||
cb( DRV_OK, aux );
|
||||
|
@ -2482,9 +2475,8 @@ imap_close_box( store_t *gctx,
|
|||
}
|
||||
if (!bl)
|
||||
break;
|
||||
if (imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"UID EXPUNGE %s", buf ) < 0)
|
||||
break;
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"UID EXPUNGE %s", buf );
|
||||
}
|
||||
imap_refcounted_done( sts );
|
||||
} else {
|
||||
|
@ -2625,13 +2617,12 @@ imap_list_store( store_t *gctx, int flags,
|
|||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
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 )) &&
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"LIST \"\" \"%\\s*\"", ctx->prefix ) < 0) ||
|
||||
((flags & LIST_INBOX) && (!(flags & LIST_PATH) || *ctx->prefix) &&
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"LIST \"\" INBOX*" ) < 0))
|
||||
{}
|
||||
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,
|
||||
"LIST \"\" \"%\\s*\"", ctx->prefix );
|
||||
if ((flags & LIST_INBOX) && (!(flags & LIST_PATH) || *ctx->prefix))
|
||||
imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box,
|
||||
"LIST \"\" INBOX*" );
|
||||
imap_refcounted_done( sts );
|
||||
}
|
||||
|
||||
|
@ -2695,8 +2686,9 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
/* Legacy SSL options */
|
||||
int require_ssl = -1, use_imaps = -1;
|
||||
int use_sslv2 = -1, use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1;
|
||||
int require_cram = -1;
|
||||
#endif
|
||||
/* Legacy SASL option */
|
||||
int require_cram = -1;
|
||||
|
||||
if (!strcasecmp( "IMAPAccount", cfg->cmd )) {
|
||||
server = nfcalloc( sizeof(*server) );
|
||||
|
@ -2829,6 +2821,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
use_tlsv11 = parse_bool( cfg );
|
||||
else if (!strcasecmp( "UseTLSv1.2", cfg->cmd ))
|
||||
use_tlsv12 = parse_bool( cfg );
|
||||
#endif
|
||||
else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
|
||||
!strcasecmp( "AuthMechs", cfg->cmd )) {
|
||||
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 )));
|
||||
} else if (!strcasecmp( "RequireCRAM", cfg->cmd ))
|
||||
require_cram = parse_bool( cfg );
|
||||
#endif
|
||||
else if (!strcasecmp( "Tunnel", cfg->cmd ))
|
||||
server->sconf.tunnel = nfstrdup( cfg->val );
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBSSL
|
||||
if (require_cram >= 0) {
|
||||
if (server->auth_mechs) {
|
||||
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)
|
||||
add_string_list(&server->auth_mechs, "CRAM-MD5");
|
||||
}
|
||||
#endif
|
||||
if (!server->auth_mechs)
|
||||
add_string_list( &server->auth_mechs, "*" );
|
||||
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)
|
||||
..
|
||||
.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
|
||||
remote Store has a \fBTrash\fR as well (with \fBTrashNewOnly\fR \fIno\fR).
|
||||
(Default: \fIno\fR)
|
||||
remote Store has a \fBTrash\fR as well (with \fBTrashNewOnly\fR \fBno\fR).
|
||||
(Default: \fBno\fR)
|
||||
..
|
||||
.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
|
||||
Store's \fBTrash\fR. When using this, the remote Store does not need an own
|
||||
\fBTrash\fR at all, yet all messages are archived.
|
||||
(Default: \fIno\fR)
|
||||
(Default: \fBno\fR)
|
||||
..
|
||||
.SS Maildir Stores
|
||||
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.
|
||||
..
|
||||
.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.
|
||||
This does not affect mailboxes that do already have a UID storage scheme;
|
||||
use \fBmdconvert\fR to change it.
|
||||
(Default: \fIno\fR)
|
||||
(Default: \fBno\fR)
|
||||
..
|
||||
.TP
|
||||
\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.
|
||||
.br
|
||||
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.
|
||||
..
|
||||
.TP
|
||||
|
@ -309,7 +309,7 @@ Specify the login name on the IMAP server.
|
|||
.TP
|
||||
\fBPass\fR \fIpassword\fR
|
||||
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
|
||||
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)
|
||||
..
|
||||
.TP
|
||||
\fBSSLType\fR {\fINone\fR|\fISTARTTLS\fR|\fIIMAPS\fR}
|
||||
\fBSSLType\fR {\fBNone\fR|\fBSTARTTLS\fR|\fBIMAPS\fR}
|
||||
Select the connection security/encryption method:
|
||||
.br
|
||||
\fINone\fR - no security.
|
||||
\fBNone\fR - no security.
|
||||
This is the default when \fBTunnel\fR is set, as tunnels are usually secure.
|
||||
.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,
|
||||
so it is the default (unless a tunnel is used).
|
||||
.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.
|
||||
..
|
||||
.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.
|
||||
Use of SSLv2 is strongly discouraged for security reasons, but might be the
|
||||
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.
|
||||
..
|
||||
.TP
|
||||
\fBSystemCertificates\fR \fIyes\fR|\fIno\fR
|
||||
\fBSystemCertificates\fR \fByes\fR|\fBno\fR
|
||||
Whether the system's default root cerificate store should be loaded.
|
||||
(Default: \fIyes\fR)
|
||||
(Default: \fByes\fR)
|
||||
..
|
||||
.TP
|
||||
\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.
|
||||
..
|
||||
.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
|
||||
mailbox names. Disabling this makes sense for some broken IMAP servers.
|
||||
This option is meaningless if a \fBPath\fR was specified.
|
||||
(Default: \fIyes\fR)
|
||||
(Default: \fByes\fR)
|
||||
..
|
||||
.TP
|
||||
\fBPathDelimiter\fR \fIdelim\fR
|
||||
Specify the server's hierarchy delimiter.
|
||||
(Default: taken from the server's first "personal" NAMESPACE)
|
||||
.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.
|
||||
..
|
||||
.SS Channels
|
||||
|
@ -471,56 +471,56 @@ If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
|
|||
(Default: \fI0\fR).
|
||||
..
|
||||
.TP
|
||||
\fBExpireUnread\fR \fIyes\fR|\fIno\fR
|
||||
\fBExpireUnread\fR \fByes\fR|\fBno\fR
|
||||
Selects whether unread messages should be affected by \fBMaxMessages\fR.
|
||||
Normally, unread messages are considered important and thus never expired.
|
||||
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,
|
||||
treating them as important would practically defeat \fBMaxMessages\fR. In this
|
||||
case you need to enable this option.
|
||||
(Default: \fIno\fR).
|
||||
(Default: \fBno\fR).
|
||||
..
|
||||
.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:
|
||||
.br
|
||||
\fIPull\fR - propagate changes from Master to Slave.
|
||||
\fBPull\fR - propagate changes from Master to Slave.
|
||||
.br
|
||||
\fIPush\fR - propagate changes from Slave to Master.
|
||||
\fBPush\fR - propagate changes from Slave to Master.
|
||||
.br
|
||||
\fINew\fR - propagate newly appeared messages.
|
||||
\fBNew\fR - propagate newly appeared messages.
|
||||
.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
|
||||
MaxSize in the destination Store.
|
||||
.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
|
||||
Store are marked as deleted only, i.e., they won't be really deleted until
|
||||
that Store is expunged.
|
||||
.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
|
||||
maildir_trash option.
|
||||
.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.
|
||||
.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.
|
||||
.IP
|
||||
\fIPull\fR and \fIPush\fR are direction flags, while \fINew\fR, \fIReNew\fR,
|
||||
\fIDelete\fR and \fIFlags\fR are type flags. The two flag classes make up a
|
||||
\fBPull\fR and \fBPush\fR are direction flags, while \fBNew\fR, \fBReNew\fR,
|
||||
\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
|
||||
perform. There are two styles of asserting the cells:
|
||||
.br
|
||||
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.
|
||||
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,
|
||||
"\fBSync\fR\ \fINew\fR\ \fIDelete\fR" will propagate message arrivals and
|
||||
deletions both ways, and "\fBSync\fR\ \fIPush\fR" will propagate all changes
|
||||
"\fBSync\fR\ \fBNew\fR\ \fBDelete\fR" will propagate message arrivals and
|
||||
deletions both ways, and "\fBSync\fR\ \fBPush\fR" will propagate all changes
|
||||
from the Slave to the Master.
|
||||
.br
|
||||
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
|
||||
the first style, they immediately assert all cells in their respective
|
||||
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
|
||||
from the Slave to the Master.
|
||||
Note that it is not allowed to assert a cell in two ways, e.g.
|
||||
"\fBSync\fR\ \fIPullNew\fR\ \fIPull\fR" and
|
||||
"\fBSync\fR\ \fIPullNew\fR\ \fIDelete\fR\ \fIPush\fR" induce error messages.
|
||||
"\fBSync\fR\ \fBPullNew\fR\ \fBPull\fR" and
|
||||
"\fBSync\fR\ \fBPullNew\fR\ \fBDelete\fR\ \fBPush\fR" induce error messages.
|
||||
..
|
||||
.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].
|
||||
Otherwise print an error message and skip that mailbox pair if a mailbox
|
||||
and the corresponding sync state does not exist.
|
||||
(Global default: \fINone\fR)
|
||||
(Global default: \fBNone\fR)
|
||||
..
|
||||
.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].
|
||||
Otherwise print an error message and skip that mailbox pair if a mailbox
|
||||
does not exist but the corresponding sync state does.
|
||||
|
@ -553,23 +553,23 @@ mark them as deleted. This ensures compatibility with \fBSyncState *\fR.
|
|||
.br
|
||||
Note that for safety, non-empty mailboxes are never deleted.
|
||||
.br
|
||||
(Global default: \fINone\fR)
|
||||
(Global default: \fBNone\fR)
|
||||
..
|
||||
.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.
|
||||
See \fBRECOMMENDATIONS\fR below.
|
||||
(Global default: \fINone\fR)
|
||||
(Global default: \fBNone\fR)
|
||||
..
|
||||
.TP
|
||||
\fBCopyArrivalDate\fR {\fIyes\fR|\fIno\fR}
|
||||
\fBCopyArrivalDate\fR {\fByes\fR|\fBno\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)
|
||||
(Default: \fBno\fR)
|
||||
..
|
||||
.P
|
||||
\fBSync\fR, \fBCreate\fR, \fBRemove\fR, \fBExpunge\fR,
|
||||
|
@ -615,7 +615,7 @@ times within a Group.
|
|||
..
|
||||
.SS Global Options
|
||||
.TP
|
||||
\fBFSync\fR \fIyes\fR|\fIno\fR
|
||||
\fBFSync\fR \fByes\fR|\fBno\fR
|
||||
.br
|
||||
Selects whether \fBmbsync\fR performs forced flushing, which determines
|
||||
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,
|
||||
in particular modern systems like ext4, btrfs and xfs. The performance impact
|
||||
on older file systems may be disproportionate.
|
||||
(Default: \fIyes\fR)
|
||||
(Default: \fByes\fR)
|
||||
..
|
||||
.TP
|
||||
\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. */
|
||||
conn->state = SCK_EOF;
|
||||
conn->read_callback( conn->callback_aux );
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
sys_error( "Socket error: secure %s %s", func, conn->name );
|
||||
} else {
|
||||
|
@ -771,6 +771,7 @@ do_queued_write( conn_t *conn )
|
|||
return -1;
|
||||
if (n != len) {
|
||||
conn->write_offset += n;
|
||||
conn->writing = 1;
|
||||
return 0;
|
||||
}
|
||||
conn->write_offset = 0;
|
||||
|
@ -780,7 +781,9 @@ do_queued_write( conn_t *conn )
|
|||
if (conn->ssl && SSL_pending( conn->ssl ))
|
||||
conf_wakeup( &conn->ssl_fake, 0 );
|
||||
#endif
|
||||
return conn->write_callback( conn->callback_aux );
|
||||
conn->writing = 0;
|
||||
conn->write_callback( conn->callback_aux );
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -803,6 +806,8 @@ do_flush( conn_t *conn )
|
|||
#ifdef HAVE_LIBZ
|
||||
if (conn->out_z) {
|
||||
int buf_avail = conn->append_avail;
|
||||
if (!conn->z_written)
|
||||
return;
|
||||
do {
|
||||
if (!bc) {
|
||||
buf_avail = WRITE_CHUNK_SIZE;
|
||||
|
@ -828,6 +833,7 @@ do_flush( conn_t *conn )
|
|||
} while (!conn->out_z->avail_out);
|
||||
conn->append_buf = bc;
|
||||
conn->append_avail = buf_avail;
|
||||
conn->z_written = 0;
|
||||
} else
|
||||
#endif
|
||||
if (bc) {
|
||||
|
@ -839,15 +845,15 @@ do_flush( conn_t *conn )
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
||||
{
|
||||
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++)
|
||||
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. */
|
||||
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;
|
||||
buf_avail = conn->out_z->avail_out;
|
||||
len -= conn->out_z->avail_in;
|
||||
conn->z_written = 1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@ -914,17 +921,7 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
|
|||
#ifdef HAVE_LIBZ
|
||||
conn->append_avail = buf_avail;
|
||||
#endif
|
||||
/* Queue the pending write once the main loop goes idle. */
|
||||
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;
|
||||
conf_wakeup( &conn->fd_fake, 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -979,10 +976,10 @@ socket_fake_cb( void *aux )
|
|||
{
|
||||
conn_t *conn = (conn_t *)aux;
|
||||
|
||||
buff_chunk_t *exwb = conn->write_buf;
|
||||
/* Ensure that a pending write gets queued. */
|
||||
do_flush( conn );
|
||||
/* If no writes were queued before, ensure that flushing commences. */
|
||||
if (!exwb)
|
||||
/* If no writes are ongoing, start writing now. */
|
||||
if (!conn->writing)
|
||||
do_queued_write( conn );
|
||||
}
|
||||
|
||||
|
|
|
@ -84,11 +84,12 @@ typedef struct {
|
|||
#ifdef HAVE_LIBZ
|
||||
z_streamp in_z, out_z;
|
||||
wakeup_t z_fake;
|
||||
int z_written;
|
||||
#endif
|
||||
|
||||
void (*bad_callback)( void *aux ); /* async fail while sending or listening */
|
||||
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 {
|
||||
void (*connect)( int ok, void *aux );
|
||||
void (*starttls)( int ok, void *aux );
|
||||
|
@ -102,6 +103,7 @@ typedef struct {
|
|||
/* writing */
|
||||
buff_chunk_t *append_buf; /* accumulating buffer */
|
||||
buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */
|
||||
int writing;
|
||||
#ifdef HAVE_LIBZ
|
||||
int append_avail; /* space left in accumulating buffer */
|
||||
#endif
|
||||
|
@ -123,7 +125,7 @@ static INLINE void socket_init( conn_t *conn,
|
|||
const server_conf_t *conf,
|
||||
void (*bad_callback)( void *aux ),
|
||||
void (*read_callback)( void *aux ),
|
||||
int (*write_callback)( void *aux ),
|
||||
void (*write_callback)( void *aux ),
|
||||
void *aux )
|
||||
{
|
||||
conn->conf = conf;
|
||||
|
@ -148,6 +150,6 @@ typedef struct conn_iovec {
|
|||
int len;
|
||||
ownership_t takeOwn;
|
||||
} 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
|
||||
|
|
Loading…
Reference in New Issue
Block a user