dovecot-2.2-pigeonhole: lib-sieve: storage: Implemented magic to...
pigeonhole at rename-it.nl
pigeonhole at rename-it.nl
Wed May 6 22:05:10 UTC 2015
details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/70a3e6c5bb1f
changeset: 2044:70a3e6c5bb1f
user: Stephan Bosch <stephan at rename-it.nl>
date: Wed May 06 23:58:57 2015 +0200
description:
lib-sieve: storage: Implemented magic to make sieve_default script visible in main storage (e.g. from ManageSieve).
diffstat:
INSTALL | 49 ++-
src/lib-sieve/sieve-script.c | 142 ++++++-
src/lib-sieve/sieve-script.h | 16 +-
src/lib-sieve/sieve-storage-private.h | 23 +-
src/lib-sieve/sieve-storage.c | 370 +++++++++++++++++-
src/lib-sieve/sieve-storage.h | 9 +
src/lib-sieve/storage/file/sieve-file-storage-save.c | 74 ++-
src/lib-sieve/storage/file/sieve-file-storage.c | 1 +
src/lib-sieve/storage/file/sieve-file-storage.h | 10 +-
src/plugins/lda-sieve/lda-sieve-plugin.c | 117 +-----
10 files changed, 627 insertions(+), 184 deletions(-)
diffs (truncated from 1281 to 300 lines):
diff -r a3d26f12c2cd -r 70a3e6c5bb1f INSTALL
--- a/INSTALL Tue May 05 13:42:38 2015 +0200
+++ b/INSTALL Wed May 06 23:58:57 2015 +0200
@@ -126,6 +126,11 @@
Multiple mail users can share a single script directory if the script
location is the same and all users share the same system credentials (uid,
gid).
+
+ default=<script-name>
+ The name by which the default Sieve script (see `sieve_default=' setting
+ below) is visible to ManageSieve clients. Normally, it is not visible at
+ all. See "Visible Default Script" section below for more information.
Sieve Interpreter - Basic Configuration
---------------------------------------
@@ -166,7 +171,9 @@
/var/lib/dovecot/default.sieve. This is usually a global script, so be sure
to pre-compile this script manually using the sievec command line tool, as
explained in the README file. This setting used to be called
- `sieve_global_path', but that name is now deprecated.
+ `sieve_global_path', but that name is now deprecated. See the "Visible
+ Default Script" section below for information on how to make the default
+ script visible from ManageSieve.
sieve_global =
Location for :global include scripts for the Sieve include extension. This
@@ -388,6 +395,46 @@
to store the compiled binaries. In that case, be sure to manually pre-compile
those scripts using the sievec tool, as explained in the README file.
+Sieve Interpreter - Visible Default Script
+------------------------------------------
+
+The `sieve_default=' setting specifies the location of a default script that
+is executed when the user has no active personal script. Normally, this
+default script is invisible to the user; i.e., it is not listed in ManageSieve.
+To give the user the ability to base a custom personal script on the default
+script, it is possible to make it visible under a specific configurable name.
+
+ManageSieve will magically list the default script under that name, even though
+it does not actually exist in the user's normal script storage location. This
+way, the ManageSieve client can see that it exists and it can retrieve its
+contents. If no normal script is active, the default is always listed as active.
+The user can replace the default with a custom script, by uploading it under the
+default script's name. If that custom script is ever deleted, the default script
+will reappear from the shadows implicitly.
+
+This way, ManageSieve clients will not need any special handling for this
+feature. If the name of the default script is equal to the name the client uses
+for the main script, it will initially see and read the default script when the
+user account is freshly created. The user can edit the script, and when the
+edited script is saved through the ManageSieve client, it will will override the
+default script. If the user ever wants to revert to the default, the user only
+needs to delete the edited script and the default will reappear.
+
+To enable this feature, the the `;default=<script-name>' option must be
+specified for the `sieve=' setting. It configures the name by which the default
+script will be known. Of course, the `sieve_default=' setting needs to point to
+a valid script location as well for this to work. If the default script does not
+exist at the indicated location, it is not shown.
+
+For example:
+
+plugin {
+...
+ sieve = file:~/sieve;active=~/.dovecot.sieve;default=roundcube
+
+ sieve_default = /var/lib/dovecot/sieve/default.sieve
+}
+
Sieve Interpreter - Extension Configuration
-------------------------------------------
diff -r a3d26f12c2cd -r 70a3e6c5bb1f src/lib-sieve/sieve-script.c
--- a/src/lib-sieve/sieve-script.c Tue May 05 13:42:38 2015 +0200
+++ b/src/lib-sieve/sieve-script.c Wed May 06 23:58:57 2015 +0200
@@ -219,6 +219,24 @@
return script;
}
+int sieve_script_check
+(struct sieve_instance *svinst, const char *location, const char *name,
+ enum sieve_error *error_r)
+{
+ struct sieve_script *script;
+ enum sieve_error error;
+
+ if (error_r == NULL)
+ error_r = &error;
+
+ script = sieve_script_create_open(svinst, location, name, error_r);
+ if (script == NULL)
+ return ( *error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
+
+ sieve_script_unref(&script);
+ return 1;
+}
+
/*
* Properties
*/
@@ -261,6 +279,11 @@
return script->open;
}
+bool sieve_script_is_default(const struct sieve_script *script)
+{
+ return script->storage->is_default;
+}
+
/*
* Stream management
*/
@@ -525,15 +548,65 @@
return -1;
}
- i_assert( (script->storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
i_assert( script->open ); // FIXME: auto-open?
- i_assert( script->v.rename != NULL );
- ret = script->v.rename(script, newname);
+ if ( storage->default_for == NULL ) {
+ i_assert( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
- /* rename INBOX mailbox attribute */
- if ( ret >= 0 && oldname != NULL )
- (void)sieve_storage_sync_script_rename(storage, oldname, newname);
+ /* rename script */
+ i_assert( script->v.rename != NULL );
+ ret = script->v.rename(script, newname);
+
+ /* rename INBOX mailbox attribute */
+ if ( ret >= 0 && oldname != NULL )
+ (void)sieve_storage_sync_script_rename(storage, oldname, newname);
+
+ } else if ( sieve_storage_check_script
+ (storage->default_for, newname, NULL) > 0 ) {
+ sieve_script_set_error(script, SIEVE_ERROR_EXISTS,
+ "A sieve script with that name already exists.");
+ sieve_storage_copy_error(storage->default_for, storage);
+ ret = -1;
+
+ } else {
+ struct istream *input;
+
+ /* copy from default */
+ if ( (ret=sieve_script_open(script, NULL)) >= 0 &&
+ (ret=sieve_script_get_stream(script, &input, NULL)) >= 0 ) {
+ ret = sieve_storage_save_as
+ (storage->default_for, input, newname);
+
+ if ( ret < 0 ) {
+ sieve_storage_copy_error(storage, storage->default_for);
+
+ } else if ( sieve_script_is_active(script) > 0 ) {
+ struct sieve_script *newscript;
+ enum sieve_error error;
+
+ newscript = sieve_storage_open_script
+ (storage->default_for, newname, &error);
+ if ( newscript == NULL ) {
+ /* Somehow not actually saved */
+ ret = ( error == SIEVE_ERROR_NOT_FOUND ? 0 : -1 );
+ } else if ( sieve_script_activate(newscript, (time_t)-1) < 0 ) {
+ /* Failed to activate; roll back */
+ ret = -1;
+ (void)sieve_script_delete(newscript);
+ sieve_script_unref(&newscript);
+ }
+
+ if (ret < 0) {
+ sieve_storage_sys_error(storage,
+ "Failed to implicitly activate script `%s' "
+ "after rename", newname);
+ sieve_storage_copy_error(storage->default_for, storage);
+ }
+ }
+ } else {
+ sieve_storage_copy_error(storage->default_for, storage);
+ }
+ }
return ret;
}
@@ -543,19 +616,28 @@
struct sieve_storage *storage = script->storage;
int ret = 0;
- i_assert( (script->storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
i_assert( script->open ); // FIXME: auto-open?
/* Is the requested script active? */
- if ( sieve_script_is_active(script) ) {
+ if ( sieve_script_is_active(script) > 0 ) {
sieve_script_set_error(script, SIEVE_ERROR_ACTIVE,
"Cannot delete the active Sieve script.");
- ret = -1;
- } else {
- i_assert( script->v.delete != NULL );
- ret = script->v.delete(script);
+ if (storage->default_for != NULL)
+ sieve_storage_copy_error(storage->default_for, storage);
+ return -1;
}
+ /* Trying to delete the default script? */
+ if ( storage->is_default ) {
+ /* ignore */
+ return 0;
+ }
+
+ i_assert( (script->storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
+
+ i_assert( script->v.delete != NULL );
+ ret = script->v.delete(script);
+
/* unset INBOX mailbox attribute */
if ( ret >= 0 )
(void)sieve_storage_sync_script_delete(storage, script->name);
@@ -564,6 +646,17 @@
int sieve_script_is_active(struct sieve_script *script)
{
+ struct sieve_storage *storage = script->storage;
+
+ /* Special handling if this is a default script */
+ if ( storage->default_for != NULL ) {
+ int ret = sieve_storage_active_script_is_default
+ (storage->default_for);
+ if (ret < 0)
+ sieve_storage_copy_error(storage, storage->default_for);
+ return ret;
+ }
+
if ( script->v.is_active == NULL )
return 0;
return script->v.is_active(script);
@@ -572,17 +665,28 @@
int sieve_script_activate(struct sieve_script *script, time_t mtime)
{
struct sieve_storage *storage = script->storage;
- int ret;
+ int ret = 0;
- i_assert( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
i_assert( script->open ); // FIXME: auto-open?
- i_assert( script->v.activate != NULL );
- ret = script->v.activate(script);
+ if (storage->default_for == NULL) {
+ i_assert( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 );
+
+ i_assert( script->v.activate != NULL );
+ ret = script->v.activate(script);
- if (ret >= 0) {
- sieve_storage_set_modified(storage, mtime);
- (void)sieve_storage_sync_script_activate(storage);
+ if (ret >= 0) {
+ sieve_storage_set_modified(storage, mtime);
+ (void)sieve_storage_sync_script_activate(storage);
+ }
+
+ } else {
+ /* Activating the default script is equal to deactivating
+ the storage */
+ ret = sieve_storage_deactivate
+ (storage->default_for, (time_t)-1);
+ if (ret < 0)
+ sieve_storage_copy_error(storage, storage->default_for);
}
return ret;
diff -r a3d26f12c2cd -r 70a3e6c5bb1f src/lib-sieve/sieve-script.h
--- a/src/lib-sieve/sieve-script.h Tue May 05 13:42:38 2015 +0200
+++ b/src/lib-sieve/sieve-script.h Wed May 06 23:58:57 2015 +0200
@@ -50,13 +50,17 @@
(struct sieve_script *script, enum sieve_error *error_r)
ATTR_NULL(2);
int sieve_script_open_as
- (struct sieve_script *script, const char *name, enum sieve_error *error_r)
- ATTR_NULL(3);
+ (struct sieve_script *script, const char *name,
+ enum sieve_error *error_r) ATTR_NULL(3);
struct sieve_script *sieve_script_create_open
- (struct sieve_instance *svinst, const char *location, const char *name,
- enum sieve_error *error_r)
- ATTR_NULL(3,4);
+ (struct sieve_instance *svinst, const char *location,
+ const char *name, enum sieve_error *error_r)
+ ATTR_NULL(3, 4);
+int sieve_script_check
+ (struct sieve_instance *svinst, const char *location,
+ const char *name, enum sieve_error *error_r)
+ ATTR_NULL(3, 4);
/*
* Binary
More information about the dovecot-cvs
mailing list