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
{
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");
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) {
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);
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);
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),
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)
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
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
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
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
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
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;
}
};
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;
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:
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++;
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
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);
/* Flags of virtual symbols */
gboolean is_virtual;
gboolean is_callback;
+
+ /* Priority */
+ gint priority;
};
*/
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
*/
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