diff options
Diffstat (limited to 'src/plugins/regexp.c')
-rw-r--r-- | src/plugins/regexp.c | 1212 |
1 files changed, 756 insertions, 456 deletions
diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index bddde5383..31d4943fd 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -40,62 +40,82 @@ #define DEFAULT_STATFILE_PREFIX "./" struct regexp_module_item { - struct expression *expr; - const gchar *symbol; - guint32 avg_time; - gpointer lua_function; + struct expression *expr; + const gchar *symbol; + guint32 avg_time; + gpointer lua_function; }; struct autolearn_data { - gchar *statfile_name; - gchar *symbol; - float weight; + gchar *statfile_name; + gchar *symbol; + float weight; }; struct regexp_ctx { - gint (*filter) (struct rspamd_task * task); - GHashTable *autolearn_symbols; - gchar *statfile_prefix; - - rspamd_mempool_t *regexp_pool; - rspamd_mempool_t *dynamic_pool; - gsize max_size; - gsize max_threads; - GThreadPool *workers; + gint (*filter) (struct rspamd_task * task); + GHashTable *autolearn_symbols; + gchar *statfile_prefix; + + rspamd_mempool_t *regexp_pool; + rspamd_mempool_t *dynamic_pool; + gsize max_size; + gsize max_threads; + GThreadPool *workers; }; struct regexp_json_buf { - gchar *buf; - gchar *pos; - size_t buflen; - struct rspamd_config *cfg; + gchar *buf; + gchar *pos; + size_t buflen; + struct rspamd_config *cfg; }; /* Lua regexp module for checking rspamd regexps */ LUA_FUNCTION_DEF (regexp, match); -static const struct luaL_reg regexplib_m[] = { +static const struct luaL_reg regexplib_m[] = { LUA_INTERFACE_DEF (regexp, match), {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static struct regexp_ctx *regexp_module_ctx = NULL; -static GMutex *workers_mtx = NULL; - -static gint regexp_common_filter (struct rspamd_task *task); -static void process_regexp_item_threaded (gpointer data, gpointer user_data); -static gboolean rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_has_content_part (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_has_content_part_len (struct rspamd_task *task, GList * args, void *unused); -static void process_regexp_item (struct rspamd_task *task, void *user_data); +static struct regexp_ctx *regexp_module_ctx = NULL; +static GMutex *workers_mtx = NULL; + +static gint regexp_common_filter (struct rspamd_task *task); +static void process_regexp_item_threaded (gpointer data, gpointer user_data); +static gboolean rspamd_regexp_match_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part_len (struct rspamd_task *task, + GList * args, + void *unused); +static void process_regexp_item (struct rspamd_task *task, void *user_data); /* Initialization */ @@ -113,13 +133,15 @@ module_t regexp_module = { /* Task cache functions */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) -static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; +static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; #else G_LOCK_DEFINE (task_cache_mtx); #endif void -task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 result) +task_cache_add (struct rspamd_task *task, + struct rspamd_regexp *re, + gint32 result) { if (result == 0) { result = -1; @@ -130,7 +152,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul #else G_LOCK (task_cache_mtx); #endif - g_hash_table_insert (task->re_cache, re->regexp_text, GINT_TO_POINTER (result)); + g_hash_table_insert (task->re_cache, re->regexp_text, + GINT_TO_POINTER (result)); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_unlock (&task_cache_mtx); #else @@ -141,8 +164,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul gint32 task_cache_check (struct rspamd_task *task, struct rspamd_regexp *re) { - gpointer res; - gint32 r; + gpointer res; + gint32 r; #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_lock (&task_cache_mtx); @@ -178,11 +201,11 @@ luaopen_regexp (lua_State * L) return 1; } -static void +static void regexp_dynamic_insert_result (struct rspamd_task *task, void *user_data) { - gchar *symbol = user_data; - + gchar *symbol = user_data; + insert_result (task, symbol, 1, NULL); } @@ -222,18 +245,18 @@ op_less_equal (gint a, gint b) static gboolean parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) { - const gchar *pos; - gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; - gint state = 0, dots = 0; - - bzero (ip_buf, sizeof (ip_buf)); + const gchar *pos; + gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; + gint state = 0, dots = 0; + + bzero (ip_buf, sizeof (ip_buf)); bzero (mask_buf, sizeof (mask_buf)); pos = begin; p = ip_buf; if (*pos == '!') { addr->negative = TRUE; - pos ++; + pos++; } else { addr->negative = FALSE; @@ -241,45 +264,45 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) while (*pos) { switch (state) { - case 0: - state = 1; - p = ip_buf; - dots = 0; - break; - case 1: - /* Begin parse ip */ - if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else if (*pos == '.') { - *p ++ = *pos ++; - dots ++; - } - else if (*pos == '/') { - pos ++; - p = mask_buf; - state = 2; - } - else { - /* Invalid character */ - return FALSE; - } - break; - case 2: - /* Parse mask */ - if (p - mask_buf > 2) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else { - return FALSE; - } - break; + case 0: + state = 1; + p = ip_buf; + dots = 0; + break; + case 1: + /* Begin parse ip */ + if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else if (*pos == '.') { + *p++ = *pos++; + dots++; + } + else if (*pos == '/') { + pos++; + p = mask_buf; + state = 2; + } + else { + /* Invalid character */ + return FALSE; + } + break; + case 2: + /* Parse mask */ + if (p - mask_buf > 2) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else { + return FALSE; + } + break; } } @@ -303,11 +326,14 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) } /* Process regexp expression */ -static gboolean -read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chain, - const gchar *symbol, const gchar *line, gboolean raw_mode) +static gboolean +read_regexp_expression (rspamd_mempool_t * pool, + struct regexp_module_item *chain, + const gchar *symbol, + const gchar *line, + gboolean raw_mode) { - struct expression *e, *cur; + struct expression *e, *cur; e = parse_expression (pool, (gchar *)line); if (e == NULL) { @@ -318,9 +344,13 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai cur = e; while (cur) { if (cur->type == EXPR_REGEXP) { - cur->content.operand = parse_regexp (pool, cur->content.operand, raw_mode); + cur->content.operand = parse_regexp (pool, + cur->content.operand, + raw_mode); if (cur->content.operand == NULL) { - msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", symbol, line); + msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", + symbol, + line); return FALSE; } cur->type = EXPR_REGEXP_PARSED; @@ -333,11 +363,14 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai /* Callbacks for reading json dynamic rules */ -gchar * -json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +json_regexp_read_cb (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { - struct regexp_json_buf *jb; - gint free, off; + struct regexp_json_buf *jb; + gint free, off; if (data->cur_data == NULL) { jb = g_malloc (sizeof (struct regexp_json_buf)); @@ -376,16 +409,16 @@ json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma void json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { - struct regexp_json_buf *jb; - guint nelts, i, j; - json_t *js, *cur_elt, *cur_nm, *it_val; - json_error_t je; - gchar *cur_rule, *cur_symbol; - double score; - struct regexp_module_item *cur_item; - GList *cur_networks = NULL; - struct dynamic_map_item *cur_nitem; - rspamd_mempool_t *new_pool; + struct regexp_json_buf *jb; + guint nelts, i, j; + json_t *js, *cur_elt, *cur_nm, *it_val; + json_error_t je; + gchar *cur_rule, *cur_symbol; + double score; + struct regexp_module_item *cur_item; + GList *cur_networks = NULL; + struct dynamic_map_item *cur_nitem; + rspamd_mempool_t *new_pool; if (data->prev_data) { jb = data->prev_data; @@ -413,7 +446,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) js = json_loads (jb->buf, &je); if (!js) { - msg_err ("cannot load json data: parse error %s, on line %d", je.text, je.line); + msg_err ("cannot load json data: parse error %s, on line %d", + je.text, + je.line); return; } @@ -422,9 +457,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("loaded json is not an array"); return; } - + new_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - + remove_dynamic_rules (jb->cfg->cache); if (regexp_module_ctx->dynamic_pool != NULL) { rspamd_mempool_delete (regexp_module_ctx->dynamic_pool); @@ -447,14 +482,15 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("factor is not a number or not exists, but is required"); continue; } - score = json_number_value (cur_nm); + score = json_number_value (cur_nm); /* Symbol param */ cur_nm = json_object_get (cur_elt, "symbol"); if (cur_nm == NULL || !json_is_string (cur_nm)) { msg_err ("symbol is not a string or not exists, but is required"); continue; } - cur_symbol = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_symbol = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); /* Enabled flag */ cur_nm = json_object_get (cur_elt, "enabled"); if (cur_nm != NULL && json_is_boolean (cur_nm)) { @@ -467,7 +503,8 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) /* Rule */ cur_nm = json_object_get (cur_elt, "rule"); if (cur_nm != NULL && json_is_string (cur_nm)) { - cur_rule = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_rule = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); } /* Networks array */ cur_nm = json_object_get (cur_elt, "networks"); @@ -475,8 +512,11 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) for (j = 0; j < json_array_size (cur_nm); j++) { it_val = json_array_get (cur_nm, i); if (it_val && json_is_string (it_val)) { - cur_nitem = rspamd_mempool_alloc (new_pool, sizeof (struct dynamic_map_item)); - if (parse_regexp_ipmask (json_string_value (it_val), cur_nitem)) { + cur_nitem = + rspamd_mempool_alloc (new_pool, + sizeof (struct dynamic_map_item)); + if (parse_regexp_ipmask (json_string_value (it_val), + cur_nitem)) { cur_networks = g_list_prepend (cur_networks, cur_nitem); } } @@ -484,10 +524,19 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } if (cur_rule) { /* Dynamic rule has rule option */ - cur_item = rspamd_mempool_alloc0 (new_pool, sizeof (struct regexp_module_item)); + cur_item = + rspamd_mempool_alloc0 (new_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = cur_symbol; - if (read_regexp_expression (new_pool, cur_item, cur_symbol, cur_rule, jb->cfg->raw_mode)) { - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, process_regexp_item, cur_item, cur_networks); + if (read_regexp_expression (new_pool, cur_item, cur_symbol, + cur_rule, jb->cfg->raw_mode)) { + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + process_regexp_item, + cur_item, + cur_networks); } else { msg_warn ("cannot parse dynamic rule"); @@ -495,7 +544,13 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } else { /* Just rule that is allways true (for whitelisting for example) */ - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, regexp_dynamic_insert_result, cur_symbol, cur_networks); + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + regexp_dynamic_insert_result, + cur_symbol, + cur_networks); } if (cur_networks) { g_list_free (cur_networks); @@ -510,22 +565,44 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { regexp_module_ctx = g_malloc (sizeof (struct regexp_ctx)); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); regexp_module_ctx->dynamic_pool = NULL; - regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, + rspamd_str_equal); regexp_module_ctx->workers = NULL; *ctx = (struct module_ctx *)regexp_module_ctx; - register_expression_function ("regexp_match_number", rspamd_regexp_match_number, NULL); - register_expression_function ("regexp_occurs_number", rspamd_regexp_occurs_number, NULL); - register_expression_function ("raw_header_exists", rspamd_raw_header_exists, NULL); - register_expression_function ("check_smtp_data", rspamd_check_smtp_data, NULL); - register_expression_function ("content_type_is_type", rspamd_content_type_is_type, NULL); - register_expression_function ("content_type_is_subtype", rspamd_content_type_is_subtype, NULL); - register_expression_function ("content_type_has_param", rspamd_content_type_has_param, NULL); - register_expression_function ("content_type_compare_param", rspamd_content_type_compare_param, NULL); - register_expression_function ("has_content_part", rspamd_has_content_part, NULL); - register_expression_function ("has_content_part_len", rspamd_has_content_part_len, NULL); + register_expression_function ("regexp_match_number", + rspamd_regexp_match_number, + NULL); + register_expression_function ("regexp_occurs_number", + rspamd_regexp_occurs_number, + NULL); + register_expression_function ("raw_header_exists", + rspamd_raw_header_exists, + NULL); + register_expression_function ("check_smtp_data", + rspamd_check_smtp_data, + NULL); + register_expression_function ("content_type_is_type", + rspamd_content_type_is_type, + NULL); + register_expression_function ("content_type_is_subtype", + rspamd_content_type_is_subtype, + NULL); + register_expression_function ("content_type_has_param", + rspamd_content_type_has_param, + NULL); + register_expression_function ("content_type_compare_param", + rspamd_content_type_compare_param, + NULL); + register_expression_function ("has_content_part", + rspamd_has_content_part, + NULL); + register_expression_function ("has_content_part_len", + rspamd_has_content_part_len, + NULL); (void)luaopen_regexp (cfg->lua_state); @@ -533,18 +610,22 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) } -/* +/* * Parse string in format: * SYMBOL:statfile:weight */ void -parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_config *cfg) +parse_autolearn_param (const gchar *param, + const gchar *value, + struct rspamd_config *cfg) { - struct autolearn_data *d; - gchar *p; + struct autolearn_data *d; + gchar *p; p = rspamd_mempool_strdup (regexp_module_ctx->regexp_pool, value); - d = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (struct autolearn_data)); + d = + rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (struct autolearn_data)); d->symbol = strsep (&p, ":"); if (d->symbol) { @@ -552,7 +633,9 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con if (d->statfile_name) { if (p != NULL && *p != '\0') { d->weight = strtod (p, NULL); - g_hash_table_insert (regexp_module_ctx->autolearn_symbols, d->symbol, d); + g_hash_table_insert (regexp_module_ctx->autolearn_symbols, + d->symbol, + d); } } else { @@ -567,11 +650,11 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con gint regexp_module_config (struct rspamd_config *cfg) { - struct regexp_module_item *cur_item; - const ucl_object_t *sec, *value; - ucl_object_iter_t it = NULL; - gint res = TRUE; - struct regexp_json_buf *jb, **pjb; + struct regexp_module_item *cur_item; + const ucl_object_t *sec, *value; + ucl_object_iter_t it = NULL; + gint res = TRUE; + struct regexp_json_buf *jb, **pjb; sec = ucl_object_find_key (cfg->rcl_obj, "regexp"); @@ -585,44 +668,61 @@ regexp_module_config (struct rspamd_config *cfg) regexp_module_ctx->workers = NULL; while ((value = ucl_iterate_object (sec, &it, true)) != NULL) { - if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", sizeof ("autolearn") - 1) == 0) { - parse_autolearn_param (ucl_object_key (value), ucl_obj_tostring (value), cfg); + if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", + sizeof ("autolearn") - 1) == 0) { + parse_autolearn_param (ucl_object_key (value), + ucl_obj_tostring (value), cfg); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", sizeof ("dynamic_rules") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", + sizeof ("dynamic_rules") - 1) == 0) { jb = g_malloc (sizeof (struct regexp_json_buf)); pjb = g_malloc (sizeof (struct regexp_json_buf *)); jb->buf = NULL; jb->cfg = cfg; *pjb = jb; if (!add_map (cfg, ucl_obj_tostring (value), - "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, - (void **)pjb)) { + "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, + (void **)pjb)) { msg_err ("cannot add map %s", ucl_obj_tostring (value)); } } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", sizeof ("max_size") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", + sizeof ("max_size") - 1) == 0) { regexp_module_ctx->max_size = ucl_obj_toint (value); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", sizeof ("max_threads") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", + sizeof ("max_threads") - 1) == 0) { regexp_module_ctx->max_threads = ucl_obj_toint (value); } else if (value->type == UCL_STRING) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); - if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), - ucl_obj_tostring (value), cfg->raw_mode)) { + if (!read_regexp_expression (regexp_module_ctx->regexp_pool, + cur_item, ucl_object_key (value), + ucl_obj_tostring (value), cfg->raw_mode)) { res = FALSE; } - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else if (value->type == UCL_USERDATA) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = value->value.ud; - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else { - msg_warn ("unknown type of attribute %s for regexp module", ucl_object_key (value)); + msg_warn ("unknown type of attribute %s for regexp module", + ucl_object_key (value)); } } @@ -633,63 +733,72 @@ gint regexp_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (regexp_module_ctx->regexp_pool); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return regexp_module_config (cfg); } struct url_regexp_param { - struct rspamd_task *task; - GRegex *regexp; - struct rspamd_regexp *re; - gboolean found; + struct rspamd_task *task; + GRegex *regexp; + struct rspamd_regexp *re; + gboolean found; }; -static gboolean +static gboolean tree_url_callback (gpointer key, gpointer value, void *data) { - struct url_regexp_param *param = data; - struct uri *url = value; - GError *err = NULL; + struct url_regexp_param *param = data; + struct uri *url = value; + GError *err = NULL; - if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned TRUE", struri (url)); + msg_info ("process test regexp %s for url %s returned TRUE", + struri (url)); } task_cache_add (param->task, param->re, 1); param->found = TRUE; return TRUE; } else if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned FALSE", struri (url)); + msg_info ("process test regexp %s for url %s returned FALSE", + struri (url)); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", param->re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + param->re->regexp_text, + err->message); } return FALSE; } -static gsize -process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar *additional, - gint limit, int_compare_func f) +static gsize +process_regexp (struct rspamd_regexp *re, + struct rspamd_task *task, + const gchar *additional, + gint limit, + int_compare_func f) { - guint8 *ct; - gsize clen; - gint r, passed = 0, start, end, old; - gboolean matched = FALSE; - - GList *cur, *headerlist; - GRegex *regexp; - GMatchInfo *info; - GError *err = NULL; - struct url_regexp_param callback_param = { + guint8 *ct; + gsize clen; + gint r, passed = 0, start, end, old; + gboolean matched = FALSE; + + GList *cur, *headerlist; + GRegex *regexp; + GMatchInfo *info; + GError *err = NULL; + struct url_regexp_param callback_param = { .task = task, .re = re, .found = FALSE }; - struct mime_text_part *part; - struct raw_header *rh; + struct mime_text_part *part; + struct raw_header *rh; if (re == NULL) { msg_info ("invalid regexp passed"); @@ -698,16 +807,21 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar callback_param.regexp = re->regexp; if ((r = task_cache_check (task, re)) != -1) { - debug_task ("regexp /%s/ is found in cache, result: %d", re->regexp_text, r); + debug_task ("regexp /%s/ is found in cache, result: %d", + re->regexp_text, + r); return r == 1; } - + if (additional != NULL) { /* We have additional parameter defined, so ignore type of regexp expression and use it for parsing */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s with test %s", re->regexp_text, additional); + msg_info ("process test regexp %s with test %s", + re->regexp_text, + additional); } - if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, 0, NULL, NULL) == TRUE) { + if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, + 0, NULL, NULL) == TRUE) { if (G_UNLIKELY (re->is_test)) { msg_info ("result of regexp %s is true", re->regexp_text); } @@ -722,39 +836,53 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar switch (re->type) { case REGEXP_NONE: - msg_warn ("bad error detected: %s has invalid regexp type", re->regexp_text); + msg_warn ("bad error detected: %s has invalid regexp type", + re->regexp_text); return 0; case REGEXP_HEADER: /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ - headerlist = message_get_header (task->task_pool, task->message, re->header, re->is_strong); + headerlist = message_get_header (task->task_pool, + task->message, + re->header, + re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; } else { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, headerlist); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, headerlist); /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); /* Try to match regexp */ if (!re->is_raw) { /* Validate input */ @@ -763,9 +891,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (cur->data && g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, &err) == TRUE) { + if (cur->data && + g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -780,10 +914,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -803,8 +944,11 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } /* Skip too large parts */ - if (regexp_module_ctx->max_size != 0 && part->content->len > regexp_module_ctx->max_size) { - msg_info ("<%s> skip part of size %Hud", task->message_id, part->content->len); + if (regexp_module_ctx->max_size != 0 && part->content->len > + regexp_module_ctx->max_size) { + msg_info ("<%s> skip part of size %Hud", + task->message_id, + part->content->len); cur = g_list_next (cur); continue; } @@ -828,12 +972,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, + 0, &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", - re->regexp_text, - (gint)clen, - end); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen, + end); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -842,7 +989,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } end += old; @@ -852,10 +1000,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -863,11 +1014,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -879,17 +1034,22 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar ct = task->msg->str; clen = task->msg->len; - if (regexp_module_ctx->max_size != 0 && clen > regexp_module_ctx->max_size) { + if (regexp_module_ctx->max_size != 0 && clen > + regexp_module_ctx->max_size) { msg_info ("<%s> skip message of size %Hz", task->message_id, clen); return 0; } /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, + &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -898,7 +1058,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } old += end; @@ -908,10 +1069,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -919,11 +1083,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } task_cache_add (task, re, 0); return 0; @@ -949,21 +1117,29 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } return 0; case REGEXP_RAW_HEADER: - debug_task ("checking for raw header: %s with regexp: %s", re->header, re->regexp_text); + debug_task ("checking for raw header: %s with regexp: %s", + re->header, + re->regexp_text); /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ headerlist = message_get_raw_header (task, re->header, re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; @@ -971,14 +1147,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); rh = cur->data; /* Try to match regexp */ if (!re->is_raw) { @@ -988,9 +1167,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (rh->value && g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, &err) == TRUE) { + if (rh->value && + g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -1005,10 +1190,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -1025,10 +1217,12 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } static gboolean -maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *L) +maybe_call_lua_function (const gchar *name, + struct rspamd_task *task, + lua_State *L) { - struct rspamd_task **ptask; - gboolean res; + struct rspamd_task **ptask; + gboolean res; lua_getglobal (L, name); if (lua_isfunction (L, -1)) { @@ -1037,7 +1231,8 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *ptask = task; /* Call function */ if (lua_pcall (L, 1, 1, 0) != 0) { - msg_info ("call to %s failed: %s", (gchar *)name, lua_tostring (L, -1)); + msg_info ("call to %s failed: %s", (gchar *)name, + lua_tostring (L, -1)); return FALSE; } res = lua_toboolean (L, -1); @@ -1050,12 +1245,12 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State return FALSE; } -static gboolean +static gboolean optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) { - struct expression *it = (*e)->next; - gboolean ret = FALSE, is_nearest = TRUE; - gint skip_level = 0; + struct expression *it = (*e)->next; + gboolean ret = FALSE, is_nearest = TRUE; + gint skip_level = 0; /* Skip nearest logical operators from optimization */ if (!it || (it->type == EXPR_OPERATION && it->content.operation != '!')) { @@ -1106,22 +1301,29 @@ optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) return ret; } -static gboolean -process_regexp_expression (struct expression *expr, const gchar *symbol, struct rspamd_task *task, - const gchar *additional, struct lua_locked_state *nL) +static gboolean +process_regexp_expression (struct expression *expr, + const gchar *symbol, + struct rspamd_task *task, + const gchar *additional, + struct lua_locked_state *nL) { - GQueue *stack; - gsize cur, op1, op2; - struct expression *it = expr; - struct rspamd_regexp *re; - gboolean try_optimize = TRUE; + GQueue *stack; + gsize cur, op1, op2; + struct expression *it = expr; + struct rspamd_regexp *re; + gboolean try_optimize = TRUE; stack = g_queue_new (); while (it) { if (it->type == EXPR_REGEXP_PARSED) { /* Find corresponding symbol */ - cur = process_regexp ((struct rspamd_regexp *)it->content.operand, task, additional, 0, NULL); + cur = process_regexp ((struct rspamd_regexp *)it->content.operand, + task, + additional, + 0, + NULL); debug_task ("regexp %s found", cur ? "is" : "is not"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); @@ -1133,13 +1335,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_FUNCTION) { if (nL) { rspamd_mutex_lock (nL->m); - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, nL->L); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false"); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, task->cfg->lua_state); + } + debug_task ("function %s returned %s", + ((struct expression_function *)it->content.operand)->name, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1151,13 +1361,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct /* This may be lua function, try to call it */ if (nL) { rspamd_mutex_lock (nL->m); - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, nL->L); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", (const gchar *)it->content.operand, cur ? "true" : "false"); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + task->cfg->lua_state); + } + debug_task ("function %s returned %s", + (const gchar *)it->content.operand, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1171,7 +1389,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct it = it->next; continue; } - re = parse_regexp (task->cfg->cfg_pool, it->content.operand, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + it->content.operand, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot parse regexp, skip expression"); g_queue_free (stack); @@ -1185,7 +1405,8 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_OPERATION) { if (g_queue_is_empty (stack)) { /* Queue has no operands for operation, exiting */ - msg_warn ("regexp expression seems to be invalid: empty stack while reading operation"); + msg_warn ( + "regexp expression seems to be invalid: empty stack while reading operation"); g_queue_free (stack); return FALSE; } @@ -1199,12 +1420,16 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct case '&': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 && op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 && op2); break; case '|': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 || op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 || op2); break; default: it = it->next; @@ -1223,7 +1448,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct } } else { - msg_warn ("regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", symbol); + msg_warn ( + "regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", + symbol); } g_queue_free (stack); @@ -1239,11 +1466,12 @@ struct regexp_threaded_ud { static void process_regexp_item_threaded (gpointer data, gpointer user_data) { - struct regexp_threaded_ud *ud = data; - struct lua_locked_state *nL = user_data; + struct regexp_threaded_ud *ud = data; + struct lua_locked_state *nL = user_data; /* Process expression */ - if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, NULL, nL)) { + if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, + NULL, nL)) { g_mutex_lock (workers_mtx); insert_result (ud->task, ud->item->symbol, 1, NULL); g_mutex_unlock (workers_mtx); @@ -1254,18 +1482,18 @@ process_regexp_item_threaded (gpointer data, gpointer user_data) static void process_regexp_item (struct rspamd_task *task, void *user_data) { - struct regexp_module_item *item = user_data; - gboolean res = FALSE; - struct regexp_threaded_ud *thr_ud; - GError *err = NULL; - struct lua_locked_state *nL; + struct regexp_module_item *item = user_data; + gboolean res = FALSE; + struct regexp_threaded_ud *thr_ud; + GError *err = NULL; + struct lua_locked_state *nL; if (!item->lua_function && regexp_module_ctx->max_threads > 1) { if (regexp_module_ctx->workers == NULL) { #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) # if GLIB_MINOR_VERSION > 20 - if (! g_thread_get_initialized ()) { + if (!g_thread_get_initialized ()) { g_thread_init (NULL); } # else @@ -1273,20 +1501,27 @@ process_regexp_item (struct rspamd_task *task, void *user_data) # endif workers_mtx = g_mutex_new (); #else - workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (GMutex)); + workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (GMutex)); g_mutex_init (workers_mtx); #endif nL = init_lua_locked (task->cfg); luaopen_regexp (nL->L); - regexp_module_ctx->workers = g_thread_pool_new (process_regexp_item_threaded, - nL, regexp_module_ctx->max_threads, TRUE, &err); + regexp_module_ctx->workers = g_thread_pool_new ( + process_regexp_item_threaded, + nL, + regexp_module_ctx->max_threads, + TRUE, + &err); if (err != NULL) { msg_err ("thread pool creation failed: %s", err->message); regexp_module_ctx->max_threads = 0; return; } } - thr_ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct regexp_threaded_ud)); + thr_ud = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct regexp_threaded_ud)); thr_ud->item = item; thr_ud->task = task; @@ -1294,7 +1529,8 @@ process_regexp_item (struct rspamd_task *task, void *user_data) register_async_thread (task->s); g_thread_pool_push (regexp_module_ctx->workers, thr_ud, &err); if (err != NULL) { - msg_err ("error pushing task to the regexp thread pool: %s", err->message); + msg_err ("error pushing task to the regexp thread pool: %s", + err->message); remove_async_thread (task->s); } } @@ -1302,25 +1538,28 @@ process_regexp_item (struct rspamd_task *task, void *user_data) /* Non-threaded version */ if (item->lua_function) { /* Just call function */ - if (lua_call_expression_func (item->lua_function, task, NULL, &res) && res) { + if (lua_call_expression_func (item->lua_function, task, NULL, + &res) && res) { insert_result (task, item->symbol, 1, NULL); } } else { /* Process expression */ - if (process_regexp_expression (item->expr, item->symbol, task, NULL, NULL)) { + if (process_regexp_expression (item->expr, item->symbol, task, NULL, + NULL)) { insert_result (task, item->symbol, 1, NULL); } } } } -static gboolean -rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_match_number (struct rspamd_task *task, GList * args, + void *unused) { - gint param_count, res = 0; - struct expression_argument *arg; - GList *cur; + gint param_count, res = 0; + struct expression_argument *arg; + GList *cur; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1339,7 +1578,8 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused } } else { - if (process_regexp_expression (cur->data, "regexp_match_number", task, NULL, NULL)) { + if (process_regexp_expression (cur->data, "regexp_match_number", + task, NULL, NULL)) { res++; } if (res >= param_count) { @@ -1352,14 +1592,16 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused return res >= param_count; } -static gboolean -rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused) { - gint limit; - struct expression_argument *arg; - struct rspamd_regexp *re; - gchar *param, *err_str, op; - int_compare_func f = NULL; + gint limit; + struct expression_argument *arg; + struct rspamd_regexp *re; + gchar *param, *err_str, op; + int_compare_func f = NULL; if (args == NULL || args->next == NULL) { msg_warn ("wrong number of parameters to function, must be 2"); @@ -1382,13 +1624,13 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse op = '='; } else { - param ++; + param++; } switch (op) { case '>': if (*param == '=') { f = op_more_equal; - param ++; + param++; } else { f = op_more; @@ -1397,7 +1639,7 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse case '<': if (*param == '=') { f = op_less_equal; - param ++; + param++; } else { f = op_less; @@ -1407,7 +1649,9 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse f = op_equal; break; default: - msg_err ("wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", op); + msg_err ( + "wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", + op); return FALSE; } @@ -1419,10 +1663,10 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse return process_regexp (re, task, NULL, limit, f); } -static gboolean +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; + struct expression_argument *arg; if (args == NULL || task == NULL) { return FALSE; @@ -1438,15 +1682,19 @@ rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) } static gboolean -match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *what) +match_smtp_data (struct rspamd_task *task, + const gchar *re_text, + const gchar *what) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (*re_text == '/') { /* This is a regexp */ if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1471,12 +1719,12 @@ match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *wh return FALSE; } -static gboolean +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; - GList *cur, *rcpt_list = NULL; - gchar *type, *what = NULL; + struct expression_argument *arg; + GList *cur, *rcpt_list = NULL; + gchar *type, *what = NULL; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1492,59 +1740,59 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) else { type = arg->data; switch (*type) { - case 'f': - case 'F': - if (g_ascii_strcasecmp (type, "from") == 0) { - what = task->from; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'h': - case 'H': - if (g_ascii_strcasecmp (type, "helo") == 0) { - what = task->helo; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'u': - case 'U': - if (g_ascii_strcasecmp (type, "user") == 0) { - what = task->user; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 's': - case 'S': - if (g_ascii_strcasecmp (type, "subject") == 0) { - what = task->subject; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'r': - case 'R': - if (g_ascii_strcasecmp (type, "rcpt") == 0) { - rcpt_list = task->rcpt; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - default: + case 'f': + case 'F': + if (g_ascii_strcasecmp (type, "from") == 0) { + what = task->from; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'h': + case 'H': + if (g_ascii_strcasecmp (type, "helo") == 0) { + what = task->helo; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'u': + case 'U': + if (g_ascii_strcasecmp (type, "user") == 0) { + what = task->user; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 's': + case 'S': + if (g_ascii_strcasecmp (type, "subject") == 0) { + what = task->subject; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'r': + case 'R': + if (g_ascii_strcasecmp (type, "rcpt") == 0) { + rcpt_list = task->rcpt; + } + else { msg_warn ("bad argument to function: %s", type); return FALSE; + } + break; + default: + msg_warn ("bad argument to function: %s", type); + return FALSE; } } @@ -1552,7 +1800,7 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) /* Not enough data so regexp would NOT be found anyway */ return FALSE; } - + /* We would process only one more argument, others are ignored */ cur = args->next; if (cur) { @@ -1572,13 +1820,16 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) } else if (arg != NULL) { if (what != NULL) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, what, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, what, NULL)) { return TRUE; } } else { while (rcpt_list) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, rcpt_list->data, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, rcpt_list->data, + NULL)) { return TRUE; } rcpt_list = g_list_next (rcpt_list); @@ -1594,11 +1845,11 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) static gint lua_regexp_match (lua_State *L) { - void *ud = luaL_checkudata (L, 1, "rspamd{task}"); - struct rspamd_task *task; - const gchar *re_text; - struct rspamd_regexp *re; - gint r = 0; + void *ud = luaL_checkudata (L, 1, "rspamd{task}"); + struct rspamd_task *task; + const gchar *re_text; + struct rspamd_regexp *re; + gint r = 0; luaL_argcheck (L, ud != NULL, 1, "'task' expected"); task = ud ? *((struct rspamd_task **)ud) : NULL; @@ -1607,7 +1858,9 @@ lua_regexp_match (lua_State *L) /* This is a regexp */ if (task != NULL) { if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1622,18 +1875,20 @@ lua_regexp_match (lua_State *L) } static gboolean -rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name, *param_pattern; - const gchar *param_data; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name, *param_pattern; + const gchar *param_data; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1656,7 +1911,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1677,15 +1933,21 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) == NULL) { result = FALSE; } else { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1693,7 +1955,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, param_data, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1711,7 +1974,7 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1733,16 +1996,18 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } static gboolean -rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name; - const gchar *param_data; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name; + const gchar *param_data; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1757,7 +2022,8 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1778,12 +2044,14 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) != NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) != NULL) { return TRUE; } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1805,17 +2073,19 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un } static gboolean -rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused) +rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1830,7 +2100,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1851,11 +2122,15 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1863,7 +2138,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, ct->subtype, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1880,7 +2156,7 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1902,17 +2178,19 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } static gboolean -rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1928,7 +2206,8 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1949,11 +2228,15 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1978,7 +2261,7 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1999,11 +2282,12 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus return FALSE; } -static gboolean -compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype) +static gboolean +compare_subtype (struct rspamd_task *task, GMimeContentType * ct, + gchar *subtype) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (subtype == NULL || ct == NULL) { msg_warn ("invalid parameters passed"); @@ -2012,7 +2296,9 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype if (*subtype == '/') { /* This is regexp, so compile and create g_regexp object */ if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode); + re = + parse_regexp (task->cfg->cfg_pool, subtype, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -2040,7 +2326,7 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype return FALSE; } -static gboolean +static gboolean compare_len (struct mime_part *part, guint min, guint max) { if (min == 0 && max == 0) { @@ -2059,13 +2345,17 @@ compare_len (struct mime_part *part, guint min, guint max) } static gboolean -common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *param_subtype, gint min_len, gint max_len) +common_has_content_part (struct rspamd_task * task, + gchar *param_type, + gchar *param_subtype, + gint min_len, + gint max_len) { - struct rspamd_regexp *re; - struct mime_part *part; - GList *cur; - GMimeContentType *ct; - gint r; + struct rspamd_regexp *re; + struct mime_part *part; + GList *cur; + GMimeContentType *ct; + gint r; cur = g_list_first (task->parts); while (cur) { @@ -2078,8 +2368,11 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa if (*param_type == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode); + if ((re = + re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_type, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); cur = g_list_next (cur); @@ -2088,7 +2381,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa re_cache_add (param_type, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (ct->type && g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { + if (ct->type && + g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { if (param_subtype) { if (compare_subtype (task, ct, param_subtype)) { if (compare_len (part, min_len, max_len)) { @@ -2143,8 +2437,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa static gboolean rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2163,11 +2457,13 @@ rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) } static gboolean -rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unused) +rspamd_has_content_part_len (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - gint min = 0, max = 0; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + gint min = 0, max = 0; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2186,7 +2482,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus errno = 0; min = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } args = args->next; @@ -2194,7 +2492,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus arg = get_function_arg (args->data, task, TRUE); max = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } } |