Skip to content

Commit

Permalink
imap: support for FETCH SNIPPET
Browse files Browse the repository at this point in the history
  • Loading branch information
Josef 'Jeff' Sipek committed Jan 24, 2018
1 parent 572b05e commit f386bd2
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 1 deletion.
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -2953,7 +2953,7 @@ dnl **
dnl IDLE doesn't really belong to banner. It's there just to make Blackberries
dnl happy, because otherwise BIS server disables push email.
capability_banner="IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE"
capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY"
AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", [IMAP capabilities])
AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", [IMAP capabilities advertised in banner])

Expand Down
89 changes: 89 additions & 0 deletions src/imap/imap-fetch-body.c
Expand Up @@ -587,3 +587,92 @@ bool imap_fetch_rfc822_init(struct imap_fetch_init_context *ctx)
ctx->error = t_strconcat("Unknown parameter ", name, NULL);
return FALSE;
}

static int ATTR_NULL(3)
fetch_snippet(struct imap_fetch_context *ctx, struct mail *mail,
void *context)
{
const bool lazy = context != NULL;
enum mail_lookup_abort temp_lookup_abort = lazy ? MAIL_LOOKUP_ABORT_NOT_IN_CACHE : mail->lookup_abort;
enum mail_lookup_abort orig_lookup_abort = mail->lookup_abort;
const char *snippet;
const char *str;
int ret;

mail->lookup_abort = temp_lookup_abort;
ret = mail_get_special(mail, MAIL_FETCH_BODY_SNIPPET, &snippet);
mail->lookup_abort = orig_lookup_abort;

if (ret == 0) {
/* got it => nothing to do */
snippet++; /* skip over snippet version byte */
} else if (mailbox_get_last_mail_error(mail->box) != MAIL_ERROR_LOOKUP_ABORTED) {
/* actual error => bail */
return -1;
} else if (lazy) {
/* not in cache && lazy => give up */
return 1;
} else {
/*
* not in cache && !lazy => someone higher up set
* MAIL_LOOKUP_ABORT_NOT_IN_CACHE and so even though we got
* a non-lazy request we failed the cache lookup.
*
* This is not an error, but since the scenario is
* sufficiently convoluted this else branch serves to
* document it.
*/
return 1;
}

str = t_strdup_printf(" SNIPPET FUZZY {%"PRIuSIZE_T"}\r\n", strlen(snippet));
if (ctx->state.cur_first) {
str++;
ctx->state.cur_first = FALSE;
}
o_stream_nsend_str(ctx->client->output, str);
o_stream_nsend_str(ctx->client->output, snippet);

return 1;
}

bool imap_fetch_snippet_init(struct imap_fetch_init_context *ctx)
{
const struct imap_arg *list_args;
unsigned int list_count;
bool lazy;

lazy = FALSE;

if (imap_arg_get_list_full(&ctx->args[0], &list_args, &list_count)) {
unsigned int i;

for (i = 0; i < list_count; i++) {
const char *str;

if (!imap_arg_get_atom(&list_args[i], &str)) {
ctx->error = "Invalid SNIPPET algorithm/modifier";
return FALSE;
}

if (strcasecmp(str, "LAZY") == 0 ||
strcasecmp(str, "LAZY=FUZZY") == 0) {
lazy = TRUE;
} else if (strcasecmp(str, "FUZZY") == 0) {
/* nothing to do */
} else {
ctx->error = t_strdup_printf("'%s' is not a "
"supported SNIPPET algorithm/modifier",
str);
return FALSE;
}
}

ctx->args += list_count;
}

ctx->fetch_ctx->fetch_data |= MAIL_FETCH_BODY_SNIPPET;
ctx->fetch_ctx->flags_update_seen = TRUE;
imap_fetch_add_handler(ctx, 0, "NIL", fetch_snippet, (void *) lazy);
return TRUE;
}
1 change: 1 addition & 0 deletions src/imap/imap-fetch.c
Expand Up @@ -997,6 +997,7 @@ imap_fetch_default_handlers[] = {
{ "INTERNALDATE", fetch_internaldate_init },
{ "MODSEQ", imap_fetch_modseq_init },
{ "RFC822", imap_fetch_rfc822_init },
{ "SNIPPET", imap_fetch_snippet_init },
{ "UID", imap_fetch_uid_init },
{ "X-GUID", fetch_guid_init },
{ "X-MAILBOX", fetch_x_mailbox_init },
Expand Down
1 change: 1 addition & 0 deletions src/imap/imap-fetch.h
Expand Up @@ -154,6 +154,7 @@ bool imap_fetch_uid_init(struct imap_fetch_init_context *ctx);
bool imap_fetch_body_section_init(struct imap_fetch_init_context *ctx);
bool imap_fetch_rfc822_init(struct imap_fetch_init_context *ctx);
bool imap_fetch_binary_init(struct imap_fetch_init_context *ctx);
bool imap_fetch_snippet_init(struct imap_fetch_init_context *ctx);

void imap_fetch_handlers_init(void);
void imap_fetch_handlers_deinit(void);
Expand Down

0 comments on commit f386bd2

Please sign in to comment.