[commit] master: Merge branch '1.3'
Skipped 2 existing revision(s) on branch 'master'. commit 062706fcbf39bcee536ea4b5c690e2f30e122faa Merge: fc300fd e4eac03 Author: Oswald Buddenhagen Date: Wed Feb 3 15:53:05 2021 +0100 Merge branch '1.3' Conflicts: configure.ac src/drv_imap.c src/drv_imap.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --cc src/drv_imap.c index 8d7c99b,810479e..9f23e08 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@@ -1381,14 -1266,16 +1381,15 @@@ parse_list_rsp_p2( imap_store_t *ctx, l return LIST_BAD; } arg = list->val; - argl = list->len; + argl = (int)list->len; - if (is_inbox( ctx, arg, argl )) { - // The server might be weird and have a non-uppercase INBOX. It - // may legitimately do so, but we need the canonical spelling. - memcpy( arg, "INBOX", 5 ); - } else if ((l = strlen( ctx->prefix ))) { - if (!starts_with( arg, argl, ctx->prefix, l )) + if ((l = strlen( ctx->prefix ))) { + if (!starts_with( arg, argl, ctx->prefix, l )) { + if (is_inbox( ctx, arg, argl )) { + // INBOX and its subfolders bypass the namespace. + goto inbox; + } - goto skip; + return LIST_OK; + } arg += l; argl -= l; // A folder named "INBOX" would be indistinguishable from the @@@ -1398,14 -1285,22 +1399,22 @@@ if (is_INBOX( ctx, arg, argl )) { if (!arg[5]) // No need to complain about subfolders as well. warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); - goto skip; + return LIST_OK; } + } else if (is_inbox( ctx, arg, argl )) { + inbox: + // The server might be weird and have a non-uppercase INBOX. It + // may legitimately do so, but we need the canonical spelling. + // Note that we do that only after prefix matching, under the + // assumption that the NAMESPACE (or Path) matches the + // capitalization of LIST. + memcpy( arg, "INBOX", 5 ); } if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */ - goto skip; + return LIST_OK; if (map_name( arg, (char **), offsetof(string_list_t, string), ctx->delimiter, "/") < 0) { warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg ); - goto skip; + return LIST_OK; } narg->next = ctx->boxes; ctx->boxes = narg; = Full diff against 1st parent = diff --git a/src/drv_imap.c b/src/drv_imap.c index 8d7c99b..9f23e08 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1382,13 +1382,14 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) } arg = list->val; argl = (int)list->len; - if (is_inbox( ctx, arg, argl )) { - // The server might be weird and have a non-uppercase INBOX. It - // may legitimately do so, but we need the canonical spelling. - memcpy( arg, "INBOX", 5 ); - } else if ((l = strlen( ctx->prefix ))) { - if (!starts_with( arg, argl, ctx->prefix, l )) + if ((l = strlen( ctx->prefix ))) { + if (!starts_with( arg, argl, ctx->prefix, l )) { + if (is_inbox( ctx, arg, argl )) { + // INBOX and its subfolders bypass the namespace. + goto inbox; + } return LIST_OK; + } arg += l; argl -= l; // A folder named "INBOX" would be indistinguishable from the @@ -1400,6 +1401,14 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); return LIST_OK; } + } else if (is_inbox( ctx, arg, argl )) { + inbox: + // The server might be weird and have a non-uppercase INBOX. It + // may legitimately do so, but we need the canonical spelling. + // Note that we do that only after prefix matching, under the + // assumption that the NAMESPACE (or Path) matches the + // capitalization of LIST. + memcpy( arg, "INBOX", 5 ); } if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */ return LIST_OK; ___
[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 = (ctx = (imap_store_t *)*ctxp); ctxp = >gen.next) if (ctx->state != SST_BAD && ((imap_store_conf_t *)ctx->gen.conf)->server == srvc) { *ctxp = ctx->gen.next; - imap_cleanup_store( ctx ); + free_string_list( ctx->boxes ); + ctx->boxes = NULL; + ctx->listed = 0; /* One could ping the server here, but given that the idle timeout * is at least 30 minutes, this sounds pretty pointless. */ ctx->state = SST_HALF; @@ -1921,7 +1916,7 @@ ensure_password( imap_server_conf_t *srvc ) if (cmd) { FILE *fp; int ret; - char buffer[2048]; // Hopefully more than enough room for XOAUTH2, etc. tokens + char buffer[8192]; // Hopefully more than enough room for XOAUTH2, etc. tokens if (*cmd == '+') { flushn(); diff --git a/src/drv_proxy.c b/src/drv_proxy.c index 2ef928a..7250293 100644 --- a/src/drv_proxy.c +++ b/src/drv_proxy.c @@ -309,9 +309,11 @@ proxy_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux ) static void proxy_invoke_bad_callback( proxy_store_t *ctx ) { + ctx->ref_count++; debug( "%sCallback enter bad store\n", ctx->label ); ctx->bad_callback( ctx->bad_callback_aux ); - debug( "%sCallback leave bad store\n", ctx->label ); \ + debug( "%sCallback leave bad store\n", ctx->label ); + proxy_store_deref( ctx ); } //# EXCLUDE alloc_store diff --git a/src/mbsync.1 b/src/mbsync.1 index 171727f..c8c8736 100644 --- a/src/mbsync.1 +++ b/src/mbsync.1 @@ -379,17 +379,27 @@ if you want to trust only hand-picked certificates. \fBCertificateFile\fR \fIpath\fR File containing additional X.509 certificates used to verify server identities. -These certificates are always trusted, regardless of validity. -.br -The certificates from this file are matched only against the received -server certificate itself; CA certificates are \fBnot\fR supported here. -Do \fBnot\fR specify the system's CA certificate store here; see -\fBSystemCertificates\fR instead. -.br -The contents for this file may be obtained using the -\fBmbsync-get-cert\fR tool; make sure to verify the fingerprints of the -certificates before trusting them, or transfer them securely from the -server's network (if it is trusted). +It may contain two types of certificates: +.RS +.IP Host +These certificates are matched only against the received server certificate +itself. +They are always trusted, regardless of validity. +A typical use case would be forcing acceptance of an expired certificate. +.br +These certificates may be obtained using the \fBmbsync-get-cert\fR tool; +make sure to verify their fingerprints before trusting them, or transfer +them securely from the server's network (if it can be trusted beyond the +server itself). +.IP CA +These certificates are used as trust anchors when building the certificate +chain for the received server certificate. +They are used to supplant or supersede the system's trust store, depending +on the \fBSystemCertificates\fR setting; +it is not necessary and not recommended to specify the system's trust store +itself here. +The trust chains are fully validated. +.RE . .TP \fBClientCertificate\fR \fIpath\fR diff --git a/src/socket.c b/src/socket.c index dbd781c..84449e7 100644 --- a/src/socket.c +++ b/src/socket.c @@ -41,7 +41,7 @@ # include # include
[commit] master: Merge branch '1.3'
Skipped 14 existing revision(s) on branch 'master'. commit cab14608caa7b99478c86b526179b3990359ea1e Merge: e565d08 80deabf Author: Oswald Buddenhagen Date: Fri Nov 22 14:06:01 2019 +0100 Merge branch '1.3' Makefile.am | 5 +- README| 7 ++ TODO | 2 - src/drv_imap.c| 58 ++ src/drv_maildir.c | 9 ++- src/main.c| 26 ++- src/mbsync.1 | 191 -- src/socket.c | 5 +- src/sync.c| 4 +- src/util.c| 5 +- 10 files changed, 194 insertions(+), 118 deletions(-) diff --cc src/mbsync.1 index 8f6c58b,6830508..171727f --- a/src/mbsync.1 +++ b/src/mbsync.1 @@@ -738,9 -745,9 +745,9 @@@ Default configuration fil .TP .B ~/.mbsync/ Directory containing synchronization state files - .. + . .SH SEE ALSO -mdconvert(1), isync(1), mutt(1), maildir(5) +mdconvert(1), mutt(1), maildir(5) .P Up to date information on \fBmbsync\fR can be found at http://isync.sf.net/ .P = Full diff against 1st parent = diff --git a/Makefile.am b/Makefile.am index 557742f..245299b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,7 +47,10 @@ LOG_PL = \ print $$log."\n"; \ } -$(srcdir)/ChangeLog: log +$(srcdir)/.git/index: +$(srcdir)/ChangeLog: $(srcdir)/.git/index + $(MAKE) log + log: @test -z "$(srcdir)" || cd $(srcdir) && \ ( ! test -d .git || \ diff --git a/README b/README index 53c3fb1..e678cb5 100644 --- a/README +++ b/README @@ -54,11 +54,18 @@ change was necessary because of massive changes in the user interface. * Requirements +perl v5.14+ Berkeley DB 4.1+ (optional) OpenSSL for TLS/SSL support (optional) Cyrus SASL (optional) zlib (optional) + The build from git also requires: + +GNU autotools (autoconf & automake) +perl module Date::Parse (libtimedate-perl on Debian, perl-TimeDate on + Fedora and Suse) + * Installation ./autogen.sh (only when building from git) diff --git a/TODO b/TODO index b074e22..f8c6d73 100644 --- a/TODO +++ b/TODO @@ -37,8 +37,6 @@ Patterns. function being missing so far - this is needed for move detection, which would work only within one Channel -normalize INBOX capitalization received from IMAP, to avoid anomalies. - 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 diff --git a/src/drv_imap.c b/src/drv_imap.c index 76c0e3d..8d2ebf5 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1180,7 +1180,7 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s ) if (!(arg = next_arg( )) || (ctx->uidnext = strtoul( arg, , 10 ), *earg)) { - error( "IMAP error: malformed NEXTUID status\n" ); + error( "IMAP error: malformed UIDNEXT status\n" ); return RESP_CANCEL; } } else if (!strcmp( "CAPABILITY", arg )) { @@ -1260,8 +1260,20 @@ parse_list_rsp_p1( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) return parse_list( ctx, cmd, parse_list_rsp_p2 ); } +// Use this to check whether a full path refers to the actual IMAP INBOX. static int is_inbox( imap_store_t *ctx, const char *arg, int argl ) +{ + if (!starts_with_upper( arg, argl, "INBOX", 5 )) + return 0; + if (arg[5] && arg[5] != ctx->delimiter[0]) + return 0; + return 1; +} + +// Use this to check whether a path fragment collides with the canonical INBOX. +static int +is_INBOX( imap_store_t *ctx, const char *arg, int argl ) { if (!starts_with( arg, argl, "INBOX", 5 )) return 0; @@ -1284,16 +1296,22 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) } arg = list->val; argl = list->len; - if ((l = strlen( ctx->prefix ))) { - if (starts_with( arg, argl, ctx->prefix, l )) { - arg += l; - argl -= l; - if (is_inbox( ctx, arg, argl )) { - if (!arg[5]) - warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); - goto skip; - } - } else if (!is_inbox( ctx, arg, argl )) { + if (is_inbox( ctx, arg, argl )) { + // The server might be weird and have a non-uppercase INBOX. It + // may legitimately do so, but we need the canonical spelling. + memcpy( arg, "INBOX", 5 ); + } else if ((l = strlen( ctx->prefix ))) { + if (!starts_with( arg, argl, ctx->prefix, l )) + goto skip; + arg += l; +
[commit] master: Merge branch '1.3'
Skipped 15 existing revision(s) on branch 'master'. commit 462fed556a4ccb57c1259570583d846d343cc628 Merge: a310e7e d0a8551 Author: Oswald Buddenhagen Date: Thu Oct 3 20:17:54 2019 +0200 Merge branch '1.3' configure.ac | 6 +-- src/common.h | 1 + src/drv_imap.c | 28 +++ src/drv_proxy_gen.pl | 1 + src/mbsync.1 | 15 +++--- src/socket.c | 111 --- 6 files changed, 114 insertions(+), 48 deletions(-) = Full diff against 1st parent = diff --git a/configure.ac b/configure.ac index 880f17c..a4c002d 100644 --- a/configure.ac +++ b/configure.ac @@ -18,14 +18,14 @@ fi need_perl=5.14 AC_CACHE_CHECK([whether perl is recent enough], ob_cv_perl_ver, [ -if $PERL -e "use v$need_perl;"; then +if $PERL -e "use v$need_perl;" 2> /dev/null; then ob_cv_perl_ver=yes else ob_cv_perl_ver=no fi ]) if test "x$ob_cv_perl_ver" = "xno"; then -AC_MSG_ERROR([perl is too old]) +AC_MSG_ERROR([perl is too old, need v$need_perl]) fi AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z, @@ -94,7 +94,7 @@ if test "x$ob_cv_with_ssl" != xno; then sav_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $SSL_LDFLAGS" AC_CHECK_LIB(dl, dlopen, [LIBDL=-ldl]) -AC_CHECK_LIB(crypto, CRYPTO_lock, [LIBCRYPTO=-lcrypto]) +AC_CHECK_LIB(crypto, X509_cmp, [LIBCRYPTO=-lcrypto]) AC_CHECK_LIB(ssl, SSL_connect, [SSL_LIBS="-lssl $LIBCRYPTO $LIBDL" have_ssl_paths=yes]) LDFLAGS=$sav_LDFLAGS diff --git a/src/common.h b/src/common.h index c731126..d45929c 100644 --- a/src/common.h +++ b/src/common.h @@ -33,6 +33,7 @@ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; +typedef unsigned long ulong; #define as(ar) (sizeof(ar)/sizeof(ar[0])) diff --git a/src/drv_imap.c b/src/drv_imap.c index 58fc9d3..7bc88f6 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -953,7 +953,7 @@ parse_date( const char *str ) struct tm datetime; memset( , 0, sizeof(datetime) ); - if (!(end = strptime( str, "%d-%b-%Y %H:%M:%S ", ))) + if (!(end = strptime( str, "%e-%b-%Y %H:%M:%S ", ))) return -1; if ((date = timegm( )) == -1) return -1; @@ -1203,17 +1203,16 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s ) return RESP_OK; } +static int parse_list_rsp_p1( imap_store_t *, list_t *, char * ); static int parse_list_rsp_p2( imap_store_t *, list_t *, char * ); static int parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd ) { - char *arg; list_t *lp; if (!is_list( list )) { free_list( list ); - bad_list: error( "IMAP error: malformed LIST response\n" ); return LIST_BAD; } @@ -1223,10 +1222,19 @@ parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd ) return LIST_OK; } free_list( list ); - if (!(arg = next_arg( ))) - goto bad_list; - if (!ctx->delimiter[0]) - ctx->delimiter[0] = arg[0]; + return parse_list( ctx, cmd, parse_list_rsp_p1 ); +} + +static int +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 )) + ctx->delimiter[0] = list->val[0]; return parse_list( ctx, cmd, parse_list_rsp_p2 ); } @@ -1873,7 +1881,7 @@ ensure_password( imap_server_conf_t *srvc ) if (cmd) { FILE *fp; int ret; - char buffer[80]; + char buffer[2048]; // Hopefully more than enough room for XOAUTH2, etc. tokens if (*cmd == '+') { flushn(); @@ -2079,7 +2087,7 @@ done_sasl_auth( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) int rc = sasl_client_step( ctx->sasl, NULL, 0, , , _len ); if (process_sasl_step( ctx, rc, NULL, 0, interact, , _len ) < 0) warn( "Warning: SASL reported failure despite successful IMAP authentication. Ignoring...\n" ); - else if (out) + else if (out_len > 0) warn( "Warning: SASL wants more steps despite successful IMAP authentication. Ignoring...\n" ); } @@ -2180,7 +2188,7 @@ imap_open_store_authenticate2( imap_store_t *ctx ) free( enc ); return; notsasl: - if (!ctx->sasl || sasl_listmech( ctx->sasl, NULL, "", "", "", , NULL, NULL ) != SASL_OK) + if (!ctx->sasl || sasl_listmech( ctx->sasl, NULL, "", " ", "", , NULL, NULL ) != SASL_OK)
[commit] master: Merge branch '1.3'
Skipped 6 existing revision(s) on branch 'master'. commit 95d18e2778f28b7aac4f92dc6770430ee7c7ca4b Merge: 37feedd acfa3a2 Author: Oswald Buddenhagen Date: Tue Nov 27 00:51:03 2018 +0100 Merge branch '1.3' src/driver.c | 9 src/driver.h | 1 + src/drv_imap.c | 56 -- src/socket.c | 2 ++ 4 files changed, 62 insertions(+), 6 deletions(-) = Full diff against 1st parent = diff --git a/src/driver.c b/src/driver.c index e522d14..e28d817 100644 --- a/src/driver.c +++ b/src/driver.c @@ -27,6 +27,15 @@ driver_t *drivers[N_DRIVERS] = { _driver, _driver }; +int +count_generic_messages( message_t *msgs ) +{ + int count = 0; + for (; msgs; msgs = msgs->next) + count++; + return count; +} + void free_generic_messages( message_t *msgs ) { diff --git a/src/driver.h b/src/driver.h index 00c5581..08edf20 100644 --- a/src/driver.h +++ b/src/driver.h @@ -261,6 +261,7 @@ struct driver { int (*get_fail_state)( store_conf_t *conf ); }; +int count_generic_messages( message_t * ); void free_generic_messages( message_t * ); void parse_generic_store( store_conf_t *store, conffile_t *cfg ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 03eaf30..58fc9d3 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -291,7 +291,7 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) int bufl, litplus, iovcnt = 1; const char *buffmt; conn_iovec_t iov[3]; - char buf[1024]; + char buf[4096]; cmd->tag = ++ctx->nexttag; if (!cmd->param.data) { @@ -448,7 +448,7 @@ imap_vprintf( const char *fmt, va_list ap ) char *d, *ed; int maxlen; char c; - char buf[1024]; /* Minimal supported command buffer size per IMAP spec. */ + char buf[4096]; d = buf; ed = d + sizeof(buf); @@ -601,8 +601,9 @@ imap_refcounted_new_cmd( imap_cmd_refcounted_state_t *sts ) free( sts ); \ } -#define DONE_REFCOUNTED_STATE_ARGS(sts, ...) \ +#define DONE_REFCOUNTED_STATE_ARGS(sts, finalize, ...) \ if (!--sts->gen.ref_count) { \ + finalize \ sts->callback( sts->gen.ret_val, __VA_ARGS__, sts->callback_aux ); \ free( sts ); \ } @@ -1108,7 +1109,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) if (status & M_FLAGS) msgdata->flags = mask; } else { - /* XXX this will need sorting for out-of-order (multiple queries) */ cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = >gen; ctx->msgapp = >gen.next; @@ -2593,6 +2593,47 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenui } } +static int +imap_sort_msgs_comp( const void *a_, const void *b_ ) +{ + const message_t *a = *(const message_t * const *)a_; + const message_t *b = *(const message_t * const *)b_; + + if (a->uid < b->uid) + return -1; + if (a->uid > b->uid) + return 1; + return 0; +} + +static void +imap_sort_msgs( imap_store_t *ctx ) +{ + int count = count_generic_messages( ctx->msgs ); + if (count <= 1) + return; + + message_t **t = nfmalloc( sizeof(*t) * count ); + + message_t *m = ctx->msgs; + for (int i = 0; i < count; i++) { + t[i] = m; + m = m->next; + } + + qsort( t, count, sizeof(*t), imap_sort_msgs_comp ); + + ctx->msgs = t[0]; + + int j; + for (j = 0; j < count - 1; j++) + t[j]->next = t[j + 1]; + ctx->msgapp = [j]->next; + *ctx->msgapp = NULL; + + free( t ); +} + static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int ); static void @@ -2621,7 +2662,10 @@ imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) + DONE_REFCOUNTED_STATE_ARGS(sts, { + if (sts->gen.ret_val == DRV_OK) + imap_sort_msgs( ctx ); + }, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) } /*** imap_fetch_msg ***/ @@ -3018,7 +3062,7 @@ imap_list_store_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_list_store_p3( imap_store_t *ctx, imap_list_store_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->boxes) + DONE_REFCOUNTED_STATE_ARGS(sts, , ctx->boxes) } /*** imap_cancel_cmds ***/ diff --git a/src/socket.c b/src/socket.c index dd79619..e3fda42 100644 --- a/src/socket.c +++ b/src/socket.c @@ -271,6 +271,8 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) ) init_wakeup(
[commit] master: Merge branch '1.3'
Skipped 1 existing revision(s) on branch 'master'. commit 940cb3255139e97c0dec98416fa98962901f9a3e Merge: 37feedd 17babc1 Author: Oswald Buddenhagen Date: Sat Sep 8 18:48:05 2018 +0200 Merge branch '1.3' src/socket.c | 2 ++ 1 file changed, 2 insertions(+) = Full diff against 1st parent = diff --git a/src/socket.c b/src/socket.c index dd79619..e3fda42 100644 --- a/src/socket.c +++ b/src/socket.c @@ -271,6 +271,8 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) ) init_wakeup( >ssl_fake, ssl_fake_cb, conn ); conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ); + if (ssl_return( "set server name", conn, SSL_set_tlsext_host_name( conn->ssl, conn->conf->host ) ) < 0) + return; SSL_set_fd( conn->ssl, conn->fd ); SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); socket_expect_read( conn, 1 ); ___ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel
[commit] master: Merge branch '1.3'
Skipped 2 existing revision(s) on branch 'master'. commit 3a7b4885278b1679e85020801391ba6c017c83a7 Merge: 940cb32 acfa3a2 Author: Oswald Buddenhagen Date: Mon Nov 26 22:50:39 2018 +0100 Merge branch '1.3' src/driver.c | 9 src/driver.h | 1 + src/drv_imap.c | 56 -- 3 files changed, 60 insertions(+), 6 deletions(-) = Full diff against 1st parent = diff --git a/src/driver.c b/src/driver.c index e522d14..e28d817 100644 --- a/src/driver.c +++ b/src/driver.c @@ -27,6 +27,15 @@ driver_t *drivers[N_DRIVERS] = { _driver, _driver }; +int +count_generic_messages( message_t *msgs ) +{ + int count = 0; + for (; msgs; msgs = msgs->next) + count++; + return count; +} + void free_generic_messages( message_t *msgs ) { diff --git a/src/driver.h b/src/driver.h index 00c5581..08edf20 100644 --- a/src/driver.h +++ b/src/driver.h @@ -261,6 +261,7 @@ struct driver { int (*get_fail_state)( store_conf_t *conf ); }; +int count_generic_messages( message_t * ); void free_generic_messages( message_t * ); void parse_generic_store( store_conf_t *store, conffile_t *cfg ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 03eaf30..58fc9d3 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -291,7 +291,7 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) int bufl, litplus, iovcnt = 1; const char *buffmt; conn_iovec_t iov[3]; - char buf[1024]; + char buf[4096]; cmd->tag = ++ctx->nexttag; if (!cmd->param.data) { @@ -448,7 +448,7 @@ imap_vprintf( const char *fmt, va_list ap ) char *d, *ed; int maxlen; char c; - char buf[1024]; /* Minimal supported command buffer size per IMAP spec. */ + char buf[4096]; d = buf; ed = d + sizeof(buf); @@ -601,8 +601,9 @@ imap_refcounted_new_cmd( imap_cmd_refcounted_state_t *sts ) free( sts ); \ } -#define DONE_REFCOUNTED_STATE_ARGS(sts, ...) \ +#define DONE_REFCOUNTED_STATE_ARGS(sts, finalize, ...) \ if (!--sts->gen.ref_count) { \ + finalize \ sts->callback( sts->gen.ret_val, __VA_ARGS__, sts->callback_aux ); \ free( sts ); \ } @@ -1108,7 +1109,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) if (status & M_FLAGS) msgdata->flags = mask; } else { - /* XXX this will need sorting for out-of-order (multiple queries) */ cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = >gen; ctx->msgapp = >gen.next; @@ -2593,6 +2593,47 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenui } } +static int +imap_sort_msgs_comp( const void *a_, const void *b_ ) +{ + const message_t *a = *(const message_t * const *)a_; + const message_t *b = *(const message_t * const *)b_; + + if (a->uid < b->uid) + return -1; + if (a->uid > b->uid) + return 1; + return 0; +} + +static void +imap_sort_msgs( imap_store_t *ctx ) +{ + int count = count_generic_messages( ctx->msgs ); + if (count <= 1) + return; + + message_t **t = nfmalloc( sizeof(*t) * count ); + + message_t *m = ctx->msgs; + for (int i = 0; i < count; i++) { + t[i] = m; + m = m->next; + } + + qsort( t, count, sizeof(*t), imap_sort_msgs_comp ); + + ctx->msgs = t[0]; + + int j; + for (j = 0; j < count - 1; j++) + t[j]->next = t[j + 1]; + ctx->msgapp = [j]->next; + *ctx->msgapp = NULL; + + free( t ); +} + static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int ); static void @@ -2621,7 +2662,10 @@ imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) + DONE_REFCOUNTED_STATE_ARGS(sts, { + if (sts->gen.ret_val == DRV_OK) + imap_sort_msgs( ctx ); + }, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) } /*** imap_fetch_msg ***/ @@ -3018,7 +3062,7 @@ imap_list_store_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_list_store_p3( imap_store_t *ctx, imap_list_store_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->boxes) + DONE_REFCOUNTED_STATE_ARGS(sts, , ctx->boxes) } /*** imap_cancel_cmds ***/ ___ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel
[commit] master: Merge branch '1.3'
Skipped 4 existing revision(s) on branch 'master'. commit 37feeddbfb8d86fcd25f90c7928d5ea139b0feb4 Merge: c4d7f01 f698f16 Author: Oswald Buddenhagen Date: Sun Jul 1 13:26:10 2018 +0200 Merge branch '1.3' src/drv_imap.c| 14 ++ src/drv_maildir.c | 6 +++--- src/drv_proxy.c | 8 src/socket.c | 3 ++- src/socket.h | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) = Full diff against 1st parent = diff --git a/src/drv_imap.c b/src/drv_imap.c index e782ec0..03eaf30 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -2927,7 +2927,7 @@ imap_find_new_msgs_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) cmd->uid = cmdp->uid; cmd->gen.param.lastuid = 1; imap_exec( ctx, >gen, imap_find_new_msgs_p3, - "UID FETCH *:* (UID)" ); + "UID FETCH * (UID)" ); } static void @@ -3137,9 +3137,15 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep ) server->pass = nfstrdup( cfg->val ); else if (!strcasecmp( "PassCmd", cfg->cmd )) server->pass_cmd = nfstrdup( cfg->val ); - else if (!strcasecmp( "Port", cfg->cmd )) - server->sconf.port = parse_int( cfg ); - else if (!strcasecmp( "Timeout", cfg->cmd )) + else if (!strcasecmp( "Port", cfg->cmd )) { + int port = parse_int( cfg ); + if ((unsigned)port > 0x) { + error( "%s:%d: Invalid port number\n", cfg->file, cfg->line ); + cfg->err = 1; + } else { + server->sconf.port = (ushort)port; + } + } else if (!strcasecmp( "Timeout", cfg->cmd )) server->sconf.timeout = parse_int( cfg ); else if (!strcasecmp( "PipelineDepth", cfg->cmd )) { if ((server->max_in_progress = parse_int( cfg )) < 1) { diff --git a/src/drv_maildir.c b/src/drv_maildir.c index d094146..d8c41c5 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -1573,7 +1573,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash, uint uid; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], base[128]; - bl = nfsnprintf( base, sizeof(base), "%ld.%d_%d.%s", (long)time( 0 ), Pid, ++MaildirCount, Hostname ); + bl = nfsnprintf( base, sizeof(base), "%lld.%d_%d.%s", (long long)time( 0 ), Pid, ++MaildirCount, Hostname ); if (!to_trash) { #ifdef USE_DB if (ctx->usedb) { @@ -1754,8 +1754,8 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg, for (;;) { nfsnprintf( buf, sizeof(buf), "%s/%s/%s", ctx->path, subdirs[gmsg->status & M_RECENT], msg->base ); s = strstr( msg->base, ((maildir_store_conf_t *)gctx->conf)->info_prefix ); - nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%ld.%d_%d.%s%s", ctx->trash, - subdirs[gmsg->status & M_RECENT], (long)time( 0 ), Pid, ++MaildirCount, Hostname, s ? s : "" ); + nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%lld.%d_%d.%s%s", ctx->trash, + subdirs[gmsg->status & M_RECENT], (long long)time( 0 ), Pid, ++MaildirCount, Hostname, s ? s : "" ); if (!rename( buf, nbuf )) break; if (!stat( buf, )) { diff --git a/src/drv_proxy.c b/src/drv_proxy.c index 4fa40a7..2ef928a 100644 --- a/src/drv_proxy.c +++ b/src/drv_proxy.c @@ -242,8 +242,8 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v static char fbuf[as(Flags) + 1]; proxy_make_flags( cmd->data->flags, fbuf ); //# END -//# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%ld, size=%d -//# DEFINE fetch_msg_print_pass_cb_args , fbuf, cmd->data->date, cmd->data->len +//# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%lld, size=%d +//# DEFINE fetch_msg_print_pass_cb_args , fbuf, (long long)cmd->data->date, cmd->data->len //# DEFINE fetch_msg_print_cb_args if (sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) { printf( "%s=\n", cmd->gen.ctx->label ); @@ -257,8 +257,8 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v static char fbuf[as(Flags) + 1]; proxy_make_flags( data->flags, fbuf ); //# END -//# DEFINE store_msg_print_fmt_args , flags=%s, date=%ld, size=%d, to_trash=%s -//# DEFINE store_msg_print_pass_args , fbuf, data->date, data->len, to_trash ? "yes" : "no" +//# DEFINE store_msg_print_fmt_args , flags=%s, date=%lld, size=%d, to_trash=%s +//# DEFINE store_msg_print_pass_args , fbuf, (long long)data->date, data->len, to_trash ? "yes" : "no" //# DEFINE store_msg_print_args if (DFlags & DEBUG_DRV_ALL) { printf(
[commit] master: Merge branch '1.3'
Skipped 10 existing revision(s) on branch 'master'. commit 904858365d636d5d949253c6e6a18227249f8ef7 Merge: cbac8aa 5072032 Author: Oswald BuddenhagenDate: Sun Apr 8 18:17:10 2018 +0200 Merge branch '1.3' Conflicts: configure.ac .gitignore| 1 + configure.ac | 17 + src/config.c | 2 ++ src/drv_imap.c| 4 ++-- src/drv_maildir.c | 21 +++-- src/main.c| 4 ++-- src/socket.h | 4 +--- src/sync.c| 2 +- src/util.c| 27 ++- 9 files changed, 47 insertions(+), 35 deletions(-) = Full diff against 1st parent = diff --git a/.gitignore b/.gitignore index 05a49c7..310c028 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ /install-sh /isync.spec /isync-*.tar.gz +/isync-*.tar.gz.asc /missing /patch-stamp /stamp-h diff --git a/configure.ac b/configure.ac index fc170f8..f56ed81 100644 --- a/configure.ac +++ b/configure.ac @@ -11,6 +11,23 @@ fi CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +AC_CHECK_PROG(PERL, perl, perl) +if test "x$PERL" = "x"; then +AC_MSG_ERROR([perl not found]) +fi + +need_perl=5.14 +AC_CACHE_CHECK([whether perl is recent enough], ob_cv_perl_ver, [ +if $PERL -e "use v$need_perl;"; then +ob_cv_perl_ver=yes +else +ob_cv_perl_ver=no +fi +]) +if test "x$ob_cv_perl_ver" = "xno"; then +AC_MSG_ERROR([perl is too old]) +fi + AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z, [AC_TRY_RUN( [#include diff --git a/src/config.c b/src/config.c index 20f09d9..8ddfe26 100644 --- a/src/config.c +++ b/src/config.c @@ -355,6 +355,8 @@ load_config( const char *where, int pseudo ) if (store) { if (!store->max_size) store->max_size = INT_MAX; + if (!store->flat_delim) + store->flat_delim = ""; *storeapp = store; storeapp = >next; *storeapp = 0; diff --git a/src/drv_imap.c b/src/drv_imap.c index 56d71cb..05afa09 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -2250,7 +2250,7 @@ imap_open_store_namespace( imap_store_t *ctx ) ctx->state = SST_HALF; ctx->prefix = cfg->gen.path; - ctx->delimiter[0] = cfg->delimiter ? cfg->delimiter : 0; + ctx->delimiter[0] = cfg->delimiter; if (((!ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) { /* get NAMESPACE info */ if (!ctx->got_namespace) @@ -2388,7 +2388,7 @@ imap_open_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) INIT_IMAP_CMD(imap_cmd_open_box_t, cmd, cmdp->callback, cmdp->callback_aux) cmd->gen.param.lastuid = 1; imap_exec( ctx, >gen, imap_open_box_p3, - "UID FETCH *:* (UID)" ); + "UID FETCH * (UID)" ); } static void diff --git a/src/drv_maildir.c b/src/drv_maildir.c index c4dd6c7..4a94696 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -1153,28 +1153,29 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist ) goto retry; } int off, in_msgid = 0; - while ((want_tuid || want_msgid) && fgets( nbuf, sizeof(nbuf), f )) { - int bufl = strlen( nbuf ); - if (bufl && nbuf[bufl - 1] == '\n') + char lnbuf[1000]; // Says RFC2822 + while ((want_tuid || want_msgid) && fgets( lnbuf, sizeof(lnbuf), f )) { + int bufl = strlen( lnbuf ); + if (bufl && lnbuf[bufl - 1] == '\n') --bufl; - if (bufl && nbuf[bufl - 1] == '\r') + if (bufl && lnbuf[bufl - 1] == '\r') --bufl; if (!bufl) break; - if (want_tuid && starts_with( nbuf, bufl, "X-TUID: ", 8 )) { + if (want_tuid && starts_with( lnbuf, bufl, "X-TUID: ", 8 )) { if (bufl < 8 + TUIDL) { error( "Maildir error: malformed X-TUID header (UID %u)\n", uid ); continue; } - memcpy(