static void fts_solr_set_default_ns(struct solr_fts_backend *backend)
{
	struct mail_namespace *ns = backend->backend.ns;
	struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(ns->user);
	const struct fts_solr_settings *set = &fuser->set;
	const char *str;

	if (backend->default_ns != NULL)
		return;

	if (set->default_ns_prefix != NULL) {
		backend->default_ns =
			mail_namespace_find_prefix(ns->user->namespaces,
						   set->default_ns_prefix);
		if (backend->default_ns == NULL) {
			i_error("fts_solr: default_ns setting points to "
				"nonexistent namespace");
		}
	}
	if (backend->default_ns == NULL) {
		backend->default_ns =
			mail_namespace_find_inbox(ns->user->namespaces);
	}
	while (backend->default_ns->alias_for != NULL)
		backend->default_ns = backend->default_ns->alias_for;

	if (ns != backend->default_ns) {
		str = solr_escape_id_str(ns->prefix);
		backend->id_namespace = i_strdup(str);
	}
}
Example #2
0
static int
lmtp_rcpt_to_is_over_quota(struct client *client,
			   const struct mail_recipient *rcpt)
{
	struct mail_user *user;
	struct mail_namespace *ns;
	struct mailbox *box;
	struct mailbox_status status;
	const char *errstr;
	enum mail_error error;
	int ret;

	if (!client->lmtp_set->lmtp_rcpt_check_quota)
		return 0;

	ret = mail_storage_service_next(storage_service,
					rcpt->service_user, &user);
	if (ret < 0)
		return -1;

	ns = mail_namespace_find_inbox(user->namespaces);
	box = mailbox_alloc(ns->list, "INBOX", 0);
	ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status);
	if (ret < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error == MAIL_ERROR_NOSPACE) {
			client_send_line(client, "552 5.2.2 <%s> %s",
					 rcpt->address, errstr);
			ret = 1;
		}
	}
	mailbox_free(&box);
	mail_user_unref(&user);
	return ret;
}
Example #3
0
static struct mail_namespace *
mail_user_find_attribute_namespace(struct mail_user *user)
{
	struct mail_namespace *ns;

	ns = mail_namespace_find_inbox(user->namespaces);
	if (ns != NULL)
		return ns;

	for (ns = user->namespaces; ns != NULL; ns = ns->next) {
		if (ns->type == MAIL_NAMESPACE_TYPE_PRIVATE)
			return ns;
	}
	return NULL;
}
static int
cmd_mailbox_metadata_open_mailbox(struct metadata_cmd_context *mctx,
				  struct mail_user *user,
				  const char *op,
				  struct mail_namespace **ns_r,
				  struct mailbox **box_r)
{
	mctx->empty_mailbox_name = mctx->mailbox[0] == '\0';

	if (mctx->empty_mailbox_name) {
		if (!mctx->ctx.allow_empty_mailbox_name) {
			i_error("Failed to %s: %s", op,
				"mailbox name cannot be empty");
			mctx->ctx.exit_code = EX_USAGE;
			return -1;
		}

		/* server attribute */
		*ns_r = mail_namespace_find_inbox(user->namespaces);
		*box_r = mailbox_alloc((*ns_r)->list, "INBOX", 0);

		mctx->key = t_strconcat(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER,
					mctx->key, NULL);
	} else {
		/* mailbox attributes */
		*ns_r = mail_namespace_find(user->namespaces, mctx->mailbox);
		*box_r = mailbox_alloc((*ns_r)->list, mctx->mailbox, 0);
	}

	if (mailbox_open(*box_r) < 0) {
		i_error("Failed to open mailbox: %s",
			mailbox_get_last_error(*box_r, NULL));
		doveadm_mail_failed_mailbox(&mctx->ctx, *box_r);
		mailbox_free(box_r);
		return -1;
	}

	return 0;
}
static int
fts_namespace_find(struct mail_user *user, const char *ns_prefix,
		   struct mail_namespace **ns_r)
{
	struct mail_namespace *ns;

	if (ns_prefix == NULL)
		ns = mail_namespace_find_inbox(user->namespaces);
	else {
		ns = mail_namespace_find_prefix(user->namespaces, ns_prefix);
		if (ns == NULL) {
			i_error("Namespace prefix not found: %s", ns_prefix);
			return -1;
		}
	}

	if (fts_list_backend(ns->list) == NULL) {
		i_error("fts not enabled for user's namespace %s", ns_prefix);
		return -1;
	}
	*ns_r = ns;
	return 0;
}
Example #6
0
struct mail_namespace *
client_find_namespace_full(struct client *client,
			   const char **mailbox, const char **error_r)
{
	struct mail_namespace *namespaces = client->user->namespaces;
	struct mail_namespace *ns;
	string_t *utf8_name;

	utf8_name = t_str_new(64);
	if (imap_utf7_to_utf8(*mailbox, utf8_name) < 0) {
		*error_r = "NO Mailbox name is not valid mUTF-7";
		return NULL;
	}

	ns = mail_namespace_find(namespaces, str_c(utf8_name));
	if ((ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 &&
	    ns->prefix_len == 0) {
		/* this matched only the autocreated prefix="" namespace.
		   give a nice human-readable error message */
		*error_r = t_strdup_printf(
			"NO Client tried to access nonexistent namespace. "
			"(Mailbox name should probably be prefixed with: %s)",
			mail_namespace_find_inbox(namespaces)->prefix);
		return NULL;
	}

	if ((client->set->parsed_workarounds &
	     		WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
	    str_len(utf8_name) > 0 &&
	    str_c(utf8_name)[str_len(utf8_name)-1] == mail_namespace_get_sep(ns)) {
		/* drop the extra trailing hierarchy separator */
		str_truncate(utf8_name, str_len(utf8_name)-1);
	}

	*mailbox = str_c(utf8_name);
	return ns;
}
Example #7
0
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                          const char **error_r)
{
    struct mail_user *user = ctx->mbox->storage->storage.user;
    struct virtual_backend_box *bbox;
    const char *p;
    bool no_wildcards = FALSE;

    if (*line == ' ' || *line == '\t') {
        /* continues the previous search rule */
        if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
            *error_r = "Search rule without a mailbox";
            return -1;
        }
        while (*line == ' ' || *line == '\t') line++;
        str_append_c(ctx->rule, ' ');
        str_append(ctx->rule, line);
        return 0;
    }
    /* if there is no rule yet, it means we want the previous mailboxes
       to use the rule that comes later */
    if (str_len(ctx->rule) > 0) {
        if (virtual_config_add_rule(ctx, error_r) < 0)
            return -1;
    }
    if (!uni_utf8_str_is_valid(line)) {
        *error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
                                   line);
        return -1;
    }

    /* new mailbox. the search args are added to it later. */
    bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
    bbox->virtual_mbox = ctx->mbox;
    if (strcasecmp(line, "INBOX") == 0)
        line = "INBOX";
    bbox->name = p_strdup(ctx->pool, line);
    switch (bbox->name[0]) {
    case '+':
        bbox->name++;
        bbox->clear_recent = TRUE;
        break;
    case '-':
        bbox->name++;
        bbox->negative_match = TRUE;
        break;
    case '!':
        /* save messages here */
        if (ctx->mbox->save_bbox != NULL) {
            *error_r = "Multiple save mailboxes defined";
            return -1;
        }
        bbox->name++;
        ctx->mbox->save_bbox = bbox;
        no_wildcards = TRUE;
        break;
    }
    if (bbox->name[0] == '/') {
        /* [+-!]/metadata entry:value */
        if ((p = strchr(bbox->name, ':')) == NULL) {
            *error_r = "':' separator missing between metadata entry name and value";
            return -1;
        }
        bbox->metadata_entry = p_strdup_until(ctx->pool, bbox->name, p++);
        bbox->metadata_value = p;
        if (!imap_metadata_verify_entry_name(bbox->metadata_entry, error_r))
            return -1;
        no_wildcards = TRUE;
    }

    if (!no_wildcards &&
            (strchr(bbox->name, '*') != NULL ||
             strchr(bbox->name, '%') != NULL)) {
        bbox->glob = imap_match_init(ctx->pool, bbox->name, TRUE, ctx->sep);
        ctx->have_wildcards = TRUE;
    }
    if (bbox->metadata_entry == NULL) {
        /* now that the prefix characters have been processed,
           find the namespace */
        bbox->ns = strcasecmp(bbox->name, "INBOX") == 0 ?
                   mail_namespace_find_inbox(user->namespaces) :
                   mail_namespace_find(user->namespaces, bbox->name);
        if (bbox->ns == NULL) {
            *error_r = t_strdup_printf("Namespace not found for %s",
                                       bbox->name);
            return -1;
        }
        if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) {
            *error_r = "Virtual mailbox can't point to itself";
            return -1;
        }
        ctx->have_mailbox_defines = TRUE;
    }

    array_append(&ctx->mbox->backend_boxes, &bbox, 1);
    return 0;
}
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
			  const char **error_r)
{
	struct mail_user *user = ctx->mbox->storage->storage.user;
	struct virtual_backend_box *bbox;
	const char *name;

	if (*line == ' ' || *line == '\t') {
		/* continues the previous search rule */
		if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
			*error_r = "Search rule without a mailbox";
			return -1;
		}
		while (*line == ' ' || *line == '\t') line++;
		str_append_c(ctx->rule, ' ');
		str_append(ctx->rule, line);
		return 0;
	}
	/* if there is no rule yet, it means we want the previous mailboxes
	   to use the rule that comes later */
	if (str_len(ctx->rule) > 0) {
		if (virtual_config_add_rule(ctx, error_r) < 0)
			return -1;
	}

	/* new mailbox. the search args are added to it later. */
	bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
	if (strcasecmp(line, "INBOX") == 0)
		line = "INBOX";
	bbox->name = p_strdup(ctx->pool, line);
	if (*line == '-' || *line == '+' || *line == '!') line++;
	bbox->ns = strcasecmp(line, "INBOX") == 0 ?
		mail_namespace_find_inbox(user->namespaces) :
		mail_namespace_find(user->namespaces, line);
	if (!uni_utf8_str_is_valid(bbox->name)) {
		*error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
					   bbox->name);
		return -1;
	}
	if (bbox->ns == NULL) {
		*error_r = t_strdup_printf("Namespace not found for %s",
					   bbox->name);
		return -1;
	}
	if (bbox->name[0] == '+') {
		bbox->name++;
		bbox->clear_recent = TRUE;
	}

	if (strchr(bbox->name, '*') != NULL ||
	    strchr(bbox->name, '%') != NULL) {
		name = bbox->name[0] == '-' ? bbox->name + 1 : bbox->name;
		bbox->glob = imap_match_init(ctx->pool, name, TRUE, ctx->sep);
		ctx->have_wildcards = TRUE;
	} else if (bbox->name[0] == '!') {
		/* save messages here */
		if (ctx->mbox->save_bbox != NULL) {
			*error_r = "Multiple save mailboxes defined";
			return -1;
		}
		bbox->name++;
		ctx->mbox->save_bbox = bbox;
	}
	ctx->have_mailbox_defines = TRUE;
	array_append(&ctx->mbox->backend_boxes, &bbox, 1);
	return 0;
}
bool cmd_setmetadata(struct client_command_context *cmd)
{
	struct imap_setmetadata_context *ctx;
	const struct imap_arg *args;
	const char *mailbox;
	struct mail_namespace *ns;
	int ret;

	ret = imap_parser_read_args(cmd->parser, 2,
				    IMAP_PARSE_FLAG_STOP_AT_LIST, &args);
	if (ret == -1) {
		client_send_command_error(cmd, NULL);
		return TRUE;
	}
	if (ret == -2)
		return FALSE;
	if (!imap_arg_get_astring(&args[0], &mailbox) ||
	    args[1].type != IMAP_ARG_LIST) {
		client_send_command_error(cmd, "Invalid arguments.");
		return TRUE;
	}

	if (!cmd->client->imap_metadata_enabled) {
		client_send_command_error(cmd, "METADATA disabled.");
		return TRUE;
	}

	ctx = p_new(cmd->pool, struct imap_setmetadata_context, 1);
	ctx->cmd = cmd;
	ctx->cmd->context = ctx;

	if (mailbox[0] == '\0') {
		/* server attribute */
		ctx->key_prefix = MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER;
		ns = mail_namespace_find_inbox(cmd->client->user->namespaces);
		mailbox = "INBOX";
	} else {
		ns = client_find_namespace(cmd, &mailbox);
		if (ns == NULL)
			return TRUE;
	}

	if (cmd->client->mailbox != NULL && !cmd->client->mailbox_examined &&
	    mailbox_equals(cmd->client->mailbox, ns, mailbox))
		ctx->box = cmd->client->mailbox;
	else {
		ctx->box = mailbox_alloc(ns->list, mailbox, 0);
		if (mailbox_open(ctx->box) < 0) {
			client_send_box_error(cmd, ctx->box);
			mailbox_free(&ctx->box);
			return TRUE;
		}
	}
	ctx->trans = mailbox_transaction_begin(ctx->box, 0);
	/* we support large literals, so read the values from client
	   asynchronously the same way as APPEND does. */
	cmd->client->input_lock = cmd;
	ctx->parser = imap_parser_create(cmd->client->input, cmd->client->output,
					 cmd->client->set->imap_max_line_length);
	o_stream_unset_flush_callback(cmd->client->output);

	cmd->func = cmd_setmetadata_continue;
	cmd->context = ctx;
	return cmd_setmetadata_continue(cmd);
}