summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-09-12 18:44:59 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-09-13 16:43:40 +0300
commit661f53f37bfa6cd7562146ec4857413797bc8dd7 (patch)
tree104fe4a8e4629d4f8dfc09a9a27f5b9cdfe6447c
parent6a1aaa2561049ba404ad5bc05820ba830fbe4af0 (diff)
downloadmailutils-661f53f37bfa6cd7562146ec4857413797bc8dd7.tar.gz
mailutils-661f53f37bfa6cd7562146ec4857413797bc8dd7.tar.bz2
Mailbox quota support in imap4d: initial implementation.
* imap4d/quota.c: New file. * imap4d/Makefile.am (imap4d_SOURCES): Add quota.c * imap4d/append.c (imap4d_append0): Refuse to append if the quota is exceeded or would be exceeded after completing the operation. * imap4d/copy.c (imap4d_copy0): Refuse to copy messages if the quota is exceeded or would be exceeded after completing the operation. Return a meaningful textual description. Attempt to restore mailbox to its original size if the operation failed. * imap4d/imap4d.c (imap4d_session_setup0): Call quota_setup. * imap4d/imap4d.h (quota_setup, quota_check, quota_update): New functions. * include/mailutils/folder.h (mu_list_response) <format>: New member. * include/mailutils/mailbox.h (mu_mailbox_create_from_record): New function. * include/mailutils/types.hin (MU_FOLDER_ATTRIBUTE_LINK): New flag. * libproto/mbox/folder.c (list_helper): Do not return symbolic links unless MU_FOLDER_ATTRIBUTE_LINK is set. Fill in the resp->format member. * mailbox/mailbox.c (_mailbox_create_from_record): New static function. (_create_mailbox0): Rewrite as a wrapper over _mailbox_create_from_record. (mu_mailbox_create_from_record): New function. * guimb/scm/Makefile.am: Add sieve.scm to AM_INSTALLCHECK_STD_OPTIONS_EXEMPT.
-rw-r--r--NEWS3
-rw-r--r--configure.ac6
-rw-r--r--guimb/scm/Makefile.am5
-rw-r--r--imap4d/Makefile.am1
-rw-r--r--imap4d/append.c48
-rw-r--r--imap4d/copy.c170
-rw-r--r--imap4d/imap4d.c5
-rw-r--r--imap4d/imap4d.h7
-rw-r--r--imap4d/quota.c203
-rw-r--r--include/mailutils/folder.h1
-rw-r--r--include/mailutils/mailbox.h5
-rw-r--r--include/mailutils/types.hin5
-rw-r--r--libproto/mbox/folder.c7
-rw-r--r--mailbox/mailbox.c188
-rw-r--r--sieve/testsuite/Reject6
15 files changed, 547 insertions, 113 deletions
diff --git a/NEWS b/NEWS
index 4e1f3fc4d..b3e774370 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
+Version 2.2.1 (Git)
+
+
Version 2.2 - 2010-09-08
* Guile support updated to compile with Guile 1.9
diff --git a/configure.ac b/configure.ac
index 275d50f1d..7d9e21810 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@ dnl with GNU Mailutils; if not, write to the Free Software Foundation,
dnl Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
AC_PREREQ(2.63)
-AC_INIT([GNU Mailutils], [2.2], [bug-mailutils@gnu.org], [mailutils])
+AC_INIT([GNU Mailutils], [2.2.1], [bug-mailutils@gnu.org], [mailutils])
AC_CONFIG_SRCDIR([mailbox/mailbox.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([gnits 1.11 dist-bzip2 dist-lzma dist-xz std-options silent-rules])
@@ -1221,7 +1221,9 @@ CPPFLAGS="$CPPFLAGS -DSYSCONFDIR=\\\"\$(sysconfdir)\\\""
AC_SUBST(RENDITION)
case `echo $VERSION|sed 's/[[^.]]//g'` in
""|".") RENDITION=DISTRIB;;
-"..") if test `echo $VERSION | sed 's/.*\.//'` -lt 50; then
+"..") MINOR=`echo $VERSION | sed 's/.*\.//'`
+ MINS=`echo $MINOR | sed 's/^[0-9][0-9]*//g'`
+ if test -n "$MINS" || test $MINOR -lt 50; then
RENDITION=DISTRIB
else
RENDITION=PROOF
diff --git a/guimb/scm/Makefile.am b/guimb/scm/Makefile.am
index 68df43fb0..5a0648340 100644
--- a/guimb/scm/Makefile.am
+++ b/guimb/scm/Makefile.am
@@ -21,6 +21,11 @@
MU_GUILE_SIEVE_SCRIPTS_X=sieve.scm
bin_SCRIPTS = sieve.scm
EXTRA_SCRIPTS=sieve.scm
+# FIXME: Sieve.scm is temporarly exempted from installchecks because
+# it may fail starting during checks, if libguile-mailutils-v- library
+# has not been previously installed. The proper fix would be to alter
+# %load-path during tests.
+AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=sieve.scm
sievemoddir=@MU_GUILE_SIEVE_MOD_DIR@
diff --git a/imap4d/Makefile.am b/imap4d/Makefile.am
index 65a5b8cba..0d5572889 100644
--- a/imap4d/Makefile.am
+++ b/imap4d/Makefile.am
@@ -49,6 +49,7 @@ imap4d_SOURCES = \
noop.c\
parsebuf.c\
preauth.c\
+ quota.c\
rename.c\
search.c\
select.c\
diff --git a/imap4d/append.c b/imap4d/append.c
index f6662aab3..dac1a8ba3 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -71,7 +71,8 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text,
struct tm *tm;
time_t t;
mu_envelope_t env;
-
+ size_t size;
+
if (mu_message_create (&msg, &tm))
return 1;
@@ -94,9 +95,9 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text,
}
}
else
- time(&t);
+ time (&t);
- tm = gmtime(&t);
+ tm = gmtime (&t);
while (*text && mu_isblank (*text))
text++;
@@ -109,17 +110,42 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text,
mu_envelope_set_date (env, _append_date, msg);
mu_envelope_set_sender (env, _append_sender, msg);
mu_message_set_envelope (msg, env, &tm);
+
+ rc = _append_size (msg, &size);
+ if (rc)
+ {
+ mu_diag_output (MU_DIAG_NOTICE,
+ _("cannot compute size of the message being appended; "
+ "using estimated value: %s"),
+ mu_strerror (rc));
+ /* raw estimate */
+ size = strlen (text);
+ }
+ rc = quota_check (size);
+ if (rc != RESP_OK)
+ {
+ *err_text = rc == RESP_NO ?
+ "Mailbox quota exceeded" : "Operation failed";
+ mu_message_destroy (&msg, &tm);
+ return 1;
+ }
+
rc = mu_mailbox_append_message (mbox, msg);
- if (rc == 0 && flags)
+ if (rc == 0)
{
- size_t num = 0;
- mu_attribute_t attr = NULL;
- mu_mailbox_messages_count (mbox, &num);
- mu_mailbox_get_message (mbox, num, &msg);
- mu_message_get_attribute (msg, &attr);
- mu_attribute_set_flags (attr, flags);
+ if (flags)
+ {
+ size_t num = 0;
+ mu_attribute_t attr = NULL;
+ mu_mailbox_messages_count (mbox, &num);
+ mu_mailbox_get_message (mbox, num, &msg);
+ mu_message_get_attribute (msg, &attr);
+ mu_attribute_set_flags (attr, flags);
+ }
+ /* FIXME: If not INBOX */
+ quota_update (size);
}
-
+
mu_message_destroy (&msg, &tm);
return rc;
}
diff --git a/imap4d/copy.c b/imap4d/copy.c
index b25e1ee30..e0ec3d3cc 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -35,6 +35,153 @@
copy messages in argv[2] to mailbox in argv[3]
*/
+static int
+copy_check_size (mu_mailbox_t mbox, size_t n, size_t *set, mu_off_t *size)
+{
+ int status;
+ size_t i;
+ mu_off_t total = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ mu_message_t msg = NULL;
+ size_t msgno = set[i];
+ if (msgno)
+ {
+ status = mu_mailbox_get_message (mbox, msgno, &msg);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
+ status);
+ return RESP_BAD;
+ }
+ else
+ {
+ size_t size;
+ status = mu_message_size (msg, &size);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL,
+ status);
+ return RESP_BAD;
+ }
+ total += size;
+ }
+ }
+ }
+ *size = total;
+ return quota_check (total);
+}
+
+static int
+try_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set)
+{
+ int result;
+ size_t i;
+ mu_off_t total;
+
+ result = copy_check_size (src, n, set, &total);
+ if (result)
+ return result;
+
+ for (i = 0; i < n; i++)
+ {
+ mu_message_t msg = NULL;
+ size_t msgno = set[i];
+
+ if (msgno)
+ {
+ int status = mu_mailbox_get_message (src, msgno, &msg);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
+ status);
+ return RESP_BAD;
+ }
+
+ status = mu_mailbox_append_message (dst, msg);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message",
+ NULL,
+ status);
+ return RESP_BAD;
+ }
+ }
+ }
+ quota_update (total);
+ return RESP_OK;
+}
+
+static int
+safe_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set,
+ char **err_text)
+{
+ size_t nmesg;
+ int status;
+
+ status = mu_mailbox_messages_count (dst, &nmesg);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_messages_count",
+ NULL, status);
+ *err_text = "Operation failed";
+ return RESP_NO;
+ }
+
+ status = try_copy (dst, src, n, set);
+ if (status)
+ {
+ size_t maxmesg;
+
+ if (status == RESP_NO)
+ *err_text = "Mailbox quota exceeded";
+ else
+ *err_text = "Operation failed";
+
+ /* If the COPY command is unsuccessful for any reason, server
+ implementations MUST restore the destination mailbox to its state
+ before the COPY attempt. */
+
+ status = mu_mailbox_messages_count (dst, &maxmesg);
+ if (status)
+ {
+ mu_url_t url = NULL;
+
+ mu_mailbox_get_url (dst, &url);
+ mu_error (_("cannot count messages in mailbox %s: %s"),
+ mu_url_to_string (url), mu_strerror (status));
+ imap4d_bye (ERR_MAILBOX_CORRUPTED);
+ }
+
+ for (nmesg++; nmesg <= maxmesg; nmesg++)
+ {
+ mu_message_t msg;
+
+ if (mu_mailbox_get_message (dst, nmesg, &msg) == 0)
+ {
+ mu_attribute_t attr;
+ mu_message_get_attribute (msg, &attr);
+ mu_attribute_set_userflag (attr, MU_ATTRIBUTE_DELETED);
+ }
+ }
+
+ status = mu_mailbox_flush (dst, 1);
+ if (status)
+ {
+ mu_url_t url = NULL;
+
+ mu_mailbox_get_url (dst, &url);
+ mu_error (_("cannot flush mailbox %s: %s"),
+ mu_url_to_string (url), mu_strerror (status));
+ imap4d_bye (ERR_MAILBOX_CORRUPTED);
+ }
+ return RESP_NO;
+ }
+
+ return RESP_OK;
+}
+
int
imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
@@ -71,6 +218,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
int arg = IMAP4_ARG_1 + !!isuid;
int ns;
+ *err_text = NULL;
if (imap4d_tokbuf_argc (tok) != arg + 2)
{
*err_text = "Invalid arguments";
@@ -89,11 +237,19 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
return RESP_OK;
}
+ if (isuid)
+ {
+ int i;
+ /* Fixup the message set. Perhaps util_msgset should do it itself? */
+ for (i = 0; i < n; i++)
+ set[i] = uid_to_msgno (set[i]);
+ }
+
mailbox_name = namespace_getfullpath (name, delim, &ns);
if (!mailbox_name)
{
- *err_text = "NO Copy failed.";
+ *err_text = "Copy failed.";
return RESP_NO;
}
@@ -106,14 +262,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]);
if (status == 0)
{
- size_t i;
- for (i = 0; i < n; i++)
- {
- mu_message_t msg = NULL;
- size_t msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
- if (msgno && mu_mailbox_get_message (mbox, msgno, &msg) == 0)
- mu_mailbox_append_message (cmbox, msg);
- }
+ status = safe_copy (cmbox, mbox, n, set, err_text);
mu_mailbox_close (cmbox);
}
mu_mailbox_destroy (&cmbox);
@@ -132,6 +281,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
of the text of the tagged NO response. This gives a hint to the
client that it can attempt a CREATE command and retry the copy if
the CREATE is successful. */
- *err_text = "[TRYCREATE] failed";
+ if (!*err_text)
+ *err_text = "[TRYCREATE] failed";
return RESP_NO;
}
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 0b36a0068..ebbdbcb3b 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -352,9 +352,14 @@ imap4d_session_setup0 ()
util_chdir (imap4d_homedir);
namespace_init_session (imap4d_homedir);
+
mu_diag_output (MU_DIAG_INFO,
_("user `%s' logged in (source: %s)"), auth_data->name,
auth_data->source);
+
+ if (auth_data->quota)
+ quota_setup ();
+
return 0;
}
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 1d9378d20..31ce80fd4 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -400,7 +400,12 @@ extern void auth_gsasl_init (void);
#else
# define auth_gsasl_init()
#endif
-
+
+/* Quota support */
+void quota_setup (void);
+int quota_check (mu_off_t size);
+void quota_update (mu_off_t size);
+
#ifdef __cplusplus
}
#endif
diff --git a/imap4d/quota.c b/imap4d/quota.c
new file mode 100644
index 000000000..b39f0d8e9
--- /dev/null
+++ b/imap4d/quota.c
@@ -0,0 +1,203 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "imap4d.h"
+
+struct imap4d_sizeinfo
+{
+ mu_off_t size;
+ mu_off_t nfiles;
+ mu_off_t ndirs;
+ mu_off_t nerrs;
+};
+
+static int
+addsize (mu_folder_t folder, struct mu_list_response *resp, void *data)
+{
+ struct imap4d_sizeinfo *si = data;
+
+ if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY)
+ si->ndirs++;
+
+ if (resp->type & MU_FOLDER_ATTRIBUTE_FILE)
+ {
+ mu_off_t size;
+ mu_mailbox_t mbox;
+ int rc;
+
+ si->nfiles++;
+
+ rc = mu_mailbox_create_from_record (&mbox, resp->format, resp->name);
+
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_from_record",
+ resp->name, rc);
+ si->nerrs++;
+ return 0;
+ }
+
+ rc = mu_mailbox_open (mbox, MU_STREAM_READ);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+ resp->name, rc);
+ si->nerrs++;
+ mu_mailbox_destroy (&mbox);
+ return 0;
+ }
+
+ rc = mu_mailbox_get_size (mbox, &size);
+ mu_mailbox_destroy (&mbox);
+
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+ resp->name, rc);
+ si->nerrs++;
+ return 0;
+ }
+ si->size += size;
+ }
+ return 0;
+}
+
+void
+directory_size (const char *dirname, mu_off_t *size)
+{
+ mu_folder_t folder;
+ struct imap4d_sizeinfo sizeinfo;
+ int status;
+
+ status = mu_folder_create (&folder, dirname);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", dirname, status);
+ return;
+ }
+
+ status = mu_folder_open (folder, MU_STREAM_READ);
+ if (status)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", dirname, status);
+ mu_folder_destroy (&folder);
+ return;
+ }
+
+ memset (&sizeinfo, 0, sizeof (sizeinfo));
+ status = mu_folder_enumerate (folder, NULL, "*", 0, 0, NULL,
+ addsize, &sizeinfo);
+ if (status)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_enumerate", dirname, status);
+ else
+ {
+ mu_diag_output (MU_DIAG_INFO,
+ _("%s statistics: size=%lu, ndirs=%lu, nfiles=%lu, nerrs=%lu"),
+ dirname,
+ (unsigned long)sizeinfo.size,
+ (unsigned long)sizeinfo.ndirs,
+ (unsigned long)sizeinfo.nfiles,
+ (unsigned long)sizeinfo.nerrs);
+ }
+ *size = sizeinfo.size;
+}
+
+
+mu_off_t used_size;
+
+void
+quota_setup ()
+{
+ directory_size (imap4d_homedir, &used_size);
+}
+
+int
+quota_check (mu_off_t size)
+{
+ char *mailbox_name;
+ mu_mailbox_t mbox;
+ mu_off_t total;
+ int rc;
+
+ if (auth_data->quota == 0)
+ return RESP_OK;
+
+ total = used_size;
+
+ mailbox_name = namespace_getfullpath ("INBOX", "/", NULL);
+ rc = mu_mailbox_create (&mbox, mailbox_name);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc);
+ free (mailbox_name);
+ }
+ else
+ {
+ do
+ {
+ mu_off_t mbsize;
+
+ rc = mu_mailbox_open (mbox, MU_STREAM_READ);
+ if (rc)
+ {
+ if (rc != ENOENT)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+ mailbox_name, rc);
+ break;
+ }
+
+ rc = mu_mailbox_get_size (mbox, &mbsize);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_size",
+ mailbox_name, rc);
+ mu_mailbox_close (mbox);
+ break;
+ }
+ total += mbsize;
+ mu_mailbox_close (mbox);
+ }
+ while (0);
+ mu_mailbox_destroy (&mbox);
+ }
+ free (mailbox_name);
+
+ if (rc)
+ return RESP_BAD;
+
+ if (total > auth_data->quota)
+ {
+ mu_diag_output (MU_DIAG_NOTICE,
+ _("user %s is out of mailbox quota"),
+ auth_data->name);
+ return RESP_NO;
+ }
+ else if (total + size > auth_data->quota)
+ {
+ mu_diag_output (MU_DIAG_NOTICE,
+ _("user %s: adding %lu bytes would exceed mailbox quota"),
+ auth_data->name, (unsigned long) size);
+ return RESP_NO;
+ }
+ return RESP_OK;
+}
+
+void
+quota_update (mu_off_t size)
+{
+ used_size += size;
+}
diff --git a/include/mailutils/folder.h b/include/mailutils/folder.h
index 03390dc62..e639d8b8e 100644
--- a/include/mailutils/folder.h
+++ b/include/mailutils/folder.h
@@ -32,6 +32,7 @@ struct mu_list_response
int level;
int separator;
char *name;
+ mu_record_t format; /* Associated mailbox format record */
};
typedef int (*mu_folder_match_fp) (const char *, void *, int);
diff --git a/include/mailutils/mailbox.h b/include/mailutils/mailbox.h
index d3aa895d1..b8567a9a1 100644
--- a/include/mailutils/mailbox.h
+++ b/include/mailutils/mailbox.h
@@ -40,9 +40,12 @@ int mu_construct_user_mailbox_url (char **pout, const char *name);
/* Constructor/destructor and possible types. */
extern int mu_mailbox_create (mu_mailbox_t *, const char *);
extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t);
+extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox,
+ mu_record_t record,
+ const char *name);
+extern int mu_mailbox_create_default (mu_mailbox_t *, const char *);
extern void mu_mailbox_destroy (mu_mailbox_t *);
-extern int mu_mailbox_create_default (mu_mailbox_t *, const char *);
extern int mu_mailbox_open (mu_mailbox_t, int flag);
extern int mu_mailbox_close (mu_mailbox_t);
diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin
index 019e66fac..5a0614671 100644
--- a/include/mailutils/types.hin
+++ b/include/mailutils/types.hin
@@ -115,8 +115,9 @@ typedef struct _mu_progmailer *mu_progmailer_t;
typedef struct _mu_secret *mu_secret_t;
typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t;
-#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
-#define MU_FOLDER_ATTRIBUTE_FILE 0x002
+#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
+#define MU_FOLDER_ATTRIBUTE_FILE 0x002
+#define MU_FOLDER_ATTRIBUTE_LINK 0x004
#define MU_FOLDER_ATTRIBUTE_ALL \
(MU_FOLDER_ATTRIBUTE_DIRECTORY|MU_FOLDER_ATTRIBUTE_FILE)
diff --git a/libproto/mbox/folder.c b/libproto/mbox/folder.c
index 3557a88f1..389d59649 100644
--- a/libproto/mbox/folder.c
+++ b/libproto/mbox/folder.c
@@ -315,7 +315,7 @@ list_helper (struct search_data *data, mu_record_t record,
DIR *dirp;
struct dirent *dp;
int stop = 0;
-
+
if (data->max_level && level > data->max_level)
return 0;
@@ -345,13 +345,15 @@ list_helper (struct search_data *data, mu_record_t record,
if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0)
continue;
fname = get_pathname (dirname, ename);
- if (stat (fname, &st) == 0)
+ if (lstat (fname, &st) == 0)
{
int f;
if (S_ISDIR (st.st_mode))
f = MU_FOLDER_ATTRIBUTE_DIRECTORY;
else if (S_ISREG (st.st_mode))
f = MU_FOLDER_ATTRIBUTE_FILE;
+ else if (S_ISLNK (st.st_mode))
+ f = MU_FOLDER_ATTRIBUTE_LINK;
else
f = 0;
if (mu_record_list_p (record, ename, f))
@@ -386,6 +388,7 @@ list_helper (struct search_data *data, mu_record_t record,
resp->level = level;
resp->separator = '/';
resp->type = type;
+ resp->format = rec;
if (resp->type == 0)
{
diff --git a/mailbox/mailbox.c b/mailbox/mailbox.c
index b06fe3d51..917c5806b 100644
--- a/mailbox/mailbox.c
+++ b/mailbox/mailbox.c
@@ -69,102 +69,110 @@ mailbox_folder_create (mu_mailbox_t mbox, const char *name,
return rc;
}
-static int
-_create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
+int
+_mailbox_create_from_record (mu_mailbox_t *pmbox,
+ mu_record_t record,
+ mu_url_t url,
+ const char *name)
{
- int status;
- mu_record_t record = NULL;
-
- if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
- == 0)
+ mu_log_level_t level;
+ int (*m_init) (mu_mailbox_t) = NULL;
+
+ mu_record_get_mailbox (record, &m_init);
+ if (m_init)
{
- mu_log_level_t level;
- int (*m_init) (mu_mailbox_t) = NULL;
+ int status;
+ int (*u_init) (mu_url_t) = NULL;
+ mu_mailbox_t mbox;
- mu_record_get_mailbox (record, &m_init);
- if (m_init)
- {
- int (*u_init) (mu_url_t) = NULL;
- mu_mailbox_t mbox;
-
- /* Allocate memory for mbox. */
- mbox = calloc (1, sizeof (*mbox));
- if (mbox == NULL)
- return ENOMEM;
-
- /* Initialize the internal lock now, so the concrete mailbox
- could use it. */
- status = mu_monitor_create (&mbox->monitor, 0, mbox);
- if (status != 0)
- {
- mu_mailbox_destroy (&mbox);
- return status;
- }
-
- /* Make sure scheme contains actual mailbox scheme */
- /* FIXME: It is appropriate not for all record types. For now we
- assume that if the record scheme ends with a plus sign, this
- should not be done. Probably it requires some flag in struct
- _mu_record? */
- if (strcmp (url->scheme, record->scheme))
- {
- char *p = strdup (record->scheme);
- if (!p)
- {
- mu_mailbox_destroy (&mbox);
- return errno;
- }
- free (url->scheme);
- url->scheme = p;
- }
-
- mu_record_get_url (record, &u_init);
- if (u_init && (status = u_init (url)) != 0)
+ /* Allocate memory for mbox. */
+ mbox = calloc (1, sizeof (*mbox));
+ if (mbox == NULL)
+ return ENOMEM;
+
+ /* Initialize the internal lock now, so the concrete mailbox
+ could use it. */
+ status = mu_monitor_create (&mbox->monitor, 0, mbox);
+ if (status != 0)
+ {
+ mu_mailbox_destroy (&mbox);
+ return status;
+ }
+
+ /* Make sure scheme contains actual mailbox scheme */
+ /* FIXME: It is appropriate not for all record types. For now we
+ assume that if the record scheme ends with a plus sign, this
+ should not be done. Probably it requires some flag in struct
+ _mu_record? */
+ if (strcmp (url->scheme, record->scheme))
+ {
+ char *p = strdup (record->scheme);
+ if (!p)
{
mu_mailbox_destroy (&mbox);
- return status;
+ return errno;
}
-
- mbox->url = url;
-
- /* Create the folder before initializing the concrete mailbox.
- The mailbox needs it's back pointer. */
- status = mailbox_folder_create (mbox, name, record);
+ free (url->scheme);
+ url->scheme = p;
+ }
+
+ mu_record_get_url (record, &u_init);
+ if (u_init && (status = u_init (url)) != 0)
+ {
+ mu_mailbox_destroy (&mbox);
+ return status;
+ }
+
+ mbox->url = url;
+
+ /* Create the folder before initializing the concrete mailbox.
+ The mailbox needs it's back pointer. */
+ status = mailbox_folder_create (mbox, name, record);
+
+ if (status == 0)
+ status = m_init (mbox); /* Create the concrete mailbox type. */
+
+ if (status != 0)
+ {
+ /* Take care not to destroy url. Leave it to caller. */
+ mbox->url = NULL;
+ mu_mailbox_destroy (&mbox);
+ }
+ else
+ {
+ *pmbox = mbox;
- if (status == 0)
- status = m_init (mbox); /* Create the concrete mailbox type. */
-
- if (status != 0)
- {
- /* Take care not to destroy url. Leave it to caller. */
- mbox->url = NULL;
- mu_mailbox_destroy (&mbox);
- }
- else
+ level = mu_global_debug_level ("mailbox");
+ if (level)
{
- *pmbox = mbox;
-
- level = mu_global_debug_level ("mailbox");
- if (level)
- {
- int status = mu_debug_create (&mbox->debug, mbox);
- if (status)
- return 0; /* FIXME: don't want to bail out just because I
- failed to create a *debug* object. But I may
- be wrong... */
- mu_debug_set_level (mbox->debug, level);
- if (level & MU_DEBUG_INHERIT)
- mu_folder_set_debug (mbox->folder, mbox->debug);
- }
+ int status = mu_debug_create (&mbox->debug, mbox);
+ if (status)
+ return 0; /* FIXME: don't want to bail out just because I
+ failed to create a *debug* object. But I may
+ be wrong... */
+ mu_debug_set_level (mbox->debug, level);
+ if (level & MU_DEBUG_INHERIT)
+ mu_folder_set_debug (mbox->folder, mbox->debug);
}
-
- return status;
}
+
+ return status;
}
return MU_ERR_NO_HANDLER;
}
static int
+_create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
+{
+ mu_record_t record = NULL;
+
+ if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
+ == 0)
+ return _mailbox_create_from_record (pmbox, record, url, name);
+ return MU_ERR_NO_HANDLER;
+}
+
+static int
_create_mailbox (mu_mailbox_t *pmbox, const char *name)
{
int status;
@@ -202,6 +210,24 @@ mu_mailbox_create_from_url (mu_mailbox_t *pmbox, mu_url_t url)
return _create_mailbox0 (pmbox, url, mu_url_to_string (url));
}
+int
+mu_mailbox_create_from_record (mu_mailbox_t *pmbox, mu_record_t record,
+ const char *name)
+{
+ mu_url_t url;
+ int rc;
+
+ rc = mu_url_create (&url, name);
+ if (rc)
+ return rc;
+ rc = mu_url_parse (url);
+ if (rc == 0)
+ rc = _mailbox_create_from_record (pmbox, record, url, name);
+ if (rc)
+ mu_url_destroy (&url);
+ return rc;
+}
+
void
mu_mailbox_destroy (mu_mailbox_t *pmbox)
{
diff --git a/sieve/testsuite/Reject b/sieve/testsuite/Reject
index d8ed5e846..d39d24219 100644
--- a/sieve/testsuite/Reject
+++ b/sieve/testsuite/Reject
@@ -52,7 +52,7 @@ ENVELOPE TO: <coyote@desert.example.org>
18: Content-Type: message/delivery-status
19:
-re
- 20: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
+ 20: Reporting-UA: sieve; GNU Mailutils [0-9][^ ]*
-re
21: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
22: Final-Recipient: RFC822; foobar@nonexistent.net
@@ -113,7 +113,7 @@ ENVELOPE TO: <b1ff@de.res.example.com>
18: Content-Type: message/delivery-status
19:
-re
- 20: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
+ 20: Reporting-UA: sieve; GNU Mailutils [0-9][^ ]*
-re
21: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
22: Final-Recipient: RFC822; foobar@nonexistent.net
@@ -172,7 +172,7 @@ ENVELOPE TO: <bar@dontmailme.org>
18: Content-Type: message/delivery-status
19:
-re
- 20: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
+ 20: Reporting-UA: sieve; GNU Mailutils [0-9][^ ]*
-re
21: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
22: Final-Recipient: RFC822; foobar@nonexistent.net

Return to:

Send suggestions and report system problems to the System administrator.