const char *ext_enotify_runtime_get_method_capability (const struct sieve_runtime_env *renv, string_t *method_uri, const char *capability) { const struct sieve_enotify_method *method; const char *uri_body; const char *result = NULL; /* Get method */ method = ext_enotify_get_method(renv, method_uri, &uri_body); if ( method == NULL ) return NULL; /* Get requested capability */ if ( method->def != NULL && method->def->runtime_get_method_capability != NULL ) { struct sieve_enotify_env nenv; memset(&nenv, 0, sizeof(nenv)); nenv.svinst = renv->svinst; nenv.method = method; nenv.ehandler = sieve_prefix_ehandler_create (renv->ehandler, sieve_runtime_get_full_command_location(renv), "notify_method_capability test"); /* Execute method function to acquire capability value */ result = method->def->runtime_get_method_capability (&nenv, str_c(method_uri), uri_body, capability); sieve_error_handler_unref(&nenv.ehandler); } return result; }
bool cmd_setactive(struct client_command_context *cmd) { struct client *client = cmd->client; struct sieve_storage *storage = client->storage; const char *scriptname; struct sieve_script *script; int ret; /* <scriptname> */ if ( !client_read_string_args(cmd, TRUE, 1, &scriptname) ) return FALSE; /* Activate, or .. */ if ( *scriptname != '\0' ) { string_t *errors = NULL; const char *errormsg = NULL; bool warnings = FALSE; bool success = TRUE; script = sieve_storage_open_script (storage, scriptname, NULL); if ( script == NULL ) { client_send_storage_error(client, storage); return TRUE; } if ( sieve_script_is_active(script) <= 0 ) { /* Script is first being activated; compile it again without the UPLOAD * flag. */ T_BEGIN { struct sieve_error_handler *ehandler; enum sieve_compile_flags cpflags = SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED; struct sieve_binary *sbin; enum sieve_error error; /* Prepare error handler */ errors = str_new(default_pool, 1024); ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE, client->set->managesieve_max_compile_errors); /* Compile */ if ( (sbin=sieve_compile_script (script, ehandler, cpflags, &error)) == NULL ) { if (error != SIEVE_ERROR_NOT_VALID) { errormsg = sieve_script_get_last_error(script, &error); if ( error == SIEVE_ERROR_NONE ) errormsg = NULL; } success = FALSE; } else { sieve_close(&sbin); } warnings = ( sieve_get_warnings(ehandler) > 0 ); sieve_error_handler_unref(&ehandler); } T_END; }
static int cmd_sieve_activate_run(struct doveadm_sieve_cmd_context *_ctx) { struct doveadm_sieve_activate_cmd_context *ctx = (struct doveadm_sieve_activate_cmd_context *)_ctx; struct sieve_storage *storage = _ctx->storage; struct sieve_script *script; enum sieve_error error; int ret = 0; script = sieve_storage_open_script (storage, ctx->scriptname, NULL); if ( script == NULL ) { i_error("Failed to activate Sieve script: %s", sieve_storage_get_last_error(storage, &error)); doveadm_sieve_cmd_failed_error(_ctx, error); return -1; } if ( sieve_script_is_active(script) <= 0 ) { /* Script is first being activated; compile it again without the UPLOAD * flag. */ struct sieve_error_handler *ehandler; enum sieve_compile_flags cpflags = SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED; struct sieve_binary *sbin; enum sieve_error error; /* 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); } sieve_error_handler_unref(&ehandler); } /* Activate only when script is valid (or already active) */ if ( ret == 0 ) { /* Refresh activation no matter what; this can also resolve some erroneous * situations. */ ret = sieve_script_activate(script, (time_t)-1); if ( ret < 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; } } sieve_script_unref(&script); return ret; }
struct sieve_binary *sieve_tool_script_open (struct sieve_instance *svinst, const char *filename) { struct sieve_error_handler *ehandler; struct sieve_binary *sbin; ehandler = sieve_stderr_ehandler_create(svinst, 0); sieve_error_handler_accept_infolog(ehandler, TRUE); if ( (sbin = sieve_open (svinst, filename, NULL, ehandler, 0, NULL)) == NULL ) { sieve_error_handler_unref(&ehandler); i_fatal("failed to compile sieve script"); } sieve_error_handler_unref(&ehandler); sieve_save(sbin, FALSE, NULL); return sbin; }
static int _ext_enotify_option_check (void *context, struct sieve_ast_argument *arg) { struct _ext_enotify_option_check_context *optn_context = (struct _ext_enotify_option_check_context *) context; struct sieve_validator *valdtr = optn_context->valdtr; const struct sieve_enotify_method *method = optn_context->method; struct sieve_enotify_env nenv; const char *option = sieve_ast_argument_strc(arg); const char *opt_name = NULL, *opt_value = NULL; bool check = TRUE; int result = 1; /* Compose log structure */ memset(&nenv, 0, sizeof(nenv)); nenv.svinst = optn_context->svinst; nenv.method = method; nenv.ehandler = sieve_prefix_ehandler_create (sieve_validator_error_handler(valdtr), sieve_error_script_location (sieve_validator_script(valdtr), arg->source_line), "notify command"); /* Parse option */ if ( !sieve_argument_is_string_literal(arg) ) { /* Variable string: partial option parse * * If the string item is not a string literal, it cannot be validated fully * at compile time. We can however check whether the '=' is in the string * specification and whether the part before the '=' is a valid option name. * In that case, the method option check function is called with the value * parameter equal to NULL, meaning that it should only check the validity * of the option itself and not the assigned value. */ if ( !ext_enotify_option_parse(NULL, option, TRUE, &opt_name, &opt_value) ) check = FALSE; } else { /* Literal string: full option parse */ if ( !ext_enotify_option_parse (&nenv, option, FALSE, &opt_name, &opt_value) ) result = -1; } /* Call method's option check function */ if ( result > 0 && check && method->def != NULL && method->def->compile_check_option != NULL ) { result = ( method->def->compile_check_option (&nenv, opt_name, opt_value) ? 1 : -1 ); } sieve_error_handler_unref(&nenv.ehandler); return result; }
void sieve_generator_free(struct sieve_generator **gentr) { sieve_ast_unref(&(*gentr)->genenv.ast); sieve_error_handler_unref(&(*gentr)->ehandler); sieve_binary_debug_writer_deinit(&(*gentr)->dwriter); if ( (*gentr)->genenv.sbin != NULL ) sieve_binary_unref(&(*gentr)->genenv.sbin); pool_unref(&((*gentr)->pool)); *gentr = NULL; }
void imap_sieve_deinit(struct imap_sieve **_isieve) { struct imap_sieve *isieve = *_isieve; *_isieve = NULL; sieve_error_handler_unref(&isieve->master_ehandler); if (isieve->storage != NULL) sieve_storage_unref(&isieve->storage); sieve_extension_unregister(isieve->ext_imapsieve); sieve_deinit(&isieve->svinst); duplicate_deinit(&isieve->dup_ctx); pool_unref(&isieve->pool); }
struct sieve_binary *sieve_tool_script_compile (struct sieve_instance *svinst, const char *filename, const char *name) { struct sieve_error_handler *ehandler; struct sieve_binary *sbin; ehandler = sieve_stderr_ehandler_create(svinst, 0); sieve_error_handler_accept_infolog(ehandler, TRUE); sieve_error_handler_accept_debuglog(ehandler, svinst->debug); if ( (sbin = sieve_compile (svinst, filename, name, ehandler, 0, NULL)) == NULL ) i_error("failed to compile sieve script '%s'", filename); sieve_error_handler_unref(&ehandler); return sbin; }
bool ext_enotify_runtime_method_validate (const struct sieve_runtime_env *renv, string_t *method_uri) { const struct sieve_extension *this_ext = renv->oprtn->ext; const struct sieve_enotify_method *method; const char *uri = str_c(method_uri); const char *scheme; bool result = TRUE; /* Get the method */ if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) return FALSE; if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) return FALSE; /* Validate the provided URI */ if ( method->def != NULL && method->def->runtime_check_uri != NULL ) { struct sieve_enotify_env nenv; memset(&nenv, 0, sizeof(nenv)); nenv.svinst = renv->svinst; nenv.method = method; nenv.ehandler = sieve_prefix_ehandler_create (renv->ehandler, sieve_runtime_get_full_command_location(renv), "valid_notify_method test"); /* Use the method check function to validate the URI */ result = method->def->runtime_check_uri(&nenv, str_c(method_uri), uri); sieve_error_handler_unref(&nenv.ehandler); } return result; }
static bool cmd_putscript_finish_parsing(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_putscript_context *ctx = cmd->context; const struct managesieve_arg *args; int ret; /* if error occurs, the CRLF is already read. */ client->input_skip_line = FALSE; /* <script literal> */ ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args); if (ret == -1 || client->output->closed) { if (ctx->storage != NULL) client_send_command_error(cmd, NULL); cmd_putscript_finish(ctx); return TRUE; } if (ret < 0) { /* need more data */ return FALSE; } if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) { struct sieve_script *script; bool success = TRUE; /* Eat away the trailing CRLF */ client->input_skip_line = TRUE; /* Obtain script object for uploaded script */ script = sieve_storage_save_get_tempscript(ctx->save_ctx); /* Check result */ if ( script == NULL ) { client_send_storage_error(client, ctx->storage); cmd_putscript_finish(ctx); return TRUE; } /* If quoted string, the size was not known until now */ if ( ctx->script_size == 0 ) { if (sieve_script_get_size(script, &ctx->script_size) < 0) { client_send_storage_error(client, ctx->storage); cmd_putscript_finish(ctx); return TRUE; } /* Check quota; max size is already checked */ if ( ctx->scriptname != NULL && !managesieve_quota_check_all (client, ctx->scriptname, ctx->script_size) ) { cmd_putscript_finish(ctx); return TRUE; } } /* Try to compile script */ T_BEGIN { struct sieve_error_handler *ehandler; enum sieve_compile_flags cpflags = SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED; struct sieve_binary *sbin; enum sieve_error error; string_t *errors; /* Mark this as an activation when we are replacing the active script */ if ( sieve_storage_save_will_activate(ctx->save_ctx) ) { cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED; } /* Prepare error handler */ errors = str_new(default_pool, 1024); ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE, client->set->managesieve_max_compile_errors); /* Compile */ if ( (sbin=sieve_compile_script (script, ehandler, cpflags, &error)) == NULL ) { if ( error != SIEVE_ERROR_NOT_VALID ) { const char *errormsg = sieve_script_get_last_error(script, &error); if ( error != SIEVE_ERROR_NONE ) client_send_no(client, errormsg); else client_send_no(client, str_c(errors)); } else { client_send_no(client, str_c(errors)); } success = FALSE; } else { sieve_close(&sbin); /* Commit to save only when this is a putscript command */ if ( ctx->scriptname != NULL ) { ret = sieve_storage_save_commit(&ctx->save_ctx); /* Check commit */ if (ret < 0) { client_send_storage_error(client, ctx->storage); success = FALSE; } } } /* Finish up */ cmd_putscript_finish(ctx); /* Report result to user */ if ( success ) { if ( ctx->scriptname != NULL ) { client->put_count++; client->put_bytes += ctx->script_size; } else { client->check_count++; client->check_bytes += ctx->script_size; } if ( sieve_get_warnings(ehandler) > 0 ) client_send_okresp(client, "WARNINGS", str_c(errors)); else { if ( ctx->scriptname != NULL ) client_send_ok(client, "PUTSCRIPT completed."); else client_send_ok(client, "Script checked successfully."); } } sieve_error_handler_unref(&ehandler); str_free(&errors); } T_END; return TRUE; } client_send_command_error(cmd, "Too many command arguments."); cmd_putscript_finish(ctx); return TRUE; }
int ext_enotify_runtime_check_operands (const struct sieve_runtime_env *renv, string_t *method_uri, string_t *message, string_t *from, struct sieve_stringlist *options, const struct sieve_enotify_method **method_r, void **method_context) { const struct sieve_enotify_method *method; const char *uri_body; /* Get method */ method = ext_enotify_get_method(renv, method_uri, &uri_body); if ( method == NULL ) return SIEVE_EXEC_FAILURE; /* Check provided operands */ if ( method->def != NULL && method->def->runtime_check_operands != NULL ) { struct sieve_enotify_env nenv; int result = SIEVE_EXEC_OK; memset(&nenv, 0, sizeof(nenv)); nenv.svinst = renv->svinst; nenv.method = method; nenv.ehandler = sieve_prefix_ehandler_create (renv->ehandler, sieve_runtime_get_full_command_location(renv), "notify action"); /* Execute check function */ if ( method->def->runtime_check_operands (&nenv, str_c(method_uri), uri_body, message, from, sieve_result_pool(renv->result), method_context) ) { /* Check any provided options */ if ( options != NULL ) { string_t *option = NULL; int ret; /* Iterate through all provided options */ while ( (ret=sieve_stringlist_next_item(options, &option)) > 0 ) { const char *opt_name = NULL, *opt_value = NULL; /* Parse option into <optionname> and <value> */ if ( ext_enotify_option_parse (&nenv, str_c(option), FALSE, &opt_name, &opt_value) ) { /* Set option */ if ( method->def->runtime_set_option != NULL ) { (void) method->def->runtime_set_option (&nenv, *method_context, opt_name, opt_value); } } } /* Check for binary corruptions encountered during string list iteration */ if ( ret >= 0 ) { *method_r = method; } else { /* Binary corrupt */ sieve_runtime_trace_error (renv, "invalid item in options string list"); result = SIEVE_EXEC_BIN_CORRUPT; } } else { /* No options */ *method_r = method; } } else { /* Operand check failed */ result = SIEVE_EXEC_FAILURE; } sieve_error_handler_unref(&nenv.ehandler); return result; } /* No check function defined: a most unlikely situation */ *method_context = NULL; *method_r = method; return SIEVE_EXEC_OK; }
bool ext_enotify_compile_check_arguments (struct sieve_validator *valdtr, struct sieve_command *cmd, struct sieve_ast_argument *uri_arg, struct sieve_ast_argument *msg_arg, struct sieve_ast_argument *from_arg, struct sieve_ast_argument *options_arg) { const struct sieve_extension *this_ext = cmd->ext; struct sieve_instance *svinst = this_ext->svinst; const char *uri = sieve_ast_argument_strc(uri_arg); const char *scheme; const struct sieve_enotify_method *method; struct sieve_enotify_env nenv; bool result = TRUE; /* If the uri string is not a constant literal, we cannot determine which * method is used, so we bail out successfully and defer checking to runtime. */ if ( !sieve_argument_is_string_literal(uri_arg) ) return TRUE; /* Parse scheme part of URI */ if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) { sieve_argument_validate_error(valdtr, uri_arg, "notify command: invalid scheme part for method URI '%s'", str_sanitize(sieve_ast_argument_strc(uri_arg), 80)); return FALSE; } /* Find used method with the parsed scheme identifier */ if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) { sieve_argument_validate_error(valdtr, uri_arg, "notify command: invalid method '%s'", scheme); return FALSE; } if ( method->def == NULL ) return TRUE; /* Compose log structure */ memset(&nenv, 0, sizeof(nenv)); nenv.svinst = svinst; nenv.method = method; /* Check URI itself */ if ( result && method->def->compile_check_uri != NULL ) { /* Set log location to location of URI argument */ nenv.ehandler = sieve_prefix_ehandler_create (sieve_validator_error_handler(valdtr), sieve_error_script_location (sieve_validator_script(valdtr), uri_arg->source_line), "notify command"); /* Execute method check function */ result = method->def->compile_check_uri (&nenv, sieve_ast_argument_strc(uri_arg), uri); } /* Check :message argument */ if ( result && msg_arg != NULL && sieve_argument_is_string_literal(msg_arg) && method->def->compile_check_message != NULL ) { /* Set log location to location of :message argument */ sieve_error_handler_unref(&nenv.ehandler); nenv.ehandler = sieve_prefix_ehandler_create (sieve_validator_error_handler(valdtr), sieve_error_script_location (sieve_validator_script(valdtr), msg_arg->source_line), "notify command"); /* Execute method check function */ result = method->def->compile_check_message (&nenv, sieve_ast_argument_str(msg_arg)); } /* Check :from argument */ if ( result && from_arg != NULL && sieve_argument_is_string_literal(from_arg) && method->def->compile_check_from != NULL ) { /* Set log location to location of :from argument */ sieve_error_handler_unref(&nenv.ehandler); nenv.ehandler = sieve_prefix_ehandler_create (sieve_validator_error_handler(valdtr), sieve_error_script_location (sieve_validator_script(valdtr), from_arg->source_line), "notify command"); /* Execute method check function */ result = method->def->compile_check_from (&nenv, sieve_ast_argument_str(from_arg)); } sieve_error_handler_unref(&nenv.ehandler); /* Check :options argument */ if ( result && options_arg != NULL ) { struct sieve_ast_argument *option = options_arg; struct _ext_enotify_option_check_context optn_context = { svinst, valdtr, method }; /* Parse and check options */ result = ( sieve_ast_stringlist_map (&option, (void *) &optn_context, _ext_enotify_option_check) > 0 ); /* Discard argument if options are not accepted by method */ if ( result && method->def->compile_check_option == NULL ) { sieve_argument_validate_warning(valdtr, options_arg, "notify command: method '%s' accepts no options", scheme); (void)sieve_ast_arguments_detach(options_arg,1); } } return result; }
void sieve_errors_deinit(struct sieve_instance *svinst) { sieve_error_handler_unref(&svinst->system_ehandler); }