bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* message parts parsed from BODYSTRUCTURE */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mime_arg(struct mail_search_mime_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_parent_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* PARENT EXISTS: matches if this part has a parent.
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* PARENT <mpart-key>: matches if this part's parent matches the
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpart-key (subargs).
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mail_search_mime_args_reset(args->value.subargs, TRUE);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (args->value.subargs, search_mime_arg, mpctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_child_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* CHILD EXISTS: matches if this part has any children; i.e., it is
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* CHILD <mpart-key>: matches if this part has any child that mathes
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch the mpart-key (subargs).
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ARRAY(struct search_mimepart_stack) prev_stack;
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* preserve current stack for any nested CHILD PARENT nastiness */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_copy(&prev_stack.arr, 0, &mpctx->stack.arr, 0,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(depth == array_count(&mpctx->stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mail_search_mime_args_reset(args->value.subargs, TRUE);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (args->value.subargs, search_mime_arg, mpctx)) != 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_assert(depth == array_count(&mpctx->stack));
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (part->parent == NULL || part->parent == prev_part)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch level = array_idx_modifiable(&mpctx->stack, depth);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_copy(&mpctx->stack.arr, 0, &prev_stack.arr, 0,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Normalization is required */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type, time_t search_time,
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 struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type, const char *key,
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 return (strstr(str_c(addrs_enc), key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_filename_match(struct search_mimepart_context *mpctx,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct index_search_context *ictx = mpctx->index_ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (!message_part_data_get_filename(part, &value))
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch i_panic("search key not utf8: %s", arg->value.str);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strncmp(value, key, strlen(key)) == 0 ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strncmp(value + (vlen - alen), key, alen) == 0 ? 1 : 0);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_param_match(const struct message_part_param *params,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch unsigned int i;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Is normalization required? */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch for (i = 0; i < params_count; i++) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (strstr(params[i].value, key) != NULL ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschseach_arg_mime_language_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *key)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct message_part_data *data = mpctx->mime_part->data;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: Should use RFC 4647 matching rules */
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 const struct message_part_data *data = part->data;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size == arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size > arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (part->body_size.virtual_size < arg->value.size ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (data->content_transfer_encoding != NULL &&
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_language_match(mpctx, arg->value.str);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->type, arg->value.time, data->envelope);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->type, arg->value.str, data->envelope);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth == arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth >= arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->depth <= arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return (mpctx->index == arg->value.number ? 1 : 0);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_parent_match(mpctx, arg);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return seach_arg_mime_child_match(mpctx, arg);
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch return seach_arg_mime_filename_match(mpctx, arg);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mime_arg(struct mail_search_mime_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int seach_arg_mime_parts_match(struct search_mimepart_context *mpctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch array_delete(&mpctx->stack, array_count(&mpctx->stack)-1, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (&mpctx->stack, array_count(&mpctx->stack)-1);
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 index_search_context *ctx = mpctx->index_ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: could the mail object already have message_part tree with
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch MAIL_FETCH_IMAP_BODYSTRUCTURE, &bodystructure) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (imap_bodystructure_parse_full(bodystructure, mpctx->pool,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* FIXME: implement HEADER, BODY and TEXT (not from BODYSTRUCTURE)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch Needs to support FTS */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (mpctx, arg->value.mime_part->args, mpctx->mime_parts);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic void search_mimepart_arg(struct mail_search_arg *arg,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch switch (search_arg_match_mimepart(mpctx, arg)) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* unknown */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschint index_search_mime_arg_match(struct mail_search_arg *args,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Boschsearch_mime_arg_deinit(struct mail_search_mime_arg *arg,
2b1933b133f3e3571b32fa56fb823b4a6f9aab57Stephan Bosch struct search_mimepart_context *mpctx ATTR_UNUSED)