static int moderator_action (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) { mu_message_t msg, orig; int rc; size_t nparts = 0; int discard = 0; int ismime; if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE) { mu_sieve_locus_t locus; mu_sieve_get_locus (mach, &locus); mu_sieve_debug (mach, "%s:%lu: moderator_test %lu\n", locus.source_file, (u_long) locus.source_line, (u_long) mu_sieve_get_message_num (mach)); } msg = mu_sieve_get_message (mach); mu_message_is_multipart (msg, &ismime); if (!ismime) { mu_sieve_error (mach, _("message is not multipart")); mu_sieve_abort (mach); } mu_message_get_num_parts (msg, &nparts); if (nparts != 3) /* Mailman moderation requests have three parts */ { mu_sieve_error (mach, _("expected 3 parts, but found %lu"), (unsigned long) nparts); mu_sieve_abort (mach); } if ((rc = moderator_message_get_part (mach, msg, 2, &orig))) mu_sieve_abort (mach); rc = moderator_filter_message (mach, tags, orig, &discard); mu_message_unref (orig); if (rc) mu_sieve_abort (mach); if (discard && !mu_sieve_is_dry_run (mach)) { mu_message_t request; char *from = NULL; mu_sieve_value_t *arg; if ((rc = moderator_message_get_part (mach, msg, 3, &request))) { mu_sieve_error (mach, _("cannot get message part #3: %s"), mu_strerror (rc)); mu_sieve_abort (mach); } if (mu_sieve_tag_lookup (tags, "address", &arg)) from = arg->v.string; if (moderator_discard_message (mach, request, from)) discard = 0; else { if (!mu_sieve_tag_lookup (tags, "keep", NULL)) { mu_attribute_t attr = 0; if (mu_message_get_attribute (msg, &attr) == 0) mu_attribute_set_deleted (attr); } else discard = 0; } mu_message_unref (request); } mu_sieve_log_action (mach, "MODERATOR", discard ? _("discarding message") : _("keeping message")); return 0; }
static int moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg, int *pdiscard) { int rc; mu_sieve_machine_t newmach; mu_attribute_t attr; mu_sieve_value_t *arg; if (mu_sieve_tag_lookup (tags, "source", &arg)) { rc = mu_sieve_machine_inherit (mach, &newmach); if (rc) { mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), mu_strerror (rc)); return 1; } /* FIXME: This should be configurable: moderator :inherit moderator :debug 2 ... */ rc = mu_sieve_compile (newmach, arg->v.string); if (rc) mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string); } else if (mu_sieve_tag_lookup (tags, "program", &arg)) { struct mu_locus locus; rc = mu_sieve_machine_inherit (mach, &newmach); if (rc) { mu_sieve_error (mach, _("cannot initialize sieve machine: %s"), mu_strerror (rc)); return 1; } mu_sieve_get_locus (mach, &locus); rc = mu_sieve_compile_buffer (newmach, arg->v.string, strlen (arg->v.string), locus.mu_file, locus.mu_line); if (rc) mu_sieve_error (mach, _("cannot compile subprogram")); } else rc = mu_sieve_machine_dup (mach, &newmach); if (rc) return rc; mu_message_get_attribute (msg, &attr); mu_attribute_unset_deleted (attr); rc = mu_sieve_message (newmach, msg); if (rc) mu_sieve_error (newmach, _("failed to run inferior sieve machine")); else *pdiscard = mu_attribute_is_deleted (attr); mu_sieve_machine_destroy (&newmach); return rc; }
/* Handler for the timestamp test */ static int timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) { mu_sieve_value_t *h, *v; mu_header_t hdr; char *val; time_t now = time (NULL); time_t tlimit, tval; int rc; if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE) { mu_sieve_locus_t locus; mu_sieve_get_locus (mach, &locus); mu_sieve_debug (mach, "%s:%lu: TIMESTAMP\n", locus.source_file, (unsigned long) locus.source_line); } /* Retrieve required arguments: */ /* First argument: header name */ h = mu_sieve_value_get (args, 0); if (!h) { mu_sieve_arg_error (mach, 1); mu_sieve_abort (mach); } /* Second argument: date displacement */ v = mu_sieve_value_get (args, 1); if (!v) { mu_sieve_arg_error (mach, 2); mu_sieve_abort (mach); } if (mu_parse_date (v->v.string, &tlimit, &now)) { mu_sieve_error (mach, _("cannot parse date specification (%s)"), v->v.string); mu_sieve_abort (mach); } rc = mu_message_get_header (mu_sieve_get_message (mach), &hdr); if (rc) { mu_sieve_error (mach, "mu_message_get_header: %s", mu_strerror (rc)); mu_sieve_abort (mach); } if (mu_header_aget_value (hdr, h->v.string, &val)) return 0; if (mu_parse_date (val, &tval, &now)) { mu_sieve_error (mach, "cannot parse header date specification (%s)", val); free (val); mu_sieve_abort (mach); } free (val); rc = tval > tlimit; if (mu_sieve_tag_lookup (tags, "before", NULL)) rc = !rc; return rc; }