aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2013-01-06 17:26:17 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2013-01-06 17:26:17 +0400
commit54c2f784b7848b15f0a12329dd282e24fad87c04 (patch)
tree566c99d17ad85d9c11cfa2c9c8c94ec04fe66376
parent393a7c39ecc9224faa7c11afc32c8e74f54ea3c5 (diff)
downloadrspamd-54c2f784b7848b15f0a12329dd282e24fad87c04.tar.gz
rspamd-54c2f784b7848b15f0a12329dd282e24fad87c04.zip
* Add symbols command for webui.
-rw-r--r--src/cfg_file.h18
-rw-r--r--src/cfg_utils.c16
-rw-r--r--src/cfg_xml.c51
-rw-r--r--src/webui.c91
4 files changed, 166 insertions, 10 deletions
diff --git a/src/cfg_file.h b/src/cfg_file.h
index c6c8487ce..538167ea8 100644
--- a/src/cfg_file.h
+++ b/src/cfg_file.h
@@ -139,6 +139,23 @@ struct module_opt {
};
/**
+ * Symbol definition
+ */
+struct symbol_def {
+ gchar *name;
+ gchar *description;
+ gdouble weight;
+};
+
+/**
+ * Symbols group
+ */
+struct symbols_group {
+ gchar *name;
+ GList *symbols;
+};
+
+/**
* Statfile section definition
*/
struct statfile_section {
@@ -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 */
diff --git a/src/cfg_utils.c b/src/cfg_utils.c
index ae0971d6a..7b1910324 100644
--- a/src/cfg_utils.c
+++ b/src/cfg_utils.c
@@ -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);
}
diff --git a/src/cfg_xml.c b/src/cfg_xml.c
index 88650c990..6ae3ce7c3 100644
--- a/src/cfg_xml.c
+++ b/src/cfg_xml.c
@@ -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;
}
diff --git a/src/webui.c b/src/webui.c
index 36eb47fda..92b8c601c 100644
--- a/src/webui.c
+++ b/src/webui.c
@@ -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);