Re: [PATCH] add support for built-in oauthbearer auth mechanism

2020-08-04 Thread Oswald Buddenhagen
what is the fundamental advantage over using a SASL plugin like 
https://github.com/tarickb/sasl-xoauth2 ?




___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[PATCH] add support for built-in oauthbearer auth mechanism

2020-08-04 Thread MichaƂ Winiarski
this can be combined with an external tool (PassCmd) to generate access
tokens used for authentication

For more information, see:
https://tools.ietf.org/html/rfc7628
---
 src/drv_imap.c | 123 -
 src/mbsync.1   |   2 +-
 2 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4ea86d6..b0a3815 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -42,6 +42,7 @@
 #endif
 
 #ifdef HAVE_LIBSSL
+# include 
 enum { SSL_None, SSL_STARTTLS, SSL_IMAPS };
 #endif
 
@@ -2108,14 +2109,91 @@ done_sasl_auth( imap_store_t *ctx, imap_cmd_t *cmd 
ATTR_UNUSED, int response )
 
 #endif
 
+static size_t
+encoded_length( size_t in )
+{
+   in += 2;
+   in /= 3;
+   in <<= 2;
+   in++;
+
+   return in;
+}
+
+static int
+auth_builtin_oauthbearer( imap_store_t *ctx )
+{
+   imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
+   imap_server_conf_t *srvc = cfg->server;
+   size_t buf_size = 38; /* format string, port, NULL */
+   size_t input_size;
+   char *buf, *buf_encoded;
+
+#ifdef HAVE_LIBSSL
+   if (!ctx->conn.ssl) {
+#endif
+   error( "Note: not using OAUTHBEARER because connection is not 
encrypted;\n" );
+   return -1;
+#ifdef HAVE_LIBSSL
+   }
+#endif
+
+   if (!ensure_user( srvc ) || !ensure_password( srvc ))
+   return -1;
+
+   buf_size += strlen( srvc->user );
+   buf_size += strlen( srvc->sconf.host );
+   buf_size += strlen( srvc->pass );
+
+   buf = nfmalloc( buf_size );
+   input_size = nfsnprintf( buf, buf_size, 
"n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
+   srvc->user, srvc->sconf.host, srvc->sconf.port, srvc->pass 
);
+
+   buf_encoded = nfmalloc ( encoded_length( input_size ) );
+
+#ifdef HAVE_LIBSSL
+   EVP_EncodeBlock( (unsigned char *)buf_encoded, (unsigned char *)buf, 
input_size );
+#endif
+
+   imap_exec( ctx, 0, imap_open_store_authenticate2_p2,
+  "AUTHENTICATE OAUTHBEARER %s", buf_encoded );
+
+   free ( buf_encoded );
+   free ( buf );
+
+   return 0;
+}
+
+static int
+auth_builtin_login( imap_store_t *ctx )
+{
+   imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
+   imap_server_conf_t *srvc = cfg->server;
+
+   if (!ensure_user( srvc ) || !ensure_password( srvc ))
+   return -1;
+
+#ifdef HAVE_LIBSSL
+   if (!ctx->conn.ssl)
+#endif
+   warn( "*** IMAP Warning *** Password is being sent in the 
clear\n" );
+   imap_exec( ctx, 0, imap_open_store_authenticate2_p2,
+  "LOGIN \"%\\s\" \"%\\s\"", srvc->user, srvc->pass );
+
+   return 0;
+}
+
+#define AUTH_BUILTIN_LOGIN 0x1
+#define AUTH_BUILTIN_OAUTHBEARER   0x2
+
 static void
 imap_open_store_authenticate2( imap_store_t *ctx )
 {
imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
imap_server_conf_t *srvc = cfg->server;
string_list_t *mech, *cmech;
-   int auth_login = 0;
-   int skipped_login = 0;
+   int auth_builtin = 0;
+   int skipped_builtin = 0;
 #ifdef HAVE_LIBSASL
const char *saslavail;
char saslmechs[1024], *saslend = saslmechs;
@@ -2126,15 +2204,19 @@ imap_open_store_authenticate2( imap_store_t *ctx )
int any = !strcmp( mech->string, "*" );
for (cmech = ctx->auth_mechs; cmech; cmech = cmech->next) {
if (any || !strcasecmp( mech->string, cmech->string )) {
-   if (!strcasecmp( cmech->string, "LOGIN" )) {
+   if (!strcasecmp( cmech->string, "LOGIN" ))
+   auth_builtin |= AUTH_BUILTIN_LOGIN;
+   if (!strcasecmp( cmech->string, "OAUTHBEARER" ))
+   auth_builtin |= 
AUTH_BUILTIN_OAUTHBEARER;
+   if (auth_builtin & (AUTH_BUILTIN_LOGIN | 
AUTH_BUILTIN_OAUTHBEARER)) {
 #ifdef HAVE_LIBSSL
-   if (ctx->conn.ssl || !any)
+   if (!ctx->conn.ssl && any) {
 #else
-   if (!any)
+   if (any) {
 #endif
-   auth_login = 1;
-   else
-   skipped_login = 1;
+   auth_builtin = 0;
+   skipped_builtin = 1;
+   }
 #ifdef HAVE_LIBSASL
} else {
int len = strlen( cmech->string );
@@ -2202,7 +2284,7 @@ imap_open_store_authenticate2( imap_store_t *ctx )
  notsasl:
if (!ctx->sasl || sasl_listmech( ctx->sasl, NULL, "", " ", 

beta testing for 1.4 release; short-term roadmap

2020-08-04 Thread Oswald Buddenhagen

hello community,

after *finally* having pushed my work branch to master (this time even 
intentionally, heh), i'm about to release 1.4.0 in a few days. please 
give the branch some good hammering.


going forward, i intend to do some more hacking before the project 
mostly hibernates again for an indefinite amount of time.


i'm particularly interested in merging max' utf-7 work (with a possible 
utf-8 followup), which i'll finish myself if i have to.


i'm also somewhat interested in wyatt's xdg patch, but not enough to do 
more than final polishing myself.


i think i'll also merge a variation of yuri's exit code patch after all.  
whether i'll continue with a proper notification system at this time is 
unclear - i need something for desktop notifications that actually works 
(which isn't the case for any 'biff' variant i tried), but i may end up 
just extending my scripting around mbsync.


i also want to add automatic retries after network errors, as these are 
happening here way too much, and my current "solution" is a tad 
embarrassing.


i have some more things earmarked, but nothing big.


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] branch 'wip/master-next' reset

2020-08-04 Thread Oswald Buddenhagen via isync-devel
The branch 'wip/master-next', previously at 447829c, has been rewound
by 70 revision(s) and subsequently fast-forwarded by 83 revision(s) to
b148fd9.


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] branch 'wip/placeholders' deleted

2020-08-04 Thread Oswald Buddenhagen via isync-devel
The branch 'wip/placeholders', previously at 8d09ea4, has been deleted.


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: don't unnecessarily re-initialize some members of imap_store

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c83330ffe8af72b3dea381c0e43562d572d0ad85
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 09:06:41 2020 +0200

don't unnecessarily re-initialize some members of imap_store

... when recycling server connections.

 src/drv_imap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 9103e8a..75b44cd 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1824,6 +1824,8 @@ imap_alloc_store( store_conf_t *conf, const char *label )
 
/* Finally, schedule opening a new server connection. */
ctx = nfcalloc( sizeof(*ctx) );
+   ctx->gen.driver = _driver;
+   ctx->ref_count = 1;
socket_init( >conn, >sconf,
 (void (*)( void * ))imap_invoke_bad_callback,
 imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx );
@@ -1832,10 +1834,8 @@ imap_alloc_store( store_conf_t *conf, const char *label )
ctx->wait_check_append = >wait_check;
 
   gotsrv:
-   ctx->gen.driver = _driver;
ctx->gen.conf = conf;
ctx->label = label;
-   ctx->ref_count = 1;
return >gen;
 }
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: actually implement imap_commit_cmds()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit cfaa4848dd7c72e628fcc81a4c4532c9be226144
Author: Oswald Buddenhagen 
Date:   Tue Jul 28 16:14:00 2020 +0200

actually implement imap_commit_cmds()

delay reporting success of STORE FLAGS until a subsequent CHECK
succeeds.

this fixes (inverse flag change propagation) and (deletes not being
propagated) after an interruption due to prematurely logged flag
updates.

 src/drv_imap.c  | 55 +
 src/drv_proxy.c |  8 ---
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4b9a429..9103e8a 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -129,9 +129,10 @@ struct imap_store {
string_list_t *auth_mechs;
parse_list_state_t parse_list_sts;
/* command queue */
-   int nexttag, num_in_progress;
imap_cmd_t *pending, **pending_append;
imap_cmd_t *in_progress, **in_progress_append;
+   imap_cmd_t *wait_check, **wait_check_append;
+   int nexttag, num_in_progress, num_wait_check;
uint buffer_mem; /* memory currently occupied by buffers in the queue */
 
/* Used during sequential operations like connect */
@@ -169,6 +170,7 @@ struct imap_cmd {
uint data_len;
uint uid; /* to identify fetch responses */
char high_prio; /* if command is queued, put it at the front of 
the queue. */
+   char wait_check;  // Don't report success until subsequent 
CHECK success.
char to_trash; /* we are storing to trash, not current. */
char create; /* create the mailbox if we get an error which 
suggests so. */
char failok; /* Don't complain about NO response. */
@@ -286,6 +288,8 @@ new_imap_cmd( uint size )
 static void
 done_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd, int response )
 {
+   if (cmd->param.wait_check)
+   ctx->num_wait_check--;
cmd->param.done( ctx, cmd, response );
if (cmd->param.data) {
free( cmd->param.data );
@@ -405,6 +409,18 @@ flush_imap_cmds( imap_store_t *ctx )
}
 }
 
+static void
+finalize_checked_imap_cmds( imap_store_t *ctx, int resp )
+{
+   imap_cmd_t *cmd;
+
+   while ((cmd = ctx->wait_check)) {
+   if (!(ctx->wait_check = cmd->next))
+   ctx->wait_check_append = >wait_check;
+   done_imap_cmd( ctx, cmd, resp );
+   }
+}
+
 static void
 cancel_pending_imap_cmds( imap_store_t *ctx )
 {
@@ -438,6 +454,8 @@ submit_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd )
assert( cmd );
assert( cmd->param.done );
 
+   if (cmd->param.wait_check)
+   ctx->num_wait_check++;
if ((ctx->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd 
)) {
if (ctx->pending && cmd->param.high_prio) {
cmd->next = ctx->pending;
@@ -1600,7 +1618,13 @@ imap_socket_read( void *aux )
imap_ref( ctx );
if (resp == RESP_CANCEL)
imap_invoke_bad_callback( ctx );
-   done_imap_cmd( ctx, cmdp, resp );
+   if (resp == RESP_OK && cmdp->param.wait_check) {
+   cmdp->next = NULL;
+   *ctx->wait_check_append = cmdp;
+   ctx->wait_check_append = >next;
+   } else {
+   done_imap_cmd( ctx, cmdp, resp );
+   }
if (imap_deref( ctx ))
return;
if (ctx->canceling && !ctx->in_progress) {
@@ -1623,6 +1647,7 @@ get_cmd_result_p2( imap_store_t *ctx, imap_cmd_t *cmd, 
int response )
if (response != RESP_OK) {
done_imap_cmd( ctx, ocmd, response );
} else {
+   assert( !ocmd->param.wait_check );
ctx->uidnext = 1;
if (ocmd->param.to_trash)
ctx->trashnc = TrashKnown;
@@ -1643,6 +1668,7 @@ imap_cancel_store( store_t *gctx )
sasl_dispose( >sasl );
 #endif
socket_close( >conn );
+   finalize_checked_imap_cmds( ctx, RESP_CANCEL );
cancel_sent_imap_cmds( ctx );
cancel_pending_imap_cmds( ctx );
free( ctx->ns_prefix );
@@ -1699,6 +1725,8 @@ imap_free_store( store_t *gctx )
 {
imap_store_t *ctx = (imap_store_t *)gctx;
 
+   assert( !ctx->pending && !ctx->in_progress && !ctx->wait_check );
+
free_generic_messages( ctx->msgs );
ctx->msgs = NULL;
imap_set_bad_callback( gctx, imap_cancel_unowned, gctx );
@@ -1801,6 +1829,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
 imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx );
ctx->in_progress_append = >in_progress;
ctx->pending_append = >pending;
+   

[commit] master: handle CertificateFile more cleanly

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 481c12a8b31c6dd7eba048e8f42d0b9653110621
Author: Oswald Buddenhagen 
Date:   Wed Jul 29 20:23:54 2020 +0200

handle CertificateFile more cleanly

properly distribute the certificates between the SSL context's trust
store and our host cert list.

as a drive-by, clean up some nasty type casts at the cost of including
a second OpenSSL header into socket.h.

 src/common.h |  1 +
 src/socket.c | 36 
 src/socket.h |  3 ++-
 src/util.c   |  2 +-
 4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/src/common.h b/src/common.h
index 1bf3aa1..359 100644
--- a/src/common.h
+++ b/src/common.h
@@ -172,6 +172,7 @@ int ATTR_PRINTFLIKE(2, 0) nfvasprintf( char **str, const 
char *fmt, va_list va )
 int ATTR_PRINTFLIKE(2, 3) nfasprintf( char **str, const char *fmt, ... );
 int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, 
... );
 void ATTR_NORETURN oob( void );
+void ATTR_NORETURN oom( void );
 
 char *expand_strdup( const char *s );
 
diff --git a/src/socket.c b/src/socket.c
index 0599aba..ac3c847 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -194,7 +194,6 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock )
int i;
long err;
X509 *cert;
-   STACK_OF(X509_OBJECT) *trusted;
 
cert = SSL_get_peer_certificate( sock->ssl );
if (!cert) {
@@ -202,9 +201,8 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock )
return -1;
}
 
-   trusted = (STACK_OF(X509_OBJECT) *)sock->conf->trusted_certs;
-   for (i = 0; i < sk_X509_OBJECT_num( trusted ); i++) {
-   if (!X509_cmp( cert, X509_OBJECT_get0_X509( 
sk_X509_OBJECT_value( trusted, i ) ) )) {
+   for (i = 0; i < sk_X509_num( sock->conf->trusted_certs ); i++) {
+   if (!X509_cmp( cert, sk_X509_value( sock->conf->trusted_certs, 
i ) )) {
X509_free( cert );
return 0;
}
@@ -273,11 +271,33 @@ DIAG_POP
return 0;
}
 
-   if (conf->cert_file && !SSL_CTX_load_verify_locations( 
mconf->SSLContext, conf->cert_file, NULL )) {
-   print_ssl_errors( "loading certificate file '%s'", 
conf->cert_file );
-   return 0;
+   if (!(mconf->trusted_certs = sk_X509_new_null()))
+   oom();
+   if (conf->cert_file) {
+   X509_STORE *store;
+   if (!(store = X509_STORE_new()))
+   oom();
+   if (!X509_STORE_load_locations( store, conf->cert_file, NULL )) 
{
+   print_ssl_errors( "loading certificate file '%s'", 
conf->cert_file );
+   return 0;
+   }
+   STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects( store );
+   for (int i = 0; i < sk_X509_OBJECT_num( objs ); i++) {
+   X509 *cert = X509_OBJECT_get0_X509( 
sk_X509_OBJECT_value( objs, i ) );
+   if (cert) {
+   if (X509_check_ca( cert )) {
+   if (!X509_STORE_add_cert( 
SSL_CTX_get_cert_store( mconf->SSLContext ), cert ))
+   oom();
+   } else {
+   X509_up_ref( cert );  // Locking 
failure assumed impossible
+   if (!sk_X509_push( 
mconf->trusted_certs, cert ))
+   oom();
+   }
+   }
+   }
+   X509_STORE_free( store );
}
-   mconf->trusted_certs = (_STACK *)sk_X509_OBJECT_dup( 
X509_STORE_get0_objects( SSL_CTX_get_cert_store( mconf->SSLContext ) ) );
+
if (mconf->system_certs && !SSL_CTX_set_default_verify_paths( 
mconf->SSLContext )) {
ulong err;
while ((err = ERR_get_error()))
diff --git a/src/socket.h b/src/socket.h
index 5334a89..5b1edd0 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -31,6 +31,7 @@
 
 #ifdef HAVE_LIBSSL
 # include 
+# include 
 
 enum {
TLSv1 = 4,
@@ -55,7 +56,7 @@ typedef struct {
 
/* these are actually variables and are leaked at the end */
char ssl_ctx_valid;
-   _STACK *trusted_certs;
+   STACK_OF(X509) *trusted_certs;
SSL_CTX *SSLContext;
 #endif
 } server_conf_t;
diff --git a/src/util.c b/src/util.c
index a4ee67d..7f8c453 100644
--- a/src/util.c
+++ b/src/util.c
@@ -353,7 +353,7 @@ nfsnprintf( char *buf, int blen, const char *fmt, ... )
return ret;
 }
 
-static void ATTR_NORETURN
+void
 oom( void )
 {
fputs( "Fatal: Out of memory\n", stderr );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: add/fix/de-duplicate comments

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 0e5046e14afbaee599387cbbdc997c9669b8879c
Author: Oswald Buddenhagen 
Date:   Sun Nov 17 19:45:00 2019 +0100

add/fix/de-duplicate comments

 src/driver.h | 17 ++---
 src/drv_imap.c   |  1 +
 src/run-tests.pl |  1 +
 src/sync.c   |  8 
 src/sync.h   |  1 +
 5 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index b3edf88..4921153 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -73,10 +73,13 @@ typedef struct message {
char tuid[TUIDL];
 } message_t;
 
-/* For opts, both in store and driver_t->select() */
-#define OPEN_OLD(1<<0)
-#define OPEN_NEW(1<<1)
-#define OPEN_FLAGS  (1<<2)
+// For driver_t->prepare_load_box(), which may amend the passed flags.
+// The drivers don't use the first two, but may set them if loading the
+// particular range is required to handle some other flag; note that these
+// ranges may overlap.
+#define OPEN_OLD(1<<0)  // Paired messages *in* this store.
+#define OPEN_NEW(1<<1)  // Messages (possibly) not yet propagated 
*from* this store.
+#define OPEN_FLAGS  (1<<2)  // Note that fetch_msg() gets the flags 
regardless.
 #define OPEN_OLD_SIZE   (1<<3)
 #define OPEN_NEW_SIZE   (1<<4)
 #define OPEN_EXPUNGE(1<<5)
@@ -234,17 +237,17 @@ struct driver {
 * a pre-fetched one (in which case the in-memory representation is 
updated),
 * or it may be identifed by UID only. The operation may be delayed 
until commit()
 * is called. */
-   void (*set_msg_flags)( store_t *ctx, message_t *msg, uint uid, int add, 
int del, /* msg can be null, therefore uid as a fallback */
+   void (*set_msg_flags)( store_t *ctx, message_t *msg, uint uid, int add, 
int del,
   void (*cb)( int sts, void *aux ), void *aux );
 
/* Move the given message from the current mailbox to the trash folder.
 * This may expunge the original message immediately, but it needn't 
to. */
-   void (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge 
the original message immediately, but it needn't to */
+   void (*trash_msg)( store_t *ctx, message_t *msg,
   void (*cb)( int sts, void *aux ), void *aux );
 
/* Expunge deleted messages from the current mailbox and close it.
 * There is no need to explicitly close a mailbox if no expunge is 
needed. */
-   void (*close_box)( store_t *ctx, /* IMAP-style: expunge inclusive */
+   void (*close_box)( store_t *ctx,
   void (*cb)( int sts, void *aux ), void *aux );
 
/* Cancel queued commands which are not in flight yet; they will have 
their
diff --git a/src/drv_imap.c b/src/drv_imap.c
index d26fcf9..e1bc304 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3099,6 +3099,7 @@ imap_find_new_msgs_p2( imap_store_t *ctx, imap_cmd_t 
*gcmd, int response )
return;
}
 
+   // We appended messages, so we need to re-query UIDNEXT.
ctx->uidnext = 0;
 
INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cmdp->callback, 
cmdp->callback_aux)
diff --git a/src/run-tests.pl b/src/run-tests.pl
index 4c257ee..1033407 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -578,6 +578,7 @@ sub ckchan($$)
return $rslt;
 }
 
+# $boxname, $maxuid, @msgs
 sub printbox($$@)
 {
my ($bn, $mu, @ms) = @_;
diff --git a/src/sync.c b/src/sync.c
index 927..8dbdc62 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -128,7 +128,7 @@ make_flags( uchar flags, char *buf )
return d;
 }
 
-// These is the (mostly) persistent status of the sync record.
+// This is the (mostly) persistent status of the sync record.
 // Most of these bits are actually mutually exclusive. It is a
 // bitfield to allow for easy testing for multiple states.
 #define S_EXPIRE   (1<<0)  // the entry is being expired (near side 
message removal scheduled)
@@ -757,7 +757,7 @@ load_state( sync_vars_t *svars )
}
if (ll == 1)
goto gothdr;
-   if (line == 1 && isdigit( buf[0] )) {
+   if (line == 1 && isdigit( buf[0] )) {  // Pre-1.1 legacy
if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 
||
sscanf( buf1, "%u:%u", >uidval[F], 
>maxuid[F] ) < 2 ||
sscanf( buf2, "%u:%u:%u", 
>uidval[N], , >maxuid[N] ) < 3) {
@@ -781,7 +781,7 @@ load_state( sync_vars_t *svars )
svars->maxuid[N] = uid;
else if (!strcmp( buf1, "MaxExpiredFarUid" ) || 
!strcmp( buf1, "MaxExpiredMasterUid" ) /* Pre-1.4 legacy */)
svars->maxxfuid = uid;
-   else if (!strcmp( buf1, "MaxExpiredSlaveUid" ))  // 
Legacy
+   else if (!strcmp( buf1, "MaxExpiredSlaveUid" ))  // 
Pre-1.3 legacy
  

[commit] master: deprecate master/slave terminology

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c8f402e43f9c6a3c685fe0f716ffda741beeac13
Author: Oswald Buddenhagen 
Date:   Wed Jul 22 19:44:26 2020 +0200

deprecate master/slave terminology

the underlying metaphor refers to an inhumane practice, so using it
casually is rightfully offensive to many people. it isn't even a
particularly apt metaphor, as it suggests a strict hierarchy that is
counter to mbsync's highly symmetrical mode of operation.

the far/near terminology has been chosen as the replacement, as it is a
natural fit for the push/pull terminology. on the downside, due to these
not being nouns, a few uses are a bit awkward, and several others had to
be amended to include 'side'. also, it's conceptually quite close to
remote/local, which matches the typical use case, but is maybe a bit too
suggestive of actually non-existing limitations.

the new f/n suffixes of the -C/-R/-X options clash with pre-existing
options, so direct concatenation of short options is even less practical
than before (some suffixes of -D already clashed), but doing that leads
to unreadable command lines anyway.

as with previous deprecations, all pre-existing command line and config
options keep working, but yield a warning. the state files are silently
upgraded.

 NEWS|   2 +
 TODO|   8 +-
 src/config.c|  95 +-
 src/config.h|   1 +
 src/main.c  | 160 +
 src/mbsync.1|  54 +++---
 src/mbsyncrc.sample |  26 +--
 src/run-tests.pl| 104 +--
 src/sync.c  | 410 ++--
 src/sync.h  |  10 +-
 10 files changed, 450 insertions(+), 420 deletions(-)

diff --git a/NEWS b/NEWS
index 4133a50..8b6aae1 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ The IMAP user query can be scripted now.
 
 Added built-in support for macOS Keychain.
 
+The use of Master/Slave terminology has been deprecated.
+
 [1.3.0]
 
 Network timeout handling has been added.
diff --git a/TODO b/TODO
index 66c9489..7a6c98d 100644
--- a/TODO
+++ b/TODO
@@ -15,7 +15,7 @@ should complain when multiple Channels match the same folders.
 propagate folder deletions even when the folders are non-empty.
 - verify that "most" of the folders in the Channel are still there.
 - refuse to delete unpropagated messages when trashing on the remote side.
-- refuse to delete master if it has unpropagated messages. symmetry?
+- refuse to delete far side if it has unpropagated messages. symmetry?
 
 add message expiration based on arrival date (message date would be too
 unreliable). MaxAge; probably mutually exclusive to MaxMessages.
@@ -28,9 +28,9 @@ add support for event notification callbacks.
 it would be also possible to report more differentiated exit codes, but
 that seems too limiting in the general case.
 
-make it possible to have different mailbox names for Master and Slave in
+make it possible to have different mailbox names for far and near side in
 Patterns.
-- use master:slave for the pattern
+- use far:near for the pattern
   - for quoting, use more colons: the longest sequence of colons is the
 separator
 - this makes Groups mostly useless, as they are mostly a workaround for this
@@ -63,7 +63,7 @@ use MULTIAPPEND and FETCH with multiple messages.
 
 create dummies describing MIME structure of messages bigger than MaxSize.
 flagging the dummy would fetch the real message. possibly remove --renew.
-note that all interaction needs to happen on the slave side probably.
+note that all interaction needs to happen on the near side probably.
 
 don't SELECT boxes unless really needed; in particular not for appending,
 and in write-only mode not before changes are made.
diff --git a/src/config.c b/src/config.c
index 5ba3724..e6d0ff4 100644
--- a/src/config.c
+++ b/src/config.c
@@ -174,21 +174,21 @@ getopt_helper( conffile_t *cfile, int *cops, 
channel_conf_t *conf )
else if (!strcasecmp( "Flags", arg ))
*cops |= OP_FLAGS;
else if (!strcasecmp( "PullReNew", arg ))
-   conf->ops[S] |= OP_RENEW;
+   conf->ops[N] |= OP_RENEW;
else if (!strcasecmp( "PullNew", arg ))
-   conf->ops[S] |= OP_NEW;
+   conf->ops[N] |= OP_NEW;
else if (!strcasecmp( "PullDelete", arg ))
-   conf->ops[S] |= OP_DELETE;
+   conf->ops[N] |= OP_DELETE;
else if (!strcasecmp( "PullFlags", arg ))
-   conf->ops[S] |= OP_FLAGS;
+   conf->ops[N] |= OP_FLAGS;
else if (!strcasecmp( "PushReNew", arg ))
-   conf->ops[M] |= OP_RENEW;
+   conf->ops[F] |= OP_RENEW;
   

[commit] master: centralize disposal of parsed IMAP lists

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b91dd5b3bccfed97d5e479d2b18007c6fd819836
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 13:51:14 2019 +0100

centralize disposal of parsed IMAP lists

makes the code less cluttered, and it's harder to introduce leaks.

this has the hypothetical disadvantage that due to freeing being
delayed, the peak memory usage would rise significantly if we chained to
another parse_list() call which produces a big list while already
holding a big list, but that isn't the case anywhere.

 src/drv_imap.c | 30 --
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 5f51706..dbc9c5f 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -886,6 +886,7 @@ parse_list_continue( imap_store_t *ctx, char *s )
list = (resp == LIST_BAD) ? NULL : ctx->parse_list_sts.head;
ctx->parse_list_sts.head = NULL;
resp = ctx->parse_list_sts.callback( ctx, list, s );
+   free_list( list );
}
return resp;
 }
@@ -910,7 +911,6 @@ parse_namespace_rsp( imap_store_t *ctx, list_t *list, char 
*s )
if (!list) {
  bad:
error( "IMAP error: malformed NAMESPACE response\n" );
-   free_list( list );
return LIST_BAD;
}
if (list->val != NIL) {
@@ -931,22 +931,19 @@ parse_namespace_rsp( imap_store_t *ctx, list_t *list, 
char *s )
ctx->ns_delimiter = nsp_1st_dl->val[0];
// Namespace response extensions may follow here; we don't care.
}
-   free_list( list );
 
return parse_list( ctx, s, parse_namespace_rsp_p2 );
 }
 
 static int
-parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
+parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list ATTR_UNUSED, char *s )
 {
-   free_list( list );
return parse_list( ctx, s, parse_namespace_rsp_p3 );
 }
 
 static int
-parse_namespace_rsp_p3( imap_store_t *ctx ATTR_UNUSED, list_t *list, char *s 
ATTR_UNUSED )
+parse_namespace_rsp_p3( imap_store_t *ctx ATTR_UNUSED, list_t *list 
ATTR_UNUSED, char *s ATTR_UNUSED )
 {
-   free_list( list );
return LIST_OK;
 }
 
@@ -982,7 +979,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
 
if (!is_list( list )) {
error( "IMAP error: bogus FETCH response\n" );
-   free_list( list );
return LIST_BAD;
}
 
@@ -1105,7 +1101,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
if (cmdp->param.uid == uid)
goto gotuid;
error( "IMAP error: unexpected FETCH response (UID %u)\n", uid 
);
-   free_list( list );
return LIST_BAD;
  gotuid:
msgdata = ((imap_cmd_fetch_msg_t *)cmdp)->msg_data;
@@ -1131,7 +1126,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
cur->gen.tuid[0] = 0;
}
 
-   free_list( list );
return LIST_OK;
 }
 
@@ -1239,16 +1233,12 @@ parse_list_rsp( imap_store_t *ctx, list_t *list, char 
*cmd )
list_t *lp;
 
if (!is_list( list )) {
-   free_list( list );
error( "IMAP error: malformed LIST response\n" );
return LIST_BAD;
}
for (lp = list->child; lp; lp = lp->next)
-   if (is_atom( lp ) && !strcasecmp( lp->val, "\\NoSelect" )) {
-   free_list( list );
+   if (is_atom( lp ) && !strcasecmp( lp->val, "\\NoSelect" ))
return LIST_OK;
-   }
-   free_list( list );
return parse_list( ctx, cmd, parse_list_rsp_p1 );
 }
 
@@ -1257,7 +1247,6 @@ parse_list_rsp_p1( imap_store_t *ctx, list_t *list, char 
*cmd ATTR_UNUSED )
 {
if (!is_opt_atom( list )) {
error( "IMAP error: malformed LIST response\n" );
-   free_list( list );
return LIST_BAD;
}
if (!ctx->delimiter[0] && is_atom( list ))
@@ -1297,7 +1286,6 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char 
*cmd ATTR_UNUSED )
 
if (!is_atom( list )) {
error( "IMAP error: malformed LIST response\n" );
-   free_list( list );
return LIST_BAD;
}
arg = list->val;
@@ -1308,7 +1296,7 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char 
*cmd ATTR_UNUSED )
memcpy( arg, "INBOX", 5 );
} else if ((l = strlen( ctx->prefix ))) {
if (!starts_with( arg, argl, ctx->prefix, l ))
-   goto skip;
+   return LIST_OK;
arg += l;
argl -= l;
// A folder named "INBOX" would be indistinguishable from the
@@ -1318,19 +1306,17 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, 
char 

[commit] master: re-nest parse_fetch_rsp()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 47b477b3fb67f285b36e034a79d9e174bdf96ab3
Author: Oswald Buddenhagen 
Date:   Fri Nov 22 16:54:31 2019 +0100

re-nest parse_fetch_rsp()

prefer early exits over else branches, which is easier to follow.

 src/drv_imap.c | 112 -
 1 file changed, 54 insertions(+), 58 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index a22c0fd..7a08722 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1056,65 +1056,61 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
}
 
for (tmp = list->child; tmp; tmp = tmp->next) {
-   if (is_atom( tmp )) {
-   if (!strcmp( "UID", tmp->val )) {
-   tmp = tmp->next;
-   if (!is_atom( tmp ) || (uid = strtoul( 
tmp->val, , 10 ), *ep)) {
-   error( "IMAP error: unable to parse 
UID\n" );
-   goto ffail;
-   }
-   continue;  // This *is* the UID.
-   } else if (!strcmp( "FLAGS", tmp->val )) {
-   tmp = tmp->next;
-   if (is_list( tmp )) {
-   if (!parse_fetched_flags( tmp->child, 
,  ))
-   goto ffail;
-   continue;  // This may legitimately 
come without UID.
-   } else {
-   error( "IMAP error: unable to parse 
FLAGS\n" );
-   goto ffail;
-   }
-   } else if (!strcmp( "INTERNALDATE", tmp->val )) {
-   tmp = tmp->next;
-   if (is_atom( tmp )) {
-   if ((date = parse_date( tmp->val )) == 
-1) {
-   error( "IMAP error: unable to 
parse INTERNALDATE format\n" );
-   goto ffail;
-   }
-   } else {
-   error( "IMAP error: unable to parse 
INTERNALDATE\n" );
-   goto ffail;
-   }
-   } else if (!strcmp( "RFC822.SIZE", tmp->val )) {
-   tmp = tmp->next;
-   if (!is_atom( tmp ) || (size = strtoul( 
tmp->val, , 10 ), *ep)) {
-   error( "IMAP error: unable to parse 
RFC822.SIZE\n" );
-   goto ffail;
-   }
-   } else if (!strcmp( "BODY[]", tmp->val )) {
-   tmp = tmp->next;
-   if (is_atom( tmp )) {
-   body = tmp;
-   } else {
-   error( "IMAP error: unable to parse 
BODY[]\n" );
-   goto ffail;
-   }
-   } else if (!strcmp( "BODY[HEADER.FIELDS", tmp->val )) {
-   tmp = tmp->next;
-   if (is_list( tmp )) {
-   tmp = tmp->next;
-   if (!is_atom( tmp ) || strcmp( 
tmp->val, "]" ))
-   goto bfail;
-   tmp = tmp->next;
-   if (!is_atom( tmp ))
-   goto bfail;
-   parse_fetched_header( tmp->val, uid, 
,  );
-   } else {
- bfail:
-   error( "IMAP error: unable to parse 
BODY[HEADER.FIELDS ...]\n" );
-   goto ffail;
-   }
+   if (!is_atom( tmp ))
+   continue;
+   if (!strcmp( "UID", tmp->val )) {
+   tmp = tmp->next;
+   if (!is_atom( tmp ) || (uid = strtoul( tmp->val, , 
10 ), *ep)) {
+   error( "IMAP error: unable to parse UID\n" );
+   goto ffail;
+   }
+   continue;  // This *is* the UID.
+   } else if (!strcmp( "FLAGS", tmp->val )) {
+   tmp = tmp->next;
+   if (!is_list( tmp )) {
+   error( "IMAP error: unable to parse FLAGS\n" );
+   goto ffail;
+   }
+   if 

[commit] master: use more appropriate return value in driver_t::select_box()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 8457225a50d21d4b663af80c4a60202bb165a054
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 00:23:33 2020 +0200

use more appropriate return value in driver_t::select_box()

don't say DRV_CANCELED when it's really DRV_STORE_BAD, as apart from
being just wrong, it lead to the confusing effect of canceling a store
as the result of a supposed cancellation of the same store.

 src/drv_maildir.c | 2 +-
 src/sync.c| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 7ecf2d7..0cb796a 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1269,7 +1269,7 @@ maildir_select_box( store_t *gctx, const char *name )
}
} else {
if (!(ctx->path = maildir_join_path( conf, 0, name )))
-   return DRV_CANCELED;
+   return DRV_STORE_BAD;
ctx->is_inbox = 0;
}
return ctx->path ? DRV_OK : DRV_BOX_BAD;
diff --git a/src/sync.c b/src/sync.c
index 730e489..afe222d 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1190,7 +1190,7 @@ sync_boxes( store_t *ctx[], const char * const names[], 
int present[], channel_c
 * don't run into uninitialized variables. */
for (t = 0; t < 2; t++) {
switch (svars->drv[t]->select_box( ctx[t], svars->box_name[t] 
)) {
-   case DRV_CANCELED:
+   case DRV_STORE_BAD:
store_bad( AUX );
return;
case DRV_BOX_BAD:


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: handle messages which are newly doomed after an interruption

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit ceb09fcd44246ab7dad1a352b29854b6b86c3ddf
Author: Oswald Buddenhagen 
Date:   Tue Jul 21 16:10:28 2020 +0200

handle messages which are newly doomed after an interruption

we already didn't propagate messages which would be instantly expunged
from the target, but failed to cancel propagations that were already
scheduled before we got interrupted. this matters a bit when the
resumption happens significantly later than the initial attempt, giving
the user time to mark messages on the source as deleted.

 src/sync.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/sync.c b/src/sync.c
index 7ffd180..64ecaa3 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1593,7 +1593,13 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
 : svars->newmaxuid[1-t] < tmsg->uid && 
(svars->chan->ops[t] & OP_NEW)) {
debug( "new message %u on %s\n", tmsg->uid, 
str_fn[1-t] );
if ((svars->chan->ops[t] & OP_EXPUNGE) && 
(tmsg->flags & F_DELETED)) {
-   debug( "-> ignoring - would be expunged 
anyway\n" );
+   if (srec) {
+   JLOG( "- %u %u", (srec->uid[F], 
srec->uid[N]), "killing - would be expunged anyway" );
+   tmsg->srec = NULL;
+   srec->status = S_DEAD;
+   } else {
+   debug( "-> ignoring - would be 
expunged anyway\n" );
+   }
} else {
if (srec) {
debug( "-> pair(%u,%u) 
exists\n", srec->uid[F], srec->uid[N] );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: re-nest conditions for syncing new messages

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 8df1f5dd646d165a9a8fb90f57c3a8872ab3ce7a
Author: Oswald Buddenhagen 
Date:   Wed Jul 8 14:37:57 2020 +0200

re-nest conditions for syncing new messages

this makes the logic easier to follow and document in place.
also, make the comments actually match reality.

 src/sync.c | 104 ++---
 1 file changed, 59 insertions(+), 45 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 64ecaa3..f274058 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1572,14 +1572,9 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
}
}
 
-   debug( "synchronizing new entries\n" );
for (t = 0; t < 2; t++) {
+   debug( "synchronizing new messages on %s\n", str_fn[1-t] );
for (tmsg = svars->msgs[1-t]; tmsg; tmsg = tmsg->next) {
-   // If new have no srec, the message is always New. If 
we have a srec:
-   // - message is paired or expired => ignore
-   // - message was skipped => ReNew
-   // - message was attempted, but is still pending or 
failed => New
-   //
// If messages were previously ignored due to being 
excessive, they would now
// appear to be newer than the messages that got 
actually synced, so increment
// newmaxuid immediately to make sure we always look 
only at the newest ones.
@@ -1588,47 +1583,66 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
// in case of interruption - in particular skipping big 
messages would otherwise
// up the limit too early.
srec = tmsg->srec;
-   if (srec ? (((srec->status & S_PENDING) && 
(svars->chan->ops[t] & OP_NEW)) ||
-   ((srec->status & S_SKIPPED) && 
(svars->chan->ops[t] & OP_RENEW)))
-: svars->newmaxuid[1-t] < tmsg->uid && 
(svars->chan->ops[t] & OP_NEW)) {
-   debug( "new message %u on %s\n", tmsg->uid, 
str_fn[1-t] );
+   if (srec) {
+   if (srec->status & S_SKIPPED) {
+   // The message was skipped due to being 
too big.
+   if (!(svars->chan->ops[t] & OP_RENEW))
+   continue;
+   } else {
+   if (!(svars->chan->ops[t] & OP_NEW))
+   continue;
+   if (!(srec->status & S_PENDING))
+   continue;  // Nothing to do - 
the message is paired or expired
+   // Propagation was scheduled, but we 
got interrupted
+   }
+   debug( "unpropagated old message %u\n", 
tmsg->uid );
+
if ((svars->chan->ops[t] & OP_EXPUNGE) && 
(tmsg->flags & F_DELETED)) {
-   if (srec) {
-   JLOG( "- %u %u", (srec->uid[F], 
srec->uid[N]), "killing - would be expunged anyway" );
-   tmsg->srec = NULL;
-   srec->status = S_DEAD;
-   } else {
-   debug( "-> ignoring - would be 
expunged anyway\n" );
-   }
+   JLOG( "- %u %u", (srec->uid[F], 
srec->uid[N]), "killing - would be expunged anyway" );
+   tmsg->srec = NULL;
+   srec->status = S_DEAD;
+   continue;
+   }
+   } else {
+   if (!(svars->chan->ops[t] & OP_NEW))
+   continue;
+   if (tmsg->uid <= svars->newmaxuid[1-t]) {
+   // The message should be already 
paired. It's not, so it was:
+   // - previously paired, but the entry 
was expired and pruned => ignore
+   // - attempted, but failed => ignore 
(the wisdom of this is debatable)
+   // - ignored, as it would have been 
expunged anyway => ignore (even if undeleted)
+   continue;
+   }
+   debug( "new message %u\n", tmsg->uid );
+
+   if ((svars->chan->ops[t] & 

[commit] master: extract parse_fetched_header() from parse_fetch_rsp()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit d4ead05a0203d6dc959e565510f06998c3aabaa1
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 16:18:40 2019 +0100

extract parse_fetched_header() from parse_fetch_rsp()

 src/drv_imap.c | 79 +++---
 1 file changed, 43 insertions(+), 36 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 48bf6ec..6832d5d 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -965,6 +965,48 @@ parse_date( const char *str )
return date - (hours * 60 + mins) * 60;
 }
 
+static void
+parse_fetched_header( char *val, uint uid, char **tuid, char **msgid )
+{
+   char *end;
+   int off, in_msgid = 0;
+   for (; (end = strchr( val, '\n' )); val = end + 1) {
+   int len = (int)(end - val);
+   if (len && end[-1] == '\r')
+   len--;
+   if (!len)
+   break;
+   if (starts_with_upper( val, len, "X-TUID: ", 8 )) {
+   if (len < 8 + TUIDL) {
+   warn( "IMAP warning: malformed X-TUID header 
(UID %u)\n", uid );
+   continue;
+   }
+   *tuid = val + 8;
+   in_msgid = 0;
+   continue;
+   }
+   if (starts_with_upper( val, len, "MESSAGE-ID:", 11 )) {
+   off = 11;
+   } else if (in_msgid) {
+   if (!isspace( val[0] )) {
+   in_msgid = 0;
+   continue;
+   }
+   off = 1;
+   } else {
+   continue;
+   }
+   while (off < len && isspace( val[off] ))
+   off++;
+   if (off == len) {
+   in_msgid = 1;
+   continue;
+   }
+   *msgid = nfstrndup( val + off, (size_t)(len - off) );
+   in_msgid = 0;
+   }
+}
+
 static int
 parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
 {
@@ -1058,42 +1100,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
tmp = tmp->next;
if (!is_atom( tmp ))
goto bfail;
-   int off, in_msgid = 0;
-   for (char *val = tmp->val, *end; (end = 
strchr( val, '\n' )); val = end + 1) {
-   int len = (int)(end - val);
-   if (len && end[-1] == '\r')
-   len--;
-   if (!len)
-   break;
-   if (starts_with_upper( val, 
len, "X-TUID: ", 8 )) {
-   if (len < 8 + TUIDL) {
-   warn( "IMAP 
warning: malformed X-TUID header (UID %u)\n", uid );
-   continue;
-   }
-   tuid = val + 8;
-   in_msgid = 0;
-   continue;
-   }
-   if (starts_with_upper( val, 
len, "MESSAGE-ID:", 11 )) {
-   off = 11;
-   } else if (in_msgid) {
-   if (!isspace( val[0] )) 
{
-   in_msgid = 0;
-   continue;
-   }
-   off = 1;
-   } else {
-   continue;
-   }
-   while (off < len && isspace( 
val[off] ))
-   off++;
-   if (off == len) {
-   in_msgid = 1;
-   continue;
-   }
-   msgid = nfstrndup( val + off, 
(size_t)(len - off) );
-   in_msgid = 0;
-  

[commit] master: Add option to use IMAP LSUB instead of LIST

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 990cc112f1d6807adfe07a550bedd179177d5949
Author: Oswald Buddenhagen 
Date:   Tue Nov 26 15:49:19 2019 +0100

Add option to use IMAP LSUB instead of LIST

Based on patch by Cedric Ware 

 NEWS   |  2 ++
 src/drv_imap.c | 10 +++---
 src/mbsync.1   |  8 
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 18e4f13..d1a27aa 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ The IMAP '$Forwarded' / Maildir 'P' (passed) flag is supported 
now.
 
 Support for configuring a TLS cipher string was added.
 
+IMAP mailbox subscriptions are supported now.
+
 [1.3.0]
 
 Network timeout handling has been added.
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 5563ff4..7d271bd 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -66,6 +66,7 @@ typedef struct {
imap_server_conf_t *server;
char delimiter;
char use_namespace;
+   char use_lsub;
 } imap_store_conf_t;
 
 typedef struct {
@@ -1453,7 +1454,7 @@ imap_socket_read( void *aux )
error( "Error from IMAP server: %s\n", cmd );
} else if (!strcmp( "CAPABILITY", arg )) {
parse_capability( ctx, cmd );
-   } else if (!strcmp( "LIST", arg )) {
+   } else if (!strcmp( "LIST", arg ) || !strcmp( "LSUB", 
arg )) {
resp = parse_list( ctx, cmd, parse_list_rsp );
goto listret;
} else if (!strcmp( "NAMESPACE", arg )) {
@@ -3083,6 +3084,7 @@ imap_list_store( store_t *gctx, int flags,
  void (*cb)( int sts, string_list_t *boxes, void *aux ), void 
*aux )
 {
imap_store_t *ctx = (imap_store_t *)gctx;
+   imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
INIT_REFCOUNTED_STATE(imap_list_store_state_t, sts, cb, aux)
 
// ctx->prefix may be empty, "INBOX.", or something else.
@@ -3106,14 +3108,14 @@ imap_list_store( store_t *gctx, int flags,
if (pfx_is_empty)
ctx->listed |= LIST_INBOX;
imap_exec( ctx, imap_refcounted_new_cmd( >gen ), 
imap_list_store_p2,
-  "LIST \"\" \"%\\s*\"", ctx->prefix );
+  "%s \"\" \"%\\s*\"", cfg->use_lsub ? "LSUB" : 
"LIST", ctx->prefix );
}
if (((flags & LIST_INBOX) || pfx_is_inbox) && !pfx_is_empty && 
!(ctx->listed & LIST_INBOX)) {
ctx->listed |= LIST_INBOX;
if (pfx_is_inbox)
ctx->listed |= LIST_PATH;
imap_exec( ctx, imap_refcounted_new_cmd( >gen ), 
imap_list_store_p2,
-  "LIST \"\" INBOX*" );
+  "%s \"\" INBOX*", cfg->use_lsub ? "LSUB" : "LIST" );
}
imap_list_store_p3( ctx, sts );
 }
@@ -3373,6 +3375,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
store->server = srv;
} else if (!strcasecmp( "UseNamespace", cfg->cmd ))
store->use_namespace = parse_bool( cfg );
+   else if (!strcasecmp( "SubscribedOnly", cfg->cmd ))
+   store->use_lsub = parse_bool( cfg );
else if (!strcasecmp( "Path", cfg->cmd ))
store->gen.path = nfstrdup( cfg->val );
else if (!strcasecmp( "PathDelimiter", cfg->cmd )) {
diff --git a/src/mbsync.1 b/src/mbsync.1
index 325385f..423d796 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -466,6 +466,14 @@ Specify the server's hierarchy delimiter.
 Do \fInot\fR abuse this to re-interpret the hierarchy.
 Use \fBFlatten\fR instead.
 .
+.TP
+\fBSubscribedOnly\fR \fByes\fR|\fBno\fR
+Selects whether to synchronize only mailboxes that are subscribed to on the
+IMAP server. In technical terms, if this option is set, \fBmbsync\fR will use
+the IMAP command LSUB instead of LIST to look for mailboxes in this Store.
+This option make sense only in conjunction with \fBPatterns\fR.
+(Default: \fBno\fR)
+.
 .SS Channels
 .TP
 \fBChannel\fR \fIname\fR


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: remove redundant condition

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 4aaada18e9a32ca06cedc96da4ea30c8f3669b73
Author: Oswald Buddenhagen 
Date:   Sat Jul 11 16:21:20 2020 +0200

remove redundant condition

the 'pending' and 'skipped' sync record states are mutually exclusive
with having a complementary message, so there is no point in testing it
explicitly.

amends bd5fb6ff.

 src/sync.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 1eb5839..7ffd180 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1588,8 +1588,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
// in case of interruption - in particular skipping big 
messages would otherwise
// up the limit too early.
srec = tmsg->srec;
-   if (srec ? !srec->uid[t] &&
-  (((srec->status & S_PENDING) && 
(svars->chan->ops[t] & OP_NEW)) ||
+   if (srec ? (((srec->status & S_PENDING) && 
(svars->chan->ops[t] & OP_NEW)) ||
((srec->status & S_SKIPPED) && 
(svars->chan->ops[t] & OP_RENEW)))
 : svars->newmaxuid[1-t] < tmsg->uid && 
(svars->chan->ops[t] & OP_NEW)) {
debug( "new message %u on %s\n", tmsg->uid, 
str_fn[1-t] );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-duplicate exit paths of imap_alloc_store()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b148fd9e446e30b889764a4d0d96098842684270
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 09:08:17 2020 +0200

de-duplicate exit paths of imap_alloc_store()

 src/drv_imap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 75b44cd..3c2825f 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1805,8 +1805,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
for (ctxp =  (ctx = (imap_store_t *)*ctxp); ctxp = 
>gen.next)
if (ctx->state == SST_GOOD && ctx->gen.conf == conf) {
*ctxp = ctx->gen.next;
-   ctx->label = label;
-   return >gen;
+   goto gotstore;
}
 
/* Then try to recycle a server connection. */
@@ -1835,6 +1834,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
 
   gotsrv:
ctx->gen.conf = conf;
+  gotstore:
ctx->label = label;
return >gen;
 }


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: don't rewrite state gratuitously

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 68a412115a75223fb9561f0a467970d2a4af65bf
Author: Oswald Buddenhagen 
Date:   Mon Nov 25 20:55:41 2019 +0100

don't rewrite state gratuitously

delay the creation of the new state and journal until there is actually
something interesting to write. this saves some cpu cycles and prolongs
ssd life a whee bit.

 src/run-tests.pl |  5 ++--
 src/sync.c   | 71 ++--
 2 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 1033407..4b936d9 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -702,7 +702,7 @@ sub test($$$@)
rmtree "far";
 
my $njl = (@nj - 1) * 2;
-   for (my $l = 2; $l < $njl; $l++) {
+   for (my $l = 1; $l <= $njl; $l++) {
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
 
my ($nxc, @nret) = runsync("-J$l", "4-interrupt.log");
@@ -721,7 +721,8 @@ sub test($$$@)
print "Options:\n";
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." 
]\n";
my @nnj = readfile("near/.mbsyncstate.journal");
-   print "Journal:\n".join("", @nnj[0..($l / 2 - 
1)])."---\n".join("", @nnj[($l / 2)..$#nnj])."\n";
+   my $ln = int($l / 2);
+   print "Journal:\n".join("", 
@nnj[0..$ln])."---\n".join("", @nnj[($ln + 1)..$#nnj])."\n";
print "Full journal:\n".join("", @nj)."\n";
if (!$nxc) {
print "Expected result:\n";
diff --git a/src/sync.c b/src/sync.c
index 8dbdc62..f191e68 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -39,6 +39,8 @@
 # define fdatasync fsync
 #endif
 
+#define JOURNAL_VERSION "4"
+
 channel_conf_t global_conf;
 channel_conf_t *channels;
 group_conf_t *groups;
@@ -167,10 +169,12 @@ typedef struct {
uint ref_count, nsrecs, opts[2];
uint new_pending[2], flags_pending[2], trash_pending[2];
uint maxuid[2]; // highest UID that was already propagated
+   uint oldmaxuid[2];  // highest UID that was already propagated before 
this run
uint uidval[2]; // UID validity value
uint newuidval[2];  // UID validity obtained from driver
uint finduid[2];// TUID lookup makes sense only for UIDs >= this
uint maxxfuid;  // highest expired UID on far side
+   uint oldmaxxfuid;   // highest expired UID on far side before this run
uchar good_flags[2], bad_flags[2];
 } sync_vars_t;
 
@@ -218,6 +222,15 @@ static int check_cancel( sync_vars_t *svars );
 #define ST_SENDING_NEW (1<<15)
 
 
+static void
+create_state( sync_vars_t *svars )
+{
+   if (!(svars->nfp = fopen( svars->nname, "w" ))) {
+   sys_error( "Error: cannot create new sync state %s", 
svars->nname );
+   exit( 1 );
+   }
+}
+
 static void ATTR_PRINTFLIKE(2, 3)
 jFprintf( sync_vars_t *svars, const char *msg, ... )
 {
@@ -225,6 +238,16 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
 
if (JLimit && !--JLimit)
exit( 101 );
+   if (!svars->jfp) {
+   create_state( svars );
+   if (!(svars->jfp = fopen( svars->jname, svars->replayed ? "a" : 
"w" ))) {
+   sys_error( "Error: cannot create journal %s", 
svars->jname );
+   exit( 1 );
+   }
+   setlinebuf( svars->jfp );
+   if (!svars->replayed)
+   Fprintf( svars->jfp, JOURNAL_VERSION "\n" );
+   }
va_start( va, msg );
vFprintf( svars->jfp, msg, va );
va_end( va );
@@ -625,8 +648,6 @@ clean_strdup( const char *s )
 }
 
 
-#define JOURNAL_VERSION "4"
-
 static int
 prepare_state( sync_vars_t *svars )
 {
@@ -704,6 +725,12 @@ save_state( sync_vars_t *svars )
sync_rec_t *srec;
char fbuf[16]; /* enlarge when support for keywords is added */
 
+   // If no change was made, the state is also unmodified.
+   if (!svars->jfp && !svars->replayed)
+   return;
+
+   if (!svars->nfp)
+   create_state( svars );
Fprintf( svars->nfp,
 "FarUidValidity %u\nNearUidValidity %u\nMaxPulledUid 
%u\nMaxPushedUid %u\n",
 svars->uidval[F], svars->uidval[N], svars->maxuid[F], 
svars->maxuid[N] );
@@ -719,7 +746,8 @@ save_state( sync_vars_t *svars )
}
 
Fclose( svars->nfp, 1 );
-   Fclose( svars->jfp, 0 );
+   if (svars->jfp)
+   Fclose( svars->jfp, 0 );
if (!(DFlags & KEEPJOURNAL)) {
/* order is important! */
if (rename( svars->nname, svars->dname ))
@@ -1234,18 +1262,6 @@ box_opened2( sync_vars_t *svars, int t )
 
if (!lock_state( svars ))
goto bail;
-   if (!(svars->nfp = fopen( svars->nname, "w" ))) {
-   sys_error( "Error: cannot create new sync state %s", 

[commit] master: complain about malformed item names in FETCH responses

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 8acf56b3113f6b6a31bf841edfb2fe36c6206026
Author: Oswald Buddenhagen 
Date:   Fri Nov 22 17:49:04 2019 +0100

complain about malformed item names in FETCH responses

 src/drv_imap.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 7a08722..826e12b 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1056,8 +1056,10 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
}
 
for (tmp = list->child; tmp; tmp = tmp->next) {
-   if (!is_atom( tmp ))
-   continue;
+   if (!is_atom( tmp )) {
+   error( "IMAP error: bogus item name in FETCH 
response\n" );
+   goto ffail;
+   }
if (!strcmp( "UID", tmp->val )) {
tmp = tmp->next;
if (!is_atom( tmp ) || (uid = strtoul( tmp->val, , 
10 ), *ep)) {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: create placeholders for messages over MaxSize

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 70bad661298017c07d996294928f6cd7421b6792
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 14:37:53 2019 +0100

create placeholders for messages over MaxSize

this is vastly more useful than just omitting the messages with no
indication at all.

 NEWS  |   2 +
 TODO  |   5 +-
 src/driver.h  |   7 +-
 src/drv_imap.c|  14 +--
 src/drv_maildir.c |   4 +-
 src/mbsync.1  |  17 ++-
 src/run-tests.pl  |  85 +++
 src/sync.c| 263 ++
 8 files changed, 314 insertions(+), 83 deletions(-)

diff --git a/NEWS b/NEWS
index 8b6aae1..6e094e6 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ The IMAP user query can be scripted now.
 
 Added built-in support for macOS Keychain.
 
+Messages excluded by MaxSize will now result in placeholders.
+
 The use of Master/Slave terminology has been deprecated.
 
 [1.3.0]
diff --git a/TODO b/TODO
index 7a6c98d..10bd61f 100644
--- a/TODO
+++ b/TODO
@@ -61,9 +61,8 @@ messages.
 
 use MULTIAPPEND and FETCH with multiple messages.
 
-create dummies describing MIME structure of messages bigger than MaxSize.
-flagging the dummy would fetch the real message. possibly remove --renew.
-note that all interaction needs to happen on the near side probably.
+dummy messages resulting from MaxSize should contain a dump of the original
+message's MIME structure and its (reasonably sized) text parts.
 
 don't SELECT boxes unless really needed; in particular not for appending,
 and in write-only mode not before changes are made.
diff --git a/src/driver.h b/src/driver.h
index 4921153..575ec86 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -80,7 +80,6 @@ typedef struct message {
 #define OPEN_OLD(1<<0)  // Paired messages *in* this store.
 #define OPEN_NEW(1<<1)  // Messages (possibly) not yet propagated 
*from* this store.
 #define OPEN_FLAGS  (1<<2)  // Note that fetch_msg() gets the flags 
regardless.
-#define OPEN_OLD_SIZE   (1<<3)
 #define OPEN_NEW_SIZE   (1<<4)
 #define OPEN_EXPUNGE(1<<5)
 #define OPEN_SETFLAGS   (1<<6)
@@ -217,8 +216,10 @@ struct driver {
void (*load_box)( store_t *ctx, uint minuid, uint maxuid, uint finduid, 
uint pairuid, uint newuid, uint_array_t excs,
  void (*cb)( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux ), void *aux );
 
-   /* Fetch the contents and flags of the given message from the current 
mailbox. */
-   void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
+   /* Fetch the contents and flags of the given message from the current 
mailbox.
+* If minimal is non-zero, fetch only a placeholder for the requested 
message -
+* ideally, this is precisely the header, but it may be more. */
+   void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data, int 
minimal,
   void (*cb)( int sts, void *aux ), void *aux );
 
/* Store the given message to either the current mailbox or the trash 
folder.
diff --git a/src/drv_imap.c b/src/drv_imap.c
index e1bc304..4b9a429 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1098,7 +1098,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
error( "IMAP error: unable to parse 
RFC822.SIZE\n" );
goto ffail;
}
-   } else if (!strcmp( "BODY[]", name )) {
+   } else if (!strcmp( "BODY[]", name ) || !strcmp( 
"BODY[HEADER]", name )) {
if (!is_atom( tmp )) {
error( "IMAP error: unable to parse BODY[]\n" );
goto ffail;
@@ -2714,9 +2714,8 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, 
uint finduid, uint pairu
ranges[0].last = maxuid;
ranges[0].flags = 0;
uint nranges = 1;
-   if (ctx->opts & (OPEN_OLD_SIZE | OPEN_NEW_SIZE))
-   imap_set_range( ranges, , shifted_bit( 
ctx->opts, OPEN_OLD_SIZE, WantSize),
- shifted_bit( 
ctx->opts, OPEN_NEW_SIZE, WantSize), newuid );
+   if (ctx->opts & OPEN_NEW_SIZE)
+   imap_set_range( ranges, , 0, WantSize, 
newuid );
if (ctx->opts & OPEN_FIND)
imap_set_range( ranges, , 0, WantTuids, 
finduid - 1 );
if (ctx->opts & OPEN_OLD_IDS)
@@ -2811,7 +2810,7 @@ imap_submit_load_p3( imap_store_t *ctx, 
imap_load_box_state_t *sts )
 static void imap_fetch_msg_p2( imap_store_t *, imap_cmd_t *, int );
 
 static void
-imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data,
+imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data, int minimal,
 void (*cb)( int sts, void *aux ), 

[commit] master: add some ATTR_* (mostly)

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 71d7d3e6dfd29517268c1848c3348ad0eb7fae13
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 19:52:41 2019 +0200

add some ATTR_* (mostly)

mostly ATTR_PRINTFLIKE(*, 0) for functions with a va_list argument.

also, one ATTR_NORETURN and one ATTR_UNUSED, both on functions.

also, an explicit suppression for a format string stored in a variable.

 src/common.h   | 8 
 src/drv_imap.c | 3 +++
 src/main.c | 2 +-
 src/sync.c | 6 +++---
 src/util.c | 2 +-
 5 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/common.h b/src/common.h
index b15cc15..1c10459 100644
--- a/src/common.h
+++ b/src/common.h
@@ -122,8 +122,8 @@ void stats( void );
 
 /* util.c */
 
-void vdebug( int, const char *, va_list va );
-void vdebugn( int, const char *, va_list va );
+void ATTR_PRINTFLIKE(2, 0) vdebug( int, const char *, va_list va );
+void ATTR_PRINTFLIKE(2, 0) vdebugn( int, const char *, va_list va );
 void ATTR_PRINTFLIKE(1, 2) info( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) infon( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) progress( const char *, ... );
@@ -163,7 +163,7 @@ void *nfcalloc( size_t sz );
 void *nfrealloc( void *mem, size_t sz );
 char *nfstrndup( const char *str, size_t nchars );
 char *nfstrdup( const char *str );
-int nfvasprintf( char **str, const char *fmt, va_list va );
+int ATTR_PRINTFLIKE(2, 0) nfvasprintf( char **str, const char *fmt, va_list va 
);
 int ATTR_PRINTFLIKE(2, 3) nfasprintf( char **str, const char *fmt, ... );
 int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, 
... );
 void ATTR_NORETURN oob( void );
@@ -244,7 +244,7 @@ typedef struct {
 void init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux );
 void conf_wakeup( wakeup_t *tmr, int timeout );
 void wipe_wakeup( wakeup_t *tmr );
-static INLINE int pending_wakeup( wakeup_t *tmr ) { return tmr->links.next != 
0; }
+static INLINE int ATTR_UNUSED pending_wakeup( wakeup_t *tmr ) { return 
tmr->links.next != 0; }
 
 void main_loop( void );
 
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 8137edd..dc00a14 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -306,8 +306,11 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd )
buffmt = "%d %s{%d+}\r\n";
litplus = 1;
}
+DIAG_PUSH
+DIAG_DISABLE("-Wformat-nonliteral")
bufl = nfsnprintf( buf, sizeof(buf), buffmt,
   cmd->tag, cmd->cmd, cmd->param.data_len );
+DIAG_POP
if (DFlags & DEBUG_NET) {
if (ctx->num_in_progress)
printf( "(%d in progress) ", ctx->num_in_progress );
diff --git a/src/main.c b/src/main.c
index 2b761c7..2cb092c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -136,7 +136,7 @@ debug( const char *msg, ... )
 }
 
 #ifdef __linux__
-static void
+static void ATTR_NORETURN
 crashHandler( int n )
 {
int dpid;
diff --git a/src/sync.c b/src/sync.c
index 6b90ba1..786ca1e 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -74,7 +74,7 @@ Fclose( FILE *f, int safe )
}
 }
 
-void
+void ATTR_PRINTFLIKE(2, 0)
 vFprintf( FILE *f, const char *msg, va_list va )
 {
int r;
@@ -86,7 +86,7 @@ vFprintf( FILE *f, const char *msg, va_list va )
}
 }
 
-void
+void ATTR_PRINTFLIKE(2, 3)
 Fprintf( FILE *f, const char *msg, ... )
 {
va_list va;
@@ -217,7 +217,7 @@ static int check_cancel( sync_vars_t *svars );
 #define ST_SENDING_NEW (1<<15)
 
 
-void
+void ATTR_PRINTFLIKE(2, 3)
 jFprintf( sync_vars_t *svars, const char *msg, ... )
 {
va_list va;
diff --git a/src/util.c b/src/util.c
index d506273..878ee40 100644
--- a/src/util.c
+++ b/src/util.c
@@ -42,7 +42,7 @@ flushn( void )
}
 }
 
-static void
+static void ATTR_PRINTFLIKE(1, 0)
 printn( const char *msg, va_list va )
 {
if (*msg == '\v')


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: do away with newmaxuid

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit e9efc49b6c1747da7256d0c276b97689f337f871
Author: Oswald Buddenhagen 
Date:   Mon Jul 20 20:53:21 2020 +0200

do away with newmaxuid

now that expiration order is determined by a single loop ordered by
far-side UIDs, it is no longer necessary to accurately track the highest
seen UID.

as a side effect, this fixes a problem reported (way too long ago) by
Yuri D'Elia: we failed to up newmaxuid for messages we produced
ourselves, so we would keep enumerating the same messages until we also
propagated externally generated messages from that mailbox - which might
have been never for the server side of archive/trash mailboxes.

 src/run-tests.pl | 18 ++---
 src/sync.c   | 66 
 2 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 77e0abc..4c257ee 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -61,7 +61,7 @@ my @X01 = (
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "FT", G, 7, 
"FT", I, 9, "", J, 10, "" ],
  [ 10,
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", G, 7, "FT", H, 8, 
"T", J, 9, "", I, 10, "" ],
- [ 9, 0, 9,
+ [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, 
"FT", 0, 8, "", 10, 9, "", 9, 10, "" ],
 );
 test("full", \@x01, \@X01, @O01);
@@ -73,7 +73,7 @@ my @X02 = (
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", I, 9, "", J, 10, "" ],
  [ 10,
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", J, 9, "", I, 10, "" ],
- [ 9, 0, 9,
+ [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
 );
 test("full + expunge both", \@x01, \@X02, @O02);
@@ -85,7 +85,7 @@ my @X03 = (
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "FT", G, 7, 
"FT", I, 9, "", J, 10, "" ],
  [ 10,
A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", J, 9, "", I, 10, "" ],
- [ 9, 0, 9,
+ [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 
10, 9, "", 9, 10, "" ],
 );
 test("full + expunge near side", \@x01, \@X03, @O03);
@@ -133,7 +133,7 @@ my @X07 = (
A, 1, "F", B, 2, "", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "F", G, 7, 
"FT", I, 9, "", J, 10, "" ],
  [ 10,
A, 1, "", B, 2, "F", C, 3, "F", D, 4, "", E, 5, "", G, 7, "", H, 8, "", J, 
9, "", I, 10, "" ],
- [ 9, 0, 9,
+ [ 10, 0, 10,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, 
"", 10, 9, "", 9, 10, "" ],
 );
 test("new", \@x01, \@X07, @O07);
@@ -168,7 +168,7 @@ my @X11 = (
A, 1, "", B, 2, "*" ],
  [ 2,
C, 1, "*", A, 2, "" ],
- [ 2, 0, 1,
+ [ 2, 0, 2,
0, 1, "^", 1, 2, "", 2, 0, "^" ],
 );
 test("max size", \@x10, \@X11, @O11);
@@ -180,7 +180,7 @@ my @X22 = (
A, 1, "", B, 2, "*", C, 3, "*" ],
  [ 2,
C, 1, "*", A, 2, "" ],
- [ 2, 0, 1,
+ [ 3, 0, 2,
3, 1, "", 1, 2, "", 2, 0, "^" ],
 );
 test("near side max size", \@X11, \@X22, @O22);
@@ -203,7 +203,7 @@ my @X31 = (
A, 1, "F", B, 2, "", C, 3, "S", D, 4, "", E, 5, "S", F, 6, "" ],
  [ 5,
A, 1, "F", B, 2, "", D, 3, "", E, 4, "S", F, 5, "" ],
- [ 6, 3, 0,
+ [ 6, 3, 5,
1, 1, "F", 2, 2, "", 4, 3, "", 5, 4, "S", 6, 5, "" ],
 );
 test("max messages", \@x30, \@X31, @O31);
@@ -215,7 +215,7 @@ my @X32 = (
A, 1, "F", B, 2, "", C, 3, "S", D, 4, "", E, 5, "S", F, 6, "" ],
  [ 4,
A, 1, "F", D, 2, "", E, 3, "S", F, 4, "" ],
- [ 6, 3, 0,
+ [ 6, 3, 4,
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
 );
 test("max messages vs. unread", \@x30, \@X32, @O32);
@@ -236,7 +236,7 @@ my @X51 = (
A, 1, "S", B, 2, "FS", C, 3, "S", D, 4, "", E, 5, "", F, 6, "" ],
  [ 6,
B, 2, "FS", D, 4, "", E, 5, "", F, 6, "" ],
- [ 6, 3, 0,
+ [ 6, 3, 6,
2, 2, "FS", 4, 4, "", 5, 5, "", 6, 6, "" ],
 );
 test("max messages + expunge", \@x50, \@X51, @O51);
diff --git a/src/sync.c b/src/sync.c
index 18a381b..166d7fb 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -167,7 +167,6 @@ typedef struct {
uint ref_count, nsrecs, opts[2];
uint new_pending[2], flags_pending[2], trash_pending[2];
uint maxuid[2]; // highest UID that was already propagated
-   uint newmaxuid[2];  // highest UID that is currently being propagated
uint uidval[2]; // UID validity value
uint newuidval[2];  // UID validity obtained from driver
uint finduid[2];// TUID lookup makes sense only for UIDs >= this
@@ -285,6 +284,8 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
srec->msg[t] = tmsg;
ntmsg = tmsg->next;
srec->uid[t] = tmsg->uid;
+   if (tmsg->uid == svars->maxuid[t] + 1)
+   svars->maxuid[t] = tmsg->uid;
srec->status = 0;
srec->tuid[0] = 0;
}
@@ -613,7 +614,7 @@ clean_strdup( const char *s )
 }
 
 
-#define JOURNAL_VERSION "3"
+#define JOURNAL_VERSION 

[commit] master: fully decompose NAMESPACE response early on

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 7af7354dbc07cba5a97ba9d87f2c0ca5b5ec6c64
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 13:41:32 2019 +0100

fully decompose NAMESPACE response early on

that way the code becomes clearer, and we don't keep useless nodes in
memory.

 src/drv_imap.c | 65 +++---
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index c4fa03a..5f51706 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -108,7 +108,7 @@ struct imap_store {
uint got_namespace:1;
uint has_forwarded:1;
char delimiter[2]; /* hierarchy delimiter */
-   list_t *ns_personal; /* NAMESPACE info */
+   char *ns_prefix, ns_delimiter; /* NAMESPACE info */
string_list_t *boxes; // _list results
char listed; // was _list already run with these flags?
// note that the message counts do _not_ reflect stats from msgs,
@@ -902,34 +902,37 @@ static int parse_namespace_rsp_p2( imap_store_t *, list_t 
*, char * );
 static int parse_namespace_rsp_p3( imap_store_t *, list_t *, char * );
 
 static int
-parse_namespace_check( list_t *list )
+parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
 {
-   if (!list)
-   goto bad;
-   if (list->val == NIL)
-   return 0;
-   if (list->val != LIST)
-   goto bad;
-   for (list = list->child; list; list = list->next) {
+   // We use only the 1st personal namespace. Making this configurable
+   // would not add value over just specifying Path.
+
+   if (!list) {
+ bad:
+   error( "IMAP error: malformed NAMESPACE response\n" );
+   free_list( list );
+   return LIST_BAD;
+   }
+   if (list->val != NIL) {
if (list->val != LIST)
goto bad;
-   if (!is_atom( list->child ))
+   list_t *nsp_1st = list->child;
+   if (nsp_1st->val != LIST)
goto bad;
-   if (!is_opt_atom( list->child->next ))
+   list_t *nsp_1st_ns = nsp_1st->child;
+   if (!is_atom( nsp_1st_ns ))
goto bad;
-   /* Namespace response extensions may follow here; we don't 
care. */
+   ctx->ns_prefix = nsp_1st_ns->val;
+   nsp_1st_ns->val = NULL;
+   list_t *nsp_1st_dl = nsp_1st_ns->next;
+   if (!is_opt_atom( nsp_1st_dl ))
+   goto bad;
+   if (is_atom( nsp_1st_dl ))
+   ctx->ns_delimiter = nsp_1st_dl->val[0];
+   // Namespace response extensions may follow here; we don't care.
}
-   return 0;
-  bad:
-   error( "IMAP error: malformed NAMESPACE response\n" );
-   return -1;
-}
+   free_list( list );
 
-static int
-parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
-{
-   if (parse_namespace_check( (ctx->ns_personal = list) ))
-   return LIST_BAD;
return parse_list( ctx, s, parse_namespace_rsp_p2 );
 }
 
@@ -1608,7 +1611,7 @@ imap_cancel_store( store_t *gctx )
socket_close( >conn );
cancel_sent_imap_cmds( ctx );
cancel_pending_imap_cmds( ctx );
-   free_list( ctx->ns_personal );
+   free( ctx->ns_prefix );
free_string_list( ctx->auth_mechs );
free_generic_messages( ctx->msgs );
free_string_list( ctx->boxes );
@@ -2335,19 +2338,11 @@ static void
 imap_open_store_namespace2( imap_store_t *ctx )
 {
imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
-   list_t *nsp, *nsp_1st;
 
-   /* XXX for now assume 1st personal namespace */
-   if (is_list( (nsp = ctx->ns_personal) ) &&
-   is_list( (nsp_1st = nsp->child) ))
-   {
-   list_t *nsp_1st_ns = nsp_1st->child;
-   list_t *nsp_1st_dl = nsp_1st_ns->next;
-   if (!ctx->prefix && cfg->use_namespace)
-   ctx->prefix = nsp_1st_ns->val;
-   if (!ctx->delimiter[0] && is_atom( nsp_1st_dl ))
-   ctx->delimiter[0] = nsp_1st_dl->val[0];
-   }
+   if (!ctx->prefix && cfg->use_namespace)
+   ctx->prefix = ctx->ns_prefix;
+   if (!ctx->delimiter[0])
+   ctx->delimiter[0] = ctx->ns_delimiter;
imap_open_store_finalize( ctx );
 }
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: streamline counting of currently pushed messages wrt. expiration

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 5d6741a9a8ba71ae94ae15f9bd79f34d8d785ea4
Author: Oswald Buddenhagen 
Date:   Sun Jul 12 17:21:15 2020 +0200

streamline counting of currently pushed messages wrt. expiration

don't count them as alive just to ignore them in the next step.

 src/sync.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index f274058..fc7cec6 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1657,10 +1657,15 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD)
continue;
-   if ((srec = tmsg->srec) && srec->uid[F] &&
-   ((tmsg->flags | srec->aflags[N]) & ~srec->dflags[N] 
& F_DELETED) &&
-   !(srec->status & (S_EXPIRE|S_EXPIRED))) {
-   /* Message was not propagated yet, or is 
deleted. */
+   if (!(srec = tmsg->srec) || !srec->uid[F]) {
+   // The message was not propagated, so it 
doesn't count towards the total.
+   // Note that we also ignore messages we're 
currently propagating, which
+   // delays expiry of some messages by one cycle. 
Otherwise, we'd have to
+   // sequence flag propagation after message 
propagation to avoid a race
+   // with 3rd-party expunging, and that seems 
unreasonable.
+   } else if (((tmsg->flags | srec->aflags[N]) & 
~srec->dflags[N] & F_DELETED) &&
+  !(srec->status & (S_EXPIRE|S_EXPIRED))) {
+   // The paired message is being deleted.
} else {
alive++;
}
@@ -1678,7 +1683,6 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
if (!(srec = tmsg->srec) || !srec->uid[F]) {
/* We did not push the message, so it must be 
kept. */
debug( "  message %u unpropagated\n", tmsg->uid 
);
-   todel--;
} else {
nflags = (tmsg->flags | srec->aflags[N]) & 
~srec->dflags[N];
if (!(nflags & F_DELETED) || (srec->status & 
(S_EXPIRE|S_EXPIRED))) {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: make some narrowing of integers explicit

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit cc176df2c3b46d2becb6dd7c8ccc441471c468cb
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 22:10:21 2019 +0200

make some narrowing of integers explicit

this does specifically *not* cover about a bazillion warnings about
size_t being shrunk to uint - these make no sense given the expected
data set size.

 src/drv_imap.c| 2 +-
 src/drv_maildir.c | 2 +-
 src/sync.c| 6 +++---
 src/util.c| 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index ee2d1a8..90d1b95 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2377,7 +2377,7 @@ imap_open_store_ssl_bail( imap_store_t *ctx )
 static void
 imap_open_store_bail( imap_store_t *ctx, int failed )
 {
-   ((imap_store_conf_t *)ctx->gen.conf)->server->failed = failed;
+   ((imap_store_conf_t *)ctx->gen.conf)->server->failed = (char)failed;
ctx->callbacks.imap_open( DRV_STORE_BAD, ctx->callback_aux );
 }
 
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index bb98d3f..d8179de 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1017,7 +1017,7 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t 
*msglist )
entry->base = nfstrdup( e->d_name );
entry->msgid = 0;
entry->uid = uid;
-   entry->recent = i;
+   entry->recent = (uchar)i;
entry->size = 0;
entry->tuid[0] = 0;
}
diff --git a/src/sync.c b/src/sync.c
index 0d62bb8..c34c7c2 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -957,11 +957,11 @@ load_state( sync_vars_t *svars )
break;
case '*':
debug( "flags now %u\n", t3 );
-   srec->flags = t3;
+   srec->flags = (uchar)t3;
break;
case '~':
debug( "status now %#x\n", t3 );
-   srec->status = t3;
+   srec->status = (uchar)t3;
break;
default:
error( "Error: unrecognized 
journal entry at %s:%d\n", svars->jname, line );
@@ -1895,7 +1895,7 @@ msgs_copied( sync_vars_t *svars, int t )
}
for (uint i = 0; i < TUIDL; i++) {
uchar c = arc4_getbyte() & 0x3f;
-   srec->tuid[i] = c < 26 ? c + 'A' : c < 
52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/';
+   srec->tuid[i] = (char)(c < 26 ? c + 'A' 
: c < 52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/');
}
jFprintf( svars, "# %u %u %." stringify(TUIDL) 
"s\n", srec->uid[M], srec->uid[S], srec->tuid );
debug( "%sing message %u, TUID %." 
stringify(TUIDL) "s\n", str_hl[t], tmsg->uid, srec->tuid );
diff --git a/src/util.c b/src/util.c
index fc8c8df..09ac55f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -592,7 +592,7 @@ arc4_init( void )
close( fd );
 
for (i = 0; i < 256; i++)
-   rs.s[i] = i;
+   rs.s[i] = (uchar)i;
for (i = j = 0; i < 256; i++) {
si = rs.s[i];
j += si + dat[i & 127];


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: don't forget to skip dead messages on far side during expiration

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit ca72383fe947d70950ddfe110d033a158ac9a183
Author: Oswald Buddenhagen 
Date:   Thu Jul 16 13:08:29 2020 +0200

don't forget to skip dead messages on far side during expiration

this is mostly theoretical, as at this point no updates to the message
list can have actually happened. but it's future-proof and consistent
with the near-side loop.

 src/sync.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/src/sync.c b/src/sync.c
index fc7cec6..c67ba12 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1671,6 +1671,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
}
}
for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
+   if (tmsg->status & M_DEAD)
+   continue;
if ((srec = tmsg->srec) && (srec->status & S_PENDING) 
&& !(tmsg->flags & F_DELETED))
alive++;
}
@@ -1705,6 +1707,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
}
}
for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
+   if (tmsg->status & M_DEAD)
+   continue;
if ((srec = tmsg->srec) && (srec->status & S_PENDING)) {
nflags = tmsg->flags;
if (!(nflags & F_DELETED)) {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-duplicate updating of uid in sync records

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit fd7b5659ab3e50782ce19f3011916949cc6628e0
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 14:41:45 2019 +0100

de-duplicate updating of uid in sync records

 src/sync.c | 42 --
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 166d7fb..927 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -244,6 +244,22 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
 #define JLOG_SEL(_1, _2, _3, _4, x, ...) x
 #define JLOG(...) JLOG_SEL(__VA_ARGS__, JLOG4, JLOG3, NO_JLOG2, 
NO_JLOG1)(__VA_ARGS__)
 
+static void
+assign_uid( sync_vars_t *svars, sync_rec_t *srec, int t, uint uid )
+{
+   srec->uid[t] = uid;
+   if (uid == svars->maxuid[t] + 1)
+   svars->maxuid[t] = uid;
+   srec->status &= ~S_PENDING;
+   srec->tuid[0] = 0;
+}
+
+#define ASSIGN_UID(srec, t, nuid, ...) \
+   do { \
+   JLOG( "%c %u %u %u", ("<>"[t], srec->uid[F], srec->uid[N], 
nuid), __VA_ARGS__ ); \
+   assign_uid( svars, srec, t, nuid ); \
+   } while (0)
+
 static void
 match_tuids( sync_vars_t *svars, int t, message_t *msgs )
 {
@@ -279,15 +295,10 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
num_lost++;
continue;
  mfound:
-   JLOG( "%c %u %u %u", ("<>"[t], srec->uid[F], 
srec->uid[N], tmsg->uid), "TUID matched %s", diag );
tmsg->srec = srec;
srec->msg[t] = tmsg;
ntmsg = tmsg->next;
-   srec->uid[t] = tmsg->uid;
-   if (tmsg->uid == svars->maxuid[t] + 1)
-   svars->maxuid[t] = tmsg->uid;
-   srec->status = 0;
-   srec->tuid[0] = 0;
+   ASSIGN_UID( srec, t, tmsg->uid, "TUID matched %s", diag 
);
}
}
if (num_lost)
@@ -944,19 +955,11 @@ load_state( sync_vars_t *svars )
break;
case '<':
debug( "far side now %u\n", t3 
);
-   srec->uid[F] = t3;
-   if (t3 == svars->maxuid[F] + 1)
-   svars->maxuid[F] = t3;
-   srec->status &= ~S_PENDING;
-   srec->tuid[0] = 0;
+   assign_uid( svars, srec, F, t3 
);
break;
case '>':
debug( "near side now %u\n", t3 
);
-   srec->uid[N] = t3;
-   if (t3 == svars->maxuid[N] + 1)
-   svars->maxuid[N] = t3;
-   srec->status &= ~S_PENDING;
-   srec->tuid[0] = 0;
+   assign_uid( svars, srec, N, t3 
);
break;
case '*':
debug( "flags now %u\n", t3 );
@@ -1851,12 +1854,7 @@ msg_copied( int sts, uint uid, copy_vars_t *vars )
if (!uid) {  // Stored to a non-UIDPLUS mailbox
svars->state[t] |= ST_FIND_NEW;
} else {
-   JLOG( "%c %u %u %u", ("<>"[t], srec->uid[F], 
srec->uid[N], uid), "%sed message", str_hl[t] );
-   vars->srec->uid[t] = uid;
-   if (uid == svars->maxuid[t] + 1)
-   svars->maxuid[t] = uid;
-   vars->srec->status &= ~S_PENDING;
-   vars->srec->tuid[0] = 0;
+   ASSIGN_UID( srec, t, uid, "%sed message", str_hl[t] );
}
break;
case SYNC_NOGOOD:


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: make expiration loops solely far-side-driven

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit de6dc699c91e18bd3705fd253141e9ca1fb8ebcf
Author: Oswald Buddenhagen 
Date:   Thu Jul 16 14:47:30 2020 +0200

make expiration loops solely far-side-driven

we can do that, as unpaired near-side messages are ignored anyway.

this mildly changes expiration order, as near-side messages that
existed for a long time but were propagated much later will be expired
later. however, that has no practical relevance.

 src/sync.c | 96 --
 1 file changed, 42 insertions(+), 54 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index c67ba12..18a381b 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1653,74 +1653,62 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
/* Expire excess messages. Important (flagged, unread, or 
unpropagated) messages
 * older than the first not expired message are not counted 
towards the total. */
debug( "preparing message expiration\n" );
+   // Due to looping only over the far side, we completely ignore 
unpaired
+   // near-side messages. This is correct, as we cannot expire 
them without
+   // data loss anyway; consequently, we also don't count them.
+   // Note that we also ignore near-side messages we're currently 
propagating,
+   // which delays expiration of some messages by one cycle. 
Otherwise, we'd have
+   // to sequence flag propagation after message propagation to 
avoid a race
+   // with 3rd-party expunging, and that seems unreasonably 
expensive.
alive = 0;
-   for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) {
+   for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD)
continue;
-   if (!(srec = tmsg->srec) || !srec->uid[F]) {
-   // The message was not propagated, so it 
doesn't count towards the total.
-   // Note that we also ignore messages we're 
currently propagating, which
-   // delays expiry of some messages by one cycle. 
Otherwise, we'd have to
-   // sequence flag propagation after message 
propagation to avoid a race
-   // with 3rd-party expunging, and that seems 
unreasonable.
-   } else if (((tmsg->flags | srec->aflags[N]) & 
~srec->dflags[N] & F_DELETED) &&
-  !(srec->status & (S_EXPIRE|S_EXPIRED))) {
-   // The paired message is being deleted.
+   // We ignore unpaired far-side messages, as there is 
obviously nothing
+   // to expire in the first place.
+   if (!(srec = tmsg->srec))
+   continue;
+   if (!(srec->status & S_PENDING)) {
+   if (!srec->msg[N])
+   continue;  // Already expired or 
skipped.
+   nflags = (srec->msg[N]->flags | 
srec->aflags[N]) & ~srec->dflags[N];
} else {
-   alive++;
+   nflags = tmsg->flags;
}
-   }
-   for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
-   if (tmsg->status & M_DEAD)
-   continue;
-   if ((srec = tmsg->srec) && (srec->status & S_PENDING) 
&& !(tmsg->flags & F_DELETED))
+   if (!(nflags & F_DELETED) || (srec->status & 
(S_EXPIRE|S_EXPIRED)))
+   // The message is not deleted, or it is, but 
only due to being expired.
alive++;
}
todel = alive - svars->chan->max_messages;
debug( "%d alive messages, %d excess - expiring\n", alive, 
todel );
alive = 0;
-   for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) {
-   if (tmsg->status & M_DEAD)
-   continue;
-   if (!(srec = tmsg->srec) || !srec->uid[F]) {
-   /* We did not push the message, so it must be 
kept. */
-   debug( "  message %u unpropagated\n", tmsg->uid 
);
-   } else {
-   nflags = (tmsg->flags | srec->aflags[N]) & 
~srec->dflags[N];
-   if (!(nflags & F_DELETED) || (srec->status & 
(S_EXPIRE|S_EXPIRED))) {
-   /* The message is not deleted, or is 
already (being) expired. */
-   if ((nflags & F_FLAGGED) || !((nflags & 
F_SEEN) || 

[commit] master: Add support for specifying cipher string used for ssl connection

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 07cb422cbb552744ac7cd13507fa4933de98ab15
Author: Jaroslav Suchanek 
AuthorDate: Sat Nov 9 19:47:55 2019 +0100
Commit: Oswald Buddenhagen 
CommitDate: Tue Aug 4 14:49:58 2020 +0200

Add support for specifying cipher string used for ssl connection

Some distributions (e.g. Fedora) added support for system wide crypto
policies. This is supported in most common crypto libraries including
OpenSSL. Applications can override this policy using their own cipher
string. This commit adds support for specifying the cipher string in
the mbsync configuration.

For example, to exclude Diffie-Hellman, the user can specify
  CipherString "DEFAULT:!DH"
in the IMAP Account's configuration.

 NEWS   | 2 ++
 src/drv_imap.c | 2 ++
 src/mbsync.1   | 7 +++
 src/socket.c   | 5 +
 src/socket.h   | 1 +
 5 files changed, 17 insertions(+)

diff --git a/NEWS b/NEWS
index ef795a8..18e4f13 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ The 'isync' compatibility wrapper was removed.
 
 The IMAP '$Forwarded' / Maildir 'P' (passed) flag is supported now.
 
+Support for configuring a TLS cipher string was added.
+
 [1.3.0]
 
 Network timeout handling has been added.
diff --git a/src/drv_imap.c b/src/drv_imap.c
index e2d5fce..b6f7278 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3295,6 +3295,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
   cfg->file, cfg->line, 
server->sconf.client_keyfile );
cfg->err = 1;
}
+   } else if (!strcasecmp( "CipherString", cfg->cmd )) {
+   server->sconf.cipher_string = nfstrdup( cfg->val );
} else if (!strcasecmp( "SSLType", cfg->cmd )) {
if (!strcasecmp( "None", cfg->val )) {
server->ssl_type = SSL_None;
diff --git a/src/mbsync.1 b/src/mbsync.1
index c8c8736..325385f 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -414,6 +414,13 @@ so it is unlikely that you need this option.
 File containing the private key corresponding to \fBClientCertificate\fR.
 .
 .TP
+\fBCipherString\fR \fIstring\fR
+Specify OpenSSL cipher string for connections secured with TLS up to
+version 1.2 (but not 1.3 and above).
+The format is described in \fBciphers\fR\|(1).
+(Default: empty, which implies system wide policy).
+.
+.TP
 \fBPipelineDepth\fR \fIdepth\fR
 Maximum number of IMAP commands which can be simultaneously in flight.
 Setting this to \fI1\fR disables pipelining.
diff --git a/src/socket.c b/src/socket.c
index 4034d9d..feb6511 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -263,6 +263,11 @@ init_ssl_ctx( const server_conf_t *conf )
 
SSL_CTX_set_options( mconf->SSLContext, options );
 
+   if (conf->cipher_string && !SSL_CTX_set_cipher_list( mconf->SSLContext, 
conf->cipher_string )) {
+   print_ssl_errors( "setting cipher string '%s'", 
conf->cipher_string );
+   return 0;
+   }
+
if (conf->cert_file && !SSL_CTX_load_verify_locations( 
mconf->SSLContext, conf->cert_file, 0 )) {
print_ssl_errors( "loading certificate file '%s'", 
conf->cert_file );
return 0;
diff --git a/src/socket.h b/src/socket.h
index d760c56..f8f25b1 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -49,6 +49,7 @@ typedef struct {
char *cert_file;
char *client_certfile;
char *client_keyfile;
+   char *cipher_string;
char system_certs;
char ssl_versions;
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: don't store 'shared' and 'other' namespaces

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 6fd4e8de24a2f8f520bde43a3d0fd0f5f4f1f3cc
Author: Oswald Buddenhagen 
Date:   Sun Nov 10 17:13:41 2019 +0100

don't store 'shared' and 'other' namespaces

they are never used anyway, and aren't going to be (because configuring
that would be more annoying than just specifying Path manually).

 src/drv_imap.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index e33b588..c4fa03a 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -108,7 +108,7 @@ struct imap_store {
uint got_namespace:1;
uint has_forwarded:1;
char delimiter[2]; /* hierarchy delimiter */
-   list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
+   list_t *ns_personal; /* NAMESPACE info */
string_list_t *boxes; // _list results
char listed; // was _list already run with these flags?
// note that the message counts do _not_ reflect stats from msgs,
@@ -936,16 +936,14 @@ parse_namespace_rsp( imap_store_t *ctx, list_t *list, 
char *s )
 static int
 parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
 {
-   if (parse_namespace_check( (ctx->ns_other = list) ))
-   return LIST_BAD;
+   free_list( list );
return parse_list( ctx, s, parse_namespace_rsp_p3 );
 }
 
 static int
-parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
+parse_namespace_rsp_p3( imap_store_t *ctx ATTR_UNUSED, list_t *list, char *s 
ATTR_UNUSED )
 {
-   if (parse_namespace_check( (ctx->ns_shared = list) ))
-   return LIST_BAD;
+   free_list( list );
return LIST_OK;
 }
 
@@ -1611,8 +1609,6 @@ imap_cancel_store( store_t *gctx )
cancel_sent_imap_cmds( ctx );
cancel_pending_imap_cmds( ctx );
free_list( ctx->ns_personal );
-   free_list( ctx->ns_other );
-   free_list( ctx->ns_shared );
free_string_list( ctx->auth_mechs );
free_generic_messages( ctx->msgs );
free_string_list( ctx->boxes );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: IMAP: reject unqualified non-uppercased INBOX spellings

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit e9407cc1f724315daa47d617a0ebbd36a2415129
Author: Oswald Buddenhagen 
Date:   Thu Jun 2 19:41:03 2011 +0200

IMAP: reject unqualified non-uppercased INBOX spellings

otherwise the server would interpret it as INBOX contrary to our
expectations, which might lead to moderately surprising effects.

if you really want to sync your ~/maildir/inbox to the IMAP INBOX,
specify it as the Maildir Store's Inbox.

 src/drv_imap.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index b6f7278..5563ff4 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1350,9 +1350,17 @@ static int
 prepare_box( char **buf, const imap_store_t *ctx )
 {
const char *name = ctx->name;
+   const char *pfx = ctx->prefix;
 
-   return prepare_name( buf, ctx,
-   (starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] == 
'/')) ? "" : ctx->prefix, name );
+   if (starts_with_upper( name, -1, "INBOX", 5 ) && (!name[5] || name[5] 
== '/')) {
+   if (!memcmp( name, "INBOX", 5 )) {
+   pfx = "";
+   } else if (!*pfx) {
+   error( "IMAP error: cannot use unqualified '%s'. Did 
you mean INBOX?", name );
+   return -1;
+   }
+   }
+   return prepare_name( buf, ctx, pfx, name );
 }
 
 static int


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: add ability to script IMAP user query

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 03b15dbdd341375e2f3350bdfe0d957b64c4edde
Author: Oswald Buddenhagen 
Date:   Tue Nov 26 12:17:33 2019 +0100

add ability to script IMAP user query

It was already possible to retrieve passwords from arbitrary commands.
But this goes only half the way to allowing automated derivation of
login credentials, as some environments may also have different user
names based on the system. Therefore, add the UserCmd option to
complement PassCmd.

Based on a patch series by Patrick Steinhardt 

 NEWS   |   2 +
 src/drv_imap.c | 126 +
 src/mbsync.1   |   9 
 3 files changed, 87 insertions(+), 50 deletions(-)

diff --git a/NEWS b/NEWS
index 761337e..41934a5 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ Support for configuring a TLS cipher string was added.
 
 IMAP mailbox subscriptions are supported now.
 
+The IMAP user query can be scripted now.
+
 [1.3.0]
 
 Network timeout handling has been added.
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 92008b7..3980044 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -50,6 +50,7 @@ typedef struct imap_server_conf {
char *name;
server_conf_t sconf;
char *user;
+   char *user_cmd;
char *pass;
char *pass_cmd;
int max_in_progress;
@@ -1936,12 +1937,50 @@ imap_open_store_authenticate_p3( imap_store_t *ctx, 
imap_cmd_t *cmd ATTR_UNUSED,
 }
 #endif
 
+static char *
+cred_from_cmd( const char *cred, const char *cmd, const char *srv_name )
+{
+   FILE *fp;
+   int ret;
+   char buffer[8192];  // Hopefully more than enough room for XOAUTH2, 
etc. tokens
+
+   if (*cmd == '+') {
+   flushn();
+   cmd++;
+   }
+   if (!(fp = popen( cmd, "r" ))) {
+ pipeerr:
+   sys_error( "Skipping account %s, %s failed", srv_name, cred );
+   return NULL;
+   }
+   if (!fgets( buffer, sizeof(buffer), fp ))
+   buffer[0] = 0;
+   if ((ret = pclose( fp )) < 0)
+   goto pipeerr;
+   if (ret) {
+   if (WIFSIGNALED( ret ))
+   error( "Skipping account %s, %s crashed\n", srv_name, 
cred );
+   else
+   error( "Skipping account %s, %s exited with status 
%d\n", srv_name, cred, WEXITSTATUS( ret ) );
+   return NULL;
+   }
+   if (!buffer[0]) {
+   error( "Skipping account %s, %s produced no output\n", 
srv_name, cred );
+   return NULL;
+   }
+   buffer[strcspn( buffer, "\n" )] = 0; /* Strip trailing newline */
+   return nfstrdup( buffer );
+}
+
 static const char *
 ensure_user( imap_server_conf_t *srvc )
 {
if (!srvc->user) {
-   error( "Skipping account %s, no user\n", srvc->name );
-   return NULL;
+   if (srvc->user_cmd) {
+   srvc->user = cred_from_cmd( "UserCmd", srvc->user_cmd, 
srvc->name );
+   } else {
+   error( "Skipping account %s, no user\n", srvc->name );
+   }
}
return srvc->user;
 }
@@ -1949,56 +1988,25 @@ ensure_user( imap_server_conf_t *srvc )
 static const char *
 ensure_password( imap_server_conf_t *srvc )
 {
-   char *cmd = srvc->pass_cmd;
-
-   if (cmd) {
-   FILE *fp;
-   int ret;
-   char buffer[8192];  // Hopefully more than enough room for 
XOAUTH2, etc. tokens
-
-   if (*cmd == '+') {
+   if (!srvc->pass) {
+   if (srvc->pass_cmd) {
+   srvc->pass = cred_from_cmd( "PassCmd", srvc->pass_cmd, 
srvc->name );
+   } else {
flushn();
-   cmd++;
-   }
-   if (!(fp = popen( cmd, "r" ))) {
- pipeerr:
-   sys_error( "Skipping account %s, password command 
failed", srvc->name );
-   return NULL;
-   }
-   if (!fgets( buffer, sizeof(buffer), fp ))
-   buffer[0] = 0;
-   if ((ret = pclose( fp )) < 0)
-   goto pipeerr;
-   if (ret) {
-   if (WIFSIGNALED( ret ))
-   error( "Skipping account %s, password command 
crashed\n", srvc->name );
-   else
-   error( "Skipping account %s, password command 
exited with status %d\n", srvc->name, WEXITSTATUS( ret ) );
-   return NULL;
-   }
-   if (!buffer[0]) {
-   error( "Skipping account %s, password command produced 
no output\n", srvc->name );
-   return NULL;
-   }
-   buffer[strcspn( buffer, "\n" )] = 0; /* Strip trailing newline 
*/
-   free( srvc->pass ); /* From previous runs */
-   srvc->pass = 

[commit] master: rewrite nonsensical struct packing magic

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 6010fe104ef2a3e91335fdb7e686939d6af82a46
Author: Oswald Buddenhagen 
Date:   Fri Nov 15 20:20:45 2019 +0100

rewrite nonsensical struct packing magic

this couldn't have possibly worked - the alignment also determines the
sizeof, thus defeating the intent of the packing.

 src/common.h | 24 +---
 src/util.c   |  3 ++-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/common.h b/src/common.h
index c834cb1..c00495f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -47,12 +47,10 @@ typedef unsigned long ulong;
 # define ATTR_UNUSED __attribute__((unused))
 # define ATTR_NORETURN __attribute__((noreturn))
 # define ATTR_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
-# define ATTR_PACKED(ref) __attribute__((packed,aligned(sizeof(ref
 #else
 # define ATTR_UNUSED
 # define ATTR_NORETURN
 # define ATTR_PRINTFLIKE(fmt,var)
-# define ATTR_PACKED(ref)
 #endif
 
 #if defined(__clang__)
@@ -137,7 +135,7 @@ void flushn( void );
 typedef struct string_list {
struct string_list *next;
char string[1];
-} ATTR_PACKED(void *) string_list_t;
+} string_list_t;
 
 void add_string_list_n( string_list_t **list, const char *str, uint len );
 void add_string_list( string_list_t **list, const char *str );
@@ -176,22 +174,26 @@ int map_name( const char *arg, char **result, uint 
reserve, const char *in, cons
typedef struct { \
T *data; \
uint size; \
-   } ATTR_PACKED(T *) T##_array_t; \
-   typedef struct { \
+   } T##_array_t; \
+   typedef union { \
T##_array_t array; \
-   uint alloc; \
-   } ATTR_PACKED(T *) T##_array_alloc_t; \
+   struct { \
+   T *dummy_data; \
+   uint dummy_size; \
+   uint alloc; \
+   } extra; \
+   } T##_array_alloc_t; \
static INLINE T *T##_array_append( T##_array_alloc_t *arr ) \
{ \
-   if (arr->array.size == arr->alloc) { \
-   arr->alloc = arr->alloc * 2 + 100; \
-   arr->array.data = nfrealloc( arr->array.data, 
arr->alloc * sizeof(T) ); \
+   if (arr->array.size == arr->extra.alloc) { \
+   arr->extra.alloc = arr->extra.alloc * 2 + 100; \
+   arr->array.data = nfrealloc( arr->array.data, 
arr->extra.alloc * sizeof(T) ); \
} \
return >array.data[arr->array.size++]; \
}
 
 #define ARRAY_INIT(arr) \
-   do { (arr)->array.data = NULL; (arr)->array.size = (arr)->alloc = 0; } 
while (0)
+   do { (arr)->array.data = NULL; (arr)->array.size = (arr)->extra.alloc = 
0; } while (0)
 
 #define ARRAY_SQUEEZE(arr) \
do { \
diff --git a/src/util.c b/src/util.c
index 08443de..c6c597c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -23,6 +23,7 @@
 #include "common.h"
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -174,7 +175,7 @@ add_string_list_n( string_list_t **list, const char *str, 
uint len )
 {
string_list_t *elem;
 
-   elem = nfmalloc( sizeof(*elem) + len );
+   elem = nfmalloc( offsetof(string_list_t, string) + len + 1 );
elem->next = *list;
*list = elem;
memcpy( elem->string, str, len );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-duplicate FETCH response data item traversal somewhat

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 503478533ce4221c88c9614d515479d78837c595
Author: Oswald Buddenhagen 
Date:   Fri Nov 22 17:50:01 2019 +0100

de-duplicate FETCH response data item traversal somewhat

 src/drv_imap.c | 20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 826e12b..92008b7 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1060,15 +1060,15 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
error( "IMAP error: bogus item name in FETCH 
response\n" );
goto ffail;
}
-   if (!strcmp( "UID", tmp->val )) {
-   tmp = tmp->next;
+   const char *name = tmp->val;
+   tmp = tmp->next;
+   if (!strcmp( "UID", name )) {
if (!is_atom( tmp ) || (uid = strtoul( tmp->val, , 
10 ), *ep)) {
error( "IMAP error: unable to parse UID\n" );
goto ffail;
}
continue;  // This *is* the UID.
-   } else if (!strcmp( "FLAGS", tmp->val )) {
-   tmp = tmp->next;
+   } else if (!strcmp( "FLAGS", name )) {
if (!is_list( tmp )) {
error( "IMAP error: unable to parse FLAGS\n" );
goto ffail;
@@ -1076,8 +1076,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
if (!parse_fetched_flags( tmp->child, ,  ))
goto ffail;
continue;  // This may legitimately come without UID.
-   } else if (!strcmp( "INTERNALDATE", tmp->val )) {
-   tmp = tmp->next;
+   } else if (!strcmp( "INTERNALDATE", name )) {
if (!is_atom( tmp )) {
error( "IMAP error: unable to parse 
INTERNALDATE\n" );
goto ffail;
@@ -1086,21 +1085,18 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
error( "IMAP error: unable to parse 
INTERNALDATE format\n" );
goto ffail;
}
-   } else if (!strcmp( "RFC822.SIZE", tmp->val )) {
-   tmp = tmp->next;
+   } else if (!strcmp( "RFC822.SIZE", name )) {
if (!is_atom( tmp ) || (size = strtoul( tmp->val, , 
10 ), *ep)) {
error( "IMAP error: unable to parse 
RFC822.SIZE\n" );
goto ffail;
}
-   } else if (!strcmp( "BODY[]", tmp->val )) {
-   tmp = tmp->next;
+   } else if (!strcmp( "BODY[]", name )) {
if (!is_atom( tmp )) {
error( "IMAP error: unable to parse BODY[]\n" );
goto ffail;
}
body = tmp;
-   } else if (!strcmp( "BODY[HEADER.FIELDS", tmp->val )) {
-   tmp = tmp->next;
+   } else if (!strcmp( "BODY[HEADER.FIELDS", name )) {
if (!is_list( tmp )) {
  bfail:
error( "IMAP error: unable to parse 
BODY[HEADER.FIELDS ...]\n" );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: add support for (disabling) TLS v1.3

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit d09f988c70e6598a7deb8de5a5c6496c32ab88d9
Author: Oswald Buddenhagen 
Date:   Tue Nov 26 16:05:46 2019 +0100

add support for (disabling) TLS v1.3

this is actually potentially counterproductive, as people who have set
SSLVersions and fail to adjust it will _lose_ tls 1.3 support. however,
without the option being there, people (incorrectly) believe that tls
1.3 is not supported.

 NEWS   |  2 ++
 src/drv_imap.c | 15 ++-
 src/mbsync.1   |  4 ++--
 src/socket.c   |  4 
 src/socket.h   |  3 ++-
 5 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index d1a27aa..d7a79a8 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@
 
 The 'isync' compatibility wrapper was removed.
 
+Added support for disabling TLS v1.3 - adjust SSLVersions if you set it.
+
 The IMAP '$Forwarded' / Maildir 'P' (passed) flag is supported now.
 
 Support for configuring a TLS cipher string was added.
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 7d271bd..5285f64 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3194,7 +3194,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 #ifdef HAVE_LIBSSL
/* Legacy SSL options */
int require_ssl = -1, use_imaps = -1;
-   int use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1;
+   int use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1, 
use_tlsv13 = -1;
 #endif
/* Legacy SASL option */
int require_cram = -1;
@@ -3234,7 +3234,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
arg += 6;
server->ssl_type = SSL_IMAPS;
if (server->sconf.ssl_versions == -1)
-   server->sconf.ssl_versions = SSLv3 | 
TLSv1 | TLSv1_1 | TLSv1_2;
+   server->sconf.ssl_versions = SSLv3 | 
TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3;
} else
 #endif
if (starts_with( arg, -1, "imap:", 5 ))
@@ -,6 +,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
server->sconf.ssl_versions |= TLSv1_1;
} else if (!strcasecmp( "TLSv1.2", arg )) {
server->sconf.ssl_versions |= TLSv1_2;
+   } else if (!strcasecmp( "TLSv1.3", arg )) {
+   server->sconf.ssl_versions |= TLSv1_3;
} else {
error( "%s:%d: Unrecognized SSL 
version\n", cfg->file, cfg->line );
cfg->err = 1;
@@ -3352,6 +3354,8 @@ 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 );
+   else if (!strcasecmp( "UseTLSv1.3", cfg->cmd ))
+   use_tlsv13 = parse_bool( cfg );
 #endif
else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
 !strcasecmp( "AuthMechs", cfg->cmd )) {
@@ -3412,7 +3416,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
return 1;
}
 #ifdef HAVE_LIBSSL
-   if ((use_sslv3 & use_tlsv1 & use_tlsv11 & use_tlsv12) != -1 || 
use_imaps >= 0 || require_ssl >= 0) {
+   if ((use_sslv3 & use_tlsv1 & use_tlsv11 & use_tlsv12 & 
use_tlsv13) != -1 || use_imaps >= 0 || require_ssl >= 0) {
if (server->ssl_type >= 0 || server->sconf.ssl_versions 
>= 0) {
error( "%s '%s': The deprecated UseSSL*, 
UseTLS*, UseIMAPS, and RequireSSL options are mutually exclusive with SSLType 
and SSLVersions.\n", type, name );
cfg->err = 1;
@@ -3423,7 +3427,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
(use_sslv3 != 1 ? 0 : SSLv3) |
(use_tlsv1 == 0 ? 0 : TLSv1) |
(use_tlsv11 != 1 ? 0 : TLSv1_1) |
-   (use_tlsv12 != 1 ? 0 : TLSv1_2);
+   (use_tlsv12 != 1 ? 0 : TLSv1_2) |
+   (use_tlsv13 != 1 ? 0 : TLSv1_3);
if (use_imaps == 1) {
server->ssl_type = SSL_IMAPS;
} else if (require_ssl) {
@@ -3441,7 +3446,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
}
} else {
if (server->sconf.ssl_versions < 0)
-   server->sconf.ssl_versions = TLSv1 | TLSv1_1 | 
TLSv1_2;
+   

[commit] master: fix loading of some messages' sizes in some partial sync scenarios

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 395f8025003c080203ecb8680e9d84d0d8bb2f1b
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 11:52:26 2019 +0100

fix loading of some messages' sizes in some partial sync scenarios

we need to pass a different "boundary" UID to driver_t::load_box() for
every OPEN_* flag that queries a partial range:
- OPEN_FIND refers to messages newer than all we know about
- OPEN_OLD_IDS refers to messages which are paired
- OPEN_{OLD,NEW}_SIZE refers to messages (not) above the committed
  boundary of already propagated messages

we treated the 3rd like the 2nd, which was just wrong - the actual
boundary may be lower or higher, so we'd produce wrong results when
MaxSize was set and only one of New and ReNew was requested.

 src/driver.h  | 10 +-
 src/drv_imap.c|  8 
 src/drv_maildir.c | 15 ---
 src/drv_proxy.c   |  4 ++--
 src/sync.c| 28 ++--
 5 files changed, 29 insertions(+), 36 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index 11cc9ba..b3edf88 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -206,12 +206,12 @@ struct driver {
 * Consider only messages with UIDs between minuid and maxuid 
(inclusive)
 * and those named in the excs array (smaller than minuid).
 * The driver takes ownership of the excs array.
-* Messages starting with newuid need to have the TUID populated when 
OPEN_FIND is set.
-* Messages up to seenuid need to have the Message-Id populated when 
OPEN_OLD_IDS is set.
-* Messages up to seenuid need to have the size populated when 
OPEN_OLD_SIZE is set;
-* likewise messages above seenuid when OPEN_NEW_SIZE is set.
+* Messages starting with finduid need to have the TUID populated when 
OPEN_FIND is set.
+* Messages up to pairuid need to have the Message-Id populated when 
OPEN_OLD_IDS is set.
+* Messages up to newuid need to have the size populated when 
OPEN_OLD_SIZE is set;
+* likewise messages above newuid when OPEN_NEW_SIZE is set.
 * The returned message list remains owned by the driver. */
-   void (*load_box)( store_t *ctx, uint minuid, uint maxuid, uint newuid, 
uint seenuid, uint_array_t excs,
+   void (*load_box)( store_t *ctx, uint minuid, uint maxuid, uint finduid, 
uint pairuid, uint newuid, uint_array_t excs,
  void (*cb)( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux ), void *aux );
 
/* Fetch the contents and flags of the given message from the current 
mailbox. */
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 5acbd79..d26fcf9 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2683,7 +2683,7 @@ static void imap_submit_load( imap_store_t *, const char 
*, int, imap_load_box_s
 static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t * );
 
 static void
-imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint 
seenuid, uint_array_t excs,
+imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint finduid, uint 
pairuid, uint newuid, uint_array_t excs,
void (*cb)( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux ), void *aux )
 {
imap_store_t *ctx = (imap_store_t *)gctx;
@@ -2716,11 +2716,11 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, 
uint newuid, uint seenui
uint nranges = 1;
if (ctx->opts & (OPEN_OLD_SIZE | OPEN_NEW_SIZE))
imap_set_range( ranges, , shifted_bit( 
ctx->opts, OPEN_OLD_SIZE, WantSize),
- shifted_bit( 
ctx->opts, OPEN_NEW_SIZE, WantSize), seenuid );
+ shifted_bit( 
ctx->opts, OPEN_NEW_SIZE, WantSize), newuid );
if (ctx->opts & OPEN_FIND)
-   imap_set_range( ranges, , 0, WantTuids, 
newuid - 1 );
+   imap_set_range( ranges, , 0, WantTuids, 
finduid - 1 );
if (ctx->opts & OPEN_OLD_IDS)
-   imap_set_range( ranges, , WantMsgids, 
0, seenuid );
+   imap_set_range( ranges, , WantMsgids, 
0, pairuid );
for (uint r = 0; r < nranges; r++) {
sprintf( buf, "%u:%u", ranges[r].first, 
ranges[r].last );
imap_submit_load( ctx, buf, ranges[r].flags, 
sts );
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index b1c9026..f1ff2fc 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -70,7 +70,7 @@ typedef struct {
 typedef struct {
store_t gen;
int uvfd, uvok, is_inbox, fresh[3];
-   uint opts, minuid, maxuid, newuid, seenuid, uidvalidity, nuid;
+   uint opts, minuid, maxuid, finduid, pairuid, newuid, uidvalidity, nuid;

[commit] master: handle bogus IMAP FETCH responses more robustly

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 67ea5bea7f84a9a58e05a4f28d787ff3322a3029
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 17:24:38 2019 +0100

handle bogus IMAP FETCH responses more robustly

don't use assert()s when the error condition can stem not only from
errors in mbsync's logic, but also from the IMAP stream being corrupted.

amends 72be55b0e.

REFMAIL: 20191021233411.55ctuvslkfqf2pna@koblih.localdomain

 src/drv_imap.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4d3a038..48bf6ec 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -974,7 +974,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
msg_data_t *msgdata;
imap_cmd_t *cmdp;
uchar mask = 0, status = 0;
-   uint i, uid = 0, size = 0;
+   uint i, uid = 0, need_uid = 0, size = 0;
time_t date = 0;
 
if (!is_list( list )) {
@@ -990,6 +990,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
error( "IMAP error: unable to parse 
UID\n" );
goto ffail;
}
+   continue;  // This *is* the UID.
} else if (!strcmp( "FLAGS", tmp->val )) {
tmp = tmp->next;
if (is_list( tmp )) {
@@ -1018,6 +1019,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
}
}
status |= M_FLAGS;
+   continue;  // This may legitimately 
come without UID.
} else {
error( "IMAP error: unable to parse 
FLAGS\n" );
goto ffail;
@@ -1099,17 +1101,27 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
}
}
}
+   need_uid = 1;
}
 
if (!uid) {
-   assert( !body && !tuid && !msgid );
+   if (need_uid) {
+   error( "IMAP error: received payload without UID\n" );
+   goto ffail;
+   }
// Ignore async flag updates for now.
} else if ((cmdp = ctx->in_progress) && cmdp->param.lastuid) {
-   assert( !body && !tuid && !msgid );
+   if (need_uid || (status & M_FLAGS)) {
+   error( "IMAP error: received extraneous data in 
response to UID query\n" );
+   goto ffail;
+   }
// Workaround for server not sending UIDNEXT and/or APPENDUID.
ctx->uidnext = uid + 1;
} else if (body) {
-   assert( !tuid && !msgid );
+   if (tuid || msgid) {  // Only those that leak; ignore others.
+   error( "IMAP error: received extraneous data with full 
message\n" );
+   goto ffail;
+   }
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
if (cmdp->param.uid == uid)
goto gotuid;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: turn maildir_again() into a proper varargs function

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit df22514ced8e6a62e6456496b645609af0b07930
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 16:54:28 2020 +0200

turn maildir_again() into a proper varargs function

this is mostly to work around the fact that both gcc and clang won't
accept the format string declaration (i.e., will complain with
-Wformat-nonliteral) if the *called* function does not actually take a
va_list.

on the upside, it makes one caller cleaner. yay ...

 src/common.h  |  1 +
 src/drv_maildir.c | 12 +++-
 src/util.c| 15 +++
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/common.h b/src/common.h
index a04e9f9..b15cc15 100644
--- a/src/common.h
+++ b/src/common.h
@@ -130,6 +130,7 @@ void ATTR_PRINTFLIKE(1, 2) progress( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) notice( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) warn( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) error( const char *, ... );
+void ATTR_PRINTFLIKE(1, 0) vsys_error( const char *, va_list va );
 void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... );
 void flushn( void );
 
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 984e36c..777280d 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1510,14 +1510,16 @@ maildir_rescan( maildir_store_t *ctx )
return DRV_OK;
 }
 
-static int
-maildir_again( maildir_store_t *ctx, maildir_message_t *msg,
-   const char *err, const char *fn, const char *fn2 )
+static int ATTR_PRINTFLIKE(3, 0)
+maildir_again( maildir_store_t *ctx, maildir_message_t *msg, const char *err, 
... )
 {
int ret;
 
if (errno != ENOENT) {
-   sys_error( err, fn, fn2 );
+   va_list va;
+   va_start( va, err );
+   vsys_error( err, va );
+   va_end( va );
return DRV_BOX_BAD;
}
if ((ret = maildir_rescan( ctx )) != DRV_OK)
@@ -1539,7 +1541,7 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, 
msg_data_t *data,
nfsnprintf( buf, sizeof(buf), "%s/%s/%s", ctx->path, 
subdirs[gmsg->status & M_RECENT], msg->base );
if ((fd = open( buf, O_RDONLY )) >= 0)
break;
-   if ((ret = maildir_again( ctx, msg, "Cannot open %s", buf, 0 )) 
!= DRV_OK) {
+   if ((ret = maildir_again( ctx, msg, "Cannot open %s", buf )) != 
DRV_OK) {
cb( ret, aux );
return;
}
diff --git a/src/util.c b/src/util.c
index 93e6e7e..d506273 100644
--- a/src/util.c
+++ b/src/util.c
@@ -149,19 +149,26 @@ error( const char *msg, ... )
 }
 
 void
-sys_error( const char *msg, ... )
+vsys_error( const char *msg, va_list va )
 {
-   va_list va;
char buf[1024];
 
flushn();
-   va_start( va, msg );
if ((uint)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf))
oob();
-   va_end( va );
perror( buf );
 }
 
+void
+sys_error( const char *msg, ... )
+{
+   va_list va;
+
+   va_start( va, msg );
+   vsys_error( msg, va );
+   va_end( va );
+}
+
 void
 add_string_list_n( string_list_t **list, const char *str, int len )
 {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: extract parse_fetched_flags() from parse_fetch_rsp()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 81c4bfeefad7a62947ae29359bcb07924a6154d1
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 16:32:32 2019 +0100

extract parse_fetched_flags() from parse_fetch_rsp()

 src/drv_imap.c | 62 --
 1 file changed, 35 insertions(+), 27 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 6832d5d..a22c0fd 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -965,6 +965,37 @@ parse_date( const char *str )
return date - (hours * 60 + mins) * 60;
 }
 
+static int
+parse_fetched_flags( list_t *list, uchar *flags, uchar *status )
+{
+   for (; list; list = list->next) {
+   if (!is_atom( list )) {
+   error( "IMAP error: unable to parse FLAGS list\n" );
+   return 0;
+   }
+   if (list->val[0] != '\\' && list->val[0] != '$')
+   continue;
+   if (!strcmp( "\\Recent", list->val )) {
+   *status |= M_RECENT;
+   goto flagok;
+   }
+   for (uint i = 0; i < as(Flags); i++) {
+   if (!strcmp( Flags[i], list->val )) {
+   *flags |= 1 << i;
+   goto flagok;
+   }
+   }
+   if (list->val[0] == '$')
+   goto flagok; // Ignore unknown user-defined flags 
(keywords)
+   if (list->val[1] == 'X' && list->val[2] == '-')
+   goto flagok; // Ignore system flag extensions
+   warn( "IMAP warning: unknown system flag %s\n", list->val );
+ flagok: ;
+   }
+   *status |= M_FLAGS;
+   return 1;
+}
+
 static void
 parse_fetched_header( char *val, uint uid, char **tuid, char **msgid )
 {
@@ -1010,13 +1041,13 @@ parse_fetched_header( char *val, uint uid, char **tuid, 
char **msgid )
 static int
 parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
 {
-   list_t *body = NULL, *tmp, *flags;
+   list_t *body = NULL, *tmp;
char *tuid = NULL, *msgid = NULL, *ep;
imap_message_t *cur;
msg_data_t *msgdata;
imap_cmd_t *cmdp;
uchar mask = 0, status = 0;
-   uint i, uid = 0, need_uid = 0, size = 0;
+   uint uid = 0, need_uid = 0, size = 0;
time_t date = 0;
 
if (!is_list( list )) {
@@ -1036,31 +1067,8 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
} else if (!strcmp( "FLAGS", tmp->val )) {
tmp = tmp->next;
if (is_list( tmp )) {
-   for (flags = tmp->child; flags; flags = 
flags->next) {
-   if (is_atom( flags )) {
-   if (flags->val[0] == 
'\\' || flags->val[0] == '$') {
-   if (!strcmp( 
"\\Recent", flags->val)) {
-   status 
|= M_RECENT;
-   goto 
flagok;
-   }
-   for (i = 0; i < 
as(Flags); i++)
-   if 
(!strcmp( Flags[i], flags->val)) {
-   
mask |= 1 << i;
-   
goto flagok;
-   }
-   if 
(flags->val[0] == '$')
-   goto 
flagok; /* ignore unknown user-defined flags (keywords) */
-   if 
(flags->val[0] == '\\' && flags->val[1] == 'X' && flags->val[2] == '-')
-   goto 
flagok; /* ignore system flag extensions */
-   warn( "IMAP 
warning: unknown system flag %s\n", flags->val );
-   }
- flagok: ;
-   } else {
-   error( "IMAP error: 
unable to parse FLAGS list\n" );
-   goto ffail;
-   }
-   }
-   status |= M_FLAGS;
+   if (!parse_fetched_flags( tmp->child, 
,  ))
+ 

[commit] master: shrink some data at the source to avoid subsequent narrowing

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 4d7e169e5722babc0b78c71ed33f68030aaffd13
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 21:24:17 2019 +0200

shrink some data at the source to avoid subsequent narrowing

 src/common.h | 5 +++--
 src/config.c | 2 +-
 src/config.h | 2 +-
 src/sync.c   | 8 
 src/util.c   | 2 +-
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/common.h b/src/common.h
index 1c10459..cd95ab2 100644
--- a/src/common.h
+++ b/src/common.h
@@ -218,7 +218,8 @@ typedef struct notifier {
 #ifdef HAVE_SYS_POLL_H
int index;
 #else
-   int fd, events;
+   int fd;
+   short events;
 #endif
 } notifier_t;
 
@@ -231,7 +232,7 @@ typedef struct notifier {
 #endif
 
 void init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void 
*aux );
-void conf_notifier( notifier_t *sn, int and_events, int or_events );
+void conf_notifier( notifier_t *sn, short and_events, short or_events );
 void wipe_notifier( notifier_t *sn );
 
 typedef struct {
diff --git a/src/config.c b/src/config.c
index a2c0dda..f22e259 100644
--- a/src/config.c
+++ b/src/config.c
@@ -86,7 +86,7 @@ get_arg( conffile_t *cfile, int required, int *comment )
return ret;
 }
 
-int
+char
 parse_bool( conffile_t *cfile )
 {
if (!strcasecmp( cfile->val, "yes" ) ||
diff --git a/src/config.h b/src/config.h
index 2025347..779c3ee 100644
--- a/src/config.h
+++ b/src/config.h
@@ -40,7 +40,7 @@ typedef struct {
 
 char *get_arg( conffile_t *cfile, int required, int *comment );
 
-int parse_bool( conffile_t *cfile );
+char parse_bool( conffile_t *cfile );
 int parse_int( conffile_t *cfile );
 int parse_size( conffile_t *cfile );
 int getcline( conffile_t *cfile );
diff --git a/src/sync.c b/src/sync.c
index 4508ac1..0d62bb8 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1397,7 +1397,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
message_t *tmsg;
flag_vars_t *fv;
int no[2], del[2], alive, todel;
-   int sflags, nflags, aflags, dflags;
+   uchar sflags, nflags, aflags, dflags;
uint hashsz, idx;
 
if (check_ret( sts, aux ))
@@ -1723,7 +1723,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
if (!(srec->status & S_PENDING)) {
if (!srec->msg[S])
continue;
-   uint nex = (srec->wstate / W_NEXPIRE) & 1;
+   uchar nex = (srec->wstate / W_NEXPIRE) & 1;
if (nex != ((srec->status / S_EXPIRED) & 1)) {
/* The record needs a state change ... 
*/
if (nex != ((srec->status / S_EXPIRE) & 
1)) {
@@ -1991,14 +1991,14 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int 
t )
jFprintf( svars, "%c %u %u 0\n", "><"[t], srec->uid[M], 
srec->uid[S] );
srec->uid[1-t] = 0;
} else {
-   uint nflags = (srec->flags | srec->aflags[t]) & 
~srec->dflags[t];
+   uchar nflags = (srec->flags | srec->aflags[t]) & 
~srec->dflags[t];
if (srec->flags != nflags) {
debug( "  pair(%u,%u): updating flags (%u -> %u; 
%sed)\n", srec->uid[M], srec->uid[S], srec->flags, nflags, str_hl[t] );
srec->flags = nflags;
jFprintf( svars, "* %u %u %u\n", srec->uid[M], 
srec->uid[S], nflags );
}
if (t == S) {
-   uint nex = (srec->wstate / W_NEXPIRE) & 1;
+   uchar nex = (srec->wstate / W_NEXPIRE) & 1;
if (nex != ((srec->status / S_EXPIRED) & 1)) {
debug( "  pair(%u,%u): expired %d (commit)\n", 
srec->uid[M], srec->uid[S], nex );
srec->status = (srec->status & ~S_EXPIRED) | 
(nex * S_EXPIRED);
diff --git a/src/util.c b/src/util.c
index 738254d..fc8c8df 100644
--- a/src/util.c
+++ b/src/util.c
@@ -695,7 +695,7 @@ init_notifier( notifier_t *sn, int fd, void (*cb)( int, 
void * ), void *aux )
 }
 
 void
-conf_notifier( notifier_t *sn, int and_events, int or_events )
+conf_notifier( notifier_t *sn, short and_events, short or_events )
 {
 #ifdef HAVE_SYS_POLL_H
int idx = sn->index;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: fix lots of sign conversion warnings

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit e2d3b4d55b36b252d19d0c8b77e2ea59db7e4cd3
Author: Oswald Buddenhagen 
Date:   Wed Jul 8 17:27:37 2020 +0200

fix lots of sign conversion warnings

... by making a lot of objects unsigned, and some signed.
casts which lose precision and change the sign in one go (ssize_t and
time_t to uint on LP64) are made explicit as well.

 src/common.h  | 22 +--
 src/config.c  | 21 ++-
 src/config.h  |  2 +-
 src/driver.c  |  4 +-
 src/driver.h  | 12 +++---
 src/drv_imap.c| 95 ---
 src/drv_maildir.c | 95 ---
 src/drv_proxy.c   | 16 
 src/main.c|  9 +++--
 src/socket.c  | 58 +++--
 src/socket.h  | 18 -
 src/sync.c| 47 +++
 src/sync.h|  2 +-
 src/util.c| 52 +-
 14 files changed, 230 insertions(+), 223 deletions(-)

diff --git a/src/common.h b/src/common.h
index cd95ab2..548567f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -41,7 +41,7 @@ typedef unsigned long ulong;
 #define stringify(x) stringify__(x)
 
 #define shifted_bit(in, from, to) \
-   (((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / from : 
1)) & to)
+   ((int)(((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / 
from : 1)) & to))
 
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
 # define ATTR_UNUSED __attribute__((unused))
@@ -112,7 +112,7 @@ extern int Pid;
 extern char Hostname[256];
 extern const char *Home;
 
-extern int BufferLimit;
+extern uint BufferLimit;
 
 extern int new_total[2], new_done[2];
 extern int flags_total[2], flags_done[2];
@@ -139,7 +139,7 @@ typedef struct string_list {
char string[1];
 } ATTR_PACKED(void *) string_list_t;
 
-void add_string_list_n( string_list_t **list, const char *str, int len );
+void add_string_list_n( string_list_t **list, const char *str, uint len );
 void add_string_list( string_list_t **list, const char *str );
 void free_string_list( string_list_t *list );
 
@@ -150,9 +150,9 @@ void *memrchr( const void *s, int c, size_t n );
 size_t strnlen( const char *str, size_t maxlen );
 #endif
 
-int starts_with( const char *str, int strl, const char *cmp, int cmpl );
-int starts_with_upper( const char *str, int strl, const char *cmp, int cmpl );
-int equals( const char *str, int strl, const char *cmp, int cmpl );
+int starts_with( const char *str, int strl, const char *cmp, uint cmpl );
+int starts_with_upper( const char *str, int strl, const char *cmp, uint cmpl );
+int equals( const char *str, int strl, const char *cmp, uint cmpl );
 
 #ifndef HAVE_TIMEGM
 time_t timegm( struct tm *tm );
@@ -170,16 +170,16 @@ void ATTR_NORETURN oob( void );
 
 char *expand_strdup( const char *s );
 
-int map_name( const char *arg, char **result, int reserve, const char *in, 
const char *out );
+int map_name( const char *arg, char **result, uint reserve, const char *in, 
const char *out );
 
 #define DEFINE_ARRAY_TYPE(T) \
typedef struct { \
T *data; \
-   int size; \
+   uint size; \
} ATTR_PACKED(T *) T##_array_t; \
typedef struct { \
T##_array_t array; \
-   int alloc; \
+   uint alloc; \
} ATTR_PACKED(T *) T##_array_alloc_t; \
static INLINE T *T##_array_append( T##_array_alloc_t *arr ) \
{ \
@@ -205,7 +205,7 @@ int find_uint_array( const uint_array_t array, uint value );
 void arc4_init( void );
 uchar arc4_getbyte( void );
 
-int bucketsForSize( int size );
+uint bucketsForSize( uint size );
 
 typedef struct list_head {
struct list_head *next, *prev;
@@ -216,7 +216,7 @@ typedef struct notifier {
void (*cb)( int what, void *aux );
void *aux;
 #ifdef HAVE_SYS_POLL_H
-   int index;
+   uint index;
 #else
int fd;
short events;
diff --git a/src/config.c b/src/config.c
index f22e259..8cb56c6 100644
--- a/src/config.c
+++ b/src/config.c
@@ -121,13 +121,13 @@ parse_int( conffile_t *cfile )
return ret;
 }
 
-int
+uint
 parse_size( conffile_t *cfile )
 {
char *p;
-   int ret;
+   uint ret;
 
-   ret = strtol (cfile->val, , 10);
+   ret = strtoul( cfile->val, , 10 );
if (*p == 'k' || *p == 'K')
ret *= 1024, p++;
else if (*p == 'm' || *p == 'M')
@@ -319,7 +319,8 @@ load_config( const char *where, int pseudo )
group_conf_t *group, **groupapp = 
string_list_t *chanlist, **chanlistapp;
char *arg, *p;
-   int len, cops, gcops, max_size, ms, i;
+   uint len, max_size;
+   int cops, gcops, ms, i;
char path[_POSIX_PATH_MAX];
char buf[1024];
 
@@ -354,7 +355,7 @@ load_config( const char *where, int pseudo )
if (drivers[i]->parse_store( ,  )) {
if (store) {
   

[commit] master: modernize list of gcc warning flags somewhat

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit a6bb26091a575756cb8554d3376feb52f0300f92
Author: Oswald Buddenhagen 
Date:   Fri Nov 15 20:21:50 2019 +0100

modernize list of gcc warning flags somewhat

 configure.ac | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index a4c002d..811db2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,16 @@ AM_MAINTAINER_MODE
 
 AC_PROG_CC_C99
 if test "$GCC" = yes; then
-CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wstrict-prototypes -std=c99 
-pedantic -Wno-overlength-strings"
+warnings="
+-Wall -Wextra
+-Wshadow
+-Wcast-qual
+-Wformat=2 -Wformat-signedness -Wformat-nonliteral
+-Wstrict-prototypes
+
+-Wno-overlength-strings
+"
+CFLAGS="$CFLAGS -pipe -std=c99 -pedantic $(echo $warnings)"
 fi
 
 CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: drop redundant conn->writing member

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c391b06b07ec6310fbce1759c4a2d85bb0027c98
Author: Oswald Buddenhagen 
Date:   Sat Nov 16 16:00:06 2019 +0100

drop redundant conn->writing member

this information is already encoded in the socket notifier's config.

 src/common.h |  1 +
 src/socket.c |  4 +---
 src/socket.h |  1 -
 src/util.c   | 10 ++
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/common.h b/src/common.h
index c00495f..f95a8e2 100644
--- a/src/common.h
+++ b/src/common.h
@@ -235,6 +235,7 @@ typedef struct notifier {
 
 void init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void 
*aux );
 void conf_notifier( notifier_t *sn, short and_events, short or_events );
+short notifier_config( notifier_t *sn );
 void wipe_notifier( notifier_t *sn );
 
 typedef struct {
diff --git a/src/socket.c b/src/socket.c
index b7b6fc2..0599aba 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -884,7 +884,6 @@ do_queued_write( conn_t *conn )
return -1;
if (n != (int)len) {
conn->write_offset += (uint)n;
-   conn->writing = 1;
return 0;
}
conn->write_offset = 0;
@@ -894,7 +893,6 @@ do_queued_write( conn_t *conn )
if (conn->ssl && SSL_pending( conn->ssl ))
conf_wakeup( >ssl_fake, 0 );
 #endif
-   conn->writing = 0;
conn->write_callback( conn->callback_aux );
return -1;
 }
@@ -1103,7 +1101,7 @@ socket_fake_cb( void *aux )
/* Ensure that a pending write gets queued. */
do_flush( conn );
/* If no writes are ongoing, start writing now. */
-   if (!conn->writing)
+   if (!(notifier_config( >notify ) & POLLOUT))
do_queued_write( conn );
 }
 
diff --git a/src/socket.h b/src/socket.h
index bcc7fe1..5334a89 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -103,7 +103,6 @@ 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
uint append_avail; /* space left in accumulating buffer */
 #endif
diff --git a/src/util.c b/src/util.c
index c6c597c..a4ee67d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -704,6 +704,16 @@ conf_notifier( notifier_t *sn, short and_events, short 
or_events )
 #endif
 }
 
+short
+notifier_config( notifier_t *sn )
+{
+#ifdef HAVE_SYS_POLL_H
+   return pollfds[sn->index].events;
+#else
+   return sn->events;
+#endif
+}
+
 void
 wipe_notifier( notifier_t *sn )
 {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: remove support for SSLv3

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 234becf5309cf84f21f1ac069ba731f578c54346
Author: Oswald Buddenhagen 
Date:   Tue Nov 26 16:18:58 2019 +0100

remove support for SSLv3

it's insecure and default builds of openssl don't include it any more.

 NEWS   |  1 +
 src/drv_imap.c | 11 +--
 src/socket.c   |  4 +---
 src/socket.h   |  1 -
 4 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/NEWS b/NEWS
index d7a79a8..761337e 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@
 The 'isync' compatibility wrapper was removed.
 
 Added support for disabling TLS v1.3 - adjust SSLVersions if you set it.
+Removed support for obsolete/insecure SSL v3.
 
 The IMAP '$Forwarded' / Maildir 'P' (passed) flag is supported now.
 
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 5285f64..8137edd 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3194,7 +3194,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 #ifdef HAVE_LIBSSL
/* Legacy SSL options */
int require_ssl = -1, use_imaps = -1;
-   int use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1, 
use_tlsv13 = -1;
+   int use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1, use_tlsv13 = -1;
 #endif
/* Legacy SASL option */
int require_cram = -1;
@@ -3234,7 +3234,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
arg += 6;
server->ssl_type = SSL_IMAPS;
if (server->sconf.ssl_versions == -1)
-   server->sconf.ssl_versions = SSLv3 | 
TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3;
+   server->sconf.ssl_versions = TLSv1 | 
TLSv1_1 | TLSv1_2 | TLSv1_3;
} else
 #endif
if (starts_with( arg, -1, "imap:", 5 ))
@@ -3326,7 +3326,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
if (!strcasecmp( "SSLv2", arg )) {
warn( "Warning: SSLVersion SSLv2 is no 
longer supported\n" );
} else if (!strcasecmp( "SSLv3", arg )) {
-   server->sconf.ssl_versions |= SSLv3;
+   warn( "Warning: SSLVersion SSLv3 is no 
longer supported\n" );
} else if (!strcasecmp( "TLSv1", arg )) {
server->sconf.ssl_versions |= TLSv1;
} else if (!strcasecmp( "TLSv1.1", arg )) {
@@ -3347,7 +3347,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
else if (!strcasecmp( "UseSSLv2", cfg->cmd ))
warn( "Warning: UseSSLv2 is no longer supported\n" );
else if (!strcasecmp( "UseSSLv3", cfg->cmd ))
-   use_sslv3 = parse_bool( cfg );
+   warn( "Warning: UseSSLv3 is no longer supported\n" );
else if (!strcasecmp( "UseTLSv1", cfg->cmd ))
use_tlsv1 = parse_bool( cfg );
else if (!strcasecmp( "UseTLSv1.1", cfg->cmd ))
@@ -3416,7 +3416,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
return 1;
}
 #ifdef HAVE_LIBSSL
-   if ((use_sslv3 & use_tlsv1 & use_tlsv11 & use_tlsv12 & 
use_tlsv13) != -1 || use_imaps >= 0 || require_ssl >= 0) {
+   if ((use_tlsv1 & use_tlsv11 & use_tlsv12 & use_tlsv13) != -1 || 
use_imaps >= 0 || require_ssl >= 0) {
if (server->ssl_type >= 0 || server->sconf.ssl_versions 
>= 0) {
error( "%s '%s': The deprecated UseSSL*, 
UseTLS*, UseIMAPS, and RequireSSL options are mutually exclusive with SSLType 
and SSLVersions.\n", type, name );
cfg->err = 1;
@@ -3424,7 +3424,6 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
}
warn( "Notice: %s '%s': UseSSL*, UseTLS*, UseIMAPS, and 
RequireSSL are deprecated. Use SSLType and SSLVersions instead.\n", type, name 
);
server->sconf.ssl_versions =
-   (use_sslv3 != 1 ? 0 : SSLv3) |
(use_tlsv1 == 0 ? 0 : TLSv1) |
(use_tlsv11 != 1 ? 0 : TLSv1_1) |
(use_tlsv12 != 1 ? 0 : TLSv1_2) |
diff --git a/src/socket.c b/src/socket.c
index 5d7a019..bf09e5e 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -233,7 +233,6 @@ static int
 init_ssl_ctx( const server_conf_t *conf )
 {
server_conf_t *mconf = (server_conf_t *)conf;
-   int options = 0;
 
if (conf->SSLContext)
return conf->ssl_ctx_valid;
@@ -248,8 +247,7 @@ init_ssl_ctx( const server_conf_t *conf )
return 0;
}
 
-   if (!(conf->ssl_versions & SSLv3))
- 

[commit] master: purge handling of pending sync entries from state file

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b514d9ddbc065deab8d5122e02398fd20e0ffe97
Author: Oswald Buddenhagen 
Date:   Sat Jul 4 16:13:50 2020 +0200

purge handling of pending sync entries from state file

these cannot actually end up in the committed state.

amends bd5fb6ff.

 src/sync.c | 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 419f8e6..f35b3f7 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -703,7 +703,7 @@ save_state( sync_vars_t *svars )
continue;
make_flags( srec->flags, fbuf );
Fprintf( svars->nfp, "%u %u %s%s\n", srec->uid[M], srec->uid[S],
-(srec->status & S_SKIPPED) ? "^" : (srec->status & 
S_PENDING) ? "!" : (srec->status & S_EXPIRED) ? "~" : "", fbuf );
+(srec->status & S_SKIPPED) ? "^" : (srec->status & 
S_EXPIRED) ? "~" : "", fbuf );
}
 
Fclose( svars->nfp, 1 );
@@ -799,28 +799,19 @@ load_state( sync_vars_t *svars )
if (*s == '^') {
s++;
srec->status = S_SKIPPED;
-   } else if (*s == '!') {
-   s++;
-   srec->status = S_PENDING;
} else if (*s == '~' || *s == 'X' /* Pre-1.3 legacy */) 
{
s++;
srec->status = S_EXPIRE | S_EXPIRED;
} else if (srec->uid[M] == (uint)-1) {  // Pre-1.3 
legacy
srec->uid[M] = 0;
srec->status = S_SKIPPED;
-   } else if (srec->uid[M] == (uint)-2) {
-   srec->uid[M] = 0;
-   srec->status = S_PENDING;
} else if (srec->uid[S] == (uint)-1) {
srec->uid[S] = 0;
srec->status = S_SKIPPED;
-   } else if (srec->uid[S] == (uint)-2) {
-   srec->uid[S] = 0;
-   srec->status = S_PENDING;
}
srec->flags = parse_flags( s );
debug( "  entry (%u,%u,%u,%s)\n", srec->uid[M], 
srec->uid[S], srec->flags,
-  (srec->status & S_SKIPPED) ? "SKIP" : 
(srec->status & S_PENDING) ? "FAIL" : (srec->status & S_EXPIRED) ? "XPIRE" : "" 
);
+  (srec->status & S_SKIPPED) ? "SKIP" : 
(srec->status & S_EXPIRED) ? "XPIRE" : "" );
*svars->srecadd = srec;
svars->srecadd = >next;
svars->nsrecs++;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: fix strftime() format string warning properly

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 27a1935361f90a72bbb9a625fb6a8e8895d92b13
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 20:42:04 2019 +0200

fix strftime() format string warning properly

the workaround for -Wformat triggered -Wformat-nonliteral in turn.
so instead go back to using pragmas and add a proper gcc version check.

this also works with clang - mostly for qt-creator's code model, which
is clang-based.

amends/reverts 55e65147.

 src/common.h   | 16 
 src/drv_imap.c | 11 ---
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/common.h b/src/common.h
index d52240e..a04e9f9 100644
--- a/src/common.h
+++ b/src/common.h
@@ -55,6 +55,22 @@ typedef unsigned long ulong;
 # define ATTR_PACKED(ref)
 #endif
 
+#if defined(__clang__)
+# define DO_PRAGMA__(text) _Pragma(#text)
+# define DIAG_PUSH DO_PRAGMA__(clang diagnostic push)
+# define DIAG_POP DO_PRAGMA__(clang diagnostic pop)
+# define DIAG_DISABLE(text) DO_PRAGMA__(clang diagnostic ignored text)
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+# define DO_PRAGMA__(text) _Pragma(#text)
+# define DIAG_PUSH DO_PRAGMA__(GCC diagnostic push)
+# define DIAG_POP DO_PRAGMA__(GCC diagnostic pop)
+# define DIAG_DISABLE(text) DO_PRAGMA__(GCC diagnostic ignored text)
+#else
+# define DIAG_PUSH
+# define DIAG_POP
+# define DIAG_DISABLE(text)
+#endif
+
 #if __GNUC__ >= 7
 # define FALLTHROUGH __attribute__((fallthrough));
 #else
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 7eeff82..e49d040 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2927,12 +2927,6 @@ imap_trash_msg( store_t *gctx, message_t *msg,
 
 static void imap_store_msg_p2( imap_store_t *, imap_cmd_t *, int );
 
-static size_t
-my_strftime( char *s, size_t max, const char *fmt, const struct tm *tm )
-{
-return strftime( s, max, fmt, tm );
-}
-
 static void
 imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
 void (*cb)( int sts, uint uid, void *aux ), void *aux )
@@ -2971,7 +2965,10 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
}
if (data->date) {
/* configure ensures that %z actually works. */
-   my_strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z", 
localtime( >date ) );
+DIAG_PUSH
+DIAG_DISABLE("-Wformat")
+   strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z", 
localtime( >date ) );
+DIAG_POP
imap_exec( ctx, >gen, imap_store_msg_p2,
   "APPEND \"%\\s\" %s\"%\\s\" ", buf, flagstr, datestr 
);
} else {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: add option to get password from macOS Keychain

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 198ca65b6ea1d46e6ce8b9e9c2d4e10033c5247b
Author: Oswald Buddenhagen 
Date:   Wed Nov 27 17:13:44 2019 +0100

add option to get password from macOS Keychain

this is better than using PassCmd, as it allows the keychain manager to
identify the calling process and therefore use a selective whitelist.

unlike in the now removed example, we use an "internet password" for the
imap protocol, rather than a "generic password" - this seems more
appropriate.

based on a patch by Oliver Runge 

 NEWS|  2 ++
 configure.ac| 34 +-
 src/Makefile.am |  2 +-
 src/drv_imap.c  | 43 +++
 src/mbsync.1| 22 ++
 src/mbsyncrc.sample |  5 -
 6 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index 41934a5..4133a50 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ IMAP mailbox subscriptions are supported now.
 
 The IMAP user query can be scripted now.
 
+Added built-in support for macOS Keychain.
+
 [1.3.0]
 
 Network timeout handling has been added.
diff --git a/configure.ac b/configure.ac
index 811db2c..50e5ddb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,9 @@
 AC_INIT([isync], [1.4.0])
 AC_CONFIG_HEADERS([autodefs.h])
-AM_INIT_AUTOMAKE
 
+AC_CANONICAL_TARGET
+
+AM_INIT_AUTOMAKE
 AM_MAINTAINER_MODE
 
 AC_PROG_CC_C99
@@ -198,6 +200,29 @@ fi
 
 AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes)
 
+case $target_os in
+darwin*)
+darwin=yes
+;;
+*)
+darwin=no
+;;
+esac
+
+AC_ARG_WITH(
+macos-keychain,
+[AS_HELP_STRING([--with-macos-keychain], [Support macOS keychain])],
+[have_macos_keychain=$withval],
+[have_macos_keychain=$darwin])
+if test "x$have_macos_keychain" != xno; then
+if test $darwin = no; then
+AC_MSG_ERROR([Cannot use macOS Keychain outside macOS.])
+fi
+have_macos_keychain=yes
+AC_DEFINE(HAVE_MACOS_KEYCHAIN, 1, [Define to 1 if you have the macOS 
Keychain Services API.])
+AC_SUBST(KEYCHAIN_LIBS, ["-Wl,-framework,Security"])
+fi
+
 AC_CONFIG_FILES([Makefile src/Makefile isync.spec])
 AC_OUTPUT
 
@@ -222,4 +247,11 @@ if test "x$ac_cv_berkdb4" = xyes; then
 else
 AC_MSG_RESULT([Not using Berkeley DB])
 fi
+if test $darwin = yes; then
+if test "x$have_macos_keychain" = xyes; then
+AC_MSG_RESULT([Using macOS Keychain])
+else
+AC_MSG_RESULT([Not using macOS Keychain])
+fi
+fi
 AC_MSG_RESULT()
diff --git a/src/Makefile.am b/src/Makefile.am
index 63c4e22..76dff34 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
 mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c 
drv_maildir.c drv_proxy.c
-mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS)
+mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) 
$(KEYCHAIN_LIBS)
 noinst_HEADERS = common.h config.h driver.h sync.h socket.h
 
 drv_proxy.$(OBJEXT): drv_proxy.inc
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 3980044..5acbd79 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -41,6 +41,10 @@
 # include 
 #endif
 
+#ifdef HAVE_MACOS_KEYCHAIN
+# include 
+#endif
+
 #ifdef HAVE_LIBSSL
 enum { SSL_None, SSL_STARTTLS, SSL_IMAPS };
 #endif
@@ -58,6 +62,9 @@ typedef struct imap_server_conf {
string_list_t *auth_mechs;
 #ifdef HAVE_LIBSSL
char ssl_type;
+#endif
+#ifdef HAVE_MACOS_KEYCHAIN
+   char use_keychain;
 #endif
char failed;
 } imap_server_conf_t;
@@ -1991,6 +1998,31 @@ ensure_password( imap_server_conf_t *srvc )
if (!srvc->pass) {
if (srvc->pass_cmd) {
srvc->pass = cred_from_cmd( "PassCmd", srvc->pass_cmd, 
srvc->name );
+#ifdef HAVE_MACOS_KEYCHAIN
+   } else if (srvc->use_keychain) {
+   void *password_data;
+   UInt32 password_length;
+   OSStatus ret = SecKeychainFindInternetPassword(
+   NULL,  // keychainOrArray
+   strlen( srvc->sconf.host ), 
srvc->sconf.host,
+   0, NULL,  // securityDomain
+   strlen( srvc->user ), srvc->user,
+   0, NULL,  // path
+   0,  // port - we could use it, but it 
seems pointless
+   kSecProtocolTypeIMAP,
+   kSecAuthenticationTypeDefault,
+   _length, _data,
+   NULL );  // itemRef
+   if (ret != errSecSuccess) {
+   CFStringRef errmsg = SecCopyErrorMessageString( 
ret, NULL );
+   error( "Looking up Keychain failed: %s\n",
+  

[commit] master: fix signedness issues surrounding UIDs

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 2f3cb5f4815d0024042bfb8387163b210acf3a6f
Author: Oswald Buddenhagen 
Date:   Wed Jul 8 13:45:06 2020 +0200

fix signedness issues surrounding UIDs

amends bb632d1c.

 src/driver.h  |  4 ++--
 src/drv_imap.c| 10 +-
 src/drv_maildir.c |  6 +++---
 src/drv_proxy.c   |  2 +-
 src/sync.c| 20 ++--
 5 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index 238819d..48093af 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -176,10 +176,10 @@ struct driver {
/* Open the selected mailbox.
 * Note that this should not directly complain about failure to open. */
void (*open_box)( store_t *ctx,
- void (*cb)( int sts, int uidvalidity, void *aux ), 
void *aux );
+ void (*cb)( int sts, uint uidvalidity, void *aux ), 
void *aux );
 
/* Return the minimal UID the next stored message will have. */
-   int (*get_uidnext)( store_t *ctx );
+   uint (*get_uidnext)( store_t *ctx );
 
/* Return the flags that can be stored in the selected mailbox. */
xint (*get_supported_flags)( store_t *ctx );
diff --git a/src/drv_imap.c b/src/drv_imap.c
index e49d040..c3b83f2 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -2392,7 +2392,7 @@ imap_get_box_path( store_t *gctx ATTR_UNUSED )
 
 typedef struct {
imap_cmd_t gen;
-   void (*callback)( int sts, int uidvalidity, void *aux );
+   void (*callback)( int sts, uint uidvalidity, void *aux );
void *callback_aux;
 } imap_cmd_open_box_t;
 
@@ -2402,7 +2402,7 @@ static void imap_open_box_p4( imap_store_t *, 
imap_cmd_open_box_t *, int );
 
 static void
 imap_open_box( store_t *gctx,
-   void (*cb)( int sts, int uidvalidity, void *aux ), void *aux )
+   void (*cb)( int sts, uint uidvalidity, void *aux ), void *aux )
 {
imap_store_t *ctx = (imap_store_t *)gctx;
imap_cmd_open_box_t *cmd;
@@ -2465,7 +2465,7 @@ imap_open_box_p4( imap_store_t *ctx, imap_cmd_open_box_t 
*cmdp, int response )
cmdp->callback( response, ctx->uidvalidity, cmdp->callback_aux );
 }
 
-static int
+static uint
 imap_get_uidnext( store_t *gctx )
 {
imap_store_t *ctx = (imap_store_t *)gctx;
@@ -2954,12 +2954,12 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
cmd->gen.param.create = 1;
cmd->gen.param.to_trash = 1;
if (prepare_trash( , ctx ) < 0) {
-   cb( DRV_BOX_BAD, -1, aux );
+   cb( DRV_BOX_BAD, 0, aux );
return;
}
} else {
if (prepare_box( , ctx ) < 0) {
-   cb( DRV_BOX_BAD, -1, aux );
+   cb( DRV_BOX_BAD, 0, aux );
return;
}
}
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 9b42efc..984e36c 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -697,7 +697,7 @@ maildir_store_uidval( maildir_store_t *ctx )
 static int
 maildir_init_uidval( maildir_store_t *ctx )
 {
-   ctx->uidvalidity = time( 0 );
+   ctx->uidvalidity = (uint)time( 0 );
ctx->nuid = 0;
ctx->uvok = 0;
 #ifdef USE_DB
@@ -1279,7 +1279,7 @@ maildir_get_box_path( store_t *gctx )
 
 static void
 maildir_open_box( store_t *gctx,
-  void (*cb)( int sts, int uidvalidity, void *aux ), void *aux 
)
+  void (*cb)( int sts, uint uidvalidity, void *aux ), void 
*aux )
 {
maildir_store_t *ctx = (maildir_store_t *)gctx;
int ret;
@@ -1324,7 +1324,7 @@ maildir_open_box( store_t *gctx,
cb( ret, ctx->uidvalidity, aux );
 }
 
-static int
+static uint
 maildir_get_uidnext( store_t *gctx )
 {
maildir_store_t *ctx = (maildir_store_t *)gctx;
diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index 7250293..36463c6 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -204,7 +204,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( 
@decl_cb_args@void *aux ), v
if (excs.size) {
debugn( "  excs:" );
for (int t = 0; t < excs.size; t++)
-   debugn( " %d", excs.data[t] );
+   debugn( " %u", excs.data[t] );
debug( "\n" );
}
 //# END
diff --git a/src/sync.c b/src/sync.c
index 7438745..9aacfa5 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1005,11 +1005,11 @@ delete_state( sync_vars_t *svars )
}
 }
 
-static void box_confirmed( int sts, int uidvalidity, void *aux );
+static void box_confirmed( int sts, uint uidvalidity, void *aux );
 static void box_confirmed2( sync_vars_t *svars, int t );
 static void box_deleted( int sts, void *aux );
 static void box_created( int sts, void *aux );
-static void box_opened( int sts, int uidvalidity, void *aux );
+static void box_opened( int sts, uint uidvalidity, void *aux );
 static void box_opened2( sync_vars_t 

[commit] master: make more objects static

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 5c2e8d3e147ad4550fbdb66585a93b1a03e1f756
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 20:54:01 2019 +0200

make more objects static

 src/config.c   | 2 +-
 src/drv_imap.c | 2 +-
 src/main.c | 4 ++--
 src/sync.c | 8 
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/config.c b/src/config.c
index 8ddfe26..a2c0dda 100644
--- a/src/config.c
+++ b/src/config.c
@@ -34,7 +34,7 @@
 #include 
 #include 
 
-store_conf_t *stores;
+static store_conf_t *stores;
 
 char *
 get_arg( conffile_t *cfile, int required, int *comment )
diff --git a/src/drv_imap.c b/src/drv_imap.c
index dc00a14..ee2d1a8 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3184,7 +3184,7 @@ imap_get_fail_state( store_conf_t *gconf )
 
 /*** imap_parse_store ***/
 
-imap_server_conf_t *servers, **serverapp = 
+static imap_server_conf_t *servers, **serverapp = 
 
 static int
 imap_parse_store( conffile_t *cfg, store_conf_t **storep )
diff --git a/src/main.c b/src/main.c
index 2cb092c..c2420ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,8 +49,8 @@ const char *Home; /* for config */
 
 int BufferLimit = 10 * 1024 * 1024;
 
-int chans_total, chans_done;
-int boxes_total, boxes_done;
+static int chans_total, chans_done;
+static int boxes_total, boxes_done;
 int new_total[2], new_done[2];
 int flags_total[2], flags_done[2];
 int trash_total[2], trash_done[2];
diff --git a/src/sync.c b/src/sync.c
index 786ca1e..cf788f0 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -65,7 +65,7 @@ debugn( const char *msg, ... )
va_end( va );
 }
 
-void
+static void
 Fclose( FILE *f, int safe )
 {
if ((safe && (fflush( f ) || (UseFSync && fdatasync( fileno( f )  
|| fclose( f ) == EOF) {
@@ -74,7 +74,7 @@ Fclose( FILE *f, int safe )
}
 }
 
-void ATTR_PRINTFLIKE(2, 0)
+static void ATTR_PRINTFLIKE(2, 0)
 vFprintf( FILE *f, const char *msg, va_list va )
 {
int r;
@@ -86,7 +86,7 @@ vFprintf( FILE *f, const char *msg, va_list va )
}
 }
 
-void ATTR_PRINTFLIKE(2, 3)
+static void ATTR_PRINTFLIKE(2, 3)
 Fprintf( FILE *f, const char *msg, ... )
 {
va_list va;
@@ -217,7 +217,7 @@ static int check_cancel( sync_vars_t *svars );
 #define ST_SENDING_NEW (1<<15)
 
 
-void ATTR_PRINTFLIKE(2, 3)
+static void ATTR_PRINTFLIKE(2, 3)
 jFprintf( sync_vars_t *svars, const char *msg, ... )
 {
va_list va;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: wrap jFprintf()+debug() into a macro

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit d93726067dc298a33f65800d73a3fe1e35c46afc
Author: Oswald Buddenhagen 
Date:   Wed Jul 8 22:16:47 2020 +0200

wrap jFprintf()+debug() into a macro

this ensures that everything that is logged to the journal also appears
in the debug output, and it makes the code less noisy.

 src/common.h |  7 
 src/sync.c   | 97 +++-
 2 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/src/common.h b/src/common.h
index f95a8e2..1bf3aa1 100644
--- a/src/common.h
+++ b/src/common.h
@@ -40,6 +40,13 @@ typedef unsigned long ulong;
 #define stringify__(x) #x
 #define stringify(x) stringify__(x)
 
+// From https://stackoverflow.com/a/62984543/3685191
+#define deparen(x) esc_(ish_ x)
+#define esc_(...) esc__(__VA_ARGS__)
+#define esc__(...) van_ ## __VA_ARGS__
+#define ish_(...) ish_ __VA_ARGS__
+#define van_ish_
+
 #define shifted_bit(in, from, to) \
((int)(((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / 
from : 1)) & to))
 
diff --git a/src/sync.c b/src/sync.c
index 5243b23..419f8e6 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -233,6 +233,18 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
exit( 100 );
 }
 
+#define JLOG_(log_fmt, log_args, dbg_fmt, ...) \
+   do { \
+   debug( "-> log: " log_fmt " (" dbg_fmt ")\n", __VA_ARGS__ ); \
+   jFprintf( svars, log_fmt "\n", deparen(log_args) ); \
+   } while (0)
+#define JLOG3(log_fmt, log_args, dbg_fmt) \
+   JLOG_(log_fmt, log_args, dbg_fmt, deparen(log_args))
+#define JLOG4(log_fmt, log_args, dbg_fmt, dbg_args) \
+   JLOG_(log_fmt, log_args, dbg_fmt, deparen(log_args), deparen(dbg_args))
+#define JLOG_SEL(_1, _2, _3, _4, x, ...) x
+#define JLOG(...) JLOG_SEL(__VA_ARGS__, JLOG4, JLOG3, NO_JLOG2, 
NO_JLOG1)(__VA_ARGS__)
+
 static void
 match_tuids( sync_vars_t *svars, int t, message_t *msgs )
 {
@@ -245,7 +257,7 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
if (srec->status & S_DEAD)
continue;
if (!srec->uid[t] && srec->tuid[0]) {
-   debug( "  pair(%u,%u): lookup %s, TUID %." 
stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid );
+   debug( "pair(%u,%u) TUID %." stringify(TUIDL) "s\n", 
srec->uid[M], srec->uid[S], srec->tuid );
for (tmsg = ntmsg; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD)
continue;
@@ -262,15 +274,13 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
goto mfound;
}
}
-   debug( "  -> TUID lost\n" );
-   jFprintf( svars, "& %u %u\n", srec->uid[M], 
srec->uid[S] );
+   JLOG( "& %u %u", (srec->uid[M], srec->uid[S]), "TUID 
lost" );
// Note: status remains S_PENDING.
srec->tuid[0] = 0;
num_lost++;
continue;
  mfound:
-   debug( "  -> new UID %u %s\n", tmsg->uid, diag );
-   jFprintf( svars, "%c %u %u %u\n", "<>"[t], 
srec->uid[M], srec->uid[S], tmsg->uid );
+   JLOG( "%c %u %u %u", ("<>"[t], srec->uid[M], 
srec->uid[S], tmsg->uid), "TUID matched %s", diag );
tmsg->srec = srec;
srec->msg[t] = tmsg;
ntmsg = tmsg->next;
@@ -1496,7 +1506,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) {
svars->uidval[M] = svars->newuidval[M];
svars->uidval[S] = svars->newuidval[S];
-   jFprintf( svars, "| %u %u\n", svars->uidval[M], 
svars->uidval[S] );
+   JLOG( "| %u %u", (svars->uidval[M], svars->uidval[S]), "new 
UIDVALIDITYs" );
}
 
info( "Synchronizing...\n" );
@@ -1516,9 +1526,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
// It does not matter whether one side was already 
known to be missing
// (never stored [skipped or failed] or expunged 
[possibly expired]) -
// now both are missing, so the entry is superfluous.
-   debug( "  vanished\n" );
srec->status = S_DEAD;
-   jFprintf( svars, "- %u %u\n", srec->uid[M], 
srec->uid[S] );
+   JLOG( "- %u %u", (srec->uid[M], srec->uid[S]), "both 
missing" );
} else {
// del[] means that a message becomes known to have 
been expunged.
del[M] = no[M] && srec->uid[M];
@@ -1540,8 +1549,7 @@ 

[commit] master: sanitize error handling in IMAP FETCH response processing

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit a5a8783ea3de982dfd7c3926646033919bbf6af3
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 14:29:42 2019 +0100

sanitize error handling in IMAP FETCH response processing

abort on actual error conditions (protocol errors) and downgrade the
rest to warnings.

REFMAIL: 20191102164509.dxayakg3hrmozjnm@carbon

 src/drv_imap.c | 51 ++
 1 file changed, 35 insertions(+), 16 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index dbc9c5f..4d3a038 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -968,8 +968,8 @@ parse_date( const char *str )
 static int
 parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
 {
-   list_t *tmp, *flags;
-   char *body = NULL, *tuid = NULL, *msgid = NULL, *ep;
+   list_t *body = NULL, *tmp, *flags;
+   char *tuid = NULL, *msgid = NULL, *ep;
imap_message_t *cur;
msg_data_t *msgdata;
imap_cmd_t *cmdp;
@@ -986,8 +986,10 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s 
ATTR_UNUSED )
if (is_atom( tmp )) {
if (!strcmp( "UID", tmp->val )) {
tmp = tmp->next;
-   if (!is_atom( tmp ) || (uid = strtoul( 
tmp->val, , 10 ), *ep))
+   if (!is_atom( tmp ) || (uid = strtoul( 
tmp->val, , 10 ), *ep)) {
error( "IMAP error: unable to parse 
UID\n" );
+   goto ffail;
+   }
} else if (!strcmp( "FLAGS", tmp->val )) {
tmp = tmp->next;
if (is_list( tmp )) {
@@ -1007,34 +1009,44 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char 
*s ATTR_UNUSED )
goto 
flagok; /* ignore unknown user-defined flags (keywords) */
if 
(flags->val[0] == '\\' && flags->val[1] == 'X' && flags->val[2] == '-')
goto 
flagok; /* ignore system flag extensions */
-   error( "IMAP 
warning: unknown system flag %s\n", flags->val );
+   warn( "IMAP 
warning: unknown system flag %s\n", flags->val );
}
  flagok: ;
-   } else
+   } else {
error( "IMAP error: 
unable to parse FLAGS list\n" );
+   goto ffail;
+   }
}
status |= M_FLAGS;
-   } else
+   } else {
error( "IMAP error: unable to parse 
FLAGS\n" );
+   goto ffail;
+   }
} else if (!strcmp( "INTERNALDATE", tmp->val )) {
tmp = tmp->next;
if (is_atom( tmp )) {
-   if ((date = parse_date( tmp->val )) == 
-1)
+   if ((date = parse_date( tmp->val )) == 
-1) {
error( "IMAP error: unable to 
parse INTERNALDATE format\n" );
-   } else
+   goto ffail;
+   }
+   } else {
error( "IMAP error: unable to parse 
INTERNALDATE\n" );
+   goto ffail;
+   }
} else if (!strcmp( "RFC822.SIZE", tmp->val )) {
tmp = tmp->next;
-   if (!is_atom( tmp ) || (size = strtoul( 
tmp->val, , 10 ), *ep))
+   if (!is_atom( tmp ) || (size = strtoul( 
tmp->val, , 10 ), *ep)) {
error( "IMAP error: unable to parse 
RFC822.SIZE\n" );
+   goto ffail;
+   }
} else if (!strcmp( "BODY[]", tmp->val )) {
tmp = tmp->next;
if (is_atom( tmp )) {
-   body = tmp->val;
-   tmp->val = NULL;   /* don't free 
together with list */
- 

[commit] master: rename socket_expect_read() => socket_expect_activity()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit e7bc402d09bba365b7ef34bf223a39155b5d8dab
Author: Oswald Buddenhagen 
Date:   Sat Nov 16 17:14:57 2019 +0100

rename socket_expect_read() => socket_expect_activity()

... to better reflect its (mostly new) function.

 src/drv_imap.c | 16 
 src/socket.c   | 10 +-
 src/socket.h   |  2 +-
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index c3b83f2..e2d5fce 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -345,7 +345,7 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd )
*ctx->in_progress_append = cmd;
ctx->in_progress_append = >next;
ctx->num_in_progress++;
-   socket_expect_read( >conn, 1 );
+   socket_expect_activity( >conn, 1 );
 }
 
 static int
@@ -409,7 +409,7 @@ cancel_sent_imap_cmds( imap_store_t *ctx )
 {
imap_cmd_t *cmd;
 
-   socket_expect_read( >conn, 0 );
+   socket_expect_activity( >conn, 0 );
while ((cmd = ctx->in_progress)) {
ctx->in_progress = cmd->next;
/* don't update num_in_progress and in_progress_append - store 
is dead */
@@ -1469,7 +1469,7 @@ imap_socket_read( void *aux )
error( "IMAP error: unexpected reply: %s %s\n", arg, 
cmd ? cmd : "" );
break; /* this may mean anything, so prefer not to spam 
the log */
} else if (*arg == '+') {
-   socket_expect_read( >conn, 0 );
+   socket_expect_activity( >conn, 0 );
/* There can be any number of commands in flight, but 
only the last
 * one can require a continuation, as it enforces a 
round-trip. */
cmdp = (imap_cmd_t *)((char *)ctx->in_progress_append -
@@ -1499,7 +1499,7 @@ imap_socket_read( void *aux )
error( "IMAP error: unexpected command 
continuation request\n" );
break;
}
-   socket_expect_read( >conn, 1 );
+   socket_expect_activity( >conn, 1 );
} else {
tag = atoi( arg );
for (pcmdp = >in_progress; (cmdp = *pcmdp); pcmdp 
= >next)
@@ -1511,7 +1511,7 @@ imap_socket_read( void *aux )
if (!(*pcmdp = cmdp->next))
ctx->in_progress_append = pcmdp;
if (!--ctx->num_in_progress)
-   socket_expect_read( >conn, 0 );
+   socket_expect_activity( >conn, 0 );
arg = next_arg(  );
if (!arg) {
error( "IMAP error: malformed tagged 
response\n" );
@@ -1798,7 +1798,7 @@ imap_open_store_connected( int ok, void *aux )
socket_start_tls( >conn, imap_open_store_tlsstarted1 );
 #endif
else
-   socket_expect_read( >conn, 1 );
+   socket_expect_activity( >conn, 1 );
 }
 
 #ifdef HAVE_LIBSSL
@@ -1810,14 +1810,14 @@ imap_open_store_tlsstarted1( int ok, void *aux )
if (!ok)
imap_open_store_ssl_bail( ctx );
else
-   socket_expect_read( >conn, 1 );
+   socket_expect_activity( >conn, 1 );
 }
 #endif
 
 static void
 imap_open_store_greeted( imap_store_t *ctx )
 {
-   socket_expect_read( >conn, 0 );
+   socket_expect_activity( >conn, 0 );
if (!ctx->caps)
imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" );
else
diff --git a/src/socket.c b/src/socket.c
index 4e64515..4034d9d 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -329,7 +329,7 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void 
*aux ) )
return;
}
SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
-   socket_expect_read( conn, 1 );
+   socket_expect_activity( conn, 1 );
start_tls_p2( conn );
 }
 
@@ -348,7 +348,7 @@ start_tls_p2( conn_t *conn )
 
 static void start_tls_p3( conn_t *conn, int ok )
 {
-   socket_expect_read( conn, 0 );
+   socket_expect_activity( conn, 0 );
conn->state = SCK_READY;
conn->callbacks.starttls( ok, conn->callback_aux );
 }
@@ -578,7 +578,7 @@ socket_connect_one( conn_t *sock )
return;
}
conf_notifier( >notify, 0, POLLOUT );
-   socket_expect_read( sock, 1 );
+   socket_expect_activity( sock, 1 );
sock->state = SCK_CONNECTING;
info( "\v\n" );
return;
@@ -612,7 +612,7 @@ socket_connected( conn_t *conn )
conn->addrs = 0;
}
conf_notifier( >notify, 0, POLLIN );
-   socket_expect_read( conn, 0 );
+   socket_expect_activity( conn, 0 );
conn->state = SCK_READY;
conn->callbacks.connect( 1, conn->callback_aux );
 }
@@ 

[commit] master: set sync record's flags only after propagating new message

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 25b1c2b9e730cd5a61581c6379e4c6a1900f38eb
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 12:34:36 2019 +0100

set sync record's flags only after propagating new message

this is semantically cleaner, and fixes storing the flags in the rare
case that flags are not being synced and the target is not being
expunged, as in this case flags are queried only during the actual
propagation.

 src/sync.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 9bc08b6..6b90ba1 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -262,7 +262,6 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
}
debug( "  -> TUID lost\n" );
jFprintf( svars, "& %u %u\n", srec->uid[M], 
srec->uid[S] );
-   srec->flags = 0;
// Note: status remains S_PENDING.
srec->tuid[0] = 0;
num_lost++;
@@ -942,7 +941,6 @@ load_state( sync_vars_t *svars )
break;
case '&':
debug( "TUID %." 
stringify(TUIDL) "s lost\n", srec->tuid );
-   srec->flags = 0;
srec->tuid[0] = 0;
break;
case '<':
@@ -1623,11 +1621,6 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
debug( "  -> pair(%u,%u) 
created\n", srec->uid[M], srec->uid[S] );
}
if ((tmsg->flags & F_FLAGGED) || 
tmsg->size <= svars->chan->stores[t]->max_size) {
-   if (tmsg->flags != srec->flags) 
{
-   srec->flags = 
tmsg->flags;
-   jFprintf( svars, "* %u 
%u %u\n", srec->uid[M], srec->uid[S], srec->flags );
-   debug( "  -> updated 
flags to %u\n", tmsg->flags );
-   }
if (srec->status != S_PENDING) {
debug( "  -> not too 
big any more\n" );
srec->status = 
S_PENDING;
@@ -1845,6 +1838,11 @@ msg_copied( int sts, uint uid, copy_vars_t *vars )
sync_rec_t *srec = vars->srec;
switch (sts) {
case SYNC_OK:
+   if (vars->msg->flags != srec->flags) {
+   srec->flags = vars->msg->flags;
+   debug( "  -> updated flags to %u\n", srec->flags );
+   jFprintf( svars, "* %u %u %u\n", srec->uid[M], 
srec->uid[S], srec->flags );
+   }
if (!uid) {  // Stored to a non-UIDPLUS mailbox
svars->state[t] |= ST_FIND_NEW;
} else {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: move state assignment to a more natural place

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 21179458385aa576da53cce7a0d88b9eaefddd91
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 13:36:15 2019 +0200

move state assignment to a more natural place

... so it's right next to the related callback assignment.

 src/socket.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/socket.c b/src/socket.c
index 84449e7..37fd318 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -299,6 +299,7 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void 
*aux ) )
static int ssl_inited;
 
conn->callbacks.starttls = cb;
+   conn->state = SCK_STARTTLS;
 
if (!ssl_inited) {
SSL_library_init();
@@ -329,7 +330,6 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void 
*aux ) )
}
SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
socket_expect_read( conn, 1 );
-   conn->state = SCK_STARTTLS;
start_tls_p2( conn );
 }
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: make find_uint_array() never create negative indices

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit e334eb3580923fc01451732ba9a3601036e9537c
Author: Oswald Buddenhagen 
Date:   Fri Nov 22 21:02:50 2019 +0100

make find_uint_array() never create negative indices

 src/util.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/util.c b/src/util.c
index 2a96389..93e6e7e 100644
--- a/src/util.c
+++ b/src/util.c
@@ -549,8 +549,8 @@ sort_uint_array( uint_array_t array )
 int
 find_uint_array( uint_array_t array, uint value )
 {
-   int bot = 0, top = array.size - 1;
-   while (bot <= top) {
+   int bot = 0, top = array.size;
+   while (bot < top) {
int i = (bot + top) / 2;
uint elt = array.data[i];
if (elt == value)
@@ -558,7 +558,7 @@ find_uint_array( uint_array_t array, uint value )
if (elt < value)
bot = i + 1;
else
-   top = i - 1;
+   top = i;
}
return 0;
 }


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: constness fixes

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit def22db09679c1570e82eeb9e6ad75f8bfcfeb53
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 21:13:28 2019 +0200

constness fixes

add missing const qualifications, and add "const cast" suppressions
where unavoidable.

 src/drv_maildir.c | 5 -
 src/main.c| 8 
 src/socket.c  | 5 -
 src/sync.c| 2 +-
 src/sync.h| 2 +-
 src/util.c| 2 +-
 6 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 777280d..bb98d3f 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -649,7 +649,10 @@ static void
 make_key( const char *info_stop, DBT *tkey, const char *name )
 {
char *u = strpbrk( name, info_stop );
+DIAG_PUSH
+DIAG_DISABLE("-Wcast-qual")  // C has no const_cast<> ...
tkey->data = (char *)name;
+DIAG_POP
tkey->size = u ? (size_t)(u - name) : strlen( name );
 }
 #endif /* USE_DB */
@@ -844,7 +847,7 @@ maildir_set_uid( maildir_store_t *ctx, const char *name, 
uint *uid )
 static int
 maildir_compare( const void *l, const void *r )
 {
-   msg_t *lm = (msg_t *)l, *rm = (msg_t *)r;
+   const msg_t *lm = (const msg_t *)l, *rm = (const msg_t *)r;
char *ldot, *rdot, *ldot2, *rdot2, *lseq, *rseq;
int ret, llen, rlen;
 
diff --git a/src/main.c b/src/main.c
index c2420ef..d8ea02f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -248,8 +248,8 @@ is_inbox( const char *name )
 static int
 cmp_box_names( const void *a, const void *b )
 {
-   const char *as = *(const char **)a;
-   const char *bs = *(const char **)b;
+   const char *as = *(const char * const *)a;
+   const char *bs = *(const char * const *)b;
int ai = is_inbox( as );
int bi = is_inbox( bs );
int di = bi - ai;
@@ -1087,14 +1087,14 @@ sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox )
if (!mvars->list) {
nfasprintf( >names[M], "%s%s", mpfx, mbox->name 
);
nfasprintf( >names[S], "%s%s", spfx, mbox->name 
);
-   sync_boxes( mvars->ctx, (const char **)mvars->names, 
mbox->present, mvars->chan, done_sync_2_dyn, mvars );
+   sync_boxes( mvars->ctx, (const char * const 
*)mvars->names, mbox->present, mvars->chan, done_sync_2_dyn, mvars );
return 1;
}
printf( "%s%s <=> %s%s\n", mpfx, mbox->name, spfx, mbox->name );
} else {
if (!mvars->list) {
mvars->names[M] = mvars->names[S] = mbox->name;
-   sync_boxes( mvars->ctx, (const char **)mvars->names, 
mbox->present, mvars->chan, done_sync, mvars );
+   sync_boxes( mvars->ctx, (const char * const 
*)mvars->names, mbox->present, mvars->chan, done_sync, mvars );
return 1;
}
puts( mbox->name );
diff --git a/src/socket.c b/src/socket.c
index bf09e5e..42385f0 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -232,7 +232,10 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock )
 static int
 init_ssl_ctx( const server_conf_t *conf )
 {
+DIAG_PUSH
+DIAG_DISABLE("-Wcast-qual")  // C has no 'mutable' or const_cast<> ...
server_conf_t *mconf = (server_conf_t *)conf;
+DIAG_POP
 
if (conf->SSLContext)
return conf->ssl_ctx_valid;
@@ -320,7 +323,7 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void 
*aux ) )
}
 
init_wakeup( >ssl_fake, ssl_fake_cb, conn );
-   if (!(conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext 
))) {
+   if (!(conn->ssl = SSL_new( ((server_conf_t const 
*)conn->conf)->SSLContext ))) {
print_ssl_errors( "initializing SSL connection" );
start_tls_p3( conn, 0 );
return;
diff --git a/src/sync.c b/src/sync.c
index cf788f0..4508ac1 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1002,7 +1002,7 @@ static void box_opened2( sync_vars_t *svars, int t );
 static void load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t 
mexcs );
 
 void
-sync_boxes( store_t *ctx[], const char *names[], int present[], channel_conf_t 
*chan,
+sync_boxes( store_t *ctx[], const char * const names[], int present[], 
channel_conf_t *chan,
 void (*cb)( int sts, void *aux ), void *aux )
 {
sync_vars_t *svars;
diff --git a/src/sync.h b/src/sync.h
index be26660..9b904c3 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -80,7 +80,7 @@ extern const char *str_ms[2], *str_hl[2];
 #define BOX_PRESENT   1
 
 /* All passed pointers must stay alive until cb is called. */
-void sync_boxes( store_t *ctx[], const char *names[], int present[], 
channel_conf_t *chan,
+void sync_boxes( store_t *ctx[], const char * const names[], int present[], 
channel_conf_t *chan,
  void (*cb)( int sts, void *aux ), void *aux );
 
 #endif
diff --git a/src/util.c b/src/util.c
index 878ee40..738254d 100644
--- 

[commit] master: consistently use NULL for null pointers

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 64e5f07ad3371fa5e10fc0ad715a68205f4effb7
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 20:50:31 2019 +0200

consistently use NULL for null pointers

makes the code noisier, but also somewhat more expressive.

 src/common.h |  4 +-
 src/config.c | 28 ++---
 src/drv_imap.c   | 94 ++--
 src/drv_maildir.c| 72 -
 src/drv_proxy_gen.pl |  2 +-
 src/main.c   | 32 +++
 src/mdconvert.c  | 12 +++---
 src/socket.c | 34 
 src/socket.h |  2 +-
 src/sync.c   | 10 ++---
 src/util.c   | 12 +++---
 11 files changed, 151 insertions(+), 151 deletions(-)

diff --git a/src/common.h b/src/common.h
index 548567f..c834cb1 100644
--- a/src/common.h
+++ b/src/common.h
@@ -191,7 +191,7 @@ int map_name( const char *arg, char **result, uint reserve, 
const char *in, cons
}
 
 #define ARRAY_INIT(arr) \
-   do { (arr)->array.data = 0; (arr)->array.size = (arr)->alloc = 0; } 
while (0)
+   do { (arr)->array.data = NULL; (arr)->array.size = (arr)->alloc = 0; } 
while (0)
 
 #define ARRAY_SQUEEZE(arr) \
do { \
@@ -245,7 +245,7 @@ typedef struct {
 void init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux );
 void conf_wakeup( wakeup_t *tmr, int timeout );
 void wipe_wakeup( wakeup_t *tmr );
-static INLINE int ATTR_UNUSED pending_wakeup( wakeup_t *tmr ) { return 
tmr->links.next != 0; }
+static INLINE int ATTR_UNUSED pending_wakeup( wakeup_t *tmr ) { return 
tmr->links.next != NULL; }
 
 void main_loop( void );
 
diff --git a/src/config.c b/src/config.c
index 8cb56c6..5ba3724 100644
--- a/src/config.c
+++ b/src/config.c
@@ -54,7 +54,7 @@ get_arg( conffile_t *cfile, int required, int *comment )
error( "%s:%d: parameter missing\n", cfile->file, 
cfile->line );
cfile->err = 1;
}
-   ret = 0;
+   ret = NULL;
} else {
for (escaped = 0, quoted = 0, ret = t = p; c; c = *p) {
p++;
@@ -74,12 +74,12 @@ get_arg( conffile_t *cfile, int required, int *comment )
if (escaped) {
error( "%s:%d: unterminated escape sequence\n", 
cfile->file, cfile->line );
cfile->err = 1;
-   ret = 0;
+   ret = NULL;
}
if (quoted) {
error( "%s:%d: missing closing quote\n", cfile->file, 
cfile->line );
cfile->err = 1;
-   ret = 0;
+   ret = NULL;
}
}
cfile->rest = p;
@@ -196,7 +196,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t 
*conf )
   cfile->file, cfile->line, arg );
cfile->err = 1;
}
-   while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
+   while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
conf->ops[M] |= XOP_HAVE_TYPE;
} else if (!strcasecmp( "SyncState", cfile->cmd ))
conf->sync_state = expand_strdup( cfile->val );
@@ -223,7 +223,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t 
*conf )
   cfile->file, 
cfile->line, boxOps[i].name, arg );
cfile->err = 1;
}
-   } while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 
)));
+   } while ((arg = get_arg( cfile, ARG_OPTIONAL, 
NULL )));
conf->ops[M] |= op * (XOP_HAVE_EXPUNGE / 
OP_EXPUNGE);
return 1;
}
@@ -239,7 +239,7 @@ getcline( conffile_t *cfile )
char *arg;
int comment;
 
-   if (cfile->rest && (arg = get_arg( cfile, ARG_OPTIONAL, 0 ))) {
+   if (cfile->rest && (arg = get_arg( cfile, ARG_OPTIONAL, NULL ))) {
error( "%s:%d: excess token '%s'\n", cfile->file, cfile->line, 
arg );
cfile->err = 1;
}
@@ -251,7 +251,7 @@ getcline( conffile_t *cfile )
continue;
return 1;
}
-   if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, 0 )))
+   if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, NULL )))
continue;
return 1;
}
@@ -343,7 +343,7 @@ load_config( const char *where, int pseudo )
cfile.bufl = sizeof(buf) - 1;
cfile.line = 0;
cfile.err = 0;
-   cfile.rest = 0;
+   cfile.rest = NULL;
 
gcops = 0;
global_conf.expire_unread = -1;
@@ -360,7 +360,7 @@ load_config( const char *where, int pseudo )

[commit] master: re-nest conditions in socket_fd_cb()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 8a03651dd8a40afd0ac520fc3e6dcd228db24ca3
Author: Oswald Buddenhagen 
Date:   Sat Nov 16 14:17:06 2019 +0100

re-nest conditions in socket_fd_cb()

conn->state == SCK_STARTTLS implies conn->ssl != NULL.

 src/socket.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/socket.c b/src/socket.c
index 37fd318..4e64515 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1063,11 +1063,11 @@ socket_fd_cb( int events, void *aux )
conf_wakeup( >fd_timeout, conn->conf->timeout );
 
 #ifdef HAVE_LIBSSL
-   if (conn->state == SCK_STARTTLS) {
-   start_tls_p2( conn );
-   return;
-   }
if (conn->ssl) {
+   if (conn->state == SCK_STARTTLS) {
+   start_tls_p2( conn );
+   return;
+   }
if (do_queued_write( conn ) < 0)
return;
socket_fill( conn );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-noise -Dd output somewhat

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c5d3565db5dd846dd33c380df0f62069f618db54
Author: Oswald Buddenhagen 
Date:   Fri Nov 22 20:10:15 2019 +0100

de-noise -Dd output somewhat

drop commas and left-align fields in message lists.

 src/drv_proxy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index 36463c6..cb59148 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -216,7 +216,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( 
@decl_cb_args@void *aux ), v
 //# DEFINE load_box_print_cb_args
if (sts == DRV_OK) {
for (message_t *msg = msgs; msg; msg = msg->next)
-   debug( "  uid=%5u, flags=%4s, size=%6d, tuid=%." 
stringify(TUIDL) "s\n",
+   debug( "  uid=%-5u flags=%-4s size=%-6d tuid=%." 
stringify(TUIDL) "s\n",
   msg->uid, (msg->status & M_FLAGS) ? 
(proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? 
msg->tuid : "?" );
}
 //# END
@@ -226,7 +226,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( 
@decl_cb_args@void *aux ), v
 //# DEFINE find_new_msgs_print_cb_args
if (sts == DRV_OK) {
for (message_t *msg = msgs; msg; msg = msg->next)
-   debug( "  uid=%5u, tuid=%." stringify(TUIDL) "s\n", 
msg->uid, msg->tuid );
+   debug( "  uid=%-5u tuid=%." stringify(TUIDL) "s\n", 
msg->uid, msg->tuid );
}
 //# END
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: don't leak the channel list after all

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 85688d1c1a6053041e49b959350ed585f8209b4a
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 22:42:42 2019 +0100

don't leak the channel list after all

unlike the actual configuration data, it's not kept in global variables,
so it shows up in memcheck.

amends 1de3ecd88.

 src/main.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index d505681..2b761c7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -973,7 +973,10 @@ sync_chans( main_vars_t *mvars, int ent )
chans_done++;
stats();
}
-   } while ((mvars->chanptr = mvars->chanptr->next));
+   chan_ent_t *nchan = mvars->chanptr->next;
+   free( mvars->chanptr );
+   mvars->chanptr = nchan;
+   } while (mvars->chanptr);
for (t = 0; t < N_DRIVERS; t++)
drivers[t]->cleanup();
 }


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: give the coverity build result archive a more descriptive name

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 30e166aa180cdfec3b9db91736b9ab9cda577fa7
Author: Oswald Buddenhagen 
Date:   Sun Nov 24 10:54:02 2019 +0100

give the coverity build result archive a more descriptive name

 Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 245299b..26de90a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,7 +59,7 @@ log:
 
 cov-scan: clean
/opt/cov-analysis-*/bin/cov-build --dir cov-int $(MAKE)
-   tar cavf isync.tar.xz cov-int
+   tar cavf isync-cov.tar.xz cov-int
 
 deb:
CFLAGS= INSTALL= dpkg-buildpackage -b --no-sign


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: show the right state file after idempotence test failure

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 50eab085091b06ce948a837206ee8a368738a97c
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 12:06:44 2019 +0100

autotest: show the right state file after idempotence test failure

amends efd72b85.

 src/run-tests.pl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 5a97bf8..b0d7311 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -730,7 +730,7 @@ sub test($$$@)
print "Expected result:\n";
printchan($tx);
print "Actual result:\n";
-   showchan("slave/.mbsyncstate");
+   showchan("slave/.mbsyncstate.new");
}
print "Debug output:\n";
print @nret;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-noise msg_copied() and flags_set() somewhat

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b677bfe7e530da38e135fab0c6e4309a9e0de201
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 12:31:10 2019 +0100

de-noise msg_copied() and flags_set() somewhat

assign temporary srec object instead of always spelling out the
indirection.

 src/sync.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 9bd963a..c9b362c 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1840,22 +1840,23 @@ static void
 msg_copied( int sts, uint uid, copy_vars_t *vars )
 {
SVARS_CHECK_CANCEL_RET;
+   sync_rec_t *srec = vars->srec;
switch (sts) {
case SYNC_OK:
if (!uid) {  // Stored to a non-UIDPLUS mailbox
svars->state[t] |= ST_FIND_NEW;
} else {
debug( "  -> new UID %u on %s\n", uid, str_ms[t] );
-   jFprintf( svars, "%c %u %u %u\n", "<>"[t], 
vars->srec->uid[M], vars->srec->uid[S], uid );
+   jFprintf( svars, "%c %u %u %u\n", "<>"[t], 
srec->uid[M], srec->uid[S], uid );
vars->srec->uid[t] = uid;
vars->srec->status &= ~S_PENDING;
vars->srec->tuid[0] = 0;
}
break;
case SYNC_NOGOOD:
-   debug( "  -> killing (%u,%u)\n", vars->srec->uid[M], 
vars->srec->uid[S] );
-   vars->srec->status = S_DEAD;
-   jFprintf( svars, "- %u %u\n", vars->srec->uid[M], 
vars->srec->uid[S] );
+   debug( "  -> killing (%u,%u)\n", srec->uid[M], srec->uid[S] );
+   srec->status = S_DEAD;
+   jFprintf( svars, "- %u %u\n", srec->uid[M], srec->uid[S] );
break;
default:
cancel_sync( svars );
@@ -1965,13 +1966,14 @@ static void
 flags_set( int sts, void *aux )
 {
SVARS_CHECK_RET_VARS(flag_vars_t);
+   sync_rec_t *srec = vars->srec;
switch (sts) {
case DRV_OK:
if (vars->aflags & F_DELETED)
-   vars->srec->wstate |= W_DEL(t);
+   srec->wstate |= W_DEL(t);
else if (vars->dflags & F_DELETED)
-   vars->srec->wstate &= ~W_DEL(t);
-   flags_set_p2( svars, vars->srec, t );
+   srec->wstate &= ~W_DEL(t);
+   flags_set_p2( svars, srec, t );
break;
}
free( vars );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: centralize "const cast" in make_key()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 01348f6f7c7df2da04fe2b890a1c708bd1aab7a1
Author: Oswald Buddenhagen 
Date:   Fri Nov 15 20:04:26 2019 +0100

centralize "const cast" in make_key()

 src/drv_maildir.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 3c987a5..9b42efc 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -646,10 +646,10 @@ maildir_validate( const char *box, int create, 
maildir_store_t *ctx )
 
 #ifdef USE_DB
 static void
-make_key( const char *info_stop, DBT *tkey, char *name )
+make_key( const char *info_stop, DBT *tkey, const char *name )
 {
char *u = strpbrk( name, info_stop );
-   tkey->data = name;
+   tkey->data = (char *)name;
tkey->size = u ? (size_t)(u - name) : strlen( name );
 }
 #endif /* USE_DB */
@@ -830,7 +830,7 @@ maildir_set_uid( maildir_store_t *ctx, const char *name, 
uint *uid )
return ret;
*uid = ++ctx->nuid;
 
-   make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, , 
(char *)name );
+   make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, , 
name );
value.data = uid;
value.size = sizeof(*uid);
if ((ret = ctx->db->put( ctx->db, 0, , , 0 ))) {
@@ -1737,7 +1737,7 @@ maildir_purge_msg( maildir_store_t *ctx, const char *name 
)
 
if ((ret = maildir_uidval_lock( ctx )) != DRV_OK)
return ret;
-   make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, , 
(char *)name );
+   make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, , 
name );
if ((ret = ctx->db->del( ctx->db, 0, , 0 ))) {
ctx->db->err( ctx->db, ret, "Maildir error: db->del()" );
return DRV_BOX_BAD;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: actually implement maildir_get_uidnext()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 83adb9a39ba36660a6643799550e3e3f61436100
Author: Oswald Buddenhagen 
Date:   Wed Jul 22 14:18:14 2020 +0200

actually implement maildir_get_uidnext()

the assumption was that this wouldn't be needed, as maildir_store_msg()
reliably delivers a UID. however, if we crash right before the callback
can record that UID, we'd still use OPEN_FIND in the next run, which
requires the saved next UID.

 src/drv_maildir.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 8d2d2a9..3c987a5 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1325,9 +1325,11 @@ maildir_open_box( store_t *gctx,
 }
 
 static int
-maildir_get_uidnext( store_t *gctx ATTR_UNUSED )
+maildir_get_uidnext( store_t *gctx )
 {
-   return 0;
+   maildir_store_t *ctx = (maildir_store_t *)gctx;
+
+   return ctx->nuid;
 }
 
 static xint


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: kill TODO item about killing INBOX

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 100475665918e5e8c5f58db76d918eba13a0bb02
Author: Oswald Buddenhagen 
Date:   Mon Sep 9 20:08:28 2019 +0200

kill TODO item about killing INBOX

while it's correct that mbsync doesn't strictly need to support both
Inbox and Path in a single Channel due to being able to Group Channels,
this "simplification" would have some undesirable effects:
- the concept is part of IMAP and provides a certain level of
  "zero-conf" (in particular via NAMESPACE). having to set up two Stores
  and associated Channels for one Account to reproduce this
  functionality would add quite some redundancy to common
  configurations.
- implementing MapInbox and move detection across Channels would add
  significant complexity.

one reason why one would want this change in the first place is to get
rid of the ambiguity of INBOX appearing right under Path. this could be
avoided by either using a different magic prefix that cannot appear in
actual mailbox names, or requiring a prefix for boxes inside path as
well. neither approach seems worth the effort, given that nesting
"INBOX" under Path causes problems for some other IMAP clients anyway.

 TODO | 6 --
 1 file changed, 6 deletions(-)

diff --git a/TODO b/TODO
index f8c6d73..66c9489 100644
--- a/TODO
+++ b/TODO
@@ -37,12 +37,6 @@ Patterns.
   function being missing so far
 - this is needed for move detection, which would work only within one Channel
 
-kill the concept of an INBOX, it is a relic from single-channel operation.
-if somebody needs it, he can have two stores with different Paths. the path
-can name a single (in-)box (curr. broken with maildir). an empty box name
-actually means empty, so the IMAP mailbox should use INBOX for Path (can't
-make that the default, as it would mess up the NAMESPACE).
-
 add regexp-based mailbox path rewriting to the drivers. user would provide
 expressions for both directions. every transformation would be immediately
 verified with the inverse transform. PathDelimiter and Flatten would become


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: create the temp dir in $TEMP

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit ef2caa074edfa0f6124aecead56e8253f047819c
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 11:59:05 2019 +0100

autotest: create the temp dir in $TEMP

on modern systems, this makes it likely to end up on tmpfs, which is a
lot faster and ssd-friendlier.

the symlink is not deleted at the end, to minimize fs churn. that means
it will be dangling after a reboot, which gets fixed in the next run.

 src/run-tests.pl | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 539ad80..3618db5 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -20,11 +20,16 @@ use warnings;
 use strict;
 use Cwd;
 use File::Path;
+use File::Temp 'tempdir';
 
 my $use_vg = $ENV{USE_VALGRIND};
 my $mbsync = getcwd()."/mbsync";
 
--d "tmp" or mkdir "tmp";
+if (!-d "tmp") {
+  unlink "tmp";
+  my $tdir = tempdir();
+  symlink $tdir, "tmp" or die "Cannot symlink temp directory: $!\n";
+}
 chdir "tmp" or die "Cannot enter temp direcory.\n";
 
 sub show($$$);
@@ -236,8 +241,6 @@ test("max messages + expunge", \@x50, \@X51, @O51);
 
 

 
-chdir "..";
-rmdir "tmp";
 print "OK.\n";
 exit 0;
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: Maildir: fix setting flags on messages without ":2, " part

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 38e7b4db2243e2bff7a6ae6ce2834acb0ba60286
Author: Oswald Buddenhagen 
Date:   Sun Jun 14 13:16:07 2020 +0200

Maildir: fix setting flags on messages without ":2," part

this is mostly hypothetical, as all messages i've encountered actually
have it even if no flags are set on them.

 src/drv_maildir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 3e67baf..c5c723c 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1716,7 +1716,7 @@ maildir_set_msg_flags( store_t *gctx, message_t *gmsg, 
uint uid ATTR_UNUSED, int
}
tl = ol + 3 + fl;
} else {
-   tl = ol + maildir_make_flags( conf->info_delimiter, 
msg->gen.flags, nbuf + bl + ol );
+   tl = ol + maildir_make_flags( conf->info_delimiter, 
(uchar)add, nbuf + bl + ol );
}
if (!rename( buf, nbuf ))
break;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: atomize & document conditions in load() exception list construction

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit abdca388f6f0200120e244220539803b1461df28
Author: Oswald Buddenhagen 
Date:   Tue Jul 7 21:14:59 2020 +0200

atomize & document conditions in load() exception list construction

 src/sync.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index c9b362c..9bc08b6 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1310,14 +1310,16 @@ box_opened2( sync_vars_t *svars, int t )
for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD)
continue;
-   if (!srec->uid[M])  // No message; other state 
is irrelevant
-   continue;
-   if (minwuid > srec->uid[M] && (!(svars->opts[M] 
& OPEN_NEW) || svars->maxuid[M] >= srec->uid[M])) {
-   if (!srec->uid[S] && !(srec->status & 
S_PENDING))  // Only actually paired up messages matter
-   continue;
-   /* The pair is alive, but outside the 
bulk range. */
-   *uint_array_append(  ) = 
srec->uid[M];
-   }
+   if (!srec->uid[M])
+   continue;  // No message; other state 
is irrelevant
+   if (srec->uid[M] >= minwuid)
+   continue;  // Message is in non-expired 
range
+   if ((svars->opts[M] & OPEN_NEW) && srec->uid[M] 
>= svars->maxuid[M])
+   continue;  // Message is in expired 
range, but new range overlaps that
+   if (!srec->uid[S] && !(srec->status & 
S_PENDING))
+   continue;  // Only actually paired up 
messages matter
+   // The pair is alive, but outside the bulk range
+   *uint_array_append(  ) = srec->uid[M];
}
sort_uint_array( mexcs.array );
} else {


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: re-order mailbox contents according to UIDs

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 6734b9ce7dbebb441bde80c1bd8ec43cc7973c1a
Author: Oswald Buddenhagen 
Date:   Fri Apr 3 10:43:19 2020 +0200

autotest: re-order mailbox contents according to UIDs

... instead of subjects, because that's way more natural and thus less
confusing.

 src/run-tests.pl | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 072f84e..8253399 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -57,7 +57,7 @@ my @X01 = (
  [ 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, 
"FT", 9, 9, "", 10, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 9, 10, "", 10, 9, "" ],
+   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 10, 9, "", 9, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, 
"FT", 0, 8, "", 10, 9, "", 9, 10, "" ],
 );
@@ -69,7 +69,7 @@ my @X02 = (
  [ 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 9, "", 10, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 10, "", 10, 9, "" ],
+   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
 );
@@ -81,7 +81,7 @@ my @X03 = (
  [ 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, 
"FT", 9, 9, "", 10, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 10, "", 10, 9, "" ],
+   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 
10, 9, "", 9, 10, "" ],
 );
@@ -93,7 +93,7 @@ my @X04 = (
  [ 9,
1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 9, 10, "", 10, 9, "" ],
+   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 10, 9, "", 9, 10, "" ],
  [ 9, 0, 0,
1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 
0, 8, "", 9, 10, "" ],
 );
@@ -129,7 +129,7 @@ my @X07 = (
  [ 10,
1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "", 10, 10, "" ],
  [ 10,
-   1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "", 9, 
10, "", 10, 9, "" ],
+   1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "", 10, 
9, "", 9, 10, "" ],
  [ 9, 0, 9,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, 
"", 10, 9, "", 9, 10, "" ],
 );
@@ -360,7 +360,7 @@ sub showbox($)
 
my ($mu, %ms) = readbox($bn);
my @MS = ($mu);
-   for my $uid (sort { $ms{$a}[0] <=> $ms{$b}[0] } keys %ms) {
+   for my $uid (sort { $a <=> $b } keys %ms) {
push @MS, $ms{$uid}[0], $uid, $ms{$uid}[1];
}
printbox($bn, @MS);


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: de-noise initialization of sync records

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 841f07efd006bbbd5855037eb95f63e18f303e07
Author: Oswald Buddenhagen 
Date:   Tue Dec 3 13:06:12 2019 +0100

de-noise initialization of sync records

use calloc() instead of malloc().

 src/sync.c | 25 -
 1 file changed, 4 insertions(+), 21 deletions(-)

diff --git a/src/sync.c b/src/sync.c
index 9aacfa5..9bd963a 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -781,7 +781,7 @@ load_state( sync_vars_t *svars )
error( "Error: invalid sync state entry at 
%s:%d\n", svars->dname, line );
goto jbail;
}
-   srec = nfmalloc( sizeof(*srec) );
+   srec = nfcalloc( sizeof(*srec) );
srec->uid[M] = t1;
srec->uid[S] = t2;
s = fbuf;
@@ -806,15 +806,10 @@ load_state( sync_vars_t *svars )
} else if (srec->uid[S] == (uint)-2) {
srec->uid[S] = 0;
srec->status = S_PENDING;
-   } else
-   srec->status = 0;
-   srec->wstate = 0;
+   }
srec->flags = parse_flags( s );
debug( "  entry (%u,%u,%u,%s)\n", srec->uid[M], 
srec->uid[S], srec->flags,
   (srec->status & S_SKIPPED) ? "SKIP" : 
(srec->status & S_PENDING) ? "FAIL" : (srec->status & S_EXPIRED) ? "XPIRE" : "" 
);
-   srec->msg[M] = srec->msg[S] = 0;
-   srec->tuid[0] = 0;
-   srec->next = 0;
*svars->srecadd = srec;
svars->srecadd = >next;
svars->nsrecs++;
@@ -908,7 +903,7 @@ load_state( sync_vars_t *svars )
svars->uidval[M] = t1;
svars->uidval[S] = t2;
} else if (c == '+') {
-   srec = nfmalloc( sizeof(*srec) );
+   srec = nfcalloc( sizeof(*srec) );
srec->uid[M] = t1;
srec->uid[S] = t2;
if (svars->newmaxuid[M] < t1)
@@ -916,12 +911,7 @@ load_state( sync_vars_t *svars )
if (svars->newmaxuid[S] < t2)
svars->newmaxuid[S] = t2;
debug( "  new entry(%u,%u)\n", t1, t2 );
-   srec->msg[M] = srec->msg[S] = 0;
srec->status = S_PENDING;
-   srec->wstate = 0;
-   srec->flags = 0;
-   srec->tuid[0] = 0;
-   srec->next = 0;
*svars->srecadd = srec;
svars->srecadd = >next;
svars->nsrecs++;
@@ -1534,7 +1524,6 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
del[S] = no[S] && srec->uid[S];
 
for (t = 0; t < 2; t++) {
-   srec->aflags[t] = srec->dflags[t] = 0;
if (srec->msg[t] && (srec->msg[t]->flags & 
F_DELETED))
srec->wstate |= W_DEL(t);
if (del[t]) {
@@ -1618,19 +1607,13 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
if (srec) {
debug( "  -> pair(%u,%u) 
exists\n", srec->uid[M], srec->uid[S] );
} else {
-   srec = nfmalloc( sizeof(*srec) 
);
-   srec->next = 0;
+   srec = nfcalloc( sizeof(*srec) 
);
*svars->srecadd = srec;
svars->srecadd = >next;
svars->nsrecs++;
srec->status = S_PENDING;
-   srec->wstate = 0;
-   srec->flags = 0;
-   srec->tuid[0] = 0;
srec->uid[1-t] = tmsg->uid;
-   srec->uid[t] = 0;
srec->msg[1-t] = tmsg;
-   

[commit] master: don't use reserved identifier pattern in stringify()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b885e0e03abf8f126154dbce89a06068e6f7ed3a
Author: Oswald Buddenhagen 
Date:   Sun Jul 28 22:31:41 2019 +0200

don't use reserved identifier pattern in stringify()

 src/common.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/common.h b/src/common.h
index d45929c..d52240e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -37,8 +37,8 @@ typedef unsigned long ulong;
 
 #define as(ar) (sizeof(ar)/sizeof(ar[0]))
 
-#define __stringify(x) #x
-#define stringify(x) __stringify(x)
+#define stringify__(x) #x
+#define stringify(x) stringify__(x)
 
 #define shifted_bit(in, from, to) \
(((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / from : 
1)) & to)


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: get rid of maildir_find_new_msgs() stub

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c84235b068220a02800aad01ad244fe215f05734
Author: Oswald Buddenhagen 
Date:   Tue Jul 21 17:16:24 2020 +0200

get rid of maildir_find_new_msgs() stub

a failed assertion isn't any better than a clean segfault with an
obvious backtrace.

 src/drv_maildir.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index c5c723c..8d2d2a9 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1669,13 +1669,6 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int 
to_trash,
cb( DRV_OK, uid, aux );
 }
 
-static void
-maildir_find_new_msgs( store_t *gctx ATTR_UNUSED, uint newuid ATTR_UNUSED,
-   void (*cb)( int sts, message_t *msgs, void *aux ) 
ATTR_UNUSED, void *aux ATTR_UNUSED )
-{
-   assert( !"maildir_find_new_msgs is not supposed to be called" );
-}
-
 static void
 maildir_set_msg_flags( store_t *gctx, message_t *gmsg, uint uid ATTR_UNUSED, 
int add, int del,
void (*cb)( int sts, void *aux ), void *aux )
@@ -1953,7 +1946,7 @@ struct driver maildir_driver = {
maildir_load_box,
maildir_fetch_msg,
maildir_store_msg,
-   maildir_find_new_msgs,
+   NULL,  // find_new_msgs
maildir_set_msg_flags,
maildir_trash_msg,
maildir_close_box,


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: use symbolic message subjects

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 406931bc45d1260cd4ea68ac26e1729e1649f8f8
Author: Oswald Buddenhagen 
Date:   Thu Apr 2 20:39:07 2020 +0200

autotest: use symbolic message subjects

... instead of numbers. otherwise there is too much confusion with UIDs.

 src/run-tests.pl | 73 +---
 1 file changed, 38 insertions(+), 35 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 8253399..3fd15b4 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -41,12 +41,15 @@ sub test($$$@);
 # master/slave: [ maxuid, { seq, uid, flags }... ]
 # state: [ MaxPulledUid, MaxExpiredMasterUid, MaxPushedUid, { muid, suid, 
flags }... ]
 
+use enum qw(:=1 A..Z);
+sub mn($) { chr(64 + shift) }
+
 # generic syncing tests
 my @x01 = (
  [ 9,
-   1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "" ],
+   A, 1, "F", B, 2, "", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "F", G, 7, 
"FT", I, 9, "" ],
  [ 9,
-   1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "", 10, 
9, "" ],
+   A, 1, "", B, 2, "F", C, 3, "F", D, 4, "", E, 5, "", G, 7, "", H, 8, "", J, 
9, "" ],
  [ 8, 0, 0,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, 
"" ],
 );
@@ -55,9 +58,9 @@ my @O01 = ("", "", "");
 #show("01", "01", "01");
 my @X01 = (
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, 
"FT", 9, 9, "", 10, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "FT", G, 7, 
"FT", I, 9, "", J, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 10, 9, "", 9, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", G, 7, "FT", H, 8, 
"T", J, 9, "", I, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, 
"FT", 0, 8, "", 10, 9, "", 9, 10, "" ],
 );
@@ -67,9 +70,9 @@ my @O02 = ("", "", "Expunge Both\n");
 #show("01", "02", "02");
 my @X02 = (
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 9, "", 10, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", I, 9, "", J, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", J, 9, "", I, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
 );
@@ -79,9 +82,9 @@ my @O03 = ("", "", "Expunge Slave\n");
 #show("01", "03", "03");
 my @X03 = (
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, 
"FT", 9, 9, "", 10, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "FT", G, 7, 
"FT", I, 9, "", J, 10, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", J, 9, "", I, 10, "" ],
  [ 9, 0, 9,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 
10, 9, "", 9, 10, "" ],
 );
@@ -91,9 +94,9 @@ my @O04 = ("", "", "Sync Pull\n");
 #show("01", "04", "04");
 my @X04 = (
  [ 9,
-   1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "" ],
+   A, 1, "F", B, 2, "", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "F", G, 7, 
"FT", I, 9, "" ],
  [ 10,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"T", 10, 9, "", 9, 10, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", G, 7, "FT", H, 8, 
"T", J, 9, "", I, 10, "" ],
  [ 9, 0, 0,
1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 
0, 8, "", 9, 10, "" ],
 );
@@ -103,9 +106,9 @@ my @O05 = ("", "", "Sync Flags\n");
 #show("01", "05", "05");
 my @X05 = (
  [ 9,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "F", G, 7, 
"FT", I, 9, "" ],
  [ 9,
-   1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, 
"", 10, 9, "" ],
+   A, 1, "F", B, 2, "F", C, 3, "FS", D, 4, "", E, 5, "T", G, 7, "FT", H, 8, 
"", J, 9, "" ],
  [ 8, 0, 0,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, 
"FT", 8, 8, "" ],
 );
@@ -115,9 +118,9 @@ my @O06 = ("", "", "Sync Delete\n");
 #show("01", "06", "06");
 my @X06 = (
  [ 9,
-   1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, 
"FT", 9, 9, "" ],
+   A, 1, "F", B, 2, "", C, 3, "FS", D, 4, "", E, 5, "T", F, 6, "FT", G, 7, 
"FT", I, 9, "" ],
  [ 9,
-   1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "T", 
10, 9, "" ],
+   A, 1, "", B, 2, "F", C, 3, "F", D, 4, "", E, 5, "", G, 7, "", H, 8, "T", J, 
9, "" ],
  [ 8, 0, 0,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 0, "", 7, 7, "", 0, 8, 
"" ],
 );
@@ -127,9 +130,9 @@ my @O07 = ("", "", "Sync New\n");
 #show("01", "07", "07");
 my @X07 = (
  [ 10,
-   1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, 
"FT", 9, 9, "", 10, 

[commit] master: don't leak box list from the command line

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 09d11245cde07fa7711cdb78b695a44e14f0fa38
Author: Oswald Buddenhagen 
Date:   Mon Nov 11 22:32:21 2019 +0100

don't leak box list from the command line

we also free the box list obtained from IMAP, so there isn't a real
reason not to do that for one from the command line.

amends 1de3ecd88.

 src/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main.c b/src/main.c
index d301e6f..d505681 100644
--- a/src/main.c
+++ b/src/main.c
@@ -959,7 +959,7 @@ sync_chans( main_vars_t *mvars, int ent )
mvars->skip = 1;
return;
}
-   if (mvars->chanptr->boxlist == 2) {
+   if (mvars->chanptr->boxlist) {
for (nmbox = mvars->chanptr->boxes; (mbox = nmbox); ) {
nmbox = mbox->next;
free( mbox->name );


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: assume that each message has a UID

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit b59ee239a4b7caa956c3912f2514318d4be333b8
Author: Oswald Buddenhagen 
Date:   Fri Apr 3 11:21:09 2020 +0200

autotest: assume that each message has a UID

followup to 7ce658d14.

 src/run-tests.pl | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index b0d7311..4c84ef5 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -329,8 +329,6 @@ sub readbox($)
my ($uid, $flg, $num);
if ($f =~ 
/^\d+\.\d+_\d+\.[-[:alnum:]]+,U=(\d+):2,(.*)$/) {
($uid, $flg) = ($1, $2);
-   } elsif ($f =~ 
/^\d+\.\d+_(\d+)\.[-[:alnum:]]+:2,(.*)$/) {
-   ($uid, $flg) = (0, $2);
} else {
print STDERR "unrecognided file name '$f' in 
'$bn'.\n";
exit 1;
@@ -453,13 +451,8 @@ sub mkbox($$@)
close FILE;
while (@ms) {
my ($num, $uid, $flg) = (shift @ms, shift @ms, shift @ms);
-   if ($uid) {
-   $uid = ",U=".$uid;
-   } else {
-   $uid = "";
-   }
my $big = $flg =~ s/\*//;
-   open(FILE, ">", $bn."/".($flg =~ /S/ ? "cur" : 
"new")."/0.1_".$num.".local".$uid.":2,".$flg) or
+   open(FILE, ">", $bn."/".($flg =~ /S/ ? "cur" : 
"new")."/0.1_".$num.".local,U=".$uid.":2,".$flg) or
die "Cannot create message $num in mailbox $bn.\n";
print FILE "From: foo\nTo: bar\nDate: Thu, 1 Jan 1970 00:00:00 
+\nSubject: $num\n\n".(("A"x50)."\n")x($big*30);
close FILE;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: re-organize mailbox storage by UID

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit f3629c69e1b098cc0ef475dbc915e9f958df90cf
Author: Oswald Buddenhagen 
Date:   Fri Apr 3 12:18:26 2020 +0200

autotest: re-organize mailbox storage by UID

an effect of 7ce658d is that we can index messages by UID rather than
content (or more specifically, subject). apart from being cleaner, it
allows duplicated subjects.

 src/run-tests.pl | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 4c84ef5..072f84e 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -344,7 +344,7 @@ sub readbox($)
print STDERR "message '$f' in '$bn' has no 
identifier.\n";
exit 1;
}
-   @{ $ms{$num} } = ($uid, $flg.($sz>1000?"*":""));
+   @{ $ms{$uid} } = ($num, $flg.($sz>1000?"*":""));
}
}
return ($mu, %ms);
@@ -360,8 +360,8 @@ sub showbox($)
 
my ($mu, %ms) = readbox($bn);
my @MS = ($mu);
-   for my $num (sort { $a <=> $b } keys %ms) {
-   push @MS, $num, $ms{$num}[0], $ms{$num}[1];
+   for my $uid (sort { $ms{$a}[0] <=> $ms{$b}[0] } keys %ms) {
+   push @MS, $ms{$uid}[0], $uid, $ms{$uid}[1];
}
printbox($bn, @MS);
 }
@@ -487,19 +487,19 @@ sub ckbox($$@)
}
while (@MS) {
my ($num, $uid, $flg) = (shift @MS, shift @MS, shift @MS);
-   if (!defined $ms{$num}) {
-   print STDERR "No message $bn:$num.\n";
+   my $m = delete $ms{$uid};
+   if (!defined $m) {
+   print STDERR "No message $bn:$uid.\n";
return 1;
}
-   if ($ms{$num}[0] ne $uid) {
-   print STDERR "UID mismatch for $bn:$num.\n";
+   if ($$m[0] ne $num) {
+   print STDERR "Subject mismatch for $bn:$uid.\n";
return 1;
}
-   if ($ms{$num}[1] ne $flg) {
-   print STDERR "Flag mismatch for $bn:$num.\n";
+   if ($$m[1] ne $flg) {
+   print STDERR "Flag mismatch for $bn:$uid.\n";
return 1;
}
-   delete $ms{$num};
}
if (%ms) {
print STDERR "Excess messages in '$bn': ".join(", ", sort({$a 
<=> $b } keys(%ms))).".\n";


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: autotest: fix prototype of ckbox()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit d59392e9010714ca3aaf8ac21840f14ba712c384
Author: Oswald Buddenhagen 
Date:   Sun Dec 29 11:59:47 2019 +0100

autotest: fix prototype of ckbox()

 src/run-tests.pl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 3618db5..5a97bf8 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -482,8 +482,8 @@ sub mkchan($$@)
close FILE;
 }
 
-# $config, $boxname, $maxuid, @msgs
-sub ckbox($$$@)
+# $boxname, $maxuid, @msgs
+sub ckbox($$@)
 {
my ($bn, $MU, @MS) = @_;
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] tag 'v1.3.3' created

2020-08-04 Thread Oswald Buddenhagen via isync-devel
The tag 'v1.3.3' has been created at c97e650.


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] master: Merge branch '1.3'

2020-08-04 Thread Oswald Buddenhagen via isync-devel
Skipped 7 existing revision(s) on branch 'master'.

commit 5fee222f8408d5dd82b40d53c663b8ceffa13914
Merge: cab1460 c97e650
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 14:48:58 2020 +0200

Merge branch '1.3'

 src/drv_imap.c  | 17 ++--
 src/drv_proxy.c |  4 +++-
 src/mbsync.1| 32 +++--
 src/socket.c| 54 +++--
 src/socket.h|  2 +-
 5 files changed, 61 insertions(+), 48 deletions(-)


= Full diff against 1st parent =

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 8d2ebf5..7eeff82 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1586,14 +1586,6 @@ get_cmd_result_p2( imap_store_t *ctx, imap_cmd_t *cmd, 
int response )
 
 /*** imap_cancel_store ***/
 
-
-static void
-imap_cleanup_store( imap_store_t *ctx )
-{
-   free_generic_messages( ctx->msgs );
-   free_string_list( ctx->boxes );
-}
-
 static void
 imap_cancel_store( store_t *gctx )
 {
@@ -1609,7 +1601,8 @@ imap_cancel_store( store_t *gctx )
free_list( ctx->ns_other );
free_list( ctx->ns_shared );
free_string_list( ctx->auth_mechs );
-   imap_cleanup_store( ctx );
+   free_generic_messages( ctx->msgs );
+   free_string_list( ctx->boxes );
imap_deref( ctx );
 }
 
@@ -1746,7 +1739,9 @@ imap_alloc_store( store_conf_t *conf, const char *label )
for (ctxp =  (ctx = (imap_store_t *)*ctxp); ctxp = 
>gen.next)
if (ctx->state != SST_BAD && ((imap_store_conf_t 
*)ctx->gen.conf)->server == srvc) {
*ctxp = ctx->gen.next;
-   imap_cleanup_store( ctx );
+   free_string_list( ctx->boxes );
+   ctx->boxes = NULL;
+   ctx->listed = 0;
/* One could ping the server here, but given that the 
idle timeout
 * is at least 30 minutes, this sounds pretty 
pointless. */
ctx->state = SST_HALF;
@@ -1921,7 +1916,7 @@ ensure_password( imap_server_conf_t *srvc )
if (cmd) {
FILE *fp;
int ret;
-   char buffer[2048];  // Hopefully more than enough room for 
XOAUTH2, etc. tokens
+   char buffer[8192];  // Hopefully more than enough room for 
XOAUTH2, etc. tokens
 
if (*cmd == '+') {
flushn();
diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index 2ef928a..7250293 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -309,9 +309,11 @@ proxy_set_bad_callback( store_t *gctx, void (*cb)( void 
*aux ), void *aux )
 static void
 proxy_invoke_bad_callback( proxy_store_t *ctx )
 {
+   ctx->ref_count++;
debug( "%sCallback enter bad store\n", ctx->label );
ctx->bad_callback( ctx->bad_callback_aux );
-   debug( "%sCallback leave bad store\n", ctx->label ); \
+   debug( "%sCallback leave bad store\n", ctx->label );
+   proxy_store_deref( ctx );
 }
 
 //# EXCLUDE alloc_store
diff --git a/src/mbsync.1 b/src/mbsync.1
index 171727f..c8c8736 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -379,17 +379,27 @@ if you want to trust only hand-picked certificates.
 \fBCertificateFile\fR \fIpath\fR
 File containing additional X.509 certificates used to verify server
 identities.
-These certificates are always trusted, regardless of validity.
-.br
-The certificates from this file are matched only against the received
-server certificate itself; CA certificates are \fBnot\fR supported here.
-Do \fBnot\fR specify the system's CA certificate store here; see
-\fBSystemCertificates\fR instead.
-.br
-The contents for this file may be obtained using the
-\fBmbsync-get-cert\fR tool; make sure to verify the fingerprints of the
-certificates before trusting them, or transfer them securely from the
-server's network (if it is trusted).
+It may contain two types of certificates:
+.RS
+.IP Host
+These certificates are matched only against the received server certificate
+itself.
+They are always trusted, regardless of validity.
+A typical use case would be forcing acceptance of an expired certificate.
+.br
+These certificates may be obtained using the \fBmbsync-get-cert\fR tool;
+make sure to verify their fingerprints before trusting them, or transfer
+them securely from the server's network (if it can be trusted beyond the
+server itself).
+.IP CA
+These certificates are used as trust anchors when building the certificate
+chain for the received server certificate.
+They are used to supplant or supersede the system's trust store, depending
+on the \fBSystemCertificates\fR setting;
+it is not necessary and not recommended to specify the system's trust store
+itself here.
+The trust chains are fully validated.
+.RE
 .
 .TP
 \fBClientCertificate\fR \fIpath\fR
diff --git a/src/socket.c b/src/socket.c
index dbd781c..84449e7 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -41,7 +41,7 @@
 # include 
 # include 
 

[commit] 1.3: don't crash in proxy_invoke_bad_callback()

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c82397cf6e6c3c89b3b5bce6836bf17208abae70
Author: Oswald Buddenhagen 
Date:   Mon Aug 3 12:39:33 2020 +0200

don't crash in proxy_invoke_bad_callback()

we need to hold a ref to the proxy store, as after the bad_callback()
it's otherwise likely gone.

 src/drv_proxy.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/drv_proxy.c b/src/drv_proxy.c
index 6a62f22..1188f1f 100644
--- a/src/drv_proxy.c
+++ b/src/drv_proxy.c
@@ -306,9 +306,11 @@ proxy_set_bad_callback( store_t *gctx, void (*cb)( void 
*aux ), void *aux )
 static void
 proxy_invoke_bad_callback( proxy_store_t *ctx )
 {
+   ctx->ref_count++;
debug( "%sCallback enter bad store\n", ctx->label );
ctx->bad_callback( ctx->bad_callback_aux );
-   debug( "%sCallback leave bad store\n", ctx->label ); \
+   debug( "%sCallback leave bad store\n", ctx->label );
+   proxy_store_deref( ctx );
 }
 
 //# EXCLUDE alloc_store


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: increase PassCmd output buffer even more

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 3651c30296cbe8995b8a9c1c839088fa03778540
Author: Oswald Buddenhagen 
Date:   Tue Jul 28 00:28:11 2020 +0200

increase PassCmd output buffer even more

apparently, some XOAUTH2 tokens are at 2.4K already, so make it 8K to be
*really* safe for a while.

REFMAIL: <20200716000515.ga2111...@lysator.liu.se>

 src/drv_imap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4ea86d6..d429bcb 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1893,7 +1893,7 @@ ensure_password( imap_server_conf_t *srvc )
if (cmd) {
FILE *fp;
int ret;
-   char buffer[2048];  // Hopefully more than enough room for 
XOAUTH2, etc. tokens
+   char buffer[8192];  // Hopefully more than enough room for 
XOAUTH2, etc. tokens
 
if (*cmd == '+') {
flushn();


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: fix version comparison in LibreSSL conditional

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 30261fe6f17b24bd57008ffde9650cd1a13d9cbd
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 11:17:56 2020 +0200

fix version comparison in LibreSSL conditional

the operator was exactly inverted. that means that it actually wouldn't
compile with both older versions (that needed the aliases) and
potentially new versions (that will hide the data members - still not
the case as of 3.2).

amends 8a40554f0.

 src/socket.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/socket.c b/src/socket.c
index 6078f99..84449e7 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -41,7 +41,7 @@
 # include 
 # include 
 # if OPENSSL_VERSION_NUMBER < 0x1010L \
-   || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 
0x2070100fL)
+   || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 
0x2070100fL)
 #  define X509_OBJECT_get0_X509(o) ((o)->data.x509)
 #  define X509_STORE_get0_objects(o) ((o)->objs)
 # endif


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: unbreak CertificateFile documentation

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 09540b5648aecd1bd2e29db0b6201ca71381a058
Author: Oswald Buddenhagen 
Date:   Sun Aug 2 20:05:42 2020 +0200

unbreak CertificateFile documentation

the file may in fact contain CA certs.

amends 7d9d3e15.

 src/mbsync.1 | 32 +---
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/mbsync.1 b/src/mbsync.1
index 6830508..dfdba79 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -379,17 +379,27 @@ if you want to trust only hand-picked certificates.
 \fBCertificateFile\fR \fIpath\fR
 File containing additional X.509 certificates used to verify server
 identities.
-These certificates are always trusted, regardless of validity.
-.br
-The certificates from this file are matched only against the received
-server certificate itself; CA certificates are \fBnot\fR supported here.
-Do \fBnot\fR specify the system's CA certificate store here; see
-\fBSystemCertificates\fR instead.
-.br
-The contents for this file may be obtained using the
-\fBmbsync-get-cert\fR tool; make sure to verify the fingerprints of the
-certificates before trusting them, or transfer them securely from the
-server's network (if it is trusted).
+It may contain two types of certificates:
+.RS
+.IP Host
+These certificates are matched only against the received server certificate
+itself.
+They are always trusted, regardless of validity.
+A typical use case would be forcing acceptance of an expired certificate.
+.br
+These certificates may be obtained using the \fBmbsync-get-cert\fR tool;
+make sure to verify their fingerprints before trusting them, or transfer
+them securely from the server's network (if it can be trusted beyond the
+server itself).
+.IP CA
+These certificates are used as trust anchors when building the certificate
+chain for the received server certificate.
+They are used to supplant or supersede the system's trust store, depending
+on the \fBSystemCertificates\fR setting;
+it is not necessary and not recommended to specify the system's trust store
+itself here.
+The trust chains are fully validated.
+.RE
 .
 .TP
 \fBClientCertificate\fR \fIpath\fR


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: fix re-using server connections for new stores

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 542e38dd49b4ac0ecf96637be289b6e71ac84990
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 10:10:47 2020 +0200

fix re-using server connections for new stores

we failed to reset the box list pointer after freeing it, which would
lead to a crash.
we also failed to reset the listing status, which would lead to
malfunction if we hadn't already crashed.

this inlines imap_cleanup_store(), as there isn't much value in keeping
it. the message list is already freed when disowning the store anyway.

 src/drv_imap.c | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index d429bcb..fbf3072 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -1558,14 +1558,6 @@ get_cmd_result_p2( imap_store_t *ctx, imap_cmd_t *cmd, 
int response )
 
 /*** imap_cancel_store ***/
 
-
-static void
-imap_cleanup_store( imap_store_t *ctx )
-{
-   free_generic_messages( ctx->msgs );
-   free_string_list( ctx->boxes );
-}
-
 static void
 imap_cancel_store( store_t *gctx )
 {
@@ -1581,7 +1573,8 @@ imap_cancel_store( store_t *gctx )
free_list( ctx->ns_other );
free_list( ctx->ns_shared );
free_string_list( ctx->auth_mechs );
-   imap_cleanup_store( ctx );
+   free_generic_messages( ctx->msgs );
+   free_string_list( ctx->boxes );
imap_deref( ctx );
 }
 
@@ -1718,7 +1711,9 @@ imap_alloc_store( store_conf_t *conf, const char *label )
for (ctxp =  (ctx = (imap_store_t *)*ctxp); ctxp = 
>gen.next)
if (ctx->state != SST_BAD && ((imap_store_conf_t 
*)ctx->gen.conf)->server == srvc) {
*ctxp = ctx->gen.next;
-   imap_cleanup_store( ctx );
+   free_string_list( ctx->boxes );
+   ctx->boxes = NULL;
+   ctx->listed = 0;
/* One could ping the server here, but given that the 
idle timeout
 * is at least 30 minutes, this sounds pretty 
pointless. */
ctx->state = SST_HALF;


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: fix simultaneously connecting to multiple hosts in non-IPv6 builds

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit 813ad67c5664019d198b5c0832c10142a20f2793
Author: Oswald Buddenhagen 
Date:   Mon Jul 27 22:48:41 2020 +0200

fix simultaneously connecting to multiple hosts in non-IPv6 builds

we need to deep-copy the struct hostent data, as otherwise the
concurrent connects will overwrite each other's lookup results.

this is a rather hypothetical fix, as the bug currently affects only
channels connecting two IMAP accounts, and only if the first host's
first address asynchronously fails to connect.

 src/socket.c | 52 +---
 src/socket.h |  2 +-
 2 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/src/socket.c b/src/socket.c
index dbd781c..6078f99 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -430,6 +430,32 @@ socket_close_internal( conn_t *sock )
sock->fd = -1;
 }
 
+#ifndef HAVE_IPV6
+struct addr_info {
+   struct addr_info *ai_next;
+   struct sockaddr_in ai_addr[1];
+};
+
+#define freeaddrinfo(ai) free( ai )
+
+static struct addr_info *
+init_addrinfo( struct hostent *he )
+{
+   uint naddr = 0;
+   for (char **addr = he->h_addr_list; *addr; addr++)
+   naddr++;
+   struct addr_info *caddr = nfcalloc( naddr * sizeof(struct addrinfo) );
+   struct addr_info *ret, **caddrp = 
+   for (char **addr = he->h_addr_list; *addr; addr++, caddr++) {
+   caddr->ai_addr->sin_family = AF_INET;
+   memcpy( >ai_addr->sin_addr.s_addr, *addr, sizeof(struct 
in_addr) );
+   *caddrp = caddr;
+   caddrp = >ai_next;
+   }
+   return ret;
+}
+#endif
+
 void
 socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
 {
@@ -479,8 +505,6 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux 
) )
return;
}
info( "\vok\n" );
-
-   sock->curr_addr = sock->addrs;
 #else
struct hostent *he;
 
@@ -493,8 +517,9 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux 
) )
}
info( "\vok\n" );
 
-   sock->curr_addr = he->h_addr_list;
+   sock->addrs = init_addrinfo( he );
 #endif
+   sock->curr_addr = sock->addrs;
socket_connect_one( sock );
}
 }
@@ -506,16 +531,10 @@ socket_connect_one( conn_t *sock )
 #ifdef HAVE_IPV6
struct addrinfo *ai;
 #else
-   struct {
-   struct sockaddr_in ai_addr[1];
-   } ai[1];
+   struct addr_info *ai;
 #endif
 
-#ifdef HAVE_IPV6
if (!(ai = sock->curr_addr)) {
-#else
-   if (!*sock->curr_addr) {
-#endif
error( "No working address found for %s\n", sock->conf->host );
socket_connect_bail( sock );
return;
@@ -532,11 +551,6 @@ socket_connect_one( conn_t *sock )
 #endif
{
struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
-#ifndef HAVE_IPV6
-   memset( in, 0, sizeof(*in) );
-   in->sin_family = AF_INET;
-   in->sin_addr.s_addr = *((int *)*sock->curr_addr);
-#endif
in->sin_port = htons( sock->conf->port );
nfasprintf( >name, "%s (%s:%hu)",
sock->conf->host, inet_ntoa( in->sin_addr ), 
sock->conf->port );
@@ -579,11 +593,7 @@ socket_connect_next( conn_t *conn )
sys_error( "Cannot connect to %s", conn->name );
free( conn->name );
conn->name = 0;
-#ifdef HAVE_IPV6
conn->curr_addr = conn->curr_addr->ai_next;
-#else
-   conn->curr_addr++;
-#endif
socket_connect_one( conn );
 }
 
@@ -597,12 +607,10 @@ socket_connect_failed( conn_t *conn )
 static void
 socket_connected( conn_t *conn )
 {
-#ifdef HAVE_IPV6
if (conn->addrs) {
freeaddrinfo( conn->addrs );
conn->addrs = 0;
}
-#endif
conf_notifier( >notify, 0, POLLIN );
socket_expect_read( conn, 0 );
conn->state = SCK_READY;
@@ -612,12 +620,10 @@ socket_connected( conn_t *conn )
 static void
 socket_cleanup_names( conn_t *conn )
 {
-#ifdef HAVE_IPV6
if (conn->addrs) {
freeaddrinfo( conn->addrs );
conn->addrs = 0;
}
-#endif
free( conn->name );
conn->name = 0;
 }
diff --git a/src/socket.h b/src/socket.h
index f80c2ef..1fdd7aa 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -73,7 +73,7 @@ typedef struct {
 #ifdef HAVE_IPV6
struct addrinfo *addrs, *curr_addr; /* needed during connect */
 #else
-   char **curr_addr; /* needed during connect */
+   struct addr_info *addrs, *curr_addr; /* needed during connect */
 #endif
char *name;
 #ifdef HAVE_LIBSSL


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel


[commit] 1.3: bump version

2020-08-04 Thread Oswald Buddenhagen via isync-devel
commit c97e650c241536b5fafcccd138428d1c7a22cdd7
Author: Oswald Buddenhagen 
Date:   Tue Aug 4 14:44:17 2020 +0200

bump version

 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index ca3ee33..188d712 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([isync], [1.3.2])
+AC_INIT([isync], [1.3.3])
 AC_CONFIG_HEADERS([autodefs.h])
 AM_INIT_AUTOMAKE
 


___
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel