~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
 */

#include "lib.h"
#include "mail-storage.h"
#include "mail-namespace.h"

#include "sieve-common.h"
#include "sieve-commands.h"
#include "sieve-actions.h"
#include "sieve-code.h"
#include "sieve-actions.h"
#include "sieve-result.h"
#include "sieve-generator.h"

#include "ext-mailbox-common.h"

/*
 * Tagged argument
 */

static bool tag_mailbox_create_validate
	(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
		struct sieve_command *cmd);
static bool tag_mailbox_create_generate
	(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
    struct sieve_command *context);

const struct sieve_argument_def mailbox_create_tag = {
	"create",
	NULL,
	tag_mailbox_create_validate,
	NULL, NULL,
	tag_mailbox_create_generate
};

/*
 * Side effect
 */

static void seff_mailbox_create_print
	(const struct sieve_side_effect *seffect, const struct sieve_action *action,
		const struct sieve_result_print_env *rpenv, bool *keep);
static int seff_mailbox_create_pre_execute
	(const struct sieve_side_effect *seffect, const struct sieve_action *action,
		const struct sieve_action_exec_env *aenv, void **se_context,
		void *tr_context);

const struct sieve_side_effect_def mailbox_create_side_effect = {
	SIEVE_OBJECT("create", &mailbox_create_operand, 0),
	&act_store,
	NULL, NULL, NULL,
	seff_mailbox_create_print,
	seff_mailbox_create_pre_execute,
	NULL, NULL, NULL
};

/*
 * Operand
 */

static const struct sieve_extension_objects ext_side_effects =
	SIEVE_EXT_DEFINE_SIDE_EFFECT(mailbox_create_side_effect);

const struct sieve_operand_def mailbox_create_operand = {
	"create operand",
	&mailbox_extension,
	0,
	&sieve_side_effect_operand_class,
	&ext_side_effects
};

/*
 * Tag validation
 */

static bool tag_mailbox_create_validate
(struct sieve_validator *valdtr ATTR_UNUSED,
	struct sieve_ast_argument **arg, struct sieve_command *cmd ATTR_UNUSED)
{
	*arg = sieve_ast_argument_next(*arg);

	return TRUE;
}

/*
 * Code generation
 */

static bool tag_mailbox_create_generate
(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
	struct sieve_command *context ATTR_UNUSED)
{
	if ( sieve_ast_argument_type(arg) != SAAT_TAG ) {
		return FALSE;
	}

	sieve_opr_side_effect_emit
		(cgenv->sblock, arg->argument->ext, &mailbox_create_side_effect);

	return TRUE;
}

/*
 * Side effect implementation
 */

static void seff_mailbox_create_print
(const struct sieve_side_effect *seffect ATTR_UNUSED,
	const struct sieve_action *action ATTR_UNUSED,
	const struct sieve_result_print_env *rpenv, bool *keep ATTR_UNUSED)
{
	sieve_result_seffect_printf(rpenv, "create mailbox if it does not exist");
}

static int seff_mailbox_create_pre_execute
(const struct sieve_side_effect *seffect ATTR_UNUSED,
	const struct sieve_action *action ATTR_UNUSED,
	const struct sieve_action_exec_env *aenv ATTR_UNUSED,
	void **se_context ATTR_UNUSED, void *tr_context ATTR_UNUSED)
{
	struct act_store_transaction *trans =
		(struct act_store_transaction *) tr_context;
	struct mail_storage **storage = &(aenv->exec_status->last_storage);
	enum mail_error error;

	/* Check whether creation is necessary */
	if ( trans->box == NULL || trans->disabled )
		return SIEVE_EXEC_OK;

	/* Check whether creation has a chance of working */
	switch ( trans->error_code ) {
	case MAIL_ERROR_NONE:
	case MAIL_ERROR_NOTFOUND:
		break;
	case MAIL_ERROR_TEMP:
		return SIEVE_EXEC_TEMP_FAILURE;
	default:
		return SIEVE_EXEC_FAILURE;
	}

	trans->error = NULL;
	trans->error_code = MAIL_ERROR_NONE;

	*storage = mailbox_get_storage(trans->box);

	/* Create mailbox */
	if ( mailbox_create(trans->box, NULL, FALSE) < 0 ) {
		(void)mail_storage_get_last_error(*storage, &error);
		if ( error != MAIL_ERROR_EXISTS ) {
			sieve_act_store_get_storage_error(aenv, trans);
			return ( trans->error_code == MAIL_ERROR_TEMP ?
				SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE );
		}
	}

	/* Subscribe to it if necessary */
	if ( aenv->scriptenv->mailbox_autosubscribe ) {
		(void)mailbox_list_set_subscribed
			(mailbox_get_namespace(trans->box)->list,
			 mailbox_get_name(trans->box), TRUE);
	}

	/* Try opening again */
	if ( mailbox_open(trans->box) < 0 ) {
		/* Failed definitively */
		sieve_act_store_get_storage_error(aenv, trans);
		return ( trans->error_code == MAIL_ERROR_TEMP ?
			SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE );
	}

	return SIEVE_EXEC_OK;
}