"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/drv_imap.c" between
isync-1.4.1.tar.gz and isync-1.4.2.tar.gz

About: isync is a commandline application which synchronizes a local maildir-style mailbox with a remote IMAP4 mailbox, suitable for use in IMAP-disconnected mode.

drv_imap.c  (isync-1.4.1):drv_imap.c  (isync-1.4.2)
skipping to change at line 77 skipping to change at line 77
char use_keychain; char use_keychain;
#endif #endif
char failed; char failed;
} imap_server_conf_t; } imap_server_conf_t;
typedef union imap_store_conf { typedef union imap_store_conf {
store_conf_t gen; store_conf_t gen;
struct { struct {
STORE_CONF STORE_CONF
imap_server_conf_t *server; imap_server_conf_t *server;
char *path; // Note: this may be modified after the delimiter is determined.
char delimiter; char delimiter;
char use_namespace; char use_namespace;
char use_lsub; char use_lsub;
}; };
} imap_store_conf_t; } imap_store_conf_t;
typedef union imap_message { typedef union imap_message {
message_t gen; message_t gen;
struct { struct {
MESSAGE(union imap_message) MESSAGE(union imap_message)
skipping to change at line 117 skipping to change at line 118
int level, need_bytes; int level, need_bytes;
} parse_list_state_t; } parse_list_state_t;
typedef struct imap_cmd imap_cmd_t; typedef struct imap_cmd imap_cmd_t;
union imap_store { union imap_store {
store_t gen; store_t gen;
struct { struct {
STORE(union imap_store) STORE(union imap_store)
const char *label; // foreign const char *label; // foreign
const char *prefix;
const char *name; const char *name;
char *prefix;
uint ref_count; uint ref_count;
uint opts; uint opts;
enum { SST_BAD, SST_HALF, SST_GOOD } state; enum { SST_BAD, SST_HALF, SST_GOOD } state;
// The trash folder's existence is not confirmed yet // The trash folder's existence is not confirmed yet
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc; enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
// What kind of BODY-less FETCH response we're expecting // What kind of BODY-less FETCH response we're expecting
enum { FetchNone, FetchMsgs, FetchUidNext } fetch_sts; enum { FetchNone, FetchMsgs, FetchUidNext } fetch_sts;
uint got_namespace:1; uint got_namespace:1;
uint has_forwarded:1; uint has_forwarded:1;
char delimiter[2]; // Hierarchy delimiter char delimiter[2]; // Hierarchy delimiter
skipping to change at line 219 skipping to change at line 220
msg_data_t *msg_data; msg_data_t *msg_data;
}; };
} imap_cmd_fetch_msg_t; } imap_cmd_fetch_msg_t;
typedef union { typedef union {
imap_cmd_t gen; imap_cmd_t gen;
struct { struct {
IMAP_CMD IMAP_CMD
void (*callback)( int sts, uint uid, void *aux ); void (*callback)( int sts, uint uid, void *aux );
void *callback_aux; void *callback_aux;
uint out_uid;
}; };
} imap_cmd_out_uid_t; } imap_cmd_out_uid_t;
typedef union { typedef union {
imap_cmd_t gen; imap_cmd_t gen;
struct { struct {
IMAP_CMD IMAP_CMD
void (*callback)( int sts, message_t *msgs, void *aux ); void (*callback)( int sts, message_t *msgs, void *aux );
void *callback_aux; void *callback_aux;
imap_message_t **out_msgs; imap_message_t **out_msgs;
skipping to change at line 1275 skipping to change at line 1275
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "UIDNEXT", arg )) { } else if (!strcmp( "UIDNEXT", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidnext = strtoul( arg, &earg, 10 ), *earg != ']')) (ctx->uidnext = strtoul( arg, &earg, 10 ), *earg != ']'))
{ {
error( "IMAP error: malformed UIDNEXT status\n" ); error( "IMAP error: malformed UIDNEXT status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "CAPABILITY", arg )) { } else if (!strcmp( "CAPABILITY", arg )) {
if (!(p = strchr( s, ']' ))) { if (!s || !(p = strchr( s, ']' ))) {
error( "IMAP error: malformed CAPABILITY status\n" ); error( "IMAP error: malformed CAPABILITY status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
*p = 0; *p = 0;
parse_capability( ctx, s ); parse_capability( ctx, s );
} else if (!strcmp( "ALERT]", arg )) { } else if (!strcmp( "ALERT]", arg )) {
/* RFC2060 says that these messages MUST be displayed /* RFC2060 says that these messages MUST be displayed
* to the user * to the user
*/ */
if (!s) { if (!s) {
error( "IMAP error: malformed ALERT status\n" ); error( "IMAP error: malformed ALERT status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
for (; isspace( (uchar)*s ); s++); for (; isspace( (uchar)*s ); s++);
error( "*** IMAP ALERT *** %s\n", s ); error( "*** IMAP ALERT *** %s\n", s );
} else if (cmd && !strcmp( "APPENDUID", arg )) { } else if (!strcmp( "APPENDUID", arg )) {
// The checks ensure that:
// - cmd => this is the final tagged response of a command, at wh
ich
// point cmd was already removed from ctx->in_progress, so para
m.uid
// is available for reuse.
// - !param.uid => the command isn't actually a FETCH. This doesn
't
// really matter, as the field is safe to overwrite given the
// previous condition; it just has no effect for non-APPENDs.
if (!cmd || cmd->param.uid) {
error( "IMAP error: unexpected APPENDUID status\n" );
return RESP_CANCEL;
}
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) ||
!(arg = next_arg( &s )) || !(arg = next_arg( &s )) ||
(((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg != ']')) (cmd->param.uid = strtoul( arg, &earg, 10 ), *earg != ']'))
{ {
error( "IMAP error: malformed APPENDUID status\n" ); error( "IMAP error: malformed APPENDUID status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "PERMANENTFLAGS", arg )) { } else if (!strcmp( "PERMANENTFLAGS", arg )) {
parse_list_init( &ctx->parse_list_sts ); parse_list_init( &ctx->parse_list_sts );
if (parse_imap_list( NULL, &s, &ctx->parse_list_sts ) != LIST_OK || *s != ']') { if (parse_imap_list( NULL, &s, &ctx->parse_list_sts ) != LIST_OK || *s != ']') {
error( "IMAP error: malformed PERMANENTFLAGS status\n" ); error( "IMAP error: malformed PERMANENTFLAGS status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
skipping to change at line 1377 skipping to change at line 1388
static int static int
is_INBOX( imap_store_t *ctx, const char *arg, int argl ) is_INBOX( imap_store_t *ctx, const char *arg, int argl )
{ {
if (!starts_with( arg, argl, "INBOX", 5 )) if (!starts_with( arg, argl, "INBOX", 5 ))
return 0; return 0;
if (arg[5] && arg[5] != ctx->delimiter[0]) if (arg[5] && arg[5] != ctx->delimiter[0])
return 0; return 0;
return 1; return 1;
} }
static void
normalize_INBOX( imap_store_t *ctx, char *arg, int argl )
{
if (is_inbox( ctx, arg, argl ))
memcpy( arg, "INBOX", 5 );
}
static int static int
parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
{ {
string_list_t *narg; string_list_t *narg;
char *arg, c; char *arg, c;
int argl; int argl;
uint l; uint l;
if (!is_atom( list )) { if (!is_atom( list )) {
error( "IMAP error: malformed LIST response\n" ); error( "IMAP error: malformed LIST response\n" );
return LIST_BAD; return LIST_BAD;
} }
arg = list->val; arg = list->val;
argl = (int)list->len; argl = (int)list->len;
// The server might be weird and have a non-uppercase INBOX. It
// may legitimately do so, but we need the canonical spelling.
normalize_INBOX( ctx, arg, argl );
if ((l = strlen( ctx->prefix ))) { if ((l = strlen( ctx->prefix ))) {
if (!starts_with( arg, argl, ctx->prefix, l )) { if (!starts_with( arg, argl, ctx->prefix, l )) {
if (is_inbox( ctx, arg, argl )) { if (!is_INBOX( ctx, arg, argl ))
// INBOX and its subfolders bypass the namespace. return LIST_OK;
goto inbox; // INBOX and its subfolders bypass the namespace.
} else {
arg += l;
argl -= l;
// A folder named "INBOX" would be indistinguishable from
the
// actual INBOX after prefix stripping, so drop it. This
applies
// only to the fully uppercased spelling, as our canonica
l box
// names are case-sensitive (unlike IMAP's INBOX).
if (is_INBOX( ctx, arg, argl )) {
if (!arg[5]) // No need to complain about subfol
ders as well.
warn( "IMAP warning: ignoring INBOX in %s
\n", ctx->prefix );
return LIST_OK;
} }
return LIST_OK;
} }
arg += l;
argl -= l;
// A folder named "INBOX" would be indistinguishable from the
// actual INBOX after prefix stripping, so drop it. This applies
// only to the fully uppercased spelling, as our canonical box
// names are case-sensitive (unlike IMAP's INBOX).
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 );
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 bro ken servers */ if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround bro ken servers */
return LIST_OK; return LIST_OK;
if (map_name( arg, (char **)&narg, offsetof(string_list_t, string), ctx-> delimiter, "/") < 0) { if (map_name( arg, (char **)&narg, offsetof(string_list_t, string), ctx-> delimiter, "/") < 0) {
warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg ); warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg );
return LIST_OK; return LIST_OK;
} }
// Validate the normalized name. Technically speaking, we could tolerate // Validate the normalized name. Technically speaking, we could tolerate
// '//' and '/./', and '/../' being forbidden is a limitation of the Mail dir // '//' and '/./', and '/../' being forbidden is a limitation of the Mail dir
// driver, but there isn't really a legitimate reason for these being pre sent. // driver, but there isn't really a legitimate reason for these being pre sent.
skipping to change at line 2542 skipping to change at line 2554
ctx->delimiter[0] = ctx->ns_delimiter; ctx->delimiter[0] = ctx->ns_delimiter;
imap_open_store_finalize( ctx ); imap_open_store_finalize( ctx );
} }
static void static void
imap_open_store_finalize( imap_store_t *ctx ) imap_open_store_finalize( imap_store_t *ctx )
{ {
ctx->state = SST_GOOD; ctx->state = SST_GOOD;
if (!ctx->prefix) if (!ctx->prefix)
ctx->prefix = ""; ctx->prefix = "";
else
normalize_INBOX( ctx, ctx->prefix, -1 );
ctx->trashnc = TrashUnknown; ctx->trashnc = TrashUnknown;
ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux ); ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux );
} }
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
static void static void
imap_open_store_ssl_bail( imap_store_t *ctx ) imap_open_store_ssl_bail( imap_store_t *ctx )
{ {
/* This avoids that we try to send LOGOUT to an unusable socket. */ /* This avoids that we try to send LOGOUT to an unusable socket. */
socket_close( &ctx->conn ); socket_close( &ctx->conn );
skipping to change at line 3166 skipping to change at line 3180
if (data->flags) { if (data->flags) {
d = imap_make_flags( data->flags, flagstr ); d = imap_make_flags( data->flags, flagstr );
flagstr[d++] = ' '; flagstr[d++] = ' ';
} }
flagstr[d] = 0; flagstr[d] = 0;
INIT_IMAP_CMD(imap_cmd_out_uid_t, cmd, cb, aux) INIT_IMAP_CMD(imap_cmd_out_uid_t, cmd, cb, aux)
ctx->buffer_mem += data->len; ctx->buffer_mem += data->len;
cmd->param.data_len = data->len; cmd->param.data_len = data->len;
cmd->param.data = data->data; cmd->param.data = data->data;
cmd->out_uid = 0;
if (to_trash) { if (to_trash) {
cmd->param.create = 1; cmd->param.create = 1;
cmd->param.to_trash = 1; cmd->param.to_trash = 1;
if (prepare_trash( &buf, ctx ) < 0) { if (prepare_trash( &buf, ctx ) < 0) {
cb( DRV_BOX_BAD, 0, aux ); cb( DRV_BOX_BAD, 0, aux );
return; return;
} }
} else { } else {
if (prepare_box( &buf, ctx ) < 0) { if (prepare_box( &buf, ctx ) < 0) {
skipping to change at line 3202 skipping to change at line 3215
} }
free( buf ); free( buf );
} }
static void static void
imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response )
{ {
imap_cmd_out_uid_t *cmdp = (imap_cmd_out_uid_t *)cmd; imap_cmd_out_uid_t *cmdp = (imap_cmd_out_uid_t *)cmd;
transform_msg_response( &response ); transform_msg_response( &response );
cmdp->callback( response, cmdp->out_uid, cmdp->callback_aux ); cmdp->callback( response, cmdp->param.uid, cmdp->callback_aux );
} }
/******************* imap_find_new_msgs *******************/ /******************* imap_find_new_msgs *******************/
static void imap_find_new_msgs_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p2( imap_store_t *, imap_cmd_t *, int );
static void imap_find_new_msgs_p3( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p3( imap_store_t *, imap_cmd_t *, int );
static void imap_find_new_msgs_p4( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p4( imap_store_t *, imap_cmd_t *, int );
static void static void
imap_find_new_msgs( store_t *gctx, uint newuid, imap_find_new_msgs( store_t *gctx, uint newuid,
 End of changes. 15 change blocks. 
32 lines changed or deleted 51 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)