summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmailutils/base/locker.c32
-rw-r--r--libmu_sieve/extensions/vacation.c206
-rw-r--r--libmu_sieve/sieve.y26
3 files changed, 181 insertions, 83 deletions
diff --git a/libmailutils/base/locker.c b/libmailutils/base/locker.c
index dc33fdc49..5f34947c2 100644
--- a/libmailutils/base/locker.c
+++ b/libmailutils/base/locker.c
@@ -447,7 +447,37 @@ mu_locker_create (mu_locker_t *plocker, const char *fname, int flags)
return EINVAL;
if ((err = mu_unroll_symlink (fname, &filename)))
- return err;
+ {
+ if (err == ENOENT)
+ {
+ /* Try the directory part. If it unrolls successfully (i.e.
+ all its components exist), tuck the filename part back in
+ the resulting path and use it as the lock filename. */
+ char *p, *tmp = strdup (fname);
+ if (!tmp)
+ return ENOMEM;
+ p = strchr (tmp, '/');
+ if (!p)
+ filename = tmp;
+ else
+ {
+ err = mu_unroll_symlink (tmp, &filename);
+ free (tmp);
+ if (err)
+ return err;
+ tmp = realloc (filename, strlen (filename) + strlen (p) + 1);
+ if (!tmp)
+ {
+ free (filename);
+ return ENOMEM;
+ }
+ strcat (tmp, p);
+ filename = tmp;
+ }
+ }
+ else
+ return err;
+ }
l = calloc (1, sizeof (*l));
diff --git a/libmu_sieve/extensions/vacation.c b/libmu_sieve/extensions/vacation.c
index 6f63f6530..f61b0012b 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -140,7 +140,8 @@ diag (mu_sieve_machine_t mach)
}
-struct addr_data {
+struct addr_data
+{
mu_address_t addr;
char *my_address;
};
@@ -159,38 +160,38 @@ _compare (void *item, void *data)
of the originating mail. Return non-zero if so and store a pointer
to the matching address to *MY_ADDRESS. */
static int
-match_addresses (mu_header_t hdr, mu_sieve_value_t *addresses, char **my_address)
+match_addresses (mu_header_t hdr, mu_sieve_value_t *addresses,
+ char **my_address)
{
int match = 0;
- char *str;
+ const char *str;
struct addr_data ad;
ad.my_address = NULL;
- if (mu_header_aget_value (hdr, MU_HEADER_TO, &str) == 0)
+ if (mu_header_sget_value (hdr, MU_HEADER_TO, &str) == 0)
{
if (!mu_address_create (&ad.addr, str))
{
match += mu_sieve_vlist_do (addresses, _compare, &ad);
mu_address_destroy (&ad.addr);
}
- free (str);
}
- if (!match && mu_header_aget_value (hdr, MU_HEADER_CC, &str) == 0)
+ if (!match && mu_header_sget_value (hdr, MU_HEADER_CC, &str) == 0)
{
if (!mu_address_create (&ad.addr, str))
{
match += mu_sieve_vlist_do (addresses, _compare, &ad);
mu_address_destroy (&ad.addr);
}
- free (str);
}
*my_address = ad.my_address;
return match;
}
-struct regex_data {
+struct regex_data
+{
mu_sieve_machine_t mach;
char *email;
};
@@ -253,12 +254,11 @@ static int
bulk_precedence_p (mu_header_t hdr)
{
int rc = 0;
- char *str;
- if (mu_header_aget_value (hdr, MU_HEADER_PRECEDENCE, &str) == 0)
+ const char *str;
+ if (mu_header_sget_value (hdr, MU_HEADER_PRECEDENCE, &str) == 0)
{
rc = mu_c_strcasecmp (str, "bulk") == 0
|| mu_c_strcasecmp (str, "junk") == 0;
- free (str);
}
return rc;
}
@@ -267,20 +267,78 @@ bulk_precedence_p (mu_header_t hdr)
#define DAYS_DEFAULT 7
#define DAYS_MAX 60
-/* Check and updated vacation database. Return 0 if the mail should
- be answered. */
+static int
+test_and_update_prop (mu_property_t prop, const char *from,
+ time_t now, unsigned int days,
+ mu_sieve_machine_t mach)
+{
+ const char *result;
+ char *timebuf;
+ time_t last;
+
+ int rc = mu_property_sget_value (prop, from, &result);
+ switch (rc)
+ {
+ case MU_ERR_NOENT:
+ break;
+
+ case 0:
+ last = (time_t) strtoul (result, NULL, 0);
+ if (last + (24 * 60 * 60 * days) > now)
+ return 1;
+ break;
+
+ default:
+ mu_sieve_error (mach, "%lu: mu_property_sget_value: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ return -1;
+ }
+
+ rc = mu_asprintf (&timebuf, "%lu", (unsigned long) now);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: mu_asprintf: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ return -1;
+ }
+
+ rc = mu_property_set_value (prop, from, timebuf, 1);
+ free (timebuf);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: mu_property_set_value: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ return -1;
+ }
+
+ rc = mu_property_save (prop);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: mu_property_save: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ return -1;
+ }
+ return 0;
+}
+
+/* Check and update the vacation database. Return 0 if the mail should
+ be answered, 0 if it should not, and throw exception if an error
+ occurs. */
static int
check_db (mu_sieve_machine_t mach, mu_list_t tags, char *from)
{
-#ifdef USE_DBM
- DBM_FILE db;
- DBM_DATUM key, value;
- time_t now;
- char buffer[64];
- char *file, *home;
+ mu_property_t prop;
+ char *file;
mu_sieve_value_t *arg;
unsigned int days;
+ time_t now;
int rc;
+ mu_stream_t str;
+ mu_locker_t locker;
if (mu_sieve_tag_lookup (tags, "days", &arg))
{
@@ -293,69 +351,67 @@ check_db (mu_sieve_machine_t mach, mu_list_t tags, char *from)
else
days = DAYS_DEFAULT;
- home = mu_get_homedir ();
-
- file = mu_make_file_name (home ? home : ".", ".vacation");
+ file = mu_tilde_expansion ("~/.vacation", "/", NULL);
if (!file)
{
mu_sieve_error (mach, _("%lu: cannot build db file name"),
(unsigned long) mu_sieve_get_message_num (mach));
- free (home);
mu_sieve_abort (mach);
}
- free (home);
-
- rc = mu_dbm_open (file, &db, MU_STREAM_RDWR, 0600);
+
+ rc = mu_locker_create (&locker, file, 0);
if (rc)
{
- mu_sieve_error (mach,
- _("%lu: cannot open `%s': %s"),
- (unsigned long) mu_sieve_get_message_num (mach), file,
+ mu_sieve_error (mach, _("%lu: cannot lock %s: %s"),
+ (unsigned long) mu_sieve_get_message_num (mach),
+ file,
mu_strerror (rc));
free (file);
mu_sieve_abort (mach);
}
- free (file);
- time (&now);
-
- MU_DATUM_SIZE (key) = strlen (from);
- MU_DATUM_PTR (key) = from;
-
- rc = mu_dbm_fetch (db, key, &value);
- if (!rc)
+ rc = mu_file_stream_create (&str, file, MU_STREAM_RDWR|MU_STREAM_CREAT);
+ if (rc)
{
- time_t last;
-
- strncpy(buffer, MU_DATUM_PTR (value), MU_DATUM_SIZE (value));
- buffer[MU_DATUM_SIZE (value)] = 0;
-
- last = (time_t) strtoul (buffer, NULL, 0);
+ mu_sieve_error (mach, "%lu: mu_file_stream_create(%s): %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ file,
+ mu_strerror (rc));
+ mu_locker_destroy (&locker);
+ free (file);
+ mu_sieve_abort (mach);
+ }
+
+ free (file);
+ rc = mu_property_create_init (&prop, mu_assoc_property_init, str);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: mu_property_create_init: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ mu_locker_destroy (&locker);
+ mu_sieve_abort (mach);
+ }
- if (last + (24 * 60 * 60 * days) > now)
- {
- mu_dbm_close (db);
- return 1;
- }
+ rc = mu_locker_lock (locker);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: cannot lock vacation database: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ mu_property_destroy (&prop);
+ mu_sieve_abort (mach);
}
- MU_DATUM_SIZE (value) = snprintf (buffer, sizeof buffer, "%ld", now);
- MU_DATUM_PTR (value) = buffer;
- MU_DATUM_SIZE (key) = strlen (from);
- MU_DATUM_PTR (key) = from;
+ rc = test_and_update_prop (prop, from, now, days, mach);
+ mu_property_destroy (&prop);
+ mu_locker_unlock (locker);
+ mu_locker_destroy (&locker);
+ if (rc == -1)
+ mu_sieve_abort (mach);
- mu_dbm_insert (db, key, value, 1);
- mu_dbm_close (db);
- return 0;
-#else
- mu_sieve_error (mach,
- /* TRANSLATORS: 'vacation' and ':days' are Sieve keywords.
- Do not translate them! */
- _("%d: vacation compiled without DBM support. Ignoring :days tag"),
- mu_sieve_get_message_num (mach));
- return 0;
-#endif
+ return rc;
}
/* Add a reply prefix to the subject. *PSUBJECT points to the
@@ -411,7 +467,8 @@ vacation_subject (mu_sieve_machine_t mach, mu_list_t tags,
if (mu_sieve_tag_lookup (tags, "subject", &arg))
subject = arg->v.string;
else if (mu_message_get_header (msg, &hdr) == 0
- && mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT, &value) == 0)
+ && mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT,
+ &value) == 0)
{
char *p;
@@ -436,9 +493,7 @@ vacation_subject (mu_sieve_machine_t mach, mu_list_t tags,
if (rc)
{
mu_sieve_error (mach,
- /* TRANSLATORS: 'vacation' is the name of the
- Sieve action. Do not translate it! */
- _("%lu: vacation - cannot compile reply prefix regexp: %s: %s"),
+ _("%lu: cannot compile reply prefix regexp: %s: %s"),
(unsigned long) mu_sieve_get_message_num (mach),
mu_strerror (rc),
err ? err : "");
@@ -521,23 +576,12 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
}
mailer = mu_sieve_get_mailer (mach);
- rc = mu_mailer_open (mailer, 0);
- if (rc)
- {
- mu_url_t url = NULL;
- mu_mailer_get_url (mailer, &url);
-
- mu_sieve_error (mach,
- _("%lu: cannot open mailer %s: %s"),
- (unsigned long) mu_sieve_get_message_num (mach),
- mu_url_to_string (url), mu_strerror (rc));
- }
- else
+ if (mailer)
{
rc = mu_mailer_send_message (mailer, newmsg, from_addr, to_addr);
- mu_mailer_close (mailer);
}
- mu_mailer_destroy (&mailer);
+ else
+ rc = MU_ERR_FAILURE;
}
mu_address_destroy (&to_addr);
mu_address_destroy (&from_addr);
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve.y
index 79ae1fb48..45bc090e4 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve.y
@@ -465,7 +465,31 @@ mu_mailer_t
mu_sieve_get_mailer (mu_sieve_machine_t mach)
{
if (!mach->mailer)
- mu_mailer_create (&mach->mailer, NULL);
+ {
+ int rc;
+
+ rc = mu_mailer_create (&mach->mailer, NULL);
+ if (rc)
+ {
+ mu_sieve_error (mach,
+ _("%lu: cannot create mailer: %s"),
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_strerror (rc));
+ return NULL;
+ }
+ rc = mu_mailer_open (mach->mailer, 0);
+ if (rc)
+ {
+ mu_url_t url = NULL;
+ mu_mailer_get_url (mach->mailer, &url);
+ mu_sieve_error (mach,
+ _("%lu: cannot open mailer %s: %s"),
+ (unsigned long) mu_sieve_get_message_num (mach),
+ mu_url_to_string (url), mu_strerror (rc));
+ mu_mailer_destroy (&mach->mailer);
+ return NULL;
+ }
+ }
return mach->mailer;
}

Return to:

Send suggestions and report system problems to the System administrator.