~ubuntu-branches/ubuntu/wily/dovecot/wily-proposed

« back to all changes in this revision

Viewing changes to src/plugins/lazy-expunge/lazy-expunge-plugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2008-08-02 14:00:15 UTC
  • mto: (1.11.1 upstream) (4.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20080802140015-zbmjsgoodeyc9z4s
Tags: upstream-1.1.2
ImportĀ upstreamĀ versionĀ 1.1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2006 Timo Sirainen */
 
1
/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
2
2
 
3
 
#include "common.h"
 
3
#include "lib.h"
4
4
#include "ioloop.h"
5
5
#include "array.h"
6
6
#include "str.h"
7
7
#include "seq-range-array.h"
8
8
#include "maildir-storage.h"
9
 
#include "client.h"
10
 
#include "namespace.h"
 
9
#include "mail-namespace.h"
11
10
#include "lazy-expunge-plugin.h"
12
11
 
13
12
#include <stdio.h>
17
16
#include <time.h>
18
17
 
19
18
#define LAZY_EXPUNGE_CONTEXT(obj) \
20
 
        *((void **)array_idx_modifyable(&(obj)->module_contexts, \
21
 
                                        lazy_expunge_storage_module_id))
 
19
        MODULE_CONTEXT(obj, lazy_expunge_mail_storage_module)
 
20
#define LAZY_EXPUNGE_LIST_CONTEXT(obj) \
 
21
        MODULE_CONTEXT(obj, lazy_expunge_mailbox_list_module)
22
22
 
23
23
enum lazy_namespace {
24
24
        LAZY_NAMESPACE_EXPUNGE,
28
28
        LAZY_NAMESPACE_COUNT
29
29
};
30
30
 
 
31
struct lazy_expunge_mailbox_list {
 
32
        union mailbox_list_module_context module_ctx;
 
33
 
 
34
        struct mail_storage *storage;
 
35
};
 
36
 
31
37
struct lazy_expunge_mail_storage {
32
 
        struct mail_storage_vfuncs super;
 
38
        union mail_storage_module_context module_ctx;
 
39
 
33
40
        bool internal_namespace;
34
41
};
35
42
 
36
 
struct lazy_expunge_mailbox {
37
 
        struct mailbox_vfuncs super;
38
 
};
39
 
 
40
43
struct lazy_expunge_transaction {
41
 
        array_t ARRAY_DEFINE(expunge_seqs, struct seq_range);
 
44
        union mailbox_transaction_module_context module_ctx;
 
45
 
 
46
        ARRAY_TYPE(seq_range) expunge_seqs;
42
47
        struct mailbox *expunge_box;
43
 
};
44
48
 
45
 
struct lazy_expunge_mail {
46
 
        struct mail_vfuncs super;
 
49
        bool failed;
47
50
};
48
51
 
49
52
const char *lazy_expunge_plugin_version = PACKAGE_VERSION;
50
53
 
 
54
static void (*lazy_expunge_next_hook_mail_namespaces_created)
 
55
        (struct mail_namespace *namespaces);
51
56
static void (*lazy_expunge_next_hook_mail_storage_created)
52
57
        (struct mail_storage *storage);
53
 
static void (*lazy_expunge_next_hook_client_created)(struct client **client);
54
 
 
55
 
static unsigned int lazy_expunge_storage_module_id = 0;
56
 
static bool lazy_expunge_storage_module_id_set = FALSE;
57
 
 
58
 
static struct namespace *lazy_namespaces[LAZY_NAMESPACE_COUNT];
 
58
static void (*lazy_expunge_next_hook_mailbox_list_created)
 
59
        (struct mailbox_list *list);
 
60
 
 
61
static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_storage_module,
 
62
                                  &mail_storage_module_register);
 
63
static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_module,
 
64
                                  &mail_module_register);
 
65
static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mailbox_list_module,
 
66
                                  &mailbox_list_module_register);
 
67
 
 
68
static struct mail_namespace *lazy_namespaces[LAZY_NAMESPACE_COUNT];
59
69
 
