From 5d7f1005f5727ecd49b2e98a6768d8e83f027d1b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 3 Jan 2008 20:28:10 +0100
Subject: [PATCH] Implemented required features for use with MANAGESIEVE
 service.

---
 src/lib-sieve/Makefile.am                     |   5 +-
 .../plugins/include/ext-include-common.c      |   4 +-
 src/lib-sieve/sieve-binary.c                  |   1 +
 src/lib-sieve/sieve-error-private.h           |  38 ++++++
 src/lib-sieve/sieve-error.c                   |  97 +++++++--------
 src/lib-sieve/sieve-error.h                   |   3 +-
 src/lib-sieve/sieve-generator.c               |   4 +
 src/lib-sieve/sieve-interpreter.c             |   8 +-
 src/lib-sieve/sieve-lexer.c                   |  11 +-
 src/lib-sieve/sieve-parser.c                  |   9 +-
 src/lib-sieve/sieve-result.c                  |  24 ++--
 src/lib-sieve/sieve-script-private.h          |  29 +++++
 src/lib-sieve/sieve-script.c                  | 114 +++++++++++-------
 src/lib-sieve/sieve-script.h                  |  10 +-
 src/lib-sieve/sieve-validator.c               |   3 +
 src/lib-sieve/sieve.c                         |   9 +-
 src/lib-sieve/sieve.h                         |   8 +-
 src/plugins/lda-sieve/lda-sieve-plugin.c      |   4 +-
 src/sieve-bin/bin-common.c                    |   9 +-
 src/sieve-bin/sieve-exec.c                    |   2 +-
 src/sieve-bin/sieve-test.c                    |   3 +-
 21 files changed, 257 insertions(+), 138 deletions(-)
 create mode 100644 src/lib-sieve/sieve-error-private.h
 create mode 100644 src/lib-sieve/sieve-script-private.h

diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 1ec16b8a8..b17925420 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -72,6 +72,8 @@ libsieve_la_SOURCES = \
 
 noinst_HEADERS = \
 	sieve-lexer.h \
+	sieve-script.h \
+	sieve-script-private.h
 	sieve-ast.h \
 	sieve-binary.h \
 	sieve-parser.h \
@@ -79,8 +81,9 @@ noinst_HEADERS = \
 	sieve-generator.h \
 	sieve-interpreter.h \
 	sieve-code-dumper.h \
-	sieve-result.h
+	sieve-result.h \
 	sieve-error.h \
+	sieve-error-private.h \
 	sieve-comparators.h \
 	sieve-match-types.h \
 	sieve-address-parts.h \
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index beff7de0a..5b3aa59d8 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -297,7 +297,7 @@ bool ext_include_binary_open(struct sieve_binary *sbin)
 		/* Can we find/open the script dependency ? */
 		script_path = ext_include_get_script_path(location, str_c(script_name));		
 		if ( script_path == NULL || 
-			!(script=sieve_script_create(script_path, str_c(script_name), NULL)) ) {
+			!(script=sieve_script_create(script_path, str_c(script_name), NULL, NULL)) ) {
 			/* No, recompile */
 			return FALSE;
 		}
@@ -461,7 +461,7 @@ bool ext_include_generate_include
 		return FALSE;
 	
 	/* Create script object */
