1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2  */
3 
4 #include "lib.h"
5 #include "array.h"
6 #include "str-sanitize.h"
7 #include "home-expand.h"
8 #include "eacces-error.h"
9 #include "mkdir-parents.h"
10 #include "ioloop.h"
11 #include "mail-storage-private.h"
12 
13 #include "sieve-common.h"
14 #include "sieve-settings.h"
15 #include "sieve-error-private.h"
16 
17 #include "sieve-script-private.h"
18 #include "sieve-storage-private.h"
19 
20 /*
21  * Synchronization
22  */
23 
sieve_storage_sync_init(struct sieve_storage * storage,struct mail_user * user)24 int sieve_storage_sync_init
25 (struct sieve_storage *storage, struct mail_user *user)
26 {
27 	enum sieve_storage_flags sflags = storage->flags;
28 
29 	if ( (sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
30 		(sflags & SIEVE_STORAGE_FLAG_READWRITE) == 0 )
31 		return 0;
32 
33 	if ( !storage->allows_synchronization ) {
34 		if ( (sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 )
35 			return -1;
36 		return 0;
37 	}
38 
39 	e_debug(storage->event, "sync: Synchronization active");
40 
41 	storage->sync_inbox_ns = mail_namespace_find_inbox(user->namespaces);
42 	return 0;
43 }
44 
sieve_storage_sync_deinit(struct sieve_storage * storage ATTR_UNUSED)45 void sieve_storage_sync_deinit
46 (struct sieve_storage *storage ATTR_UNUSED)
47 {
48 	/* nothing */
49 }
50 
51 /*
52  * Sync attributes
53  */
54 
sieve_storage_sync_transaction_begin(struct sieve_storage * storage,struct mailbox_transaction_context ** trans_r)55 static int sieve_storage_sync_transaction_begin
56 (struct sieve_storage *storage, struct mailbox_transaction_context **trans_r)
57 {
58 	enum mailbox_flags mflags = MAILBOX_FLAG_IGNORE_ACLS;
59 	struct mail_namespace *ns = storage->sync_inbox_ns;
60 	struct mailbox *inbox;
61 	enum mail_error error;
62 
63 	if (ns == NULL)
64 		return 0;
65 
66 	inbox = mailbox_alloc(ns->list, "INBOX", mflags);
67 	if (mailbox_open(inbox) < 0) {
68 		e_warning(storage->event, "sync: "
69 			  "Failed to open user INBOX for attribute modifications: %s",
70 			  mailbox_get_last_internal_error(inbox, &error));
71 		mailbox_free(&inbox);
72 		return -1;
73 	}
74 
75 	*trans_r = mailbox_transaction_begin(inbox,
76 					     MAILBOX_TRANSACTION_FLAG_EXTERNAL,
77 					     __func__);
78 	return 1;
79 }
80 
sieve_storage_sync_transaction_finish(struct sieve_storage * storage,struct mailbox_transaction_context ** trans)81 static int sieve_storage_sync_transaction_finish
82 (struct sieve_storage *storage, struct mailbox_transaction_context **trans)
83 {
84 	struct mailbox *inbox;
85 	int ret;
86 
87 	inbox = mailbox_transaction_get_mailbox(*trans);
88 
89 	if ((ret=mailbox_transaction_commit(trans)) < 0) {
90 		enum mail_error error;
91 
92 		e_warning(storage->event, "sync: "
93 			  "Failed to update INBOX attributes: %s",
94 			   mail_storage_get_last_error(
95 				mailbox_get_storage(inbox), &error));
96 	}
97 
98 	mailbox_free(&inbox);
99 	return ret;
100 }
101 
sieve_storage_sync_script_save(struct sieve_storage * storage,const char * name)102 int sieve_storage_sync_script_save
103 (struct sieve_storage *storage, const char *name)
104 {
105 	struct mailbox_transaction_context *trans;
106 	const char *key;
107 	int ret;
108 
109 	if ((ret=sieve_storage_sync_transaction_begin
110 		(storage, &trans)) <= 0)
111 		return ret;
112 
113 	key = t_strconcat
114 		(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL);
115 
116 	mail_index_attribute_set(trans->itrans, TRUE, key, ioloop_time, 0);
117 
118 	return sieve_storage_sync_transaction_finish(storage, &trans);
119 }
120 
sieve_storage_sync_script_rename(struct sieve_storage * storage,const char * oldname,const char * newname)121 int sieve_storage_sync_script_rename
122 (struct sieve_storage *storage, const char *oldname,
123 	const char *newname)
124 {
125 	struct mailbox_transaction_context *trans;
126 	const char *oldkey, *newkey;
127 	int ret;
128 
129 	if ((ret=sieve_storage_sync_transaction_begin
130 		(storage, &trans)) <= 0)
131 		return ret;
132 
133 	oldkey = t_strconcat
134 		(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, oldname, NULL);
135 	newkey = t_strconcat
136 		(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, newname, NULL);
137 
138 	mail_index_attribute_unset(trans->itrans, TRUE, oldkey, ioloop_time);
139 	mail_index_attribute_set(trans->itrans, TRUE, newkey, ioloop_time, 0);
140 
141 	return sieve_storage_sync_transaction_finish(storage, &trans);
142 }
143 
sieve_storage_sync_script_delete(struct sieve_storage * storage,const char * name)144 int sieve_storage_sync_script_delete
145 (struct sieve_storage *storage, const char *name)
146 {
147 	struct mailbox_transaction_context *trans;
148 	const char *key;
149 	int ret;
150 
151 	if ((ret=sieve_storage_sync_transaction_begin
152 		(storage, &trans)) <= 0)
153 		return ret;
154 
155 	key = t_strconcat
156 		(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL);
157 
158 	mail_index_attribute_unset(trans->itrans, TRUE, key, ioloop_time);
159 
160 	return sieve_storage_sync_transaction_finish(storage, &trans);
161 }
162 
sieve_storage_sync_script_activate(struct sieve_storage * storage)163 int sieve_storage_sync_script_activate
164 (struct sieve_storage *storage)
165 {
166 	struct mailbox_transaction_context *trans;
167 	int ret;
168 
169 	if ((ret=sieve_storage_sync_transaction_begin
170 		(storage, &trans)) <= 0)
171 		return ret;
172 
173 	mail_index_attribute_set(trans->itrans,
174 		TRUE, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT, ioloop_time, 0);
175 
176 	return sieve_storage_sync_transaction_finish(storage, &trans);
177 }
178 
sieve_storage_sync_deactivate(struct sieve_storage * storage)179 int sieve_storage_sync_deactivate
180 (struct sieve_storage *storage)
181 {
182 	struct mailbox_transaction_context *trans;
183 	int ret;
184 
185 	if ((ret=sieve_storage_sync_transaction_begin
186 		(storage, &trans)) <= 0)
187 		return ret;
188 
189 	mail_index_attribute_unset(trans->itrans,
190 		TRUE, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT, ioloop_time);
191 
192 	return sieve_storage_sync_transaction_finish(storage, &trans);
193 }
194 
195 
196