]> source.dussan.org Git - rspamd.git/commitdiff
Allow rspamd HTTP router to serve static files.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 30 Mar 2014 21:04:25 +0000 (22:04 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 30 Mar 2014 21:04:25 +0000 (22:04 +0100)
src/http.c
src/http.h
src/rdns
src/webui.c

index e64f8a2e904fe0875d48b3fb6f5b368ec1536b79..81e8f8f5c102869123d33d8e39d69fcd6395ebf8 100644 (file)
@@ -940,6 +940,56 @@ rspamd_http_router_error_handler (struct rspamd_http_connection *conn, GError *e
        }
 }
 
+static gboolean
+rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry,
+               struct rspamd_http_message *msg)
+{
+       struct stat st;
+       int fd;
+       char filebuf[PATH_MAX], realbuf[PATH_MAX];
+       struct rspamd_http_message *reply_msg;
+
+       /* XXX: filter filename component only */
+       rspamd_snprintf (filebuf, sizeof (filebuf), "%s%c%v",
+                       entry->rt->default_fs_path, G_DIR_SEPARATOR, msg->url);
+
+       if (realpath (filebuf, realbuf) == NULL ||
+                       lstat (realbuf, &st) == -1 ||
+                       !S_ISREG (st.st_mode)) {
+               /* Skip everything suspicious */
+               return FALSE;
+       }
+
+       fd = open (realbuf, O_RDONLY);
+       if (fd == -1) {
+               return FALSE;
+       }
+
+       reply_msg = rspamd_http_new_message (HTTP_RESPONSE);
+       reply_msg->date = time (NULL);
+       reply_msg->code = 200;
+       reply_msg->body = g_string_sized_new (st.st_size);
+
+       if (read (fd, reply_msg->body->str, st.st_size) != st.st_size) {
+               close (fd);
+               rspamd_http_message_free (reply_msg);
+               return FALSE;
+       }
+
+       reply_msg->body->len = st.st_size;
+       reply_msg->body->str[st.st_size] = '\0';
+       close (fd);
+
+       rspamd_http_connection_reset (entry->conn);
+
+       /* XXX: detect content type */
+       rspamd_http_connection_write_message (entry->conn, reply_msg, NULL,
+                       "text/plain", entry, entry->conn->fd,
+                       entry->rt->ptv, entry->rt->ev_base);
+
+       return TRUE;
+}
+
 static int
 rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
                struct rspamd_http_message *msg)
@@ -967,19 +1017,23 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
                        return handler (entry, msg);
                }
                else {
-                       err = g_error_new (HTTP_ERROR, 404,
-                                                       "Not found");
-                       if (entry->rt->error_handler != NULL) {
-                               entry->rt->error_handler (entry, err);
+                       if (entry->rt->default_fs_path == NULL ||
+                                       rspamd_http_router_try_file (entry, msg)) {
+                               err = g_error_new (HTTP_ERROR, 404,
+                                               "Not found");
+                               if (entry->rt->error_handler != NULL) {
+                                       entry->rt->error_handler (entry, err);
+                               }
+                               err_msg = rspamd_http_new_message (HTTP_RESPONSE);
+                               err_msg->date = time (NULL);
+                               err_msg->code = err->code;
+                               err_msg->body = g_string_new (err->message);
+                               rspamd_http_connection_reset (entry->conn);
+                               rspamd_http_connection_write_message (entry->conn, err_msg, NULL,
+                                               "text/plain", entry, entry->conn->fd,
+                                               entry->rt->ptv, entry->rt->ev_base);
+                               g_error_free (err);
                        }
-                       err_msg = rspamd_http_new_message (HTTP_RESPONSE);
-                       err_msg->date = time (NULL);
-                       err_msg->code = err->code;
-                       err_msg->body = g_string_new (err->message);
-                       rspamd_http_connection_reset (entry->conn);
-                       rspamd_http_connection_write_message (entry->conn, err_msg, NULL,
-                                       "text/plain", entry, entry->conn->fd, entry->rt->ptv, entry->rt->ev_base);
-                       g_error_free (err);
                }
        }
 
@@ -989,9 +1043,11 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
 struct rspamd_http_connection_router*
 rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
                rspamd_http_router_finish_handler_t fh,
-               struct timeval *timeout, struct event_base *base)
+               struct timeval *timeout, struct event_base *base,
+               const char *default_fs_path)
 {
        struct rspamd_http_connection_router* new;
+       struct stat st;
 
        new = g_slice_alloc (sizeof (struct rspamd_http_connection_router));
        new->paths = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
@@ -1007,6 +1063,14 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
                new->ptv = NULL;
        }
 
+       if (default_fs_path != NULL && stat (default_fs_path, &st) != -1 &&
+                       S_ISDIR (st.st_mode)) {
+               new->default_fs_path = g_strdup (default_fs_path);
+       }
+       else {
+               new->default_fs_path = NULL;
+       }
+
        return new;
 }
 
@@ -1037,7 +1101,8 @@ rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router,
        conn->conn = rspamd_http_connection_new (NULL, rspamd_http_router_error_handler,
                        rspamd_http_router_finish_handler, 0, RSPAMD_HTTP_SERVER);
 
-       rspamd_http_connection_read_message (conn->conn, conn, fd, router->ptv, router->ev_base);
+       rspamd_http_connection_read_message (conn->conn, conn, fd, router->ptv,
+                       router->ev_base);
        LL_PREPEND (router->conns, conn);
 }
 
@@ -1051,6 +1116,9 @@ rspamd_http_router_free (struct rspamd_http_connection_router *router)
                        rspamd_http_entry_free (conn);
                }
 
+               if (router->default_fs_path != NULL) {
+                       g_free (router->default_fs_path);
+               }
                g_hash_table_unref (router->paths);
                g_slice_free1 (sizeof (struct rspamd_http_connection_router), router);
        }
index ffa2ecca2bd535240b236ba6cc7aad279e381e2f..8af4429c62b983d6e85da59d5b8bd9895453b9e9 100644 (file)
@@ -119,6 +119,7 @@ struct rspamd_http_connection_router {
        struct timeval tv;
        struct timeval *ptv;
        struct event_base *ev_base;
+       gchar *default_fs_path;
        rspamd_http_router_error_handler_t error_handler;
        rspamd_http_router_finish_handler_t finish_handler;
 };
@@ -242,13 +243,16 @@ time_t rspamd_http_parse_date (const gchar *header, gsize len);
  * Create new http connection router and the associated HTTP connection
  * @param eh error handler callback
  * @param fh finish handler callback
+ * @param default_fs_path if not NULL try to serve static files from
+ * the specified directory
  * @return
  */
 struct rspamd_http_connection_router* rspamd_http_router_new (
                rspamd_http_router_error_handler_t eh,
                rspamd_http_router_finish_handler_t fh,
                struct timeval *timeout,
-               struct event_base *base);
+               struct event_base *base,
+               const char *default_fs_path);
 
 /**
  * Add new path to the router
index 5ca36d831ef871fbc7b76846b554a875c1ef5a87..38f3dc889752939835591ee1d29495c00117f41e 160000 (submodule)
--- a/src/rdns
+++ b/src/rdns
@@ -1 +1 @@
-Subproject commit 5ca36d831ef871fbc7b76846b554a875c1ef5a87
+Subproject commit 38f3dc889752939835591ee1d29495c00117f41e
index 99cb95ec06ce35819906090d9049b8991e0ca011..c7441461dc26e740dfd171711469ed80eb270837 100644 (file)
@@ -1812,7 +1812,8 @@ start_webui_worker (struct rspamd_worker *worker)
        }
        /* Accept event */
        ctx->http = rspamd_http_router_new (rspamd_webui_error_handler,
-                       rspamd_webui_finish_handler, &ctx->io_tv, ctx->ev_base);
+                       rspamd_webui_finish_handler, &ctx->io_tv, ctx->ev_base,
+                       NULL);
 
        /* Add callbacks for different methods */
        rspamd_http_router_add_path (ctx->http, PATH_AUTH, rspamd_webui_handle_auth);