]> source.dussan.org Git - rspamd.git/commitdiff
* Add symbols command for webui.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 6 Jan 2013 13:26:17 +0000 (17:26 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Sun, 6 Jan 2013 13:26:17 +0000 (17:26 +0400)
src/cfg_file.h
src/cfg_utils.c
src/cfg_xml.c
src/webui.c

index c6c8487ce1e23e319e3273850ae0be924a810376..538167ea8783fe2e208f153dbea2074d2e2600b5 100644 (file)
@@ -138,6 +138,23 @@ struct module_opt {
        enum lua_var_type lua_type;                                             /**< type of lua variable                                                               */
 };
 
+/**
+ * Symbol definition
+ */
+struct symbol_def {
+       gchar *name;
+       gchar *description;
+       gdouble weight;
+};
+
+/**
+ * Symbols group
+ */
+struct symbols_group {
+       gchar *name;
+       GList *symbols;
+};
+
 /**
  * Statfile section definition
  */
@@ -308,6 +325,7 @@ struct config_file {
        GHashTable* modules_opts;                                               /**< hash for module options indexed by module name             */
        GHashTable* variables;                                                  /**< hash of $variables defined in config, indexed by variable name */
        GHashTable* metrics;                                                    /**< hash of metrics indexed by metric name                             */
+       GList* symbols_groups;                                                  /**< groups of symbols                                                                  */
        GList* metrics_list;                                                    /**< linked list of metrics                                                             */
        GHashTable* metrics_symbols;                                    /**< hash table of metrics indexed by symbol                    */
        GHashTable* c_modules;                                                  /**< hash of c modules indexed by module name                   */
index ae0971d6a5977e49871645d7fd9d811d5bf34987..7b1910324771346a739933193bbf7d44dc21f529 100644 (file)
@@ -236,6 +236,9 @@ init_defaults (struct config_file *cfg)
 void
 free_config (struct config_file *cfg)
 {
+       GList                                                   *cur;
+       struct symbols_group                    *gr;
+
        remove_all_maps (cfg);
        g_hash_table_remove_all (cfg->modules_opts);
        g_hash_table_unref (cfg->modules_opts);
@@ -251,6 +254,19 @@ free_config (struct config_file *cfg)
        g_hash_table_unref (cfg->cfg_params);
        g_hash_table_destroy (cfg->metrics_symbols);
        g_hash_table_destroy (cfg->classifiers_symbols);
+       /* Free symbols groups */
+       cur = cfg->symbols_groups;
+       while (cur) {
+               gr = cur->data;
+               if (gr->symbols) {
+                       g_list_free (gr->symbols);
+               }
+               cur = g_list_next (cur);
+       }
+       if (cfg->symbols_groups) {
+               g_list_free (cfg->symbols_groups);
+       }
+
        if (cfg->checksum) {
                g_free (cfg->checksum);
        }
index 88650c99028181c03448401b60f5670abb1fc677..6ae3ce7c378d12193e7914c7786c069447f44930 100644 (file)
@@ -1050,15 +1050,28 @@ handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
        return TRUE;
 }
 
+static gint
+symbols_group_find_func (gconstpointer a, gconstpointer b)
+{
+       const struct symbols_group              *gr = a;
+       const gchar                                             *uv = b;
+
+       return g_ascii_strcasecmp (gr->name, uv);
+}
+
 gboolean
 handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
 {
-       gchar                          *strval, *err, *desc;
+       gchar                          *strval, *err, *desc, *group;
        double                         *value;
-       GList                          *metric_list;
+       GList                          *metric_list, *group_list;
        struct metric                  *metric = ctx->section_pointer;
+       struct symbols_group               *sym_group;
+       struct symbol_def                          *sym_def;
 
+       sym_def = memory_pool_alloc (cfg->cfg_pool, sizeof (struct symbol_def));
        value = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
+
        if (attrs == NULL || (strval = g_hash_table_lookup (attrs, "weight")) == NULL) {
                msg_info ("symbol tag should have \"weight\" attribute, assume weight 1.0");
                *value = 1.0;
@@ -1072,19 +1085,30 @@ handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
                }
        }
        
+       sym_def->weight = *value;
+       sym_def->name = memory_pool_strdup (cfg->cfg_pool, data);
+
        if (attrs != NULL) {
                desc = g_hash_table_lookup (attrs, "description");
                if (desc) {
-                       g_hash_table_insert (metric->descriptions, data, memory_pool_strdup (cfg->cfg_pool, desc));
+                       sym_def->description = memory_pool_strdup (cfg->cfg_pool, desc);
+                       g_hash_table_insert (metric->descriptions, data, sym_def->description);
+               }
+               else {
+                       sym_def->description = NULL;
+               }
+               group = g_hash_table_lookup (attrs, "group");
+               if (group == NULL) {
+                       group = "ungrouped";
                }
        }
 
-       g_hash_table_insert (metric->symbols, data, value);
+       g_hash_table_insert (metric->symbols, sym_def->name, value);
 
-       if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, data)) == NULL) {
+       if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, sym_def->name)) == NULL) {
                metric_list = g_list_prepend (NULL, metric);
                memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, metric_list);
