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");