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