Compare commits

..

6 Commits

Author SHA1 Message Date
Oswald Buddenhagen 15c7e02e4a accept zero-sized messages from IMAP 1 month ago
Behnam Lal d7305e12d9 mbsync-get-cert: add support for STARTTLS 1 month ago
Oswald Buddenhagen a1be7e9a36 make summary more concise 1 month ago
Oswald Buddenhagen 1e7a75095b fix crash when resuming message propagation with MaxMessages 1 month ago
Oswald Buddenhagen 5f953c5162 fix omissions in making expiration target side configurable 1 month ago
Oswald Buddenhagen bf34d9fd29 do not let both-sided uidvalidity change deter us 1 month ago
  1. 30
      mbsync-get-cert
  2. 5
      src/drv_imap.c
  3. 32
      src/main_sync.c
  4. 2
      src/mbsync.1.in
  5. 1
      src/socket.c
  6. 37
      src/sync.c
  7. 5
      src/util.c

30
mbsync-get-cert

@ -9,9 +9,25 @@
# from a trusted source.
#
if [ $# != 1 ]; then
echo "Usage: $0 <host>" >&2
usage() {
echo "Usage: $0 [-s] <host>" >&2
echo " -s Use IMAP+STARTTLS (port 143) instead of IMAPS (port 993)" >&2
exit 1
}
STARTTLS=false
while getopts "s" opt; do
case $opt in
s) STARTTLS=true ;;
*) usage ;;
esac
done
shift `expr $OPTIND - 1`
if [ $# -ne 1 ]; then
usage
fi
HOST=$1
@ -33,7 +49,15 @@ TMPFILE=$TMPDIR/get-cert
ERRFILE=$TMPDIR/get-cert-err
CERTFILE=$TMPDIR/cert
echo QUIT | openssl s_client -connect $HOST:993 -showcerts \
if $STARTTLS; then
FLAGS="-starttls imap"
PORT=143
else
FLAGS=
PORT=993
fi
echo QUIT | openssl s_client $FLAGS -connect $HOST:$PORT -showcerts \
> $TMPFILE 2> $ERRFILE
sed -e '1,/^-----BEGIN CERTIFICATE-----/d' \
-e '/^-----END CERTIFICATE-----/,$d' < $TMPFILE > $CERTFILE

5
src/drv_imap.c

@ -780,6 +780,8 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
if (sts->callback->atom( ctx, NULL, bytes, AtomChunkedLiteral ) != LIST_OK)
goto bail;
sts->in_literal = ChunkedLiteral;
if (!bytes)
goto nobytes;
sts->big_literal = 1;
get_chunked:
n = 1;
@ -806,7 +808,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
} else if (DFlags & DEBUG_NET_ALL) {
printf( "%s=========\n", ctx->label );
fwrite( p, n, 1, stdout );
if (p[n - 1] != '\n')
if (n && p[n - 1] != '\n')
fputs( "\n(no-nl) ", stdout );
printf( "%s=========\n", ctx->label );
} else {
@ -819,6 +821,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
bytes -= n;
if (bytes > 0)
goto postpone;
nobytes:
if (sts->in_literal == ChunkedLiteral && sts->callback->atom( ctx, NULL, 0, AtomLiteral ) != LIST_OK)
goto bail;
getline:

32
src/main_sync.c

@ -9,7 +9,6 @@
#define nz(a, b) ((a) ? (a) : (b))
static int ops_any[2], trash_any[2], expunge_any[2];
static int chans_total, chans_done;
static int boxes_total, boxes_done;
@ -84,25 +83,10 @@ summary( void )
if (!boxes_done)
return; // Shut up if we errored out early.
printf( "Processed %d box(es) in %d channel(s)", boxes_done, chans_done );
for (int t = 2; --t >= 0; ) {
if (ops_any[t])
printf( (DFlags & DRYRUN) ?
",\nwould %s %d new message(s) and %d flag update(s)" :
",\n%sed %d new message(s) and %d flag update(s)",
str_hl[t], new_done[t], flags_done[t] );
if (trash_any[t])
printf( (DFlags & DRYRUN) ?
",\nwould move %d %s message(s) to trash" :
",\nmoved %d %s message(s) to trash",
trash_done[t], str_fn[t] );
if (expunge_any[t])
printf( (DFlags & DRYRUN) ?
",\nwould expunge %d message(s) from %s" :
",\nexpunged %d message(s) from %s",
expunge_done[t], str_fn[t] );
}
puts( "." );
printf( "Channels: %d Boxes: %d Far: +%d *%d #%d -%d Near: +%d *%d #%d -%d\n",
chans_done, boxes_done,
new_done[F], flags_done[F], trash_done[F], expunge_done[F],
new_done[N], flags_done[N], trash_done[N], expunge_done[N] );
}
static int
@ -244,14 +228,6 @@ add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] )
free( ce );
return NULL;
}
if (chan->ops[t] & OP_MASK_TYPE)
ops_any[t] = 1;
if (chan->ops[t] & (OP_EXPUNGE | OP_EXPUNGE_SOLO)) {
expunge_any[t] = 1;
if (chan->stores[t]->trash ||
(chan->stores[t^1]->trash && chan->stores[t^1]->trash_remote_new))
trash_any[t] = 1;
}
}
**chanapp = ce;

