Allow to set mailbox permissions using fileinto Sieve action.
* mailbox/permstr.c: New file. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add permstr.c. * imap4d/imap4d.c (parse_mode_spec): Remove function. (cb_mailbox_mode): Use mu_parse_stream_perm_string instead of parse_mode_spec. * imap4d/imap4d.h (namespace_getfullpath) (namespace_checkfullpath): First arg is const. * imap4d/namespace.c (namespace_getfullpath) (namespace_checkfullpath): First arg is const. * include/mailutils/message.h (mu_message_save_to_mailbox): Add 5th argument (permissions). * mailbox/message.c: Likewise. * include/mailutils/mutil.h (mu_parse_stream_perm_string): New proto. (mu_stream_flags_to_mode): Add isdir argument. * libsieve/actions.c (sieve_action_fileinto): New tag :permissions allows to set permissions to the mailbox being created. * mailbox/mutil.c (mu_stream_flags_to_mode): Add 2nd argument (isdir). Any bits in [go] sets imply raising 'x' bit for directories (i.e. if isdir != 0). * libproto/maildir/mbox.c, mailbox/amd.c: Update calls to mu_stream_flags_to_mode. * NEWS, doc/texinfo/sieve.texi: Update. Allow to set file permissions of the local mailboxes during creation.
Showing
16 changed files
with
346 additions
and
120 deletions
1 | 2008-11-07 Sergey Poznyakoff <gray@gnu.org.ua> | 1 | 2008-11-07 Sergey Poznyakoff <gray@gnu.org.ua> |
2 | 2 | ||
3 | Allow to set mailbox permissions using fileinto Sieve action. | ||
4 | |||
5 | * mailbox/permstr.c: New file. | ||
6 | * mailbox/Makefile.am (libmailutils_la_SOURCES): Add permstr.c. | ||
7 | * imap4d/imap4d.c (parse_mode_spec): Remove function. | ||
8 | (cb_mailbox_mode): Use mu_parse_stream_perm_string instead of | ||
9 | parse_mode_spec. | ||
10 | * imap4d/imap4d.h (namespace_getfullpath) | ||
11 | (namespace_checkfullpath): First arg is const. | ||
12 | * imap4d/namespace.c (namespace_getfullpath) | ||
13 | (namespace_checkfullpath): First arg is const. | ||
14 | * include/mailutils/message.h (mu_message_save_to_mailbox): Add | ||
15 | 5th argument (permissions). | ||
16 | * mailbox/message.c: Likewise. | ||
17 | * include/mailutils/mutil.h (mu_parse_stream_perm_string): New | ||
18 | proto. | ||
19 | (mu_stream_flags_to_mode): Add isdir argument. | ||
20 | * libsieve/actions.c (sieve_action_fileinto): New tag :permissions | ||
21 | allows to set permissions to the mailbox being created. | ||
22 | * mailbox/mutil.c (mu_stream_flags_to_mode): Add 2nd argument | ||
23 | (isdir). Any bits in [go] sets imply raising 'x' bit for | ||
24 | directories (i.e. if isdir != 0). | ||
25 | |||
26 | * libproto/maildir/mbox.c, mailbox/amd.c: Update calls to | ||
27 | mu_stream_flags_to_mode. | ||
28 | |||
29 | * NEWS, doc/texinfo/sieve.texi: Update. | ||
30 | |||
3 | Allow to set file permissions of the local mailboxes during | 31 | Allow to set file permissions of the local mailboxes during |
4 | creation. | 32 | creation. |
5 | 33 | ... | ... |
1 | GNU mailutils NEWS -- history of user-visible changes. 2008-10-23 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2008-11-07 |
2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, |
3 | 2008 Free Software Foundation, Inc. | 3 | 2008 Free Software Foundation, Inc. |
4 | See the end of file for copying conditions. | 4 | See the end of file for copying conditions. |
... | @@ -61,7 +61,9 @@ message', below. | ... | @@ -61,7 +61,9 @@ message', below. |
61 | The communication protocol has been modified to make this possible. | 61 | The communication protocol has been modified to make this possible. |
62 | The traditional comsat protocol is supported as well. | 62 | The traditional comsat protocol is supported as well. |
63 | 63 | ||
64 | ** New Sieve action `pipe' | 64 | ** Sieve |
65 | |||
66 | *** New Sieve action `pipe' | ||
65 | 67 | ||
66 | Syntax: pipe [:envelope] <command line: string> | 68 | Syntax: pipe [:envelope] <command line: string> |
67 | 69 | ||
... | @@ -69,6 +71,18 @@ This action executes the given <command line> and pipes the message to | ... | @@ -69,6 +71,18 @@ This action executes the given <command line> and pipes the message to |
69 | its standard input. If the :envelope tag is given, the envelope of the | 71 | its standard input. If the :envelope tag is given, the envelope of the |
70 | message is piped as well. | 72 | message is piped as well. |
71 | 73 | ||
74 | *** Fileinto :permissions | ||
75 | |||
76 | The `fileinto' action takes a tag :permissions that allows to set | ||
77 | permissions on the mailbox, in case it is created. Its argument is a | ||
78 | string, similar to that used in chmod(1): | ||
79 | |||
80 | [go](+|=)[rw] | ||
81 | |||
82 | For example: | ||
83 | |||
84 | fileinto :permissions "g=rw,o=r" "/shared/mailbox" | ||
85 | |||
72 | ** Client SMTP STARTTLS support | 86 | ** Client SMTP STARTTLS support |
73 | 87 | ||
74 | ** Support for new protocols: POPS (pops://) and IMAPS (imaps://), | 88 | ** Support for new protocols: POPS (pops://) and IMAPS (imaps://), | ... | ... |
1 | @c This is part of the GNU Mailutils manual. | 1 | @c This is part of the GNU Mailutils manual. |
2 | @c Copyright (C) 1999,2000,2001,2002,2003,2004, | 2 | @c Copyright (C) 1999,2000,2001,2002,2003,2004, |
3 | @c 2007 Free Software Foundation, Inc. | 3 | @c 2007, 2008 Free Software Foundation, Inc. |
4 | @c See file mailutils.texi for copying conditions. | 4 | @c See file mailutils.texi for copying conditions. |
5 | @comment ******************************************************************* | 5 | @comment ******************************************************************* |
6 | 6 | ||
... | @@ -929,7 +929,7 @@ if header :contains ["from"] ["idiot@@example.edu"] | ... | @@ -929,7 +929,7 @@ if header :contains ["from"] ["idiot@@example.edu"] |
929 | @end smallexample | 929 | @end smallexample |
930 | @end deffn | 930 | @end deffn |
931 | 931 | ||
932 | @deffn Action fileinto @var{folder} | 932 | @deffn Action fileinto [:permissions @var{mode}] @var{folder} |
933 | @noindent | 933 | @noindent |
934 | 934 | ||
935 | Required arguments: | 935 | Required arguments: |
... | @@ -939,7 +939,74 @@ Required arguments: | ... | @@ -939,7 +939,74 @@ Required arguments: |
939 | A string representing the folder name | 939 | A string representing the folder name |
940 | @end table | 940 | @end table |
941 | 941 | ||
942 | The @code{fileinto} action delivers the message into the specified folder. | 942 | @noindent |
943 | Tagged arguments: | ||
944 | |||
945 | @table @code | ||
946 | @item :permissions @var{mode} | ||
947 | Specifies the permissions to use, if the mailbox is created. | ||
948 | @end table | ||
949 | |||
950 | The @code{fileinto} action delivers the message into the specified | ||
951 | folder. If the folder is local, it is created using permissions | ||
952 | @samp{0600}, for regular files, and @samp{0700} for directories. This | ||
953 | default can be changed by using the @code{:permissions} tag. Its | ||
954 | argument is a mode specification, similar to that used by | ||
955 | @command{chmod} shell utility. It is a list of permissions settings | ||
956 | separated by commas. Each setting begins with one of the following | ||
957 | letters: | ||
958 | |||
959 | @table @asis | ||
960 | @item g | ||
961 | Set permissions for the users in the file group. | ||
962 | |||
963 | @item o | ||
964 | Set permissions for users not in the file's group. | ||
965 | @end table | ||
966 | |||
967 | This letter must be followed by either @samp{+} or @samp{=} and the | ||
968 | list of permissions to be set. This latter list is a string | ||
969 | containing any one or both of the following characters: | ||
970 | |||
971 | @table @asis | ||
972 | @item r | ||
973 | Grant permission to read. | ||
974 | |||
975 | @item w | ||
976 | Grant permission to write. | ||
977 | @end table | ||
978 | |||
979 | For example, the following instruction creates the mailbox | ||
980 | @file{~/shared} which will be world readable and writable | ||
981 | for the group: | ||
982 | |||
983 | @smallexample | ||
984 | fileinto :permissions "g=rw,o=r" "~/shared" | ||
985 | @end smallexample | ||
986 | |||
987 | Notice that: | ||
988 | |||
989 | @enumerate 1 | ||
990 | @item | ||
991 | The @code{:permissions} setting are affected by the current umask | ||
992 | value. | ||
993 | |||
994 | @item | ||
995 | Only @code{r} and @code{w} permissions can be set, since other | ||
996 | permissions do not seem to be useful for mailboxes. However, for | ||
997 | mailboxes that have a directory structure (such as maildir and MH), | ||
998 | any settings in @samp{g} and @samp{o} sets imply setting the | ||
999 | executable bit. | ||
1000 | |||
1001 | @item | ||
1002 | Owner's permissions cannot be set. The owner always has all | ||
1003 | permissions on the mailbox he created. | ||
1004 | |||
1005 | @item | ||
1006 | The @code{:permissions} settings apply only to local mailboxes. They | ||
1007 | are ignored for remote mailboxes. | ||
1008 | @end enumerate | ||
1009 | |||
943 | @end deffn | 1010 | @end deffn |
944 | 1011 | ||
945 | @deffn Action reject @var{reason} | 1012 | @deffn Action reject @var{reason} | ... | ... |
... | @@ -284,101 +284,13 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val) | ... | @@ -284,101 +284,13 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val) |
284 | return 0; | 284 | return 0; |
285 | } | 285 | } |
286 | 286 | ||
287 | #define FILE_MODE_READ 0x1 | ||
288 | #define FILE_MODE_WRITE 0x2 | ||
289 | |||
290 | static int | ||
291 | parse_mode_bits (int *pmode, const char *str, const char **endp) | ||
292 | { | ||
293 | switch (*str) | ||
294 | { | ||
295 | case '+': | ||
296 | case '=': | ||
297 | str++; | ||
298 | break; | ||
299 | |||
300 | default: | ||
301 | *endp = str; | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | for (; *str; str++) | ||
306 | { | ||
307 | switch (*str) | ||
308 | { | ||
309 | case 'r': | ||
310 | *pmode |= FILE_MODE_READ; | ||
311 | break; | ||
312 | |||
313 | case 'w': | ||
314 | *pmode |= FILE_MODE_WRITE; | ||
315 | break; | ||
316 | |||
317 | case ',': | ||
318 | *endp = str; | ||
319 | return 0; | ||
320 | |||
321 | default: | ||
322 | *endp = str; | ||
323 | return 1; | ||
324 | } | ||
325 | } | ||
326 | *endp = str; | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int | ||
331 | parse_mode_spec (int *pmode, const char *str, const char **endp) | ||
332 | { | ||
333 | int mode = 0; | ||
334 | int f; | ||
335 | while (*str) | ||
336 | { | ||
337 | switch (*str) | ||
338 | { | ||
339 | case 'g': | ||
340 | if (parse_mode_bits (&f, str + 1, &str)) | ||
341 | { | ||
342 | *endp = str; | ||
343 | return 1; | ||
344 | } | ||
345 | if (f & FILE_MODE_READ) | ||
346 | mode |= MU_STREAM_IRGRP; | ||
347 | if (f & FILE_MODE_WRITE) | ||
348 | mode |= MU_STREAM_IWGRP; | ||
349 | break; | ||
350 | |||
351 | case 'o': | ||
352 | if (parse_mode_bits (&f, str + 1, &str)) | ||
353 | { | ||
354 | *endp = str; | ||
355 | return 1; | ||
356 | } | ||
357 | if (f & FILE_MODE_READ) | ||
358 | mode |= MU_STREAM_IROTH; | ||
359 | if (f & FILE_MODE_WRITE) | ||
360 | mode |= MU_STREAM_IWOTH; | ||
361 | break; | ||
362 | |||
363 | default: | ||
364 | *endp = str; | ||
365 | return 1; | ||
366 | } | ||
367 | if (*str == ',') | ||
368 | str++; | ||
369 | } | ||
370 | *pmode = mode; | ||
371 | *endp = str; | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int | 287 | static int |
376 | cb_mailbox_mode (mu_debug_t debug, void *data, mu_config_value_t *val) | 288 | cb_mailbox_mode (mu_debug_t debug, void *data, mu_config_value_t *val) |
377 | { | 289 | { |
378 | char *p; | 290 | const char *p; |
379 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug)) | 291 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug)) |
380 | return 1; | 292 | return 1; |
381 | if (parse_mode_spec ((int *)data, val->v.string, &p)) | 293 | if (mu_parse_stream_perm_string ((int *)data, val->v.string, &p)) |
382 | mu_cfg_format_error (debug, MU_DEBUG_ERROR, | 294 | mu_cfg_format_error (debug, MU_DEBUG_ERROR, |
383 | _("invalid mode string near %s"), p); | 295 | _("invalid mode string near %s"), p); |
384 | return 0; | 296 | return 0; | ... | ... |
... | @@ -283,8 +283,9 @@ extern mu_list_t namespace[NS_MAX]; | ... | @@ -283,8 +283,9 @@ extern mu_list_t namespace[NS_MAX]; |
283 | 283 | ||
284 | extern int namespace_init_session (char *path); | 284 | extern int namespace_init_session (char *path); |
285 | extern void namespace_init (void); | 285 | extern void namespace_init (void); |
286 | extern char *namespace_getfullpath (char *name, const char *delim, int *pns); | 286 | extern char *namespace_getfullpath (const char *name, const char *delim, |
287 | extern char *namespace_checkfullpath (char *name, const char *pattern, | 287 | int *pns); |
288 | extern char *namespace_checkfullpath (const char *name, const char *pattern, | ||
288 | const char *delim, int *pns); | 289 | const char *delim, int *pns); |
289 | int imap4d_session_setup (char *username); | 290 | int imap4d_session_setup (char *username); |
290 | int imap4d_session_setup0 (void); | 291 | int imap4d_session_setup0 (void); | ... | ... |
... | @@ -166,11 +166,12 @@ risky_pattern (const char *pattern, int delim) | ... | @@ -166,11 +166,12 @@ risky_pattern (const char *pattern, int delim) |
166 | } | 166 | } |
167 | 167 | ||
168 | char * | 168 | char * |
169 | namespace_checkfullpath (char *name, const char *pattern, const char *delim, | 169 | namespace_checkfullpath (const char *name, const char *pattern, |
170 | int *nspace) | 170 | const char *delim, int *nspace) |
171 | { | 171 | { |
172 | struct namespace_info info; | 172 | struct namespace_info info; |
173 | char *p, *path = NULL; | 173 | const char *p; |
174 | char *path = NULL; | ||
174 | char *scheme = NULL; | 175 | char *scheme = NULL; |
175 | 176 | ||
176 | p = strchr (name, ':'); | 177 | p = strchr (name, ':'); |
... | @@ -226,17 +227,18 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim, | ... | @@ -226,17 +227,18 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim, |
226 | } | 227 | } |
227 | 228 | ||
228 | char * | 229 | char * |
229 | namespace_getfullpath (char *name, const char *delim, int *nspace) | 230 | namespace_getfullpath (const char *name, const char *delim, int *nspace) |
230 | { | 231 | { |
232 | char *ret; | ||
231 | if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) | 233 | if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) |
232 | { | 234 | { |
233 | name = strdup (auth_data->mailbox); | 235 | ret = strdup (auth_data->mailbox); |
234 | if (nspace) | 236 | if (nspace) |
235 | *nspace = NS_PRIVATE; | 237 | *nspace = NS_PRIVATE; |
236 | } | 238 | } |
237 | else | 239 | else |
238 | name = namespace_checkfullpath (name, NULL, delim, nspace); | 240 | ret = namespace_checkfullpath (name, NULL, delim, nspace); |
239 | return name; | 241 | return ret; |
240 | } | 242 | } |
241 | 243 | ||
242 | int | 244 | int | ... | ... |
... | @@ -124,7 +124,8 @@ extern int mu_message_get_attachment_name (mu_message_t, char *name, | ... | @@ -124,7 +124,8 @@ extern int mu_message_get_attachment_name (mu_message_t, char *name, |
124 | extern int mu_message_aget_attachment_name (mu_message_t, char **name); | 124 | extern int mu_message_aget_attachment_name (mu_message_t, char **name); |
125 | 125 | ||
126 | extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, | 126 | extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, |
127 | mu_debug_t debug, const char *toname); | 127 | mu_debug_t debug, const char *toname, |
128 | int perms); | ||
128 | 129 | ||
129 | 130 | ||
130 | extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg); | 131 | extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg); | ... | ... |
... | @@ -155,7 +155,10 @@ extern size_t mu_strftime (char *s, size_t max, const char *format, | ... | @@ -155,7 +155,10 @@ extern size_t mu_strftime (char *s, size_t max, const char *format, |
155 | extern int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, | 155 | extern int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, |
156 | int *perr); | 156 | int *perr); |
157 | 157 | ||
158 | extern int mu_stream_flags_to_mode (int flags); | 158 | extern int mu_stream_flags_to_mode (int flags, int isdir); |
159 | |||
160 | extern int mu_parse_stream_perm_string (int *pmode, const char *str, | ||
161 | const char **endp); | ||
159 | 162 | ||
160 | 163 | ||
161 | #ifdef __cplusplus | 164 | #ifdef __cplusplus | ... | ... |
... | @@ -435,7 +435,8 @@ maildir_create (struct _amd_data *amd, int flags) | ... | @@ -435,7 +435,8 @@ maildir_create (struct _amd_data *amd, int flags) |
435 | char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL); | 435 | char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL); |
436 | int rc = maildir_opendir (&dir, tmpname, | 436 | int rc = maildir_opendir (&dir, tmpname, |
437 | PERMS | | 437 | PERMS | |
438 | mu_stream_flags_to_mode (amd->mailbox->flags)); | 438 | mu_stream_flags_to_mode (amd->mailbox->flags, |
439 | 1)); | ||
439 | if (rc) | 440 | if (rc) |
440 | return rc; | 441 | return rc; |
441 | closedir (dir); | 442 | closedir (dir); |
... | @@ -528,7 +529,8 @@ maildir_flush (struct _amd_data *amd) | ... | @@ -528,7 +529,8 @@ maildir_flush (struct _amd_data *amd) |
528 | char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL); | 529 | char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL); |
529 | 530 | ||
530 | rc = maildir_opendir (&dir, tmpname, | 531 | rc = maildir_opendir (&dir, tmpname, |
531 | PERMS | mu_stream_flags_to_mode (amd->mailbox->flags)); | 532 | PERMS | |
533 | mu_stream_flags_to_mode (amd->mailbox->flags, 1)); | ||
532 | if (rc) | 534 | if (rc) |
533 | { | 535 | { |
534 | free (tmpname); | 536 | free (tmpname); |
... | @@ -668,7 +670,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -668,7 +670,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
668 | name = maildir_mkfilename (amd->name, NEWSUF, NULL); | 670 | name = maildir_mkfilename (amd->name, NEWSUF, NULL); |
669 | 671 | ||
670 | status = maildir_opendir (&dir, name, | 672 | status = maildir_opendir (&dir, name, |
671 | PERMS | mu_stream_flags_to_mode (mailbox->flags)); | 673 | PERMS | |
674 | mu_stream_flags_to_mode (mailbox->flags, 1)); | ||
672 | if (status == 0) | 675 | if (status == 0) |
673 | { | 676 | { |
674 | maildir_deliver_new (amd, dir); | 677 | maildir_deliver_new (amd, dir); |
... | @@ -679,7 +682,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -679,7 +682,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
679 | name = maildir_mkfilename (amd->name, CURSUF, NULL); | 682 | name = maildir_mkfilename (amd->name, CURSUF, NULL); |
680 | /* 3rd phase: Scan cur/ */ | 683 | /* 3rd phase: Scan cur/ */ |
681 | status = maildir_opendir (&dir, name, | 684 | status = maildir_opendir (&dir, name, |
682 | PERMS | mu_stream_flags_to_mode (mailbox->flags)); | 685 | PERMS | |
686 | mu_stream_flags_to_mode (mailbox->flags, 1)); | ||
683 | if (status == 0) | 687 | if (status == 0) |
684 | { | 688 | { |
685 | status = maildir_scan_dir (amd, dir, CURSUF); | 689 | status = maildir_scan_dir (amd, dir, CURSUF); | ... | ... |
... | @@ -79,19 +79,34 @@ static int | ... | @@ -79,19 +79,34 @@ static int |
79 | sieve_action_fileinto (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | 79 | sieve_action_fileinto (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) |
80 | { | 80 | { |
81 | int rc; | 81 | int rc; |
82 | int mbflags = 0; | ||
83 | mu_sieve_value_t *opt; | ||
82 | mu_sieve_value_t *val = mu_sieve_value_get (args, 0); | 84 | mu_sieve_value_t *val = mu_sieve_value_get (args, 0); |
83 | if (!val) | 85 | if (!val) |
84 | { | 86 | { |
85 | mu_sieve_error (mach, _("cannot get filename!")); | 87 | mu_sieve_error (mach, _("cannot get filename!")); |
86 | mu_sieve_abort (mach); | 88 | mu_sieve_abort (mach); |
87 | } | 89 | } |
90 | |||
91 | if (mu_sieve_tag_lookup (tags, "permissions", &opt)) | ||
92 | { | ||
93 | const char *p; | ||
94 | |||
95 | if (mu_parse_stream_perm_string (&mbflags, opt->v.string, &p)) | ||
96 | { | ||
97 | /* Should not happen, but anyway... */ | ||
98 | mu_sieve_error (mach, _("invalid permissions (near %s)"), p); | ||
99 | return 1; | ||
100 | } | ||
101 | } | ||
102 | |||
88 | mu_sieve_log_action (mach, "FILEINTO", | 103 | mu_sieve_log_action (mach, "FILEINTO", |
89 | _("delivering into %s"), val->v.string); | 104 | _("delivering into %s"), val->v.string); |
90 | if (mu_sieve_is_dry_run (mach)) | 105 | if (mu_sieve_is_dry_run (mach)) |
91 | return 0; | 106 | return 0; |
92 | 107 | ||
93 | rc = mu_message_save_to_mailbox (mach->msg, mach->ticket, mach->debug, | 108 | rc = mu_message_save_to_mailbox (mach->msg, mach->ticket, mach->debug, |
94 | val->v.string); | 109 | val->v.string, mbflags); |
95 | if (rc) | 110 | if (rc) |
96 | mu_sieve_error (mach, _("cannot save to mailbox: %s"), | 111 | mu_sieve_error (mach, _("cannot save to mailbox: %s"), |
97 | mu_strerror (rc)); | 112 | mu_strerror (rc)); |
... | @@ -506,14 +521,54 @@ mu_sieve_data_type fileinto_args[] = { | ... | @@ -506,14 +521,54 @@ mu_sieve_data_type fileinto_args[] = { |
506 | SVT_VOID | 521 | SVT_VOID |
507 | }; | 522 | }; |
508 | 523 | ||
524 | static int | ||
525 | perms_tag_checker (const char *name, mu_list_t tags, mu_list_t args) | ||
526 | { | ||
527 | mu_iterator_t itr; | ||
528 | int err = 0; | ||
529 | |||
530 | if (!tags || mu_list_get_iterator (tags, &itr)) | ||
531 | return 0; | ||
532 | for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr); | ||
533 | mu_iterator_next (itr)) | ||
534 | { | ||
535 | int flag; | ||
536 | char *p; | ||
537 | mu_sieve_runtime_tag_t *t; | ||
538 | mu_iterator_current (itr, (void **)&t); | ||
539 | if (strcmp (t->tag, "permissions") == 0) | ||
540 | { | ||
541 | if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p)) | ||
542 | { | ||
543 | mu_sv_compile_error (&mu_sieve_locus, | ||
544 | _("invalid permissions (near %s)"), p); | ||
545 | err = 1; | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | mu_iterator_destroy (&itr); | ||
550 | return err; | ||
551 | } | ||
552 | |||
553 | static mu_sieve_tag_def_t perms_tags[] = { | ||
554 | { "permissions", SVT_STRING }, | ||
555 | { NULL } | ||
556 | }; | ||
557 | |||
558 | static mu_sieve_tag_group_t fileinto_tag_groups[] = { | ||
559 | { perms_tags, perms_tag_checker }, | ||
560 | { NULL } | ||
561 | }; | ||
562 | |||
509 | void | 563 | void |
510 | mu_sv_register_standard_actions (mu_sieve_machine_t mach) | 564 | mu_sv_register_standard_actions (mu_sieve_machine_t mach) |
511 | { | 565 | { |
512 | mu_sieve_register_action (mach, "stop", sieve_action_stop, NULL, NULL, 1); | 566 | mu_sieve_register_action (mach, "stop", sieve_action_stop, NULL, NULL, 1); |
513 | mu_sieve_register_action (mach, "keep", sieve_action_keep, NULL, NULL, 1); | 567 | mu_sieve_register_action (mach, "keep", sieve_action_keep, NULL, NULL, 1); |
514 | mu_sieve_register_action (mach, "discard", sieve_action_discard, NULL, NULL, 1); | 568 | mu_sieve_register_action (mach, "discard", sieve_action_discard, |
569 | NULL, NULL, 1); | ||
515 | mu_sieve_register_action (mach, "fileinto", sieve_action_fileinto, | 570 | mu_sieve_register_action (mach, "fileinto", sieve_action_fileinto, |
516 | fileinto_args, NULL, 0); | 571 | fileinto_args, fileinto_tag_groups, 0); |
517 | mu_sieve_register_action (mach, "reject", sieve_action_reject, fileinto_args, | 572 | mu_sieve_register_action (mach, "reject", sieve_action_reject, fileinto_args, |
518 | NULL, 0); | 573 | NULL, 0); |
519 | mu_sieve_register_action (mach, "redirect", sieve_action_redirect, | 574 | mu_sieve_register_action (mach, "redirect", sieve_action_redirect, | ... | ... |
... | @@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ | ... | @@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ |
108 | opool.c\ | 108 | opool.c\ |
109 | parse822.c\ | 109 | parse822.c\ |
110 | parsedate.c\ | 110 | parsedate.c\ |
111 | permstr.c\ | ||
111 | progmailer.c\ | 112 | progmailer.c\ |
112 | property.c\ | 113 | property.c\ |
113 | registrar.c\ | 114 | registrar.c\ | ... | ... |
... | @@ -336,9 +336,8 @@ amd_open (mu_mailbox_t mailbox, int flags) | ... | @@ -336,9 +336,8 @@ amd_open (mu_mailbox_t mailbox, int flags) |
336 | if ((flags & MU_STREAM_CREAT) && errno == ENOENT) | 336 | if ((flags & MU_STREAM_CREAT) && errno == ENOENT) |
337 | { | 337 | { |
338 | int rc; | 338 | int rc; |
339 | 339 | int perms = mu_stream_flags_to_mode (flags, 1); | |
340 | if (mkdir (amd->name, | 340 | if (mkdir (amd->name, S_IRUSR|S_IWUSR|S_IXUSR|perms)) |
341 | S_IRUSR|S_IWUSR|S_IXUSR|mu_stream_flags_to_mode (flags))) | ||
342 | return errno; | 341 | return errno; |
343 | if (stat (amd->name, &st) < 0) | 342 | if (stat (amd->name, &st) < 0) |
344 | return errno; | 343 | return errno; | ... | ... |
... | @@ -488,7 +488,7 @@ _file_open (mu_stream_t stream) | ... | @@ -488,7 +488,7 @@ _file_open (mu_stream_t stream) |
488 | return errno; | 488 | return errno; |
489 | /* Race condition here when creating the file ??. */ | 489 | /* Race condition here when creating the file ??. */ |
490 | fd = open (filename, flg|O_CREAT|O_EXCL, | 490 | fd = open (filename, flg|O_CREAT|O_EXCL, |
491 | 0600 | mu_stream_flags_to_mode (flags)); | 491 | 0600 | mu_stream_flags_to_mode (flags, 0)); |
492 | if (fd < 0) | 492 | if (fd < 0) |
493 | return errno; | 493 | return errno; |
494 | } | 494 | } | ... | ... |
... | @@ -1112,7 +1112,7 @@ message_body_read (mu_stream_t stream, char *buffer, size_t n, mu_off_t off, | ... | @@ -1112,7 +1112,7 @@ message_body_read (mu_stream_t stream, char *buffer, size_t n, mu_off_t off, |
1112 | int | 1112 | int |
1113 | mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, | 1113 | mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, |
1114 | mu_debug_t debug, | 1114 | mu_debug_t debug, |
1115 | const char *toname) | 1115 | const char *toname, int perms) |
1116 | { | 1116 | { |
1117 | int rc = 0; | 1117 | int rc = 0; |
1118 | mu_mailbox_t to = 0; | 1118 | mu_mailbox_t to = 0; |
... | @@ -1148,7 +1148,9 @@ mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, | ... | @@ -1148,7 +1148,9 @@ mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, |
1148 | } | 1148 | } |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | if ((rc = mu_mailbox_open (to, MU_STREAM_WRITE | MU_STREAM_CREAT))) | 1151 | if ((rc = mu_mailbox_open (to, |
1152 | MU_STREAM_WRITE | MU_STREAM_CREAT | ||
1153 | | (perms & MU_STREAM_IMASK)))) | ||
1152 | { | 1154 | { |
1153 | MU_DEBUG2 (debug, MU_DEBUG_ERROR, | 1155 | MU_DEBUG2 (debug, MU_DEBUG_ERROR, |
1154 | "mu_mailbox_open (%s) failed: %s\n", toname, | 1156 | "mu_mailbox_open (%s) failed: %s\n", toname, | ... | ... |
... | @@ -1491,7 +1491,7 @@ mu_sql_decode_password_type (const char *arg, enum mu_password_type *t) | ... | @@ -1491,7 +1491,7 @@ mu_sql_decode_password_type (const char *arg, enum mu_password_type *t) |
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | int | 1493 | int |
1494 | mu_stream_flags_to_mode (int flags) | 1494 | mu_stream_flags_to_mode (int flags, int isdir) |
1495 | { | 1495 | { |
1496 | int mode = 0; | 1496 | int mode = 0; |
1497 | if (flags & MU_STREAM_IRGRP) | 1497 | if (flags & MU_STREAM_IRGRP) |
... | @@ -1502,5 +1502,14 @@ mu_stream_flags_to_mode (int flags) | ... | @@ -1502,5 +1502,14 @@ mu_stream_flags_to_mode (int flags) |
1502 | mode |= S_IROTH; | 1502 | mode |= S_IROTH; |
1503 | if (flags & MU_STREAM_IWOTH) | 1503 | if (flags & MU_STREAM_IWOTH) |
1504 | mode |= S_IWOTH; | 1504 | mode |= S_IWOTH; |
1505 | |||
1506 | if (isdir) | ||
1507 | { | ||
1508 | if (mode & (S_IRGRP|S_IWGRP)) | ||
1509 | mode |= S_IXGRP; | ||
1510 | if (mode & (S_IROTH|S_IWOTH)) | ||
1511 | mode |= S_IXOTH; | ||
1512 | } | ||
1513 | |||
1505 | return mode; | 1514 | return mode; |
1506 | } | 1515 | } | ... | ... |
mailbox/permstr.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2008 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | #if HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | #include <mailutils/stream.h> | ||
23 | #include <mailutils/mutil.h> | ||
24 | #include <mailutils/errno.h> | ||
25 | |||
26 | #define FILE_PERM_READ 0x1 | ||
27 | #define FILE_PERM_WRITE 0x2 | ||
28 | |||
29 | static int | ||
30 | parse_perm_bits (int *pmode, const char *str, const char **endp) | ||
31 | { | ||
32 | switch (*str) | ||
33 | { | ||
34 | case '+': | ||
35 | case '=': | ||
36 | str++; | ||
37 | break; | ||
38 | |||
39 | default: | ||
40 | if (endp) | ||
41 | *endp = str; | ||
42 | return 1; | ||
43 | } | ||
44 | |||
45 | for (; *str; str++) | ||
46 | { | ||
47 | switch (*str) | ||
48 | { | ||
49 | case 'r': | ||
50 | *pmode |= FILE_PERM_READ; | ||
51 | break; | ||
52 | |||
53 | case 'w': | ||
54 | *pmode |= FILE_PERM_WRITE; | ||
55 | break; | ||
56 | |||
57 | case ',': | ||
58 | if (endp) | ||
59 | *endp = str; | ||
60 | return 0; | ||
61 | |||
62 | default: | ||
63 | if (endp) | ||
64 | *endp = str; | ||
65 | return 1; | ||
66 | } | ||
67 | } | ||
68 | if (endp) | ||
69 | *endp = str; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /* Parse a MU stream permission specification in form: | ||
74 | |||
75 | g(+|=)[wr]+,o(+|=)[wr]+ | ||
76 | |||
77 | Return 0 on success. | ||
78 | On failure, return MU_ERR_FAILURE and point endp to the offending character. | ||
79 | */ | ||
80 | int | ||
81 | mu_parse_stream_perm_string (int *pmode, const char *str, const char **endp) | ||
82 | { | ||
83 | int mode = 0; | ||
84 | int f; | ||
85 | while (*str) | ||
86 | { | ||
87 | switch (*str) | ||
88 | { | ||
89 | case 'g': | ||
90 | if (parse_perm_bits (&f, str + 1, &str)) | ||
91 | { | ||
92 | if (endp) | ||
93 | *endp = str; | ||
94 | return MU_ERR_FAILURE; | ||
95 | } | ||
96 | if (f & FILE_PERM_READ) | ||
97 | mode |= MU_STREAM_IRGRP; | ||
98 | if (f & FILE_PERM_WRITE) | ||
99 | mode |= MU_STREAM_IWGRP; | ||
100 | break; | ||
101 | |||
102 | case 'o': | ||
103 | if (parse_perm_bits (&f, str + 1, &str)) | ||
104 | { | ||
105 | if (endp) | ||
106 | *endp = str; | ||
107 | return MU_ERR_FAILURE; | ||
108 | } | ||
109 | if (f & FILE_PERM_READ) | ||
110 | mode |= MU_STREAM_IROTH; | ||
111 | if (f & FILE_PERM_WRITE) | ||
112 | mode |= MU_STREAM_IWOTH; | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | if (endp) | ||
117 | *endp = str; | ||
118 | return MU_ERR_FAILURE; | ||
119 | } | ||
120 | if (*str == ',') | ||
121 | str++; | ||
122 | } | ||
123 | *pmode = mode; | ||
124 | if (endp) | ||
125 | *endp = str; | ||
126 | return 0; | ||
127 | } | ||
128 |
-
Please register or sign in to post a comment