60
70
static struct mailbox *
61
71
mailbox_open_or_create(struct mail_storage *storage, const char *name)
62
72
{
63
73
        struct mailbox *box;
64
 
        bool syntax, temp;
 
74
        enum mail_error error;
65
75
 
66
76
        box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
67
77
                           MAILBOX_OPEN_KEEP_RECENT |
69
79
        if (box != NULL)
70
80
                return box;
71
81
 
72
 
        (void)mail_storage_get_last_error(storage, &syntax, &temp);
73
 
        if (syntax || temp)
 
82
        (void)mail_storage_get_last_error(storage, &error);
 
83
        if (error != MAIL_ERROR_NOTFOUND)
74
84
                return NULL;
75
85
 
76
 
        /* probably the mailbox just doesn't exist. try creating it. */
 
86
        /* try creating it. */
77
87
        if (mail_storage_mailbox_create(storage, name, FALSE) < 0)
78
88
                return NULL;
79
89
 
83
93
        return box;
84
94
}
85
95
 
86
 
static int lazy_expunge_mail_expunge(struct mail *_mail)
 
96
static void lazy_expunge_mail_expunge(struct mail *_mail)
87
97
{
88
98
        struct lazy_expunge_transaction *lt =
89
99
                LAZY_EXPUNGE_CONTEXT(_mail->transaction);
96
106
                if (lt->expunge_box == NULL) {
97
107
                        mail_storage_set_critical(_mail->box->storage,
98
108
                                "lazy_expunge: Couldn't open expunge mailbox");
99
 
                        return -1;
 
109
                        lt->failed = TRUE;
 
110
                        return;
100
111
                }
101
112
        }
102
113
 
103
114
        seq_range_array_add(&lt->expunge_seqs, 32, _mail->uid);
104
 
        return 0;
105
115
}
106
116
 
107
117
static struct mailbox_transaction_context *
108
118
lazy_expunge_transaction_begin(struct mailbox *box,
109
119
                               enum mailbox_transaction_flags flags)
110
120
{
111
 
        struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(box);
 
121
        union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(box);
112
122
        struct mailbox_transaction_context *t;
113
123
        struct lazy_expunge_transaction *lt;
114
124
 
115
 
        t = qbox->super.transaction_begin(box, flags);
 
125
        t = mbox->super.transaction_begin(box, flags);
116
126
        lt = i_new(struct lazy_expunge_transaction, 1);
117
127
 
118
 
        array_idx_set(&t->module_contexts, lazy_expunge_storage_module_id, &lt);
 
128
        MODULE_CONTEXT_SET(t, lazy_expunge_mail_storage_module, lt);
119
129
        return t;
120
130
}
121
131
 
124
134
        unsigned int dir_len;
125
135
};
126
136
 
127
 
