* Creates new dynamic map of IP/mask addresses.
* @param {string} mapline URL for a map
* @param {string} description optional map description
- * @return {radix} radix tree object
+ * @return {map} radix tree object
* @example
local ip_map = rspamd_config:add_radix_map ('file:///path/to/file', 'my radix map')
...
/***
* @method rspamd_config:radix_from_config(mname, optname)
- * Creates new static map of IP/mask addresses from config.
+ * Creates new embedded map of IP/mask addresses from config.
* @param {string} mname name of module
* @param {string} optname option to get
- * @return {radix} radix tree object
+ * @return {map} radix tree object
* @example
local ip_map = rspamd_config:radix_from_config ('mymodule', 'ips')
...
* Creates new dynamic map string objects.
* @param {string} mapline URL for a map
* @param {string} description optional map description
- * @return {hash} hash set object
+ * @return {map} hash set object
* @example
local hash_map = rspamd_config:add_hash_map ('file:///path/to/file', 'my hash map')
...
* Creates new dynamic map of key/values associations.
* @param {string} mapline URL for a map
* @param {string} description optional map description
- * @return {hash} hash table object
+ * @return {map} hash table object
* @example
local kv_map = rspamd_config:add_kv_map ('file:///path/to/file', 'my kv map')
...
end
*/
/***
- * @method rspamd_config:add_map(mapline[, description], callback)
- * Creates new dynamic map with free-form callback
- * @param {string} mapline URL for a map
- * @param {string} description optional map description
- * @param {function} callback function to be called on map load and/or update
- * @return {bool} `true` if map has been added
+ * @method rspamd_config:add_map({args})
+ * Creates new dynamic map according to the attributes passed.
+ *
+ * - `type`: type of map to be created, can be one of the following set:
+ * + `set`: set of strings
+ * + `radix`: map of IP addresses to strings
+ * + `map`: map of strings to strings
+ * + `regexp`: map of regexps to strings
+ * + `callback`: map processed by lua callback
+ * - `url`: url to load map from
+ * - `description`: map's description
+ * - `callback`: lua callback for the map
+ *
+ * @return {map} `true` if map has been added
* @example
local str = ''
lua_config_add_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *map_line, *description;
+ const gchar *map_line = NULL, *description = NULL;
+ const gchar *type = NULL;
struct lua_map_callback_data *cbdata;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;
- int cbidx;
+ int cbidx = -1, ret;
+ GError *err = NULL;
if (cfg) {
- map_line = luaL_checkstring (L, 2);
+ if (lua_type (L, 2) == LUA_TTABLE) {
+ if (!rspamd_lua_parse_table_arguments (L, 2, &err,
+ "type=*S;description=S;callback=F;url=*S",
+ &type, &description, &cbidx, &map_line)) {
+ ret = luaL_error (L, "invalid table arguments: %s", err->message);
+ g_error_free (err);
+
+ return ret;
+ }
- if (lua_gettop (L) == 4) {
- description = lua_tostring (L, 3);
- cbidx = 4;
- }
- else {
- description = NULL;
- cbidx = 3;
- }
+ g_assert (type != NULL && map_line != NULL);
- map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
- map->type = RSPAMD_LUA_MAP_CALLBACK;
- map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
- sizeof (*map->data.cbdata));
- cbdata = map->data.cbdata;
- cbdata->L = L;
- cbdata->data = NULL;
- cbdata->lua_map = map;
-
- if (lua_type (L, cbidx) == LUA_TFUNCTION) {
- lua_pushvalue (L, cbidx);
- /* Get a reference */
- cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
- }
- else {
- /*
- * Now we can create maps with delayed callbacks, to allow better
- * closures generation
- */
- cbdata->ref = -1;
- }
+ if (strcmp (type, "callback") == 0) {
+ if (cbidx == -1) {
+ ret = luaL_error (L, "invalid table arguments: callback missing");
+ return ret;
+ }
+
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->type = RSPAMD_LUA_MAP_CALLBACK;
+ map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
+ sizeof (*map->data.cbdata));
+ cbdata = map->data.cbdata;
+ cbdata->L = L;
+ cbdata->data = NULL;
+ cbdata->lua_map = map;
+ cbdata->ref = cbidx;
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ lua_map_read, lua_map_fin,
+ (void **)&map->data.cbdata)) == NULL) {
+ msg_warn_config ("invalid map %s", map_line);
+ luaL_unref (L, LUA_REGISTRYINDEX, cbidx);
+ lua_pushnil (L);
+
+ return 1;
+ }
+ }
+ else if (strcmp (type, "set") == 0) {
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->data.hash = g_hash_table_new (rspamd_strcase_hash,
+ rspamd_strcase_equal);
+ map->type = RSPAMD_LUA_MAP_SET;
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ rspamd_hosts_read,
+ rspamd_hosts_fin,
+ (void **)&map->data.hash)) == NULL) {
+ msg_warn_config ("invalid set map %s", map_line);
+ g_hash_table_destroy (map->data.hash);
+ lua_pushnil (L);
+
+ return 1;
+ }
+ }
+ else if (strcmp (type, "map") == 0) {
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->data.hash = g_hash_table_new (rspamd_strcase_hash,
+ rspamd_strcase_equal);
+ map->type = RSPAMD_LUA_MAP_HASH;
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ rspamd_kv_list_read,
+ rspamd_kv_list_fin,
+ (void **)&map->data.hash)) == NULL) {
+ msg_warn_config ("invalid hash map %s", map_line);
+ g_hash_table_destroy (map->data.hash);
+ lua_pushnil (L);
+ return 1;
+ }
+ }
+ else if (strcmp (type, "radix") == 0) {
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->data.radix = radix_create_compressed ();
+ map->type = RSPAMD_LUA_MAP_RADIX;
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ rspamd_radix_read,
+ rspamd_radix_fin,
+ (void **)&map->data.radix)) == NULL) {
+ msg_warn_config ("invalid radix map %s", map_line);
+ radix_destroy_compressed (map->data.radix);
+ lua_pushnil (L);
+ return 1;
+ }
+ }
+ else if (strcmp (type, "regexp") == 0) {
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->data.radix = radix_create_compressed ();
+ map->type = RSPAMD_LUA_MAP_RADIX;
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ rspamd_regexp_list_read,
+ rspamd_regexp_list_fin,
+ (void **)&map->data.re_map)) == NULL) {
+ msg_warn_config ("invalid regexp map %s", map_line);
+ lua_pushnil (L);
+ return 1;
+ }
+ }
+ else {
+ ret = luaL_error (L, "invalid arguments: unknown type '%s'", type);
+
+ return ret;
+ }
- if ((m = rspamd_map_add (cfg, map_line, description,
- lua_map_read, lua_map_fin,
- (void **)&map->data.cbdata)) == NULL) {
- msg_warn_config ("invalid map %s", map_line);
- lua_pushnil (L);
- }
- else {
map->map = m;
pmap = lua_newuserdata (L, sizeof (void *));
*pmap = map;
rspamd_lua_setclass (L, "rspamd{map}", -1);
}
+ else {
+ /*
+ * Legacy format add_map(map_line, description, callback)
+ */
+ map_line = luaL_checkstring (L, 2);
+
+ if (lua_gettop (L) == 4) {
+ description = lua_tostring (L, 3);
+ cbidx = 4;
+ }
+ else {
+ description = NULL;
+ cbidx = 3;
+ }
+
+ map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
+ map->type = RSPAMD_LUA_MAP_CALLBACK;
+ map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
+ sizeof (*map->data.cbdata));
+ cbdata = map->data.cbdata;
+ cbdata->L = L;
+ cbdata->data = NULL;
+ cbdata->lua_map = map;
+
+ if (lua_type (L, cbidx) == LUA_TFUNCTION) {
+ lua_pushvalue (L, cbidx);
+ /* Get a reference */
+ cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
+ }
+ else {
+ /*
+ * Now we can create maps with delayed callbacks, to allow better
+ * closures generation
+ */
+ cbdata->ref = -1;
+ }
+
+ if ((m = rspamd_map_add (cfg, map_line, description,
+ lua_map_read, lua_map_fin,
+ (void **)&map->data.cbdata)) == NULL) {
+ msg_warn_config ("invalid map %s", map_line);
+ lua_pushnil (L);
+ }
+ else {
+ map->map = m;
+ pmap = lua_newuserdata (L, sizeof (void *));
+ *pmap = map;
+ rspamd_lua_setclass (L, "rspamd{map}", -1);
+ }
+ }
}
else {
return luaL_error (L, "invalid arguments");
struct rspamd_lua_ip *addr = NULL;
const gchar *key, *value = NULL;
gpointer ud;
+ gsize len;
guint32 key_num = 0;
gboolean ret = FALSE;
ret = g_hash_table_lookup (map->data.hash, key) != NULL;
}
}
- else {
- /* key-value map */
- key = lua_tostring (L, 2);
+ else if (map->type == RSPAMD_LUA_MAP_REGEXP) {
+ key = lua_tolstring (L, 2, &len);
if (key) {
- value = g_hash_table_lookup (map->data.hash, key);
+ value = rspamd_match_regexp_map (map->data.re_map, key, len);
if (value) {
lua_pushstring (L, value);
}
}
}
+ else {
+ /* key-value map */
+ key = lua_tostring (L, 2);
+
+ if (key) {
+ value = g_hash_table_lookup (map->data.hash, key);
+ }
+
+ if (value) {
+ lua_pushstring (L, value);
+ return 1;
+ }
+ }
}
else {
return luaL_error (L, "invalid arguments");