static CamelSExpResult *
get_current_date (struct _CamelSExp *f,
                  gint argc,
                  struct _CamelSExpResult **argv,
                  FilterMessageSearch *fms)
{
	CamelSExpResult *r;

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
	r->value.number = time (NULL);

	return r;
}
/* remember, the size comparisons are done at Kbytes */
static CamelSExpResult *
get_size (struct _CamelSExp *f,
          gint argc,
          struct _CamelSExpResult **argv,
          FilterMessageSearch *fms)
{
	CamelSExpResult *r;

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
	r->value.number = camel_message_info_get_size (fms->info) / 1024;

	return r;
}
static CamelSExpResult *
get_relative_months (struct _CamelSExp *f,
                     gint argc,
                     struct _CamelSExpResult **argv,
                     gpointer data)
{
	CamelSExpResult *r;

	d (printf ("executing get-relative-months\n"));

	if (argc != 1 || argv[0]->type != CAMEL_SEXP_RES_INT) {
		r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
		r->value.boolean = FALSE;

		g_debug ("%s: Expecting 1 argument, an integer, but got %d arguments", G_STRFUNC, argc);
	} else {
		r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
		r->value.number = camel_folder_search_util_add_months (time (NULL), argv[0]->value.number);
	}

	return r;
}
static CamelSExpResult *
match_all (struct _CamelSExp *f,
           gint argc,
           struct _CamelSExpTerm **argv,
           gpointer data)
{
	CamelSExpResult *r;

	d (printf ("executing match-all: %d", argc));
	if (argc == 0) {
		r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
		r->value.string = g_strdup ("1");
	} else if (argv[0]->type != CAMEL_SEXP_TERM_BOOL)
		r = camel_sexp_term_eval (f, argv[0]);
	else {
		r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
		r->value.string = g_strdup (argv[0]->value.boolean ? "1" : "0");
	}

	return r;

}
static CamelSExpResult *
get_current_date (struct _CamelSExp *f,
                  gint argc,
                  struct _CamelSExpResult **argv,
                  gpointer data)
{
	CamelSExpResult *r;

	d (printf ("executing get-current-date\n"));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
	r->value.number = time (NULL);
	return r;
}
static CamelSExpResult *
get_size (struct _CamelSExp *f,
          gint argc,
          struct _CamelSExpResult **argv,
          gpointer data)
{
	CamelSExpResult *r;

	d (printf ("executing get-size\n"));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
	r->value.string = g_strdup ("size/1024");

	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 *
system_flag (struct _CamelSExp *f,
             gint argc,
             struct _CamelSExpResult **argv,
             FilterMessageSearch *fms)
{
	CamelSExpResult *r;

	if (argc != 1 || argv[0]->type != CAMEL_SEXP_RES_STRING)
		camel_sexp_fatal_error (f, _("Invalid arguments to (system-flag)"));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
	r->value.boolean = camel_system_flag_get (camel_message_info_flags (fms->info), argv[0]->value.string);

	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 *
header_exists (struct _CamelSExp *f,
               gint argc,
               struct _CamelSExpResult **argv,
               gpointer data)
{
	CamelSExpResult *r;
	gchar *headername;

	d (printf ("executing header-exists: %d", argc));

	headername = camel_db_get_column_name (argv[0]->value.string);
	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
	r->value.string = g_strdup_printf ("(%s NOTNULL)", headername);
	g_free (headername);
	return r;
}
Beispiel #11
0
static CamelSExpResult *
match_all (struct _CamelSExp *f,
           gint argc,
           struct _CamelSExpTerm **argv,
           FilterMessageSearch *fms)
{
	/* match-all: when dealing with single messages is a no-op */
	CamelSExpResult *r;

	if (argc > 0)
		return camel_sexp_term_eval (f, argv[0]);

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
	r->value.boolean = TRUE;

	return r;
}
Beispiel #12
0
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;
}
Beispiel #13
0
static CamelSExpResult *
user_tag (struct _CamelSExp *f,
          gint argc,
          struct _CamelSExpResult **argv,
          FilterMessageSearch *fms)
{
	CamelSExpResult *r;
	const gchar *tag;

	if (argc != 1 || argv[0]->type != CAMEL_SEXP_RES_STRING)
		camel_sexp_fatal_error (f, _("Invalid arguments to (user-tag)"));

	tag = camel_message_info_user_tag (fms->info, argv[0]->value.string);

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
	r->value.string = g_strdup (tag ? tag : "");

	return r;
}
static CamelSExpResult *
user_tag (struct _CamelSExp *f,
          gint argc,
          struct _CamelSExpResult **argv,
          gpointer data)
{
	CamelSExpResult *r;

	d (printf ("executing user-tag: %d", argc));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
	/* Hacks no otherway to fix these really :( */
	if (g_strcmp0 (argv[0]->value.string, "completed-on") == 0)
		r->value.string = g_strdup_printf ("(usertags LIKE '%ccompleted-on 0%c' AND usertags LIKE '%ccompleted-on%c')", '%', '%', '%', '%');
	else if (g_strcmp0 (argv[0]->value.string, "follow-up") == 0)
		r->value.string = g_strdup_printf ("usertags NOT LIKE '%cfollow-up%c'", '%', '%');
	else
		r->value.string = g_strdup ("usertags");

	return r;
}
/* this should support all arguments ...? */
static CamelSExpResult *
eval_gt (struct _CamelSExp *f,
         gint argc,
         struct _CamelSExpTerm **argv,
         gpointer data)
{
	struct _CamelSExpResult *r, *r1, *r2;

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);

	if (argc == 2) {
		GString *str = g_string_new ("( ");
		r1 = camel_sexp_term_eval (f, argv[0]);
		r2 = camel_sexp_term_eval (f, argv[1]);

		if (r1->type == CAMEL_SEXP_RES_INT)
			g_string_append_printf (str, "%d", r1->value.number);
		else if (r1->type == CAMEL_SEXP_RES_TIME)
			g_string_append_printf (str, "%ld", r1->value.time);
		else if (r1->type == CAMEL_SEXP_RES_STRING)
			g_string_append_printf (str, "%s", r1->value.string);

		g_string_append_printf (str, " > ");
		if (r2->type == CAMEL_SEXP_RES_INT)
			g_string_append_printf (str, "%d", r2->value.number);
		if (r2->type == CAMEL_SEXP_RES_BOOL)
			g_string_append_printf (str, "%d", r2->value.boolean);
		else if (r2->type == CAMEL_SEXP_RES_TIME)
			g_string_append_printf (str, "%ld", r2->value.time);
		else if (r2->type == CAMEL_SEXP_RES_STRING)
			g_string_append_printf (str, "%s", r2->value.string);
		camel_sexp_result_free (f, r1);
		camel_sexp_result_free (f, r2);
		g_string_append (str, " )");

		r->value.string = str->str;
		g_string_free (str, FALSE);
	}
	return r;
}
static CamelSExpResult *
sql_exp (struct _CamelSExp *f,
         gint argc,
         struct _CamelSExpResult **argv,
         gpointer data)
{
	CamelSExpResult *r;
	gint i;
	GString *str = g_string_new (NULL);

	d (printf ("executing sql-exp\n"));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
	for (i = 0; i < argc; i++) {
		if (argv[i]->type == CAMEL_SEXP_RES_STRING && argv[i]->value.string)
			g_string_append (str, argv[i]->value.string);
	}
	r->value.string = str->str;
	g_string_free (str, FALSE);

	return r;
}
static CamelSExpResult *
system_flag (struct _CamelSExp *f,
             gint argc,
             struct _CamelSExpResult **argv,
             gpointer data)
{
	CamelSExpResult *r;
	gchar *tstr;

	d (printf ("executing system-flag: %d", argc));

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);

	if (argc != 1) {
		r->value.string = g_strdup ("(0)");
	} else {
		tstr = camel_db_get_column_name (argv[0]->value.string);
		r->value.string = g_strdup_printf ("(%s = 1)", tstr);
		g_free (tstr);
	}

	return r;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
	const gchar *contents;

	message = camel_filter_search_get_message (fms, f);

	if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING
	    && (contents = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string))
	    && 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;

	return r;
}
static CamelSExpResult *
func_not (CamelSExp *f,
          gint argc,
          struct _CamelSExpTerm **argv,
          gpointer data)
{
	CamelSExpResult *r = NULL, *r1;

	d (printf ("executing not: %d", argc));
	r1 = camel_sexp_term_eval (f, argv[0]);

	if (r1->type == CAMEL_SEXP_RES_STRING) {
		r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
		/* HACK: Fix and handle completed-on better. */
		if (g_strcmp0 (r1->value.string, "( (usertags LIKE '%completed-on 0%' AND usertags LIKE '%completed-on%') )") == 0)
			r->value.string = g_strdup ("( (not (usertags LIKE '%completed-on 0%')) AND usertags LIKE '%completed-on%' )");
		else
			r->value.string = g_strdup_printf (
				"(NOT (%s))", r1->value.string);
	}
	camel_sexp_result_free (f, r1);

	return r;
}
Beispiel #22
0
static CamelSExpResult *
user_flag (struct _CamelSExp *f,
           gint argc,
           struct _CamelSExpResult **argv,
           FilterMessageSearch *fms)
{
	CamelSExpResult *r;
	gboolean truth = FALSE;
	gint i;

	/* performs an OR of all words */
	for (i = 0; i < argc && !truth; i++) {
		if (argv[i]->type == CAMEL_SEXP_RES_STRING
		    && camel_message_info_user_flag (fms->info, argv[i]->value.string)) {
			truth = TRUE;
			break;
		}
	}

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
	r->value.boolean = truth;

	return r;
}
Beispiel #23
0
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;
}
Beispiel #24
0
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 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;
}