Coverage Report

Created: 2026-06-09 06:49

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