Coverage Report

Created: 2026-10-28 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/sieve-storage-settings.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "str-sanitize.h"
5
#include "array.h"
6
#include "sort.h"
7
#include "settings.h"
8
#include "settings-parser.h"
9
10
#include "sieve-script.h"
11
#include "sieve-storage.h"
12
#include "sieve-storage-settings.h"
13
14
static bool
15
sieve_storage_settings_check(void *_set, pool_t pool, const char **error_r);
16
17
#undef DEF
18
#define DEF(type, name) SETTING_DEFINE_STRUCT_##type( \
19
  "sieve_"#name, name, \
20
  struct sieve_storage_settings)
21
22
static const struct setting_filter_array_order sieve_storage_order_precedence = {
23
  .info = &sieve_storage_setting_parser_info,
24
  .field_name = "sieve_script_precedence",
25
};
26
27
static const struct setting_define sieve_storage_setting_defines[] = {
28
  DEF(STR, script_storage),
29
  DEF(UINT, script_precedence),
30
31
  DEF(STR, script_type),
32
  DEF(BOOLLIST, script_cause),
33
  DEF(STR, script_driver),
34
  DEF(STR, script_name),
35
  DEF(STR, script_bin_path),
36
37
  DEF(SIZE, quota_storage_size),
38
  DEF(UINT, quota_script_count),
39
40
  { .type = SET_FILTER_ARRAY, .key = "sieve_script",
41
     .offset = offsetof(struct sieve_storage_settings, storages),
42
     .filter_array_field_name = "sieve_script_storage",
43
     .filter_array_order = &sieve_storage_order_precedence },
44
45
  SETTING_DEFINE_LIST_END,
46
};
47
48
static const struct sieve_storage_settings sieve_storage_default_settings = {
49
  .script_storage = "",
50
  .script_precedence = UINT_MAX,
51
52
  .script_type = SIEVE_STORAGE_TYPE_PERSONAL,
53
  .script_cause = ARRAY_INIT,
54
55
  .script_driver = "file",
56
  .script_name = "",
57
  .script_bin_path = "",
58
59
  .quota_storage_size = SET_SIZE_UNLIMITED,
60
  .quota_script_count = SET_UINT_UNLIMITED,
61
62
  .storages = ARRAY_INIT,
63
};
64
65
const struct setting_parser_info sieve_storage_setting_parser_info = {
66
  .name = "sieve_storage",
67
68
  .defines = sieve_storage_setting_defines,
69
  .defaults = &sieve_storage_default_settings,
70
71
  .struct_size = sizeof(struct sieve_storage_settings),
72
73
  .pool_offset1 = 1 + offsetof(struct sieve_storage_settings, pool),
74
75
  .check_func = sieve_storage_settings_check,
76
};
77
78
/* <settings checks> */
79
static bool
80
sieve_storage_settings_check(void *_set, pool_t pool ATTR_UNUSED,
81
           const char **error_r)
82
0
{
83
0
  struct sieve_storage_settings *set = _set;
84
85
0
  if (*set->script_storage != '\0' &&
86
0
      !sieve_storage_name_is_valid(set->script_storage)) {
87
0
    *error_r = t_strdup_printf(
88
0
      "Invalid script storage name '%s'",
89
0
      str_sanitize(set->script_storage, 128));
90
0
    return FALSE;
91
0
  }
92
0
  if (*set->script_name != '\0' &&
93
0
      !sieve_script_name_is_valid(set->script_name)) {
94
0
    *error_r = t_strdup_printf(
95
0
      "Invalid script name '%s'",
96
0
      str_sanitize(set->script_name, 128));
97
0
    return FALSE;
98
0
  }
99
100
0
  if (set->quota_storage_size == 0) {
101
0
    *error_r = "quota_storage_size must not be 0";
102
0
    return FALSE;
103
0
  }
104
0
  if (set->quota_script_count == 0) {
105
0
    *error_r = "quota_script_count must not be 0";
106
0
    return FALSE;
107
0
  }
108
109
0
  if (array_is_created(&set->script_cause))
110
0
    array_sort(&set->script_cause, i_strcmp_p);
111
112
0
  return TRUE;
113
0
}
114
/* </settings checks> */
115
116
bool sieve_storage_settings_match_script_type(
117
  const struct sieve_storage_settings *set, const char *type)
118
0
{
119
0
  if (strcasecmp(type, SIEVE_STORAGE_TYPE_ANY) == 0)
120
0
    return TRUE;
121
0
  if (strcasecmp(type, set->script_type) == 0)
122
0
    return TRUE;
123
0
  return FALSE;
124
0
}
125
126
bool sieve_storage_settings_match_script_cause(
127
  const struct sieve_storage_settings *set, const char *cause)
128
0
{
129
0
  if (strcasecmp(cause, SIEVE_SCRIPT_CAUSE_ANY) == 0) {
130
    /* Any cause will match */
131
0
    return TRUE;
132
0
  }
133
0
  if (!array_is_created(&set->script_cause)) {
134
    /* Causes are not configured for this storage */
135
0
    if (strcasecmp(set->script_type,
136
0
             SIEVE_STORAGE_TYPE_PERSONAL) == 0) {
137
      /* For personal storages the default is to match any
138
         cause. */
139
0
      return TRUE;
140
0
    }
141
0
    if (strcasecmp(cause, SIEVE_SCRIPT_CAUSE_DELIVERY) == 0) {
142
      /* The default cause is delivery */
143
0
      return TRUE;
144
0
    }
145
0
    return FALSE;
146
0
  }
147
148
  /* Causes are configured for this storage: perform lookup */
149
150
0
  unsigned int set_cause_count;
151
0
  const char *const *set_cause;
152
153
0
  set_cause = array_get(&set->script_cause, &set_cause_count);
154
0
  return (i_bsearch(cause, set_cause, set_cause_count,
155
       sizeof(const char *), search_strcasecmp) != NULL);
156
0
}