From 7083c65314d0cb81d0f391fc8f579727568b3439 Mon Sep 17 00:00:00 2001 From: chme Date: Sun, 3 Dec 2017 09:21:17 +0100 Subject: [PATCH] [main/httpd] Configurable web root directory over cli parameter --- src/httpd.c | 26 +++++++++++++++++++++----- src/httpd.h | 2 +- src/main.c | 53 +++++++++++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/httpd.c b/src/httpd.c index 4560c9dd..e2602298 100644 --- a/src/httpd.c +++ b/src/httpd.c @@ -72,8 +72,6 @@ #endif -#define WEB_ROOT DATADIR "/htdocs" - #define STREAM_CHUNK_SIZE (64 * 1024) #define ERR_PAGE "\n\n" \ "%d %s\n" \ @@ -117,6 +115,7 @@ static const struct content_type_map ext2ctype[] = static const char *http_reply_401 = "401 UnauthorizedAuthorization required"; +static const char *webroot_directory; struct event_base *evbase_httpd; #ifdef HAVE_EVENTFD @@ -142,7 +141,7 @@ struct stream_ctx *g_st; static int path_is_legal(const char *path) { - return strncmp(WEB_ROOT, path, strlen(WEB_ROOT)); + return strncmp(webroot_directory, path, strlen(webroot_directory)); } /* Callback from the worker thread (async operation as it may block) */ @@ -279,7 +278,7 @@ serve_file(struct evhttp_request *req, const char *uri) if (!httpd_admin_check_auth(req)) return; - ret = snprintf(path, sizeof(path), "%s%s", WEB_ROOT, uri); + ret = snprintf(path, sizeof(path), "%s%s", webroot_directory, uri); if ((ret < 0) || (ret >= sizeof(path))) { DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri); @@ -1555,13 +1554,30 @@ httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passw /* Thread: main */ int -httpd_init(void) +httpd_init(const char *webroot) { + struct stat sb; int v6enabled; int ret; httpd_exit = 0; + DPRINTF(E_DBG, L_HTTPD, "Starting web server with root directory '%s'\n", webroot); + ret = lstat(webroot, &sb); + if (ret < 0) + { + DPRINTF(E_LOG, L_HTTPD, "Could not lstat() web root directory '%s': %s\n", webroot, strerror(errno)); + + return -1; + } + if (!S_ISDIR(sb.st_mode)) + { + DPRINTF(E_LOG, L_HTTPD, "Web root directory '%s' is not a directory\n", webroot); + + return -1; + } + webroot_directory = webroot; + evbase_httpd = event_base_new(); if (!evbase_httpd) { diff --git a/src/httpd.h b/src/httpd.h index f6daa019..74ddef15 100644 --- a/src/httpd.h +++ b/src/httpd.h @@ -157,7 +157,7 @@ int httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm); int -httpd_init(void); +httpd_init(const char *webroot); void httpd_deinit(void); diff --git a/src/main.c b/src/main.c index c0db5163..2090cd96 100644 --- a/src/main.c +++ b/src/main.c @@ -79,6 +79,7 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL; #endif #define PIDFILE STATEDIR "/run/" PACKAGE ".pid" +#define WEB_ROOT DATADIR "/htdocs" struct event_base *evbase_main; @@ -108,6 +109,7 @@ usage(char *program) printf(" -f Run in foreground\n"); printf(" -b ffid to be broadcast\n"); printf(" -v Display version information\n"); + printf(" -w Use as the web root directory for serving static files\n"); printf("\n\n"); printf("Available log domains:\n"); logger_domains(); @@ -469,6 +471,7 @@ main(int argc, char **argv) char *logfile; char *ffid; char *pidfile; + char *webroot; char **buildopts; const char *av_version; const char *gcry_version; @@ -489,6 +492,7 @@ main(int argc, char **argv) { "config", 1, NULL, 'c' }, { "pidfile", 1, NULL, 'P' }, { "version", 0, NULL, 'v' }, + { "webroot", 1, NULL, 'w' }, { "mdns-no-rsp", 0, NULL, 512 }, { "mdns-no-daap", 0, NULL, 513 }, @@ -498,6 +502,7 @@ main(int argc, char **argv) configfile = CONFFILE; pidfile = PIDFILE; + webroot = WEB_ROOT; loglevel = -1; logdomains = NULL; logfile = NULL; @@ -506,7 +511,7 @@ main(int argc, char **argv) mdns_no_rsp = 0; mdns_no_daap = 0; - while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1) + while ((option = getopt_long(argc, argv, "D:d:c:P:fb:vw:", option_map, NULL)) != -1) { switch (option) { @@ -519,8 +524,8 @@ main(int argc, char **argv) break; case 'b': - ffid = optarg; - break; + ffid = optarg; + break; case 'd': ret = safe_atoi32(optarg, &option); @@ -528,34 +533,38 @@ main(int argc, char **argv) fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg); else loglevel = option; - break; + break; case 'D': logdomains = optarg; - break; + break; - case 'f': - background = 0; - break; + case 'f': + background = 0; + break; - case 'c': - configfile = optarg; - break; + case 'c': + configfile = optarg; + break; - case 'P': + case 'P': pidfile = optarg; - break; + break; - case 'v': + case 'v': version(); - return EXIT_SUCCESS; - break; + return EXIT_SUCCESS; + break; - default: - usage(argv[0]); - return EXIT_FAILURE; - break; - } + case 'w': + webroot = optarg; + break; + + default: + usage(argv[0]); + return EXIT_FAILURE; + break; + } } ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel); @@ -763,7 +772,7 @@ main(int argc, char **argv) } /* Spawn HTTPd thread */ - ret = httpd_init(); + ret = httpd_init(webroot); if (ret != 0) { DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n");