2
src/mbsync.1.in

@ -802,7 +802,7 @@ No attempt is made to calculate the totals in advance, so they grow over
time as more information is gathered.
.P
Irrespective of output redirection, \fBmbsync\fR will print a summary
of the above in plain language upon completion, except in quiet mode.
of the above upon completion, except in quiet mode.
.
.SH RECOMMENDATIONS
Make sure your IMAP server does not auto-expunge deleted messages - it is

1
src/socket.c

@ -952,7 +952,6 @@ socket_expect_bytes( conn_t *conn, uint len )
char *
socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len )
{
assert( min_len > 0 );
assert( min_len <= sizeof(conn->buf) );
assert( min_len <= max_len );

37
src/sync.c

@ -511,7 +511,7 @@ box_opened2( sync_vars_t *svars, int t )
channel_conf_t *chan;
sync_rec_t *srec;
uint_array_alloc_t mexcs;
uint opts[2], fails, minwuid;
uint opts[2], minwuid;
svars->state[t] |= ST_SELECTED;
if (!(svars->state[t^1] & ST_SELECTED))
@ -520,23 +520,13 @@ box_opened2( sync_vars_t *svars, int t )
ctx[1] = svars->ctx[1];
chan = svars->chan;
fails = 0;
for (t = 0; t < 2; t++)
if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t])
fails++;
// If only one side changed UIDVALIDITY, we will try to re-approve it further down.
if (fails == 2) {
error( "Error: channel %s: UIDVALIDITY of both far side %s and near side %s changed.\n",
svars->chan->name, svars->orig_name[F], svars->orig_name[N]);
if (!lock_state( svars )) {
bail:
svars->ret = SYNC_FAIL;
sync_bail( svars );
return;
}
if (!lock_state( svars ))
goto bail;
int any_dummies[2] = { 0, 0 };
int any_purges[2] = { 0, 0 };
int any_upgrades[2] = { 0, 0 };
@ -574,9 +564,11 @@ box_opened2( sync_vars_t *svars, int t )
}
opts[F] = opts[N] = 0;
if (fails)
opts[F] = opts[N] = OPEN_PAIRED | OPEN_PAIRED_IDS;
for (t = 0; t < 2; t++) {
if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t]) {
opts[F] |= OPEN_PAIRED | OPEN_PAIRED_IDS;
opts[N] |= OPEN_PAIRED | OPEN_PAIRED_IDS;
}
if (any_purges[t]) {
debug( "resuming %d %s purge(s)\n", any_purges[t], str_fn[t] );
opts[t] |= OPEN_SETFLAGS;
@ -859,8 +851,15 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if (!srec->msg[t^1])
continue; // Partner disappeared.
if (!srec->msg[t^1]->msgid || strcmp( srec->msg[F]->msgid, srec->msg[N]->msgid )) {
error( "Error: channel %s, %s box %s: UIDVALIDITY genuinely changed (at UID %u).\n",
svars->chan->name, str_fn[t], svars->orig_name[t], srec->uid[t] );
if (svars->uidval[t^1] != svars->newuidval[t^1]) {
error( "Error: channel %s, %s box %s (at UID %u):"
" Unable to recover from both-sided UIDVALIDITY change,"
" as it is genuine on at least one side.\n",
svars->chan->name, str_fn[t], svars->orig_name[t], srec->uid[t] );
} else {
error( "Error: channel %s, %s box %s (at UID %u): UIDVALIDITY genuinely changed.\n",
svars->chan->name, str_fn[t], svars->orig_name[t], srec->uid[t] );
}
uvchg:
svars->ret |= SYNC_FAIL;
cancel_sync( svars );
@ -1014,7 +1013,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
sflags = sanitize_flags( sflags, svars, t );
if ((t != xt) && (srec->status & (S_EXPIRE | S_EXPIRED))) {
/* Don't propagate deletion resulting from expiration. */
debug( " near side expiring\n" );
debug( " %s side expiring\n", str_fn[xt] );
sflags &= ~F_DELETED;
}
if (srec->status & S_DUMMY(t^1)) {
@ -1205,7 +1204,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if (!srec->uid[xt^1])
continue;
if (!(srec->status & S_PENDING)) {
// We ignore unpaired far-side messages, as there is obviously nothing
// We ignore unpaired keep-side messages, as there is obviously nothing
// to expire in the first place.
if (!srec->msg[xt])
continue;
@ -1230,6 +1229,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
// but we may be pulling in the real ones.
nflags = (srec->pflags | srec->aflags[xt]) & ~srec->dflags[xt];
} else {
if (!srec->msg[xt^1])
continue;
nflags = srec->msg[xt^1]->flags;
}
}

5
src/util.c

@ -637,6 +637,11 @@ nfmalloc( size_t sz )
{
void *ret;
#ifndef __GLIBC__
// The C standard allows NULL returns for zero-sized allocations.
if (!sz)
sz = 1;
#endif
if (!(ret = malloc( sz )))
oom();
return ret;

Loading…
Cancel
Save