static int lazy_expunge_move(struct maildir_mailbox *mbox __attr_unused__,
 
137
static int lazy_expunge_move(struct maildir_mailbox *mbox,
128
138
                             const char *path, void *context)
129
139
{
130
140
        struct lazy_expunge_move_context *ctx = context;
172
182
 
173
183
        range = array_get(&lt->expunge_seqs, &count);
174
184
        for (i = 0; i < count && ret == 0; i++) {
175
 
                if (mailbox_get_uids(srcbox, range[i].seq1, range[i].seq2,
176
 
                                     &seq1, &seq2) < 0) {
177
 
                        ret = -1;
178
 
                        break;
179
 
                }
180
 
 
 
185
                mailbox_get_uids(srcbox, range[i].seq1, range[i].seq2,
 
186
                                 &seq1, &seq2);
181
187
                for (uid = range[i].seq1; uid <= range[i].seq2; uid++) {
182
188
                        if (maildir_file_do(msrcbox, uid, lazy_expunge_move,
183
189
                                            &ctx) < 0) {
189
195
                        mail_index_expunge(itrans->trans, seq);
190
196
        }
191
197
 
192
 
        if (mailbox_transaction_commit(&trans, 0) < 0)
 
198
        if (mailbox_transaction_commit(&trans) < 0)
193
199
                ret = -1;
194
200
 
195
201
        str_free(&ctx.path);
207
213
 
208
214
static int
209
215
lazy_expunge_transaction_commit(struct mailbox_transaction_context *ctx,
210
 
                                enum mailbox_sync_flags flags)
 
216
                                uint32_t *uid_validity_r,
 
217
                                uint32_t *first_saved_uid_r,
 
218
                                uint32_t *last_saved_uid_r)
211
219
{
212
 
        struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
 
220
        union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
213
221
        struct lazy_expunge_transaction *lt = LAZY_EXPUNGE_CONTEXT(ctx);
214
222
        struct mailbox *srcbox = ctx->box;
215
223
        int ret;
216
224
 
217
 
        ret = qbox->super.transaction_commit(ctx, flags);
 
225
        if (lt->failed) {
 
226
                mbox->super.transaction_rollback(ctx);
 
227
                ret = -1;
 
228
        } else {
 
229
                ret = mbox->super.transaction_commit(ctx, uid_validity_r,
 
230
                                                     first_saved_uid_r,
 
231
                                                     last_saved_uid_r);
 
232
        }
218
233
 
219
234
        if (ret == 0 && array_is_created(&lt->expunge_seqs))
220
235
                ret = lazy_expunge_move_expunges(srcbox, lt);
226
241
static void
227
242
lazy_expunge_transaction_rollback(struct mailbox_transaction_context *ctx)
228
243
{
229
 
        struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
 
244
        union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
230
245
        struct lazy_expunge_transaction *lt = LAZY_EXPUNGE_CONTEXT(ctx);
231
246
 
232
 
        qbox->super.transaction_rollback(ctx);
 
247
        mbox->super.transaction_rollback(ctx);
233
248
        lazy_expunge_transaction_free(lt);
234
249
}
235
250
 
238
253
                        enum mail_fetch_field wanted_fields,
239
254
                        struct mailbox_header_lookup_ctx *wanted_headers)
240
255
{
241
 
        struct lazy_expunge_mailbox *qbox = LAZY_EXPUNGE_CONTEXT(t->box);
242
 
        struct lazy_expunge_mail *lmail;
 
256
        union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(t->box);
 
257
        union mail_module_context *mmail;
243
258
        struct mail *_mail;
244
259
        struct mail_private *mail;
245
260
 
246
 
        _mail = qbox->super.mail_alloc(t, wanted_fields, wanted_headers);
 
261
        _mail = mbox->super.mail_alloc(t, wanted_fields, wanted_headers);
247
262
        mail = (struct mail_private *)_mail;
248
263
 
249
 
        lmail = p_new(mail->pool, struct lazy_expunge_mail, 1);
250
 
        lmail->super = mail->v;
 
264
        mmail = p_new(mail->pool, union mail_module_context, 1);
 
265
        mmail->super = mail->v;
251
266
 
252
267
        mail->v.expunge = lazy_expunge_mail_expunge;
253
 
        array_idx_set(&mail->module_contexts,
254
 
                      lazy_expunge_storage_module_id, &lmail);
 
268
        MODULE_CONTEXT_SET_SELF(mail, lazy_expunge_mail_module, mmail);
255
269
        return _mail;
256
270
}
257
271
 
262
276
        struct lazy_expunge_mail_storage *lstorage =
263
277
                LAZY_EXPUNGE_CONTEXT(storage);
264
278
        struct mailbox *box;
265
 
        struct lazy_expunge_mailbox *qbox;
 
279
        union mailbox_module_context *mbox;
266
280
 
267
 
        box = lstorage->super.mailbox_open(storage, name, input, flags);
 
281
        box = lstorage->module_ctx.super.
 
282
                mailbox_open(storage, name, input, flags);
268
283
        if (box == NULL || lstorage->internal_namespace)
269
284
                return box;
270
285
 
271
 
        qbox = p_new(box->pool, struct lazy_expunge_mailbox, 1);
272
 
        qbox->super = box->v;
 
286
        mbox = p_new(box->pool, union mailbox_module_context, 1);
 
287
        mbox->super = box->v;
273
288
 
274
289
        box->v.transaction_begin = lazy_expunge_transaction_begin;
275
290
        box->v.transaction_commit = lazy_expunge_transaction_commit;
276
291
        box->v.transaction_rollback = lazy_expunge_transaction_rollback;
277
292
        box->v.mail_alloc = lazy_expunge_mail_alloc;
278
 
        array_idx_set(&box->module_contexts,
279
 
                      lazy_expunge_storage_module_id, &qbox);
 
293
        MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module, mbox);
280
294
        return box;
281
295
}
282
296
 
283
 
static int dir_move_or_merge(struct mail_storage *storage,
 
297
static int dir_move_or_merge(struct mailbox_list *list,
284
298
                             const char *srcdir, const char *destdir)
285
299
{
286
300
        DIR *dir;
293
307
                return 0;
294
308
 
295
309
        if (!EDESTDIREXISTS(errno)) {
296
 
                mail_storage_set_critical(storage,
 
310
                mailbox_list_set_critical(list,
297
311
                        "rename(%s, %s) failed: %m", srcdir, destdir);
298
312
        }
299
313
 
300
314
        /* rename all the files separately */
301
315
        dir = opendir(srcdir);
302
316
        if (dir == NULL) {
303
 
                mail_storage_set_critical(storage,
 
317
                mailbox_list_set_critical(list,
304
318
                        "opendir(%s) failed: %m", srcdir);
305
319
                return -1;
306
320
        }
328
342
 
329
343
                if (rename(str_c(src_path), str_c(dest_path)) < 0 &&
330
344
                    errno != ENOENT) {
331
 
                        mail_storage_set_critical(storage,
 
345
                        mailbox_list_set_critical(list,
332
346
                                "rename(%s, %s) failed: %m",
333
347
                                str_c(src_path), str_c(dest_path));
334
348
                        ret = -1;
335
349
                }
336
350
        }
337
351
        if (closedir(dir) < 0) {
338
 
                mail_storage_set_critical(storage,
 
352
                mailbox_list_set_critical(list,
339
353
                        "closedir(%s) failed: %m", srcdir);
340
354
                ret = -1;
341
355
        }
342
356
        if (ret == 0) {
343
357
                if (rmdir(srcdir) < 0) {
344
 
                        mail_storage_set_critical(storage,
 
358
                        mailbox_list_set_critical(list,
345
359
                                "rmdir(%s) failed: %m", srcdir);
346
360
                        ret = -1;
347
361
                }
350
364
}
351
365
 
352
366
static int
353
 
mailbox_move(struct mail_storage *src_storage, const char *src_name,
354
 
             struct mail_storage *dest_storage, const char **_dest_name)
 
367
mailbox_move(struct mailbox_list *src_list, const char *src_name,
 
368
             struct mailbox_list *dest_list, const char **_dest_name)
355
369
{
356
 
        struct index_storage *src_istorage =
357
 
                (struct index_storage *)src_storage;
358
 
        struct index_storage *dest_istorage =
359
 
                (struct index_storage *)dest_storage;
360
370
        const char *dest_name = *_dest_name;
361
371
        const char *srcdir, *src2dir, *src3dir, *destdir;
362
 
        bool is_file;
363
372
 
364
 
        srcdir = mail_storage_get_mailbox_path(src_storage, src_name, &is_file);
365
 
        destdir = mail_storage_get_mailbox_path(dest_storage, dest_name,
366
 
                                                &is_file);
 
373
        srcdir = mailbox_list_get_path(src_list, src_name,
 
374
                                       MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
375
        destdir = mailbox_list_get_path(dest_list, dest_name,
 
376
                                        MAILBOX_LIST_PATH_TYPE_MAILBOX);
367
377
        while (rename(srcdir, destdir) < 0) {
368
378
                if (errno == ENOENT)
369
379
                        return 0;
370
380
 
371
381
                if (!EDESTDIREXISTS(errno)) {
372
 
                        mail_storage_set_critical(src_storage,
 
382
                        mailbox_list_set_critical(src_list,
373
383
                                "rename(%s, %s) failed: %m", srcdir, destdir);
374
384
                        return -1;
375
385
                }
378
388
                   update the filename. */
379
389
                dest_name = t_strdup_printf("%s-%04u", *_dest_name,
380
390
                                            (uint32_t)random());
381
 
                destdir = mail_storage_get_mailbox_path(dest_storage, dest_name,
382
 
                                                        &is_file);
 
391
                destdir = mailbox_list_get_path(dest_list, dest_name,
 
392
                                                MAILBOX_LIST_PATH_TYPE_MAILBOX);
383
393
        }
384
394
 
385
 
        t_push();
386
 
        src2dir = mail_storage_get_mailbox_control_dir(src_storage, src_name);
 
395
        src2dir = mailbox_list_get_path(src_list, src_name,
 
396
                                        MAILBOX_LIST_PATH_TYPE_CONTROL);
387
397
        if (strcmp(src2dir, srcdir) != 0) {
388
 
                destdir = mail_storage_get_mailbox_control_dir(dest_storage,
389
 
                                                               dest_name);
390
 
                (void)dir_move_or_merge(src_storage, src2dir, destdir);
 
398
                destdir = mailbox_list_get_path(dest_list, dest_name,
 
399
                                                MAILBOX_LIST_PATH_TYPE_CONTROL);
 
400
                (void)dir_move_or_merge(src_list, src2dir, destdir);
391
401
        }
392
 
        src3dir = t_strconcat(src_istorage->index_dir, "/"MAILDIR_FS_SEP_S,
393
 
                              src_name, NULL);
 
402
        src3dir = mailbox_list_get_path(src_list, src_name,
 
403
                                        MAILBOX_LIST_PATH_TYPE_INDEX);
394
404
        if (strcmp(src3dir, srcdir) != 0 && strcmp(src3dir, src2dir) != 0) {
395
 
                destdir = t_strconcat(dest_istorage->index_dir,
396
 
                                      "/"MAILDIR_FS_SEP_S,
397
 
                                      dest_name, NULL);
398
 
                (void)dir_move_or_merge(src_storage, src3dir, destdir);
 
405
                destdir = mailbox_list_get_path(dest_list, dest_name,
 
406
                                                MAILBOX_LIST_PATH_TYPE_INDEX);
 
407
                (void)dir_move_or_merge(src_list, src3dir, destdir);
399
408
        }
400
 
        t_pop();
401
409
 
402
410
        *_dest_name = dest_name;
403
411
        return 1;
404
412
}
405
413
 
406
414
static int
407
 
lazy_expunge_mailbox_delete(struct mail_storage *storage, const char *name)
 
415
lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
408
416
{
409
 
        struct lazy_expunge_mail_storage *lstorage =
410
 
                LAZY_EXPUNGE_CONTEXT(storage);
411
 
        struct mail_storage *dest_storage;
 
417
        struct lazy_expunge_mailbox_list *llist =
 
418
                LAZY_EXPUNGE_LIST_CONTEXT(list);
 
419
        struct lazy_expunge_mail_storage *lstorage;
 
420
        struct mailbox_list *dest_list;
412
421
        enum mailbox_name_status status;
413
422
        const char *destname;
414
423
        struct tm *tm;
415
424
        char timestamp[256];
416
425
        int ret;
417
426
 
 
427
        if (llist->storage == NULL) {
 
428
                /* not a maildir storage */
 
429
                return llist->module_ctx.super.delete_mailbox(list, name);
 
430
        }
 
431
 
 
432
        lstorage = LAZY_EXPUNGE_CONTEXT(llist->storage);
418
433
        if (lstorage->internal_namespace)
419
 
                return lstorage->super.mailbox_delete(storage, name);
420
 
 
421
 
        mail_storage_clear_error(storage);
 
434
                return llist->module_ctx.super.delete_mailbox(list, name);
422
435
 
423
436
        /* first do the normal sanity checks */
424
437
        if (strcmp(name, "INBOX") == 0) {
425
 
                mail_storage_set_error(storage, "INBOX can't be deleted.");
 
438
                mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
 
439
                                       "INBOX can't be deleted.");
426
440
                return -1;
427
441
        }
428
442
 
429
 
        if (mail_storage_get_mailbox_name_status(storage, name, &status) < 0)
 
443
        if (mailbox_list_get_mailbox_name_status(list, name, &status) < 0)
430
444
                return -1;
431
445
        if (status == MAILBOX_NAME_INVALID) {
432
 
                mail_storage_set_error(storage, "Invalid mailbox name");
 
446
                mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
 
447
                                       "Invalid mailbox name");
433
448
                return -1;
434
449
        }
435
450
 
436
451
        /* destination mailbox name needs to contain a timestamp */
437
452
        tm = localtime(&ioloop_time);
438
453
        if (strftime(timestamp, sizeof(timestamp), "%Y%m%d-%H%M%S", tm) == 0)
439
 
                strocpy(timestamp, dec2str(ioloop_time), sizeof(timestamp));
 
454
                i_strocpy(timestamp, dec2str(ioloop_time), sizeof(timestamp));
440
455
        destname = t_strconcat(name, "-", timestamp, NULL);
441
456
 
442
457
        /* first move the actual mailbox */
443
 
        dest_storage = lazy_namespaces[LAZY_NAMESPACE_DELETE]->storage;
444
 
        if ((ret = mailbox_move(storage, name, dest_storage, &destname)) < 0)
 
458
        dest_list = lazy_namespaces[LAZY_NAMESPACE_DELETE]->storage->list;
 
459
        if ((ret = mailbox_move(list, name, dest_list, &destname)) < 0)
445
460
                return -1;
446
461
        if (ret == 0) {
447
 
                mail_storage_set_error(storage,
448
 
                        MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND, name);
 
462
                mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
 
463
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
449
464
                return -1;
450
465
        }
451
466
 
452
467
        /* next move the expunged messages mailbox, if it exists */
453
 
        storage = lazy_namespaces[LAZY_NAMESPACE_EXPUNGE]->storage;
454
 
        dest_storage = lazy_namespaces[LAZY_NAMESPACE_DELETE_EXPUNGE]->storage;
455
 
        (void)mailbox_move(storage, name, dest_storage, &destname);
 
468
        list = lazy_namespaces[LAZY_NAMESPACE_EXPUNGE]->storage->list;
 
469
        dest_list =
 
470
                lazy_namespaces[LAZY_NAMESPACE_DELETE_EXPUNGE]->storage->list;
 
471
        (void)mailbox_move(list, name, dest_list, &destname);
456
472
        return 0;
457
473
}
458
474
 
 
475
static void lazy_expunge_mail_storage_init(struct mail_storage *storage)
 
476
{
 
477
        struct lazy_expunge_mailbox_list *llist =
 
478
                LAZY_EXPUNGE_LIST_CONTEXT(storage->list);
 
479
        struct lazy_expunge_mail_storage *lstorage;
 
480
        const char *const *p;
 
481
        unsigned int i;
 
482
 
 
483
        /* if this is one of our internal storages, mark it as such before
 
484
           quota plugin sees it */
 
485
        p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
 
486
        for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
 
487
                if (strcmp(storage->ns->prefix, *p) == 0) {
 
488
                        storage->ns->flags |= NAMESPACE_FLAG_INTERNAL;
 
489
                        break;
 
490
                }
 
491
        }
 
492
 
 
493
        llist->storage = storage;
 
494
 
 
495
        lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
 
496
        lstorage->module_ctx.super = storage->v;
 
497
        storage->v.mailbox_open = lazy_expunge_mailbox_open;
 
498
 
 
499
        MODULE_CONTEXT_SET(storage, lazy_expunge_mail_storage_module, lstorage);
 
500
}
 
501
 
459
502
static void lazy_expunge_mail_storage_created(struct mail_storage *storage)
460
503
{
461
 
        struct lazy_expunge_mail_storage *lstorage;
 
504
        /* only maildir supported for now */
 
505
        if (strcmp(storage->name, "maildir") == 0)
 
506
                lazy_expunge_mail_storage_init(storage);
462
507
 
463
508
        if (lazy_expunge_next_hook_mail_storage_created != NULL)
464
509
                lazy_expunge_next_hook_mail_storage_created(storage);
465
 
 
466
 
        /* only maildir supported for now */
467
 
        if (strcmp(storage->name, "maildir") != 0)
468
 
                return;
469
 
 
470
 
        lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
471
 
        lstorage->super = storage->v;
472
 
        storage->v.mailbox_open = lazy_expunge_mailbox_open;
473
 
        storage->v.mailbox_delete = lazy_expunge_mailbox_delete;
474
 
 
475
 
        if (!lazy_expunge_storage_module_id_set) {
476
 
                lazy_expunge_storage_module_id = mail_storage_module_id++;
477
 
                lazy_expunge_storage_module_id_set = TRUE;
478
 
        }
479
 
 
480
 
        array_idx_set(&storage->module_contexts,
481
 
                      lazy_expunge_storage_module_id, &lstorage);
482
 
}
483
 
 
484
 
static void lazy_expunge_hook_client_created(struct client **client)
 
510
}
 
511
 
 
512
static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
 
513
{
 
514
        struct lazy_expunge_mailbox_list *llist;
 
515
 
 
516
        if (lazy_expunge_next_hook_mailbox_list_created != NULL)
 
517
                lazy_expunge_next_hook_mailbox_list_created(list);
 
518
 
 
519
        llist = p_new(list->pool, struct lazy_expunge_mailbox_list, 1);
 
520
        llist->module_ctx.super = list->v;
 
521
        list->v.delete_mailbox = lazy_expunge_mailbox_list_delete;
 
522
 
 
523
        MODULE_CONTEXT_SET(list, lazy_expunge_mailbox_list_module, llist);
 
524
}
 
525
 
 
526
static void
 
527
lazy_expunge_hook_mail_namespaces_created(struct mail_namespace *namespaces)
485
528
{
486
529
        struct lazy_expunge_mail_storage *lstorage;
487
530
        const char *const *p;
488
531
        int i;
489
532
 
490
 
        if (lazy_expunge_next_hook_client_created != NULL)
491
 
                lazy_expunge_next_hook_client_created(client);
 
533
        if (lazy_expunge_next_hook_mail_namespaces_created != NULL)
 
534
                lazy_expunge_next_hook_mail_namespaces_created(namespaces);
492
535
 
493
 
        /* FIXME: this works only as long as there's only one client. */
494
 
        t_push();
495
 
        p = t_strsplit(getenv("LAZY_EXPUNGE"), " ");
 
536
        p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
496
537
        for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
497
538
                const char *name = *p;
498
539
 
500
541
                        i_fatal("lazy_expunge: Missing namespace #%d", i + 1);
501
542
 
502
543
                lazy_namespaces[i] =
503
 
                        namespace_find_prefix((*client)->namespaces, name);
 
544
                        mail_namespace_find_prefix(namespaces, name);
504
545
                if (lazy_namespaces[i] == NULL)
505
546
                        i_fatal("lazy_expunge: Unknown namespace: '%s'", name);
506
547
                if (strcmp(lazy_namespaces[i]->storage->name, "maildir") != 0) {
513
554
                lstorage = LAZY_EXPUNGE_CONTEXT(lazy_namespaces[i]->storage);
514
555
                lstorage->internal_namespace = TRUE;
515
556
        }
516
 
        t_pop();
517
557
}
518
558
 
519
559
void lazy_expunge_plugin_init(void)
521
561
        if (getenv("LAZY_EXPUNGE") == NULL)
522
562
                return;
523
563
 
524
 
        lazy_expunge_next_hook_client_created = hook_client_created;
525
 
        hook_client_created = lazy_expunge_hook_client_created;
 
564
        lazy_expunge_next_hook_mail_namespaces_created =
 
565
                hook_mail_namespaces_created;
 
566
        hook_mail_namespaces_created =
 
567
                lazy_expunge_hook_mail_namespaces_created;
526
568
 
527
 
        lazy_expunge_next_hook_mail_storage_created =
528
 
                hook_mail_storage_created;
 
569
        lazy_expunge_next_hook_mail_storage_created = hook_mail_storage_created;
529
570
        hook_mail_storage_created = lazy_expunge_mail_storage_created;
 
571
 
 
572
        lazy_expunge_next_hook_mailbox_list_created = hook_mailbox_list_created;
 
573
        hook_mailbox_list_created = lazy_expunge_mailbox_list_created;
530
574
}
531
575
 
532
576
void lazy_expunge_plugin_deinit(void)
533
577
{
534
 
        if (lazy_expunge_storage_module_id_set) {
535
 
                hook_client_created = lazy_expunge_hook_client_created;
 
578
        if (getenv("LAZY_EXPUNGE") == NULL)
 
579
                return;
536
580
 
537
 
                hook_mail_storage_created =
538
 
                        lazy_expunge_next_hook_mail_storage_created;
539
 
        }
 
581
        hook_mail_namespaces_created =
 
582
                lazy_expunge_hook_mail_namespaces_created;
 
583
        hook_mail_storage_created = lazy_expunge_next_hook_mail_storage_created;
 
584
        hook_mailbox_list_created = lazy_expunge_next_hook_mailbox_list_created;
540
585
}