expire-plugin.c revision 4d9c5b872a985e9ff028dae97e6996c67116298b
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2006 PT.COM / SAPO. Code by Tianyan Liu */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "lib.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "dict.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "index-mail.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "index-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "expire-env.h"
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen#include "expire-plugin.h"
e54512a5189192fe72d1e2c53927c98c5ac920b4Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include <stdlib.h>
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen#define EXPIRE_CONTEXT(obj) \
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen *((void **)array_idx_modifiable(&(obj)->module_contexts, \
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen expire.storage_module_id))
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainenstruct expire {
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct dict *db;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct expire_env *env;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen const char *username;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen unsigned int storage_module_id;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen bool storage_module_id_set;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen void (*next_hook_mail_storage_created)(struct mail_storage *storage);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct expire_mail_storage {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_storage_vfuncs super;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenstruct expire_mailbox {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mailbox_vfuncs super;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen time_t expire_secs;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen};
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainenstruct expire_mail {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_vfuncs super;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstruct expire_transaction_context {
8fb1e3e2349c9940732b5bb77a2a4053b8f72a4fTimo Sirainen struct mail *mail;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen time_t first_save_time;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen unsigned int first_expunged:1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenconst char *expire_plugin_version = PACKAGE_VERSION;
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainenstatic struct expire expire;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic struct mailbox_transaction_context *
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenexpire_mailbox_transaction_begin(struct mailbox *box,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen enum mailbox_transaction_flags flags)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(box);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen struct mailbox_transaction_context *t;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen struct expire_transaction_context *xt;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen t = xpr_box->super.transaction_begin(box, flags);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen xt = i_new(struct expire_transaction_context, 1);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen xt->mail = mail_alloc(t, 0, NULL);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen array_idx_set(&t->module_contexts, expire.storage_module_id, &xt);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return t;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int first_nonexpunged_timestamp(struct mailbox_transaction_context *_t,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen time_t *stamp_r)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen{
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen struct index_transaction_context *t =
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen (struct index_transaction_context *)_t;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(_t);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen struct mail_index_view *view = t->trans_view;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const struct mail_index_header *hdr;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const struct mail_index_record *rec;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen uint32_t seq;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen int ret = 0;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen /* find the first non-expunged mail. we're here because the first
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen mail was expunged, so don't bother checking it. */
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen hdr = mail_index_get_header(view);
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen for (seq = 2; seq <= hdr->messages_count; seq++) {
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen ret = mail_index_lookup(view, seq, &rec);
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen if (ret != 0)
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen break;
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen }
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen if (ret < 0) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen *stamp_r = 0;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (ret > 0) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen mail_set_seq(xt->mail, seq);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *stamp_r = mail_get_save_date(xt->mail);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen if (*stamp_r == (time_t)-1)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } else {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* everything expunged */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *stamp_r = 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic int
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenexpire_mailbox_transaction_commit(struct mailbox_transaction_context *t,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mailbox_sync_flags flags)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *key, *value;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen time_t new_stamp;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen bool update_dict;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int ret;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_push();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen key = t_strconcat(DICT_PATH_SHARED, expire.username, "/",
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen t->box->name, NULL);
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen if (xt->first_expunged) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* first mail expunged. dict needs updating. */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen update_dict = first_nonexpunged_timestamp(t, &new_stamp) == 0;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen } else {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen /* saved new mails. dict needs to be updated only if this is
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen the first mail in the database */
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen ret = dict_lookup(expire.db, pool_datastack_create(),
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen key, &value);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen update_dict = ret == 0 || strtoul(value, NULL, 10) == 0;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen new_stamp = xt->first_save_time;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen mail_free(&xt->mail);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen i_free(xt);
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen if (xpr_box->super.transaction_commit(t, flags) < 0) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen t_pop();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen return -1;
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen }
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen if (update_dict) {
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen struct dict_transaction_context *dctx;
5df33e9ee65eec194105b338c55dedbf8422f695Timo Sirainen
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen new_stamp += xpr_box->expire_secs;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
5df33e9ee65eec194105b338c55dedbf8422f695Timo Sirainen dctx = dict_transaction_begin(expire.db);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen dict_set(dctx, key, dec2str(new_stamp));
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen dict_transaction_commit(dctx);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen t_pop();
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen return 0;
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen}
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainenstatic void
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainenexpire_mailbox_transaction_rollback(struct mailbox_transaction_context *t)
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainen{
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mail_free(&xt->mail);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen xpr_box->super.transaction_rollback(t);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen i_free(xt);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainen
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainenstatic int expire_mail_expunge(struct mail *_mail)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct expire_mail *xpr_mail = EXPIRE_CONTEXT(mail);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct expire_transaction_context *xt =
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen EXPIRE_CONTEXT(_mail->transaction);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (xpr_mail->super.expunge(_mail) < 0)
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return -1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (_mail->seq == 1) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* first mail expunged, database needs to be updated */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen xt->first_expunged = TRUE;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen }
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return 0;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic struct mail *
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenexpire_mail_alloc(struct mailbox_transaction_context *t,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen enum mail_fetch_field wanted_fields,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen struct expire_mail *xpr_mail;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct mail *_mail;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct mail_private *mail;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen _mail = xpr_box->super.mail_alloc(t, wanted_fields, wanted_headers);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail = (struct mail_private *)_mail;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen xpr_mail = p_new(mail->pool, struct expire_mail, 1);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen xpr_mail->super = mail->v;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen mail->v.expunge = expire_mail_expunge;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen array_idx_set(&mail->module_contexts, expire.storage_module_id,
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen &xpr_mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return _mail;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic void
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenmail_set_save_time(struct mailbox_transaction_context *t, uint32_t seq)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen{
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen struct index_transaction_context *it =
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen (struct index_transaction_context *)t;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
1952eb389b8aba39195380970f905dcebea38dfcTimo Sirainen if (xt->first_save_time == 0)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen xt->first_save_time = ioloop_time;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_add(it->cache_trans, seq, MAIL_CACHE_SAVE_DATE,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen &ioloop_time, sizeof(ioloop_time));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenstatic int
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenexpire_save_init(struct mailbox_transaction_context *t,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen time_t received_date, int timezone_offset,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const char *from_envelope, struct istream *input,
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct mail *dest_mail, struct mail_save_context **ctx_r)
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen int ret;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (dest_mail == NULL)
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen dest_mail = xt->mail;
45b2a27617d8475f71fdfc870690e46cd63849f2Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen ret = xpr_box->super.save_init(t, flags, keywords, received_date,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen timezone_offset, from_envelope, input,
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen dest_mail, ctx_r);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen if (ret >= 0)
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen mail_set_save_time(t, dest_mail->seq);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen return ret;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen}
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainenexpire_copy(struct mailbox_transaction_context *t, struct mail *mail,
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen struct mail *dest_mail)
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen{
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen int ret;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen if (dest_mail == NULL)
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen dest_mail = xt->mail;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen ret = xpr_box->super.copy(t, mail, flags, keywords, dest_mail);
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen if (ret >= 0)
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen mail_set_save_time(t, dest_mail->seq);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return ret;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void mailbox_expire_hook(struct mailbox *box, time_t expire_secs)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct expire_mailbox *xpr_box;
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen xpr_box = p_new(box->pool, struct expire_mailbox, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen xpr_box->super = box->v;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
5f44975ec6c5755dd74bcd4c47a123a7242ecab3Timo Sirainen box->v.transaction_begin = expire_mailbox_transaction_begin;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->v.transaction_commit = expire_mailbox_transaction_commit;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->v.transaction_rollback = expire_mailbox_transaction_rollback;
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen box->v.mail_alloc = expire_mail_alloc;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen box->v.save_init = expire_save_init;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen box->v.copy = expire_copy;
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen xpr_box->expire_secs = expire_secs;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen array_idx_set(&box->module_contexts,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen expire.storage_module_id, &xpr_box);
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen}
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainenstatic struct mailbox *
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenexpire_mailbox_open(struct mail_storage *storage, const char *name,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct istream *input, enum mailbox_open_flags flags)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen struct expire_mail_storage *xpr_storage = EXPIRE_CONTEXT(storage);
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen struct mailbox *box;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const struct expire_box *expire_box;
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen box = xpr_storage->super.mailbox_open(storage, name, input, flags);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (box != NULL) {
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen expire_box = expire_box_find(expire.env, name);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (expire_box != NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mailbox_expire_hook(box, expire_box->expire_secs);
df459621b9124dfd88d56619ac84611f30fec854Stephan Bosch }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return box;
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
946f22af116d5af80d5bbe1710ac121aa5acef71Stephan Boschstatic void expire_mail_storage_created(struct mail_storage *storage)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct expire_mail_storage *xpr_storage;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (expire.next_hook_mail_storage_created != NULL)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen expire.next_hook_mail_storage_created(storage);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen xpr_storage = p_new(storage->pool, struct expire_mail_storage, 1);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen xpr_storage->super = storage->v;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen storage->v.mailbox_open = expire_mailbox_open;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (!expire.storage_module_id_set) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen expire.storage_module_id = mail_storage_module_id++;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen expire.storage_module_id_set = TRUE;
eed20b28dd9039d21f5c2770beef2e8b19f7c2f9Timo Sirainen }
eed20b28dd9039d21f5c2770beef2e8b19f7c2f9Timo Sirainen
eed20b28dd9039d21f5c2770beef2e8b19f7c2f9Timo Sirainen array_idx_set(&storage->module_contexts,
eed20b28dd9039d21f5c2770beef2e8b19f7c2f9Timo Sirainen expire.storage_module_id, &xpr_storage);
eed20b28dd9039d21f5c2770beef2e8b19f7c2f9Timo Sirainen}
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenvoid expire_plugin_init(void)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *env, *dict_uri;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen env = getenv("EXPIRE");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (env != NULL) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen dict_uri = getenv("EXPIRE_DICT");
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (dict_uri == NULL)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_fatal("expire plugin: expire_dict setting missing");
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen expire.env = expire_env_init(env);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen expire.db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, NULL);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen expire.username = getenv("USER");
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen expire.next_hook_mail_storage_created =
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen hook_mail_storage_created;
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen hook_mail_storage_created = expire_mail_storage_created;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainenvoid expire_plugin_deinit(void)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (expire.db != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen hook_mail_storage_created =
60576cd64e6a537413cd90104f7e862f71d48c81Timo Sirainen expire.next_hook_mail_storage_created;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen dict_deinit(&expire.db);
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen expire_env_deinit(expire.env);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen }
203560029e3ad8687c2c759e6a81ecdb8b37ebe6Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen