/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "hash.h"
#include "seq-range-array.h"
#include "mkdir-parents.h"
#include "mail-storage-private.h"
#include "mail-search-build.h"
#include "mailbox-list-private.h"
#include "mail-namespace.h"
#include "lazy-expunge-plugin.h"
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
struct lazy_expunge_mail {
bool moving;
bool recursing;
};
struct lazy_expunge_mail_user {
const char *lazy_mailbox_vname;
const char *env;
bool copy_only_last_instance;
};
struct lazy_expunge_mailbox_list {
};
struct lazy_expunge_transaction {
char *delayed_errstr;
char *delayed_internal_errstr;
bool copy_only_last_instance;
};
static const char *
{
const char *name;
return luser->lazy_mailbox_vname;
/* use the (canonical / unaliased) storage name */
/* replace hierarchy separators with destination virtual separator */
unsigned int i;
for (i = 0; name[i] != '\0'; i++) {
else
}
}
/* add expunge namespace prefix. the name is now a proper vname */
}
static struct mailbox *
const char **error_r)
{
const char *name;
if (mailbox_open(box) == 0) {
return box;
}
if (error != MAIL_ERROR_NOTFOUND) {
mailbox_free(&box);
return NULL;
}
/* try creating and re-opening it. */
mailbox_free(&box);
return NULL;
}
if (mailbox_open(box) < 0) {
mailbox_free(&box);
return NULL;
}
return box;
}
static unsigned int
const char *guid)
{
void *refcountp;
unsigned int refcount;
1024);
}
if (refcount == 1) {
} else {
}
return refcount-1;
}
{
unsigned long refcount;
if (error == MAIL_ERROR_EXPUNGED) {
/* already expunged - just ignore it */
return 0;
}
"lazy_expunge: Couldn't lookup message's refcount: %s",
errstr);
return -1;
}
if (*value == '\0') {
/* refcounts not supported by backend. assume all mails are
the last instance. */
return 1;
}
if (refcount > 1) {
/* this probably isn't the last instance of the mail, but
it's possible that the same mail was copied to this mailbox
multiple times and we're deleting more than one instance
within this transaction. in those cases each expunge will
see the same refcount, so we need to adjust the refcount
by tracking the expunged message GUIDs. */
if (error == MAIL_ERROR_EXPUNGED) {
/* already expunged - just ignore it */
return 0;
}
"lazy_expunge: Couldn't lookup message's GUID: %s", errstr);
return -1;
}
if (*value == '\0') {
/* GUIDs not supported by backend, but refcounts are?
not with our current backends. */
"lazy_expunge: Message unexpectedly has no GUID");
return -1;
}
}
}
{
/* lazy_expunge not enabled at all */
return FALSE;
}
if (llist->internal_namespace) {
/* lazy-expunge namespace */
return TRUE;
}
/* lazy-expunge mailbox */
return TRUE;
}
return FALSE;
}
struct mail_storage *storage)
{
const char *errstr;
if (error == MAIL_ERROR_EXPUNGED) {
/* expunging failed because the mail was already expunged.
we don't want to fail because of that. */
return;
}
return;
}
{
const char *error;
int ret;
return;
return;
}
/* Clear this in case the mail is used for non-move later on. */
/* don't copy the mail if we're expunging from lazy_expunge
namespace (even if it's via a virtual mailbox) */
return;
}
return;
}
if (lt->copy_only_last_instance) {
/* we want to copy only the last instance of the mail to
lazy_expunge namespace. other instances will be expunged
immediately. */
if (moving)
ret = 0;
return;
}
if (ret == 0) {
return;
}
}
"lazy_expunge: Couldn't open expunge mailbox: "
"%s", error);
return;
}
"lazy_expunge: Couldn't sync expunge mailbox");
return;
}
__func__);
}
}
{
}
static struct mailbox_transaction_context *
const char *reason)
{
struct mailbox_transaction_context *t;
return t;
}
{
}
static int
struct mail_transaction_commit_changes *changes_r)
{
int ret;
}
}
lt->delayed_errstr);
ret = -1;
} else {
"Lazy-expunge transaction failed: %s",
ret = -1;
}
return ret;
}
static void
{
}
{
return;
}
static int
{
if (!src_llist->allow_rename &&
return -1;
}
}
{
return;
if (!lazy_expunge_is_internal_mailbox(box)) {
v->copy = lazy_expunge_copy;
} else if (llist->internal_namespace) {
} else {
/* internal mailbox in a non-internal namespace -
don't add any unnecessary restrictions to it. if it's not
wanted, just use the ACL plugin. */
}
}
{
return;
/* if this is one of our internal namespaces, mark it as such before
quota plugin sees it */
llist);
}
}
static void
{
return;
/* we don't want to override this namespace's expunge operation. */
} else {
/* store the the expunged mails to the specified mailbox. */
}
}
{
/* mail_namespaces_created hook isn't necessarily ever called */
}
{
const char *env;
} else if (user->mail_debug) {
i_debug("lazy_expunge: No lazy_expunge setting - "
"plugin disabled");
}
}
};
{
}
void lazy_expunge_plugin_deinit(void)
{
}