[Dovecot] Loadable module

Timo Sirainen tss at iki.fi
Tue Jul 22 17:11:12 EEST 2003


On Tue, 2003-07-22 at 14:04, Maikel Verheijen wrote:
> When you have time to create the hooks to the various locations within
> dovecot, I am willing to try to make a module to support Maildir
> quota's. Would that be possible with the hooks, and can that be done
> using a plugin as well?

Hmm. You probably want to override mailbox class's (yea, C class :)
expunge, copy and save_*() methods and make them check/update the quota
files.

You can do the above by overriding mail_storage's open_mailbox() method.

Only hook that I'd need to add is the "mail_storage created" where you
can override the open_mailbox().

You probably want to add some own variables to mailbox class (eg.
pointers to original expunge/copy/save* methods). I'm not really sure
how this should be done. A few possibilities:

1) C++ -like class extension. You create:

struct maildir_quota_mailbox {
  struct index_mailbox parent; // mbox/maildir uses index_mailbox
  // your stuff here
};

And then casting mailbox -> maildir_quota_mailbox.

But this has the problem that you can't create more than one module
which extents a class.

2) A common module_data mapping for all modules. You'd call

struct maildir_quota_data *data = map_lookup(mailbox, "maildir quota");

3) Something more object oriented, piping the requests through possibly
multiple classes:

// more easily described in C++:
mailbox = new acl_mailbox(new quota_mailbox(new maildir_mailbox()));

struct quota_mailbox {
  struct mailbox mailbox;
  struct mailbox *next_mailbox;
  // your own stuff
};

quota_mailbox_init(struct mailbox *next) {
  struct quota_mailbox *box = i_new(struct quota_mailbox, 1);

  box->next_mailbox = next;

  // fill in the functions we want to grab
  box->mailbox = quota_mailbox_defaults;

  // whatever functions we left NULL, copy them from "next".
  mailbox_fill_defaults(&box->mailbox, next);
}

int quota_mailbox_expunge(struct mailbox *box) {
  struct quota_mailbox *qbox = (struct quota_mailbox *) mailbox;

  if (!qbox->next->expunge(qbox->next))
    return FALSE;
  return quota_update(qbox);
}

OK. 3) is the best idea :) But it requires a few changes to make it
work.

Actually, I think this is exactly how I want quota and ACLs to be
implemented. No extra interface changes for either one of them.

For quota, you'd want to do something like:

expunge(): nothing special, just update the quota file after expunges

save_next(): Check data istream's size and if it's over quota, fail.

copy(): this is somewhat problematic, if there wasn't the maildir
hardlinks you wouldn't have to touch it at all..




More information about the dovecot mailing list