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:
- 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.
- A common module_data mapping for all modules. You'd call
struct maildir_quota_data *data = map_lookup(mailbox, "maildir quota");
- 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..