move dispatch cbs and data to one place
[project/uhttpd.git] / file.c
diff --git a/file.c b/file.c
index fa37155..ae4517c 100644 (file)
--- a/file.c
+++ b/file.c
@@ -70,7 +70,6 @@ static char * canonpath(const char *path, char *path_resolved)
        char path_copy[PATH_MAX];
        char *path_cpy = path_copy;
        char *path_res = path_resolved;
-       struct stat s;
 
        /* relative -> absolute */
        if (*path != '/') {
@@ -122,17 +121,14 @@ next:
 
        *path_res = '\0';
 
-       /* test access */
-       if (!stat(path_resolved, &s) && (s.st_mode & S_IROTH))
-               return path_resolved;
-
-       return NULL;
+       return path_resolved;
 }
 
 /* Returns NULL on error.
 ** NB: improperly encoded URL should give client 400 [Bad Syntax]; returning
 ** NULL here causes 404 [Not Found], but that's not too unreasonable. */
-struct path_info * uh_path_lookup(struct client *cl, const char *url)
+static struct path_info *
+uh_path_lookup(struct client *cl, const char *url)
 {
        static char path_phys[PATH_MAX];
        static char path_info[PATH_MAX];
@@ -319,10 +315,10 @@ static char * uh_file_unix2date(time_t ts)
 
 static char *uh_file_header(struct client *cl, int idx)
 {
-       if (!cl->data.file.hdr[idx])
+       if (!cl->dispatch.file.hdr[idx])
                return NULL;
 
-       return (char *) blobmsg_data(cl->data.file.hdr[idx]);
+       return (char *) blobmsg_data(cl->dispatch.file.hdr[idx]);
 }
 
 static void uh_file_response_ok_hdrs(struct client *cl, struct stat *s)
@@ -533,7 +529,7 @@ static void uh_file_dirlist(struct client *cl, struct path_info *pi)
 static void file_write_cb(struct client *cl)
 {
        char buf[512];
-       int fd = cl->data.file.fd;
+       int fd = cl->dispatch.file.fd;
        int r;
 
        while (cl->us->w.data_bytes < 256) {
@@ -554,7 +550,7 @@ static void file_write_cb(struct client *cl)
 
 static void uh_file_free(struct client *cl)
 {
-       close(cl->data.file.fd);
+       close(cl->dispatch.file.fd);
 }
 
 static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
@@ -587,13 +583,14 @@ static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
                return;
        }
 
-       cl->data.file.fd = fd;
-       cl->dispatch_write_cb = file_write_cb;
-       cl->dispatch_free = uh_file_free;
+       cl->dispatch.file.fd = fd;
+       cl->dispatch.write_cb = file_write_cb;
+       cl->dispatch.free = uh_file_free;
+       cl->dispatch.close_fds = uh_file_free;
        file_write_cb(cl);
 }
 
-static void uh_file_request(struct client *cl, struct path_info *pi)
+static void uh_file_request(struct client *cl, struct path_info *pi, const char *url)
 {
        static const struct blobmsg_policy hdr_policy[__HDR_MAX] = {
                [HDR_IF_MODIFIED_SINCE] = { "if-modified-since", BLOBMSG_TYPE_STRING },
@@ -607,15 +604,32 @@ static void uh_file_request(struct client *cl, struct path_info *pi)
 
        blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head));
 
-       cl->data.file.hdr = tb;
-       if ((pi->stat.st_mode & S_IFREG) && ((fd = open(pi->phys, O_RDONLY)) > 0))
+       cl->dispatch.file.hdr = tb;
+
+       if (!(pi->stat.st_mode & S_IROTH))
+               goto error;
+
+       if (pi->stat.st_mode & S_IFREG) {
+               fd = open(pi->phys, O_RDONLY);
+               if (fd < 0)
+                       goto error;
+
                uh_file_data(cl, pi, fd);
-       else if ((pi->stat.st_mode & S_IFDIR) && !conf.no_dirlists)
+       } else if ((pi->stat.st_mode & S_IFDIR)) {
+               if (conf.no_dirlists)
+                       goto error;
+
                uh_file_dirlist(cl, pi);
-       else
-               uh_client_error(cl, 403, "Forbidden",
-                               "Access to this resource is forbidden");
-       cl->data.file.hdr = NULL;
+       } else {
+               goto error;
+       }
+
+       return;
+
+error:
+       uh_client_error(cl, 403, "Forbidden",
+                       "You don't have permission to access %s on this server.",
+                       url);
 }
 
 static bool __handle_file_request(struct client *cl, const char *url)
@@ -626,8 +640,10 @@ static bool __handle_file_request(struct client *cl, const char *url)
        if (!pi)
                return false;
 
-       if (!pi->redirected)
-               uh_file_request(cl, pi);
+       if (!pi->redirected) {
+               uh_file_request(cl, pi, url);
+               cl->dispatch.file.hdr = NULL;
+       }
 
        return true;
 }
@@ -638,5 +654,5 @@ void uh_handle_file_request(struct client *cl)
            __handle_file_request(cl, conf.error_handler))
                return;
 
-       uh_client_error(cl, 404, "Not Found", "No such file or directory");
+       uh_client_error(cl, 404, "Not Found", "The requested URL %s was not found on this server.", cl->request.url);
 }