summaryrefslogtreecommitdiffstats
path: root/src/webui.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/webui.c')
-rw-r--r--src/webui.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/webui.c b/src/webui.c
index 05c64fc1d..326cd7639 100644
--- a/src/webui.c
+++ b/src/webui.c
@@ -58,6 +58,8 @@
/* HTTP paths */
#define PATH_AUTH "/login"
#define PATH_SYMBOLS "/symbols"
+#define PATH_MAPS "/maps"
+#define PATH_GET_MAP "/getmap"
gpointer init_webui_worker (void);
void start_webui_worker (struct rspamd_worker *worker);
@@ -253,6 +255,7 @@ http_handle_auth (struct evhttp_request *req, gpointer arg)
evb = evbuffer_new ();
if (!evb) {
msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
return;
}
@@ -320,6 +323,7 @@ http_handle_symbols (struct evhttp_request *req, gpointer arg)
evb = evbuffer_new ();
if (!evb) {
msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500", NULL);
return;
}
@@ -363,6 +367,157 @@ http_handle_symbols (struct evhttp_request *req, gpointer arg)
evbuffer_free (evb);
}
+/*
+ * Maps command handler:
+ * request: /maps
+ * headers: Password
+ * reply: json [
+ * {
+ * "map": "name",
+ * "description": "description",
+ * "editable": true
+ * },
+ * {...}
+ * ]
+ */
+static void
+http_handle_maps (struct evhttp_request *req, gpointer arg)
+{
+ struct rspamd_webui_worker_ctx *ctx = arg;
+ struct evbuffer *evb;
+ GList *cur;
+ struct rspamd_map *map;
+ gboolean editable;
+
+ evb = evbuffer_new ();
+ if (!evb) {
+ msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ return;
+ }
+
+ /* Trailer */
+ evbuffer_add (evb, "[", 1);
+
+ /* Iterate over all maps */
+ cur = ctx->cfg->maps;
+ while (cur) {
+ map = cur->data;
+ if (map->protocol == MAP_PROTO_FILE && map->description != NULL) {
+ if (access (map->uri, R_OK) == 0) {
+ editable = access (map->uri, W_OK) == 0;
+ evbuffer_add_printf (evb, "{\"map\":%u,\"description\":\"%s\",\"editable\":%s%s",
+ map->id, map->description, editable ? "true" : "false",
+ g_list_next (cur) ? "}," : "}");
+ }
+ }
+ cur = g_list_next (cur);
+ }
+
+ 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);
+}
+
+/*
+ * Get map command handler:
+ * request: /getmap
+ * headers: Password, Map
+ * reply: plain-text
+ */
+static void
+http_handle_get_map (struct evhttp_request *req, gpointer arg)
+{
+ struct rspamd_webui_worker_ctx *ctx = arg;
+ struct evbuffer *evb;
+ GList *cur;
+ struct rspamd_map *map;
+ const gchar *idstr;
+ gchar *errstr;
+ struct stat st;
+ gint fd;
+ guint32 id;
+ gboolean found = FALSE;
+
+ evb = evbuffer_new ();
+ if (!evb) {
+ msg_err ("cannot allocate evbuffer for reply");
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ return;
+ }
+
+ idstr = evhttp_find_header (req->input_headers, "Map");
+
+ if (idstr == NULL) {
+ msg_info ("absent map id");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+
+ id = strtoul (idstr, &errstr, 10);
+ if (*errstr != '\0') {
+ msg_info ("invalid map id");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+
+ /* Now let's be sure that we have map defined in configuration */
+ cur = ctx->cfg->maps;
+ while (cur) {
+ map = cur->data;
+ if (map->id == id && map->protocol == MAP_PROTO_FILE) {
+ found = TRUE;
+ break;
+ }
+ cur = g_list_next (cur);
+ }
+
+ if (!found) {
+ msg_info ("map not found");
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_NOTFOUND, "404 map not found", NULL);
+ return;
+ }
+
+ if (stat (map->uri, &st) == -1 || (fd = open (map->uri, O_RDONLY)) == -1) {
+ msg_err ("cannot open map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map open error", NULL);
+ return;
+ }
+ /* Set buffer size */
+ if (evbuffer_expand (evb, st.st_size) != 0) {
+ msg_err ("cannot allocate buffer for map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 insufficient memory", NULL);
+ close (fd);
+ return;
+ }
+
+ /* Read the whole buffer */
+ if (evbuffer_read (evb, fd, st.st_size) == -1) {
+ msg_err ("cannot read map %s: %s", map->uri, strerror (errno));
+ evbuffer_free (evb);
+ evhttp_send_reply (req, HTTP_INTERNAL, "500 map read error", NULL);
+ close (fd);
+ return;
+ }
+
+ evhttp_add_header (req->output_headers, "Connection", "close");
+ http_calculate_content_length (evb, req);
+
+ close (fd);
+
+ evhttp_send_reply (req, HTTP_OK, "OK", evb);
+ evbuffer_free (evb);
+}
+
+
gpointer
init_webui_worker (void)
{
@@ -438,6 +593,8 @@ 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);
+ evhttp_set_cb (ctx->http, PATH_MAPS, http_handle_maps, ctx);
+ evhttp_set_cb (ctx->http, PATH_GET_MAP, http_handle_get_map, ctx);
ctx->resolver = dns_resolver_init (ctx->ev_base, worker->srv->cfg);