bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "lib.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "str.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "message-date.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "message-address.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "message-part-data.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "imap-bodystructure.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-search.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-search-mime.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "index-search-private.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstruct search_mimepart_stack {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch};
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstruct search_mimepart_context {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch pool_t pool;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct index_search_context *index_ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* message parts parsed from BODYSTRUCTURE */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *mime_parts, *mime_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch string_t *buf;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int depth, index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARRAY(struct search_mimepart_stack) stack;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch};
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mime_arg(struct mail_search_mime_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_parent_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *args)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *part = mpctx->mime_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int prev_depth, prev_index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_stack *level;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (args->value.subargs == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* PARENT EXISTS: matches if this part has a parent.
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->parent != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* PARENT <mpart-key>: matches if this part's parent matches the
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpart-key (subargs).
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch prev_depth = mpctx->depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch prev_index = mpctx->index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (&mpctx->stack, mpctx->depth-1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->mime_part = part->parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mail_search_mime_args_reset(args->value.subargs, TRUE);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->index = level->index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->depth = mpctx->depth-1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ret = mail_search_mime_args_foreach
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (args->value.subargs, search_mime_arg, mpctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->mime_part = part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->index = prev_index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->depth = prev_depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_child_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *args)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *part, *prev_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int prev_depth, prev_index, depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_stack *level;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret = 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = mpctx->mime_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (args->value.subargs == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* CHILD EXISTS: matches if this part has any children; i.e., it is
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch multipart.
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->children != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* CHILD <mpart-key>: matches if this part has any child that mathes
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch the mpart-key (subargs).
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch prev_part = part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch prev_depth = mpctx->depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch prev_index = mpctx->index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch depth = mpctx->depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch T_BEGIN {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARRAY(struct search_mimepart_stack) prev_stack;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* preserve current stack for any nested CHILD PARENT nastiness */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch t_array_init(&prev_stack, 16);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_copy(&prev_stack.arr, 0, &mpctx->stack.arr, 0,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_count(&mpctx->stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch depth++;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (depth < array_count(&mpctx->stack))
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(depth == array_count(&mpctx->stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_append_space(&mpctx->stack);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index = 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->children;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while (part != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->mime_part = part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mail_search_mime_args_reset(args->value.subargs, TRUE);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->depth = depth - prev_depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->index = level->index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if ((ret=mail_search_mime_args_foreach
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (args->value.subargs, search_mime_arg, mpctx)) != 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (part->children != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch depth++;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (depth < array_count(&mpctx->stack))
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(depth == array_count(&mpctx->stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_append_space(&mpctx->stack);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index = 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->children;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while (part->next == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (part->parent == NULL || part->parent == prev_part)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch depth--;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index++;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->next;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_clear(&mpctx->stack);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_copy(&mpctx->stack.arr, 0, &prev_stack.arr, 0,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_count(&prev_stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } T_END;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->mime_part = prev_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->index = prev_index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->depth = prev_depth;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_substring_match(
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *key, const char *value)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (value == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Normalization is required */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strstr(value, key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_envelope_time_match(
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type, time_t search_time,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const struct message_part_envelope *envelope)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch time_t sent_time;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int timezone_offset;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (envelope == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* NOTE: RFC-3501 specifies that timezone is ignored
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch in searches. sent_time is returned as UTC, so change it. */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch // FIXME: adjust comment
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (!message_date_parse((const unsigned char *)envelope->date,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strlen(envelope->date), &sent_time, &timezone_offset))
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sent_time += timezone_offset * 60;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (type) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTBEFORE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return sent_time < search_time ? 1 : 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTON:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (sent_time >= search_time &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sent_time < search_time + 3600*24) ? 1 : 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTSINCE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return sent_time >= search_time ? 1 : 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch default:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_unreached();
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_envelope_address_match(
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type, const char *key,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const struct message_part_envelope *envelope)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const struct message_address *addrs;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch string_t *addrs_enc;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (envelope == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (type) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_CC:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->cc;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_BCC:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->bcc;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FROM:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->from;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENDER:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->sender;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_REPLY_TO:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->reply_to;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_TO:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs = envelope->to;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch default:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_unreached();
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: do we need to normalize anything? at least case insensitivity.
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch MIME header encoding will make this a bit difficult, so it should
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch probably be normalized directly in the struct message_address. */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch addrs_enc = t_str_new(128);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch message_address_write(addrs_enc, addrs);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strstr(str_c(addrs_enc), key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_filename_match(struct search_mimepart_context *mpctx,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct mail_search_mime_arg *arg)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct index_search_context *ictx = mpctx->index_ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *part = mpctx->mime_part;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch char *key;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *value;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch size_t vlen, alen;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (!message_part_data_get_filename(part, &value))
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch if (mpctx->buf == NULL)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch mpctx->buf = str_new(default_pool, 256);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch if (arg->context == NULL) {
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch str_truncate(mpctx->buf, 0);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch if (ictx->mail_ctx.normalizer(arg->value.str,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch strlen(arg->value.str), mpctx->buf) < 0)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch i_panic("search key not utf8: %s", arg->value.str);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch key = i_strdup(str_c(mpctx->buf));
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch arg->context = (void *)key;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch } else {
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch key = (char *)arg->context;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch }
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch str_truncate(mpctx->buf, 0);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch if (ictx->mail_ctx.normalizer(value,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch strlen(value), mpctx->buf) >= 0)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch value = str_c(mpctx->buf);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch switch (arg->type) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_IS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strcmp(value, key) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_CONTAINS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strstr(value, key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_BEGINS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strncmp(value, key, strlen(key)) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_ENDS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch vlen = strlen(value);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch alen = strlen(key);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strncmp(value + (vlen - alen), key, alen) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch default:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_unreached();
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschstatic void
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschsearch_arg_mime_filename_deinit(
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct mail_search_mime_arg *arg)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch{
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch char *key = (char *)arg->context;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch i_free(key);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_param_match(const struct message_part_param *params,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int params_count,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *name, const char *key)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int i;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Is normalization required? */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch for (i = 0; i < params_count; i++) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (strcasecmp(params[i].name, name) == 0) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (key == NULL || *key == '\0')
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strstr(params[i].value, key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_language_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *key)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part_data *data = mpctx->mime_part->data;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *const *lang;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(data != NULL);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch lang = data->content_language;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (lang != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while (*lang != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Should use RFC 4647 matching rules */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (strcasecmp(*lang, key) == 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch lang++;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch/* Returns >0 = matched, 0 = not matched (unused), -1 = unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int search_mime_arg_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *arg)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *part = mpctx->mime_part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const struct message_part_data *data = part->data;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(data != NULL);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (arg->type) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_OR:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SUB:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_unreached();
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SIZE_EQUAL:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size == arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SIZE_LARGER:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size > arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SIZE_SMALLER:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size < arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DESCRIPTION:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_substring_match(mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str, data->content_description);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DISPOSITION_TYPE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_disposition != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_disposition,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DISPOSITION_PARAM:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_param_match
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (data->content_disposition_params,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch data->content_disposition_params_count,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->field_name, arg->value.str);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_ENCODING:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_transfer_encoding != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_transfer_encoding,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_ID:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_id != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_id,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_LANGUAGE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_language_match(mpctx, arg->value.str);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_LOCATION:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_location != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_location,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_MD5:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_md5 != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcmp(data->content_md5,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_TYPE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_type != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_type,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SUBTYPE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_subtype != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch strcasecmp(data->content_subtype,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_PARAM:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_param_match
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (data->content_type_params,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch data->content_type_params_count,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->field_name, arg->value.str);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTBEFORE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTON:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENTSINCE:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_envelope_time_match
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->type, arg->value.time, data->envelope);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_CC:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_BCC:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FROM:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_REPLY_TO:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SENDER:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_TO:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_envelope_address_match
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->type, arg->value.str, data->envelope);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_SUBJECT:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (data->envelope == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_substring_match(mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str, data->envelope->subject);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_IN_REPLY_TO:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (data->envelope == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_substring_match(mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str, data->envelope->in_reply_to);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_MESSAGE_ID:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (data->envelope == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_substring_match(mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->value.str, data->envelope->message_id);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DEPTH_EQUAL:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth == arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DEPTH_MIN:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth >= arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_DEPTH_MAX:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth <= arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_INDEX:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->index == arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_PARENT:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_parent_match(mpctx, arg);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_CHILD:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_child_match(mpctx, arg);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_IS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_CONTAINS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_BEGINS:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_FILENAME_ENDS:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch return seach_arg_mime_filename_match(mpctx, arg);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_HEADER:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_BODY:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case SEARCH_MIME_TEXT:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mime_arg(struct mail_search_mime_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (search_mime_arg_match(mpctx, arg)) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case -1:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case 0:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARG_SET_RESULT(arg, 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch default:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARG_SET_RESULT(arg, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_parts_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *args,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *parts)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part *part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_stack *level;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_append_space(&mpctx->stack);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index = 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = parts;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while (part != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->mime_part = part;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mail_search_mime_args_reset(args, TRUE);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->index = level->index;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->depth = array_count(&mpctx->stack)-1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if ((ret=mail_search_mime_args_foreach
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (args, search_mime_arg, mpctx)) != 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (part->children != NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_append_space(&mpctx->stack);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index = 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->children;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while (part->next == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (part->parent == NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_delete(&mpctx->stack, array_count(&mpctx->stack)-1, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (&mpctx->stack, array_count(&mpctx->stack)-1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level->index++;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch part = part->next;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch/* Returns >0 = matched, 0 = not matched, -1 = unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int search_arg_match_mimepart(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_arg *arg)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct index_search_context *ctx = mpctx->index_ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *bodystructure, *error;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (arg->type != SEARCH_MIMEPART)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (mpctx->pool == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx->pool = pool_alloconly_create
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (MEMPOOL_GROWING"search mime parts", 4096);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch p_array_init(&mpctx->stack, mpctx->pool, 16);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (mpctx->mime_parts == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: could the mail object already have message_part tree with
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch data? */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (mail_get_special(ctx->cur_mail,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch MAIL_FETCH_IMAP_BODYSTRUCTURE, &bodystructure) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (imap_bodystructure_parse_full(bodystructure, mpctx->pool,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch &mpctx->mime_parts, &error) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: implement HEADER, BODY and TEXT (not from BODYSTRUCTURE)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch Needs to support FTS */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_parts_match
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->value.mime_part->args, mpctx->mime_parts);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mimepart_arg(struct mail_search_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (search_arg_match_mimepart(mpctx, arg)) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case -1:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch case 0:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARG_SET_RESULT(arg, 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch default:
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARG_SET_RESULT(arg, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch break;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschint index_search_mime_arg_match(struct mail_search_arg *args,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct index_search_context *ctx)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context mpctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_zero(&mpctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpctx.index_ctx = ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ret = mail_search_args_foreach(args,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch search_mimepart_arg, &mpctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
c69a177207ed18d0f0210347430a60957136bd6cJosef 'Jeff' Sipek pool_unref(&mpctx.pool);
e9fbe5e18b798728041b7e2ffc6c4fa964fc35a3Josef 'Jeff' Sipek str_free(&mpctx.buf);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschstatic void
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschsearch_mime_arg_deinit(struct mail_search_mime_arg *arg,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch{
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch switch (arg->type) {
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch case SEARCH_MIME_FILENAME_IS:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch case SEARCH_MIME_FILENAME_CONTAINS:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch case SEARCH_MIME_FILENAME_BEGINS:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch case SEARCH_MIME_FILENAME_ENDS:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch search_arg_mime_filename_deinit(mpctx, arg);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch break;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch default:
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch break;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch }
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch}
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschvoid index_search_mime_arg_deinit(struct mail_search_arg *arg,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct index_search_context *ctx)
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch{
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct search_mimepart_context mpctx;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct mail_search_mime_arg *args;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch i_assert(arg->type == SEARCH_MIMEPART);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch args = arg->value.mime_part->args;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch i_zero(&mpctx);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch mpctx.index_ctx = ctx;
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch mail_search_mime_args_reset(args, TRUE);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch (void)mail_search_mime_args_foreach(args,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch search_mime_arg_deinit, &mpctx);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch}