Coverage Report

Created: 2026-06-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-storage/mail-search-mime-build.c
Line
Count
Source
1
/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "str.h"
5
#include "charset-utf8.h"
6
#include "mail-storage-private.h"
7
#include "mail-search-parser.h"
8
#include "mail-search-mime-register.h"
9
#include "mail-search-mime-build.h"
10
11
static int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx,
12
          struct mail_search_mime_arg **arg_r);
13
14
struct mail_search_mime_arg *
15
mail_search_mime_build_new(struct mail_search_mime_build_context *ctx,
16
          enum mail_search_mime_arg_type type)
17
0
{
18
0
  struct mail_search_mime_arg *arg;
19
20
0
  arg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1);
21
0
  arg->type = type;
22
0
  return arg;
23
0
}
24
25
struct mail_search_mime_arg *
26
mail_search_mime_build_str(struct mail_search_mime_build_context *ctx,
27
          enum mail_search_mime_arg_type type)
28
0
{
29
0
  struct mail_search_mime_arg *sarg;
30
0
  const char *value;
31
32
0
  sarg = mail_search_mime_build_new(ctx, type);
33
0
  if (mail_search_parse_string(ctx->ctx->parser, &value) < 0)
34
0
    return NULL;
35
0
  sarg->value.str = p_strdup(ctx->ctx->pool, value);
36
0
  return sarg;
37
0
}
38
39
static int
40
mail_search_mime_build_key_int(struct mail_search_mime_build_context *ctx,
41
        struct mail_search_mime_arg *parent,
42
        struct mail_search_mime_arg **arg_r)
43
0
{
44
0
  struct mail_search_mime_arg *sarg;
45
0
  struct mail_search_mime_arg *old_parent = ctx->parent;
46
0
  const char *key;
47
0
  const struct mail_search_mime_register_arg *reg_arg;
48
0
  int ret;
49
50
0
  ctx->parent = parent;
51
52
0
  if ((ret = mail_search_parse_key(ctx->ctx->parser, &key)) <= 0)
53
0
    return ret;
54
55
0
  if (strcmp(key, MAIL_SEARCH_PARSER_KEY_LIST) == 0) {
56
0
    if (mail_search_mime_build_list(ctx, &sarg) < 0)
57
0
      return -1;
58
0
    if (sarg->value.subargs == NULL) {
59
0
      ctx->ctx->_error = "No MIMEPART keys inside list";
60
0
      return -1;
61
0
    }
62
63
0
    ctx->parent = old_parent;
64
0
    *arg_r = sarg;
65
0
    return 1;
66
0
  }
67
0
  key = t_str_ucase(key);
68
69
0
  reg_arg = mail_search_mime_register_find(key);
70
0
  if (reg_arg != NULL)
71
0
    sarg = reg_arg->build(ctx);
72
0
  else {
73
0
    sarg = NULL;
74
0
    ctx->ctx->_error = p_strconcat
75
0
      (ctx->ctx->pool, "Unknown MIMEPART key ", key, NULL);
76
0
  }
77
78
0
  ctx->parent = old_parent;
79
0
  *arg_r = sarg;
80
0
  return sarg == NULL ? -1 : 1;
81
0
}
82
83
int mail_search_mime_build_key(struct mail_search_mime_build_context *ctx,
84
        struct mail_search_mime_arg *parent,
85
        struct mail_search_mime_arg **arg_r)
86
0
{
87
0
  int ret;
88
89
0
  ret = mail_search_mime_build_key_int(ctx, parent, arg_r);
90
0
  if (ret <= 0) {
91
0
    if (ret == 0)
92
0
      ctx->ctx->_error = "Missing MIMEPART key";
93
0
    return -1;
94
0
  }
95
0
  return 0;
96
0
}
97
98
static int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx,
99
          struct mail_search_mime_arg **arg_r)
100
0
{
101
0
  struct mail_search_mime_arg *sarg, **subargs;
102
0
  enum mail_search_mime_arg_type cur_type = SEARCH_MIME_SUB;
103
0
  int ret;
104
105
0
  sarg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1);
106
0
  sarg->type = cur_type;
107
108
0
  subargs = &sarg->value.subargs;
109
0
  while ((ret = mail_search_mime_build_key_int(ctx, sarg, subargs)) > 0) {
110
0
    if (cur_type == sarg->type) {
111
      /* expected type */
112
0
    } else if (cur_type == SEARCH_MIME_SUB) {
113
      /* type changed. everything in this list must now
114
         belong to this type. */
115
0
      cur_type = sarg->type;
116
0
    } else {
117
0
      ctx->ctx->_error =
118
0
        "Use parenthesis when mixing ANDs and ORs";
119
0
      return -1;
120
0
    }
121
0
    subargs = &(*subargs)->next;
122
0
    sarg->type = SEARCH_MIME_SUB;
123
0
  }
124
0
  if (ret < 0)
125
0
    return -1;
126
0
  sarg->type = cur_type;
127
0
  *arg_r = sarg;
128
0
  return 0;
129
0
}
130
131
int mail_search_mime_build(struct mail_search_build_context *bctx,
132
          struct mail_search_mime_part **mpart_r)
133
0
{
134
0
  struct mail_search_mime_build_context ctx;
135
0
  struct mail_search_mime_part *mpart;
136
0
  struct mail_search_mime_arg *root;
137
0
  int ret;
138
139
0
  *mpart_r = NULL;
140
141
0
  i_zero(&ctx);
142
0
  ctx.ctx = bctx;
143
0
  ctx.mime_part = mpart =
144
0
    p_new(bctx->pool, struct mail_search_mime_part, 1);
145
146
0
  if ((ret=mail_search_mime_build_key(&ctx, NULL, &root)) < 0)
147
0
    return ret;
148
149
0
  if (root->type == SEARCH_MIME_SUB && !root->match_not) {
150
    /* simple SUB root */
151
0
    mpart->args = root->value.subargs;
152
0
  } else {
153
0
    mpart->args = root;
154
0
  }
155
156
0
  *mpart_r = mpart;
157
0
  return 0;
158
0
}
159
160
struct mail_search_mime_arg *
161
mail_search_mime_build_add(pool_t pool,
162
          struct mail_search_mime_part *mpart,
163
          enum mail_search_mime_arg_type type)
164
0
{
165
0
  struct mail_search_mime_arg *arg;
166
167
0
  arg = p_new(pool, struct mail_search_mime_arg, 1);
168
0
  arg->type = type;
169
170
0
  arg->next = mpart->args;
171
0
  mpart->args = arg;
172
0
  return arg;
173
0
}