* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+
#define _BSD_SOURCE
#define _DARWIN_C_SOURCE
#define _XOPEN_SOURCE 700
{
static char path_phys[PATH_MAX];
static char path_info[PATH_MAX];
+ static char path_query[PATH_MAX];
static struct path_info p;
const char *docroot = conf.docroot;
/* separate query string from url */
if ((pathptr = strchr(url, '?')) != NULL) {
- p.query = pathptr[1] ? pathptr + 1 : NULL;
+ if (pathptr[1]) {
+ p.query = path_query;
+ snprintf(path_query, sizeof(path_query), "%s",
+ pathptr + 1);
+ }
/* urldecode component w/o query */
if (pathptr > url) {
return uh_file_response_ok_hdrs(cl, s);
}
+static void uh_file_response_405(struct client *cl)
+{
+ uh_http_header(cl, 405, "Method Not Allowed");
+}
+
static void uh_file_response_412(struct client *cl)
{
uh_http_header(cl, 412, "Precondition Failed");
const char *type = "directory";
unsigned int mode = S_IXOTH;
struct stat s;
+ char *escaped;
char *file;
char buf[128];
int i;
if (!(s.st_mode & mode))
goto next;
+ escaped = uh_htmlescape(name);
+
+ if (!escaped)
+ goto next;
+
uh_chunk_printf(cl,
"<li><strong><a href='%s%s%s'>%s</a>%s"
"</strong><br /><small>modified: %s"
"<br />%s - %.02f kbyte<br />"
"<br /></small></li>",
- path, name, suffix,
- name, suffix,
+ path, escaped, suffix,
+ escaped, suffix,
uh_file_unix2date(s.st_mtime, buf, sizeof(buf)),
type, s.st_size / 1024.0);
+ free(escaped);
*file = 0;
next:
free(files[i]);
static void uh_file_dirlist(struct client *cl, struct path_info *pi)
{
struct dirent **files = NULL;
+ char *escaped_path = uh_htmlescape(pi->name);
int count = 0;
+ if (!escaped_path)
+ {
+ uh_client_error(cl, 500, "Internal Server Error", "Out of memory");
+ return;
+ }
+
uh_file_response_200(cl, NULL);
ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n");
uh_chunk_printf(cl,
"<html><head><title>Index of %s</title></head>"
"<body><h1>Index of %s</h1><hr /><ol>",
- pi->name, pi->name);
+ escaped_path, escaped_path);
count = scandir(pi->phys, &files, NULL, dirent_cmp);
if (count > 0) {
strcpy(uh_buf, pi->phys);
- list_entries(cl, files, count, pi->name, uh_buf);
+ list_entries(cl, files, count, escaped_path, uh_buf);
}
+ free(escaped_path);
free(files);
uh_chunk_printf(cl, "</ol><hr /></body></html>");
static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
{
/* test preconditions */
- if (!uh_file_if_modified_since(cl, &pi->stat) ||
- !uh_file_if_match(cl, &pi->stat) ||
- !uh_file_if_range(cl, &pi->stat) ||
- !uh_file_if_unmodified_since(cl, &pi->stat) ||
- !uh_file_if_none_match(cl, &pi->stat)) {
+ if (!cl->dispatch.no_cache &&
+ (!uh_file_if_modified_since(cl, &pi->stat) ||
+ !uh_file_if_match(cl, &pi->stat) ||
+ !uh_file_if_range(cl, &pi->stat) ||
+ !uh_file_if_unmodified_since(cl, &pi->stat) ||
+ !uh_file_if_none_match(cl, &pi->stat))) {
ustream_printf(cl->us, "\r\n");
uh_request_done(cl);
close(fd);
{
int fd;
struct http_request *req = &cl->request;
- char *error_handler;
+ char *error_handler, *escaped_url;
+
+ switch (cl->request.method) {
+ case UH_HTTP_MSG_GET:
+ case UH_HTTP_MSG_POST:
+ case UH_HTTP_MSG_HEAD:
+ case UH_HTTP_MSG_OPTIONS:
+ break;
+
+ default:
+ uh_file_response_405(cl);
+ ustream_printf(cl->us, "\r\n");
+ uh_request_done(cl);
+ return;
+ }
if (!(pi->stat.st_mode & S_IROTH))
goto error;
return;
}
+ escaped_url = uh_htmlescape(url);
+
uh_client_error(cl, 403, "Forbidden",
"You don't have permission to access %s on this server.",
- url);
+ escaped_url ? escaped_url : "the url");
+
+ if (escaped_url)
+ free(escaped_url);
}
void uh_dispatch_add(struct dispatch_handler *d)
cl->dispatch.data_blocked = false;
uh_invoke_script(cl, dr->d, dr->path ? &dr->pi : NULL);
client_poll_post_data(cl);
+ ustream_poll(cl->us);
}
}
_field(phys) \
_field(name) \
_field(info) \
- _field(query) \
- _field(auth)
+ _field(query)
static void
uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi)
{
struct deferred_request *dr;
- char *_root, *_phys, *_name, *_info, *_query, *_auth;
+ char *_root, *_phys, *_name, *_info, *_query;
cl->dispatch.req_free = uh_free_pending_request;
struct dispatch_handler *d;
struct blob_attr *tb[__HDR_MAX];
struct path_info *pi;
+ char *user, *pass, *auth;
pi = uh_path_lookup(cl, url);
if (!pi)
return true;
blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head));
- if (tb[HDR_AUTHORIZATION])
- pi->auth = blobmsg_data(tb[HDR_AUTHORIZATION]);
- if (!uh_auth_check(cl, pi))
+ auth = tb[HDR_AUTHORIZATION] ? blobmsg_data(tb[HDR_AUTHORIZATION]) : NULL;
+
+ if (!uh_auth_check(cl, pi->name, auth, &user, &pass))
return true;
+ if (user && pass) {
+ blobmsg_add_string(&cl->hdr, "http-auth-user", user);
+ blobmsg_add_string(&cl->hdr, "http-auth-pass", pass);
+ }
+
d = dispatch_find(url, pi);
if (d)
uh_invoke_handler(cl, d, url, pi);
struct http_request *req = &cl->request;
struct dispatch_handler *d;
char *url = blobmsg_data(blob_data(cl->hdr.head));
- char *error_handler;
+ char *error_handler, *escaped_url;
+ blob_buf_init(&cl->hdr_response, 0);
url = uh_handle_alias(url);
uh_handler_run(cl, &url, false);
if (__handle_file_request(cl, url))
return;
- if (uh_handler_run(cl, &url, true) &&
- (!url || __handle_file_request(cl, url)))
- return;
+ if (uh_handler_run(cl, &url, true)) {
+ if (!url)
+ return;
+
+ uh_handler_run(cl, &url, false);
+ if (__handle_file_request(cl, url))
+ return;
+ }
req->redirect_status = 404;
if (conf.error_handler) {
return;
}
- uh_client_error(cl, 404, "Not Found", "The requested URL %s was not found on this server.", url);
+ escaped_url = uh_htmlescape(url);
+
+ uh_client_error(cl, 404, "Not Found", "The requested URL %s was not found on this server.",
+ escaped_url ? escaped_url : "");
+
+ if (escaped_url)
+ free(escaped_url);
}