-	if ( (script = sieve_script_create(script_path, script_name, ehandler)) 
+	if ( (script = sieve_script_create(script_path, script_name, ehandler, NULL)) 
 		== NULL )
 		return FALSE;
 	
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index 663ea1cae..2c174d1f7 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -16,6 +16,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 /*
  * Config
diff --git a/src/lib-sieve/sieve-error-private.h b/src/lib-sieve/sieve-error-private.h
new file mode 100644
index 000000000..c81332c8e
--- /dev/null
+++ b/src/lib-sieve/sieve-error-private.h
@@ -0,0 +1,38 @@
+#ifndef __SIEVE_ERROR_PRIVATE_H
+#define __SIEVE_ERROR_PRIVATE_H
+
+#include "sieve-error.h"
+
+struct sieve_error_handler {
+    pool_t pool;
+	int refcount;
+
+    int errors;
+    int warnings;
+
+    /* Should we copy log to i_error, i_warning and i_info? */
+    bool log_master;
+
+    /* Should the errorhandler handle or discard info log?
+     * (This does not influence the previous setting)
+     */
+    bool log_info;
+
+    void (*verror)
+        (struct sieve_error_handler *ehandler, const char *location,
+            const char *fmt, va_list args);
+    void (*vwarning)
+        (struct sieve_error_handler *ehandler, const char *location,
+            const char *fmt, va_list args);
+    void (*vinfo)
+        (struct sieve_error_handler *ehandler, const char *location,
+            const char *fmt, va_list args);
+
+    void (*free)
+        (struct sieve_error_handler *ehandler);
+};
+
+void sieve_error_handler_init
+    (struct sieve_error_handler *ehandler, pool_t pool);
+
+#endif /* __SIEVE_ERROR_PRIVATE_H */
diff --git a/src/lib-sieve/sieve-error.c b/src/lib-sieve/sieve-error.c
index 578205c69..5e27f67f7 100644
--- a/src/lib-sieve/sieve-error.c
+++ b/src/lib-sieve/sieve-error.c
@@ -4,7 +4,7 @@
 #include "str.h"
 #include "ostream.h"
 
-#include "sieve-error.h"
+#include "sieve-error-private.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -16,37 +16,6 @@
 	"internal error occurred: refer to server log for more information."
 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
 
-/* This should be moved to a sieve-errors-private.h when the need for other 
- * types of (externally defined) error handlers arises.
- */
-struct sieve_error_handler {	
-	pool_t pool;
-	
-	int errors;
-	int warnings;
-	
-	/* Should we copy log to i_error, i_warning and i_info? */
-	bool log_master; 
-	
-	/* Should the errorhandler handle or discard info log?
-	 * (This does not influence the previous setting) 
-	 */
-	bool log_info;
-	
-	void (*verror)
-		(struct sieve_error_handler *ehandler, const char *location, 
-			const char *fmt, va_list args);
-	void (*vwarning)
-		(struct sieve_error_handler *ehandler, const char *location, 
-			const char *fmt, va_list args);
-	void (*vinfo)
-		(struct sieve_error_handler *ehandler, const char *location, 
-			const char *fmt, va_list args);
-
-	void (*free)
-		(struct sieve_error_handler *ehandler);
-};
-
 void sieve_verror
 	(struct sieve_error_handler *ehandler, const char *location, 
 		const char *fmt, va_list args)
@@ -128,20 +97,37 @@ void sieve_error_handler_copy_masterlog
 	ehandler->log_master = enable;
 }
 
-void sieve_error_handler_free(struct sieve_error_handler **ehandler)
+void sieve_error_handler_init
+	(struct sieve_error_handler *ehandler, pool_t pool)
 {
-	pool_t pool;
-	
-	if ( *ehandler != NULL ) {
-		if ( (*ehandler)->free != NULL )
-			(*ehandler)->free(*ehandler);
-	
-		pool = (*ehandler)->pool;
-		pool_unref(&pool);
-	
-		if ( pool == NULL )
-			*ehandler = NULL;
-	}
+	ehandler->pool = pool;
+	ehandler->refcount = 1;
+	ehandler->errors = 0;
+	ehandler->warnings = 0;
+}
+
+void sieve_error_handler_ref(struct sieve_error_handler *ehandler)
+{
+	if ( ehandler == NULL ) return;
+
+	ehandler->refcount++;
+}
+
+void sieve_error_handler_unref(struct sieve_error_handler **ehandler)
+{
+	if ( *ehandler == NULL ) return;
+
+    i_assert((*ehandler)->refcount > 0);
+
+    if (--(*ehandler)->refcount != 0)
+        return;
+
+	if ( (*ehandler)->free != NULL )
+		(*ehandler)->free(*ehandler);
+
+	pool_unref(&((*ehandler)->pool));
+
+	*ehandler = NULL;
 }
 
 /* Output errors directly to stderror (merge this with logfile below?) */