-               g_hash_table_insert (cfg->metrics_symbols, data, metric_list);
+               g_hash_table_insert (cfg->metrics_symbols, sym_def->name, metric_list);
        }
        else {
                /* Slow but keep start element of list in safe */
@@ -1093,6 +1117,21 @@ handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
                }
        }
 
+       /* Search for symbol group */
+       group_list = g_list_find_custom (cfg->symbols_groups, group, symbols_group_find_func);
+       if (group_list == NULL) {
+               /* Create new group */
+               sym_group = memory_pool_alloc (cfg->cfg_pool, sizeof (struct symbols_group));
+               sym_group->name = memory_pool_strdup (cfg->cfg_pool, group);
+               sym_group->symbols = NULL;
+               cfg->symbols_groups = g_list_prepend (cfg->symbols_groups, sym_group);
+       }
+       else {
+               sym_group = group_list->data;
+       }
+       /* Insert symbol */
+       sym_group->symbols = g_list_prepend (sym_group->symbols, sym_def);
+
        return TRUE;
 }
 
index 36eb47fda4167df42ce205d9a416af650e4a3611..92b8c601c1205b2b180287a106cdf85fc67dc20c 100644 (file)
@@ -57,6 +57,7 @@
 
 /* HTTP paths */
 #define PATH_AUTH "/login"
+#define PATH_SYMBOLS "/symbols"
 
 gpointer init_webui_worker (void);
 void start_webui_worker (struct rspamd_worker *worker);
@@ -218,6 +219,16 @@ webui_ssl_init (struct rspamd_webui_worker_ctx *ctx)
 }
 #endif
 
+/* Calculate and set content-length header */
+static void
+http_calculate_content_length (struct evbuffer *evb, struct evhttp_request *req)
+{
+       gchar                                                                    numbuf[64];
+
+       rspamd_snprintf (numbuf, sizeof (numbuf), "%z", evbuffer_get_length (evb));
+       evhttp_add_header(req->output_headers, "Content-Length", numbuf);
+}
+
 /* Command handlers */
 
 /*
@@ -266,15 +277,86 @@ http_handle_auth (struct evhttp_request *req, gpointer arg)
                hours = uptime / 3600;
                minutes = uptime / 60 - hours * 60;
                uptime -= hours * 3600 + minutes * 60;
-               rspamd_snprintf (uptime_buf, sizeof (uptime_buf), "%d hour%s %d minute%s %d second%s", hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " ", (gint)uptime, uptime > 1 ? "s" : " ");
+               rspamd_snprintf (uptime_buf, sizeof (uptime_buf), "%d hour%s %d minute%s %d second%s", hours, hours != 1 ? "s" : " ", minutes, minutes != 1 ? "s" : " ", (gint)uptime, uptime != 1 ? "s" : " ");
        }
 
        evbuffer_add_printf (evb, "{\"auth\": \"%s\", \"version\": \"%s\", \"uptime\": \"%s\", \"error\": \"%s\"}" CRLF,
                        auth, RVERSION, uptime_buf, error);
-       evhttp_add_header(req->output_headers, "Connection", "close");
+       evhttp_add_header (req->output_headers, "Connection", "close");
+       http_calculate_content_length (evb, req);
+
+       evhttp_send_reply (req, HTTP_OK, "OK", evb);
+       evbuffer_free (evb);
+}
+
+/*
+ * Symbols command handler:
+ * request: /symbols
+ * reply: json [{
+ *     "name": "group_name",
+ *     "symbols": [
+ *             {
+ *             "name": "name",
+ *             "weight": 0.1,
+ *             "description": "description of symbol"
+ *             },
+ *             {...}
+ * },
+ * {...}]
+ */
+static void
+http_handle_symbols (struct evhttp_request *req, gpointer arg)
+{
+       struct rspamd_webui_worker_ctx                  *ctx = arg;
+       struct evbuffer                                                 *evb;
+       GList                                                                   *cur_gr, *cur_sym;
+       struct symbols_group                                    *gr;
+       struct symbol_def                                               *sym;
+
+       evb = evbuffer_new ();
+       if (!evb) {
+               msg_err ("cannot allocate evbuffer for reply");
+               return;
+       }
+
+       /* Trailer */
+       evbuffer_add (evb, "[", 1);
+
+       /* Go throught all symbols groups */
+       cur_gr = ctx->cfg->symbols_groups;
+       while (cur_gr) {
+               gr = cur_gr->data;
+               evbuffer_add_printf (evb, "{\"group\":\"%s\",\"rules\":[", gr->name);
+               /* Iterate throught all symbols */
+               cur_sym = gr->symbols;
+               while (cur_sym) {
+                       sym = cur_sym->data;
+
+                       if (sym->description) {
+                               evbuffer_add_printf (evb, "{\"symbol\":\"%s\",\"weight\":%.2f,\"description\":\"%s\"%s", sym->name, sym->weight,
+                                               sym->description, g_list_next (cur_sym) ? "}," : "}");
+                       }
+                       else {
+                               evbuffer_add_printf (evb, "{\"symbol\":\"%s\",\"weight\":%.2f%s", sym->name, sym->weight,
+                                                                               g_list_next (cur_sym) ? "}," : "}");
+                       }
+
+                       cur_sym = g_list_next (cur_sym);
+               }
+               if (g_list_next (cur_gr)) {
+                       evbuffer_add (evb, "]},", 3);
+               }
+               else {
+                       evbuffer_add (evb, "]},", 2);
+               }
+               cur_gr = g_list_next (cur_gr);
+       }
+       evbuffer_add (evb, "]" CRLF, 3);
+       evhttp_add_header (req->output_headers, "Connection", "close");
+       http_calculate_content_length (evb, req);
 
-       evhttp_send_reply(req, HTTP_OK, "OK", evb);
-       evbuffer_free(evb);
+       evhttp_send_reply (req, HTTP_OK, "OK", evb);
+       evbuffer_free (evb);
 }
 
 gpointer
@@ -351,6 +433,7 @@ start_webui_worker (struct rspamd_worker *worker)
 
        /* Add callbacks for different methods */
        evhttp_set_cb (ctx->http, PATH_AUTH, http_handle_auth, ctx);
+       evhttp_set_cb (ctx->http, PATH_SYMBOLS, http_handle_symbols, ctx);
 
        ctx->resolver = dns_resolver_init (ctx->ev_base, worker->srv->cfg);