|
@@ -47,7 +47,7 @@ static void uh_sigchld(int sig)
|
|
|
while( waitpid(-1, NULL, WNOHANG) > 0 ) { }
|
|
while( waitpid(-1, NULL, WNOHANG) > 0 ) { }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static void uh_config_parse(const char *path)
|
|
|
|
|
|
|
+static void uh_config_parse(struct config *conf)
|
|
|
{
|
|
{
|
|
|
FILE *c;
|
|
FILE *c;
|
|
|
char line[512];
|
|
char line[512];
|
|
@@ -55,7 +55,10 @@ static void uh_config_parse(const char *path)
|
|
|
char *pass = NULL;
|
|
char *pass = NULL;
|
|
|
char *eol = NULL;
|
|
char *eol = NULL;
|
|
|
|
|
|
|
|
- if( (c = fopen(path ? path : "/etc/httpd.conf", "r")) != NULL )
|
|
|
|
|
|
|
+ const char *path = conf->file ? conf->file : "/etc/httpd.conf";
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if( (c = fopen(path, "r")) != NULL )
|
|
|
{
|
|
{
|
|
|
memset(line, 0, sizeof(line));
|
|
memset(line, 0, sizeof(line));
|
|
|
|
|
|
|
@@ -74,9 +77,23 @@ static void uh_config_parse(const char *path)
|
|
|
"Notice: No password set for user %s, ignoring "
|
|
"Notice: No password set for user %s, ignoring "
|
|
|
"authentication on %s\n", user, line
|
|
"authentication on %s\n", user, line
|
|
|
);
|
|
);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if( !strncmp(line, "I:", 2) )
|
|
|
|
|
+ {
|
|
|
|
|
+ if( !(user = strchr(line, ':')) || (*user++ = 0) ||
|
|
|
|
|
+ !(eol = strchr(user, '\n')) || (*eol++ = 0) )
|
|
|
|
|
+ continue;
|
|
|
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ conf->index_file = strdup(user);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if( !strncmp(line, "E404:", 5) )
|
|
|
|
|
+ {
|
|
|
|
|
+ if( !(user = strchr(line, ':')) || (*user++ = 0) ||
|
|
|
|
|
+ !(eol = strchr(user, '\n')) || (*eol++ = 0) )
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ conf->error_handler = strdup(user);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -302,6 +319,7 @@ static struct http_request * uh_http_header_parse(struct client *cl, char *buffe
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* valid enough */
|
|
/* valid enough */
|
|
|
|
|
+ req.redirect_status = 200;
|
|
|
return &req;
|
|
return &req;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -505,8 +523,9 @@ int main (int argc, char **argv)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
- while( (opt = getopt(argc, argv, "fSC:K:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 )
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ while( (opt = getopt(argc, argv,
|
|
|
|
|
+ "fSDC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0
|
|
|
|
|
+ ) {
|
|
|
switch(opt)
|
|
switch(opt)
|
|
|
{
|
|
{
|
|
|
/* [addr:]port */
|
|
/* [addr:]port */
|
|
@@ -597,11 +616,38 @@ int main (int argc, char **argv)
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
|
|
+ /* error handler */
|
|
|
|
|
+ case 'E':
|
|
|
|
|
+ if( (strlen(optarg) == 0) || (optarg[0] != '/') )
|
|
|
|
|
+ {
|
|
|
|
|
+ fprintf(stderr, "Error: Invalid error handler: %s\n",
|
|
|
|
|
+ optarg);
|
|
|
|
|
+ exit(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ conf.error_handler = optarg;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ /* index file */
|
|
|
|
|
+ case 'I':
|
|
|
|
|
+ if( (strlen(optarg) == 0) || (optarg[0] == '/') )
|
|
|
|
|
+ {
|
|
|
|
|
+ fprintf(stderr, "Error: Invalid index page: %s\n",
|
|
|
|
|
+ optarg);
|
|
|
|
|
+ exit(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ conf.index_file = optarg;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
/* don't follow symlinks */
|
|
/* don't follow symlinks */
|
|
|
case 'S':
|
|
case 'S':
|
|
|
conf.no_symlinks = 1;
|
|
conf.no_symlinks = 1;
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
|
|
+ /* don't list directories */
|
|
|
|
|
+ case 'D':
|
|
|
|
|
+ conf.no_dirlists = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
#ifdef HAVE_CGI
|
|
#ifdef HAVE_CGI
|
|
|
/* cgi prefix */
|
|
/* cgi prefix */
|
|
|
case 'x':
|
|
case 'x':
|
|
@@ -678,7 +724,10 @@ int main (int argc, char **argv)
|
|
|
" -K file ASN.1 server private key file\n"
|
|
" -K file ASN.1 server private key file\n"
|
|
|
#endif
|
|
#endif
|
|
|
" -h directory Specify the document root, default is '.'\n"
|
|
" -h directory Specify the document root, default is '.'\n"
|
|
|
|
|
+ " -E string Use given virtual URL as 404 error handler\n"
|
|
|
|
|
+ " -I string Use given filename as index page for directories\n"
|
|
|
" -S Do not follow symbolic links outside of the docroot\n"
|
|
" -S Do not follow symbolic links outside of the docroot\n"
|
|
|
|
|
+ " -D Do not allow directory listings, send 403 instead\n"
|
|
|
#ifdef HAVE_LUA
|
|
#ifdef HAVE_LUA
|
|
|
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
|
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
|
|
" -L file Lua handler script, omit to disable Lua\n"
|
|
" -L file Lua handler script, omit to disable Lua\n"
|
|
@@ -727,7 +776,7 @@ int main (int argc, char **argv)
|
|
|
conf.realm = "Protected Area";
|
|
conf.realm = "Protected Area";
|
|
|
|
|
|
|
|
/* config file */
|
|
/* config file */
|
|
|
- uh_config_parse(conf.file);
|
|
|
|
|
|
|
+ uh_config_parse(&conf);
|
|
|
|
|
|
|
|
/* default network timeout */
|
|
/* default network timeout */
|
|
|
if( conf.network_timeout <= 0 )
|
|
if( conf.network_timeout <= 0 )
|
|
@@ -913,8 +962,29 @@ int main (int argc, char **argv)
|
|
|
/* 404 */
|
|
/* 404 */
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- uh_http_sendhf(cl, 404, "Not Found",
|
|
|
|
|
- "No such file or directory");
|
|
|
|
|
|
|
+ /* Try to invoke an error handler */
|
|
|
|
|
+ pin = uh_path_lookup(cl, conf.error_handler);
|
|
|
|
|
+
|
|
|
|
|
+ if( pin && uh_auth_check(cl, req, pin) )
|
|
|
|
|
+ {
|
|
|
|
|
+ req->redirect_status = 404;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef HAVE_CGI
|
|
|
|
|
+ if( uh_path_match(conf.cgi_prefix, pin->name) )
|
|
|
|
|
+ {
|
|
|
|
|
+ uh_cgi_request(cl, req, pin);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+#endif
|
|
|
|
|
+ {
|
|
|
|
|
+ uh_file_request(cl, req, pin);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ uh_http_sendhf(cl, 404, "Not Found",
|
|
|
|
|
+ "No such file or directory");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|