@@ -172,15 +158,15 @@ struct sieve_error_handler *sieve_stderr_ehandler_create( void )
 	pool_t pool;
 	struct sieve_error_handler *ehandler;
 	
-	/* Pool is not strictly necessary, but other hander types will need a pool,
+	/* Pool is not strictly necessary, but other handler types will need a pool,
 	 * so this one will have one too.
 	 */
 	pool = pool_alloconly_create
-		("stderr_error_handler", sizeof(struct sieve_error_handler));	
+		("stderr_error_handler", sizeof(struct sieve_error_handler));
+//		("stderr_error_handler", 128);	
 	ehandler = p_new(pool, struct sieve_error_handler, 1);
-	ehandler->pool = pool;
-	ehandler->errors = 0;
-	ehandler->warnings = 0;
+	sieve_error_handler_init(ehandler, pool);
+
 	ehandler->verror = sieve_stderr_verror;
 	ehandler->vwarning = sieve_stderr_vwarning;
 	ehandler->vinfo = sieve_stderr_vinfo;
@@ -241,9 +227,9 @@ struct sieve_error_handler *sieve_strbuf_ehandler_create
     pool = pool_alloconly_create("strbuf_error_handler", 256);
     ehandler = p_new(pool, struct sieve_strbuf_ehandler, 1);
 	ehandler->errors = strbuf;
-    ehandler->handler.pool = pool;
-    ehandler->handler.errors = 0;
-    ehandler->handler.warnings = 0;
+    
+	sieve_error_handler_init(&ehandler->handler, pool);
+
     ehandler->handler.verror = sieve_strbuf_verror;
     ehandler->handler.vwarning = sieve_strbuf_vwarning;
     ehandler->handler.vinfo = sieve_strbuf_vinfo;
@@ -389,9 +375,8 @@ struct sieve_error_handler *sieve_logfile_ehandler_create(const char *logfile)
 	
 	pool = pool_alloconly_create("logfile_error_handler", 256);	
 	ehandler = p_new(pool, struct sieve_logfile_ehandler, 1);
-	ehandler->handler.pool = pool;
-	ehandler->handler.errors = 0;
-	ehandler->handler.warnings = 0;
+	sieve_error_handler_init(&ehandler->handler, pool);
+
 	ehandler->handler.verror = sieve_logfile_verror;
 	ehandler->handler.vwarning = sieve_logfile_vwarning;
 	ehandler->handler.vinfo = sieve_logfile_vinfo;
diff --git a/src/lib-sieve/sieve-error.h b/src/lib-sieve/sieve-error.h
index 3b389cb8a..787ed7c67 100644
--- a/src/lib-sieve/sieve-error.h
+++ b/src/lib-sieve/sieve-error.h
@@ -97,7 +97,8 @@ void sieve_error_handler_copy_masterlog
 unsigned int sieve_get_errors(struct sieve_error_handler *ehandler);
 unsigned int sieve_get_warnings(struct sieve_error_handler *ehandler);
 
-void sieve_error_handler_free(struct sieve_error_handler **ehandler);
+void sieve_error_handler_ref(struct sieve_error_handler *ehandler);
+void sieve_error_handler_unref(struct sieve_error_handler **ehandler);
 
 /* Error handlers */
 
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index 9e5bd09ba..082b5ca63 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -60,7 +60,9 @@ struct sieve_generator *sieve_generator_create
 	pool = pool_alloconly_create("sieve_generator", 4096);	
 	gentr = p_new(pool, struct sieve_generator, 1);
 	gentr->pool = pool;
+
 	gentr->ehandler = ehandler;
+	sieve_error_handler_ref(ehandler);
 	
 	gentr->ast = ast;	
 	gentr->script = sieve_ast_script(ast);
@@ -88,6 +90,8 @@ void sieve_generator_free(struct sieve_generator **generator)
 	if ( (*generator)->binary != NULL )
 		sieve_binary_unref(&(*generator)->binary);
 	
+	sieve_error_handler_unref(&(*generator)->ehandler);
+
 	pool_unref(&((*generator)->pool));
 	
 	*generator = NULL;
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index fe85abf29..63522d84d 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -124,9 +124,11 @@ struct sieve_interpreter *sieve_interpreter_create
 	pool = pool_alloconly_create("sieve_interpreter", 4096);	
 	interp = p_new(pool, struct sieve_interpreter, 1);
 	interp->pool = pool;
+
 	interp->ehandler = ehandler;
-	interp->runenv.interp = interp;
-	
+	sieve_error_handler_ref(ehandler);
+
+	interp->runenv.interp = interp;	
 	interp->runenv.sbin = sbin;
 	interp->runenv.script = sieve_binary_script(sbin);
 	sieve_binary_ref(sbin);
@@ -161,6 +163,8 @@ void sieve_interpreter_free(struct sieve_interpreter **interp)
 
 	if ( (*interp)->runenv.msgctx != NULL )
 		 sieve_message_context_unref(&(*interp)->runenv.msgctx);
+
+	sieve_error_handler_unref(&(*interp)->ehandler);
 		 
 	pool_unref(&((*interp)->pool));
 	
diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c
index db4285073..287d787ad 100644
--- a/src/lib-sieve/sieve-lexer.c
+++ b/src/lib-sieve/sieve-lexer.c
@@ -80,7 +80,7 @@ struct sieve_lexer *sieve_lexer_create
 	struct sieve_lexer *lexer;
 	struct istream *stream;
 	
-	stream = sieve_script_open(script);
+	stream = sieve_script_open(script, NULL);
 	if ( stream == NULL )
 		return NULL;
 	
@@ -88,6 +88,9 @@ struct sieve_lexer *sieve_lexer_create
 	lexer = p_new(pool, struct sieve_lexer, 1);
 	lexer->pool = pool;
 	
+	lexer->ehandler = ehandler;
+	sieve_error_handler_ref(ehandler);
+
 	lexer->input = stream;
 	i_stream_ref(lexer->input);
 	
@@ -102,9 +105,7 @@ struct sieve_lexer *sieve_lexer_create
 	lexer->token_type = STT_NONE;
 	lexer->token_str_value = NULL;
 	lexer->token_int_value = 0;
-	
-	lexer->ehandler = ehandler;
-	
+		
 	return lexer;
 }
 
@@ -115,6 +116,8 @@ void sieve_lexer_free(struct sieve_lexer **lexer)
 	sieve_script_close((*lexer)->script);
 	sieve_script_unref(&(*lexer)->script);
 
+	sieve_error_handler_unref(&(*lexer)->ehandler);
+
 	pool_unref(&(*lexer)->pool); 
 
 	*lexer = NULL;
diff --git a/src/lib-sieve/sieve-parser.c b/src/lib-sieve/sieve-parser.c
index 087d37b05..e28b0a467 100644
--- a/src/lib-sieve/sieve-parser.c
+++ b/src/lib-sieve/sieve-parser.c
@@ -82,14 +82,15 @@ struct sieve_parser *sieve_parser_create
 		parser = p_new(pool, struct sieve_parser, 1);
 		parser->pool = pool;
 		
+		parser->ehandler = ehandler;
+		sieve_error_handler_ref(ehandler);
+
 		parser->script = script;
 		sieve_script_ref(script);
 				
 		parser->lexer = lexer;
 		parser->ast = NULL;
-		
-		parser->ehandler = ehandler;
-		
+				
 		return parser;
 	}
 	
@@ -104,6 +105,8 @@ void sieve_parser_free(struct sieve_parser **parser)
 	sieve_lexer_free(&(*parser)->lexer);
 	sieve_script_unref(&(*parser)->script);
 
+	sieve_error_handler_unref(&(*parser)->ehandler);
+
 	pool_unref(&(*parser)->pool);
 	
 	*parser = NULL;
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index af78f5fcc..7884ffb49 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -38,6 +38,8 @@ struct sieve_result_side_effect {
 
 struct sieve_result {
 	pool_t pool;
+	int refcount;
+
 	struct sieve_error_handler *ehandler;
 		
 	struct sieve_action_exec_env action_env;
@@ -53,8 +55,12 @@ struct sieve_result *sieve_result_create
 	 
 	pool = pool_alloconly_create("sieve_result", 4096);	
 	result = p_new(pool, struct sieve_result, 1);
+	result->refcount = 1;
 	result->pool = pool;
+	
 	result->ehandler = ehandler;
+	sieve_error_handler_ref(ehandler);
+
 	result->action_env.result = result;
 		
 	result->first_action = NULL;
@@ -65,17 +71,21 @@ struct sieve_result *sieve_result_create
 
 void sieve_result_ref(struct sieve_result *result) 
 {
-	pool_ref(result->pool);
+	result->refcount++;
 }
 
 void sieve_result_unref(struct sieve_result **result) 
 {
-	if ( result != NULL && *result != NULL ) {
-		pool_t pool = (*result)->pool;
-		pool_unref(&pool);
-		if ( pool == NULL )
-			*result = NULL;
-	}
+	i_assert((*result)->refcount > 0);
+
+    if (--(*result)->refcount != 0)
+        return;
+
+	sieve_error_handler_unref(&(*result)->ehandler);
+
+    pool_unref(&(*result)->pool);
+
+    *result = NULL;
 }
 
 inline pool_t sieve_result_pool(struct sieve_result *result)
diff --git a/src/lib-sieve/sieve-script-private.h b/src/lib-sieve/sieve-script-private.h
new file mode 100644
index 000000000..175526104
--- /dev/null
+++ b/src/lib-sieve/sieve-script-private.h
@@ -0,0 +1,29 @@
+#ifndef __SIEVE_SCRIPT_PRIVATE_H
+#define __SIEVE_SCRIPT_PRIVATE_H
+
+#include "sieve-script.h"
+
+struct sieve_script {
+    pool_t pool;
+    unsigned int refcount;
+
+    struct stat st;
+
+    struct sieve_error_handler *ehandler;
+
+    /* Parameters */
+    const char *name;
+    const char *filename;
+    const char *dirpath;
+    const char *path;
+
+    /* Stream */
+    int fd; /* FIXME: we could use the stream's autoclose facility */
+    struct istream *stream;
+};
+
+struct sieve_script *sieve_script_init
+(struct sieve_script *script, const char *path, const char *name,
+    struct sieve_error_handler *ehandler, bool *exists_r);
+
+#endif /* __SIEVE_SCRIPT_PRIVATE_H */
diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index df6cd7117..0c307edf6 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -5,38 +5,26 @@
 #include "sieve-common.h"
 #include "sieve-error.h"
 
-#include "sieve-script.h"
+#include "sieve-script-private.h"
 
-#define SIEVE_READ_BLOCK_SIZE (1024*8)
-
-struct sieve_script {
-	pool_t pool;
-	unsigned int refcount;
-	
-	struct stat st;
-
-	struct sieve_error_handler *ehandler;
-		
-	/* Parameters */
-	const char *name;
-	const char *dirpath;
-	const char *path;	
+#include <sys/stat.h>
+#include <fcntl.h>
 
-	/* Stream */
-	int fd; /* FIXME: we could use the stream's autoclose facility */
-	struct istream *stream;
-};
+#define SIEVE_READ_BLOCK_SIZE (1024*8)
 
 /* Script object */
-
-struct sieve_script *sieve_script_create
-	(const char *path, const char *name, struct sieve_error_handler *ehandler)
+struct sieve_script *sieve_script_init
+(struct sieve_script *script, const char *path, const char *name, 
+	struct sieve_error_handler *ehandler, bool *exists_r)
 {
+	int ret;
 	pool_t pool;
 	struct stat st;
-	struct sieve_script *script;
 	const char *filename, *dirpath;
 
+	if ( exists_r != NULL )
+		*exists_r = FALSE;
+
 	T_FRAME(
 		/* Extract filename from path */
 		filename = strrchr(path, '/');
@@ -61,32 +49,52 @@ struct sieve_script *sieve_script_create
 		
 		/* First obtain stat data from the system */
 	
-		if ( stat(path, &st) < 0 ) {
-			if ( errno == ENOENT )
-				sieve_error(ehandler, path, "sieve script does not exist");
-			else 
-				sieve_critical(ehandler, path, "failed to stat sieve script: %m");
+		if ( (ret=stat(path, &st)) < 0 && (errno != ENOENT || exists_r == NULL) ) {
+			if ( errno == ENOENT ) 
+				sieve_error(ehandler, name, "sieve script does not exist");
+			else
+				sieve_critical(ehandler, name, "failed to stat sieve script file '%s': %m", path);
 			script = NULL;
 		} else {
+			/* Only create/init the object if it stat()s without problems */
+
+			if ( !S_ISREG(st.st_mode) ) {
+                sieve_critical(ehandler, name, 
+					"sieve script file '%s' is not a regular file.", path);
+                script = NULL;
+            } else {
+				if ( exists_r != NULL )
+					*exists_r = ( ret >= 0 );					
+
+				if ( script == NULL ) {
+					pool = pool_alloconly_create("sieve_script", 1024);
+					script = p_new(pool, struct sieve_script, 1);
+					script->pool = pool;
+				} else 
+					pool = script->pool;
 	
-			/* Only create object if it stat()s without problems */
-	
-			pool = pool_alloconly_create("sieve_script", 1024);
-			script = p_new(pool, struct sieve_script, 1);
-			script->pool = pool;
-			script->refcount = 1;
-			script->ehandler = ehandler;
+				script->refcount = 1;
+				script->ehandler = ehandler;
+				sieve_error_handler_ref(ehandler);
 	
-			memcpy((void *) &script->st, (void *) &st, sizeof(st));
-			script->path = p_strdup(pool, path);	
-			script->dirpath = p_strdup(pool, dirpath);
-			script->name = p_strdup(pool, name);
+				memcpy((void *) &script->st, (void *) &st, sizeof(st));
+				script->path = p_strdup(pool, path);	
+				script->filename = p_strdup(pool, filename);
+				script->dirpath = p_strdup(pool, dirpath);
+				script->name = p_strdup(pool, name);
+			}
 		}
 	);
 
 	return script;
 }
 
+struct sieve_script *sieve_script_create(const char *path, const char *name,
+    struct sieve_error_handler *ehandler, bool *exists_r)
+{
+	return sieve_script_init(NULL, path, name, ehandler, exists_r);
+}
+
 void sieve_script_ref(struct sieve_script *script)
 {
 	script->refcount++;
@@ -102,6 +110,8 @@ void sieve_script_unref(struct sieve_script **script)
 	if ( (*script)->stream != NULL )
 		i_stream_destroy(&(*script)->stream);
 
+	sieve_error_handler_unref(&(*script)->ehandler);
+
 	pool_unref(&(*script)->pool);
 
 	*script = NULL;
@@ -109,15 +119,22 @@ void sieve_script_unref(struct sieve_script **script)
 
 /* Stream manageement */
 
-struct istream *sieve_script_open(struct sieve_script *script)
+struct istream *sieve_script_open
+(struct sieve_script *script, bool *deleted_r)
 {
 	int fd;
 
+	if ( deleted_r != NULL )
+		*deleted_r = FALSE;
+
 	if ( (fd=open(script->path, O_RDONLY)) < 0 ) {
 		if ( errno == ENOENT ) 
-			/* Not supposed to occur, create() does stat already */
-			sieve_error(script->ehandler, script->name, 
-				"sieve script '%s' does not exist", script->name);
+			if ( deleted_r == NULL ) 
+				/* Not supposed to occur, create() does stat already */
+				sieve_error(script->ehandler, script->name, 
+					"sieve script '%s' does not exist", script->name);
+			else 
+				*deleted_r = TRUE;
 		else
 			sieve_critical(script->ehandler, script->path, 
 				"failed to open sieve script: %m");
@@ -134,6 +151,11 @@ void sieve_script_close(struct sieve_script *script)
 	i_stream_destroy(&script->stream);
 }
 
+uoff_t sieve_script_get_size(struct sieve_script *script)
+{
+	return script->st.st_size;
+}
+
 /* Comparison */
 
 int sieve_script_cmp
@@ -160,6 +182,11 @@ inline const char *sieve_script_name(struct sieve_script *script)
 	return script->name;
 }
 
+inline const char *sieve_script_filename(struct sieve_script *script)
+{
+	return script->filename;
+}
+
 inline const char *sieve_script_path(struct sieve_script *script)
 {
 	return script->path;
@@ -170,4 +197,3 @@ inline const char *sieve_script_binpath(struct sieve_script *script)
 	return t_strconcat(script->dirpath, "/", script->name, ".svbin", NULL);
 }
 
-
diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h
index 34d681980..e0da16a17 100644
--- a/src/lib-sieve/sieve-script.h
+++ b/src/lib-sieve/sieve-script.h
@@ -3,21 +3,22 @@
 
 #include "sieve-common.h"
 
-/* FIXME: This conflicts with the managesieve implementation */
-
 struct sieve_script;
 
 struct sieve_script *sieve_script_create
-	(const char *path, const char *name, struct sieve_error_handler *ehandler);
+	(const char *path, const char *name, 
+		struct sieve_error_handler *ehandler, bool *exists_r);
 
 void sieve_script_ref(struct sieve_script *script);
 void sieve_script_unref(struct sieve_script **script);
 
 /* Stream manageement */
 
-struct istream *sieve_script_open(struct sieve_script *script);
+struct istream *sieve_script_open(struct sieve_script *script, bool *deleted_r);
 void sieve_script_close(struct sieve_script *script);
 
+uoff_t sieve_script_get_size(struct sieve_script *script);
+
 int sieve_script_cmp
 	(struct sieve_script *script1, struct sieve_script *script2);
 unsigned int sieve_script_hash(struct sieve_script *script);
@@ -30,6 +31,7 @@ static inline bool sieve_script_equals
 }
 
 inline const char *sieve_script_name(struct sieve_script *script);
+inline const char *sieve_script_filename(struct sieve_script *script);
 inline const char *sieve_script_path(struct sieve_script *script);
 inline const char *sieve_script_binpath(struct sieve_script *script);
 
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index e8a6da6b4..dd5921a30 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -95,6 +95,7 @@ struct sieve_validator *sieve_validator_create
 	validator->pool = pool;
 	
 	validator->ehandler = ehandler;
+	sieve_error_handler_ref(ehandler);
 	
 	validator->ast = ast;	
 	validator->script = sieve_ast_script(ast);
@@ -134,6 +135,8 @@ void sieve_validator_free(struct sieve_validator **validator)
 	hash_destroy(&(*validator)->commands);
 	sieve_ast_unref(&(*validator)->ast);
 
+	sieve_error_handler_unref(&(*validator)->ehandler);
+
 	pool_unref(&(*validator)->pool);
 
 	*validator = NULL;
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 14d3cf7f5..e2ce4b464 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -123,7 +123,7 @@ struct sieve_binary *sieve_compile
 	struct sieve_script *script;
 	struct sieve_binary *sbin;
 
-	if ( (script = sieve_script_create(script_path, NULL, ehandler)) == NULL )
+	if ( (script = sieve_script_create(script_path, NULL, ehandler, NULL)) == NULL )
 		return NULL;
 	
 	sbin = sieve_compile_script(script, ehandler);
@@ -140,7 +140,7 @@ struct sieve_binary *sieve_open
 	struct sieve_binary *sbin;
 	const char *binpath;
 	
-	script = sieve_script_create(script_path, NULL, ehandler);
+	script = sieve_script_create(script_path, NULL, ehandler, NULL);
 
 	if ( script == NULL )
 		return NULL;
@@ -223,4 +223,7 @@ void sieve_close(struct sieve_binary **sbin)
 	sieve_binary_unref(sbin);
 }
 
-	
+const char *sieve_get_capabilities(void) 
+{
+	return "fileinto reject envelope encoded-character";	
+}
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index da41f24ae..e64940fca 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -3,9 +3,6 @@
 #ifndef __SIEVE_H
 #define __SIEVE_H
 
-#include "lib.h"
-#include "mail-storage.h"
-
 #include <stdio.h>
 
 #include "sieve-error.h"
@@ -101,4 +98,9 @@ int sieve_execute
  */
 void sieve_close(struct sieve_binary **sbin);
 
+/* sieve_get_capabilities:
+ *
+ */
+const char *sieve_get_capabilities(void);
+
 #endif
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 56d7cb0f3..b79714b45 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -96,7 +96,7 @@ static int lda_sieve_run
 		i_error("sieve: Failed to compile script. "
 			"Log should be available as %s", scriptlog);
 
-		sieve_error_handler_free(&ehandler);
+		sieve_error_handler_unref(&ehandler);
 		return -1;
 	}
 
@@ -132,7 +132,7 @@ static int lda_sieve_run
 	if ( ret < 0 )
 		i_error("sieve: Failed to execute script %s", script_path);
 
-	sieve_error_handler_free(&ehandler);
+	sieve_error_handler_unref(&ehandler);
 
 	return ret;
 }
diff --git a/src/sieve-bin/bin-common.c b/src/sieve-bin/bin-common.c
index 4c3157094..850f79ade 100644
--- a/src/sieve-bin/bin-common.c
+++ b/src/sieve-bin/bin-common.c
@@ -3,6 +3,7 @@
 #include "ioloop.h"
 #include "ostream.h"
 #include "hostpid.h"
+#include "mail-storage.h"
 
 #include "sieve.h"
 #include "bin-common.h"
@@ -75,11 +76,11 @@ struct sieve_binary *bin_compile_sieve_script(const char *filename)
 	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
 	if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) {
-		sieve_error_handler_free(&ehandler);
+		sieve_error_handler_unref(&ehandler);
 		i_fatal("Failed to compile sieve script\n");
 	}
 
-	sieve_error_handler_free(&ehandler);
+	sieve_error_handler_unref(&ehandler);
 		
 	return sbin;
 }
@@ -93,11 +94,11 @@ struct sieve_binary *bin_open_sieve_script(const char *filename)
 	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
 	if ( (sbin = sieve_open(filename, ehandler)) == NULL ) {
-		sieve_error_handler_free(&ehandler);
+		sieve_error_handler_unref(&ehandler);
 		i_fatal("Failed to compile sieve script\n");
 	}
 
-	sieve_error_handler_free(&ehandler);
+	sieve_error_handler_unref(&ehandler);
 		
 	return sbin;
 }
diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c
index 3a6e47911..1f927319f 100644
--- a/src/sieve-bin/sieve-exec.c
+++ b/src/sieve-bin/sieve-exec.c
@@ -195,7 +195,7 @@ int main(int argc, char **argv)
 		i_info("Final result: failed (caller please handle implicit keep!)\n");
 
 	sieve_close(&sbin);
-	sieve_error_handler_free(&ehandler);
+	sieve_error_handler_unref(&ehandler);
 
 	bin_close_mail_file(mfd);
 	mail_raw_close(mailr);
diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-bin/sieve-test.c
index 5cef7b875..c30ff636d 100644
--- a/src/sieve-bin/sieve-test.c
+++ b/src/sieve-bin/sieve-test.c
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "ostream.h"
+#include "mail-storage.h"
 
 #include "bin-common.h"
 #include "mail-raw.h"
@@ -124,7 +125,7 @@ int main(int argc, char **argv)
 	(void) sieve_test(sbin, &msgdata, &scriptenv, ehandler);
 
 	sieve_close(&sbin);
-	sieve_error_handler_free(&ehandler);
+	sieve_error_handler_unref(&ehandler);
 
 	bin_close_mail_file(mfd);
 	
-- 
GitLab