From fa816c6bdfa56b7089d1b361e5a9f2129a6ab82c Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@dovecot.fi>
Date: Wed, 2 May 2018 23:46:27 +0200
Subject: [PATCH] lib-sieve: Add support for compiling Sieve scripts from an
 input stream.

---
 configure.ac                                  |  1 +
 src/lib-sieve/Makefile.am                     |  1 +
 src/lib-sieve/sieve-script-private.h          |  1 +
 src/lib-sieve/sieve-script.h                  |  8 ++
 src/lib-sieve/sieve-storage-private.h         |  6 ++
 src/lib-sieve/storage/Makefile.am             |  1 +
 src/lib-sieve/storage/data/Makefile.am        | 13 +++
 .../storage/data/sieve-data-script.c          | 94 +++++++++++++++++++
 .../storage/data/sieve-data-storage.c         | 47 ++++++++++
 .../storage/data/sieve-data-storage.h         | 30 ++++++
 10 files changed, 202 insertions(+)
 create mode 100644 src/lib-sieve/storage/data/Makefile.am
 create mode 100644 src/lib-sieve/storage/data/sieve-data-script.c
 create mode 100644 src/lib-sieve/storage/data/sieve-data-storage.c
 create mode 100644 src/lib-sieve/storage/data/sieve-data-storage.h

diff --git a/configure.ac b/configure.ac
index 53b3359f6..091973e95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,7 @@ src/Makefile
 src/lib-sieve/Makefile
 src/lib-sieve/util/Makefile
 src/lib-sieve/storage/Makefile
+src/lib-sieve/storage/data/Makefile
 src/lib-sieve/storage/file/Makefile
 src/lib-sieve/storage/dict/Makefile
 src/lib-sieve/storage/ldap/Makefile
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 021aebc1a..938bda0a3 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -48,6 +48,7 @@ endif
 
 strgdir = $(top_builddir)/src/lib-sieve/storage
 storages = \
+	$(strgdir)/data/libsieve_storage_data.la \
 	$(strgdir)/file/libsieve_storage_file.la \
 	$(strgdir)/dict/libsieve_storage_dict.la \
 	$(strgdir)/ldap/libsieve_storage_ldap.la \
diff --git a/src/lib-sieve/sieve-script-private.h b/src/lib-sieve/sieve-script-private.h
index 7f1edff72..3338ba45d 100644
--- a/src/lib-sieve/sieve-script-private.h
+++ b/src/lib-sieve/sieve-script-private.h
@@ -78,6 +78,7 @@ void sieve_script_init
  * Built-in script drivers
  */
 
+extern const struct sieve_script sieve_data_script;
 extern const struct sieve_script sieve_file_script;
 extern const struct sieve_script sieve_dict_script;
 extern const struct sieve_script sieve_ldap_script;
diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h
index 66198fb65..f3709f389 100644
--- a/src/lib-sieve/sieve-script.h
+++ b/src/lib-sieve/sieve-script.h
@@ -59,6 +59,14 @@ int sieve_script_check
 		const char *name, enum sieve_error *error_r)
 		ATTR_NULL(3, 4);
 
+/*
+ * Data script
+ */
+
+struct sieve_script *sieve_data_script_create_from_input
+	(struct sieve_instance *svinst, const char *name,
+		struct istream *input);
+
 /*
  * Binary
  */
diff --git a/src/lib-sieve/sieve-storage-private.h b/src/lib-sieve/sieve-storage-private.h
index 9cdb877f7..97e5c9edd 100644
--- a/src/lib-sieve/sieve-storage-private.h
+++ b/src/lib-sieve/sieve-storage-private.h
@@ -198,6 +198,12 @@ const struct sieve_storage *sieve_storage_find_class
  * Built-in storage drivers
  */
 
+/* data (currently only for internal use) */
+
+#define SIEVE_DATA_STORAGE_DRIVER_NAME "data"
+
+extern const struct sieve_storage sieve_data_storage;
+
 /* file */
 
 #define SIEVE_FILE_STORAGE_DRIVER_NAME "file"
diff --git a/src/lib-sieve/storage/Makefile.am b/src/lib-sieve/storage/Makefile.am
index 00e770de8..ba39e4a06 100644
--- a/src/lib-sieve/storage/Makefile.am
+++ b/src/lib-sieve/storage/Makefile.am
@@ -1,4 +1,5 @@
 SUBDIRS = \
+	data \
 	file \
 	dict \
 	ldap
