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 177 178 179 180 181 182 183 184 185 186 187
|
/* Copyright (c) 2002-2017 Pigeonhole authors, see the included COPYING file
*/
#include "lib.h"
#include "istream.h"
#include "doveadm-mail.h"
#include "sieve.h"
#include "sieve-script.h"
#include "sieve-storage.h"
#include "doveadm-sieve-cmd.h"
struct doveadm_sieve_put_cmd_context {
struct doveadm_sieve_cmd_context ctx;
const char *scriptname;
unsigned int activate:1;
};
static int cmd_sieve_put_run
(struct doveadm_sieve_cmd_context *_ctx)
{
struct doveadm_sieve_put_cmd_context *ctx =
(struct doveadm_sieve_put_cmd_context *)_ctx;
struct sieve_storage_save_context *save_ctx;
struct sieve_storage *storage = _ctx->storage;
struct istream *input = _ctx->ctx.cmd_input;
enum sieve_error error;
ssize_t ret;
bool save_failed = FALSE;
save_ctx = sieve_storage_save_init
(storage, ctx->scriptname, input);
if ( save_ctx == NULL ) {
i_error("Saving failed: %s",
sieve_storage_get_last_error(storage, &error));
doveadm_sieve_cmd_failed_error(_ctx, error);
return -1;
}
while ( (ret = i_stream_read(input)) > 0 || ret == -2 ) {
if ( sieve_storage_save_continue(save_ctx) < 0 ) {
save_failed = TRUE;
ret = -1;
break;
}
}
i_assert(ret == -1);
if ( input->stream_errno != 0 ) {
i_error("read(script input) failed: %s", i_stream_get_error(input));
doveadm_sieve_cmd_failed_error
(&ctx->ctx, SIEVE_ERROR_TEMP_FAILURE);
} else if ( save_failed ) {
i_error("Saving failed: %s",
sieve_storage_get_last_error(storage, NULL));
doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage);
} else if ( sieve_storage_save_finish(save_ctx) < 0 ) {
i_error("Saving failed: %s",
sieve_storage_get_last_error(storage, NULL));
doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage);
} else {
ret = 0;
}
/* Verify that script compiles */
if ( ret == 0 ) {
struct sieve_error_handler *ehandler;
enum sieve_compile_flags cpflags =
SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED;
struct sieve_script *script;
struct sieve_binary *sbin;
/* Obtain script object for uploaded script */
script = sieve_storage_save_get_tempscript(save_ctx);
/* Check result */
if ( script == NULL ) {
i_error("Saving failed: %s",
sieve_storage_get_last_error(storage, &error));
doveadm_sieve_cmd_failed_error(_ctx, error);
ret = -1;
} else {
/* Mark this as an activation when we are replacing the active script */
if ( ctx->activate || sieve_storage_save_will_activate(save_ctx) )
cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED;
/* Compile */
ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, NULL, 0);
if ( (sbin=sieve_compile_script
(script, ehandler, cpflags, &error)) == NULL ) {
doveadm_sieve_cmd_failed_error(_ctx, error);
ret = -1;
} else {
sieve_close(&sbin);
/* Script is valid; commit it to storage */
ret = sieve_storage_save_commit(&save_ctx);
if (ret < 0) {
i_error("Saving failed: %s",
sieve_storage_get_last_error(storage, &error));
doveadm_sieve_cmd_failed_error(_ctx, error);
ret = -1;
}
}
sieve_error_handler_unref(&ehandler);
}
}
if ( save_ctx != NULL )
sieve_storage_save_cancel(&save_ctx);
if ( ctx->activate && ret == 0 ) {
struct sieve_script *script = sieve_storage_open_script
(storage, ctx->scriptname, NULL);
if ( script == NULL ||
sieve_script_activate(script, (time_t)-1) < 0) {
i_error("Failed to activate Sieve script: %s",
sieve_storage_get_last_error(storage, &error));
doveadm_sieve_cmd_failed_error(_ctx, error);
ret = -1;
}
}
i_assert(input->eof);
return ret < 0 ? -1 : 0;
}
static void cmd_sieve_put_init
(struct doveadm_mail_cmd_context *_ctx,
const char *const args[])
{
struct doveadm_sieve_put_cmd_context *ctx =
(struct doveadm_sieve_put_cmd_context *)_ctx;
if ( str_array_length(args) != 1 )
doveadm_mail_help_name("sieve put");
doveadm_sieve_cmd_scriptnames_check(args);
ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]);
doveadm_mail_get_input(_ctx);
}
static bool
cmd_sieve_put_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
{
struct doveadm_sieve_put_cmd_context *ctx =
(struct doveadm_sieve_put_cmd_context *)_ctx;
switch ( c ) {
case 'a':
ctx->activate = TRUE;
break;
default:
return FALSE;
}
return TRUE;
}
static struct doveadm_mail_cmd_context *
cmd_sieve_put_alloc(void)
{
struct doveadm_sieve_put_cmd_context *ctx;
ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_put_cmd_context);
ctx->ctx.ctx.getopt_args = "a";
ctx->ctx.ctx.v.parse_arg = cmd_sieve_put_parse_arg;
ctx->ctx.ctx.v.init = cmd_sieve_put_init;
ctx->ctx.v.run = cmd_sieve_put_run;
return &ctx->ctx.ctx;
}
struct doveadm_cmd_ver2 doveadm_sieve_cmd_put = {
.name = "sieve put",
.mail_cmd = cmd_sieve_put_alloc,
.usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-a] <scriptname>",
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_MAIL_COMMON
DOVEADM_CMD_PARAM('a',"activate",CMD_PARAM_BOOL,0)
DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAM('\0',"file",CMD_PARAM_ISTREAM,CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAMS_END
};
|