summaryrefslogtreecommitdiff
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
parent9b8d38ab209c6e7e747d6d420f1b105fe858c7eb (diff)
browse: add upload button
-rw-r--r--Makefile4
-rw-r--r--browse.c156
-rw-r--r--download.c47
-rw-r--r--download.h2
-rw-r--r--file.c74
-rw-r--r--file.h27
-rw-r--r--http.c13
-rw-r--r--http.h4
-rw-r--r--mime.c8
-rw-r--r--mime.h6
-rw-r--r--str.c2
-rw-r--r--str.h2
-rw-r--r--template.c4
-rw-r--r--template.h3
-rw-r--r--template/browse_head.html1
-rw-r--r--upload.c66
-rw-r--r--upload.h54
-rw-r--r--url.c5
-rw-r--r--url.h2
19 files changed, 349 insertions, 131 deletions
diff --git a/Makefile b/Makefile
index 0c485c0..69c5b9b 100644
--- a/Makefile
+++ b/Makefile
@@ -47,10 +47,10 @@ all: main
.c.o:
$(CC) -o $@ -c $< $(CFLAGS)
-main: str.o config.o mime.o url.o template.o file.o http.o download.o browse.o main.o
+main: str.o config.o mime.o url.o template.o file.o http.o upload.o download.o browse.o main.o
$(CC) -o $@ $> $(LDFLAGS)
-test: str.o config.o mime.o url.o template.o file.o http.o download.o browse.o test.o
+test: str.o config.o mime.o url.o template.o file.o http.o upload.o download.o browse.o test.o
$(CC) -o $@ $> $(LDFLAGS)
env: env.o
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);
diff --git a/download.c b/download.c
index a8f5947..15da06d 100644
--- a/download.c
+++ b/download.c
@@ -47,10 +47,10 @@
#include "util.h"
/*
- * download url = r->pname / DOWNLOAD_URL / file->path / file->name
+ * download url = r->pname / DOWNLOAD_URL / file->path
*/
size_t
-build_download_url(struct kreq * r, struct file * file)
+build_download_url(const struct kreq * r, struct file * file)
{
char action_url[PATH_MAX];
size_t action_url_len;
@@ -60,7 +60,7 @@ build_download_url(struct kreq * r, struct file * file)
return 0;
action_url_len = url_build(action_url, PATH_MAX, r->pname, DOWNLOAD_URL,
- file->path, file->name, NULL);
+ file->path, NULL);
if (action_url_len == 0 || action_url_len >= PATH_MAX) {
kutil_warn(r, NULL,
"download: action URL overflow: %s", action_url);
@@ -79,7 +79,6 @@ build_download_url(struct kreq * r, struct file * file)
struct http_ret
download(struct kreq * r)
{
- char *file_name, *data_dir;
void *buffer;
struct file *f;
int fd;
@@ -93,16 +92,6 @@ download(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,
- "download: data dir not configured"
- };
- goto end;
- }
-
/* check that the requested URL can be safely processed */
if (strlen(r->path) == 0 || !check_request_path(r->path, r->suffix)) {
ret = (struct http_ret) {
@@ -131,36 +120,20 @@ download(struct kreq * r)
goto end;
}
}
-
- path_size = url_build(file_path, PATH_MAX, data_dir, request_path,
- NULL);
- if (path_size == 0) {
+ /* build file metadata */
+ f = file_new(request_path);
+ if (f == NULL) {
ret = (struct http_ret) {
KHTTP_404,
- "download: unable to build file path"
- };
- goto end;
- }
- if (path_size >= PATH_MAX) {
- ret = (struct http_ret) {
- KHTTP_414,
- "download: request too long"
+ "download: file metadata failure"
};
goto end;
}
- /* build file metadata */
- file_name = str_split(request_path, '/');
- if (file_name == NULL)
- f = file_new("/", 1, request_path, strlen(request_path)); /* ROOT file */
- else {
- f = file_new(request_path, strlen(request_path), file_name,
- strlen(file_name));
- free(file_name);/* copied in file_new */
- }
- if (f == NULL) {
+ path_size = file_get_data_path(f, file_path, PATH_MAX);
+ if (path_size == 0 || path_size >= PATH_MAX) {
ret = (struct http_ret) {
KHTTP_404,
- "download: file metadata failure"
+ "download: unable to build file path"
};
goto end;
}
diff --git a/download.h b/download.h
index 94daff4..f602bd7 100644
--- a/download.h
+++ b/download.h
@@ -43,7 +43,7 @@
* Returns the length of the created URL, or 0 in case of failure.
*/
size_t
-build_download_url(struct kreq *, struct file *);
+build_download_url(const struct kreq *, struct file *);
/*
* Return a requested file.
diff --git a/file.c b/file.c
index 1a53b89..239f548 100644
--- a/file.c
+++ b/file.c
@@ -37,6 +37,7 @@
#include "config.h"
#include "file.h"
#include "mime.h"
+#include "str.h"
#include "url.h"
#include "util.h"
@@ -50,10 +51,6 @@ file_free(struct file * file)
free(file->path);
file->path = NULL;
}
- if (file->name != NULL) {
- free(file->name);
- file->name = NULL;
- }
if (file->action_url != NULL) {
free(file->action_url);
file->action_url = NULL;
@@ -61,7 +58,7 @@ file_free(struct file * file)
free(file);
}
-static bool
+static bool
fill_metadata(struct file * f)
{
char *ext, *data_dir;
@@ -77,7 +74,7 @@ fill_metadata(struct file * f)
f->mime = MIME_BIN;
/* check if it is a directory */
- path_len = url_build(path, PATH_MAX, data_dir, f->path, f->name, NULL);
+ path_len = url_build(path, PATH_MAX, data_dir, f->path, NULL);
if (path_len == 0 || path_len >= PATH_MAX)
return false;
@@ -88,8 +85,8 @@ fill_metadata(struct file * f)
f->is_dir = S_ISDIR(sb.st_mode);
/* find mime from file extension */
- ext = strrchr(f->name, '.');
- if (!ext || ext == f->name) {
+ ext = strrchr(f->path, '.');
+ if (!ext || ext == f->path) {
return true;
}
ext++;
@@ -99,27 +96,68 @@ fill_metadata(struct file * f)
}
struct file *
-file_new(char *dir, size_t dir_len, char *name, size_t name_len)
+file_new(const char *path)
{
struct file *file;
+ if (path == NULL)
+ return NULL;
+
file = (struct file *) calloc(1, sizeof(struct file));
if (file == NULL)
return NULL;
- file->path = strndup(dir, dir_len);
- if (file->path == NULL) {
- file_free(file);
- return NULL;
- }
- file->name = strndup(name, name_len);
- if (file->name == NULL) {
- file_free(file);
- return NULL;
+ /* empty path is considered as root */
+ if (strlen(path) == 0) {
+ file->path = malloc(sizeof(char) * 2);
+ if (file->path == NULL) {
+ file_free(file);
+ return NULL;
+ }
+ strlcpy(file->path, "/", 2);
+ } else {
+ file->path = strdup(path);
+ if (file->path == NULL) {
+ file_free(file);
+ return NULL;
+ }
}
+
if (!fill_metadata(file)) {
file_free(file);
return NULL;
}
return file;
}
+
+char *
+file_get_basename(const struct file * f)
+{
+ if (f == NULL || f->path == NULL)
+ return NULL;
+
+ /* is the path a basename itself? */
+ if (strrchr(f->path, '/') == NULL)
+ return f->path;
+
+ /* split for the basename */
+ return str_split(f->path, '/');
+}
+
+size_t
+file_get_data_path(const struct file * f, char *data_path, size_t data_path_len)
+{
+ char *data_dir;
+ size_t path_len;
+
+ data_dir = config_data_dir();
+ if (data_dir == NULL)
+ return 0;
+
+ /* check if it is a directory */
+ path_len = url_build(data_path, data_path_len, data_dir, f->path, NULL);
+ if (path_len == 0 || path_len >= PATH_MAX)
+ return 0;
+
+ return path_len;
+}
diff --git a/file.h b/file.h
index f6dd5f7..38ca06e 100644
--- a/file.h
+++ b/file.h
@@ -42,12 +42,11 @@
*/
struct file {
SLIST_ENTRY(file) files;
- size_t size;
- enum mime mime;
- char *path; /* relative to DATA_DIR */
- char *name;
- char *action_url; /* action URL for HTML page */
- bool is_dir;
+ size_t size;
+ enum mime mime;
+ char *path; /* relative to DATA_DIR */
+ char *action_url; /* action URL for HTML page */
+ bool is_dir;
};
/*
@@ -58,9 +57,21 @@ void
file_free(struct file *);
/*
- * Build a new file
+ * Build a new file from its relative paÃth to the data dir.
*/
struct file *
-file_new(char *, size_t, char *, size_t);
+file_new(const char *);
+
+/*
+ * Get the file basename.
+ */
+char *
+file_get_basename(const struct file *);
+
+/*
+ * Build the data path (on the filesystem) for a file.
+ */
+size_t
+file_get_data_path(const struct file *, char *, size_t);
#endif /* FILE_H */
diff --git a/http.c b/http.c
index ef8d90c..5bad1d8 100644
--- a/http.c
+++ b/http.c
@@ -37,12 +37,19 @@
#include "str.h"
bool
-http_open_file(struct kreq * r, enum khttp code, struct file * f)
+http_open_file(struct kreq * r, enum khttp code, const struct file * f)
{
char *filename;
+ if (f == NULL || f->path == NULL)
+ return false;
+
+ filename = file_get_basename(f);
+ if (filename == NULL)
+ return false;
+
/* file name needs to be url encoded for special chars */
- filename = khttp_urlencode(f->name);
+ filename = khttp_urlencode(filename);
if (filename == NULL)
return false;
@@ -69,7 +76,7 @@ http_open(struct kreq * r, enum khttp code, enum kmime mime)
}
void
-http_exit(struct kreq * r, enum khttp code, char *content,...)
+http_exit(const struct kreq * r, enum khttp code, const char *content,...)
{
va_list args;
diff --git a/http.h b/http.h
index 6ca25e9..71a5d61 100644
--- a/http.h
+++ b/http.h
@@ -48,7 +48,7 @@ struct http_ret {
* All parameters are required.
*/
bool
-http_open_file(struct kreq *, enum khttp, struct file *);
+http_open_file(struct kreq *, enum khttp, const struct file *);
/*
* Initialize headers and start the document body with the provided http code.
@@ -67,6 +67,6 @@ http_open(struct kreq *, enum khttp, enum kmime);
* This function exits with EXIT_FAILURE. It never returns.
*/
void
-http_exit(struct kreq *, enum khttp, char *,...);
+http_exit(const struct kreq *, enum khttp, const char *,...);
#endif /* HTTP_H */
diff --git a/mime.c b/mime.c
index 7136a99..57a0d2c 100644
--- a/mime.c
+++ b/mime.c
@@ -34,7 +34,7 @@
#include "mime.h"
struct mime_map {
- char* str;
+ char *str;
enum mime mime;
};
@@ -119,11 +119,11 @@ char* mime_desc_list[MIME__MAX] = {
};
enum mime
-mime_from_ext(char * ext)
+mime_from_ext(const char *ext)
{
struct mime_map *mime;
- for(mime = mime_ext_list; mime->str != NULL; mime++) {
+ for (mime = mime_ext_list; mime->str != NULL; mime++) {
if (strcasecmp(ext, mime->str) == 0) {
return mime->mime;
}
@@ -132,7 +132,7 @@ mime_from_ext(char * ext)
}
-char *
+const char *
mime_str(enum mime mime)
{
return mime_desc_list[mime];
diff --git a/mime.h b/mime.h
index 40ad66a..5a88917 100644
--- a/mime.h
+++ b/mime.h
@@ -74,12 +74,12 @@ enum mime {
* Find mime from file extension
*/
enum mime
-mime_from_ext(char *);
+mime_from_ext(const char *);
/*
* Return the mime type description
*/
-char *
+const char *
mime_str(enum mime);
-#endif /* MIME_H */
+#endif /* MIME_H */
diff --git a/str.c b/str.c
index 88a83b4..6521fa6 100644
--- a/str.c
+++ b/str.c
@@ -32,7 +32,7 @@
#include <string.h>
char *
-str_split(char *str, char c)
+str_split(const char *str, char c)
{
char *right, *result;
size_t right_len;
diff --git a/str.h b/str.h
index 4d02cfc..76fd186 100644
--- a/str.h
+++ b/str.h
@@ -32,7 +32,7 @@
* Returns a newly allocated string that contains the beginning of the
* provided string up to the provided char.
*/
-char *str_split(char *, char);
+char *str_split(const char *, char);
/*
* Replaces a char in-place in the provided string.
diff --git a/template.c b/template.c
index f6a55b2..4ac3e9f 100644
--- a/template.c
+++ b/template.c
@@ -43,7 +43,7 @@
* to be used in case of success).
*/
static int
-read_file(char *path, char **output, size_t * read_size)
+read_file(const char *path, char **output, size_t * read_size)
{
long file_size;
FILE *fp;
@@ -82,7 +82,7 @@ read_file(char *path, char **output, size_t * read_size)
}
struct page_template *
-page_template_new(char *page)
+page_template_new(const char *page)
{
struct page_template *tmpl;
char template_path[PATH_MAX];
diff --git a/template.h b/template.h
index 560465f..966ab36 100644
--- a/template.h
+++ b/template.h
@@ -45,7 +45,8 @@ struct page_template {
/*
* Build a new set of templates for a specific page.
*/
-struct page_template *page_template_new(char *);
+struct page_template *
+page_template_new(const char *);
/*
* Free a set of templates. Should be able to free a partially allocated set of
diff --git a/template/browse_head.html b/template/browse_head.html
index 48ffee4..7ed3c58 100644
--- a/template/browse_head.html
+++ b/template/browse_head.html
@@ -1,4 +1,5 @@
<h1><i class="fa-regular fa-folder-open"></i> Vault</h1>
+<a href="@@upload_url@@">Upload here</a>
<table id="file-list">
<thead>
<tr>
diff --git a/upload.c b/upload.c
new file mode 100644
index 0000000..03e4169
--- /dev/null
+++ b/upload.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023, Vincent Douillet <vincent@vdouillet.fr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <kcgi.h>
+#include <limits.h>
+#include <string.h>
+
+#include "upload.h"
+#include "url.h"
+
+/*
+ * upload url = r->pname / UPLOAD_URL / file->path
+ */
+size_t
+build_upload_url(const struct kreq * r, struct file * file)
+{
+ char action_url[PATH_MAX];
+ size_t action_url_len;
+
+ if (!file->is_dir)
+ return 0;
+
+ action_url_len = url_build(action_url, PATH_MAX, r->pname, UPLOAD_URL,
+ file->path, NULL);
+ if (action_url_len == 0 || action_url_len >= PATH_MAX) {
+ kutil_warn(r, NULL,
+ "upload: action URL overflow: %s", action_url);
+ return 0;
+ }
+ file->action_url = strndup(action_url, action_url_len);
+ if (file->action_url == NULL) {
+ kutil_warn(r, NULL,
+ "upload: unable to allocate file url buffer: %s",
+ action_url);
+ return 0;
+ }
+ return action_url_len;
+}
diff --git a/upload.h b/upload.h
new file mode 100644
index 0000000..69dcb4c
--- /dev/null
+++ b/upload.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2023, Vincent Douillet <vincent@vdouillet.fr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UPLOAD_H
+#define UPLOAD_H
+
+#include <kcgi.h>
+
+#include "file.h"
+
+#define UPLOAD_URL "upload"
+
+/*
+ * Build the URL to download a file and assigns it to the file's action_url.
+ * All parameters are required
+ * Returns the length of the created URL, or 0 in case of failure.
+ */
+size_t
+build_upload_url(const struct kreq *, struct file *);
+
+/*
+ * Print an upload form (http GET) or handle an upload form submission (http
+ * POST).
+ */
+struct http_ret upload(struct kreq *);
+
+#endif /* UPLOAD_H */
diff --git a/url.c b/url.c
index 3e82821..adcc95d 100644
--- a/url.c
+++ b/url.c
@@ -38,9 +38,9 @@
#include "url.h"
bool
-check_request_path(char *path, char *suffix)
+check_request_path(const char *path, const char *suffix)
{
- char p[PATH_MAX], resolved[PATH_MAX];
+ char p [PATH_MAX], resolved[PATH_MAX];
char *rp, *data_dir;
data_dir = config_data_dir();
@@ -61,7 +61,6 @@ check_request_path(char *path, char *suffix)
if (strlcat(p, suffix, sizeof(p)) >= sizeof(p))
return false;
}
-
/* canonicalize the path */
rp = realpath(p, resolved);
if (rp == NULL)
diff --git a/url.h b/url.h
index cd52a3e..e91925b 100644
--- a/url.h
+++ b/url.h
@@ -41,7 +41,7 @@
* The suffix is required but can be an empty string
*/
bool
-check_request_path(char *, char *);
+check_request_path(const char *, const char *);
/*
* Build an URL from the provided components.