Пример #1
0
static bool cmd_putscript_continue_script(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_putscript_context *ctx = cmd->context;
	size_t size;
	int ret;

	if (ctx->save_ctx != NULL) {
		while (ctx->script_size == 0 || ctx->input->v_offset != ctx->script_size) {
			if ( ctx->max_script_size > 0 &&
				ctx->input->v_offset > ctx->max_script_size ) {
				(void)managesieve_quota_check_validsize(client, ctx->input->v_offset);
				cmd_putscript_finish(ctx);
				return TRUE;
			}

			ret = i_stream_read(ctx->input);
			if ((ret != -1 || ctx->input->stream_errno != EINVAL ||
				client->input->eof) &&
				sieve_storage_save_continue(ctx->save_ctx) < 0) {
				/* we still have to finish reading the script
			   	  from client */
				sieve_storage_save_cancel(&ctx->save_ctx);
				break;
			}
			if (ret == -1 || ret == 0)
        break;
		}
	}

	if (ctx->save_ctx == NULL) {
		(void)i_stream_read(ctx->input);
		(void)i_stream_get_data(ctx->input, &size);
		i_stream_skip(ctx->input, size);
	}

	if (ctx->input->eof || client->input->closed) {
		bool failed = FALSE;
		bool all_written = FALSE;

		if ( ctx->script_size == 0 ) {
			if ( !client->input->eof &&
				ctx->input->stream_errno == EINVAL ) {
				client_send_command_error(cmd, t_strdup_printf(
					"Invalid input: %s", i_stream_get_error(ctx->input)));
				client->input_skip_line = TRUE;
				failed = TRUE;
			}
			all_written = ( ctx->input->eof && ctx->input->stream_errno == 0 );

		} else {
			all_written = ( ctx->input->v_offset == ctx->script_size );
		}

		/* finished */
		ctx->input = NULL;

		if ( !failed ) {
			if (ctx->save_ctx == NULL) {
				/* failed above */
				client_send_storage_error(client, ctx->storage);
				failed = TRUE;
			} else if (!all_written) {
				/* client disconnected before it finished sending the
					 whole script. */
				failed = TRUE;
				sieve_storage_save_cancel(&ctx->save_ctx);
				client_disconnect
					(client, "EOF while appending in PUTSCRIPT/CHECKSCRIPT");
			} else if (sieve_storage_save_finish(ctx->save_ctx) < 0) {
				failed = TRUE;
				client_send_storage_error(client, ctx->storage);
			} else {
				failed = client->input->closed;
			}
		}

		if (failed) {
			cmd_putscript_finish(ctx);
			return TRUE;
		}

		/* finish */
		client->command_pending = FALSE;
		managesieve_parser_reset(ctx->save_parser);
		cmd->func = cmd_putscript_finish_parsing;
		return cmd_putscript_finish_parsing(cmd);
	}

	return FALSE;
}
Пример #2
0
static int
sieve_attribute_set_sieve(struct mail_storage *storage,
			  const char *key,
			  const struct mail_attribute_value *value)
{
	struct sieve_storage *svstorage;
	struct sieve_storage_save_context *save_ctx;
	struct istream *input;
	const char *scriptname;
	int ret;

	if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) {
		if (ret == 0) {
			mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
					       "Sieve not enabled for user");
		}
		return -1;
	}

	if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0)
		return sieve_attribute_set_default(storage, svstorage, value);
	if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
		    strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) != 0) {
		mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
				       "Nonexistent sieve attribute");
		return -1;
	}
	scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES);

	if (value->value != NULL) {
		input = i_stream_create_from_data(value->value,
						  strlen(value->value));
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
		i_stream_unref(&input);
	} else if (value->value_stream != NULL) {
		input = value->value_stream;
		save_ctx = sieve_storage_save_init(svstorage, scriptname, input);
	} else {
		return sieve_attribute_unset_script(storage, svstorage, scriptname);
	}

	if (save_ctx == NULL) {
		/* save initialization failed */
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		return -1;
	}

	sieve_storage_save_set_mtime(save_ctx, value->last_change);

	ret = 0;
	while (i_stream_read(input) > 0) {
		if (sieve_storage_save_continue(save_ctx) < 0) {
			mail_storage_set_critical(storage,
				"Failed to save sieve script '%s': %s", scriptname,
				sieve_storage_get_last_error(svstorage, NULL));
			ret = -1;
			break;
		}
	}
	i_assert(input->eof || ret < 0);
	if (input->stream_errno != 0) {
		errno = input->stream_errno;
		mail_storage_set_critical(storage,
			"Saving sieve script: read(%s) failed: %m",
			i_stream_get_name(input));
		ret = -1;
	}
	if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	if (ret < 0)
		sieve_storage_save_cancel(&save_ctx);
	else if (sieve_storage_save_commit(&save_ctx) < 0) {
		mail_storage_set_critical(storage,
			"Failed to save sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
		ret = -1;
	}
	return ret;
}