summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--perl/Rspamd.xs253
-rw-r--r--src/expressions.c13
-rw-r--r--src/message.c266
-rw-r--r--src/message.h3
-rw-r--r--src/plugins/regexp.c24
6 files changed, 290 insertions, 270 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d61844e70..fad4f5d4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -272,6 +272,7 @@ SET(TESTDEPENDS src/mem_pool.c
src/util.c
src/fuzzy.c
src/memcached.c
+ src/message.c
src/expressions.c
src/statfile.c)
diff --git a/perl/Rspamd.xs b/perl/Rspamd.xs
index 892e4b006..ecfe0b93b 100644
--- a/perl/Rspamd.xs
+++ b/perl/Rspamd.xs
@@ -126,262 +126,9 @@ call_sub_foreach(GMimeObject *mime_object, gpointer data)
perl_call_sv (svdata->svfunc, G_DISCARD);
}
}
-/* known header field types */
-enum {
- HEADER_FROM = 0,
- HEADER_REPLY_TO,
- HEADER_TO,
- HEADER_CC,
- HEADER_BCC,
- HEADER_SUBJECT,
- HEADER_DATE,
- HEADER_MESSAGE_ID,
- HEADER_UNKNOWN
-};
-
-static GList *
-local_message_get_header(GMimeMessage *message, const char *field)
-{
- GList * gret = NULL;
-#ifndef GMIME24
- struct raw_header *h;
-
- if (field == NULL) {
- return NULL;
- }
- h = GMIME_OBJECT(message)->headers->headers;
- while (h) {
- if (h->value && !g_strncasecmp(field, h->name, strlen(field))) {
- gret = g_list_prepend(gret, g_strdup(h->value));
- }
- h = h->next;
- }
- return gret;
-#else
- GMimeHeaderList *ls;
- GMimeHeaderIter *iter;
- const char *name;
-
- ls = GMIME_OBJECT(message)->headers;
-
- if (g_mime_header_list_get_iter (ls, iter)) {
- while (g_mime_header_iter_is_valid (iter)) {
- name = g_mime_header_iter_get_name (iter);
- if (!g_strncasecmp (field, name, strlen (name))) {
- gret = g_list_prepend (gret, g_strdup (g_mime_header_iter_get_value (iter)));
- }
- if (!g_mime_header_iter_next (iter)) {
- break;
- }
- }
- }
-
- return gret;
-#endif
-}
-
-/**
-* g_mime_message_set_date_from_string: Set the message sent-date
-* @message: MIME Message
-* @string: A string of date
-*
-* Set the sent-date on a MIME Message.
-**/
-static void
-local_mime_message_set_date_from_string (GMimeMessage *message, const gchar *string)
-{
- time_t date;
- int offset = 0;
-
- date = g_mime_utils_header_decode_date (string, &offset);
- g_mime_message_set_date (message, date, offset);
-}
-
-#ifdef GMIME24
-
-#define ADD_RECIPIENT_TEMPLATE(type,def) \
-static void \
-local_message_add_recipients_from_string_##type (GMimeMessage *message, const gchar *string, const gchar *value) \
-{ \
- InternetAddressList *il, *new; \
- \
- il = g_mime_message_get_recipients (message, (def)); \
- new = internet_address_list_parse_string (string); \
- internet_address_list_append (il, new); \
-} \
-
-ADD_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
-ADD_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
-ADD_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
-
-#define GET_RECIPIENT_TEMPLATE(type,def) \
-static InternetAddressList* \
-local_message_get_recipients_##type (GMimeMessage *message, const char *unused) \
-{ \
- return g_mime_message_get_recipients (message, (def)); \
-}
-
-GET_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
-GET_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
-GET_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
-
-#endif
-/* different declarations for different types of set and get functions */
-typedef const char *(*GetFunc) (GMimeMessage *message);
-typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage *message, const char *type );
-typedef GList *(*GetListFunc) (GMimeMessage *message, const char *type );
-typedef void (*SetFunc) (GMimeMessage *message, const char *value);
-typedef void (*SetListFunc) (GMimeMessage *message, const char *field, const char *value);
-/** different types of functions
-*
-* FUNC_CHARPTR
-* - function with no arguments
-* - get returns char*
-*
-* FUNC_IA (from Internet Address)
-* - function with additional "field" argument from the fieldfunc table,
-* - get returns Glist*
-*
-* FUNC_LIST
-* - function with additional "field" argument (given arbitrary header field name)
-* - get returns Glist*
-**/
-enum {
- FUNC_CHARPTR = 0,
- FUNC_CHARFREEPTR,
- FUNC_IA,
- FUNC_LIST
-};
-
-/**
-* fieldfunc struct: structure of MIME fields and corresponding get and set
-* functions.
-**/
-static struct {
- char * name;
- GetFunc func;
- GetRcptFunc rcptfunc;
- GetListFunc getlistfunc;
- SetFunc setfunc;
- SetListFunc setlfunc;
- gint functype;
-} fieldfunc[] = {
- { "From", g_mime_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARPTR },
- { "Reply-To", g_mime_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARPTR },
-#ifndef GMIME24
- { "To", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Cc", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Bcc", NULL, g_mime_message_get_recipients, NULL, NULL, g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Date", g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
-#else
- { "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA },
- { "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA },
- { "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA },
- { "Date", g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
-#endif
- { "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR },
- { "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR },
-#ifndef GMIME24
- { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST }
-#else
- { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_object_append_header, FUNC_LIST }
-#endif
-};
-
-
-
-/**
-* message_set_header: set header of any type excluding special (Content- and MIME-Version:)
-**/
-static void
-message_set_header (GMimeMessage *message, const char *field, const char *value)
-{
- gint i;
-
-
- if (!g_strcasecmp (field, "MIME-Version:") || !g_strncasecmp (field, "Content-", 8)) {
- return;
- }
- for (i=0; i<=HEADER_UNKNOWN; ++i) {
- if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
- switch (fieldfunc[i].functype) {
- case FUNC_CHARPTR:
- (*(fieldfunc[i].setfunc))(message, value);
- break;
- case FUNC_IA:
- (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value);
- break;
- case FUNC_LIST:
- (*(fieldfunc[i].setlfunc))(message, field, value);
- break;
- }
- break;
- }
- }
-}
-
-
-/**
-* message_get_header: returns the list of 'any header' values
-* (except of unsupported yet Content- and MIME-Version special headers)
-*
-* You should free the GList list by yourself.
-**/
-static
-GList *
-message_get_header(GMimeMessage *message, const char *field) {
- gint i;
- char * ret = NULL, *ia_string;
- GList * gret = NULL;
- InternetAddressList *ia_list = NULL, *ia;
-
- for (i = 0; i <= HEADER_UNKNOWN; ++i) {
- if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
- switch (fieldfunc[i].functype) {
- case FUNC_CHARFREEPTR:
- ret = (char *)(*(fieldfunc[i].func))(message);
- break;
- case FUNC_CHARPTR:
- ret = (char *)(*(fieldfunc[i].func))(message);
- break;
- case FUNC_IA:
- ia_list = (*(fieldfunc[i].rcptfunc))(message, field);
- gret = g_list_alloc();
- ia = ia_list;
-#ifndef GMIME24
- while (ia && ia->address) {
-
- ia_string = internet_address_to_string ((InternetAddress *)ia->address, FALSE);
- gret = g_list_append (gret, ia_string);
- ia = ia->next;
- }
-#else
- i = internet_address_list_length (ia);
- while (i > 0) {
- ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE);
- gret = g_list_append (gret, ia_string);
- -- i;
- }
-#endif
- break;
- case FUNC_LIST:
- gret = (*(fieldfunc[i].getlistfunc))(message, field);
- break;
- }
- break;
- }
- }
- if (gret == NULL && ret != NULL) {
- gret = g_list_prepend (gret, g_strdup (ret));
- }
- if (fieldfunc[i].functype == FUNC_CHARFREEPTR && ret) {
- g_free (ret);
- }
- return gret;
-}
MODULE = Mail::Rspamd PACKAGE = Mail::Rspamd::Log PREFIX = rspamd_log_
PROTOTYPES: DISABLE
diff --git a/src/expressions.c b/src/expressions.c
index eefd11f78..46a4f17fe 100644
--- a/src/expressions.c
+++ b/src/expressions.c
@@ -585,6 +585,7 @@ gboolean
rspamd_header_exists (struct worker_task *task, GList *args)
{
struct expression_argument *arg;
+ GList *headerlist;
if (args == NULL || task == NULL) {
return FALSE;
@@ -595,11 +596,13 @@ rspamd_header_exists (struct worker_task *task, GList *args)
msg_warn ("rspamd_header_exists: invalid argument to function is passed");
return FALSE;
}
-#ifdef GMIME24
- return (g_mime_object_get_header (GMIME_OBJECT (task->message), (char *)arg->data) != NULL);
-#else
- return (g_mime_message_get_header (task->message, (char *)arg->data) != NULL);
-#endif
+
+ headerlist = message_get_header (task->message, (char *)arg->data);
+ if (headerlist) {
+ g_list_free (headerlist);
+ return TRUE;
+ }
+ return FALSE;
}
/*
diff --git a/src/message.c b/src/message.c
index 807463a82..be470bb65 100644
--- a/src/message.c
+++ b/src/message.c
@@ -552,3 +552,269 @@ get_next_text_part (memory_pool_t *pool, GList *parts, GList **cur)
return NULL;
}
+
+struct raw_header {
+ struct raw_header *next;
+ char *name;
+ char *value;
+};
+
+typedef struct _GMimeHeader {
+ GHashTable *hash;
+ GHashTable *writers;
+ struct raw_header *headers;
+} local_GMimeHeader;
+
+
+/* known header field types */
+enum {
+ HEADER_FROM = 0,
+ HEADER_REPLY_TO,
+ HEADER_TO,
+ HEADER_CC,
+ HEADER_BCC,
+ HEADER_SUBJECT,
+ HEADER_DATE,
+ HEADER_MESSAGE_ID,
+ HEADER_UNKNOWN
+};
+
+static GList *
+local_message_get_header(GMimeMessage *message, const char *field)
+{
+ GList * gret = NULL;
+#ifndef GMIME24
+ struct raw_header *h;
+
+ if (field == NULL) {
+ return NULL;
+ }
+ h = GMIME_OBJECT(message)->headers->headers;
+ while (h) {
+ if (h->value && !g_strncasecmp (field, h->name, strlen (field))) {
+ gret = g_list_prepend(gret, g_strdup (h->value));
+ }
+ h = h->next;
+ }
+ return gret;
+#else
+ GMimeHeaderList *ls;
+ GMimeHeaderIter *iter;
+ const char *name;
+
+ ls = GMIME_OBJECT(message)->headers;
+
+ if (g_mime_header_list_get_iter (ls, iter)) {
+ while (g_mime_header_iter_is_valid (iter)) {
+ name = g_mime_header_iter_get_name (iter);
+ if (!g_strncasecmp (field, name, strlen (name))) {
+ gret = g_list_prepend (gret, g_strdup (g_mime_header_iter_get_value (iter)));
+ }
+ if (!g_mime_header_iter_next (iter)) {
+ break;
+ }
+ }
+ }
+
+ return gret;
+#endif
+}
+
+/**
+* g_mime_message_set_date_from_string: Set the message sent-date
+* @message: MIME Message
+* @string: A string of date
+*
+* Set the sent-date on a MIME Message.
+**/
+void
+local_mime_message_set_date_from_string (GMimeMessage *message, const gchar *string)
+{
+ time_t date;
+ int offset = 0;
+
+ date = g_mime_utils_header_decode_date (string, &offset);
+ g_mime_message_set_date (message, date, offset);
+}
+
+#ifdef GMIME24
+
+#define ADD_RECIPIENT_TEMPLATE(type,def) \
+static void \
+local_message_add_recipients_from_string_##type (GMimeMessage *message, const gchar *string, const gchar *value) \
+{ \
+ InternetAddressList *il, *new; \
+ \
+ il = g_mime_message_get_recipients (message, (def)); \
+ new = internet_address_list_parse_string (string); \
+ internet_address_list_append (il, new); \
+} \
+
+ADD_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
+ADD_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
+ADD_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
+
+#define GET_RECIPIENT_TEMPLATE(type,def) \
+static InternetAddressList* \
+local_message_get_recipients_##type (GMimeMessage *message, const char *unused) \
+{ \
+ return g_mime_message_get_recipients (message, (def)); \
+}
+
+GET_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
+GET_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
+GET_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
+
+#endif
+
+
+/* different declarations for different types of set and get functions */
+typedef const char *(*GetFunc) (GMimeMessage *message);
+typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage *message, const char *type );
+typedef GList *(*GetListFunc) (GMimeMessage *message, const char *type );
+typedef void (*SetFunc) (GMimeMessage *message, const char *value);
+typedef void (*SetListFunc) (GMimeMessage *message, const char *field, const char *value);
+
+/** different types of functions
+*
+* FUNC_CHARPTR
+* - function with no arguments
+* - get returns char*
+*
+* FUNC_IA (from Internet Address)
+* - function with additional "field" argument from the fieldfunc table,
+* - get returns Glist*
+*
+* FUNC_LIST
+* - function with additional "field" argument (given arbitrary header field name)
+* - get returns Glist*
+**/
+enum {
+ FUNC_CHARPTR = 0,
+ FUNC_CHARFREEPTR,
+ FUNC_IA,
+ FUNC_LIST
+};
+
+/**
+* fieldfunc struct: structure of MIME fields and corresponding get and set
+* functions.
+**/
+static struct {
+ char * name;
+ GetFunc func;
+ GetRcptFunc rcptfunc;
+ GetListFunc getlistfunc;
+ SetFunc setfunc;
+ SetListFunc setlfunc;
+ gint functype;
+} fieldfunc[] = {
+ { "From", g_mime_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARPTR },
+ { "Reply-To", g_mime_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARPTR },
+#ifndef GMIME24
+ { "To", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Cc", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Bcc",NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
+ { "Date", (GetFunc)g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
+#else
+ { "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA },
+ { "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA },
+ { "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA },
+ { "Date", g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
+#endif
+ { "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR },
+ { "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR },
+#ifndef GMIME24
+ { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST }
+#else
+ { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_object_append_header, FUNC_LIST }
+#endif
+};
+/**
+* message_set_header: set header of any type excluding special (Content- and MIME-Version:)
+**/
+void
+message_set_header (GMimeMessage *message, const char *field, const char *value)
+{
+ gint i;
+
+ if (!g_strcasecmp (field, "MIME-Version:") || !g_strncasecmp (field, "Content-", 8)) {
+ return;
+ }
+ for (i=0; i<=HEADER_UNKNOWN; ++i) {
+ if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ switch (fieldfunc[i].functype) {
+ case FUNC_CHARPTR:
+ (*(fieldfunc[i].setfunc))(message, value);
+ break;
+ case FUNC_IA:
+ (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value);
+ break;
+ case FUNC_LIST:
+ (*(fieldfunc[i].setlfunc))(message, field, value);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+
+/**
+* message_get_header: returns the list of 'any header' values
+* (except of unsupported yet Content- and MIME-Version special headers)
+*
+* You should free the GList list by yourself.
+**/
+GList *
+message_get_header (GMimeMessage *message, const char *field)
+{
+ gint i;
+ char * ret = NULL, *ia_string;
+ GList * gret = NULL;
+ InternetAddressList *ia_list = NULL, *ia;
+
+ for (i = 0; i <= HEADER_UNKNOWN; ++i) {
+ if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ switch (fieldfunc[i].functype) {
+ case FUNC_CHARFREEPTR:
+ ret = (char *)(*(fieldfunc[i].func))(message);
+ break;
+ case FUNC_CHARPTR:
+ ret = (char *)(*(fieldfunc[i].func))(message);
+ break;
+ case FUNC_IA:
+ ia_list = (*(fieldfunc[i].rcptfunc))(message, field);
+ gret = g_list_alloc();
+ ia = ia_list;
+#ifndef GMIME24
+ while (ia && ia->address) {
+
+ ia_string = internet_address_to_string ((InternetAddress *)ia->address, FALSE);
+ gret = g_list_append (gret, ia_string);
+ ia = ia->next;
+ }
+#else
+ i = internet_address_list_length (ia);
+ while (i > 0) {
+ ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE);
+ gret = g_list_append (gret, ia_string);
+ -- i;
+ }
+#endif
+ break;
+ case FUNC_LIST:
+ gret = (*(fieldfunc[i].getlistfunc))(message, field);
+ break;
+ }
+ break;
+ }
+ }
+ if (gret == NULL && ret != NULL) {
+ gret = g_list_prepend (gret, g_strdup (ret));
+ }
+ if (fieldfunc[i].functype == FUNC_CHARFREEPTR && ret) {
+ g_free (ret);
+ }
+ return gret;
+}
diff --git a/src/message.h b/src/message.h
index eaf9f493e..7a39c03af 100644
--- a/src/message.h
+++ b/src/message.h
@@ -44,4 +44,7 @@ int process_learn (struct controller_session *session);
*/
GByteArray* get_next_text_part (memory_pool_t *pool, GList *parts, GList **cur);
+void message_set_header (GMimeMessage *message, const char *field, const char *value);
+GList* message_get_header (GMimeMessage *message, const char *field);
+
#endif
diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c
index 6509a4e5e..c106ae3e5 100644
--- a/src/plugins/regexp.c
+++ b/src/plugins/regexp.c
@@ -154,7 +154,7 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task)
{
char *headerv, *c, t;
struct mime_part *part;
- GList *cur;
+ GList *cur, *headerlist;
struct uri *url;
if (re == NULL) {
@@ -171,25 +171,25 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task)
return 0;
}
msg_debug ("process_regexp: checking header regexp: %s = /%s/", re->header, re->regexp_text);
-#ifdef GMIME24
- headerv = (char *)g_mime_object_get_header (GMIME_OBJECT (task->message), re->header);
-#else
- headerv = (char *)g_mime_message_get_header (task->message, re->header);
-#endif
- if (headerv == NULL) {
+ headerlist = message_get_header (task->message, re->header);
+ if (headerlist == NULL) {
return 0;
}
else {
if (re->regexp == NULL) {
msg_debug ("process_regexp: regexp contains only header and it is found %s", re->header);
+ g_list_free (headerlist);
return 1;
}
- if (g_regex_match (re->regexp, headerv, 0, NULL) == TRUE) {
- return 1;
- }
- else {
- return 0;
+ cur = headerlist;
+ while (cur) {
+ if (g_regex_match (re->regexp, cur->data, 0, NULL) == TRUE) {
+ return 1;
+ }
+ cur = g_list_next (cur);
}
+ g_list_free (headerlist);
+ return 0;
}
break;
case REGEXP_MIME: