static CamelSExpResult * header_regex (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); CamelMimeMessage *message; regex_t pattern; gchar *contents = NULL; message = camel_filter_search_get_message (fms, f); if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING && (contents = camel_search_get_header_decoded (argv[0]->value.string, camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string), camel_search_get_default_charset_from_message (message))) && camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | CAMEL_SEARCH_MATCH_ICASE, argc - 1, argv + 1, fms->error) == 0) { r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0; regfree (&pattern); } else r->value.boolean = FALSE; g_free (contents); return r; }
static CamelSExpResult * get_received_date (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelMimeMessage *message; CamelSExpResult *r; message = camel_filter_search_get_message (fms, f); r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT); r->value.number = camel_mime_message_get_date_received (message, NULL); return r; }
static CamelSExpResult * header_source (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelMimeMessage *message; CamelSExpResult *r; const gchar *src; CamelService *msg_source = NULL; gboolean truth = FALSE; if (fms->source) { src = fms->source; } else { message = camel_filter_search_get_message (fms, f); src = camel_mime_message_get_source (message); } if (src) msg_source = ref_service_for_source (fms->session, src); if (msg_source != NULL) { gint ii; for (ii = 0; ii < argc && !truth; ii++) { if (argv[ii]->type == CAMEL_SEXP_RES_STRING) { CamelService *candidate; candidate = ref_service_for_source ( fms->session, argv[ii]->value.string); if (candidate != NULL) { truth = (msg_source == candidate); g_object_unref (candidate); } } } g_object_unref (msg_source); } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.boolean = truth; return r; }
static CamelSExpResult * body_contains (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); CamelMimeMessage *message; regex_t pattern; if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->error) == 0) { message = camel_filter_search_get_message (fms, f); r->value.boolean = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern); regfree (&pattern); } else r->value.boolean = FALSE; return r; }
static CamelSExpResult * header_full_regex (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); CamelMimeMessage *message; regex_t pattern; gchar *contents; if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_REGEX | CAMEL_SEARCH_MATCH_ICASE | CAMEL_SEARCH_MATCH_NEWLINE, argc, argv, fms->error) == 0) { message = camel_filter_search_get_message (fms, f); contents = get_full_header (message); r->value.boolean = regexec (&pattern, contents, 0, NULL, 0) == 0; g_free (contents); regfree (&pattern); } else r->value.boolean = FALSE; return r; }
static CamelSExpResult * header_exists (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelMimeMessage *message; gboolean matched = FALSE; CamelSExpResult *r; gint i; message = camel_filter_search_get_message (fms, f); for (i = 0; i < argc && !matched; i++) { if (argv[i]->type == CAMEL_SEXP_RES_STRING) matched = camel_medium_get_header (CAMEL_MEDIUM (message), argv[i]->value.string) != NULL; } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.boolean = matched; return r; }
static CamelSExpResult * junk_test (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r; CamelMessageInfo *info = fms->info; CamelJunkFilter *junk_filter; CamelMessageFlags flags; CamelMimeMessage *message; CamelJunkStatus status; const GHashTable *ht; const struct _camel_header_param *node; gboolean sender_is_known; gboolean message_is_junk = FALSE; GError *error = NULL; junk_filter = camel_session_get_junk_filter (fms->session); if (junk_filter == NULL) goto exit; /* Check if the message is already classified. */ flags = camel_message_info_flags (info); if (flags & CAMEL_MESSAGE_JUNK) { if (camel_debug ("junk")) printf ( "Message has a Junk flag set already, " "skipping junk test...\n"); goto exit; } if (flags & CAMEL_MESSAGE_NOTJUNK) { if (camel_debug ("junk")) printf ( "Message has a NotJunk flag set already, " "skipping junk test...\n"); goto exit; } /* Check the headers for a junk designation. */ ht = camel_session_get_junk_headers (fms->session); node = camel_message_info_headers (info); while (node != NULL) { const gchar *value = NULL; if (node->name != NULL) value = g_hash_table_lookup ( (GHashTable *) ht, node->name); message_is_junk = (value != NULL) && (camel_strstrcase (node->value, value) != NULL); if (message_is_junk) { if (camel_debug ("junk")) printf ( "Message contains \"%s: %s\"", node->name, value); goto done; } node = node->next; } /* If the sender is known, the message is not junk. */ sender_is_known = camel_session_lookup_addressbook ( fms->session, camel_message_info_from (info)); if (camel_debug ("junk")) printf ( "Sender '%s' in book? %d\n", camel_message_info_from (info), sender_is_known); if (sender_is_known) goto done; /* Consult 3rd party junk filtering software. */ message = camel_filter_search_get_message (fms, f); status = camel_junk_filter_classify ( junk_filter, message, NULL, &error); if (error == NULL) { const gchar *status_desc; switch (status) { case CAMEL_JUNK_STATUS_INCONCLUSIVE: status_desc = "inconclusive"; message_is_junk = FALSE; break; case CAMEL_JUNK_STATUS_MESSAGE_IS_JUNK: status_desc = "junk"; message_is_junk = TRUE; break; case CAMEL_JUNK_STATUS_MESSAGE_IS_NOT_JUNK: status_desc = "not junk"; message_is_junk = FALSE; break; default: g_warn_if_reached (); status_desc = "invalid"; message_is_junk = FALSE; break; } if (camel_debug ("junk")) g_print ( "Junk filter classification: %s\n", status_desc); } else { g_warn_if_fail (status == CAMEL_JUNK_STATUS_ERROR); g_warning ("%s: %s", G_STRFUNC, error->message); g_error_free (error); message_is_junk = FALSE; } done: if (camel_debug ("junk")) printf ( "Message is determined to be %s\n", message_is_junk ? "*JUNK*" : "clean"); exit: r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.number = message_is_junk; return r; }
static gint run_command (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelMimeMessage *message; CamelStream *stream; gint i; gint pipe_to_child; GPid child_pid; GError *error = NULL; GPtrArray *args; child_watch_data_t child_watch_data; GSource *source; GMainContext *context; if (argc < 1 || argv[0]->value.string[0] == '\0') return 0; args = g_ptr_array_new (); for (i = 0; i < argc; i++) g_ptr_array_add (args, argv[i]->value.string); g_ptr_array_add (args, NULL); if (!g_spawn_async_with_pipes (NULL, (gchar **) args->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, child_setup_func, NULL, &child_pid, &pipe_to_child, NULL, NULL, &error)) { g_ptr_array_free (args, TRUE); g_set_error ( fms->error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to create child process '%s': %s"), argv[0]->value.string, error->message); g_error_free (error); return -1; } g_ptr_array_free (args, TRUE); message = camel_filter_search_get_message (fms, f); stream = camel_stream_fs_new_with_fd (pipe_to_child); camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), stream, NULL, NULL); camel_stream_flush (stream, NULL, NULL); g_object_unref (stream); context = g_main_context_new (); child_watch_data.loop = g_main_loop_new (context, FALSE); g_main_context_unref (context); source = g_child_watch_source_new (child_pid); g_source_set_callback (source, (GSourceFunc) child_watch, &child_watch_data, NULL); g_source_attach (source, g_main_loop_get_context (child_watch_data.loop)); g_source_unref (source); g_main_loop_run (child_watch_data.loop); g_main_loop_unref (child_watch_data.loop); #ifndef G_OS_WIN32 if (WIFEXITED (child_watch_data.child_status)) return WEXITSTATUS (child_watch_data.child_status); else return -1; #else return child_watch_data.child_status; #endif }
static CamelSExpResult * check_header (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how) { gboolean matched = FALSE; CamelSExpResult *r; gint i; if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING) { gchar *name = argv[0]->value.string; /* shortcut: a match for "" against any header always matches */ for (i = 1; i < argc && !matched; i++) matched = argv[i]->type == CAMEL_SEXP_RES_STRING && argv[i]->value.string[0] == 0; if (g_ascii_strcasecmp (name, "x-camel-mlist") == 0) { const gchar *list = camel_message_info_mlist (fms->info); if (list) { for (i = 1; i < argc && !matched; i++) { if (argv[i]->type == CAMEL_SEXP_RES_STRING) matched = camel_search_header_match (list, argv[i]->value.string, how, CAMEL_SEARCH_TYPE_MLIST, NULL); } } } else if (fms->message || !check_header_in_message_info (fms->info, argc, argv, how, &matched)) { CamelMimeMessage *message; CamelMimePart *mime_part; struct _camel_header_raw *header; const gchar *charset = NULL; camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED; CamelContentType *ct; message = camel_filter_search_get_message (fms, f); mime_part = CAMEL_MIME_PART (message); /* FIXME: what about Resent-To, Resent-Cc and Resent-From? */ if (g_ascii_strcasecmp ("to", name) == 0 || g_ascii_strcasecmp ("cc", name) == 0 || g_ascii_strcasecmp ("from", name) == 0) type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED; else if (message) { ct = camel_mime_part_get_content_type (mime_part); if (ct) { charset = camel_content_type_param (ct, "charset"); charset = camel_iconv_charset_name (charset); } } for (header = mime_part->headers; header && !matched; header = header->next) { /* empty name means any header */ if (!name || !*name || !g_ascii_strcasecmp (header->name, name)) { for (i = 1; i < argc && !matched; i++) { if (argv[i]->type == CAMEL_SEXP_RES_STRING) matched = camel_search_header_match (header->value, argv[i]->value.string, how, type, charset); } } } } } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.boolean = matched; return r; }
static CamelSExpResult * junk_test (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelSExpResult *r; gboolean retval = FALSE; CamelMessageInfo *info = fms->info; CamelJunkFilter *junk_filter; junk_filter = camel_session_get_junk_filter (fms->session); d(printf("doing junk test for message from '%s'\n", camel_message_info_from (fms->info))); if (junk_filter != NULL && (camel_message_info_flags (info) & (CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK)) == 0) { const GHashTable *ht = camel_session_get_junk_headers (fms->session); const struct _camel_header_param *node = camel_message_info_headers (info); while (node && !retval) { if (node->name) { gchar *value = (gchar *) g_hash_table_lookup ((GHashTable *) ht, node->name); d(printf("JunkCheckMatch: %s %s %s\n", node->name, node->value, value)); if (value) retval = camel_strstrcase (node->value, value) != NULL; } node = node->next; } if (camel_debug ("junk")) printf("filtered based on junk header ? %d\n", retval); if (!retval) { retval = camel_session_lookup_addressbook (fms->session, camel_message_info_from (info)) != TRUE; if (camel_debug ("junk")) printf("Sender '%s' in book? %d\n", camel_message_info_from (info), !retval); if (retval) /* Not in book. Could be spam. So check for it */ { CamelMimeMessage *message; CamelJunkStatus status; gboolean success; d(printf("filtering message\n")); message = camel_filter_search_get_message (fms, f); success = camel_junk_filter_classify (junk_filter, message, &status, NULL, NULL); retval = success && (status == CAMEL_JUNK_STATUS_MESSAGE_IS_JUNK); } } if (camel_debug ("junk")) printf("junk filter => %s\n", retval ? "*JUNK*" : "clean"); } else if (junk_filter != NULL && camel_debug ("junk")) { if (camel_message_info_flags (info) & CAMEL_MESSAGE_JUNK) printf ("Message has a Junk flag set already, skipping junk test...\n"); else if (camel_message_info_flags (info) & CAMEL_MESSAGE_NOTJUNK) printf ("Message has a NotJunk flag set already, skipping junk test...\n"); } r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL); r->value.number = retval; return r; }