virtual-mail.c revision 7631f16156aca373004953fe6b01a7f343fb47e0
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (c) 2008-2011 Dovecot authors, see the included COPYING file */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "lib.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "array.h"
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "index-mail.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "virtual-storage.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt#include "virtual-transaction.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstruct virtual_mail {
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose struct index_mail imail;
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose enum mail_fetch_field wanted_fields;
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose struct mailbox_header_lookup_ctx *wanted_headers;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* currently active mail */
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mail *backend_mail;
d71cd46ede9c57e3947c86c61306a9caddce242cLukas Slebodnik /* all allocated mails */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY_DEFINE(backend_mails, struct mail *);
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* mail is lost if backend_mail doesn't point to correct mail */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int lost:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozekstruct mail *
deeadf40db3a1eec64cf030e54afc4cb8612a8d5Lukas Slebodnikvirtual_mail_alloc(struct mailbox_transaction_context *t,
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik enum mail_fetch_field wanted_fields,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_header_lookup_ctx *wanted_headers)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
f0ea3ed816182fadf77f3e7f7ddb298b287007adLukas Slebodnik struct virtual_mailbox *mbox = (struct virtual_mailbox *)t->box;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct virtual_mail *vmail;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher pool_t pool;
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher pool = pool_alloconly_create("vmail", 1024);
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina vmail = p_new(pool, struct virtual_mail, 1);
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina vmail->imail.mail.pool = pool;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina vmail->imail.mail.v = virtual_mail_vfuncs;
c481179da5d5b53ce16d8784c0bd2857ffc2f061Lukas Slebodnik vmail->imail.mail.mail.box = t->box;
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher vmail->imail.mail.mail.transaction = t;
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik array_create(&vmail->imail.mail.module_contexts, pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sizeof(void *), 5);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->imail.data_pool =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_alloconly_create("virtual index_mail", 512);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->imail.ibox = INDEX_STORAGE_CONTEXT(t->box);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->wanted_fields = wanted_fields;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (wanted_headers != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->wanted_headers = wanted_headers;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_header_lookup_ref(wanted_headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce i_array_init(&vmail->backend_mails, array_count(&mbox->backend_boxes));
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnik return &vmail->imail.mail.mail;
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnik}
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnik
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozekstatic void virtual_mail_free(struct mail *mail)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek{
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce struct mail **mails;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce unsigned int i, count;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mails = array_get_modifiable(&vmail->backend_mails, &count);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek for (i = 0; i < count; i++)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mail_free(&mails[i]);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek array_free(&vmail->backend_mails);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (vmail->wanted_headers != NULL)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mailbox_header_lookup_unref(&vmail->wanted_headers);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek pool_unref(&vmail->imail.data_pool);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek pool_unref(&vmail->imail.mail.pool);
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek}
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozekstatic struct mail *
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozekbackend_mail_find(struct virtual_mail *vmail, struct mailbox *box)
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik{
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik struct mail *const *mails;
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik unsigned int i, count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mails = array_get(&vmail->backend_mails, &count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mails[i]->box == box)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mails[i];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
d921c1eba437662437847279f251a0a5d8f70127Maxim}
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maximstruct mail *
d921c1eba437662437847279f251a0a5d8f70127Maximvirtual_mail_set_backend_mail(struct mail *mail,
d921c1eba437662437847279f251a0a5d8f70127Maxim struct virtual_backend_box *bbox)
d921c1eba437662437847279f251a0a5d8f70127Maxim{
d921c1eba437662437847279f251a0a5d8f70127Maxim struct virtual_mail *vmail = (struct virtual_mail *)mail;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer struct mailbox_transaction_context *backend_trans;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer struct mailbox_header_lookup_ctx *backend_headers;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer backend_trans = virtual_transaction_get(mail->transaction, bbox->box);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer backend_headers = vmail->wanted_headers == NULL ? NULL :
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer mailbox_header_lookup_init(bbox->box,
327127bb7fcc07f882209f029e14026de1b23c94Maxim vmail->wanted_headers->name);
327127bb7fcc07f882209f029e14026de1b23c94Maxim vmail->backend_mail = mail_alloc(backend_trans, vmail->wanted_fields,
327127bb7fcc07f882209f029e14026de1b23c94Maxim backend_headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (backend_headers != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_header_lookup_unref(&backend_headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&vmail->backend_mails, &vmail->backend_mail, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return vmail->backend_mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void virtual_mail_set_seq(struct mail *mail, uint32_t seq, bool saving)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce{
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
07d82f79d2970a08628ebf71343441ec55faa6faPavel Březina struct virtual_backend_box *bbox;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct virtual_mail_index_record *vrec;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const void *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool expunged;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(!saving);
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose mail_index_lookup_ext(mail->box->view, seq, mbox->virtual_ext_id,
03713859dffacc7142393e53c73d8d4cf7dee8d5Pavel Březina &data, &expunged);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik vrec = data;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke bbox = virtual_backend_box_lookup(mbox, vrec->mailbox_id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->backend_mail = backend_mail_find(vmail, bbox->box);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (vmail->backend_mail == NULL)
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek virtual_mail_set_backend_mail(mail, bbox);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher vmail->lost = !mail_set_uid(vmail->backend_mail, vrec->real_uid);
772464c842968d6e544118ae1aa7c49a7cda2ad6Stephen Gallagher memset(&vmail->imail.data, 0, sizeof(vmail->imail.data));
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley p_clear(vmail->imail.data_pool);
068dbee9ca7bf5b37330eff91c94ae10f288d09fJakub Hrozek
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek vmail->imail.data.seq = seq;
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozek mail->seq = seq;
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek mail_index_lookup_uid(mail->box->view, seq, &mail->uid);
f36078af138f052cd9a30360867b0ebd0805af5eJakub Hrozek
34c78b745eb349eef2b0f13ef2b722632aebe619Jan Cholasta if (!vmail->lost) {
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek mail->expunged = vmail->backend_mail->expunged;
e07a94a66985b674c5df11ca466792902164c4e2George McCollister mail->has_nuls = vmail->backend_mail->has_nuls;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek mail->has_no_nuls = vmail->backend_mail->has_no_nuls;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik } else {
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer mail->expunged = TRUE;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer mail->has_nuls = FALSE;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose mail->has_no_nuls = FALSE;
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool virtual_mail_set_uid(struct mail *mail, uint32_t uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!mail_index_lookup_seq(mail->box->view, uid, &seq))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_set_seq(mail, seq, FALSE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void virtual_mail_set_uid_cache_updates(struct mail *mail, bool set)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
a5077712fc8c24e8cad08207b7b5a6603bde6a7cJakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_private *p = (struct mail_private *)vmail->backend_mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p->v.set_uid_cache_updates(vmail->backend_mail, set);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool virtual_mail_prefetch(struct mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct virtual_mail *vmail = (struct virtual_mail *)mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_private *p = (struct mail_private *)vmail->backend_mail;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose return p->v.prefetch(vmail->backend_mail);
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke}
6b0a7c72bb841d6885a620c68bd51d55109b66c7Jakub Hrozek
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnikstatic int virtual_mail_handle_lost(struct virtual_mail *vmail)
0e1dcef53d9d8465ce97d31ad11be4445a6e7eb8Lukas Slebodnik{
c3889e5a101a075defe533d81f5296d5e680f639Lukas Slebodnik if (!vmail->lost)
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina return 0;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek mail_set_expunged(&vmail->imail.mail.mail);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek return -1;
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov}
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březinastatic int
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březinavirtual_mail_get_parts(struct mail *mail, struct message_part **parts_r)
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina{
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher struct virtual_mail *vmail = (struct virtual_mail *)mail;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher if (virtual_mail_handle_lost(vmail) < 0)
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik return -1;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik if (mail_get_parts(vmail->backend_mail, parts_r) < 0) {
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik virtual_box_copy_error(mail->box, vmail->backend_mail->box);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return -1;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik }
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik return 0;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnikstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervirtual_mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r)
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos{
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos struct virtual_mail *vmail = (struct virtual_mail *)mail;
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos int tz;
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos if (timezone_r == NULL)
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos timezone_r = &tz;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek if (virtual_mail_handle_lost(vmail) < 0)
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek return -1;
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher if (mail_get_date(vmail->backend_mail, date_r, timezone_r) < 0) {
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek virtual_box_copy_error(mail->box, vmail->backend_mail->box);
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int virtual_mail_get_received_date(struct mail *mail, time_t *date_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct virtual_mail *vmail = (struct virtual_mail *)mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (virtual_mail_handle_lost(vmail) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek if (mail_get_received_date(vmail->backend_mail, date_r) < 0) {
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek virtual_box_copy_error(mail->box, vmail->backend_mail->box);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozekstatic int virtual_mail_get_save_date(struct mail *mail, time_t *date_r)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek{
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (virtual_mail_handle_lost(vmail) < 0)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_get_save_date(vmail->backend_mail, date_r) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_box_copy_error(mail->box, vmail->backend_mail->box);
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka return -1;
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka }
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozekstatic int virtual_mail_get_virtual_mail_size(struct mail *mail, uoff_t *size_r)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct virtual_mail *vmail = (struct virtual_mail *)mail;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (virtual_mail_handle_lost(vmail) < 0)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (mail_get_virtual_size(vmail->backend_mail, size_r) < 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek virtual_box_copy_error(mail->box, vmail->backend_mail->box);
d9378e64499642e86989158f274372187314d5b2Lukas Slebodnik return -1;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return 0;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek}
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozekstatic int virtual_mail_get_physical_size(struct mail *mail, uoff_t *size_r)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek{
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek if (virtual_mail_handle_lost(vmail) < 0)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_get_physical_size(vmail->backend_mail, size_r) < 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek virtual_box_copy_error(mail->box, vmail->backend_mail->box);
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher return -1;
f5b6f977d4144c28e9c66f3f1c9d634d595d1117Marko Myllynen }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik}
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnikstatic int
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnikvirtual_mail_get_first_header(struct mail *mail, const char *field,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik bool decode_to_utf8, const char **value_r)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik{
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct mail_private *p = (struct mail_private *)vmail->backend_mail;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik return -1;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (p->v.get_first_header(vmail->backend_mail, field,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik decode_to_utf8, value_r) < 0) {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik virtual_box_copy_error(mail->box, vmail->backend_mail->box);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik return -1;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return 0;
dc4c30bae512c0b45ff925d9e998337f8fe97e94Lukas Slebodnik}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikvirtual_mail_get_headers(struct mail *mail, const char *field,
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek bool decode_to_utf8, const char *const **value_r)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik struct mail_private *p = (struct mail_private *)vmail->backend_mail;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (p->v.get_headers(vmail->backend_mail, field,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik decode_to_utf8, value_r) < 0) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik virtual_box_copy_error(mail->box, vmail->backend_mail->box);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnikstatic int
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnikvirtual_mail_get_header_stream(struct mail *mail,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct mailbox_header_lookup_ctx *headers,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct istream **stream_r)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik{
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct mailbox_header_lookup_ctx *backend_headers;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik int ret;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik backend_headers = mailbox_header_lookup_init(vmail->backend_mail->box,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik headers->name);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ret = mail_get_header_stream(vmail->backend_mail, backend_headers,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik stream_r);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik mailbox_header_lookup_unref(&backend_headers);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (ret < 0) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik virtual_box_copy_error(mail->box, vmail->backend_mail->box);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return 0;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikstatic int
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikvirtual_mail_get_stream(struct mail *mail, struct message_size *hdr_size,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik struct message_size *body_size,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik struct istream **stream_r)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov if (virtual_mail_handle_lost(vmail) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_get_stream(vmail->backend_mail, hdr_size, body_size,
3d038d2e0dc7af04ec2f7c85ae325accb39f6237Jakub Hrozek stream_r) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_box_copy_error(mail->box, vmail->backend_mail->box);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozekstatic int
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozekvirtual_mail_get_special(struct mail *mail, enum mail_fetch_field field,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek const char **value_r)
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek{
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek struct virtual_mail *vmail = (struct virtual_mail *)mail;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek struct mailbox *box = vmail->backend_mail->box;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek if (virtual_mail_handle_lost(vmail) < 0)
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek return -1;
e07a94a66985b674c5df11ca466792902164c4e2George McCollister if (mail_get_special(vmail->backend_mail, field, value_r) < 0) {
e07a94a66985b674c5df11ca466792902164c4e2George McCollister virtual_box_copy_error(mail->box, box);
e07a94a66985b674c5df11ca466792902164c4e2George McCollister return -1;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose return 0;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose}
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozekstatic struct mail *virtual_mail_get_real_mail(struct mail *mail)
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct virtual_mail *vmail = (struct virtual_mail *)mail;
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce return mail_get_real_mail(vmail->backend_mail);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce}
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorcestatic void virtual_mail_update_pop3_uidl(struct mail *mail, const char *uidl)
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce{
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce struct virtual_mail *vmail = (struct virtual_mail *)mail;
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce mail_update_pop3_uidl(vmail->backend_mail, uidl);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce}
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorcestatic void virtual_mail_expunge(struct mail *mail)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik{
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik return;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik mail_expunge(vmail->backend_mail);
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik}
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikstatic void virtual_mail_parse(struct mail *mail, bool parse_body)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik{
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik return;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik mail_parse(vmail->backend_mail, parse_body);
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik}
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikstatic void
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnikvirtual_mail_set_cache_corrupted(struct mail *mail, enum mail_fetch_field field)
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik{
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik struct virtual_mail *vmail = (struct virtual_mail *)mail;
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik if (virtual_mail_handle_lost(vmail) < 0)
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik return;
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik mail_set_cache_corrupted(vmail->backend_mail, field);
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik}
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnikstruct mail_vfuncs virtual_mail_vfuncs = {
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik NULL,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik virtual_mail_free,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik virtual_mail_set_seq,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik virtual_mail_set_uid,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik virtual_mail_set_uid_cache_updates,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik virtual_mail_prefetch,
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_get_flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_get_keywords,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_get_keyword_indexes,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_get_modseq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_parts,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_date,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_received_date,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_save_date,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_virtual_mail_size,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_physical_size,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_first_header,
1c7f25390572025baa6783ede14523e22fc73043Lukas Slebodnik virtual_mail_get_headers,
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek virtual_mail_get_header_stream,
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek virtual_mail_get_stream,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher virtual_mail_get_special,
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov virtual_mail_get_real_mail,
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov index_mail_update_flags,
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher index_mail_update_keywords,
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher index_mail_update_modseq,
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek virtual_mail_update_pop3_uidl,
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek virtual_mail_expunge,
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek virtual_mail_parse,
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek virtual_mail_set_cache_corrupted,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher NULL
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher