summaryrefslogtreecommitdiff
path: root/browse.c
diff options
context:
space:
mode:
authorVincent Douillet <vincent@vdouillet.fr>2024-09-05 12:58:22 +0200
committerVincent Douillet <vincent@vdouillet.fr>2024-09-06 12:22:20 +0200
commit35a145fd161fb4d4f19aa9820b50438695b94414 (patch)
tree00e9f341d5b7e0a6874efbe9fafc0500cf13cd2d /browse.c
parent9b8d38ab209c6e7e747d6d420f1b105fe858c7eb (diff)
browse: add upload button
Diffstat (limited to 'browse.c')
-rw-r--r--browse.c156
1 files changed, 112 insertions, 44 deletions
diff --git a/browse.c b/browse.c
index 868388f..ce76290 100644
--- a/browse.c
+++ b/browse.c
@@ -44,7 +44,9 @@
#include "download.h"
#include "file.h"
#include "http.h"
+#include "str.h"
#include "template.h"
+#include "upload.h"
#include "url.h"
/*
@@ -53,7 +55,7 @@
SLIST_HEAD(, file) list;
/*
- * browse url = r->pname / BROWSE_URL / file->path / file->name
+ * browse url = r->pname / BROWSE_URL / file->path
*/
static size_t
build_browse_url(struct kreq * r, struct file * file)
@@ -65,7 +67,7 @@ build_browse_url(struct kreq * r, struct file * file)
return 0;
action_url_len = url_build(action_url, PATH_MAX, r->pname, BROWSE_URL,
- file->path, file->name, NULL);
+ file->path, NULL);
if (action_url_len == 0 || action_url_len >= PATH_MAX) {
kutil_warn(r, NULL,
"browse: action URL overflow: %s", action_url);
@@ -82,16 +84,25 @@ build_browse_url(struct kreq * r, struct file * file)
}
static int
-build_file_list(struct kreq * r, const char *request_dir)
+build_file_list(struct kreq * r, const struct file * request_dir)
{
bool action_url_ok;
- char *file_name;
+ char file_path[PATH_MAX], request_dir_path[PATH_MAX];
DIR *data_dir;
+ size_t file_path_len, request_dir_len;
struct dirent *dir;
struct file *file;
struct file *last_file;
- data_dir = opendir(request_dir);
+ request_dir_len = file_get_data_path(request_dir, request_dir_path,
+ PATH_MAX);
+ if (request_dir_len == 0) {
+ kutil_warn(r, NULL,
+ "browse: Unable to build request dir path: %s",
+ request_dir_path);
+ return -1;
+ }
+ data_dir = opendir(request_dir_path);
if (NULL == data_dir)
return -1;
@@ -99,16 +110,24 @@ build_file_list(struct kreq * r, const char *request_dir)
last_file = NULL;
while ((dir = readdir(data_dir)) != NULL) {
/* ignore special . and .. folders */
- file_name = dir->d_name;
- if (strcmp(".", file_name) == 0 || strcmp("..", file_name) == 0)
+ if (strcmp(".", dir->d_name) == 0
+ || strcmp("..", dir->d_name) == 0)
+ continue;
+ /* build file path */
+ file_path_len = url_build(file_path, PATH_MAX, r->path,
+ dir->d_name, NULL);
+ if (file_path_len == 0 || file_path_len >= PATH_MAX) {
+ kutil_warn(r, NULL,
+ "browse: unable to build file, skipping %s",
+ dir->d_name);
continue;
+ }
/* build file */
- file = file_new(r->path, strlen(r->path), dir->d_name,
- dir->d_namlen);
+ file = file_new(file_path);
if (file == NULL) {
kutil_warn(r, NULL,
"browse: unable to allocate file, skipping %s",
- file_name);
+ dir->d_name);
continue;
}
/* build action url */
@@ -119,7 +138,7 @@ build_file_list(struct kreq * r, const char *request_dir)
if (!action_url_ok) {
kutil_warn(r, NULL,
"browse: unable to build action url, skipping %s",
- file_name);
+ dir->d_name);
file_free(file);
continue;
}
@@ -136,10 +155,8 @@ build_file_list(struct kreq * r, const char *request_dir)
return 0;
}
-static const char *const template_keys[] = {"icon", "name", "url", "size"};
-
/*
- * data required in the template function
+ * data required in the template functions
*/
struct template_data {
struct kreq *r;
@@ -147,9 +164,45 @@ struct template_data {
struct file *f;
};
+static const char *const header_template_keys[] = {"upload_url"};
+
+static int
+header_template_callback(size_t index, void *arg)
+{
+ struct kreq *r;
+ struct khtmlreq *html;
+ struct template_data *data;
+
+ if (arg == NULL) {
+ kutil_warn(NULL, NULL,
+ "Invalid data for browse header template");
+ return 0;
+ }
+ data = arg;
+ r = data->r;
+ html = data->html;
+
+ switch (index) {
+ case 0:
+ /* upload_url */
+ K_OK(khtml_puts(html, data->f->action_url), r);
+ break;
+ default:
+ kutil_warnx(r, NULL,
+ "Invalid key index for browse header template: %zd",
+ index);
+ return 0;
+ }
+
+ return 1;
+}
+
+static const char *const file_template_keys[] = {"icon", "name", "url", "size"};
+
static int
-template_callback(size_t index, void *arg)
+file_template_callback(size_t index, void *arg)
{
+ char *basename;
struct kreq *r;
struct khtmlreq *html;
struct template_data *data;
@@ -158,7 +211,7 @@ template_callback(size_t index, void *arg)
char size_read[] = {'k', 'M', 'G'};
if (arg == NULL) {
- kutil_warn(NULL, NULL, "Invalid data for browse template");
+ kutil_warn(NULL, NULL, "Invalid data for browse file template");
return 0;
}
data = arg;
@@ -172,7 +225,14 @@ template_callback(size_t index, void *arg)
break;
case 1:
/* name */
- K_OK(khtml_puts(html, data->f->name), r);
+ basename = file_get_basename(data->f);
+ if (basename == NULL) {
+ kutil_warnx(r, NULL,
+ "browse: unable to get file name: %s",
+ data->f->path);
+ break;
+ }
+ K_OK(khtml_puts(html, basename), r);
break;
case 2:
/* url */
@@ -195,7 +255,7 @@ template_callback(size_t index, void *arg)
break;
default:
kutil_warnx(r, NULL,
- "Invalid key index for browse template: %zd",
+ "Invalid key index for browse file template: %zd",
index);
return 0;
}
@@ -206,9 +266,6 @@ template_callback(size_t index, void *arg)
struct http_ret
browse(struct kreq * r)
{
- size_t url_len;
- char current_dir[PATH_MAX];
- char *data_dir;
struct file *file;
struct page_template *tmpl;
struct http_ret ret;
@@ -217,6 +274,7 @@ browse(struct kreq * r)
struct template_data data;
/* initialize vars */
+ file = NULL;
tmpl = NULL;
/* initialize return structure for success */
@@ -224,16 +282,6 @@ browse(struct kreq * r)
KHTTP_200, ""
};
- /* check that data dir is configured */
- data_dir = config_data_dir();
- if (data_dir == NULL) {
- ret = (struct http_ret) {
- KHTTP_400,
- "browse: data dir is not configured"
- };
- goto end;
- }
-
/* check that the requested URL can be safely processed */
if (!check_request_path(r->path, r->suffix)) {
ret = (struct http_ret) {
@@ -243,28 +291,37 @@ browse(struct kreq * r)
goto end;
}
/* list requested directory content */
- url_len = url_build(current_dir, PATH_MAX, data_dir, r->path,
- NULL);
- if (url_len == 0) {
+ file = file_new(r->path);
+ if (file == NULL) {
+ ret = (struct http_ret) {
+ KHTTP_404,
+ "browse: Unable to build data file"
+ };
+ goto end;
+ }
+ if (!file->is_dir) {
ret = (struct http_ret) {
KHTTP_404,
- "browse: Unable to build data path"
+ "browse: Invalid data file"
};
goto end;
}
- if (url_len >= PATH_MAX) {
+ if (build_upload_url(r, file) == 0) {
ret = (struct http_ret) {
- KHTTP_414, ""
+ KHTTP_500,
+ "browse: Can't build upload url"
};
goto end;
}
- if (build_file_list(r, current_dir) < 0) {
+
+ if (build_file_list(r, file) < 0) {
ret = (struct http_ret) {
KHTTP_500,
"browse: Unable to build file list"
};
goto end;
}
+
/* read template */
tmpl = page_template_new(BROWSE_URL);
if (tmpl == NULL) {
@@ -274,21 +331,29 @@ browse(struct kreq * r)
};
goto end;
}
+
/* we have all the data we need, we can start to write output page */
http_open(r, KHTTP_200, r->mime);
K_OK(khttp_puts(r, tmpl->header), r);
- K_OK(khttp_puts(r, tmpl->page_header), r);
K_OK(khtml_open(&html, r, 0), r);
- /* print file list */
- template.key = template_keys;
- template.keysz = 4;
- template.cb = template_callback;
+ /* print browse header with action buttons for current dir */
+ template.key = header_template_keys;
+ template.keysz = 1;
+ template.cb = header_template_callback;
template.arg = &data;
data.r = r;
data.html = &html;
+ data.f = file;
+ K_OK(khttp_template_buf(r, &template, tmpl->page_header,
+ strlen(tmpl->page_header)), r);
+
+ /* print file list */
+ template.key = file_template_keys;
+ template.keysz = 4;
+ template.cb = file_template_callback;
SLIST_FOREACH(file, &list, files) {
data.f = file;
@@ -304,7 +369,10 @@ browse(struct kreq * r)
/* free page template and file list */
end:
page_template_free(tmpl);
- file = NULL;
+ if (file != NULL) {
+ free(file);
+ file = NULL;
+ }
while (!SLIST_EMPTY(&list)) {
file = SLIST_FIRST(&list);
SLIST_REMOVE_HEAD(&list, files);