summaryrefslogtreecommitdiff
path: root/upload.c
diff options
context:
space:
mode:
authorVincent Douillet <vincent@vdouillet.fr>2024-09-09 13:52:35 +0200
committerVincent Douillet <vincent@vdouillet.fr>2024-09-10 12:01:05 +0200
commit4e921ffa31fdca2425d326efda1c6d9ad190359a (patch)
tree8d0fe130bd26dedb5c0754249734608217bbd6b9 /upload.c
parentd7edafe299d44a0bec9d29e2b3a4ca853ffa1a80 (diff)
upload: handle form submission
Diffstat (limited to 'upload.c')
-rw-r--r--upload.c139
1 files changed, 112 insertions, 27 deletions
diff --git a/upload.c b/upload.c
index fef628e..765e694 100644
--- a/upload.c
+++ b/upload.c
@@ -34,6 +34,7 @@
#include <limits.h>
#include <string.h>
+#include "browse.h"
#include "cgi.h"
#include "http.h"
#include "template.h"
@@ -115,56 +116,42 @@ header_template_callback(size_t index, void *arg)
return 1;
}
-struct http_ret
-upload(struct kreq * r)
+/*
+ * GET request, we print upload form
+ */
+void
+upload_get(struct kreq * r, struct http_ret * ret, struct file * file)
{
- struct file *file;
- struct http_ret ret;
struct khtmlreq html;
struct ktemplate template;
struct page_template *tmpl;
struct template_data data;
- /* initialize vars and return structure for success */
- file = NULL;
tmpl = NULL;
- ret = (struct http_ret) {
- KHTTP_200, ""
- };
- /* build file and submit url */
- file = file_new(r->path);
- if (file == NULL) {
- ret = (struct http_ret) {
- KHTTP_404,
- "upload: Unable to build data file"
- };
- goto end;
- }
+ /* action url is form submit url */
if (build_upload_url(r, file) == 0) {
- ret = (struct http_ret) {
+ *ret = (struct http_ret) {
KHTTP_500,
- "upload: Can't build upload url"
+ "upload: Can't build upload url"
};
goto end;
}
-
/* read template */
tmpl = page_template_new(UPLOAD_URL);
if (tmpl == NULL) {
- ret = (struct http_ret) {
+ *ret = (struct http_ret) {
KHTTP_500,
- "upload: Unable to read template"
+ "upload: Unable to read template"
};
goto end;
}
-
+ /* print upload form */
http_open(r, KHTTP_200, r->mime);
K_OK(khttp_puts(r, tmpl->header), r);
K_OK(khtml_open(&html, r, 0), r);
- /* print upload form */
template.key = header_template_keys;
template.keysz = 2;
template.cb = header_template_callback;
@@ -180,9 +167,107 @@ upload(struct kreq * r)
K_OK(khtml_close(&html), r);
- /* free allocated memory */
end:
- file_free(file);
page_template_free(tmpl);
+}
+
+/*
+ * POST request, we handle upload form
+ */
+void
+upload_post(struct kreq * r, struct http_ret * ret, struct file * f)
+{
+ char path[PATH_MAX];
+ FILE *to_write;
+ size_t path_len, i;
+
+ /* prepare action url for return redirection in case of success */
+ if (build_browse_url(r, f) == 0) {
+ *ret = (struct http_ret) {
+ KHTTP_500,
+ "upload: can't build return url"
+ };
+ return;
+ }
+
+ /*
+ * data should have been validated prior to handling the request, so
+ * here we should have an array of fields named "file", each field
+ * corresponding to one uploaded file
+ */
+ for (i = 0; i < r->fieldsz; i++) {
+ struct kpair *upl = &(r->fields[i]);
+ path_len = file_get_data_path(f, path, PATH_MAX, upl->file);
+ if (path_len == 0 || path_len >= PATH_MAX) {
+ *ret = (struct http_ret) {
+ KHTTP_500,
+ "upload: can't build file path"
+ };
+ return;
+ }
+ to_write = fopen(path, "wb");
+ if (to_write == NULL) {
+ *ret = (struct http_ret) {
+ KHTTP_500,
+ "upload: can't open file for writing"
+ };
+ return;
+ }
+ if (fwrite(upl->val, sizeof(char), upl->valsz, to_write)
+ != upl->valsz) {
+ *ret = (struct http_ret) {
+ KHTTP_500,
+ "upload: error while writing file"
+ };
+ return;
+ }
+ if (fclose(to_write) != 0) {
+ *ret = (struct http_ret) {
+ KHTTP_500,
+ "upload: error while closing file"
+ };
+ return;
+ }
+ }
+
+ /* on success, redirect to the directory where new files were created */
+ khttp_head(r, kresps[KRESP_LOCATION], "%s", f->action_url);
+ http_open(r, KHTTP_303, r->mime);
+
+ *ret = (struct http_ret) {
+ KHTTP_303,
+ ""
+ };
+}
+
+
+struct http_ret
+upload(struct kreq * r)
+{
+ struct file *file;
+ struct http_ret ret;
+
+ file = NULL;
+ ret = (struct http_ret) {
+ KHTTP_200, ""
+ };
+
+ /* build file corresponding to request (ie. upload) path */
+ file = file_new(r->path);
+ if (file == NULL) {
+ ret = (struct http_ret) {
+ KHTTP_404,
+ "upload: Unable to build data file"
+ };
+ goto end;
+ }
+ /* print form or handle submission according to HTTP method */
+ if (r->method == KMETHOD_POST)
+ upload_post(r, &ret, file);
+ else
+ upload_get(r, &ret, file);
+
+end:
+ file_free(file);
return ret;
}