Coverage Report

Created: 2026-07-30 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/sieve-storage.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "str.h"
6
#include "str-sanitize.h"
7
#include "hash.h"
8
#include "home-expand.h"
9
#include "eacces-error.h"
10
#include "mkdir-parents.h"
11
#include "ioloop.h"
12
#include "settings.h"
13
#include "settings-consts.h"
14
15
#include "sieve-common.h"
16
#include "sieve-error-private.h"
17
18
#include "sieve-script-private.h"
19
#include "sieve-storage-private.h"
20
21
#include <sys/types.h>
22
#include <sys/stat.h>
23
#include <unistd.h>
24
#include <time.h>
25
#include <utime.h>
26
27
struct event_category event_category_sieve_storage = {
28
  .parent = &event_category_sieve,
29
  .name = "sieve-storage",
30
};
31
32
/*
33
 * Storage name
34
 */
35
36
bool sieve_storage_name_is_valid(const char *name)
37
0
{
38
0
  return sieve_script_name_is_valid(name);
39
0
}
40
41
/*
42
 * Storage class
43
 */
44
45
struct sieve_storage_class_registry {
46
  ARRAY_TYPE(sieve_storage_class) storage_classes;
47
};
48
49
void sieve_storages_init(struct sieve_instance *svinst)
50
0
{
51
0
  svinst->storage_reg = p_new(svinst->pool,
52
0
            struct sieve_storage_class_registry, 1);
53
0
  p_array_init(&svinst->storage_reg->storage_classes, svinst->pool, 8);
54
55
0
  sieve_storage_class_register(svinst, &sieve_file_storage);
56
0
  sieve_storage_class_register(svinst, &sieve_dict_storage);
57
#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD)
58
  sieve_storage_class_register(svinst, &sieve_ldap_storage);
59
#endif
60
0
}
61
62
void sieve_storages_deinit(struct sieve_instance *svinst ATTR_UNUSED)
63
0
{
64
  /* nothing yet */
65
0
}
66
67
void sieve_storage_class_register(struct sieve_instance *svinst,
68
          const struct sieve_storage *storage_class)
69
0
{
70
0
  struct sieve_storage_class_registry *reg = svinst->storage_reg;
71
0
  const struct sieve_storage *old_class;
72
73
0
  old_class = sieve_storage_class_find(svinst,
74
0
               storage_class->driver_name);
75
0
  if (old_class != NULL) {
76
0
    if (old_class->v.alloc == NULL) {
77
      /* replacing a "support not compiled in" storage class
78
       */
79
0
      sieve_storage_class_unregister(svinst, old_class);
80
0
    } else {
81
0
      i_panic("sieve_storage_class_register(%s): "
82
0
        "Already registered",
83
0
        storage_class->driver_name);
84
0
    }
85
0
  }
86
87
0
  array_append(&reg->storage_classes, &storage_class, 1);
88
0
}
89
90
void sieve_storage_class_unregister(struct sieve_instance *svinst,
91
            const struct sieve_storage *storage_class)
92
0
{
93
0
  struct sieve_storage_class_registry *reg = svinst->storage_reg;
94
0
  const struct sieve_storage *const *classes;
95
0
  unsigned int i, count;
96
97
0
  classes = array_get(&reg->storage_classes, &count);
98
0
  for (i = 0; i < count; i++) {
99
0
    if (classes[i] == storage_class) {
100
0
      array_delete(&reg->storage_classes, i, 1);
101
0
      break;
102
0
    }
103
0
  }
104
0
}
105
106
const struct sieve_storage *
107
sieve_storage_class_find(struct sieve_instance *svinst, const char *name)
108
0
{
109
0
  struct sieve_storage_class_registry *reg = svinst->storage_reg;
110
0
  const struct sieve_storage *const *classes;
111
0
  unsigned int i, count;
112
113
0
  i_assert(name != NULL);
114
115
0
  classes = array_get(&reg->storage_classes, &count);
116
0
  for (i = 0; i < count; i++) {
117
0
    if (strcasecmp(classes[i]->driver_name, name) == 0)
118
0
      return classes[i];
119
0
  }
120
0
  return NULL;
121
0
}
122
123
bool sieve_storage_class_exists(struct sieve_instance *svinst,
124
        const char *name)
125
0
{
126
0
  return (sieve_storage_class_find(svinst, name) != NULL);
127
0
}
128
129
/*
130
 * Storage event
131
 */
132
133
static void
134
sieve_storage_update_event_prefix(struct event *event, const char *storage_name,
135
          bool is_default)
136
0
{
137
0
  string_t *prefix = t_str_new(128);
138
139
0
  str_append(prefix, "storage");
140
0
  if (storage_name != NULL && *storage_name != '\0') {
141
0
    str_append_c(prefix, ' ');
142
0
    str_append(prefix, storage_name);
143
0
  }
144
0
  if (is_default)
145
0
    str_append(prefix, " (default)");
146
0
  str_append(prefix, ": ");
147
0
  event_set_append_log_prefix(event, str_c(prefix));
148
0
}
149
150
static struct event *
151
sieve_storage_create_event(struct sieve_instance *svinst,
152
         struct event *event_parent,
153
         const char *storage_name)
154
0
{
155
0
  struct event *event;
156
157
0
  event = event_create(event_parent == NULL ?
158
0
           svinst->event : event_parent);
159
0
  if (event_parent != svinst->event)
160
0
    event_add_category(event, &event_category_sieve);
161
0
  event_add_category(event, &event_category_sieve_storage);
162
163
0
  sieve_storage_update_event_prefix(event, storage_name, FALSE);
164
0
  return event;
165
0
}
166
167
static struct event *
168
sieve_storage_create_driver_event(struct event *event_parent,
169
          const char *driver_name)
170
0
{
171
0
  struct event *event;
172
173
0
  event = event_create(event_parent);
174
0
  event_add_str(event, "driver", driver_name);
175
0
  event_set_append_log_prefix(event,
176
0
    t_strdup_printf("%s: ", driver_name));
177
178
0
  return event;
179
0
}
180
181
/*
182
 * Storage instance
183
 */
184
185
static int
186
sieve_storage_alloc_from_class(struct sieve_instance *svinst,
187
             struct event *event,
188
             const struct sieve_storage *storage_class,
189
             const char *cause, const char *script_type,
190
             const char *storage_name,
191
             const char *script_name,
192
             enum sieve_storage_flags flags,
193
             struct sieve_storage **storage_r,
194
             enum sieve_error *error_code_r,
195
             const char **error_r)
