summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c')
-rw-r--r--pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
new file mode 100644
index 0000000..e0fd33d
--- /dev/null
+++ b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
@@ -0,0 +1,284 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str-sanitize.h"
+#include "mail-storage.h"
+#include "mail-namespace.h"
+
+#include "sieve-common.h"
+#include "sieve-actions.h"
+#include "sieve-extensions.h"
+#include "sieve-commands.h"
+#include "sieve-stringlist.h"
+#include "sieve-code.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-dump.h"
+
+#include "ext-mailbox-common.h"
+
+/*
+ * Mailboxexists command
+ *
+ * Syntax:
+ * mailboxexists <mailbox-names: string-list>
+ */
+
+static bool
+tst_mailboxexists_validate(struct sieve_validator *valdtr,
+ struct sieve_command *tst);
+static bool
+tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv,
+ struct sieve_command *ctx);
+
+const struct sieve_command_def mailboxexists_test = {
+ .identifier = "mailboxexists",
+ .type = SCT_TEST,
+ .positional_args = 1,
+ .subtests = 0,
+ .block_allowed = FALSE,
+ .block_required = FALSE,
+ .validate = tst_mailboxexists_validate,
+ .generate = tst_mailboxexists_generate,
+};
+
+/*
+ * Mailboxexists operation
+ */
+
+static bool
+tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv,
+ sieve_size_t *address);
+static int
+tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv,
+ sieve_size_t *address);
+
+const struct sieve_operation_def mailboxexists_operation = {
+ .mnemonic = "MAILBOXEXISTS",
+ .ext_def = &mailbox_extension,
+ .dump = tst_mailboxexists_operation_dump,
+ .execute = tst_mailboxexists_operation_execute,
+};
+
+/*
+ * Test validation
+ */
+
+struct _validate_context {
+ struct sieve_validator *valdtr;
+ struct sieve_command *tst;
+};
+
+static int
+tst_mailboxexists_mailbox_validate(void *context,
+ struct sieve_ast_argument *arg)
+{
+ struct _validate_context *valctx =
+ (struct _validate_context *)context;
+
+ if (sieve_argument_is_string_literal(arg)) {
+ const char *mailbox = sieve_ast_argument_strc(arg), *error;
+
+ if (!sieve_mailbox_check_name(mailbox, &error)) {
+ sieve_argument_validate_warning(
+ valctx->valdtr, arg, "%s test: "
+ "invalid mailbox name `%s' specified: %s",
+ sieve_command_identifier(valctx->tst),
+ str_sanitize(mailbox, 256), error);
+ }
+ }
+
+ return 1;
+}
+
+static bool
+tst_mailboxexists_validate(struct sieve_validator *valdtr,
+ struct sieve_command *tst)
+{
+ struct sieve_ast_argument *arg = tst->first_positional;
+ struct sieve_ast_argument *aarg;
+ struct _validate_context valctx;
+
+ if (!sieve_validate_positional_argument(
+ valdtr, tst, arg, "mailbox-names", 1, SAAT_STRING_LIST))
+ return FALSE;
+
+ if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE))
+ return FALSE;
+
+ aarg = arg;
+ i_zero(&valctx);
+ valctx.valdtr = valdtr;
+ valctx.tst = tst;
+
+ return (sieve_ast_stringlist_map(
+ &aarg, (void*)&valctx,
+ tst_mailboxexists_mailbox_validate) >= 0);
+}
+
+/*
+ * Test generation
+ */
+
+static bool
+tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv,
+ struct sieve_command *tst)
+{
+ sieve_operation_emit(cgenv->sblock, tst->ext, &mailboxexists_operation);
+
+ /* Generate arguments */
+ return sieve_generate_arguments(cgenv, tst, NULL);
+}
+
+/*
+ * Code dump
+ */
+
+static bool
+tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv,
+ sieve_size_t *address)
+{
+ sieve_code_dumpf(denv, "MAILBOXEXISTS");
+ sieve_code_descend(denv);
+
+ return sieve_opr_stringlist_dump(denv, address, "mailbox-names");
+}
+
+/*
+ * Code execution
+ */
+
+static int
+tst_mailboxexists_test_mailbox(const struct sieve_runtime_env *renv,
+ const char *mailbox, bool trace,
+ bool *all_exist_r)
+{
+ const struct sieve_execute_env *eenv = renv->exec_env;
+ struct mailbox *box;
+ const char *error;
+
+ /* Check validity of mailbox name */
+ if (!sieve_mailbox_check_name(mailbox, &error)) {
+ sieve_runtime_warning(
+ renv, NULL, "mailboxexists test: "
+ "invalid mailbox name `%s' specified: %s",
+ str_sanitize(mailbox, 256), error);
+ *all_exist_r = FALSE;
+ return SIEVE_EXEC_OK;
+ }
+
+ /* Open the box */
+ box = mailbox_alloc_for_user(eenv->scriptenv->user,
+ mailbox,
+ MAILBOX_FLAG_POST_SESSION);
+
+ if (mailbox_open(box) < 0) {
+ if (trace) {
+ sieve_runtime_trace(
+ renv, 0,
+ "mailbox `%s' cannot be opened",
+ str_sanitize(mailbox, 80));
+ }
+ mailbox_free(&box);
+ *all_exist_r = FALSE;
+ return SIEVE_EXEC_OK;
+ }
+
+ /* Also fail when it is readonly */
+ if (mailbox_is_readonly(box)) {
+ if (trace) {
+ sieve_runtime_trace(
+ renv, 0,
+ "mailbox `%s' is read-only",
+ str_sanitize(mailbox, 80));
+ }
+ mailbox_free(&box);
+ *all_exist_r = FALSE;
+ return SIEVE_EXEC_OK;
+ }
+
+ /* FIXME: check acl for 'p' or 'i' ACL permissions as
+ required by RFC */
+
+ if (trace) {
+ sieve_runtime_trace(
+ renv, 0, "mailbox `%s' exists",
+ str_sanitize(mailbox, 80));
+ }
+
+ /* Close mailbox */
+ mailbox_free(&box);
+ return SIEVE_EXEC_OK;
+}
+
+static int
+tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv,
+ sieve_size_t *address)
+{
+ const struct sieve_execute_env *eenv = renv->exec_env;
+ struct sieve_stringlist *mailbox_names;
+ string_t *mailbox_item;
+ bool trace = FALSE;
+ bool all_exist = TRUE;
+ int ret;
+
+ /*
+ * Read operands
+ */
+
+ /* Read notify uris */
+ ret = sieve_opr_stringlist_read(renv, address, "mailbox-names",
+ &mailbox_names);
+ if (ret <= 0)
+ return ret;
+
+ /*
+ * Perform operation
+ */
+
+ if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) {
+ sieve_runtime_trace(renv, 0, "mailboxexists test");
+ sieve_runtime_trace_descend(renv);
+
+ trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
+ }
+
+ if (eenv->scriptenv->user == NULL) {
+ sieve_runtime_trace(renv, 0, "no mail user; yield true");
+ sieve_interpreter_set_test_result(renv->interp, TRUE);
+ return SIEVE_EXEC_OK;
+ }
+
+ mailbox_item = NULL;
+ while (all_exist &&
+ (ret = sieve_stringlist_next_item(mailbox_names,
+ &mailbox_item)) > 0) {
+ const char *mailbox = str_c(mailbox_item);
+
+ ret = tst_mailboxexists_test_mailbox(renv, mailbox,
+ trace, &all_exist);
+ if (ret <= 0)
+ return ret;
+ }
+
+ if (ret < 0) {
+ sieve_runtime_trace_error(
+ renv, "invalid mailbox name item");
+ return SIEVE_EXEC_BIN_CORRUPT;
+ }
+
+ if (trace) {
+ if (all_exist) {
+ sieve_runtime_trace(renv, 0,
+ "all mailboxes are available");
+ } else {
+ sieve_runtime_trace(renv, 0,
+ "some mailboxes are unavailable");
+ }
+ }
+
+ sieve_interpreter_set_test_result(renv->interp, all_exist);
+ return SIEVE_EXEC_OK;
+}