diff options
Diffstat (limited to 'upload.c')
-rw-r--r-- | upload.c | 139 |
1 files changed, 112 insertions, 27 deletions
@@ -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; } |