Coverage Report

Created: 2026-08-08 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/sieve-execute.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
5
#include "sieve-execute.h"
6
7
struct sieve_execute_state {
8
  void *dup_trans;
9
};
10
11
struct event_category event_category_sieve_execute = {
12
  .parent = &event_category_sieve,
13
  .name = "sieve-execute",
14
};
15
16
static struct sieve_execute_state *
17
sieve_execute_state_create(struct sieve_execute_env *eenv)
18
0
{
19
0
  return p_new(eenv->pool, struct sieve_execute_state, 1);
20
0
}
21
22
static void
23
sieve_execute_state_free(struct sieve_execute_state **_estate,
24
       struct sieve_execute_env *eenv)
25
0
{
26
0
  struct sieve_execute_state *estate = *_estate;
27
0
  const struct sieve_script_env *senv = eenv->scriptenv;
28
29
0
  *_estate = NULL;
30
31
0
  if (senv->duplicate_transaction_rollback != NULL)
32
0
    senv->duplicate_transaction_rollback(&estate->dup_trans);
33
0
}
34
35
void sieve_execute_init(struct sieve_execute_env *eenv,
36
      struct sieve_instance *svinst, pool_t pool,
37
      const struct sieve_message_data *msgdata,
38
      const struct sieve_script_env *senv,
39
      enum sieve_execute_flags flags)
40
0
{
41
0
  i_assert(svinst->username != NULL);
42
43
0
  i_zero(eenv);
44
0
  eenv->svinst = svinst;
45
0
  eenv->pool = pool;
46
0
  eenv->flags = flags;
47
0
  eenv->msgdata = msgdata;
48
0
  eenv->scriptenv = senv;
49
50
0
  pool_ref(pool);
51
0
  eenv->event = event_create(svinst->event);
52
0
  event_add_category(eenv->event, &event_category_sieve_execute);
53
0
  event_add_str(eenv->event, "message_id", msgdata->id);
54
0
  if ((flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) {
55
    /* Make sure important envelope fields are available */
56
0
    event_add_str(eenv->event, "mail_from",
57
0
      smtp_address_encode(msgdata->envelope.mail_from));
58
0
    event_add_str(eenv->event, "rcpt_to",
59
0
      smtp_address_encode(msgdata->envelope.rcpt_to));
60
0
  }
61
62
0
  eenv->state = sieve_execute_state_create(eenv);
63
64
0
  eenv->exec_status = senv->exec_status;
65
0
  if (eenv->exec_status == NULL)
66
0
    eenv->exec_status = p_new(pool, struct sieve_exec_status, 1);
67
0
  else
68
0
    i_zero(eenv->exec_status);
69
0
}
70
71
void sieve_execute_finish(struct sieve_execute_env *eenv, int status)
72
0
{
73
0
  const struct sieve_script_env *senv = eenv->scriptenv;
74
75
0
  if (status == SIEVE_EXEC_OK) {
76
0
    if (senv->duplicate_transaction_commit != NULL) {
77
0
      senv->duplicate_transaction_commit(
78
0
        &eenv->state->dup_trans);
79
0
    }
80
0
  } else {
81
0
    if (senv->duplicate_transaction_rollback != NULL) {
82
0
      senv->duplicate_transaction_rollback(
83
0
        &eenv->state->dup_trans);
84
0
    }
85
0
  }
86
0
}
87
88
void sieve_execute_deinit(struct sieve_execute_env *eenv)
89
0
{
90
0
  sieve_execute_state_free(&eenv->state, eenv);
91
0
  event_unref(&eenv->event);
92
0
  pool_unref(&eenv->pool);
93
0
}
94
95
/*
96
 * Checking for duplicates
97
 */
98
99
static void *
100
sieve_execute_get_dup_transaction(const struct sieve_execute_env *eenv)
101
0
{
102
0
  const struct sieve_script_env *senv = eenv->scriptenv;
103
104
0
  if (senv->duplicate_transaction_begin == NULL)
105
0
    return NULL;
106
0
  if (eenv->state->dup_trans == NULL) {
107
0
    eenv->state->dup_trans =
108
0
      senv->duplicate_transaction_begin(senv);
109
0
  }
110
0
  return eenv->state->dup_trans;
111
0
}
112
113
bool sieve_execute_duplicate_check_available(
114
  const struct sieve_execute_env *eenv)
115
0
{
116
0
  const struct sieve_script_env *senv = eenv->scriptenv;
117
118
0
  return (senv->duplicate_transaction_begin != NULL);
119
0
}
120
121
int sieve_execute_duplicate_check(const struct sieve_execute_env *eenv,
122
          const void *id, size_t id_size,
123
          bool *duplicate_r)
124
0
{
125
0
  const struct sieve_script_env *senv = eenv->scriptenv;
126
0
  void *dup_trans = sieve_execute_get_dup_transaction(eenv);
127
0
  int ret;
128
129
0
  *duplicate_r = FALSE;
130
131
0
  if (senv->duplicate_check == NULL)
132
0
    return SIEVE_EXEC_OK;
133
134
0
  e_debug(eenv->svinst->event, "Check duplicate ID");
135
136
0
  ret = senv->duplicate_check(dup_trans, senv, id, id_size);
137
0
  switch (ret) {
138
0
  case SIEVE_DUPLICATE_CHECK_RESULT_EXISTS:
139
0
    *duplicate_r = TRUE;
140
0
    break;
141
0
  case SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND:
142
0
    break;
143
0
  case SIEVE_DUPLICATE_CHECK_RESULT_FAILURE:
144
0
    return SIEVE_EXEC_FAILURE;
145
0
  case SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE:
146
0
    return SIEVE_EXEC_TEMP_FAILURE;
147
0
  }
148
0
  return SIEVE_EXEC_OK;
149
0
}
150
151
void sieve_execute_duplicate_mark(const struct sieve_execute_env *eenv,
152
          const void *id, size_t id_size, time_t time)
153
0
{
154
0
  const struct sieve_script_env *senv = eenv->scriptenv;
155
0
  void *dup_trans = sieve_execute_get_dup_transaction(eenv);
156
157
0
  if (senv->duplicate_mark == NULL)
158
0
    return;
159
160
0
  e_debug(eenv->svinst->event, "Mark ID as duplicate");
161
162
0
  senv->duplicate_mark(dup_trans, senv, id, id_size, time);
163
0
}