[commit] 1.3: fix simultaneously connecting to multiple hosts in non-IPv6 builds
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 = &ret; + for (char **addr = he->h_addr_list; *addr; addr++, caddr++) { + caddr->ai_addr->sin_family = AF_INET; + memcpy( &caddr->ai_addr->sin_addr.s_addr, *addr, sizeof(struct in_addr) ); + *caddrp = caddr; + caddrp = &caddr->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( &sock->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( &conn->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
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
[commit] 1.3: fix re-using server connections for new stores
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 = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->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: don't crash in proxy_invoke_bad_callback()
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
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
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
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] master: Merge branch '1.3'
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 = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->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
[commit] tag 'v1.3.3' created
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: autotest: fix prototype of ckbox()
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] master: get rid of maildir_find_new_msgs() stub
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: don't use reserved identifier pattern in stringify()
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: autotest: re-organize mailbox storage by UID
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: use symbolic message subjects
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, 10,
[commit] master: don't leak box list from the command line
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
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-order mailbox contents according to UIDs
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
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 = &srec->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 = &srec->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 = &srec->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: actually implement maildir_get_uidnext()
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: autotest: show the right state file after idempotence test failure
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
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: re-nest conditions in socket_fd_cb()
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( &conn->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
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
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: kill TODO item about killing INBOX
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
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
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: centralize "const cast" in make_key()
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, &key, (char *)name ); + make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, &key, name ); value.data = uid; value.size = sizeof(*uid); if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 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, &key, (char *)name ); + make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, &key, name ); if ((ret = ctx->db->del( ctx->db, 0, &key, 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: give the coverity build result archive a more descriptive name
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: atomize & document conditions in load() exception list construction
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( &mexcs ) = 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( &mexcs ) = 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: make find_uint_array() never create negative indices
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
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( &mvars->names[M], "%s%s", mpfx, mbox->name ); nfasprintf( &mvars->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( &conn->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..73
[commit] master: consistently use NULL for null pointers
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: modernize list of gcc warning flags somewhat
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: remove support for SSLv3
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
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 = &srec->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
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( &data->date ) ); +DIAG_PUSH +DIAG_DISABLE("-Wformat") + strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z", localtime( &data->date ) ); +DIAG_POP imap_exec( ctx, &cmd->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
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, + &password_length, &password_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
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( &buf, ctx ) < 0) { - cb( DRV_BOX_BAD, -1, aux ); + cb( DRV_BOX_BAD, 0, aux ); return; } } else { if (prepare_box( &buf, 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_var
[commit] master: make more objects static
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 = &servers; +static imap_server_conf_t *servers, **serverapp = &servers; 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
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 @@ box_load
[commit] master: fix loading of some messages' sizes in some partial sync scenarios
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, &nranges, 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, &nranges, 0, WantTuids, newuid - 1 ); + imap_set_range( ranges, &nranges, 0, WantTuids, finduid - 1 ); if (ctx->opts & OPEN_OLD_IDS) - imap_set_range( ranges, &nranges, WantMsgids, 0, seenuid ); + imap_set_range( ranges, &nranges, 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,
[commit] master: handle bogus IMAP FETCH responses more robustly
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
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()
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, &mask, &status )) +
[commit] master: shrink some data at the source to avoid subsequent narrowing
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
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, &p, 10); + ret = strtoul( cfile->val, &p, 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 = &groups; 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( &cfile, &store )) { if (store) {
[commit] master: de-duplicate updating of uid in sync records
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
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) || ((vo
[commit] master: sanitize error handling in IMAP FETCH response processing
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, &ep, 10 ), *ep)) + if (!is_atom( tmp ) || (uid = strtoul( tmp->val, &ep, 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, &ep, 10 ), *ep)) + if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 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()
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 = &cmd->next; ctx->num_in_progress++; - socket_expect_read( &ctx->conn, 1 ); + socket_expect_activity( &ctx->conn, 1 ); } static int @@ -409,7 +409,7 @@ cancel_sent_imap_cmds( imap_store_t *ctx ) { imap_cmd_t *cmd; - socket_expect_read( &ctx->conn, 0 ); + socket_expect_activity( &ctx->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( &ctx->conn, 0 ); + socket_expect_activity( &ctx->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( &ctx->conn, 1 ); + socket_expect_activity( &ctx->conn, 1 ); } else { tag = atoi( arg ); for (pcmdp = &ctx->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->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( &ctx->conn, 0 ); + socket_expect_activity( &ctx->conn, 0 ); arg = next_arg( &cmd ); if (!arg) { error( "IMAP error: malformed tagged response\n" ); @@ -1798,7 +1798,7 @@ imap_open_store_connected( int ok, void *aux ) socket_start_tls( &ctx->conn, imap_open_store_tlsstarted1 ); #endif else - socket_expect_read( &ctx->conn, 1 ); + socket_expect_activity( &ctx->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( &ctx->conn, 1 ); + socket_expect_activity( &ctx->conn, 1 ); } #endif static void imap_open_store_greeted( imap_store_t *ctx ) { - socket_expect_read( &ctx->conn, 0 ); + socket_expect_activity( &ctx->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( &sock->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( &conn->notify, 0, POLLIN ); - socket_expect_read( conn, 0 ); + socket_expect_activi
[commit] master: set sync record's flags only after propagating new message
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
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: Add support for specifying cipher string used for ssl connection
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
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
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
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 = n
[commit] master: don't forget to skip dead messages on far side during expiration
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: drop redundant conn->writing member
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( &conn->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( &conn->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: rewrite nonsensical struct packing magic
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 &arr->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
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, &ep, 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, &mask, &status )) 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, &ep, 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
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; + server->sconf.ssl_version
[commit] master: make some narrowing of integers explicit
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: do away with newmaxuid
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 "4
[commit] master: fully decompose NAMESPACE response early on
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( &ctx->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
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: re-nest conditions for syncing new messages
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] & OP_EXPUN
[commit] master: extract parse_fetched_header() from parse_fetch_rsp()
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
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( &sts->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( &sts->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
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()
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 = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next) if (ctx->state == SST_GOOD && ctx->gen.conf == conf) { *ctxp = ctx->gen.next; - ctx->label = label; - return &ctx->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 &ctx->gen; } ___ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel
[commit] master: centralize disposal of parsed IMAP lists
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()
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, &ep, 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, &mask, &status )) - 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, &ep, 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, &tuid, &msgid ); - } 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, &ep, 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; + } +
[commit] master: use more appropriate return value in driver_t::select_box()
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
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: don't rewrite state gratuitously
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
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, &ep, 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
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, &nranges, 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, &nranges, 0, WantSize, newuid ); if (ctx->opts & OPEN_FIND) imap_set_range( ranges, &nranges, 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)(
[commit] master: add some ATTR_* (mostly)
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: add/fix/de-duplicate comments
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", &svars->uidval[F], &svars->maxuid[F] ) < 2 || sscanf( buf2, "%u:%u:%u", &svars->uidval[N], &maxxnuid, &svars->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, "MaxExpir
[commit] master: deprecate master/slave terminology
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: actually implement imap_commit_cmds()
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 = &ctx->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 = &cmdp->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( &ctx->sasl ); #endif socket_close( &ctx->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 = &ctx->in_progress; ctx->pending_app
[commit] master: handle CertificateFile more cleanly
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: don't unnecessarily re-initialize some members of imap_store
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 = &imap_driver; + ctx->ref_count = 1; socket_init( &ctx->conn, &srvc->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 = &ctx->wait_check; gotsrv: - ctx->gen.driver = &imap_driver; ctx->gen.conf = conf; ctx->label = label; - ctx->ref_count = 1; return &ctx->gen; } ___ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel
[commit] branch 'wip/master-next' reset
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
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
beta testing for 1.4 release; short-term roadmap
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
[PATCH] add support for built-in oauthbearer auth mechanism
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, "", " ", "
Re: [PATCH] add support for built-in oauthbearer auth mechanism
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