196
0
{
197
0
  struct sieve_storage *storage;
198
199
0
  i_assert(svinst->username != NULL);
200
201
0
  if (storage_class->v.alloc == NULL) {
202
0
    e_error(event, "Support not compiled in for this driver");
203
0
    sieve_error_create_script_not_found(
204
0
      script_name, error_code_r, error_r);
205
0
    return -1;
206
0
  }
207
208
0
  if ((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 &&
209
0
      !storage_class->allows_synchronization) {
210
0
    e_error(event, "Storage does not support synchronization");
211
0
    sieve_error_create_internal(error_code_r, error_r);
212
0
    return -1;
213
0
  }
214
0
  if ((flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 &&
215
0
      storage_class->v.save_init == NULL) {
216
0
    e_error(event, "Storage does not support write access");
217
0
    sieve_error_create_internal(error_code_r, error_r);
218
0
    return -1;
219
0
  }
220
221
0
  storage = storage_class->v.alloc();
222
0
  storage->storage_class = storage_class;
223
0
  storage->refcount = 1;
224
0
  storage->svinst = svinst;
225
0
  storage->cause = p_strdup(storage->pool, cause);
226
0
  storage->type = p_strdup(storage->pool, script_type);
227
0
  storage->script_name = p_strdup(storage->pool, script_name);
228
0
  storage->flags = flags;
229
230
0
  if (storage_name != NULL && *storage_name != '\0')
231
0
    storage->name = p_strdup(storage->pool, storage_name);
232
0
  else {
233
0
    storage->name = p_strconcat(
234
0
      storage->pool, "auto:", storage->type, NULL);
235
0
  }
236
237
0
  if (strcasecmp(script_type, SIEVE_STORAGE_TYPE_PERSONAL) == 0)
238
0
    storage->is_personal = TRUE;
239
240
0
  storage->event = event;
241
0
  event_ref(event);
242
243
0
  *storage_r = storage;
244
0
  return 0;
245
0
}
246
247
int sieve_storage_alloc(struct sieve_instance *svinst,
248
      struct event *event_parent,
249
      const struct sieve_storage *storage_class,
250
      const char *cause, const char *script_type,
251
      const char *storage_name, const char *script_name,
252
      enum sieve_storage_flags flags,
253
      struct sieve_storage **storage_r,
254
      enum sieve_error *error_code_r, const char **error_r)
255
0
{
256
0
  struct event *storage_event, *event;
257
0
  int ret;
258
259
0
  *storage_r = NULL;
260
0
  sieve_error_args_init(&error_code_r, &error_r);
261
262
0
  storage_event = sieve_storage_create_event(svinst, event_parent,
263
0
               storage_name);
264
0
  event = sieve_storage_create_driver_event(storage_event,
265
0
              storage_class->driver_name);
266
0
  event_unref(&storage_event);
267
268
0
  ret = sieve_storage_alloc_from_class(svinst, event, storage_class,
269
0
               cause, script_type,
270
0
               storage_name, script_name, flags,
271
0
               storage_r, error_code_r, error_r);
272
273
0
  event_unref(&event);
274
275
0
  return ret;
276
0
}
277
278
int sieve_storage_alloc_with_settings(struct sieve_instance *svinst,
279
              struct event *event_parent,
280
              const struct sieve_storage *storage_class,
281
              const char *cause,
282
              const struct sieve_storage_settings *set,
283
              enum sieve_storage_flags flags,
284
              struct sieve_storage **storage_r,
285
              enum sieve_error *error_code_r,
286
              const char **error_r)
287
0
{
288
0
  struct sieve_storage *storage;
289
0
  int ret;
290
291
0
  *storage_r = NULL;
292
0
  sieve_error_args_init(&error_code_r, &error_r);
293
294
0
  ret = sieve_storage_alloc_from_class(svinst, event_parent,
295
0
               storage_class,
296
0
               cause, set->script_type,
297
0
               set->script_storage,
298
0
               set->script_name, flags,
299
0
               &storage, error_code_r, error_r);
300
0
  if (ret < 0)
301
0
    return -1;
302
303
0
  const char *bin_path = set->script_bin_path;
304
305
0
  if (sieve_storage_get_full_path(storage, bin_path, &bin_path) < 0) {
306
0
    sieve_storage_set_critical(
307
0
      storage,
308
0
      "Binary storage path '%s' is relative to home directory, "
309
0
      "but home directory is not available.", bin_path);
310
0
    return -1;
311
0
  }
312
313
0
  storage->bin_path = p_strdup_empty(storage->pool, bin_path);
314
0
  storage->max_storage = set->quota_storage_size;
315
0
  storage->max_scripts = set->quota_script_count;
316
317
0
  if (storage->bin_path != NULL) {
318
0
    e_debug(storage->event, "Directory for binaries: %s",
319
0
      storage->bin_path);
320
0
  }
321
0
  if (storage->max_storage != SET_SIZE_UNLIMITED) {
322
0
    e_debug(storage->event, "quota: "
323
0
      "Storage limit: %"PRIuUOFF_T" bytes",
324
0
      storage->max_storage);
325
0
  }
326
0
  if (storage->max_scripts != SET_UINT_UNLIMITED) {
327
0
    e_debug(storage->event, "quota: "
328
0
      "Script count limit: %u scripts",
329
0
      storage->max_scripts);
330
0
  }
331
332
0
  *storage_r = storage;
333
0
  return 0;
334
0
}
335
336
static int
337
sieve_storage_alloc_from_settings(struct sieve_instance *svinst,
338
          struct event *event_parent, const char *cause,
339
          const struct sieve_storage_settings *set,
340
          enum sieve_storage_flags flags,
341
          struct sieve_storage **storage_r,
342
          enum sieve_error *error_code_r,
343
          const char **error_r)
344
0
{
345
0
  const struct sieve_storage *storage_class;
346
0
  struct event *event = event_parent;
347
0
  int ret;
348
349
0
  *storage_r = NULL;
350
351
0
  if (!sieve_storage_settings_match_script_cause(set, cause))
352
0
    return 0;
353
354
0
  storage_class = sieve_storage_class_find(svinst, set->script_driver);
355
  // FIXME: add support for automatic module loading (no such modules yet)
356
0
  if (storage_class == NULL) {
357
0
    e_error(event, "Unknown storage driver: %s",
358
0
      set->script_driver);
359
0
    sieve_error_create_script_not_found(set->script_name,
360
0
                error_code_r, error_r);
361
0
    event_unref(&event);
362
0
    return -1;
363
0
  }
364
365
0
  event = sieve_storage_create_driver_event(event_parent,
366
0
              storage_class->driver_name);
367
368
0
  ret = sieve_storage_alloc_with_settings(svinst, event, storage_class,
369
0
            cause, set, flags,
370
0
            storage_r, error_code_r,
371
0
            error_r);
372
373
0
  event_unref(&event);
374
375
0
  if (ret < 0)
376
0
    return -1;
377
0
  return 1;
378
0
}
379
380
static int
381
sieve_storage_autodetect(struct sieve_instance *svinst, struct event *event,
382
       const char *cause, const char *type,
383
       const struct sieve_storage_settings *set,
384
       enum sieve_storage_flags flags,
385
       struct sieve_storage **storage_r,
386
       enum sieve_error *error_code_r, const char **error_r)
387
0
{
388
0
  struct sieve_storage_class_registry *reg = svinst->storage_reg;
389
0
  int ret;
390
391
0
  *storage_r = NULL;
392
0
  sieve_error_args_init(&error_code_r, &error_r);
393
394
0
  if (!sieve_storage_settings_match_script_cause(set, cause))
395
0
    return 0;
396
0
  if (!sieve_storage_settings_match_script_type(set, type))
397
0
    return 0;
398
399
0
  const struct sieve_storage *const *classes;
400
0
  unsigned int i, count;
401
402
0
  classes = array_get(&reg->storage_classes, &count);
403
0
  ret = 0;
404
0
  for (i = 0; i < count; i++) {
405
0
    if (classes[i]->v.autodetect == NULL)
406
0
      continue;
407
0
    if (set->script_driver[0] != '\0' &&
408
0
        strcasecmp(set->script_driver,
409
0
             classes[i]->driver_name) != 0)
410
0
      continue;
411
412
0
    struct event *driver_event =
413
0
      sieve_storage_create_driver_event(
414
0
        event, classes[i]->driver_name);
415
416
0
    *storage_r = NULL;
417
0
    ret = classes[i]->v.autodetect(svinst, driver_event,
418
0
                 cause, set, flags,
419
0
                 storage_r, error_code_r,
420
0
                 error_r);
421
422
0
    event_unref(&driver_event);
423
424
0
    if (ret < 0) {
425
0
      i_assert(*error_code_r != SIEVE_ERROR_NONE);
426
0
      i_assert(*error_r != NULL);
427
0
      if (*error_code_r == SIEVE_ERROR_NOT_FOUND) {
428
0
        *error_code_r = SIEVE_ERROR_NONE;
429
0
        *error_r = NULL;
430
0
        ret = 0;
431
0
      }
432
0
    }
433
0
    i_assert(ret <= 0 || *storage_r != NULL);
434
0
    if (ret != 0)
435
0
      break;
436
0
  }
437
438
0
  if (ret == 0)
439
0
    e_debug(event, "Autodetection failed");
440
0
  return ret;
441
0
}
442
443
static int
444
sieve_storage_autodetect_any(struct sieve_instance *svinst,
445
           struct event *event_parent,
446
           const char *cause, const char *type,
447
           const struct sieve_storage_settings *set,
448
           enum sieve_storage_flags flags,
449
           struct sieve_storage **storage_r,
450
           enum sieve_error *error_code_r,
451
           const char **error_r)
452
0
{
453
0
  struct event *event;
454
0
  int ret;
455
456
0
  event = sieve_storage_create_event(svinst, event_parent, NULL);
457
458
0
  ret = sieve_storage_autodetect(svinst, event, cause, type, set,
459
0
               flags, storage_r, error_code_r, error_r);
460
461
0
  event_unref(&event);
462
0
  return ret;
463
0
}
464
465
static int
466
sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
467
      const char *cause, const char *type,
468
      const char *storage_name, bool try,
469
      enum sieve_storage_flags flags,
470
      struct sieve_storage **storage_r,
471
      enum sieve_error *error_code_r, const char **error_r)
472
0
{
473
0
  const struct sieve_storage_settings *set;
474
0
  struct sieve_storage *storage;
475
0
  const char *error;
476
0
  int ret;
477
478
0
  if (try) {
479
0
    ret = settings_try_get_filter(
480
0
      event, "sieve_script", storage_name,
481
0
      &sieve_storage_setting_parser_info, 0,
482
0
      &set, &error);
483
0
    if (ret == 0)
484
0
      return 0;
485
0
  } else {
486
0
    ret = settings_get_filter(
487
0
      event, "sieve_script", storage_name,
488
0
      &sieve_storage_setting_parser_info, 0,
489
0
      &set, &error);
490
0
  }
491
0
  if (ret < 0) {
492
0
    e_error(event, "%s", error);
493
0
    sieve_error_create_internal(error_code_r, error_r);
494
0
    return -1;
495
0
  }
496
497
0
  if (!sieve_storage_settings_match_script_type(set, type)) {
498
0
    settings_free(set);
499
0
    return 0;
500
0
  }
501
502
0
  event_add_str(event, "sieve_script", storage_name);
503
0
  settings_event_add_list_filter_name(event, "sieve_script",
504
0
              storage_name);
505
506
0
  if (set->script_driver[0] == '\0') {
507
0
    ret = sieve_storage_autodetect(svinst, event, cause, type,
508
0
                 set, flags, storage_r,
509
0
                 error_code_r, error_r);
510
0
    if (ret != 0) {
511
0
      settings_free(set);
512
0
      return ret;
513
0
    }
514
0
    e_error(event, "sieve_script_driver is empty");
515
0
    sieve_error_create_script_not_found(set->script_name,
516
0
                error_code_r, error_r);
517
0
    settings_free(set);
518
0
    return -1;
519
0
  }
520
521
0
  ret = sieve_storage_alloc_from_settings(svinst, event, cause,
522
0
            set, flags, &storage,
523
0
            error_code_r, error_r);
524
0
  settings_free(set);
525
0
  if (ret <= 0)
526
0
    return ret;
527
0
  i_assert(storage != NULL);
528
0
  i_assert(storage->v.init != NULL);
529
530
0
  T_BEGIN {
531
0
    ret = storage->v.init(storage);
532
0
    i_assert(ret <= 0);
533
0
  } T_END;
534
0
  if (ret < 0) {
535
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
536
0
    i_assert(storage->error != NULL);
537
0
    *error_code_r = storage->error_code;
538
0
    *error_r = t_strdup(storage->error);
539
0
    sieve_storage_unref(&storage);
540
0
    return -1;
541
0
  }
542
0
  *storage_r = storage;
543
0
  return 1;
544
0
}
545
546
static int
547
sieve_storage_init(struct sieve_instance *svinst, struct event *event_parent,
548
       const char *cause, const char *type,
549
       const char *storage_name, bool try,
550
       enum sieve_storage_flags flags,
551
       struct sieve_storage **storage_r,
552
       enum sieve_error *error_code_r, const char **error_r)
553
0
{
554
0
  struct event *event;
555
0
  int ret;
556
557
0
  *storage_r = NULL;
558
559
0
  event = sieve_storage_create_event(svinst, event_parent, storage_name);
560
561
0
  ret = sieve_storage_init_real(svinst, event, cause, type,
562
0
              storage_name, try, flags,
563
0
              storage_r, error_code_r, error_r);
564
565
0
  event_unref(&event);
566
567
0
  return ret;
568
0
}
569
570
int sieve_storage_create(struct sieve_instance *svinst,
571
       struct event *event, const char *cause,
572
       const char *storage_name,
573
       enum sieve_storage_flags flags,
574
       struct sieve_storage **storage_r,
575
       enum sieve_error *error_code_r, const char **error_r)
576
0
{
577
0
  struct sieve_storage *storage;
578
0
  int ret;
579
580
0
  *storage_r = NULL;
581
0
  sieve_error_args_init(&error_code_r, &error_r);
582
583
0
  ret = sieve_storage_init(svinst, event, cause, SIEVE_STORAGE_TYPE_ANY,
584
0
         storage_name, TRUE, flags,
585
0
         &storage, error_code_r, error_r);
586
0
  if (ret < 0) {
587
0
    if (*error_code_r != SIEVE_ERROR_NOT_FOUND)
588
0
      return -1;
589
0
    ret = 0;
590
0
  }
591
0
  if (ret == 0) {
592
0
    e_debug(event, "Sieve script storage '%s' not found (cause=%s)",
593
0
      storage_name, cause);
594
0
    sieve_error_create_script_not_found(
595
0
      NULL, error_code_r, error_r);
596
0
    return -1;
597
0
  }
598
0
  i_assert(storage != NULL);
599
0
  *storage_r = storage;
600
0
  return 0;
601
0
}
602
603
int sieve_storage_create_auto(struct sieve_instance *svinst,
604
            struct event *event,
605
            const char *cause, const char *type,
606
            enum sieve_storage_flags flags,
607
            struct sieve_storage **storage_r,
608
            enum sieve_error *error_code_r,
609
            const char **error_r)
610
0
{
611
0
  const struct sieve_storage_settings *storage_set;
612
0
  const char *const *storage_names;
613
0
  unsigned int i, count;
614
0
  const char *error;
615
616
0
  *storage_r = NULL;
617
0
  sieve_error_args_init(&error_code_r, &error_r);
618
619
0
  if (settings_get(event, &sieve_storage_setting_parser_info,
620
0
       SETTINGS_GET_FLAG_SORT_FILTER_ARRAYS,
621
0
       &storage_set, &error) < 0) {
622
0
    e_error(event, "%s", error);
623
0
    sieve_error_create_internal(error_code_r, error_r);
624
0
    return -1;
625
0
  }
626
0
  if (array_is_created(&storage_set->storages))
627
0
    storage_names = array_get(&storage_set->storages, &count);
628
0
  else {
629
0
    storage_names = NULL;
630
0
    count = 0;
631
0
  }
632
633
0
  struct sieve_storage *storage = NULL;
634
0
  int ret = 0;
635
636
0
  for (i = 0; i < count; i++) {
637
0
    ret = sieve_storage_init(svinst, event, cause, type,
638
0
           storage_names[i], FALSE, flags,
639
0
           &storage, error_code_r, error_r);
640
0
    if (ret < 0 && *error_code_r != SIEVE_ERROR_NOT_FOUND) {
641
0
      settings_free(storage_set);
642
0
      return -1;
643
0
    }
644
0
    if (ret > 0) {
645
0
      i_assert(storage != NULL);
646
0
      break;
647
0
    }
648
0
  }
649
0
  if (ret <= 0) {
650
0
    ret = sieve_storage_autodetect_any(svinst, event, cause, type,
651
0
               storage_set, flags, &storage,
652
0
               error_code_r, error_r);
653
0
    if (ret < 0) {
654
0
      settings_free(storage_set);
655
0
      return -1;
656
0
    }
657
0
  }
658
0
  settings_free(storage_set);
659
0
  if (ret <= 0) {
660
0
    e_debug(event,
661
0
      "storage: No matching Sieve storage configured "
662
0
      "(type=%s and cause=%s)",
663
0
      type, cause);
664
0
    sieve_error_create_script_not_found(
665
0
      NULL, error_code_r, error_r);
666
0
    return -1;
667
0
  }
668
0
  i_assert(storage != NULL);
669
0
  *storage_r = storage;
670
0
  return 0;
671
0
}
672
673
static int
674
sieve_storage_create_default(struct sieve_instance *svinst,
675
           struct event *event, const char *cause,
676
           enum sieve_storage_flags flags,
677
           struct sieve_storage **storage_r,
678
           enum sieve_error *error_code_r,
679
           const char **error_r)
680
0
{
681
0
  struct sieve_storage *storage;
682
0
  enum sieve_error error_code;
683
0
  int ret;
684
685
0
  *storage_r = NULL;
686
0
  sieve_error_args_init(&error_code_r, &error_r);
687
688
0
  ret = sieve_storage_create_auto(svinst, event, cause,
689
0
          SIEVE_STORAGE_TYPE_DEFAULT, flags,
690
0
          &storage, &error_code, error_r);
691
0
  if (ret >= 0) {
692
0
    storage->is_default = TRUE;
693
0
    sieve_storage_update_event_prefix(
694
0
      event_get_parent(storage->event), storage->name, TRUE);
695
0
  } else {
696
0
    switch (error_code) {
697
0
    case SIEVE_ERROR_NOT_FOUND:
698
0
      e_debug(event, "storage: "
699
0
        "Default script not found");
700
0
      break;
701
0
    case SIEVE_ERROR_TEMP_FAILURE:
702
0
      e_error(event, "storage: "
703
0
        "Failed to access default script "
704
0
        "(temporary failure)");
705
0
      break;
706
0
    default:
707
0
      e_error(event, "storage: "
708
0
        "Failed to access default script");
709
0
      break;
710
0
    }
711
0
    *error_code_r = error_code;
712
0
  }
713
714
0
  *storage_r = storage;
715
0
  return ret;
716
0
}
717
718
static int
719
sieve_storage_create_default_for(struct sieve_storage *storage,
720
         struct sieve_storage **storage_r,
721
         enum sieve_error *error_code_r,
722
         const char **error_r)
723
0
{
724
0
  *storage_r = NULL;
725
0
  sieve_error_args_init(&error_code_r, &error_r);
726
727
0
  if (storage->default_storage != NULL) {
728
0
    sieve_storage_ref(storage->default_storage);
729
0
    *storage_r = storage->default_storage;
730
0
    return 0;
731
0
  }
732
733
0
  struct sieve_instance *svinst = storage->svinst;
734
0
  enum sieve_error error_code;
735
0
  const char *error;
736
737
0
  i_assert(storage->default_storage_for == NULL);
738
0
  if (sieve_storage_create_default(svinst, svinst->event,
739
0
           storage->cause, 0,
740
0
           &storage->default_storage,
741
0
           &error_code, &error) < 0) {
742
0
    sieve_storage_set_error(storage, error_code, "%s", error);
743
0
    *error_code_r = storage->error_code;
744
0
    *error_r = storage->error;
745
0
    return -1;
746
0
  }
747
748
0
  storage->default_storage->default_storage_for = storage;
749
0
  sieve_storage_ref(storage);
750
751
0
  *storage_r = storage->default_storage;
752
0
  return 0;
753
0
}
754
755
int sieve_storage_create_personal(struct sieve_instance *svinst,
756
          struct mail_user *user, const char *cause,
757
          enum sieve_storage_flags flags,
758
          struct sieve_storage **storage_r,
759
          enum sieve_error *error_code_r)
760
0
{
761
0
  struct sieve_storage *storage;
762
0
  int ret;
763
764
0
  *storage_r = NULL;
765
0
  sieve_error_args_init(&error_code_r, NULL);
766
767
  /* Check whether Sieve is disabled for this user */
768
0
  if (!svinst->set->enabled) {
769
0
    e_debug(svinst->event,
770
0
      "Sieve is disabled for this user");
771
0
    *error_code_r = SIEVE_ERROR_NOT_POSSIBLE;
772
0
    return -1;
773
0
  }
774
775
  /* Attempt to locate user's main storage */
776
0
  ret = sieve_storage_create_auto(svinst, svinst->event, cause,
777
0
          SIEVE_STORAGE_TYPE_PERSONAL, flags,
778
0
          &storage, error_code_r, NULL);
779
0
  if (ret == 0) {
780
0
    i_assert(storage->is_personal);
781
0
    (void)sieve_storage_sync_init(storage, user);
782
0
  } else if (*error_code_r != SIEVE_ERROR_TEMP_FAILURE &&
783
0
       (flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
784
0
       (flags & SIEVE_STORAGE_FLAG_READWRITE) == 0) {
785
786
    /* Failed; try using default script location
787
       (not for temporary failures, read/write access, or dsync) */
788
0
    ret = sieve_storage_create_default(svinst, svinst->event,
789
0
               cause, flags, &storage,
790
0
               error_code_r, NULL);
791
0
  }
792
0
  *storage_r = storage;
793
0
  return ret;
794
0
}
795
796
void sieve_storage_ref(struct sieve_storage *storage)
797
0
{
798
0
  storage->refcount++;
799
0
}
800
801
void sieve_storage_unref(struct sieve_storage **_storage)
802
0
{
803
0
  struct sieve_storage *storage = *_storage;
804
805
0
  if (storage == NULL)
806
0
    return;
807
0
  *_storage = NULL;
808
809
0
  i_assert(storage->refcount > 0);
810
0
  if (--storage->refcount != 0)
811
0
    return;
812
813
0
  if (storage->default_storage_for != NULL) {
814
0
    i_assert(storage->is_default);
815
0
    storage->default_storage_for->default_storage = NULL;
816
0
    sieve_storage_unref(&storage->default_storage_for);
817
0
  }
818
819
0
  sieve_storage_sync_deinit(storage);
820
821
0
  if (storage->v.destroy != NULL)
822
0
    storage->v.destroy(storage);
823
824
0
  i_free(storage->error);
825
0
  event_unref(&storage->event);
826
0
  pool_unref(&storage->pool);
827
0
}
828
829
/*
830
 * Utility
831
 */
832
833
int sieve_storage_get_full_path(struct sieve_storage *storage,
834
        const char *path, const char **path_r)
835
0
{
836
0
  struct sieve_instance *svinst = storage->svinst;
837
838
0
  *path_r = path;
839
840
0
  if (path == NULL || *path == '\0')
841
0
    return 0;
842
0
  if ((path[0] != '~' || (path[1] != '/' && path[1] != '\0')) &&
843
0
      ((svinst->flags & SIEVE_FLAG_HOME_RELATIVE) == 0 ||
844
0
       path[0] == '/'))
845
0
    return 0;
846
847
  /* Home-relative path. change to absolute. */
848
0
  const char *home = sieve_environment_get_homedir(svinst);
849
850
0
  if (home == NULL)
851
0
    return -1;
852
853
0
  if (path[0] == '~' && (path[1] == '/' || path[1] == '\0'))
854
0
    *path_r = home_expand_tilde(path, home);
855
0
  else
856
0
    *path_r = t_strconcat(home, "/", path, NULL);
857
0
  return 0;
858
0
}
859
860
/*
861
 * Binary
862
 */
863
864
int sieve_storage_setup_bin_path(struct sieve_storage *storage, mode_t mode)
865
0
{
866
0
  const char *bin_path = storage->bin_path;
867
0
  struct stat st;
868
869
0
  if (bin_path == NULL) {
870
0
    sieve_storage_set_critical(
871
0
      storage, "script_bin_path not configured for storage");
872
0
    return -1;
873
0
  }
874
875
0
  if (stat(bin_path, &st) == 0) {
876
0
    e_debug(storage->event,
877
0
      "Directory for saving binary already exists");
878
0
    return 0;
879
0
  }
880
881
0
  if (errno == EACCES) {
882
0
    sieve_storage_set_critical(storage,
883
0
      "Failed to setup directory for binaries: "
884
0
      "%s", eacces_error_get("stat", bin_path));
885
0
    return -1;
886
0
  } else if (errno != ENOENT) {
887
0
    sieve_storage_set_critical(storage,
888
0
      "Failed to setup directory for binaries: "
889
0
      "stat(%s) failed: %m",
890
0
      bin_path);
891
0
    return -1;
892
0
  }
893
894
0
  if (mkdir_parents(bin_path, mode) == 0) {
895
0
    e_debug(storage->event,
896
0
      "Created directory for binaries: %s", bin_path);
897
0
    return 1;
898
0
  }
899
900
0
  switch (errno) {
901
0
  case EEXIST:
902
0
    return 0;
903
0
  case ENOENT:
904
0
    sieve_storage_set_critical(storage,
905
0
      "Directory for binaries was deleted while it was being created");
906
0
    break;
907
0
  case EACCES:
908
0
    sieve_storage_set_critical(storage,
909
0
      "%s", eacces_error_get_creating("mkdir_parents_chgrp",
910
0
              bin_path));
911
0
    break;
912
0
  default:
913
0
    sieve_storage_set_critical(storage,
914
0
      "mkdir_parents_chgrp(%s) failed: %m", bin_path);
915
0
    break;
916
0
  }
917
918
0
  return -1;
919
0
}
920
921
/*
922
 * Properties
923
 */
924
925
int sieve_storage_is_singular(struct sieve_storage *storage)
926
0
{
927
0
  if (storage->v.is_singular == NULL)
928
0
    return 1;
929
0
  return storage->v.is_singular(storage);
930
0
}
931
932
int sieve_storage_get_last_change(struct sieve_storage *storage,
933
          time_t *last_change_r)
934
0
{
935
0
  i_assert(storage->v.get_last_change != NULL);
936
0
  return storage->v.get_last_change(storage, last_change_r);
937
0
}
938
939
void sieve_storage_set_modified(struct sieve_storage *storage, time_t mtime)
940
0
{
941
0
  if (storage->v.set_modified == NULL)
942
0
    return;
943
944
0
  storage->v.set_modified(storage, mtime);
945
0
}
946
947
/*
948
 * Comparison
949
 */
950
951
int sieve_storage_cmp(const struct sieve_storage *storage1,
952
          const struct sieve_storage *storage2)
953
0
{
954
0
  int ret;
955
956
0
  if (storage1 == storage2)
957
0
    return 0;
958
0
  if (storage1 == NULL || storage2 == NULL)
959
0
    return (storage1 == NULL ? -1 : 1);
960
0
  if (storage1->storage_class != storage2->storage_class) {
961
0
    return (storage1->storage_class > storage2->storage_class ?
962
0
      1 : -1);
963
0
  }
964
0
  ret = null_strcmp(storage1->type, storage2->type);
965
0
  if (ret != 0)
966
0
    return (ret > 0 ? 1 : -1);
967
0
  return null_strcmp(storage1->name, storage2->name);
968
0
}
969
970
unsigned int sieve_storage_hash(const struct sieve_storage *storage)
971
0
{
972
0
  unsigned int hash = 0;
973
974
0
  hash ^= POINTER_CAST_TO(storage->storage_class, unsigned int);
975
0
  hash ^= str_hash(storage->type);
976
0
  hash ^= str_hash(storage->name);
977
978
0
  return hash;
979
0
}
980
981
/*
982
 * Script access
983
 */
984
985
int sieve_storage_get_script_direct(struct sieve_storage *storage,
986
            const char *name,
987
            struct sieve_script **script_r,
988
            enum sieve_error *error_code_r)
989
0
{
990
0
  int ret;
991
992
  /* Validate script name */
993
0
  if (name != NULL && !sieve_script_name_is_valid(name)) {
994
0
    sieve_storage_set_error(storage,
995
0
      SIEVE_ERROR_BAD_PARAMS,
996
0
      "Invalid script name '%s'.",
997
0
      str_sanitize(name, 80));
998
0
    *error_code_r = storage->error_code;
999
0
    return -1;
1000
0
  }
1001
0
  if (name == NULL)
1002
0
    name = storage->script_name;
1003
1004
0
  i_assert(storage->v.get_script != NULL);
1005
0
  ret = storage->v.get_script(storage, name, script_r);
1006
0
  i_assert(ret <= 0);
1007
0
  if (ret < 0) {
1008
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1009
0
    i_assert(storage->error != NULL);
1010
0
    *error_code_r = storage->error_code;
1011
0
  }
1012
0
  return ret;
1013
0
}
1014
1015
static int
1016
sieve_storage_get_default_script(struct sieve_storage *storage,
1017
         const char *name,
1018
         struct sieve_script **script_r,
1019
         enum sieve_error *error_code_r)
1020
0
{
1021
0
  struct sieve_storage *def_storage;
1022
0
  int ret;
1023
1024
0
  if (*error_code_r != SIEVE_ERROR_NOT_FOUND ||
1025
0
      (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 ||
1026
0
      !storage->is_personal)
1027
0
    return -1;
1028
1029
  /* Not found; if this name maps to the default script,
1030
     try to access that instead */
1031
0
  e_debug(storage->event, "Trying default script instead");
1032
1033
  /* Failed; try using default script location
1034
     (not for temporary failures, read/write access, or dsync) */
1035
0
  ret = sieve_storage_create_default_for(storage, &def_storage,
1036
0
                 error_code_r, NULL);
1037
0
  if (ret < 0)
1038
0
    return -1;
1039
1040
0
  if (strcmp(def_storage->script_name, name) != 0) {
1041
0
    sieve_storage_set_error(storage,
1042
0
      SIEVE_ERROR_NOT_FOUND,
1043
0
      "Default script '%s' not found",
1044
0
      str_sanitize(name, 80));
1045
0
    *error_code_r = storage->error_code;
1046
0
    sieve_storage_unref(&def_storage);
1047
0
    return -1;
1048
0
  }
1049
1050
0
  struct sieve_script *def_script;
1051
1052
0
  ret = sieve_storage_get_script_direct(def_storage, name,
1053
0
                &def_script, error_code_r);
1054
0
  if (ret < 0)
1055
0
    sieve_storage_copy_error(storage, def_storage);
1056
0
  sieve_storage_unref(&def_storage);
1057
0
  if (ret < 0)
1058
0
    return -1;
1059
0
  i_assert(def_script != NULL);
1060
1061
0
  *script_r = def_script;
1062
0
  return 0;
1063
0
}
1064
1065
int sieve_storage_get_script(struct sieve_storage *storage, const char *name,
1066
           struct sieve_script **script_r,
1067
           enum sieve_error *error_code_r)
1068
0
{
1069
0
  *script_r = NULL;
1070
0
  sieve_error_args_init(&error_code_r, NULL);
1071
0
  sieve_storage_clear_error(storage);
1072
1073
0
  if (sieve_storage_get_script_direct(storage, name,
1074
0
              script_r, error_code_r) >= 0)
1075
0
    return 0;
1076
1077
  /* Try default instead if appropriate */
1078
1079
0
  return sieve_storage_get_default_script(storage, name,
1080
0
            script_r, error_code_r);
1081
0
}
1082
1083
int sieve_storage_open_script(struct sieve_storage *storage, const char *name,
1084
            struct sieve_script **script_r,
1085
            enum sieve_error *error_code_r)
1086
0
{
1087
0
  struct sieve_script *script;
1088
1089
0
  *script_r = NULL;
1090
0
  sieve_error_args_init(&error_code_r, NULL);
1091
0
  sieve_storage_clear_error(storage);
1092
1093
0
  if (sieve_storage_get_script(storage, name, &script, error_code_r) < 0)
1094
0
    return -1;
1095
0
  if (sieve_script_open(script, error_code_r) == 0) {
1096
0
    *script_r = script;
1097
0
    return 0;
1098
0
  }
1099
0
  sieve_script_unref(&script);
1100
1101
  /* Try default instead if appropriate */
1102
1103
0
  if (sieve_storage_get_default_script(storage, name,
1104
0
               &script, error_code_r) < 0)
1105
0
    return -1;
1106
0
  if (sieve_script_open(script, error_code_r) < 0) {
1107
0
    sieve_script_unref(&script);
1108
0
    return -1;
1109
0
  }
1110
0
  *script_r = script;
1111
0
  return 0;
1112
0
}
1113
1114
static int
1115
sieve_storage_check_script_direct(struct sieve_storage *storage,
1116
          const char *name,
1117
          enum sieve_error *error_code_r)
1118
0
{
1119
0
  struct sieve_script *script;
1120
0
  int ret;
1121
1122
0
  sieve_error_args_init(&error_code_r, NULL);
1123
0
  sieve_storage_clear_error(storage);
1124
1125
0
  if (sieve_storage_get_script_direct(storage, name,
1126
0
              &script, error_code_r) < 0)
1127
0
    return (*error_code_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
1128
1129
0
  ret = sieve_script_open(script, error_code_r);
1130
0
  sieve_script_unref(&script);
1131
0
  return (ret >= 0 ? 1 :
1132
0
    (*error_code_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1));
1133
0
}
1134
1135
int sieve_storage_check_script(struct sieve_storage *storage, const char *name,
1136
             enum sieve_error *error_code_r)
1137
0
{
1138
0
  struct sieve_script *script;
1139
1140
0
  sieve_error_args_init(&error_code_r, NULL);
1141
0
  sieve_storage_clear_error(storage);
1142
1143
0
  if (sieve_storage_open_script(storage, name, &script, error_code_r) < 0)
1144
0
    return (*error_code_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
1145
1146
0
  sieve_script_unref(&script);
1147
0
  return 1;
1148
0
}
1149
1150
/*
1151
 * Active script
1152
 */
1153
1154
static int
1155
sieve_storage_active_script_do_get_name(struct sieve_storage *storage,
1156
          const char **name_r, bool *default_r)
1157
          ATTR_NULL(3)
1158
0
{
1159
0
  int ret;
1160
1161
0
  i_assert(storage->is_personal);
1162
1163
0
  if (default_r != NULL)
1164
0
    *default_r = FALSE;
1165
1166
0
  i_assert(storage->v.active_script_get_name != NULL);
1167
0
  ret = storage->v.active_script_get_name(storage, name_r);
1168
0
  if (ret < 0) {
1169
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1170
0
    i_assert(storage->error != NULL);
1171
0
    if (storage->error_code == SIEVE_ERROR_NOT_FOUND) {
1172
0
      sieve_storage_clear_error(storage);
1173
0
      ret = 0;
1174
0
    }
1175
0
  }
1176
1177
0
  if (ret != 0 ||
1178
0
      (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0)
1179
0
    return ret;
1180
1181
0
  struct sieve_storage *def_storage;
1182
1183
  /* Failed; try using default script location
1184
     (not for temporary failures, read/write access, or dsync) */
1185
0
  ret = sieve_storage_create_default_for(storage, &def_storage,
1186
0
                 NULL, NULL);
1187
0
  if (ret < 0)
1188
0
    return -1;
1189
1190
0
  *name_r = def_storage->script_name;
1191
1192
0
  ret = sieve_storage_check_script(def_storage,
1193
0
           def_storage->script_name, NULL);
1194
0
  if (ret < 0) {
1195
0
    sieve_storage_copy_error(storage, def_storage);
1196
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1197
0
    i_assert(storage->error != NULL);
1198
0
  }
1199
0
  sieve_storage_unref(&def_storage);
1200
0
  if (ret <= 0)
1201
0
    return ret;
1202
1203
0
  if (default_r != NULL)
1204
0
    *default_r = TRUE;
1205
0
  return 1;
1206
0
}
1207
1208
int sieve_storage_active_script_get_name(struct sieve_storage *storage,
1209
           const char **name_r)
1210
0
{
1211
0
  return sieve_storage_active_script_do_get_name(storage, name_r, NULL);
1212
0
}
1213
1214
int sieve_storage_active_script_is_default(struct sieve_storage *storage)
1215
0
{
1216
0
  const char *name;
1217
0
  bool is_default = FALSE;
1218
0
  int ret;
1219
1220
0
  i_assert(storage->is_personal);
1221
0
  ret = sieve_storage_active_script_do_get_name(storage, &name,
1222
0
                  &is_default);
1223
0
  return (ret < 0 ? -1 : (is_default ? 1 : 0));
1224
0
}
1225
1226
int sieve_storage_active_script_open(struct sieve_storage *storage,
1227
             struct sieve_script **script_r,
1228
             enum sieve_error *error_code_r)
1229
0
{
1230
0
  struct sieve_script *script = NULL;
1231
0
  int ret;
1232
1233
  /* When called for non-personal (default) storage, just open the primary
1234
     script by explicit path or name. */
1235
0
  if (!storage->is_personal) {
1236
0
    return sieve_storage_open_script(storage, NULL,
1237
0
             script_r, error_code_r);
1238
0
  }
1239
1240
0
  *script_r = NULL;
1241
0
  sieve_error_args_init(&error_code_r, NULL);
1242
0
  sieve_storage_clear_error(storage);
1243
1244
0
  i_assert(storage->v.active_script_open != NULL);
1245
0
  ret = storage->v.active_script_open(storage, &script);
1246
0
  i_assert(ret <= 0);
1247
0
  i_assert(ret == 0 ||
1248
0
     (storage->error_code != SIEVE_ERROR_NONE &&
1249
0
      storage->error != NULL));
1250
1251
0
  if (ret == 0 || storage->error_code != SIEVE_ERROR_NOT_FOUND ||
1252
0
      (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0) {
1253
0
    if (ret < 0)
1254
0
      *error_code_r = storage->error_code;
1255
0
    *script_r = script;
1256
0
    return ret;
1257
0
  }
1258
1259
0
  struct sieve_storage *def_storage;
1260
1261
  /* Try default script location */
1262
0
  ret = sieve_storage_create_default_for(storage, &def_storage,
1263
0
                 error_code_r, NULL);
1264
0
  if (ret < 0)
1265
0
    return -1;
1266
1267
0
  ret = sieve_storage_open_script(def_storage, NULL,
1268
0
          script_r, error_code_r);
1269
0
  if (ret < 0)
1270
0
    sieve_storage_copy_error(storage, def_storage);
1271
0
  sieve_storage_unref(&def_storage);
1272
0
  return ret;
1273
0
}
1274
1275
int sieve_storage_deactivate(struct sieve_storage *storage, time_t mtime)
1276
0
{
1277
0
  int ret;
1278
1279
0
  i_assert(storage->is_personal);
1280
0
  i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
1281
1282
0
  sieve_storage_clear_error(storage);
1283
1284
0
  i_assert(storage->v.deactivate != NULL);
1285
0
  ret = storage->v.deactivate(storage);
1286
1287
0
  if (ret >= 0) {
1288
0
    struct event_passthrough *e =
1289
0
      event_create_passthrough(storage->event)->
1290
0
      set_name("sieve_storage_deactivated");
1291
0
    e_debug(e->event(), "Storage deactivated");
1292
1293
0
    sieve_storage_set_modified(storage, mtime);
1294
0
    (void)sieve_storage_sync_deactivate(storage);
1295
0
  } else {
1296
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1297
0
    i_assert(storage->error != NULL);
1298
1299
0
    struct event_passthrough *e =
1300
0
      event_create_passthrough(storage->event)->
1301
0
      add_str("error", storage->error)->
1302
0
      set_name("sieve_storage_deactivated");
1303
0
    e_debug(e->event(), "Failed to deactivate storage: %s",
1304
0
      storage->error);
1305
0
  }
1306
1307
0
  return ret;
1308
0
}
1309
1310
int sieve_storage_active_script_get_last_change(struct sieve_storage *storage,
1311
            time_t *last_change_r)
1312
0
{
1313
0
  i_assert(storage->is_personal);
1314
0
  i_assert(storage->v.active_script_get_last_change != NULL);
1315
1316
0
  return storage->v.active_script_get_last_change(storage, last_change_r);
1317
0
}
1318
1319
/*
1320
 * Listing scripts
1321
 */
1322
1323
int sieve_storage_list_init(struct sieve_storage *storage,
1324
          struct sieve_storage_list_context **lctx_r)
1325
0
{
1326
0
  struct sieve_storage_list_context *lctx;
1327
1328
0
  *lctx_r = NULL;
1329
0
  sieve_storage_clear_error(storage);
1330
1331
0
  i_assert(storage->v.list_init != NULL);
1332
0
  if (storage->v.list_init(storage, &lctx) < 0) {
1333
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1334
0
    i_assert(storage->error != NULL);
1335
0
    return -1;
1336
0
  }
1337
1338
0
  lctx->storage = storage;
1339
0
  sieve_storage_ref(storage);
1340
1341
0
  if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0) {
1342
    /* No default script involved; return right away */
1343
0
    *lctx_r = lctx;
1344
0
    return 0;
1345
0
  }
1346
1347
  /* May need to list default script as well */
1348
1349
0
  enum sieve_error error_code;
1350
1351
0
  if (sieve_storage_create_default_for(storage, &lctx->def_storage,
1352
0
               &error_code, NULL) < 0 &&
1353
0
      error_code != SIEVE_ERROR_NOT_FOUND)
1354
0
    return -1;
1355
1356
0
  *lctx_r = lctx;
1357
0
  return 0;
1358
0
}
1359
1360
const char *
1361
sieve_storage_list_next(struct sieve_storage_list_context *lctx, bool *active_r)
1362
0
{
1363
0
  struct sieve_storage *storage = lctx->storage;
1364
0
  const char *scriptname;
1365
0
  bool script_active = FALSE;
1366
1367
0
  sieve_storage_clear_error(storage);
1368
1369
0
  i_assert(storage->v.list_next != NULL);
1370
0
  scriptname = storage->v.list_next(lctx, &script_active);
1371
1372
0
  i_assert(!script_active || !lctx->seen_active);
1373
0
  if (script_active)
1374
0
    lctx->seen_active = TRUE;
1375
1376
0
  struct sieve_storage *def_storage = lctx->def_storage;
1377
0
  bool have_default = (def_storage != NULL &&
1378
0
           def_storage->script_name != NULL);
1379
1380
0
  if (scriptname != NULL) {
1381
    /* Remember when we see that the storage has its own script for
1382
       default */
1383
0
    if (have_default &&
1384
0
        strcmp(scriptname, def_storage->script_name) == 0)
1385
0
      lctx->seen_default = TRUE;
1386
1387
0
  } else if (have_default && !lctx->seen_default &&
1388
0
       sieve_storage_check_script(def_storage, NULL, NULL) > 0) {
1389
1390
    /* Return default script at the end if it was not listed
1391
       thus far (storage backend has no script under default
1392
       name) */
1393
0
    scriptname = def_storage->script_name;
1394
0
    lctx->seen_default = TRUE;
1395
1396
    /* Mark default as active if no normal script is active */
1397
0
    if (!lctx->seen_active) {
1398
0
      script_active = TRUE;
1399
0
      lctx->seen_active = TRUE;
1400
0
    }
1401
0
  }
1402
1403
0
  if (active_r != NULL)
1404
0
    *active_r = script_active;
1405
0
  return scriptname;
1406
0
}
1407
1408
int sieve_storage_list_deinit(struct sieve_storage_list_context **_lctx)
1409
0
{
1410
0
  struct sieve_storage_list_context *lctx = *_lctx;
1411
1412
0
  if (lctx == NULL)
1413
0
    return 0;
1414
0
  *_lctx = NULL;
1415
1416
0
  struct sieve_storage *storage = lctx->storage;
1417
0
  struct sieve_storage *def_storage = lctx->def_storage;
1418
0
  int ret;
1419
1420
0
  i_assert(storage->v.list_deinit != NULL);
1421
0
  ret = storage->v.list_deinit(lctx);
1422
0
  i_assert(ret >= 0 ||
1423
0
     (storage->error_code != SIEVE_ERROR_NONE &&
1424
0
      storage->error != NULL));
1425
1426
0
  sieve_storage_unref(&def_storage);
1427
0
  sieve_storage_unref(&storage);
1428
0
  return ret;
1429
0
}
1430
1431
/*
1432
 * Saving scripts
1433
 */
1434
1435
static struct event *
1436
sieve_storage_save_create_event(struct sieve_storage *storage,
1437
        const char *scriptname) ATTR_NULL(2)
1438
0
{
1439
0
  struct event *event;
1440
1441
0
  event = event_create(storage->event);
1442
0
  event_add_str(event, "script_name", scriptname);
1443
0
  if (scriptname == NULL) {
1444
0
    event_set_append_log_prefix(event, "save: ");
1445
0
  } else {
1446
0
    event_set_append_log_prefix(
1447
0
      event, t_strdup_printf("script '%s': save: ",
1448
0
                 scriptname));
1449
0
  }
1450
1451
0
  return event;
1452
0
}
1453
1454
static void sieve_storage_save_cleanup(struct sieve_storage_save_context *sctx)
1455
0
{
1456
0
  sieve_script_unref(&sctx->scriptobject);
1457
0
}
1458
1459
static void sieve_storage_save_deinit(struct sieve_storage_save_context **_sctx)
1460
0
{
1461
0
  struct sieve_storage_save_context *sctx = *_sctx;
1462
1463
0
  *_sctx = NULL;
1464
0
  if (sctx == NULL)
1465
0
    return;
1466
1467
0
  sieve_storage_save_cleanup(sctx);
1468
0
  event_unref(&sctx->event);
1469
0
  pool_unref(&sctx->pool);
1470
0
}
1471
1472
struct sieve_storage_save_context *
1473
sieve_storage_save_init(struct sieve_storage *storage, const char *scriptname,
1474
      struct istream *input)
1475
0
{
1476
0
  struct sieve_storage_save_context *sctx;
1477
1478
0
  sieve_storage_clear_error(storage);
1479
1480
0
  if (scriptname != NULL) {
1481
    /* Validate script name */
1482
0
    if (!sieve_script_name_is_valid(scriptname)) {
1483
0
      sieve_storage_set_error(storage,
1484
0
        SIEVE_ERROR_BAD_PARAMS,
1485
0
        "Invalid Sieve script name '%s'.",
1486
0
        str_sanitize(scriptname, 80));
1487
0
      return NULL;
1488
0
    }
1489
0
  }
1490
1491
0
  i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
1492
1493
0
  i_assert(storage->v.save_alloc != NULL);
1494
0
  sctx = storage->v.save_alloc(storage);
1495
0
  sctx->storage = storage;
1496
1497
0
  sctx->event = sieve_storage_save_create_event(storage, scriptname);
1498
1499
0
  struct event_passthrough *e =
1500
0
    event_create_passthrough(sctx->event)->
1501
0
    set_name("sieve_storage_save_started");
1502
0
  e_debug(e->event(), "Started saving script");
1503
1504
0
  i_assert(storage->v.save_init != NULL);
1505
0
  if ((storage->v.save_init(sctx, scriptname, input)) < 0) {
1506
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1507
0
    i_assert(storage->error != NULL);
1508
1509
0
    struct event_passthrough *e =
1510
0
      event_create_passthrough(sctx->event)->
1511
0
      add_str("error", storage->error)->
1512
0
      set_name("sieve_storage_save_finished");
1513
0
    e_debug(e->event(), "Failed to save script: %s",
1514
0
      storage->error);
1515
1516
0
    sieve_storage_save_deinit(&sctx);
1517
0
    return NULL;
1518
0
  }
1519
1520
0
  sctx->mtime = (time_t)-1;
1521
1522
0
  i_assert(sctx->input != NULL);
1523
1524
0
  return sctx;
1525
0
}
1526
1527
int sieve_storage_save_continue(struct sieve_storage_save_context *sctx)
1528
0
{
1529
0
  struct sieve_storage *storage = sctx->storage;
1530
0
  int ret;
1531
1532
0
  sieve_storage_clear_error(storage);
1533
1534
0
  i_assert(storage->v.save_continue != NULL);
1535
0
  ret = storage->v.save_continue(sctx);
1536
0
  if (ret < 0) {
1537
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1538
0
    i_assert(storage->error != NULL);
1539
0
    sctx->failed = TRUE;
1540
0
  }
1541
0
  return ret;
1542
0
}
1543
1544
int sieve_storage_save_finish(struct sieve_storage_save_context *sctx)
1545
0
{
1546
0
  struct sieve_storage *storage = sctx->storage;
1547
0
  bool was_failed = sctx->failed;
1548
0
  int ret;
1549
1550
0
  sieve_storage_clear_error(storage);
1551
1552
0
  i_assert(!sctx->finished);
1553
0
  sctx->finished = TRUE;
1554
1555
0
  i_assert(storage->v.save_finish != NULL);
1556
0
  ret = storage->v.save_finish(sctx);
1557
0
  if (ret < 0 && !was_failed) {
1558
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1559
0
    i_assert(storage->error != NULL);
1560
1561
0
    struct event_passthrough *e =
1562
0
      event_create_passthrough(sctx->event)->
1563
0
      add_str("error", storage->error)->
1564
0
      set_name("sieve_storage_save_finished");
1565
0
    e_debug(e->event(), "Failed to upload script: %s",
1566
0
      storage->error);
1567
1568
0
    sctx->failed = TRUE;
1569
0
  }
1570
0
  return ret;
1571
0
}
1572
1573
void sieve_storage_save_set_mtime(struct sieve_storage_save_context *sctx,
1574
          time_t mtime)
1575
0
{
1576
0
  sctx->mtime = mtime;
1577
0
}
1578
1579
struct sieve_script *
1580
sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx)
1581
0
{
1582
0
  struct sieve_storage *storage = sctx->storage;
1583
1584
0
  if (sctx->failed)
1585
0
    return NULL;
1586
1587
0
  if (sctx->scriptobject != NULL)
1588
0
    return sctx->scriptobject;
1589
1590
0
  sieve_storage_clear_error(storage);
1591
1592
0
  i_assert(storage->v.save_get_tempscript != NULL);
1593
0
  sctx->scriptobject = storage->v.save_get_tempscript(sctx);
1594
1595
0
  i_assert(sctx->scriptobject != NULL ||
1596
0
     (storage->error_code != SIEVE_ERROR_NONE &&
1597
0
      storage->error != NULL));
1598
0
  return sctx->scriptobject;
1599
0
}
1600
1601
bool sieve_storage_save_will_activate(struct sieve_storage_save_context *sctx)
1602
0
{
1603
0
  struct sieve_storage *storage = sctx->storage;
1604
1605
0
  if (sctx->scriptname == NULL)
1606
0
    return FALSE;
1607
1608
0
  sieve_storage_clear_error(storage);
1609
1610
0
  if (sctx->active_scriptname == NULL) {
1611
0
    const char *scriptname;
1612
1613
0
    if (sieve_storage_active_script_get_name(sctx->storage,
1614
0
               &scriptname) > 0) {
1615
0
      sctx->active_scriptname =
1616
0
        p_strdup(sctx->pool, scriptname);
1617
0
    }
1618
0
  }
1619
1620
  /* Is the requested script active? */
1621
0
  return (sctx->active_scriptname != NULL &&
1622
0
    strcmp(sctx->scriptname, sctx->active_scriptname) == 0);
1623
0
}
1624
1625
static int
1626
sieve_storage_save_is_activating_default(
1627
  struct sieve_storage_save_context *sctx)
1628
0
{
1629
0
  struct sieve_storage *storage = sctx->storage;
1630
1631
0
  if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0)
1632
0
    return 0;
1633
0
  if (!sieve_storage_save_will_activate(sctx))
1634
0
    return 0;
1635
1636
0
  struct sieve_storage *def_storage;
1637
0
  enum sieve_error error_code;
1638
0
  int ret = 0;
1639
1640
0
  if (sieve_storage_create_default_for(storage, &def_storage,
1641
0
               &error_code, NULL) < 0) {
1642
0
    if (error_code == SIEVE_ERROR_NOT_FOUND)
1643
0
      return 0;
1644
0
    return -1;
1645
0
  }
1646
1647
0
  if (strcmp(sctx->scriptname, def_storage->script_name) == 0) {
1648
0
    ret = sieve_storage_check_script_direct(
1649
0
      storage, def_storage->script_name, &error_code);
1650
0
    if (ret == 0 ||
1651
0
        (ret < 0 && error_code == SIEVE_ERROR_NOT_FOUND))
1652
0
      ret = 1;
1653
0
    else if (ret > 0)
1654
0
      ret = 0;
1655
0
  }
1656
1657
0
  sieve_storage_unref(&def_storage);
1658
0
  return ret;
1659
0
}
1660
1661
int sieve_storage_save_commit(struct sieve_storage_save_context **_sctx)
1662
0
{
1663
0
  struct sieve_storage_save_context *sctx = *_sctx;
1664
0
  struct sieve_storage *storage;
1665
0
  const char *scriptname;
1666
0
  bool default_activate = FALSE;
1667
0
  int ret;
1668
1669
0
  *_sctx = NULL;
1670
0
  if (sctx == NULL)
1671
0
    return 0;
1672
1673
0
  storage = sctx->storage;
1674
0
  scriptname = sctx->scriptname;
1675
0
  sieve_storage_clear_error(storage);
1676
1677
0
  i_assert(!sctx->failed);
1678
0
  i_assert(sctx->finished);
1679
0
  i_assert(sctx->scriptname != NULL);
1680
1681
  /* Check whether we're replacing the default active script */
1682
0
  ret = sieve_storage_save_is_activating_default(sctx);
1683
0
  if (ret < 0)
1684
0
    return -1;
1685
0
  default_activate = (ret > 0);
1686
1687
0
  sieve_storage_save_cleanup(sctx);
1688
1689
0
  i_assert(storage->v.save_commit != NULL);
1690
0
  ret = storage->v.save_commit(sctx);
1691
0
  i_assert(ret >= 0 ||
1692
0
     (storage->error_code != SIEVE_ERROR_NONE &&
1693
0
      storage->error != NULL));
1694
1695
  /* Implicitly activate it when we're replacing the default
1696
     active script */
1697
0
  if (ret >= 0 && default_activate) {
1698
0
    struct sieve_script *script;
1699
0
    enum sieve_error error_code;
1700
1701
0
    if (sieve_storage_open_script(storage, scriptname,
1702
0
                &script, &error_code) < 0) {
1703
      /* Somehow not actually saved */
1704
0
      ret = (error_code == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
1705
0
    } else if (sieve_script_activate(script, (time_t)-1) < 0) {
1706
      /* Failed to activate; roll back */
1707
0
      ret = -1;
1708
0
      (void)sieve_script_delete(script, TRUE);
1709
0
    }
1710
0
    sieve_script_unref(&script);
1711
1712
0
    if (ret < 0) {
1713
0
      e_error(sctx->event,
1714
0
        "Failed to implicitly activate script '%s' "
1715
0
        "while replacing the default active script",
1716
0
        scriptname);
1717
0
    }
1718
0
  }
1719
1720
0
  if (ret >= 0) {
1721
0
    struct event_passthrough *e =
1722
0
      event_create_passthrough(sctx->event)->
1723
0
      set_name("sieve_storage_save_finished");
1724
0
    e_debug(e->event(), "Finished saving script");
1725
1726
    /* set INBOX mailbox attribute */
1727
0
    (void)sieve_storage_sync_script_save(storage, scriptname);
1728
0
  } else {
1729
0
    struct event_passthrough *e =
1730
0
      event_create_passthrough(sctx->event)->
1731
0
      add_str("error", storage->error)->
1732
0
      set_name("sieve_storage_save_finished");
1733
1734
0
    e_debug(e->event(), "Failed to save script: %s",
1735
0
      storage->error);
1736
0
  }
1737
1738
0
  sieve_storage_save_deinit(&sctx);
1739
0
  return ret;
1740
0
}
1741
1742
void sieve_storage_save_cancel(struct sieve_storage_save_context **_sctx)
1743
0
{
1744
0
  struct sieve_storage_save_context *sctx = *_sctx;
1745
0
  struct sieve_storage *storage;
1746
1747
0
  *_sctx = NULL;
1748
0
  if (sctx == NULL)
1749
0
    return;
1750
1751
0
  storage = sctx->storage;
1752
1753
0
  sctx->failed = TRUE;
1754
1755
0
  sieve_storage_save_cleanup(sctx);
1756
1757
0
  if (!sctx->finished)
1758
0
    (void)sieve_storage_save_finish(sctx);
1759
1760
0
  struct event_passthrough *e =
1761
0
    event_create_passthrough(sctx->event)->
1762
0
    add_str("error", "Canceled")->
1763
0
    set_name("sieve_storage_save_finished");
1764
0
  e_debug(e->event(), "Canceled saving script");
1765
1766
0
  i_assert(storage->v.save_cancel != NULL);
1767
0
  storage->v.save_cancel(sctx);
1768
1769
0
  sieve_storage_save_deinit(&sctx);
1770
0
}
1771
1772
int sieve_storage_save_as_active(struct sieve_storage *storage,
1773
         struct istream *input, time_t mtime)
1774
0
{
1775
0
  struct event *event;
1776
0
  int ret;
1777
1778
0
  sieve_storage_clear_error(storage);
1779
1780
0
  event = event_create(storage->event);
1781
0
  event_set_append_log_prefix(event, "active script: save: ");
1782
1783
0
  struct event_passthrough *e =
1784
0
    event_create_passthrough(event)->
1785
0
    set_name("sieve_storage_save_started");
1786
0
  e_debug(e->event(), "Started saving active script");
1787
1788
0
  i_assert(storage->v.save_as_active != NULL);
1789
0
  ret = storage->v.save_as_active(storage, input, mtime);
1790
1791
0
  if (ret >= 0) {
1792
0
    struct event_passthrough *e =
1793
0
      event_create_passthrough(event)->
1794
0
      set_name("sieve_storage_save_finished");
1795
0
    e_debug(e->event(), "Finished saving active script");
1796
0
  } else {
1797
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1798
0
    i_assert(storage->error != NULL);
1799
1800
0
    struct event_passthrough *e =
1801
0
      event_create_passthrough(event)->
1802
0
      add_str("error", storage->error)->
1803
0
      set_name("sieve_storage_save_finished");
1804
0
    e_debug(e->event(), "Failed to save active script: %s",
1805
0
      storage->error);
1806
0
  }
1807
1808
0
  event_unref(&event);
1809
0
  return ret;
1810
0
}
1811
1812
int sieve_storage_save_as(struct sieve_storage *storage, struct istream *input,
1813
        const char *name)
1814
0
{
1815
0
  struct event *event;
1816
0
  int ret;
1817
1818
0
  sieve_storage_clear_error(storage);
1819
1820
0
  event = sieve_storage_save_create_event(storage, name);
1821
1822
0
  struct event_passthrough *e =
1823
0
    event_create_passthrough(event)->
1824
0
    set_name("sieve_storage_save_started");
1825
0
  e_debug(e->event(), "Started saving script");
1826
1827
0
  i_assert(storage->v.save_as != NULL);
1828
0
  ret = storage->v.save_as(storage, input, name);
1829
1830
0
  if (ret >= 0) {
1831
0
    struct event_passthrough *e =
1832
0
      event_create_passthrough(event)->
1833
0
      set_name("sieve_storage_save_finished");
1834
0
    e_debug(e->event(), "Finished saving sieve script");
1835
0
  } else {
1836
0
    i_assert(storage->error_code != SIEVE_ERROR_NONE);
1837
0
    i_assert(storage->error != NULL);
1838
1839
0
    struct event_passthrough *e =
1840
0
      event_create_passthrough(event)->
1841
0
      add_str("error", storage->error)->
1842
0
      set_name("sieve_storage_save_finished");
1843
0
    e_debug(e->event(), "Failed to save script: %s",
1844
0
      storage->error);
1845
0
  }
1846
1847
0
  event_unref(&event);
1848
0
  return ret;
1849
0
}
1850
1851
/*
1852
 * Checking quota
1853
 */
1854
1855
bool sieve_storage_quota_validsize(struct sieve_storage *storage, size_t size,
1856
           uint64_t *limit_r)
1857
0
{
1858
0
  uint64_t max_size;
1859
1860
0
  max_size = sieve_max_script_size(storage->svinst);
1861
0
  if (max_size > 0 && size > max_size) {
1862
0
    *limit_r = max_size;
1863
0
    return FALSE;
1864
0
  }
1865
1866
0
  return TRUE;
1867
0
}
1868
1869
uint64_t sieve_storage_quota_max_script_size(struct sieve_storage *storage)
1870
0
{
1871
0
  return sieve_max_script_size(storage->svinst);
1872
0
}
1873
1874
int sieve_storage_quota_havespace(struct sieve_storage *storage,
1875
          const char *scriptname, size_t size,
1876
          enum sieve_storage_quota *quota_r,
1877
          uint64_t *limit_r)
1878
0
{
1879
0
  *quota_r = SIEVE_STORAGE_QUOTA_NONE;
1880
0
  *limit_r = 0;
1881
1882
  /* Check the script size */
1883
0
  if (!sieve_storage_quota_validsize(storage, size, limit_r)) {
1884
0
    *quota_r = SIEVE_STORAGE_QUOTA_MAXSIZE;
1885
0
    return 0;
1886
0
  }
1887
1888
  /* Do we need to scan the storage (quota enabled) ? */
1889
0
  if (storage->max_scripts == 0 && storage->max_storage == 0)
1890
0
    return 1;
1891
1892
0
  if (storage->v.quota_havespace == NULL)
1893
0
    return 1;
1894
1895
0
  return storage->v.quota_havespace(storage, scriptname, size,
1896
0
            quota_r, limit_r);
1897
0
}
1898
1899
/*
1900
 * Properties
1901
 */
1902
1903
const char *sieve_storage_name(const struct sieve_storage *storage)
1904
0
{
1905
0
  return storage->name;
1906
0
}
1907
1908
bool sieve_storage_is_default(const struct sieve_storage *storage)
1909
0
{
1910
0
  return storage->is_default;
1911
0
}
1912
1913
bool sieve_storage_is_personal(struct sieve_storage *storage)
1914
0
{
1915
0
  return storage->is_personal;
1916
0
}
1917
1918
/*
1919
 * Error handling
1920
 */
1921
1922
void sieve_storage_clear_error(struct sieve_storage *storage)
1923
0
{
1924
0
  i_free(storage->error);
1925
0
  storage->error_code = SIEVE_ERROR_NONE;
1926
0
  storage->error = NULL;
1927
0
}
1928
1929
void sieve_storage_set_error(struct sieve_storage *storage,
1930
           enum sieve_error error_code, const char *fmt, ...)
1931
0
{
1932
0
  va_list va;
1933
1934
0
  sieve_storage_clear_error(storage);
1935
1936
0
  if (fmt != NULL) {
1937
0
    va_start(va, fmt);
1938
0
    storage->error = i_strdup_vprintf(fmt, va);
1939
0
    va_end(va);
1940
0
  }
1941
1942
0
  storage->error_code = error_code;
1943
0
}
1944
1945
void sieve_storage_copy_error(struct sieve_storage *storage,
1946
            const struct sieve_storage *source)
1947
0
{
1948
0
  sieve_storage_clear_error(storage);
1949
0
  storage->error = i_strdup(source->error);
1950
0
  storage->error_code = source->error_code;
1951
0
}
1952
1953
void sieve_storage_set_internal_error(struct sieve_storage *storage)
1954
0
{
1955
0
  const char *error;
1956
1957
0
  sieve_storage_clear_error(storage);
1958
0
  sieve_error_create_internal(&storage->error_code, &error);
1959
0
  storage->error = i_strdup(error);
1960
0
}
1961
1962
void sieve_storage_set_critical(struct sieve_storage *storage,
1963
        const char *fmt, ...)
1964
0
{
1965
0
  va_list va;
1966
1967
0
  if (fmt != NULL) {
1968
0
    if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0) {
1969
0
      va_start(va, fmt);
1970
0
      e_error(storage->svinst->event, "%s storage: %s",
1971
0
        storage->driver_name,
1972
0
        t_strdup_vprintf(fmt, va));
1973
0
      va_end(va);
1974
1975
0
      sieve_storage_set_internal_error(storage);
1976
1977
0
    } else {
1978
0
      sieve_storage_clear_error(storage);
1979
1980
      /* no user is involved while synchronizing, so do it the
1981
         normal way */
1982
0
      va_start(va, fmt);
1983
0
      storage->error = i_strdup_vprintf(fmt, va);
1984
0
      va_end(va);
1985
1986
0
      storage->error_code = SIEVE_ERROR_TEMP_FAILURE;
1987
0
    }
1988
0
  }
1989
0
}
1990
1991
void sieve_storage_set_not_found_error(struct sieve_storage *storage,
1992
               const char *name)
1993
0
{
1994
0
  enum sieve_error error_code;
1995
0
  const char *error;
1996
1997
0
  sieve_storage_clear_error(storage);
1998
0
  name = (name == NULL || *name == '\0' ? storage->script_name : name);
1999
0
  sieve_error_create_script_not_found(name, &error_code, &error);
2000
0
  storage->error_code = error_code;
2001
0
  storage->error = i_strdup(error);
2002
0
}
2003
2004
const char *
2005
sieve_storage_get_last_error(struct sieve_storage *storage,
2006
           enum sieve_error *error_code_r)
2007
0
{
2008
  /* We get here only in error situations, so we have to return some
2009
     error. If storage->error is NULL, it means we forgot to set it at
2010
     some point..
2011
   */
2012
2013
0
  if (error_code_r != NULL)
2014
0
    *error_code_r = storage->error_code;
2015
2016
0
  return storage->error != NULL ? storage->error : "Unknown error";
2017
0
}
2018
2019
/*
2020
 * Storage sequence
2021
 */
2022
2023
int sieve_storage_sequence_create(struct sieve_instance *svinst,
2024
          struct event *event_parent,
2025
          const char *cause, const char *type,
2026
          struct sieve_storage_sequence **sseq_r,
2027
          enum sieve_error *error_code_r,
2028
          const char **error_r)
2029
0
{
2030
0
  const struct sieve_storage_settings *storage_set;
2031
0
  const char *const *storage_names;
2032
0
  unsigned int storage_count;
2033
0
  const char *error;
2034
2035
0
  *sseq_r = NULL;
2036
0
  sieve_error_args_init(&error_code_r, &error_r);
2037
2038
0
  if (settings_get(event_parent, &sieve_storage_setting_parser_info,
2039
0
       SETTINGS_GET_FLAG_SORT_FILTER_ARRAYS,
2040
0
       &storage_set, &error) < 0) {
2041
0
    e_error(event_parent, "%s", error);
2042
0
    sieve_error_create_internal(error_code_r, error_r);
2043
0
    return -1;
2044
0
  }
2045
0
  if (array_is_created(&storage_set->storages))
2046
0
    storage_names = array_get(&storage_set->storages,
2047
0
            &storage_count);
2048
0
  else {
2049
0
    storage_names = empty_str_array;
2050
0
    storage_count = 0;
2051
0
  }
2052
2053
0
  struct sieve_storage_sequence *sseq;
2054
2055
0
  sseq = i_new(struct sieve_storage_sequence, 1);
2056
0
  sseq->svinst = svinst;
2057
0
  sseq->cause = i_strdup(cause);
2058
0
  sseq->type = i_strdup(type);
2059
0
  sseq->storage_set = storage_set;
2060
0
  sseq->storage_names = storage_names;
2061
0
  sseq->storage_count = storage_count;
2062
2063
0
  sseq->event_parent = event_parent;
2064
0
  event_ref(event_parent);
2065
2066
0
  *sseq_r = sseq;
2067
0
  return 0;
2068
0
}
2069
2070
int sieve_storage_sequence_next(struct sieve_storage_sequence *sseq,
2071
        struct sieve_storage **storage_r,
2072
        enum sieve_error *error_code_r,
2073
        const char **error_r)
2074
0
{
2075
0
  struct sieve_instance *svinst = sseq->svinst;
2076
0
  int ret;
2077
2078
0
  *storage_r = NULL;
2079
0
  sieve_error_args_init(&error_code_r, &error_r);
2080
2081
0
  while (sseq->storage_index < sseq->storage_count) {
2082
0
    unsigned int index = sseq->storage_index++;
2083
2084
0
    ret = sieve_storage_init(svinst, sseq->event_parent,
2085
0
           sseq->cause, sseq->type,
2086
0
           sseq->storage_names[index], TRUE, 0,
2087
0
           storage_r, error_code_r, error_r);
2088
0
    if (ret < 0) {
2089
0
      if (*error_code_r == SIEVE_ERROR_NOT_FOUND) {
2090
0
        *error_code_r = SIEVE_ERROR_NONE;
2091
0
        *error_r = NULL;
2092
0
        continue;
2093
0
      }
2094
0
      return -1;
2095
0
    }
2096
0
    if (ret > 0) {
2097
0
      i_assert(*storage_r != NULL);
2098
0
      return 1;
2099
0
    }
2100
0
  }
2101
2102
0
  return 0;
2103
0
}
2104
2105
void sieve_storage_sequence_free(struct sieve_storage_sequence **_sseq)
2106
0
{
2107
0
  struct sieve_storage_sequence *sseq = *_sseq;
2108
2109
0
  if (sseq == NULL)
2110
0
    return;
2111
0
  *_sseq = NULL;
2112
2113
0
  event_unref(&sseq->event_parent);
2114
0
  i_free(sseq->cause);
2115
0
  i_free(sseq->type);
2116
0
  settings_free(sseq->storage_set);
2117
  i_free(sseq);
2118
0
}