diff --git a/src/lib-sieve/storage/data/Makefile.am b/src/lib-sieve/storage/data/Makefile.am
new file mode 100644
index 000000000..c17741da4
--- /dev/null
+++ b/src/lib-sieve/storage/data/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libsieve_storage_data.la
+
+AM_CPPFLAGS = \
+	$(LIBDOVECOT_INCLUDE) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/src/lib-sieve
+
+libsieve_storage_data_la_SOURCES = \
+	sieve-data-script.c \
+	sieve-data-storage.c
+
+noinst_HEADERS = \
+	sieve-data-storage.h
diff --git a/src/lib-sieve/storage/data/sieve-data-script.c b/src/lib-sieve/storage/data/sieve-data-script.c
new file mode 100644
index 000000000..a8c8af1e7
--- /dev/null
+++ b/src/lib-sieve/storage/data/sieve-data-script.c
@@ -0,0 +1,94 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str.h"
+#include "strfuncs.h"
+#include "istream.h"
+
+#include "sieve-common.h"
+#include "sieve-error.h"
+#include "sieve-dump.h"
+#include "sieve-binary.h"
+
+#include "sieve-data-storage.h"
+
+/*
+ * Script data implementation
+ */
+
+static struct sieve_data_script *sieve_data_script_alloc(void)
+{
+	struct sieve_data_script *dscript;
+	pool_t pool;
+
+	pool = pool_alloconly_create("sieve_data_script", 1024);
+	dscript = p_new(pool, struct sieve_data_script, 1);
+	dscript->script = sieve_data_script;
+	dscript->script.pool = pool;
+
+	return dscript;
+}
+
+struct sieve_script *sieve_data_script_create_from_input
+(struct sieve_instance *svinst, const char *name, struct istream *input)
+{
+	struct sieve_storage *storage;
+	struct sieve_data_script *dscript = NULL;
+
+	storage = sieve_storage_alloc(svinst, &sieve_data_storage, "", 0, FALSE);
+
+	dscript = sieve_data_script_alloc();
+	sieve_script_init(&dscript->script,
+		storage, &sieve_data_script, "data:", name);
+
+	dscript->data = input;
+	i_stream_ref(dscript->data);
+
+	sieve_storage_unref(&storage);
+
+	dscript->script.open = TRUE;
+
+	return &dscript->script;
+}
+
+static void sieve_data_script_destroy(struct sieve_script *script)
+{
+	struct sieve_data_script *dscript =
+		(struct sieve_data_script *)script;
+
+	i_stream_unref(&dscript->data);
+}
+
+static int sieve_data_script_get_stream
+(struct sieve_script *script, struct istream **stream_r,
+	enum sieve_error *error_r)
+{
+	struct sieve_data_script *dscript =
+		(struct sieve_data_script *)script;
+
+	i_stream_ref(dscript->data);
+	i_stream_seek(dscript->data, 0);
+
+	*stream_r = dscript->data;
+	*error_r = SIEVE_ERROR_NONE;
+	return 0;
+}
+
+static bool sieve_data_script_equals
+(const struct sieve_script *script ATTR_UNUSED,
+	const struct sieve_script *other ATTR_UNUSED)
+{
+	return ( script == other );
+}
+
+const struct sieve_script sieve_data_script = {
+	.driver_name = SIEVE_DATA_STORAGE_DRIVER_NAME,
+	.v = {
+		.destroy = sieve_data_script_destroy,
+
+		.get_stream = sieve_data_script_get_stream,
+
+		.equals = sieve_data_script_equals
+	}
+};
diff --git a/src/lib-sieve/storage/data/sieve-data-storage.c b/src/lib-sieve/storage/data/sieve-data-storage.c
new file mode 100644
index 000000000..21b4f3511
--- /dev/null
+++ b/src/lib-sieve/storage/data/sieve-data-storage.c
@@ -0,0 +1,47 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+
+#include "sieve-common.h"
+#include "sieve-error.h"
+
+#include "sieve-data-storage.h"
+
+/*
+ * Storage class
+ */
+
+static struct sieve_storage *sieve_data_storage_alloc(void)
+{
+	struct sieve_data_storage *dstorage;
+	pool_t pool;
+
+	pool = pool_alloconly_create("sieve_data_storage", 1024);
+	dstorage = p_new(pool, struct sieve_data_storage, 1);
+	dstorage->storage = sieve_data_storage;
+	dstorage->storage.pool = pool;
+
+	return &dstorage->storage;
+}
+
+static int sieve_data_storage_init
+(struct sieve_storage *storage ATTR_UNUSED,
+	const char *const *options ATTR_UNUSED,
+	enum sieve_error *error_r ATTR_UNUSED)
+{
+	return 0;
+}
+
+/*
+ * Driver definition
+ */
+
+const struct sieve_storage sieve_data_storage = {
+	.driver_name = SIEVE_DATA_STORAGE_DRIVER_NAME,
+	.version = 0,
+	.v = {
+		.alloc = sieve_data_storage_alloc,
+		.init = sieve_data_storage_init,
+	}
+};
diff --git a/src/lib-sieve/storage/data/sieve-data-storage.h b/src/lib-sieve/storage/data/sieve-data-storage.h
new file mode 100644
index 000000000..a200e2595
--- /dev/null
+++ b/src/lib-sieve/storage/data/sieve-data-storage.h
@@ -0,0 +1,30 @@
+#ifndef SIEVE_DATA_STORAGE_H
+#define SIEVE_DATA_STORAGE_H
+
+#include "sieve.h"
+#include "sieve-script-private.h"
+#include "sieve-storage-private.h"
+
+/*
+ * Storage class
+ */
+
+struct sieve_data_storage {
+	struct sieve_storage storage;
+};
+
+/*
+ * Script class
+ */
+
+struct sieve_data_script {
+	struct sieve_script script;
+
+	struct istream *data;
+};
+
+struct sieve_script *sieve_data_script_create_from_input
+	(struct sieve_instance *svinst, const char *name,
+		struct istream *input);
+
+#endif
-- 
GitLab