* Improve and fix multimap module * Add rspamd_config object to stage of early configure of rspamdtags/0.3.9
@@ -797,9 +797,7 @@ FOREACH(LUA_PLUGIN ${LUA_PLUGINS}) | |||
IF(NOT IS_DIRECTORY ${DESTDIR}/${ETC_PREFIX}/rspamd/plugins/lua/${_rp}) | |||
INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${DESTDIR}/${ETC_PREFIX}/rspamd/plugins/lua/${_rp})") | |||
ENDIF(NOT IS_DIRECTORY ${DESTDIR}/${ETC_PREFIX}/rspamd/plugins/lua/${_rp}) | |||
IF(NOT EXISTS ${DESTDIR}/${ETC_PREFIX}/rspamd/plugins/${_rp}/${LUA_PLUGIN}) | |||
INSTALL(FILES "src/plugins/lua/${LUA_PLUGIN}" DESTINATION etc/rspamd/plugins/lua/${_rp}) | |||
ENDIF(NOT EXISTS ${DESTDIR}/${ETC_PREFIX}/rspamd/plugins/${_rp}/${LUA_PLUGIN}) | |||
INSTALL(FILES "src/plugins/lua/${LUA_PLUGIN}" DESTINATION etc/rspamd/plugins/lua/${_rp}) | |||
ENDFOREACH(LUA_PLUGIN) | |||
# Lua config |
@@ -974,6 +974,7 @@ handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable | |||
{ | |||
gchar *val, *cur_dir, *lua_dir, *lua_file, *tmp1, *tmp2; | |||
lua_State *L = cfg->lua_state; | |||
struct config_file **pcfg; | |||
/* First check for global variable 'config' */ | |||
lua_getglobal (L, "config"); | |||
@@ -993,6 +994,13 @@ handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable | |||
lua_newtable (L); | |||
lua_setglobal (L, "composites"); | |||
} | |||
lua_getglobal (L, "rspamd_config"); | |||
if (lua_isnil (L, -1)) { | |||
pcfg = lua_newuserdata (L, sizeof (struct config_file *)); | |||
lua_setclass (L, "rspamd{config}", -1); | |||
*pcfg = cfg; | |||
lua_setglobal (L, "rspamd_config"); | |||
} | |||
/* Now config tables can be used for configuring rspamd */ | |||
/* First check "src" attribute */ | |||
if (attrs != NULL && (val = g_hash_table_lookup (attrs, "src")) != NULL) { |
@@ -16,7 +16,7 @@ | |||
extern const luaL_reg null_reg[]; | |||
#define RSPAMD_LUA_API_VERSION 3 | |||
#define RSPAMD_LUA_API_VERSION 4 | |||
/* Common utility functions */ | |||
void lua_newclass (lua_State *L, const gchar *classname, const struct luaL_reg *func); |
@@ -42,6 +42,7 @@ LUA_FUNCTION_DEF (config, get_classifier); | |||
LUA_FUNCTION_DEF (config, register_symbol); | |||
LUA_FUNCTION_DEF (config, register_virtual_symbol); | |||
LUA_FUNCTION_DEF (config, register_callback_symbol); | |||
LUA_FUNCTION_DEF (config, register_callback_symbol_priority); | |||
LUA_FUNCTION_DEF (config, register_post_filter); | |||
LUA_FUNCTION_DEF (config, register_module_option); | |||
LUA_FUNCTION_DEF (config, get_api_version); | |||
@@ -56,6 +57,7 @@ static const struct luaL_reg configlib_m[] = { | |||
LUA_INTERFACE_DEF (config, register_symbol), | |||
LUA_INTERFACE_DEF (config, register_virtual_symbol), | |||
LUA_INTERFACE_DEF (config, register_callback_symbol), | |||
LUA_INTERFACE_DEF (config, register_callback_symbol_priority), | |||
LUA_INTERFACE_DEF (config, register_module_option), | |||
LUA_INTERFACE_DEF (config, register_post_filter), | |||
LUA_INTERFACE_DEF (config, get_api_version), | |||
@@ -573,6 +575,32 @@ lua_config_register_callback_symbol (lua_State * L) | |||
return 1; | |||
} | |||
static gint | |||
lua_config_register_callback_symbol_priority (lua_State * L) | |||
{ | |||
struct config_file *cfg = lua_check_config (L); | |||
const gchar *name, *callback; | |||
double weight; | |||
gint priority; | |||
struct lua_callback_data *cd; | |||
if (cfg) { | |||
name = memory_pool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); | |||
weight = luaL_checknumber (L, 3); | |||
priority = luaL_checknumber (L, 4); | |||
callback = luaL_checkstring (L, 5); | |||
if (name) { | |||
cd = g_malloc (sizeof (struct lua_callback_data)); | |||
cd->name = g_strdup (callback); | |||
cd->L = L; | |||
register_callback_symbol_priority (&cfg->cache, name, weight, priority, lua_metric_symbol_callback, cd); | |||
} | |||
} | |||
return 1; | |||
} | |||
/* Radix and hash table functions */ | |||
static gint | |||
lua_radix_get_key (lua_State * L) |
@@ -285,6 +285,7 @@ local function add_multimap_rule(params) | |||
newrule['hash'] = cdb.create(newrule['map']) | |||
if newrule['hash'] then | |||
table.insert(rules, newrule) | |||
return newrule | |||
else | |||
rspamd_logger.warn('Cannot add rule: map doesn\'t exists: ' .. newrule['map']) | |||
end | |||
@@ -294,6 +295,7 @@ local function add_multimap_rule(params) | |||
newrule['ips'] = rspamd_config:add_radix_map (newrule['map']) | |||
if newrule['ips'] then | |||
table.insert(rules, newrule) | |||
return newrule | |||
else | |||
rspamd_logger.warn('Cannot add rule: map doesn\'t exists: ' .. newrule['map']) | |||
end | |||
@@ -301,6 +303,7 @@ local function add_multimap_rule(params) | |||
newrule['hash'] = rspamd_config:add_hash_map (newrule['map']) | |||
if newrule['hash'] then | |||
table.insert(rules, newrule) | |||
return newrule | |||
else | |||
rspamd_logger.warn('Cannot add rule: map doesn\'t exists: ' .. newrule['map']) | |||
end | |||
@@ -308,14 +311,16 @@ local function add_multimap_rule(params) | |||
newrule['hash'] = rspamd_cdb.create(newrule['map']) | |||
if newrule['hash'] then | |||
table.insert(rules, newrule) | |||
return newrule | |||
else | |||
rspamd_logger.warn('Cannot add rule: map doesn\'t exists: ' .. newrule['map']) | |||
end | |||
else | |||
table.insert(rules, newrule) | |||
return newrule | |||
end | |||
end | |||
return newrule | |||
return nil | |||
end | |||
-- Registration | |||
@@ -358,7 +363,11 @@ end | |||
if table.maxn(rules) > 0 then | |||
-- add fake symbol to check all maps inside a single callback | |||
if type(rspamd_config.get_api_version) ~= 'nil' then | |||
rspamd_config:register_callback_symbol('MULTIMAP', 1.0, 'check_multimap') | |||
if rspamd_config.get_api_version() >= 4 then | |||
rspamd_config:register_callback_symbol_priority('MULTIMAP', 1.0, -1, 'check_multimap') | |||
else | |||
rspamd_config:register_callback_symbol('MULTIMAP', 1.0, 'check_multimap') | |||
end | |||
else | |||
rspamd_config:register_symbol('MULTIMAP', 1.0, 'check_multimap') | |||
end |
@@ -60,12 +60,19 @@ cache_logic_cmp (const void *p1, const void *p2) | |||
double w1, w2; | |||
double f1 = 0, f2 = 0; | |||
if (total_frequency > 0) { | |||
f1 = ((double)i1->s->frequency * nsymbols) / (double)total_frequency; | |||
f2 = ((double)i2->s->frequency * nsymbols) / (double)total_frequency; | |||
if (i1->priority == 0 && i2->priority == 0) { | |||
if (total_frequency > 0) { | |||
f1 = ((double)i1->s->frequency * nsymbols) / (double)total_frequency; | |||
f2 = ((double)i2->s->frequency * nsymbols) / (double)total_frequency; | |||
} | |||
w1 = abs (i1->s->weight) * WEIGHT_MULT + f1 * FREQUENCY_MULT + i1->s->avg_time * TIME_MULT; | |||
w2 = abs (i2->s->weight) * WEIGHT_MULT + f2 * FREQUENCY_MULT + i2->s->avg_time * TIME_MULT; | |||
} | |||
else { | |||
/* Strict sorting */ | |||
w1 = abs (i1->priority); | |||
w2 = abs (i2->priority); | |||
} | |||
w1 = abs (i1->s->weight) * WEIGHT_MULT + f1 * FREQUENCY_MULT + i1->s->avg_time * TIME_MULT; | |||
w2 = abs (i2->s->weight) * WEIGHT_MULT + f2 * FREQUENCY_MULT + i2->s->avg_time * TIME_MULT; | |||
return (gint)w2 - w1; | |||
} | |||
@@ -250,7 +257,7 @@ enum rspamd_symbol_type { | |||
}; | |||
static void | |||
register_symbol_common (struct symbols_cache **cache, const gchar *name, double weight, | |||
register_symbol_common (struct symbols_cache **cache, const gchar *name, double weight, gint priority, | |||
symbol_func_t func, gpointer user_data, enum rspamd_symbol_type type) | |||
{ | |||
struct cache_item *item = NULL; | |||
@@ -269,6 +276,7 @@ register_symbol_common (struct symbols_cache **cache, const gchar *name, double | |||
rspamd_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); | |||
item->func = func; | |||
item->user_data = user_data; | |||
item->priority = priority; | |||
switch (type) { | |||
case SYMBOL_TYPE_NORMAL: | |||
@@ -289,11 +297,23 @@ register_symbol_common (struct symbols_cache **cache, const gchar *name, double | |||
item->s->weight = weight; | |||
} | |||
if (item->s->weight > 0) { | |||
target = &(*cache)->static_items; | |||
/* If we have undefined priority determine list according to weight */ | |||
if (priority == 0) { | |||
if (item->s->weight > 0) { | |||
target = &(*cache)->static_items; | |||
} | |||
else { | |||
target = &(*cache)->negative_items; | |||
} | |||
} | |||
else { | |||
target = &(*cache)->negative_items; | |||
/* Items with more priority are called before items with less priority */ | |||
if (priority < 0) { | |||
target = &(*cache)->negative_items; | |||
} | |||
else { | |||
target = &(*cache)->static_items; | |||
} | |||
} | |||
pcache->used_items++; | |||
@@ -307,20 +327,27 @@ void | |||
register_symbol (struct symbols_cache **cache, const gchar *name, double weight, | |||
symbol_func_t func, gpointer user_data) | |||
{ | |||
register_symbol_common (cache, name, weight, func, user_data, SYMBOL_TYPE_NORMAL); | |||
register_symbol_common (cache, name, weight, 0, func, user_data, SYMBOL_TYPE_NORMAL); | |||
} | |||
void | |||
register_virtual_symbol (struct symbols_cache **cache, const gchar *name, double weight) | |||
{ | |||
register_symbol_common (cache, name, weight, NULL, NULL, SYMBOL_TYPE_VIRTUAL); | |||
register_symbol_common (cache, name, weight, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL); | |||
} | |||
void | |||
register_callback_symbol (struct symbols_cache **cache, const gchar *name, double weight, | |||
symbol_func_t func, gpointer user_data) | |||
{ | |||
register_symbol_common (cache, name, weight, func, user_data, SYMBOL_TYPE_CALLBACK); | |||
register_symbol_common (cache, name, weight, 0, func, user_data, SYMBOL_TYPE_CALLBACK); | |||
} | |||
void | |||
register_callback_symbol_priority (struct symbols_cache **cache, const gchar *name, double weight, gint priority, | |||
symbol_func_t func, gpointer user_data) | |||
{ | |||
register_symbol_common (cache, name, weight, priority, func, user_data, SYMBOL_TYPE_CALLBACK); | |||
} | |||
void | |||
@@ -355,6 +382,7 @@ register_dynamic_symbol (memory_pool_t *dynamic_pool, struct symbols_cache **cac | |||
item->s->weight = weight; | |||
} | |||
item->is_dynamic = TRUE; | |||
item->priority = 0; | |||
pcache->used_items++; | |||
msg_debug ("used items: %d, added symbol: %s", (*cache)->used_items, name); |
@@ -40,6 +40,9 @@ struct cache_item { | |||
/* Flags of virtual symbols */ | |||
gboolean is_virtual; | |||
gboolean is_callback; | |||
/* Priority */ | |||
gint priority; | |||
}; | |||
@@ -80,6 +83,7 @@ gboolean init_symbols_cache (memory_pool_t *pool, struct symbols_cache *cache, s | |||
*/ | |||
void register_symbol (struct symbols_cache **cache, const gchar *name, double weight, symbol_func_t func, gpointer user_data); | |||
/** | |||
* Register virtual symbol | |||
* @param name name of symbol | |||
@@ -94,6 +98,14 @@ void register_virtual_symbol (struct symbols_cache **cache, const gchar *name, d | |||
*/ | |||
void register_callback_symbol (struct symbols_cache **cache, const gchar *name, double weight, symbol_func_t func, gpointer user_data); | |||
/** | |||
* Register function for symbols parsing with strict priority | |||
* @param name name of symbol | |||
* @param func pointer to handler | |||
* @param user_data pointer to user_data | |||
*/ | |||
void register_callback_symbol_priority (struct symbols_cache **cache, const gchar *name, double weight, gint priority, symbol_func_t func, gpointer user_data); | |||
/** | |||
* Register function for dynamic symbols parsing | |||
* @param name name of symbol |