* limitations under the License.
*/
+#define _BSD_SOURCE
+#define _XOPEN_SOURCE 700
+
#include <sys/types.h>
#include <sys/dir.h>
+#include <time.h>
+#include <strings.h>
#include <libubox/blobmsg.h>
char path_copy[PATH_MAX];
char *path_cpy = path_copy;
char *path_res = path_resolved;
- struct stat s;
/* relative -> absolute */
if (*path != '/') {
*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];
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)
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) {
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)
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 },
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);
}
-void uh_handle_file_request(struct client *cl)
+static bool __handle_file_request(struct client *cl, const char *url)
{
struct path_info *pi;
- pi = uh_path_lookup(cl, cl->request.url);
- if (!pi) {
- uh_request_done(cl);
- return;
+ pi = uh_path_lookup(cl, url);
+ if (!pi)
+ return false;
+
+ if (!pi->redirected) {
+ uh_file_request(cl, pi, url);
+ cl->dispatch.file.hdr = NULL;
}
- if (pi->redirected)
+ return true;
+}
+
+void uh_handle_file_request(struct client *cl)
+{
+ if (__handle_file_request(cl, cl->request.url) ||
+ __handle_file_request(cl, conf.error_handler))
return;
- uh_file_request(cl, pi);
+ uh_client_error(cl, 404, "Not Found", "The requested URL %s was not found on this server.", cl->request.url);
}