]>
Commit | Line | Data |
---|---|---|
b40388bb MT |
1 | diff -Naur cyrus-imapd-2.2.12/README.autocreate cyrus-imapd-2.2.12.autocreate2/README.autocreate |
2 | --- cyrus-imapd-2.2.12/README.autocreate 1970-01-01 02:00:00.000000000 +0200 | |
3 | +++ cyrus-imapd-2.2.12.autocreate2/README.autocreate 2005-10-19 14:48:57.930991000 +0300 | |
4 | @@ -0,0 +1,181 @@ | |
5 | +Cyrus IMAP autocreate Inbox patch | |
6 | +---------------------------------- | |
7 | + | |
8 | +NOTE : This patch has been created at the University of Athens. For more info, as well | |
9 | +as more patches on Cyrus IMAPD server, please visit http://email.uoa.gr | |
10 | + | |
11 | +The design of Cyrus IMAP server does not predict the automatic creation of users' | |
12 | +INBOX folders. The creation of a user's INBOX is considered to be an external task, | |
13 | +that has to be completed as part of the user e-mail account creation procedure. | |
14 | +Hence, to create a new e-mail account the site administrator has to | |
15 | +a) Include the new account in the user database for the authentication procedure | |
16 | + (e.g. sasldb, shadow, mysql, ldap). | |
17 | +b) Create the corresponding INBOX folder. | |
18 | + | |
19 | +Alternatively, the user, if succesfully authenticated, may create his own INBOX folder, | |
20 | +as long as the configuration of the site allows it (see "autocreatequota" in imapd.conf). | |
21 | +Unlike what uncareful readers may think, enabling the "autocreatequota" option, doesn't | |
22 | +lead to the automatic INBOX folder creation by Cyrus IMAP server. | |
23 | +In fact, "autocreate" means that the IMAP clients are allowed to automatically create | |
24 | +the user INBOX. | |
25 | + | |
26 | +This patch adds the functionality of automatic creation of the users' INBOX folders into | |
27 | +the Cyrus IMAP server. It is implemented as two features, namely the "create on login" | |
28 | +and "create on post". | |
29 | + | |
30 | + | |
31 | + | |
32 | +Create on login | |
33 | +=============== | |
34 | +This feauture provides automatic creation of a user's INBOX folder when all of the | |
35 | +following requirements are met: | |
36 | + | |
37 | +i) The user has succesfully passed the authentication procedure. | |
38 | + | |
39 | +ii) The user's authorization ID (typically the same as the user's | |
40 | +authentication ID) doesn't belong to the imap_admins or admins | |
41 | +accounts (see imapd.conf). | |
42 | + | |
43 | +iii) The "autocreatequota" option in the imap configuration file | |
44 | +has been set to a non zero value. | |
45 | + | |
46 | +iv) The corresponding to the user's authorizationID INBOX folder | |
47 | +does not exist. | |
48 | + | |
49 | +The user's first login is the most typical case when all four requirements are met. | |
50 | +Note that if the authenticatedID is allowed to proxy to another account for which | |
51 | +all of the above requirements are met, the corresponding INBOX folder for that account | |
52 | +will be created. | |
53 | + | |
54 | + | |
55 | + | |
56 | +Create on post | |
57 | +============== | |
58 | +This feauture provides automatic creation of a user's INBOX folder when all of the | |
59 | +following requirements are met. | |
60 | + | |
61 | +i) An e-mail message addressed to the user has been received. | |
62 | + | |
63 | +ii) The recipient is not any of the imap_admins or admins accounts. | |
64 | +Note that passing e-mails to admins or imap_admins accounts from | |
65 | +the MTA to LMTP should be avoided in any case. | |
66 | + | |
67 | +iii) The recipient's INBOX does not exist. | |
68 | + | |
69 | +iv) The "autocreatequota" option in the imap configuration file | |
70 | +has been set to a non zero value. | |
71 | + | |
72 | +v) The "createonpost" option in the imap configuration file | |
73 | +has been switched on. | |
74 | + | |
75 | + | |
76 | +Besides the automatic creation of INBOX folder, additional functionalities are | |
77 | +provided: | |
78 | + | |
79 | +A) Automatic creation of INBOX subfolders controlled by "autocreateinboxfolders" | |
80 | +configuration option. eg | |
81 | + | |
82 | +autocreateinboxfolders: sent|drafts|spam|templates | |
83 | + | |
84 | +B) Automatic subscription of INBOX subfolders controlled by "autosubscribeinboxfolders" | |
85 | +configuration option. eg | |
86 | + | |
87 | +autosubscribeinboxfolders: sent|spam | |
88 | + | |
89 | +Obviously, only subscription to subfolders included in the "autocreateinboxfolder" | |
90 | +list is meaningfull. | |
91 | + | |
92 | +C) Automatic subscription to shared folders (bulletin boards). The user gets | |
93 | +automatically subscribed to the shared folders declared in the "autosubscribesharedfolders" | |
94 | +configuration option in imapd.conf. | |
95 | +eg autosubscribesharedfolders: public_folder | public_folder.subfolder | |
96 | + | |
97 | +In order the above action to succeed, the shared folder has to pre-exist the INBOX creation | |
98 | +and the user must have the apropriate permissions in order to be able to subscribe to the | |
99 | +shared folder. | |
100 | + | |
101 | +* A new config option has been added. 'autosubscribe_all_sharedfolders' is a yes/no | |
102 | +option. When set to yes, the user is automatically subscribed to all shared folders one | |
103 | +has permission to subscribe to. Please, note that when this option is set to yes, then | |
104 | +'autosubscribesharedfolders' option is overriden. | |
105 | + | |
106 | +D) Automatic creation of a predefined default sieve script. | |
107 | + | |
108 | +This is very useful when a default sieve script is used for every user. Usually, a | |
109 | +default anti-spam script may me be written in a file and copied to each user | |
110 | +sieve scripts upon the INBOX creation. The imapd.conf options that have been added | |
111 | +are 'autocreate_sieve_script', 'autocreate_sieve_compiledscript' and | |
112 | +'generate_compiled_sieve_script'. | |
113 | + | |
114 | +autocreate_sieve_script configuration option refers to the full path of the file | |
115 | +that contains the sieve script. The default value is null and if no file is defined, | |
116 | +then no default script is created upon INBOX creation. (The feature is disabled) | |
117 | +eg autocreate_sieve_script: /etc/default_sieve_script | |
118 | + | |
119 | +autocreate_sieve_compiledscript configuration option refers to the full path of the | |
120 | +file that contains the bytecode compiled sieve script. If this filename is defined | |
121 | +in imapd.conf and the file exists, then it is automatically copied in the user's sieve | |
122 | +directory. If it is not defined, then a bytecode sieve script gets on the fly compiled | |
123 | +by the daemon. | |
124 | +eg autocreate_sieve_compiledscript: /etc/default_sieve_script.bc | |
125 | + | |
126 | +generate_compiled_sieve_script is a boolean option that triggers the compilation of the | |
127 | +source sieve script to bytecode sieve script. The file that the bytecode script will | |
128 | +be saved is pointed by autocreate_sieve_compiledscript. | |
129 | + | |
130 | +Ways of compiling a sieve script : | |
131 | +1. Compile a sieve script using the standard sievec utility, distributed by CMU | |
132 | +2. Compile a sieve script using the compile_sieve utility, released by UoA. This | |
133 | + tool is almost identical to the sievec utility, with the difference that it | |
134 | + reads the input and output file from autocreate_sieve_script and | |
135 | + autocreate_sieve_compiledscript options in imapd.conf | |
136 | +3. Let cyrus create a compiled sieve script using a source script. Cyrus can be | |
137 | + instructed to save the compiled script any time a compiled script does not exist. | |
138 | + | |
139 | +NOTES : | |
140 | +1. In order this functionality to work, the following requirements must have been met: | |
141 | + - 'sieveusehomedir' option must be 'no' in the configuration (default). | |
142 | + - 'sievedir' option must have a valid value. | |
143 | +2. Currently, this patch checks the validity of the source script while generating a | |
144 | + bytecode compiled script, but not the validity of the bytecode sieve script file. | |
145 | + The administrator should make sure that the provided files contain a valid sieve | |
146 | + script as well as the compiled script is updated every time the source script changes. | |
147 | + | |
148 | + | |
149 | + | |
150 | +Issues to be considered | |
151 | +======================= | |
152 | + | |
153 | +I) In order to use the create on post feauture one should be absolutely sure that: | |
154 | +a) The MTA checks the validity of the e-mail recipient before sending the e-mail to | |
155 | +LMTP. This is an RFC821 requirement. This usually expands to "the mta should be | |
156 | +able to use the account database as user mailbox database". | |
157 | +b) Only authorized accounts/services can talk to LMTP. | |
158 | + | |
159 | +II) Especially in the case of imap logins, the current patch implementation checks | |
160 | +for the INBOX folder existence upon login, causing an extra mailbox lookup in most | |
161 | +of the cases. | |
162 | +A better approach would be to chase the "IMAP_MAILBOX_NONEXISTENT" error code and | |
163 | +check if the error is associated with an INBOX folder. However, this would mess up | |
164 | +Cyrus code. The way it was implemented may not have been the most performance | |
165 | +optimized, but it produces a much cleaner and simple patch. | |
166 | + | |
167 | + | |
168 | + | |
169 | +Virtual Domains Support | |
170 | +======================= | |
171 | + | |
172 | +Virtual domains are supported by all versions of the patch for cyrus-imapd-2.2.1-BETA and | |
173 | +later. However, it is not possible to declare different INBOX subfolders to be created or | |
174 | +shared folders to be subscribed to for every domain. | |
175 | + | |
176 | + | |
177 | + | |
178 | +Things to be done | |
179 | +================= | |
180 | + | |
181 | +1. Support MURDER architecture. | |
182 | + | |
183 | + | |
184 | +For more information and updates please visit http://email.uoa.gr/autocreate | |
185 | + | |
186 | diff -Naur cyrus-imapd-2.2.12/imap/Makefile.in cyrus-imapd-2.2.12.autocreate2/imap/Makefile.in | |
187 | --- cyrus-imapd-2.2.12/imap/Makefile.in 2004-05-28 21:03:02.000000000 +0300 | |
188 | +++ cyrus-imapd-2.2.12.autocreate2/imap/Makefile.in 2005-10-19 14:48:57.935240000 +0300 | |
189 | @@ -104,7 +104,7 @@ | |
190 | convert_code.o duplicate.o saslclient.o saslserver.o signals.o \ | |
191 | annotate.o search_engines.o squat.o squat_internal.o mbdump.o \ | |
192 | imapparse.o telemetry.o user.o notify.o protocol.o quota_db.o \ | |
193 | - $(SEEN) $(IDLE) | |
194 | + autosieve.o $(SEEN) $(IDLE) | |
195 | ||
196 | IMAPDOBJS=pushstats.o backend.o imapd.o index.o tls.o version.o | |
197 | ||
198 | @@ -122,7 +122,7 @@ | |
199 | fud smmapd reconstruct quota mbpath ipurge \ | |
200 | cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \ | |
201 | ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \ | |
202 | - @IMAP_PROGS@ | |
203 | + compile_sieve @IMAP_PROGS@ | |
204 | ||
205 | BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \ | |
206 | lmtpstats.c lmtpstats.h xversion.h mupdate_err.c mupdate_err.h \ | |
207 | @@ -188,7 +188,7 @@ | |
208 | ### Services | |
209 | idled: idled.o mutex_fake.o libimap.a $(DEPLIBS) | |
210 | $(CC) $(LDFLAGS) -o idled \ | |
211 | - idled.o mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) | |
212 | + idled.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
213 | ||
214 | lmtpd: lmtpd.o $(LMTPOBJS) $(SIEVE_OBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) \ | |
215 | $(DEPLIBS) $(SERVICE) | |
216 | @@ -214,10 +214,10 @@ | |
217 | $(SERVICE) lmtpproxyd.o backend.o $(LMTPOBJS) mutex_fake.o \ | |
218 | libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
219 | ||
220 | -imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) | |
221 | +imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) | |
222 | $(CC) $(LDFLAGS) -o imapd \ | |
223 | $(SERVICE) $(IMAPDOBJS) mutex_fake.o \ | |
224 | - libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
225 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
226 | ||
227 | imapd.pure: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) | |
228 | $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \ | |
229 | @@ -232,7 +232,7 @@ | |
230 | proxyd: $(PROXYDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) | |
231 | $(CC) $(LDFLAGS) -o proxyd \ | |
232 | $(SERVICE) $(PROXYDOBJS) mutex_fake.o libimap.a \ | |
233 | - $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
234 | + $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
235 | ||
236 | proxyd.pure: $(PROXYDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) | |
237 | $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o proxyd.pure \ | |
238 | @@ -244,7 +244,7 @@ | |
239 | $(CC) $(LDFLAGS) -o mupdate \ | |
240 | $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \ | |
241 | mutex_pthread.o tls.o libimap.a \ | |
242 | - $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread | |
243 | + $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread | |
244 | ||
245 | mupdate.pure: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o \ | |
246 | libimap.a $(DEPLIBS) | |
247 | @@ -252,92 +252,96 @@ | |
248 | $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \ | |
249 | mutex_pthread.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread | |
250 | ||
251 | -pop3d: pop3d.o backend.o tls.o mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) | |
252 | +pop3d: pop3d.o backend.o tls.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) | |
253 | $(CC) $(LDFLAGS) -o pop3d pop3d.o backend.o tls.o $(SERVICE) \ | |
254 | - mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
255 | + mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
256 | ||
257 | nntpd: nntpd.o backend.o index.o smtpclient.o spool.o tls.o \ | |
258 | mutex_fake.o nntp_err.o libimap.a $(DEPLIBS) $(SERVICE) | |
259 | $(CC) $(LDFLAGS) -o nntpd nntpd.o backend.o index.o spool.o \ | |
260 | smtpclient.o tls.o $(SERVICE) mutex_fake.o nntp_err.o \ | |
261 | - libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
262 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
263 | ||
264 | -fud: fud.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) | |
265 | +fud: fud.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) | |
266 | $(CC) $(LDFLAGS) -o fud $(SERVICE) fud.o mutex_fake.o libimap.a \ | |
267 | - $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
268 | + $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
269 | ||
270 | -smmapd: smmapd.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) | |
271 | +smmapd: smmapd.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) | |
272 | $(CC) $(LDFLAGS) -o smmapd $(SERVICE) smmapd.o mutex_fake.o libimap.a \ | |
273 | - $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
274 | + $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) | |
275 | ||
276 | ### Command Line Utilities | |
277 | -arbitron: arbitron.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
278 | +arbitron: arbitron.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
279 | $(CC) $(LDFLAGS) -o arbitron arbitron.o $(CLIOBJS) \ | |
280 | - libimap.a $(DEPLIBS) $(LIBS) | |
281 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
282 | + | |
283 | +compile_sieve: compile_sieve.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
284 | + $(CC) $(LDFLAGS) -o compile_sieve compile_sieve.o $(CLIOBJS) \ | |
285 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
286 | ||
287 | -cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(DEPLIBS) | |
288 | +cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
289 | $(CC) $(LDFLAGS) -o cvt_cyrusdb cvt_cyrusdb.o $(CLIOBJS) \ | |
290 | - libimap.a $(DEPLIBS) $(LIBS) | |
291 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
292 | ||
293 | -chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(DEPLIBS) | |
294 | +chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
295 | $(CC) $(LDFLAGS) -o chk_cyrus chk_cyrus.o $(CLIOBJS) \ | |
296 | - libimap.a $(DEPLIBS) $(LIBS) | |
297 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
298 | ||
299 | -deliver: deliver.o backend.o $(LMTPOBJS) mutex_fake.o libimap.a $(DEPLIBS) | |
300 | +deliver: deliver.o backend.o $(LMTPOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
301 | $(CC) $(LDFLAGS) -o deliver deliver.o backend.o $(LMTPOBJS) \ | |
302 | - mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) | |
303 | + mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
304 | ||
305 | -ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
306 | +ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
307 | $(CC) $(LDFLAGS) -o \ | |
308 | - $@ ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
309 | + $@ ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
310 | ||
311 | -ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
312 | +ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
313 | $(CC) $(LDFLAGS) -o $@ ctl_mboxlist.o mupdate-client.o $(CLIOBJS) \ | |
314 | - libimap.a $(DEPLIBS) $(LIBS) | |
315 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
316 | ||
317 | -ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
318 | +ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
319 | $(CC) $(LDFLAGS) -o \ | |
320 | - $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
321 | + $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
322 | ||
323 | -cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
324 | +cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
325 | $(CC) $(LDFLAGS) -o $@ cyr_expire.o $(CLIOBJS) \ | |
326 | - libimap.a $(DEPLIBS) $(LIBS) | |
327 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
328 | ||
329 | -fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
330 | +fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
331 | $(CC) $(LDFLAGS) -o \ | |
332 | - $@ fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
333 | + $@ fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
334 | ||
335 | -squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
336 | +squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
337 | $(CC) $(LDFLAGS) -o squatter squatter.o index.o squat_build.o \ | |
338 | - $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
339 | + $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
340 | ||
341 | -mbpath: mbpath.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
342 | +mbpath: mbpath.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
343 | $(CC) $(LDFLAGS) -o mbpath mbpath.o $(CLIOBJS) libimap.a \ | |
344 | - $(DEPLIBS) $(LIBS) | |
345 | + $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
346 | ||
347 | -ipurge: ipurge.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
348 | +ipurge: ipurge.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
349 | $(CC) $(LDFLAGS) -o ipurge ipurge.o $(CLIOBJS) \ | |
350 | - libimap.a $(DEPLIBS) $(LIBS) | |
351 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
352 | ||
353 | -cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
354 | +cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
355 | $(CC) $(LDFLAGS) -o cyrdump cyrdump.o index.o $(CLIOBJS) \ | |
356 | - libimap.a $(DEPLIBS) $(LIBS) | |
357 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
358 | ||
359 | -mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
360 | +mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
361 | $(CC) $(LDFLAGS) -o \ | |
362 | - mbexamine mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
363 | + mbexamine mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
364 | ||
365 | -reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
366 | +reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
367 | $(CC) $(LDFLAGS) -o \ | |
368 | - reconstruct reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
369 | + reconstruct reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
370 | ||
371 | -quota: quota.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
372 | +quota: quota.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
373 | $(CC) $(LDFLAGS) -o quota quota.o $(CLIOBJS) \ | |
374 | - libimap.a $(DEPLIBS) $(LIBS) | |
375 | + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
376 | ||
377 | -tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) | |
378 | +tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) | |
379 | $(CC) $(LDFLAGS) -o \ | |
380 | - $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) | |
381 | + $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) | |
382 | ||
383 | ### Other Misc Targets | |
384 | ||
385 | diff -Naur cyrus-imapd-2.2.12/imap/autosieve.c cyrus-imapd-2.2.12.autocreate2/imap/autosieve.c | |
386 | --- cyrus-imapd-2.2.12/imap/autosieve.c 1970-01-01 02:00:00.000000000 +0200 | |
387 | +++ cyrus-imapd-2.2.12.autocreate2/imap/autosieve.c 2005-10-19 14:48:57.940098000 +0300 | |
388 | @@ -0,0 +1,587 @@ | |
389 | +#include <stdio.h> | |
390 | +#include <stdlib.h> | |
391 | +#include <string.h> | |
392 | + | |
393 | +#ifdef HAVE_UNISTD_H | |
394 | +#include <unistd.h> | |
395 | +#endif | |
396 | + | |
397 | +#include <errno.h> | |
398 | +#include <sys/types.h> | |
399 | +#include <sys/stat.h> | |
400 | +#include <sys/uio.h> | |
401 | +#include <fcntl.h> | |
402 | +#include <ctype.h> | |
403 | +#include <time.h> | |
404 | +#include <syslog.h> | |
405 | +#include <com_err.h> | |
406 | +#include <config.h> | |
407 | + | |
408 | +#include "global.h" | |
409 | +#include "util.h" | |
410 | +#include "mailbox.h" | |
411 | +#include "imap_err.h" | |
412 | +#include "sieve_interface.h" | |
413 | +#include "script.h" | |
414 | + | |
415 | +#define TIMSIEVE_FAIL -1 | |
416 | +#define TIMSIEVE_OK 0 | |
417 | +#define MAX_FILENAME 1024 | |
418 | + | |
419 | +static int get_script_name(char *sievename, size_t buflen, const char *filename); | |
420 | +static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir); | |
421 | +int autoadd_sieve(char *userid, const char *source_script); | |
422 | + | |
423 | +static void fatal(const char *s, int code); | |
424 | +static void foo(void); | |
425 | +static int sieve_notify(void *ac __attribute__((unused)), | |
426 | + void *interp_context __attribute__((unused)), | |
427 | + void *script_context __attribute__((unused)), | |
428 | + void *message_context __attribute__((unused)), | |
429 | + const char **errmsg __attribute__((unused))); | |
430 | +static int mysieve_error(int lineno, const char *msg, | |
431 | + void *i __attribute__((unused)), void *s); | |
432 | +static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); | |
433 | + | |
434 | + | |
435 | +sieve_vacation_t vacation2 = { | |
436 | + 0, /* min response */ | |
437 | + 0, /* max response */ | |
438 | + (sieve_callback *) &foo, /* autorespond() */ | |
439 | + (sieve_callback *) &foo /* send_response() */ | |
440 | +}; | |
441 | + | |
442 | + | |
443 | +/* | |
444 | + * Find the name of the sieve script | |
445 | + * given the source script and compiled script names | |
446 | + */ | |
447 | +static int get_script_name(char *sievename, size_t buflen, const char *filename) | |
448 | +{ | |
449 | + char *p; | |
450 | + int r; | |
451 | + | |
452 | + p = strrchr(filename, '/'); | |
453 | + if (p == NULL) | |
454 | + p = (char *) filename; | |
455 | + else | |
456 | + p++; | |
457 | + | |
458 | + r = strlcpy(sievename, p, buflen) - buflen; | |
459 | + return (r >= 0 || r == -buflen ? 1 : 0); | |
460 | +} | |
461 | + | |
462 | + | |
463 | +/* | |
464 | + * Find the directory where the sieve scripts of the user | |
465 | + * reside | |
466 | + */ | |
467 | +static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir) | |
468 | +{ | |
469 | + char *user = NULL, *domain = NULL; | |
470 | + | |
471 | + /* Setup the user and the domain */ | |
472 | + if(config_virtdomains && (domain = strchr(userid, '@'))) { | |
473 | + user = (char *) xmalloc((domain - userid +1) * sizeof(char)); | |
474 | + strlcpy(user, userid, domain - userid + 1); | |
475 | + domain++; | |
476 | + } else | |
477 | + user = userid; | |
478 | + | |
479 | + /* Find the dir path where the sieve scripts of the user will reside */ | |
480 | + if (config_virtdomains && domain) { | |
481 | + if(snprintf(sieve_script_dir, buflen, "%s%s%c/%s/%c/%s/", | |
482 | + sieve_dir, FNAME_DOMAINDIR, dir_hash_c(domain), domain, dir_hash_c(user), user) >= buflen) { | |
483 | + free(user); | |
484 | + return 1; | |
485 | + } | |
486 | + } else { | |
487 | + if(snprintf(sieve_script_dir, buflen, "%s/%c/%s/", | |
488 | + sieve_dir, dir_hash_c(user), user) >= buflen) | |
489 | + return 1; | |
490 | + } | |
491 | + | |
492 | + /* Free the xmalloced user memory, reserved above */ | |
493 | + if(user != userid) | |
494 | + free(user); | |
495 | + | |
496 | + return 0; | |
497 | +} | |
498 | + | |
499 | +int autoadd_sieve(char *userid, const char *source_script) | |
500 | +{ | |
501 | + sieve_script_t *s = NULL; | |
502 | + bytecode_info_t *bc = NULL; | |
503 | + char *err = NULL; | |
504 | + FILE *in_stream, *out_fp; | |
505 | + int out_fd, in_fd, r, k; | |
506 | + int do_compile = 0; | |
507 | + const char *sieve_dir = NULL; | |
508 | + const char *compiled_source_script = NULL; | |
509 | + char sievename[MAX_FILENAME]; | |
510 | + char sieve_script_name[MAX_FILENAME]; | |
511 | + char sieve_script_dir[MAX_FILENAME]; | |
512 | + char sieve_bcscript_name[MAX_FILENAME]; | |
513 | + char sieve_default[MAX_FILENAME]; | |
514 | + char sieve_tmpname[MAX_FILENAME]; | |
515 | + char sieve_bctmpname[MAX_FILENAME]; | |
516 | + char sieve_bclink_name[MAX_FILENAME]; | |
517 | + char buf[4096]; | |
518 | + mode_t oldmask; | |
519 | + struct stat statbuf; | |
520 | + | |
521 | + /* We don't support using the homedirectory, like timsieved */ | |
522 | + if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) { | |
523 | + syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf"); | |
524 | + return 1; | |
525 | + } | |
526 | + | |
527 | + /* Check if sievedir is defined in imapd.conf */ | |
528 | + if(!(sieve_dir = config_getstring(IMAPOPT_SIEVEDIR))) { | |
529 | + syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf"); | |
530 | + return 1; | |
531 | + } | |
532 | + | |
533 | + /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */ | |
534 | + if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { | |
535 | + syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it"); | |
536 | + do_compile = 1; | |
537 | + } | |
538 | + | |
539 | + if(get_script_dir(sieve_script_dir, sizeof(sieve_script_dir), userid, sieve_dir)) { | |
540 | + syslog(LOG_WARNING, "autocreate_sieve: Cannot find sieve scripts directory"); | |
541 | + return 1; | |
542 | + } | |
543 | + | |
544 | + if (get_script_name(sievename, sizeof(sievename), source_script)) { | |
545 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve script %s", source_script); | |
546 | + return 1; | |
547 | + } | |
548 | + | |
549 | + if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s%s.script.NEW",sieve_script_dir, sievename) >= sizeof(sieve_tmpname)) { | |
550 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
551 | + return 1; | |
552 | + } | |
553 | + if(snprintf(sieve_bctmpname, sizeof(sieve_bctmpname), "%s%s.bc.NEW",sieve_script_dir, sievename) >= sizeof(sieve_bctmpname)) { | |
554 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
555 | + return 1; | |
556 | + } | |
557 | + if(snprintf(sieve_script_name, sizeof(sieve_script_name), "%s%s.script",sieve_script_dir, sievename) >= sizeof(sieve_script_name)) { | |
558 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
559 | + return 1; | |
560 | + } | |
561 | + if(snprintf(sieve_bcscript_name, sizeof(sieve_bcscript_name), "%s%s.bc",sieve_script_dir, sievename) >= sizeof(sieve_bcscript_name)) { | |
562 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
563 | + return 1; | |
564 | + } | |
565 | + if(snprintf(sieve_default, sizeof(sieve_default), "%s%s",sieve_script_dir,"defaultbc") >= sizeof(sieve_default)) { | |
566 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
567 | + return 1; | |
568 | + } | |
569 | + if(snprintf(sieve_bclink_name, sizeof(sieve_bclink_name), "%s.bc", sievename) >= sizeof(sieve_bclink_name)) { | |
570 | + syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); | |
571 | + return 1; | |
572 | + } | |
573 | + | |
574 | + /* Check if a default sieve filter alrady exists */ | |
575 | + if(!stat(sieve_default,&statbuf)) { | |
576 | + syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists"); | |
577 | + fclose(in_stream); | |
578 | + return 1; | |
579 | + } | |
580 | + | |
581 | + /* Open the source script. if there is a problem with that exit */ | |
582 | + in_stream = fopen(source_script, "r"); | |
583 | + if(!in_stream) { | |
584 | + syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script); | |
585 | + return 1; | |
586 | + } | |
587 | + | |
588 | + | |
589 | + /* | |
590 | + * At this point we start the modifications of the filesystem | |
591 | + */ | |
592 | + | |
593 | + /* Create the directory where the sieve scripts will reside */ | |
594 | + r = cyrus_mkdir(sieve_script_dir, 0755); | |
595 | + if(r == -1) { | |
596 | + /* If this fails we just leave */ | |
597 | + syslog(LOG_WARNING,"autocreate_sieve: Unable to create directory %s. Check permissions",sieve_script_name); | |
598 | + return 1; | |
599 | + } | |
600 | + | |
601 | + /* | |
602 | + * We open the file that will be used as the bc file. If this file exists, overwrite it | |
603 | + * since something bad has happened. We open the file here so that this error checking is | |
604 | + * done before we try to open the rest of the files to start copying etc. | |
605 | + */ | |
606 | + out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | |
607 | + if(out_fd < 0) { | |
608 | + if(errno == EEXIST) { | |
609 | + syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname); | |
610 | + } else if (errno == EACCES) { | |
611 | + syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname); | |
612 | + fclose(in_stream); | |
613 | + return 1; | |
614 | + } else { | |
615 | + syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s. Unknown error",sieve_bctmpname); | |
616 | + fclose(in_stream); | |
617 | + return 1; | |
618 | + } | |
619 | + } | |
620 | + | |
621 | + if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) { | |
622 | + while((r = read(in_fd, buf, sizeof(buf))) > 0) { | |
623 | + if((k=write(out_fd, buf,r)) < 0) { | |
624 | + syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_bctmpname, errno); | |
625 | + close(out_fd); | |
626 | + close(in_fd); | |
627 | + fclose(in_stream); | |
628 | + unlink(sieve_bctmpname); | |
629 | + return 1; | |
630 | + } | |
631 | + } | |
632 | + | |
633 | + if(r == 0) { /* EOF */ | |
634 | + close(out_fd); | |
635 | + close(in_fd); | |
636 | + } else if (r < 0) { | |
637 | + syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file: %s. Will try to compile it", | |
638 | + compiled_source_script); | |
639 | + close(in_fd); | |
640 | + do_compile = 1; | |
641 | + if(lseek(out_fd, 0, SEEK_SET)) { | |
642 | + syslog(LOG_WARNING, "autocreate_sieve: Major IO problem. Aborting"); | |
643 | + return 1; | |
644 | + } | |
645 | + } | |
646 | + close(in_fd); | |
647 | + } else { | |
648 | + if(compiled_source_script) | |
649 | + syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script); | |
650 | + do_compile = 1; | |
651 | + } | |
652 | + | |
653 | + | |
654 | + /* Because we failed to open a precompiled bc sieve script, we compile one */ | |
655 | + if(do_compile) { | |
656 | + if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { | |
657 | + if(err && *err) { | |
658 | + syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err); | |
659 | + free(err); | |
660 | + } else | |
661 | + syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script"); | |
662 | + | |
663 | + unlink(sieve_bctmpname); | |
664 | + fclose(in_stream); | |
665 | + close(out_fd); | |
666 | + return 1; | |
667 | + } | |
668 | + | |
669 | + /* generate the bytecode */ | |
670 | + if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) { | |
671 | + syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script"); | |
672 | + /* removing the copied script and cleaning up memory */ | |
673 | + unlink(sieve_bctmpname); | |
674 | + sieve_script_free(&s); | |
675 | + fclose(in_stream); | |
676 | + close(out_fd); | |
677 | + return 1; | |
678 | + } | |
679 | + | |
680 | + if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) { | |
681 | + syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script"); | |
682 | + /* removing the copied script and cleaning up memory */ | |
683 | + unlink(sieve_bctmpname); | |
684 | + sieve_free_bytecode(&bc); | |
685 | + sieve_script_free(&s); | |
686 | + fclose(in_stream); | |
687 | + close(out_fd); | |
688 | + return 1; | |
689 | + } | |
690 | + | |
691 | + /* clean up the memory */ | |
692 | + sieve_free_bytecode(&bc); | |
693 | + sieve_script_free(&s); | |
694 | + } | |
695 | + | |
696 | + close(out_fd); | |
697 | + rewind(in_stream); | |
698 | + | |
699 | + /* Copy the initial script */ | |
700 | + oldmask = umask(077); | |
701 | + if((out_fp = fopen(sieve_tmpname, "w")) == NULL) { | |
702 | + syslog(LOG_WARNING,"autocreate_sieve: Unable to open %s destination sieve script", sieve_tmpname); | |
703 | + unlink(sieve_bctmpname); | |
704 | + umask(oldmask); | |
705 | + fclose(in_stream); | |
706 | + return 1; | |
707 | + } | |
708 | + umask(oldmask); | |
709 | + | |
710 | + while((r = fread(buf,sizeof(char), sizeof(buf), in_stream))) { | |
711 | + if( fwrite(buf,sizeof(char), r, out_fp) != r) { | |
712 | + syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file: %s",sieve_tmpname); | |
713 | + fclose(out_fp); | |
714 | + unlink(sieve_tmpname); | |
715 | + unlink(sieve_bctmpname); | |
716 | + fclose(in_stream); | |
717 | + return 1; | |
718 | + } | |
719 | + } | |
720 | + | |
721 | + if(feof(in_stream)) { | |
722 | + fclose(out_fp); | |
723 | + } else { /* ferror */ | |
724 | + fclose(out_fp); | |
725 | + unlink(sieve_tmpname); | |
726 | + unlink(sieve_bctmpname); | |
727 | + fclose(in_stream); | |
728 | + return 1; | |
729 | + } | |
730 | + | |
731 | + /* Renaming the necessary stuff */ | |
732 | + if(rename(sieve_tmpname, sieve_script_name)) { | |
733 | + unlink(sieve_tmpname); | |
734 | + unlink(sieve_bctmpname); | |
735 | + return 1; | |
736 | + } | |
737 | + | |
738 | + if(rename(sieve_bctmpname, sieve_bcscript_name)) { | |
739 | + unlink(sieve_bctmpname); | |
740 | + unlink(sieve_bcscript_name); | |
741 | + return 1; | |
742 | + } | |
743 | + | |
744 | + /* end now with the symlink */ | |
745 | + if(symlink(sieve_bclink_name, sieve_default)) { | |
746 | + if(errno != EEXIST) { | |
747 | + syslog(LOG_WARNING, "autocreate_sieve: problem making the default link."); | |
748 | + /* Lets delete the files */ | |
749 | + unlink(sieve_script_name); | |
750 | + unlink(sieve_bcscript_name); | |
751 | + } | |
752 | + } | |
753 | + | |
754 | + /* | |
755 | + * If everything has succeeded AND we have compiled the script AND we have requested | |
756 | + * to generate the global script so that it is not compiled each time then we create it. | |
757 | + */ | |
758 | + if(do_compile && | |
759 | + config_getswitch(IMAPOPT_GENERATE_COMPILED_SIEVE_SCRIPT)) { | |
760 | + | |
761 | + if(!compiled_source_script) { | |
762 | + syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf"); | |
763 | + return 0; | |
764 | + } | |
765 | + | |
766 | + if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script) >= sizeof(sieve_tmpname)) | |
767 | + return 0; | |
768 | + | |
769 | + /* | |
770 | + * Copy everything from the newly created bc sieve sieve script. | |
771 | + */ | |
772 | + if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) { | |
773 | + return 0; | |
774 | + } | |
775 | + | |
776 | + if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { | |
777 | + if(errno == EEXIST) { | |
778 | + /* Someone is already doing this so just bail out. */ | |
779 | + syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname); | |
780 | + close(in_fd); | |
781 | + return 0; | |
782 | + } else if (errno == EACCES) { | |
783 | + syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname); | |
784 | + close(in_fd); | |
785 | + return 0; | |
786 | + } else { | |
787 | + syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s",sieve_tmpname); | |
788 | + close(in_fd); | |
789 | + return 0; | |
790 | + } | |
791 | + } | |
792 | + | |
793 | + while((r = read(in_fd, buf, sizeof(buf))) > 0) { | |
794 | + if((k = write(out_fd,buf,r)) < 0) { | |
795 | + syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); | |
796 | + close(out_fd); | |
797 | + close(in_fd); | |
798 | + unlink(sieve_tmpname); | |
799 | + return 0; | |
800 | + } | |
801 | + } | |
802 | + | |
803 | + if(r == 0 ) { /*EOF */ | |
804 | + close(out_fd); | |
805 | + close(in_fd); | |
806 | + } else if (r < 0) { | |
807 | + syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); | |
808 | + close(out_fd); | |
809 | + close(in_fd); | |
810 | + unlink(sieve_tmpname); | |
811 | + return 0; | |
812 | + } | |
813 | + | |
814 | + /* Rename the temporary created sieve script to its final name. */ | |
815 | + if(rename(sieve_tmpname, compiled_source_script)) { | |
816 | + if(errno != EEXIST) { | |
817 | + unlink(sieve_tmpname); | |
818 | + unlink(compiled_source_script); | |
819 | + } | |
820 | + return 0; | |
821 | + } | |
822 | + | |
823 | + syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script); | |
824 | + } | |
825 | + | |
826 | + return 0; | |
827 | +} | |
828 | + | |
829 | +static void fatal(const char *s, int code) | |
830 | +{ | |
831 | + printf("Fatal error: %s (%d)\r\n", s, code); | |
832 | + exit(1); | |
833 | +} | |
834 | + | |
835 | +/* to make larry's stupid functions happy :) */ | |
836 | +static void foo(void) | |
837 | +{ | |
838 | + fatal("stub function called", 0); | |
839 | +} | |
840 | + | |
841 | +static int sieve_notify(void *ac __attribute__((unused)), | |
842 | + void *interp_context __attribute__((unused)), | |
843 | + void *script_context __attribute__((unused)), | |
844 | + void *message_context __attribute__((unused)), | |
845 | + const char **errmsg __attribute__((unused))) | |
846 | +{ | |
847 | + fatal("stub function called", 0); | |
848 | + return SIEVE_FAIL; | |
849 | +} | |
850 | + | |
851 | +static int mysieve_error(int lineno, const char *msg, | |
852 | + void *i __attribute__((unused)), void *s) | |
853 | +{ | |
854 | + char buf[1024]; | |
855 | + char **errstr = (char **) s; | |
856 | + | |
857 | + snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); | |
858 | + *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); | |
859 | + syslog(LOG_DEBUG, "%s", buf); | |
860 | + strcat(*errstr, buf); | |
861 | + | |
862 | + return SIEVE_OK; | |
863 | +} | |
864 | + | |
865 | +/* end the boilerplate */ | |
866 | + | |
867 | +/* returns TRUE or FALSE */ | |
868 | +int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) | |
869 | +{ | |
870 | + sieve_interp_t *i; | |
871 | + sieve_script_t *s; | |
872 | + int res; | |
873 | + | |
874 | + res = sieve_interp_alloc(&i, NULL); | |
875 | + if (res != SIEVE_OK) { | |
876 | + syslog(LOG_WARNING, "sieve_interp_alloc() returns %d\n", res); | |
877 | + return TIMSIEVE_FAIL; | |
878 | + } | |
879 | + | |
880 | + res = sieve_register_redirect(i, (sieve_callback *) &foo); | |
881 | + if (res != SIEVE_OK) { | |
882 | + syslog(LOG_WARNING, "sieve_register_redirect() returns %d\n", res); | |
883 | + return TIMSIEVE_FAIL; | |
884 | + } | |
885 | + res = sieve_register_discard(i, (sieve_callback *) &foo); | |
886 | + if (res != SIEVE_OK) { | |
887 | + syslog(LOG_WARNING, "sieve_register_discard() returns %d\n", res); | |
888 | + return TIMSIEVE_FAIL; | |
889 | + } | |
890 | + res = sieve_register_reject(i, (sieve_callback *) &foo); | |
891 | + if (res != SIEVE_OK) { | |
892 | + syslog(LOG_WARNING, "sieve_register_reject() returns %d\n", res); | |
893 | + return TIMSIEVE_FAIL; | |
894 | + } | |
895 | + res = sieve_register_fileinto(i, (sieve_callback *) &foo); | |
896 | + if (res != SIEVE_OK) { | |
897 | + syslog(LOG_WARNING, "sieve_register_fileinto() returns %d\n", res); | |
898 | + return TIMSIEVE_FAIL; | |
899 | + } | |
900 | + res = sieve_register_keep(i, (sieve_callback *) &foo); | |
901 | + if (res != SIEVE_OK) { | |
902 | + syslog(LOG_WARNING, "sieve_register_keep() returns %d\n", res); | |
903 | + return TIMSIEVE_FAIL; | |
904 | + } | |
905 | + | |
906 | + res = sieve_register_imapflags(i, NULL); | |
907 | + if (res != SIEVE_OK) { | |
908 | + syslog(LOG_WARNING, "sieve_register_imapflags() returns %d\n", res); | |
909 | + return TIMSIEVE_FAIL; | |
910 | + } | |
911 | + | |
912 | + res = sieve_register_size(i, (sieve_get_size *) &foo); | |
913 | + if (res != SIEVE_OK) { | |
914 | + syslog(LOG_WARNING, "sieve_register_size() returns %d\n", res); | |
915 | + return TIMSIEVE_FAIL; | |
916 | + } | |
917 | + | |
918 | + res = sieve_register_header(i, (sieve_get_header *) &foo); | |
919 | + if (res != SIEVE_OK) { | |
920 | + syslog(LOG_WARNING, "sieve_register_header() returns %d\n", res); | |
921 | + return TIMSIEVE_FAIL; | |
922 | + } | |
923 | + | |
924 | + res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); | |
925 | + if (res != SIEVE_OK) { | |
926 | + syslog(LOG_WARNING, "sieve_register_envelope() returns %d\n", res); | |
927 | + return TIMSIEVE_FAIL; | |
928 | + } | |
929 | + | |
930 | + res = sieve_register_vacation(i, &vacation2); | |
931 | + if (res != SIEVE_OK) { | |
932 | + syslog(LOG_WARNING, "sieve_register_vacation() returns %d\n", res); | |
933 | + return TIMSIEVE_FAIL; | |
934 | + } | |
935 | + | |
936 | + res = sieve_register_notify(i, &sieve_notify); | |
937 | + if (res != SIEVE_OK) { | |
938 | + syslog(LOG_WARNING, "sieve_register_notify() returns %d\n", res); | |
939 | + return TIMSIEVE_FAIL; | |
940 | + } | |
941 | + | |
942 | + res = sieve_register_parse_error(i, &mysieve_error); | |
943 | + if (res != SIEVE_OK) { | |
944 | + syslog(LOG_WARNING, "sieve_register_parse_error() returns %d\n", res); | |
945 | + return TIMSIEVE_FAIL; | |
946 | + } | |
947 | + | |
948 | + rewind(stream); | |
949 | + | |
950 | + *errstr = (char *) xmalloc(20 * sizeof(char)); | |
951 | + strcpy(*errstr, "script errors:\r\n"); | |
952 | + | |
953 | + res = sieve_script_parse(i, stream, errstr, &s); | |
954 | + | |
955 | + if (res == SIEVE_OK) { | |
956 | + if(ret) { | |
957 | + *ret = s; | |
958 | + } else { | |
959 | + sieve_script_free(&s); | |
960 | + } | |
961 | + free(*errstr); | |
962 | + *errstr = NULL; | |
963 | + } | |
964 | + | |
965 | + /* free interpreter */ | |
966 | + sieve_interp_free(&i); | |
967 | + | |
968 | + return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; | |
969 | +} | |
970 | + | |
971 | +/* | |
972 | + * Btw the initial date of this patch is Sep, 02 2004 which is the birthday of | |
973 | + * Pavlos. Author of cyrusmaster. So consider this patch as his birthday present | |
974 | + */ | |
975 | + | |
976 | diff -Naur cyrus-imapd-2.2.12/imap/compile_sieve.c cyrus-imapd-2.2.12.autocreate2/imap/compile_sieve.c | |
977 | --- cyrus-imapd-2.2.12/imap/compile_sieve.c 1970-01-01 02:00:00.000000000 +0200 | |
978 | +++ cyrus-imapd-2.2.12.autocreate2/imap/compile_sieve.c 2005-10-19 14:48:57.943407000 +0300 | |
979 | @@ -0,0 +1,364 @@ | |
980 | +/* This tool compiles the sieve script from a command | |
981 | +line so that it can be used wby the autoadd patch */ | |
982 | +#include <stdio.h> | |
983 | +#include <stdlib.h> | |
984 | + | |
985 | +#include <config.h> | |
986 | +#include <string.h> | |
987 | +#ifdef HAVE_UNISTD_H | |
988 | +#include <unistd.h> | |
989 | +#endif | |
990 | +#include <errno.h> | |
991 | +#include <sys/types.h> | |
992 | +#include <sys/stat.h> | |
993 | +#include <sys/uio.h> | |
994 | +#include <fcntl.h> | |
995 | +#include <ctype.h> | |
996 | +#include <time.h> | |
997 | +#include <com_err.h> | |
998 | + | |
999 | +#include "global.h" | |
1000 | + | |
1001 | +#include "util.h" | |
1002 | +#include "mailbox.h" | |
1003 | +#include "imap_err.h" | |
1004 | +#include "sieve_interface.h" | |
1005 | +#include "script.h" | |
1006 | + | |
1007 | +#include <pwd.h> | |
1008 | + | |
1009 | +#define TIMSIEVE_FAIL -1 | |
1010 | +#define TIMSIEVE_OK 0 | |
1011 | +#define MAX_FILENAME_SIZE 100 | |
1012 | + | |
1013 | +/* Needed by libconfig */ | |
1014 | +const int config_need_data = 0; | |
1015 | + | |
1016 | +static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); | |
1017 | + | |
1018 | +static void fatal(const char *s, int code) | |
1019 | +{ | |
1020 | + printf("Fatal error: %s (%d)\r\n", s, code); | |
1021 | + | |
1022 | + exit(1); | |
1023 | +} | |
1024 | + | |
1025 | +void usage(void) | |
1026 | +{ | |
1027 | + fprintf(stderr, | |
1028 | + "Usage:\n\tcompile_sieve [-C <altconfig>] [-i <infile> -o <outfile>]\n"); | |
1029 | + exit(-1); | |
1030 | +} | |
1031 | + | |
1032 | + | |
1033 | +int main (int argc, char **argv) | |
1034 | +{ | |
1035 | + | |
1036 | + sieve_script_t *s = NULL; | |
1037 | + bytecode_info_t *bc = NULL; | |
1038 | + char *err = NULL; | |
1039 | + FILE *in_stream; | |
1040 | + int out_fd,r, k, opt; | |
1041 | + char *source_script = NULL; | |
1042 | + char *compiled_source_script = NULL; | |
1043 | + mode_t oldmask; | |
1044 | + struct stat statbuf; | |
1045 | + char *alt_config = NULL; | |
1046 | + extern char *optarg; | |
1047 | + char sieve_tmpname[MAX_MAILBOX_NAME+1]; | |
1048 | + | |
1049 | + if (geteuid() == 0) fatal("must run as the Cyrus user", EC_USAGE); | |
1050 | + | |
1051 | + while((opt = getopt(argc, argv, "C:i:o:")) != EOF) { | |
1052 | + switch (opt) { | |
1053 | + case 'C': /* alt config file */ | |
1054 | + alt_config = optarg; | |
1055 | + break; | |
1056 | + case 'i': /* input script file */ | |
1057 | + source_script = optarg; | |
1058 | + break; | |
1059 | + case 'o': /* output script file */ | |
1060 | + compiled_source_script = optarg; | |
1061 | + break; | |
1062 | + default: | |
1063 | + usage(); | |
1064 | + break; | |
1065 | + } | |
1066 | + } | |
1067 | + | |
1068 | + if(source_script && !compiled_source_script) { | |
1069 | + fprintf(stderr, "No output file was defined\n"); | |
1070 | + usage(); | |
1071 | + } else if (!source_script && compiled_source_script) { | |
1072 | + fprintf(stderr, "No input file was defined\n"); | |
1073 | + usage(); | |
1074 | + } | |
1075 | + | |
1076 | + /* | |
1077 | + * If no <infile> has been defined, then read them from | |
1078 | + * the configuration file. | |
1079 | + */ | |
1080 | + if (!source_script && !compiled_source_script) { | |
1081 | + cyrus_init(alt_config, "compile_sieve", 0); | |
1082 | + | |
1083 | + /* Initially check if we want to have the sieve script created */ | |
1084 | + if(!(source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT))) { | |
1085 | + fprintf(stderr,"autocreate_sieve_script option not defined. Check imapd.conf\n"); | |
1086 | + return 1; | |
1087 | + } | |
1088 | + | |
1089 | + /* Check if we have an already compiled sieve script*/ | |
1090 | + if(!(compiled_source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { | |
1091 | + fprintf(stderr, "autocreate_sieve_compiledscript option not defined. Check imapd.conf\n"); | |
1092 | + return 1; | |
1093 | + } | |
1094 | + | |
1095 | + if(!strrchr(source_script,'/') || !strrchr(compiled_source_script,'/')) { | |
1096 | + /* | |
1097 | + * At this point the only think that is inconsistent is the directory | |
1098 | + * that was created. But if the user will have any sieve scripts then | |
1099 | + * they will eventually go there, so no big deal | |
1100 | + */ | |
1101 | + fprintf(stderr, | |
1102 | + "In imapd.conf the full path of the filenames must be defined\n"); | |
1103 | + return 1; | |
1104 | + } | |
1105 | + } | |
1106 | + | |
1107 | + printf("input file : %s, output file : %s\n", source_script, compiled_source_script); | |
1108 | + | |
1109 | + | |
1110 | + if(strlen(compiled_source_script) + sizeof(".NEW") + 1 > sizeof(sieve_tmpname)) { | |
1111 | + fprintf(stderr, "Filename %s is too big\n", compiled_source_script); | |
1112 | + return 1; | |
1113 | + } | |
1114 | + | |
1115 | + snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script); | |
1116 | + | |
1117 | + in_stream = fopen(source_script,"r"); | |
1118 | + | |
1119 | + if(!in_stream) { | |
1120 | + fprintf(stderr,"Unable to open %s source sieve script\n",source_script); | |
1121 | + return; | |
1122 | + } | |
1123 | + | |
1124 | + /* | |
1125 | + * We open the file that will be used as the bc file. If this file exists, overwrite it | |
1126 | + * since something bad has happened. We open the file here so that this error checking is | |
1127 | + * done before we try to open the rest of the files to start copying etc. | |
1128 | + */ | |
1129 | + out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | |
1130 | + if(out_fd < 0) { | |
1131 | + if(errno == EEXIST) { | |
1132 | + fprintf(stderr, "File %s already exists\n", sieve_tmpname); | |
1133 | + } else if (errno == EACCES) { | |
1134 | + fprintf(stderr,"No access to create file %s. Please check that you have the correct permissions\n", | |
1135 | + sieve_tmpname); | |
1136 | + } else { | |
1137 | + fprintf(stderr,"Unable to create %s. Please check that you have the correct permissions\n", | |
1138 | + sieve_tmpname); | |
1139 | + } | |
1140 | + | |
1141 | + fclose(in_stream); | |
1142 | + return 1; | |
1143 | + } | |
1144 | + | |
1145 | + if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { | |
1146 | + if(err && *err) { | |
1147 | + fprintf(stderr, "Error while parsing script %s\n",err); | |
1148 | + free(err); | |
1149 | + } | |
1150 | + else | |
1151 | + fprintf(stderr,"Error while parsing script\n"); | |
1152 | + unlink(sieve_tmpname); | |
1153 | + fclose(in_stream); | |
1154 | + close(out_fd); | |
1155 | + return; | |
1156 | + } | |
1157 | + | |
1158 | + | |
1159 | + /* generate the bytecode */ | |
1160 | + if(sieve_generate_bytecode(&bc,s) == TIMSIEVE_FAIL) { | |
1161 | + fprintf(stderr,"Error occured while compiling sieve script\n"); | |
1162 | + /* removing the copied script and cleaning up memory */ | |
1163 | + unlink(sieve_tmpname); | |
1164 | + sieve_script_free(&s); | |
1165 | + fclose(in_stream); | |
1166 | + close(out_fd); | |
1167 | + return; | |
1168 | + } | |
1169 | + if(sieve_emit_bytecode(out_fd,bc) == TIMSIEVE_FAIL) { | |
1170 | + fprintf(stderr, "Error occured while emitting sieve script\n"); | |
1171 | + unlink(sieve_tmpname); | |
1172 | + sieve_free_bytecode(&bc); | |
1173 | + sieve_script_free(&s); | |
1174 | + fclose(in_stream); | |
1175 | + close(out_fd); | |
1176 | + return; | |
1177 | + } | |
1178 | + | |
1179 | + /* clean up the memory */ | |
1180 | + sieve_free_bytecode(&bc); | |
1181 | + sieve_script_free(&s); | |
1182 | + | |
1183 | + close(out_fd); | |
1184 | + | |
1185 | + if(rename(sieve_tmpname, compiled_source_script)) { | |
1186 | + if(errno != EEXIST) { | |
1187 | + unlink(sieve_tmpname); | |
1188 | + unlink(compiled_source_script); | |
1189 | + return 1; | |
1190 | + } | |
1191 | + } | |
1192 | + return 0; | |
1193 | +} | |
1194 | + | |
1195 | + | |
1196 | +/* to make larry's stupid functions happy :) */ | |
1197 | +static void foo(void) | |
1198 | +{ | |
1199 | + fatal("stub function called", 0); | |
1200 | +} | |
1201 | + | |
1202 | +extern sieve_vacation_t vacation2;/* = { | |
1203 | + 0, / min response / | |
1204 | + 0, / max response / | |
1205 | + (sieve_callback *) &foo, / autorespond() / | |
1206 | + (sieve_callback *) &foo / send_response() / | |
1207 | +}; */ | |
1208 | + | |
1209 | +static int sieve_notify(void *ac __attribute__((unused)), | |
1210 | + void *interp_context __attribute__((unused)), | |
1211 | + void *script_context __attribute__((unused)), | |
1212 | + void *message_context __attribute__((unused)), | |
1213 | + const char **errmsg __attribute__((unused))) | |
1214 | +{ | |
1215 | + fatal("stub function called", 0); | |
1216 | + return SIEVE_FAIL; | |
1217 | +} | |
1218 | + | |
1219 | +static int mysieve_error(int lineno, const char *msg, | |
1220 | + void *i __attribute__((unused)), void *s) | |
1221 | +{ | |
1222 | + char buf[1024]; | |
1223 | + char **errstr = (char **) s; | |
1224 | + | |
1225 | + snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); | |
1226 | + *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); | |
1227 | + fprintf(stderr, "%s\n", buf); | |
1228 | + strcat(*errstr, buf); | |
1229 | + | |
1230 | + return SIEVE_OK; | |
1231 | +} | |
1232 | + | |
1233 | +/* end the boilerplate */ | |
1234 | + | |
1235 | +/* returns TRUE or FALSE */ | |
1236 | +int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) | |
1237 | +{ | |
1238 | + sieve_interp_t *i; | |
1239 | + sieve_script_t *s; | |
1240 | + int res; | |
1241 | + | |
1242 | + res = sieve_interp_alloc(&i, NULL); | |
1243 | + if (res != SIEVE_OK) { | |
1244 | + fprintf(stderr, "sieve_interp_alloc() returns %d\n", res); | |
1245 | + return TIMSIEVE_FAIL; | |
1246 | + } | |
1247 | + | |
1248 | + res = sieve_register_redirect(i, (sieve_callback *) &foo); | |
1249 | + if (res != SIEVE_OK) { | |
1250 | + fprintf(stderr, "sieve_register_redirect() returns %d\n", res); | |
1251 | + return TIMSIEVE_FAIL; | |
1252 | + } | |
1253 | + res = sieve_register_discard(i, (sieve_callback *) &foo); | |
1254 | + if (res != SIEVE_OK) { | |
1255 | + fprintf(stderr, "sieve_register_discard() returns %d\n", res); | |
1256 | + return TIMSIEVE_FAIL; | |
1257 | + } | |
1258 | + res = sieve_register_reject(i, (sieve_callback *) &foo); | |
1259 | + if (res != SIEVE_OK) { | |
1260 | + fprintf(stderr, "sieve_register_reject() returns %d\n", res); | |
1261 | + return TIMSIEVE_FAIL; | |
1262 | + } | |
1263 | + res = sieve_register_fileinto(i, (sieve_callback *) &foo); | |
1264 | + if (res != SIEVE_OK) { | |
1265 | + fprintf(stderr, "sieve_register_fileinto() returns %d\n", res); | |
1266 | + return TIMSIEVE_FAIL; | |
1267 | + } | |
1268 | + res = sieve_register_keep(i, (sieve_callback *) &foo); | |
1269 | + if (res != SIEVE_OK) { | |
1270 | + fprintf(stderr, "sieve_register_keep() returns %d\n", res); | |
1271 | + return TIMSIEVE_FAIL; | |
1272 | + } | |
1273 | + | |
1274 | + res = sieve_register_imapflags(i, NULL); | |
1275 | + if (res != SIEVE_OK) { | |
1276 | + fprintf(stderr, "sieve_register_imapflags() returns %d\n", res); | |
1277 | + return TIMSIEVE_FAIL; | |
1278 | + } | |
1279 | + | |
1280 | + res = sieve_register_size(i, (sieve_get_size *) &foo); | |
1281 | + if (res != SIEVE_OK) { | |
1282 | + fprintf(stderr, "sieve_register_size() returns %d\n", res); | |
1283 | + return TIMSIEVE_FAIL; | |
1284 | + } | |
1285 | + | |
1286 | + res = sieve_register_header(i, (sieve_get_header *) &foo); | |
1287 | + if (res != SIEVE_OK) { | |
1288 | + fprintf(stderr, "sieve_register_header() returns %d\n", res); | |
1289 | + return TIMSIEVE_FAIL; | |
1290 | + } | |
1291 | + | |
1292 | + res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); | |
1293 | + if (res != SIEVE_OK) { | |
1294 | + fprintf(stderr, "sieve_register_envelope() returns %d\n", res); | |
1295 | + return TIMSIEVE_FAIL; | |
1296 | + } | |
1297 | + | |
1298 | + res = sieve_register_vacation(i, &vacation2); | |
1299 | + if (res != SIEVE_OK) { | |
1300 | + fprintf(stderr, "sieve_register_vacation() returns %d\n", res); | |
1301 | + return TIMSIEVE_FAIL; | |
1302 | + } | |
1303 | + | |
1304 | + res = sieve_register_notify(i, &sieve_notify); | |
1305 | + if (res != SIEVE_OK) { | |
1306 | + fprintf(stderr, "sieve_register_notify() returns %d\n", res); | |
1307 | + return TIMSIEVE_FAIL; | |
1308 | + } | |
1309 | + | |
1310 | + res = sieve_register_parse_error(i, &mysieve_error); | |
1311 | + if (res != SIEVE_OK) { | |
1312 | + fprintf(stderr, "sieve_register_parse_error() returns %d\n", res); | |
1313 | + return TIMSIEVE_FAIL; | |
1314 | + } | |
1315 | + | |
1316 | + rewind(stream); | |
1317 | + | |
1318 | + *errstr = (char *) xmalloc(20 * sizeof(char)); | |
1319 | + strcpy(*errstr, "script errors:\r\n"); | |
1320 | + | |
1321 | + res = sieve_script_parse(i, stream, errstr, &s); | |
1322 | + | |
1323 | + if (res == SIEVE_OK) { | |
1324 | + if(ret) { | |
1325 | + *ret = s; | |
1326 | + } else { | |
1327 | + sieve_script_free(&s); | |
1328 | + } | |
1329 | + free(*errstr); | |
1330 | + *errstr = NULL; | |
1331 | + } | |
1332 | + | |
1333 | + /* free interpreter */ | |
1334 | + sieve_interp_free(&i); | |
1335 | + | |
1336 | + return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; | |
1337 | +} | |
1338 | + | |
1339 | + | |
1340 | + | |
1341 | + | |
1342 | + | |
1343 | + | |
1344 | diff -Naur cyrus-imapd-2.2.12/imap/imapd.c cyrus-imapd-2.2.12.autocreate2/imap/imapd.c | |
1345 | --- cyrus-imapd-2.2.12/imap/imapd.c 2005-02-14 08:39:55.000000000 +0200 | |
1346 | +++ cyrus-imapd-2.2.12.autocreate2/imap/imapd.c 2005-10-19 14:48:57.966749000 +0300 | |
1347 | @@ -158,6 +158,7 @@ | |
1348 | void motd_file(int fd); | |
1349 | void shut_down(int code); | |
1350 | void fatal(const char *s, int code); | |
1351 | +void autocreate_inbox(void); | |
1352 | ||
1353 | void cmdloop(void); | |
1354 | void cmd_login(char *tag, char *user); | |
1355 | @@ -1693,6 +1694,42 @@ | |
1356 | } | |
1357 | ||
1358 | /* | |
1359 | + * Autocreate Inbox and subfolders upon login | |
1360 | + */ | |
1361 | +void autocreate_inbox() | |
1362 | +{ | |
1363 | + char inboxname[MAX_MAILBOX_NAME+1]; | |
1364 | + int autocreatequota; | |
1365 | + int r; | |
1366 | + | |
1367 | + /* | |
1368 | + * Exlude admin's accounts | |
1369 | + */ | |
1370 | + if (imapd_userisadmin || imapd_userisproxyadmin) | |
1371 | + return; | |
1372 | + | |
1373 | + /* | |
1374 | + * Exclude anonymous | |
1375 | + */ | |
1376 | + if (!strcmp(imapd_userid, "anonymous")) | |
1377 | + return; | |
1378 | + | |
1379 | + if ((autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) { | |
1380 | + /* This is actyally not required | |
1381 | + as long as the lenght of userid is ok */ | |
1382 | + r = (*imapd_namespace.mboxname_tointernal) (&imapd_namespace, | |
1383 | + "INBOX", imapd_userid, inboxname); | |
1384 | + if (!r) | |
1385 | + r = mboxlist_lookup(inboxname, NULL, NULL, NULL); | |
1386 | + | |
1387 | + if (r == IMAP_MAILBOX_NONEXISTENT) | |
1388 | + mboxlist_autocreateinbox(&imapd_namespace, imapd_userid, | |
1389 | + imapd_authstate, inboxname, autocreatequota); | |
1390 | + } | |
1391 | +} | |
1392 | + | |
1393 | + | |
1394 | +/* | |
1395 | * Perform a LOGIN command | |
1396 | */ | |
1397 | void cmd_login(char *tag, char *user) | |
1398 | @@ -1848,6 +1885,9 @@ | |
1399 | strcspn(imapd_userid, "@") : 0); | |
1400 | ||
1401 | freebuf(&passwdbuf); | |
1402 | + | |
1403 | + autocreate_inbox(); | |
1404 | + | |
1405 | return; | |
1406 | } | |
1407 | ||
1408 | @@ -1993,6 +2033,8 @@ | |
1409 | config_virtdomains ? | |
1410 | strcspn(imapd_userid, "@") : 0); | |
1411 | ||
1412 | + autocreate_inbox(); | |
1413 | + | |
1414 | return; | |
1415 | } | |
1416 | ||
1417 | diff -Naur cyrus-imapd-2.2.12/imap/lmtpd.c cyrus-imapd-2.2.12.autocreate2/imap/lmtpd.c | |
1418 | --- cyrus-imapd-2.2.12/imap/lmtpd.c 2004-12-17 18:32:15.000000000 +0200 | |
1419 | +++ cyrus-imapd-2.2.12.autocreate2/imap/lmtpd.c 2005-10-19 14:48:57.971145000 +0300 | |
1420 | @@ -106,6 +106,8 @@ | |
1421 | static FILE *spoolfile(message_data_t *msgdata); | |
1422 | static void removespool(message_data_t *msgdata); | |
1423 | ||
1424 | +static int autocreate_inbox(char *rcpt_userid); | |
1425 | + | |
1426 | /* current namespace */ | |
1427 | static struct namespace lmtpd_namespace; | |
1428 | ||
1429 | @@ -504,10 +506,55 @@ | |
1430 | exit(code); | |
1431 | } | |
1432 | ||
1433 | +/* | |
1434 | + * Autocreate Inbox and subfolders upon login | |
1435 | + */ | |
1436 | +int autocreate_inbox(char *rcpt_userid) | |
1437 | +{ | |
1438 | + struct auth_state *authstate; | |
1439 | + char inboxname[MAX_MAILBOX_NAME+1]; | |
1440 | + int rcptisadmin; | |
1441 | + int autocreatequota; | |
1442 | + int r; | |
1443 | + | |
1444 | + if(rcpt_userid == NULL) | |
1445 | + return IMAP_MAILBOX_NONEXISTENT; | |
1446 | + | |
1447 | + /* | |
1448 | + * Exclude anonymous | |
1449 | + */ | |
1450 | + if (!strcmp(rcpt_userid, "anonymous")) | |
1451 | + return IMAP_MAILBOX_NONEXISTENT; | |
1452 | + | |
1453 | + /* | |
1454 | + * Check for autocreatequota and createonpost | |
1455 | + */ | |
1456 | + if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)) || | |
1457 | + !(config_getswitch(IMAPOPT_CREATEONPOST))) | |
1458 | + return IMAP_MAILBOX_NONEXISTENT; | |
1459 | + | |
1460 | + /* | |
1461 | + * Exclude admin's accounts | |
1462 | + */ | |
1463 | + authstate = auth_newstate(rcpt_userid); | |
1464 | + rcptisadmin = global_authisa(authstate, IMAPOPT_ADMINS); | |
1465 | + if (rcptisadmin) | |
1466 | + return IMAP_MAILBOX_NONEXISTENT; | |
1467 | + | |
1468 | + r = (*lmtpd_namespace.mboxname_tointernal) (&lmtpd_namespace, | |
1469 | + "INBOX", rcpt_userid, inboxname); | |
1470 | + if (!r) | |
1471 | + r = mboxlist_autocreateinbox(&lmtpd_namespace, rcpt_userid, | |
1472 | + authstate, inboxname, autocreatequota); | |
1473 | + return r; | |
1474 | +} | |
1475 | + | |
1476 | + | |
1477 | static int verify_user(const char *user, const char *domain, const char *mailbox, | |
1478 | long quotacheck, struct auth_state *authstate) | |
1479 | { | |
1480 | char namebuf[MAX_MAILBOX_NAME+1] = ""; | |
1481 | + char *userinbox = NULL; | |
1482 | int r = 0; | |
1483 | ||
1484 | if ((!user && !mailbox) || | |
1485 | @@ -545,6 +592,28 @@ | |
1486 | */ | |
1487 | r = append_check(namebuf, MAILBOX_FORMAT_NORMAL, authstate, | |
1488 | !user ? ACL_POST : 0, quotacheck > 0 ? 0 : quotacheck); | |
1489 | + if (r == IMAP_MAILBOX_NONEXISTENT && user) { | |
1490 | + if(domain) { | |
1491 | + int k; | |
1492 | + userinbox = (char *)xmalloc((strlen(user)+strlen(domain)+2)*sizeof(char)); | |
1493 | + k = strlcpy(userinbox, user, strlen(user)+1); | |
1494 | + *(userinbox + k) = '@'; | |
1495 | + strlcpy(userinbox+k+1, domain, strlen(domain)+1); | |
1496 | + } | |
1497 | + else userinbox = user; | |
1498 | + /* | |
1499 | + * Try to create automatically the mailbox, if | |
1500 | + * autocreate inbox option is enabled. | |
1501 | + */ | |
1502 | + r = autocreate_inbox(userinbox); | |
1503 | + | |
1504 | + if(userinbox != user) | |
1505 | + free(userinbox); | |
1506 | + if (!r) | |
1507 | + r = append_check(namebuf, MAILBOX_FORMAT_NORMAL, authstate, | |
1508 | + 0, quotacheck > 0 ? 0 : quotacheck); | |
1509 | + } | |
1510 | + | |
1511 | } | |
1512 | ||
1513 | if (r) syslog(LOG_DEBUG, "verify_user(%s) failed: %s", namebuf, | |
1514 | diff -Naur cyrus-imapd-2.2.12/imap/mboxlist.c cyrus-imapd-2.2.12.autocreate2/imap/mboxlist.c | |
1515 | --- cyrus-imapd-2.2.12/imap/mboxlist.c 2004-07-26 21:08:03.000000000 +0300 | |
1516 | +++ cyrus-imapd-2.2.12.autocreate2/imap/mboxlist.c 2005-10-19 14:49:25.972032000 +0300 | |
1517 | @@ -81,6 +81,12 @@ | |
1518 | #include "mboxlist.h" | |
1519 | #include "quota.h" | |
1520 | ||
1521 | +#ifdef USE_SIEVE | |
1522 | +extern int autoadd_sieve(char *userid, | |
1523 | + const char *source_script); | |
1524 | +#endif | |
1525 | + | |
1526 | + | |
1527 | #define DB config_mboxlist_db | |
1528 | #define SUBDB config_subscription_db | |
1529 | ||
1530 | @@ -98,11 +104,29 @@ | |
1531 | static int mboxlist_changequota(const char *name, int matchlen, int maycreate, | |
1532 | void *rock); | |
1533 | ||
1534 | +static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, | |
1535 | + void *rock); | |
1536 | + | |
1537 | +static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, | |
1538 | + char *userid, char *auth_userid, | |
1539 | + struct auth_state *auth_state); | |
1540 | + | |
1541 | struct change_rock { | |
1542 | struct quota *quota; | |
1543 | struct txn **tid; | |
1544 | }; | |
1545 | ||
1546 | +/* | |
1547 | + * Struct needed to be passed as void *rock to | |
1548 | + * mboxlist_autochangesub(); | |
1549 | + */ | |
1550 | +struct changesub_rock_st { | |
1551 | + char *userid; | |
1552 | + char *auth_userid; | |
1553 | + struct auth_state *auth_state; | |
1554 | +}; | |
1555 | + | |
1556 | + | |
1557 | #define FNAME_SUBSSUFFIX ".sub" | |
1558 | ||
1559 | /* | |
1560 | @@ -3124,3 +3148,338 @@ | |
1561 | ||
1562 | return DB->abort(mbdb, tid); | |
1563 | } | |
1564 | + | |
1565 | +/* | |
1566 | + * Automatically subscribe user to *ALL* shared folders, | |
1567 | + * one has permissions to be subscribed to. | |
1568 | + * INBOX subfolders are excluded. | |
1569 | + */ | |
1570 | +static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, | |
1571 | + void *rock) { | |
1572 | + | |
1573 | + struct changesub_rock_st *changesub_rock = (struct changesub_rock_st *) rock; | |
1574 | + char *userid = changesub_rock->userid; | |
1575 | + char *auth_userid = changesub_rock->auth_userid; | |
1576 | + struct auth_state *auth_state = changesub_rock->auth_state; | |
1577 | + int r; | |
1578 | + | |
1579 | + | |
1580 | + if((strlen(name) == 5 && !strncmp(name, "INBOX", 5)) || /* Exclude INBOX */ | |
1581 | + (strlen(name) > 5 && !strncmp(name, "INBOX.",6)) || /* Exclude INBOX subfolders */ | |
1582 | + (strlen(name) > 4 && !strncmp(name, "user.", 5))) /* Exclude other users' folders */ | |
1583 | + return 0; | |
1584 | + | |
1585 | + | |
1586 | + r = mboxlist_changesub(name, userid, auth_state, 1, 0); | |
1587 | + | |
1588 | + if (r) { | |
1589 | + syslog(LOG_WARNING, | |
1590 | + "autosubscribe: User %s to folder %s, subscription failed: %s", | |
1591 | + auth_userid, name, error_message(r)); | |
1592 | + } else { | |
1593 | + syslog(LOG_NOTICE, | |
1594 | + "autosubscribe: User %s to folder %s, subscription succeeded", | |
1595 | + auth_userid, name); | |
1596 | + } | |
1597 | + | |
1598 | + return 0; | |
1599 | +} | |
1600 | + | |
1601 | +#define SEP '|' | |
1602 | + | |
1603 | +/* | |
1604 | + * Automatically subscribe user to a shared folder. | |
1605 | + * Subscription is done successfully, if the shared | |
1606 | + * folder exists and the user has the necessary | |
1607 | + * permissions. | |
1608 | + */ | |
1609 | +static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, | |
1610 | + char *userid, char *auth_userid, | |
1611 | + struct auth_state *auth_state) { | |
1612 | + | |
1613 | + const char *sub ; | |
1614 | + char *p, *q, *next_sub; | |
1615 | + char folder[MAX_MAILBOX_NAME+1], name[MAX_MAILBOX_NAME+1], mailboxname[MAX_MAILBOX_NAME+1]; | |
1616 | + int len; | |
1617 | + int r = 0; | |
1618 | + int subscribe_all_sharedfolders = 0; | |
1619 | + | |
1620 | + subscribe_all_sharedfolders = config_getswitch(IMAPOPT_AUTOSUBSCRIBE_ALL_SHAREDFOLDERS); | |
1621 | + | |
1622 | + /* | |
1623 | + * If subscribeallsharedfolders is set to yes in imapd.conf, then | |
1624 | + * subscribe user to every shared folder one has the apropriate | |
1625 | + * permissions. | |
1626 | + */ | |
1627 | + if(subscribe_all_sharedfolders) { | |
1628 | + char pattern[MAX_MAILBOX_PATH+1]; | |
1629 | + struct changesub_rock_st changesub_rock; | |
1630 | + | |
1631 | + strcpy(pattern, "*"); | |
1632 | + changesub_rock.userid = userid; | |
1633 | + changesub_rock.auth_userid = auth_userid; | |
1634 | + changesub_rock.auth_state = auth_state; | |
1635 | + | |
1636 | + r = mboxlist_findall(namespace, pattern, 0, userid, | |
1637 | + auth_state, mboxlist_autochangesub, &changesub_rock); | |
1638 | + | |
1639 | + return r; | |
1640 | + } | |
1641 | + | |
1642 | + if ((sub=config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS)) == NULL) | |
1643 | + return r; | |
1644 | + | |
1645 | + next_sub = (char *) sub; | |
1646 | + while (*next_sub) { | |
1647 | + for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); | |
1648 | + for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); | |
1649 | + for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); | |
1650 | + if (!*p ) continue; | |
1651 | + | |
1652 | + len = q - p + 1; | |
1653 | + /* Check for folder length */ | |
1654 | + if (len > sizeof(folder)-1) | |
1655 | + continue; | |
1656 | + | |
1657 | + if (!r) { | |
1658 | + strncpy(folder, p, len); | |
1659 | + folder[len] = '\0'; | |
1660 | + | |
1661 | + strlcpy(name, namespace->prefix[NAMESPACE_SHARED], sizeof(name)); | |
1662 | + len = strlcat(name, folder, sizeof(name)); | |
1663 | + | |
1664 | + r = (namespace->mboxname_tointernal) (namespace, name, userid, | |
1665 | + mailboxname); | |
1666 | + } | |
1667 | + | |
1668 | + if (!r) | |
1669 | + r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 0); | |
1670 | + | |
1671 | + if (!r) { | |
1672 | + syslog(LOG_NOTICE, "autosubscribe: User %s to %s succeeded", | |
1673 | + userid, folder); | |
1674 | + } else { | |
1675 | + syslog(LOG_WARNING, "autosubscribe: User %s to %s failed: %s", | |
1676 | + userid, folder, error_message(r)); | |
1677 | + r = 0; | |
1678 | + } | |
1679 | + } | |
1680 | + | |
1681 | + return r; | |
1682 | +} | |
1683 | + | |
1684 | + | |
1685 | + | |
1686 | +int mboxlist_autocreateinbox(struct namespace *namespace, | |
1687 | + char *userid, | |
1688 | + struct auth_state *auth_state, | |
1689 | + char *mailboxname, int autocreatequota) { | |
1690 | + char name [MAX_MAILBOX_NAME+1]; | |
1691 | + char folder [MAX_MAILBOX_NAME+1]; | |
1692 | + char *auth_userid = NULL; | |
1693 | + char *partition = NULL; | |
1694 | + const char *crt; | |
1695 | + const char *sub; | |
1696 | + char *p, *q, *next_crt, *next_sub; | |
1697 | + int len; | |
1698 | + int r = 0; | |
1699 | + int numcrt = 0; | |
1700 | + int numsub = 0; | |
1701 | +#ifdef USE_SIEVE | |
1702 | + const char *source_script; | |
1703 | +#endif | |
1704 | + | |
1705 | + /* | |
1706 | + * While this is not needed for admins | |
1707 | + * and imap_admins accounts, it would be | |
1708 | + * better to separate *all* admins and | |
1709 | + * proxyservers from normal accounts | |
1710 | + * (accounts that have mailboxes). | |
1711 | + * UOA Specific note(1): Even if we do not | |
1712 | + * exclude these servers-classes here, | |
1713 | + * UOA specific code, will neither return | |
1714 | + * role, nor create INBOX, because none of these | |
1715 | + * administrative accounts belong to the | |
1716 | + * mailRecipient objectclass, or have imapPartition. | |
1717 | + * UOA Specific note(2): Another good reason for doing | |
1718 | + * this, is to prevent the code, from getting into | |
1719 | + * cyrus_ldap.c because of the continues MSA logins to LMTPd. | |
1720 | + */ | |
1721 | + | |
1722 | + /* | |
1723 | + * admins and the coresponding imap | |
1724 | + * service, had already been excluded. | |
1725 | + */ | |
1726 | + | |
1727 | + /* | |
1728 | + * Do we really need group membership | |
1729 | + * for admins or service_admins? | |
1730 | + */ | |
1731 | + if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0; | |
1732 | + if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0; | |
1733 | + | |
1734 | + /* | |
1735 | + * Do we really need group membership | |
1736 | + * for proxyservers? | |
1737 | + */ | |
1738 | + if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0; | |
1739 | + if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0; | |
1740 | + | |
1741 | + auth_userid = auth_canonuser(auth_state); | |
1742 | + | |
1743 | + if (auth_userid == NULL) { | |
1744 | + /* | |
1745 | + * Couldn't get cannon userid | |
1746 | + */ | |
1747 | + syslog(LOG_ERR, | |
1748 | + "Could not get cannon userid for user %s", userid); | |
1749 | + return IMAP_PARTITION_UNKNOWN; | |
1750 | + } | |
1751 | + | |
1752 | +#if 0 | |
1753 | + /* | |
1754 | + * Get Partition info or return. | |
1755 | + * (Here you should propably use | |
1756 | + * you own "get_partition(char *userid)" | |
1757 | + * function. Otherwise all new INBOXes will be | |
1758 | + * created into whatever partition has been declared | |
1759 | + * as default in your imapd.conf) | |
1760 | + */ | |
1761 | + | |
1762 | + partition = get_partition(userid); | |
1763 | + | |
1764 | + if (partition == NULL) { | |
1765 | + /* | |
1766 | + * Couldn't get partition info | |
1767 | + */ | |
1768 | + syslog(LOG_ERR, | |
1769 | + "Could not get imapPartition info for user %s", userid); | |
1770 | + return IMAP_PARTITION_UNKNOWN; | |
1771 | + } | |
1772 | +#endif | |
1773 | + | |
1774 | + r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, | |
1775 | + 1, userid, auth_state, 0, 0, 0); | |
1776 | + | |
1777 | + if (!r && autocreatequota > 0) | |
1778 | + r = mboxlist_setquota(mailboxname, autocreatequota, 0); | |
1779 | + | |
1780 | + if (!r) | |
1781 | + r = mboxlist_changesub(mailboxname, userid, | |
1782 | + auth_state, 1, 1); | |
1783 | + | |
1784 | + if (!r) { | |
1785 | + syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created in partition %s", | |
1786 | + auth_userid, partition == NULL ? "default" : partition); | |
1787 | + } else { | |
1788 | + syslog(LOG_ERR, "autocreateinbox: User %s, INBOX failed. %s", | |
1789 | + auth_userid, error_message(r)); | |
1790 | + } | |
1791 | + | |
1792 | + | |
1793 | +#if 0 | |
1794 | + /* Allocated from get_partition, and not needed any more */ | |
1795 | + free_partition(partition); | |
1796 | +#endif | |
1797 | + | |
1798 | + if (r) return r; | |
1799 | + | |
1800 | + | |
1801 | + /* INBOX's subfolders */ | |
1802 | + if ((crt=config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS))) | |
1803 | + sub=config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS); | |
1804 | + | |
1805 | + /* Roll through crt */ | |
1806 | + next_crt = (char *) crt; | |
1807 | + while (next_crt!=NULL && *next_crt) { | |
1808 | + for (p = next_crt ; isspace((int) *p) || *p == SEP ; p++); | |
1809 | + for (next_crt = p ; *next_crt && *next_crt != SEP ; next_crt++); | |
1810 | + for (q = next_crt ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--); | |
1811 | + | |
1812 | + if (!*p) continue; | |
1813 | + | |
1814 | + len = q - p + 1; | |
1815 | + | |
1816 | + /* First time we check for length */ | |
1817 | + if (len > sizeof(folder) - 5) | |
1818 | + r = IMAP_MAILBOX_BADNAME; | |
1819 | + | |
1820 | + if (!r) { | |
1821 | + strncpy(folder, p, len); | |
1822 | + folder[len] = '\0'; | |
1823 | + | |
1824 | + strlcpy(name, namespace->prefix[NAMESPACE_INBOX], sizeof(name)); | |
1825 | + len = strlcat(name, folder, sizeof(name)); | |
1826 | + } | |
1827 | + | |
1828 | + if (!r) | |
1829 | + r = (namespace->mboxname_tointernal) (namespace, name, userid, | |
1830 | + mailboxname); | |
1831 | + if (!r) | |
1832 | + r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, | |
1833 | + 1, userid, auth_state, 0, 0, 0); | |
1834 | + | |
1835 | + if (!r) { | |
1836 | + numcrt++; | |
1837 | + syslog(LOG_NOTICE, "autocreateinbox: User %s, subfolder %s creation succeeded.", | |
1838 | + auth_userid, name); | |
1839 | + } else { | |
1840 | + syslog(LOG_WARNING, "autocreateinbox: User %s, subfolder %s creation failed. %s", | |
1841 | + auth_userid, name, error_message(r)); | |
1842 | + r=0; | |
1843 | + continue; | |
1844 | + } | |
1845 | + | |
1846 | + /* Roll through sub */ | |
1847 | + next_sub = (char *) sub; | |
1848 | + while (next_sub!=NULL && *next_sub) { | |
1849 | + for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); | |
1850 | + for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); | |
1851 | + for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); | |
1852 | + if (!*p ) continue; | |
1853 | + | |
1854 | + len = q - p + 1; | |
1855 | + | |
1856 | + if (len != strlen(folder) || strncmp(folder, p, len)) | |
1857 | + continue; | |
1858 | + | |
1859 | + r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 1); | |
1860 | + | |
1861 | + if (!r) { | |
1862 | + numsub++; | |
1863 | + syslog(LOG_NOTICE,"autocreateinbox: User %s, subscription to %s succeeded", | |
1864 | + auth_userid, name); | |
1865 | + } else | |
1866 | + syslog(LOG_WARNING, "autocreateinbox: User %s, subscription to %s failed. %s", | |
1867 | + auth_userid, name, error_message(r)); | |
1868 | + | |
1869 | + break; | |
1870 | + } | |
1871 | + } | |
1872 | + | |
1873 | + if (crt!=NULL && *crt) | |
1874 | + syslog(LOG_INFO, "User %s, Inbox subfolders, created %d, subscribed %d", | |
1875 | + auth_userid, numcrt, numsub); | |
1876 | + | |
1877 | + /* | |
1878 | + * Check if shared folders are available for subscription. | |
1879 | + */ | |
1880 | + mboxlist_autosubscribe_sharedfolders(namespace, userid, auth_userid, auth_state); | |
1881 | + | |
1882 | +#ifdef USE_SIEVE | |
1883 | + /* | |
1884 | + * Here the autocreate sieve script feature is iniated from. | |
1885 | + */ | |
1886 | + source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT); | |
1887 | + | |
1888 | + if (source_script) { | |
1889 | + if (!autoadd_sieve(userid, source_script)) | |
1890 | + syslog(LOG_NOTICE, "autocreate_sieve: User %s, default sieve script creation succeeded", auth_userid); | |
1891 | + else | |
1892 | + syslog(LOG_WARNING, "autocreate_sieve: User %s, default sieve script creation failed", auth_userid); | |
1893 | + } | |
1894 | +#endif | |
1895 | + | |
1896 | + return r; | |
1897 | +} | |
1898 | + | |
1899 | diff -Naur cyrus-imapd-2.2.12/imap/mboxlist.h cyrus-imapd-2.2.12.autocreate2/imap/mboxlist.h | |
1900 | --- cyrus-imapd-2.2.12/imap/mboxlist.h 2004-03-17 20:07:49.000000000 +0200 | |
1901 | +++ cyrus-imapd-2.2.12.autocreate2/imap/mboxlist.h 2005-10-19 14:48:58.027033000 +0300 | |
1902 | @@ -197,4 +197,10 @@ | |
1903 | int mboxlist_commit(struct txn *tid); | |
1904 | int mboxlist_abort(struct txn *tid); | |
1905 | ||
1906 | +int mboxlist_autocreateinbox(struct namespace *namespace, | |
1907 | + char *userid, | |
1908 | + struct auth_state *auth_state, | |
1909 | + char *mailboxname, int autocreatequota); | |
1910 | + | |
1911 | + | |
1912 | #endif | |
1913 | diff -Naur cyrus-imapd-2.2.12/imap/pop3d.c cyrus-imapd-2.2.12.autocreate2/imap/pop3d.c | |
1914 | --- cyrus-imapd-2.2.12/imap/pop3d.c 2005-01-04 17:06:13.000000000 +0200 | |
1915 | +++ cyrus-imapd-2.2.12.autocreate2/imap/pop3d.c 2005-10-19 14:48:58.033335000 +0300 | |
1916 | @@ -152,6 +152,8 @@ | |
1917 | static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* <rand.time@hostname> */ | |
1918 | static void cmd_apop(char *response); | |
1919 | ||
1920 | +static int autocreate_inbox(char *inboxname, char *userid); | |
1921 | + | |
1922 | static void cmd_auth(char *arg); | |
1923 | static void cmd_capa(void); | |
1924 | static void cmd_pass(char *pass); | |
1925 | @@ -1084,6 +1086,7 @@ | |
1926 | popd_userid = xstrdup(p); | |
1927 | prot_printf(popd_out, "+OK Name is a valid mailbox\r\n"); | |
1928 | } | |
1929 | + | |
1930 | } | |
1931 | ||
1932 | void cmd_pass(char *pass) | |
1933 | @@ -1328,6 +1331,46 @@ | |
1934 | } | |
1935 | ||
1936 | /* | |
1937 | + * Autocreate Inbox and subfolders upon login | |
1938 | + */ | |
1939 | +int autocreate_inbox(char *inboxname, char *auth_userid) | |
1940 | +{ | |
1941 | + struct auth_state *authstate; | |
1942 | + int userisadmin; | |
1943 | + int autocreatequota; | |
1944 | + int r; | |
1945 | + | |
1946 | + if(inboxname == NULL || auth_userid == NULL) | |
1947 | + return IMAP_MAILBOX_NONEXISTENT; | |
1948 | + | |
1949 | + /* | |
1950 | + * Exclude anonymous | |
1951 | + */ | |
1952 | + if (!strcmp(popd_userid, "anonymous")) | |
1953 | + return IMAP_MAILBOX_NONEXISTENT; | |
1954 | + | |
1955 | + /* | |
1956 | + * Check for autocreatequota | |
1957 | + */ | |
1958 | + if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) | |
1959 | + return IMAP_MAILBOX_NONEXISTENT; | |
1960 | + | |
1961 | + /* | |
1962 | + * Exclude admin's accounts | |
1963 | + */ | |
1964 | + | |
1965 | + authstate = auth_newstate(popd_userid); | |
1966 | + userisadmin = global_authisa(authstate, IMAPOPT_ADMINS); | |
1967 | + if (userisadmin) | |
1968 | + return IMAP_MAILBOX_NONEXISTENT; | |
1969 | + | |
1970 | + r = mboxlist_autocreateinbox(&popd_namespace, auth_userid, | |
1971 | + authstate, inboxname, autocreatequota); | |
1972 | + return r; | |
1973 | +} | |
1974 | + | |
1975 | + | |
1976 | +/* | |
1977 | * Complete the login process by opening and locking the user's inbox | |
1978 | */ | |
1979 | int openinbox(void) | |
1980 | @@ -1349,6 +1392,10 @@ | |
1981 | userid, inboxname); | |
1982 | ||
1983 | if (!r) r = mboxlist_detail(inboxname, &type, NULL, &server, &acl, NULL); | |
1984 | + /* Try once again after autocreate_inbox */ | |
1985 | + if (r == IMAP_MAILBOX_NONEXISTENT && !(r = autocreate_inbox(inboxname, userid))) | |
1986 | + r = mboxlist_detail(inboxname, &type, NULL, &server, &acl, NULL); | |
1987 | + | |
1988 | if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) && | |
1989 | (!acl || | |
1990 | !((myrights = cyrus_acl_myrights(popd_authstate, acl)) & ACL_READ))) { | |
1991 | diff -Naur cyrus-imapd-2.2.12/lib/auth.h cyrus-imapd-2.2.12.autocreate2/lib/auth.h | |
1992 | --- cyrus-imapd-2.2.12/lib/auth.h 2003-10-22 21:50:12.000000000 +0300 | |
1993 | +++ cyrus-imapd-2.2.12.autocreate2/lib/auth.h 2005-10-19 14:48:58.035324000 +0300 | |
1994 | @@ -60,4 +60,6 @@ | |
1995 | extern struct auth_state *auth_newstate(const char *identifier); | |
1996 | extern void auth_freestate(struct auth_state *auth_state); | |
1997 | ||
1998 | +extern char *auth_canonuser(struct auth_state *auth_state); | |
1999 | + | |
2000 | #endif /* INCLUDED_AUTH_H */ | |
2001 | diff -Naur cyrus-imapd-2.2.12/lib/auth_krb.c cyrus-imapd-2.2.12.autocreate2/lib/auth_krb.c | |
2002 | --- cyrus-imapd-2.2.12/lib/auth_krb.c 2003-11-11 05:26:00.000000000 +0200 | |
2003 | +++ cyrus-imapd-2.2.12.autocreate2/lib/auth_krb.c 2005-10-19 14:48:58.038180000 +0300 | |
2004 | @@ -338,3 +338,11 @@ | |
2005 | free((char *)auth_state); | |
2006 | } | |
2007 | ||
2008 | +char * | |
2009 | +auth_canonuser(struct auth_state *auth_state) | |
2010 | +{ | |
2011 | + if (auth_state) | |
2012 | + return auth_state->userid; | |
2013 | + return NULL; | |
2014 | +} | |
2015 | + | |
2016 | diff -Naur cyrus-imapd-2.2.12/lib/auth_krb5.c cyrus-imapd-2.2.12.autocreate2/lib/auth_krb5.c | |
2017 | --- cyrus-imapd-2.2.12/lib/auth_krb5.c 2004-01-16 17:28:58.000000000 +0200 | |
2018 | +++ cyrus-imapd-2.2.12.autocreate2/lib/auth_krb5.c 2005-10-19 14:48:58.040108000 +0300 | |
2019 | @@ -193,4 +193,11 @@ | |
2020 | free(auth_state); | |
2021 | } | |
2022 | ||
2023 | +char * | |
2024 | +auth_canonuser(struct auth_state *auth_state) | |
2025 | +{ | |
2026 | + if (auth_state) | |
2027 | + return auth_state->userid; | |
2028 | + return NULL; | |
2029 | +} | |
2030 | ||
2031 | diff -Naur cyrus-imapd-2.2.12/lib/auth_pts.c cyrus-imapd-2.2.12.autocreate2/lib/auth_pts.c | |
2032 | --- cyrus-imapd-2.2.12/lib/auth_pts.c 2004-02-25 01:11:37.000000000 +0200 | |
2033 | +++ cyrus-imapd-2.2.12.autocreate2/lib/auth_pts.c 2005-10-19 14:48:58.042343000 +0300 | |
2034 | @@ -349,3 +349,11 @@ | |
2035 | { | |
2036 | free(auth_state); | |
2037 | } | |
2038 | + | |
2039 | +char *auth_canonuser(struct auth_state *auth_state) | |
2040 | +{ | |
2041 | + if (auth_state) | |
2042 | + return auth_state->userid.id; | |
2043 | + return NULL; | |
2044 | +} | |
2045 | + | |
2046 | diff -Naur cyrus-imapd-2.2.12/lib/auth_unix.c cyrus-imapd-2.2.12.autocreate2/lib/auth_unix.c | |
2047 | --- cyrus-imapd-2.2.12/lib/auth_unix.c 2004-09-14 01:49:29.000000000 +0300 | |
2048 | +++ cyrus-imapd-2.2.12.autocreate2/lib/auth_unix.c 2005-10-19 14:48:58.044431000 +0300 | |
2049 | @@ -267,4 +267,11 @@ | |
2050 | free((char *)auth_state); | |
2051 | } | |
2052 | ||
2053 | +char *auth_canonuser(struct auth_state *auth_state) | |
2054 | +{ | |
2055 | + if (auth_state) | |
2056 | + return auth_state->userid; | |
2057 | + | |
2058 | + return NULL; | |
2059 | +} | |
2060 | ||
2061 | diff -Naur cyrus-imapd-2.2.12/lib/imapoptions cyrus-imapd-2.2.12.autocreate2/lib/imapoptions | |
2062 | --- cyrus-imapd-2.2.12/lib/imapoptions 2004-07-21 22:07:45.000000000 +0300 | |
2063 | +++ cyrus-imapd-2.2.12.autocreate2/lib/imapoptions 2005-10-19 14:48:58.048748000 +0300 | |
2064 | @@ -169,6 +169,51 @@ | |
2065 | /* Number of seconds to wait before returning a timeout failure when | |
2066 | performing a client connection (e.g. in a murder enviornment) */ | |
2067 | ||
2068 | +{ "createonpost", 0, SWITCH } | |
2069 | +/* If yes, when lmtpd receives an incoming mail for an INBOX that does not exist, | |
2070 | + then the INBOX is automatically created by lmtpd. */ | |
2071 | + | |
2072 | +{ "autocreateinboxfolders", NULL, STRING } | |
2073 | +/* If a user does not have an INBOX created then the INBOX as well as some INBOX subfolders are | |
2074 | + created under two conditions. | |
2075 | + 1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value) | |
2076 | + 2. A message arrives for the user through the LMTPD protocol.(createonpost option must yes) | |
2077 | + autocreateinboxfolders is a list of INBOX's subfolders separated by a "|", that are automatically created by the server | |
2078 | + under the previous two situations. */ | |
2079 | + | |
2080 | +{ "autosubscribeinboxfolders", NULL, STRING } | |
2081 | +/* A list of folder names, separated by "|" that the users get automatically subscribed to, when their INBOX | |
2082 | + is created. | |
2083 | + These folder names must have been included in the autocreateinboxfolders option of the imapd.conf. */ | |
2084 | + | |
2085 | +{ "autosubscribesharedfolders", NULL, STRING } | |
2086 | +/* A list of shared folders (bulletin boards), separated by "|" that the users get | |
2087 | + automatically subscribed to, after their INBOX | |
2088 | + is created. The shared folder must have been created and the user must have the | |
2089 | + required permissions to get subscribed to the it. Otherwise the subscription fails. */ | |
2090 | + | |
2091 | +{ "autosubscribe_all_sharedfolders", 0, SWITCH } | |
2092 | +/* If set to yes then the user is automatically subscribed to all shared folders, one has permission | |
2093 | + to subscribe to. */ | |
2094 | + | |
2095 | +{ "autocreate_sieve_script", NULL, STRING } | |
2096 | +/* The full path of a file that contains a sieve script. This script automatically becomes a | |
2097 | + user's initial default sieve filter script. When this option is not defined, no default | |
2098 | + sieve filter is created. The file must be readable by the cyrus daemon. */ | |
2099 | + | |
2100 | +{ "autocreate_sieve_compiledscript", NULL, STRING } | |
2101 | +/* The full path of a file that contains a compiled in bytecode sieve script. This script | |
2102 | + automatically becomes a user's initial default sieve filter script. | |
2103 | + If this option is not specified, or the filename doesn't exist then the script defined | |
2104 | + by autocreate_sieve_script is compiled on the fly and installed as the user's default | |
2105 | + sieve script */ | |
2106 | + | |
2107 | +{ "generate_compiled_sieve_script", 0, SWITCH } | |
2108 | +/* If set to yes and no compiled sieve script file exists then the sieve script that is | |
2109 | + compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript | |
2110 | + option points. In order a compiled script to be generated, autocreate_sieve_script and | |
2111 | + autocreate_sieve_compiledscript must have valid values */ | |
2112 | + | |
2113 | { "configdirectory", NULL, STRING } | |
2114 | /* The pathname of the IMAP configuration directory. This field is | |
2115 | required. */ | |
2116 | diff -Naur cyrus-imapd-2.2.12/notifyd/Makefile.in cyrus-imapd-2.2.12.autocreate2/notifyd/Makefile.in | |
2117 | --- cyrus-imapd-2.2.12/notifyd/Makefile.in 2004-05-28 21:03:06.000000000 +0300 | |
2118 | +++ cyrus-imapd-2.2.12.autocreate2/notifyd/Makefile.in 2005-10-19 14:48:58.050575000 +0300 | |
2119 | @@ -69,10 +69,11 @@ | |
2120 | SERVICE=../master/service.o | |
2121 | ||
2122 | IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@ | |
2123 | +SIEVE_LIBS = @SIEVE_LIBS@ | |
2124 | IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@ | |
2125 | LIB_WRAP = @LIB_WRAP@ | |
2126 | LIBS = @ZEPHYR_LIBS@ @LIBS@ $(IMAP_COM_ERR_LIBS) | |
2127 | -DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ | |
2128 | +DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ | |
2129 | ||
2130 | PURIFY=/usr/local/bin/purify | |
2131 | PUREOPT=-best-effort | |
2132 | diff -Naur cyrus-imapd-2.2.12/notifyd/notifyd.c cyrus-imapd-2.2.12.autocreate2/notifyd/notifyd.c | |
2133 | --- cyrus-imapd-2.2.12/notifyd/notifyd.c 2004-12-17 18:32:25.000000000 +0200 | |
2134 | +++ cyrus-imapd-2.2.12.autocreate2/notifyd/notifyd.c 2005-10-19 14:48:58.052220000 +0300 | |
2135 | @@ -97,7 +97,7 @@ | |
2136 | ||
2137 | #define NOTIFY_MAXSIZE 8192 | |
2138 | ||
2139 | -int do_notify() | |
2140 | +static int do_notify() | |
2141 | { | |
2142 | struct sockaddr_un sun_data; | |
2143 | socklen_t sunlen = sizeof(sun_data); | |
2144 | diff -Naur cyrus-imapd-2.2.12/ptclient/Makefile.in cyrus-imapd-2.2.12.autocreate2/ptclient/Makefile.in | |
2145 | --- cyrus-imapd-2.2.12/ptclient/Makefile.in 2004-05-28 21:03:08.000000000 +0300 | |
2146 | +++ cyrus-imapd-2.2.12.autocreate2/ptclient/Makefile.in 2005-10-19 14:48:58.053762000 +0300 | |
2147 | @@ -57,10 +57,11 @@ | |
2148 | AFS_LDFLAGS = @AFS_LDFLAGS@ @COM_ERR_LDFLAGS@ | |
2149 | AFS_LIBS = @AFS_LIBS@ | |
2150 | IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@ | |
2151 | +SIEVE_LIBS = @SIEVE_LIBS@ | |
2152 | LIBS = $(IMAP_LIBS) @COM_ERR_LIBS@ | |
2153 | LIB_SASL = @LIB_SASL@ | |
2154 | LIB_WRAP = @LIB_WRAP@ | |
2155 | -DEPLIBS = ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ | |
2156 | +DEPLIBS = ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ | |
2157 | UTIL_LIBS = ../imap/mutex_fake.o ../imap/cli_fatal.o | |
2158 | ||
2159 | LDAP_LIBS=@LDAP_LIBS@ |