diff options
author | Vincent Douillet <vincent@vdouillet.fr> | 2024-12-26 18:13:42 +0100 |
---|---|---|
committer | Vincent Douillet <vincent@vdouillet.fr> | 2024-12-27 15:21:14 +0100 |
commit | fddc6610d724dc08433ea99a98406d76c47e9df1 (patch) | |
tree | 6e96ffbedbd2d7ab119345a9cc367b6869236819 | |
parent | 1bcf812973335b424655b272eb831d4eb8f059fc (diff) |
-rw-r--r-- | browse.c | 38 | ||||
-rw-r--r-- | browse.h | 5 | ||||
-rw-r--r-- | delete.c | 77 | ||||
-rw-r--r-- | delete.h | 2 | ||||
-rw-r--r-- | download.c | 46 | ||||
-rw-r--r-- | download.h | 2 | ||||
-rw-r--r-- | http.h | 8 | ||||
-rw-r--r-- | main.c | 12 | ||||
-rw-r--r-- | mime.c | 1 | ||||
-rw-r--r-- | test.c | 224 | ||||
-rw-r--r-- | upload.c | 66 | ||||
-rw-r--r-- | upload.h | 2 |
12 files changed, 218 insertions, 265 deletions
@@ -275,12 +275,11 @@ file_template_callback(size_t index, void *arg) return 1; } -struct http_ret +void browse(struct kreq * r) { struct file *file; struct page_template *tmpl; - struct http_ret ret; struct khtmlreq html; struct ktemplate template; struct template_data data; @@ -289,53 +288,30 @@ browse(struct kreq * r) file = NULL; tmpl = NULL; - /* initialize return structure for success */ - ret = (struct http_ret) { - KHTTP_200, "" - }; - /* list requested directory content */ file = file_new(r->path); if (file == NULL) { - ret = (struct http_ret) { - KHTTP_404, - "browse: Unable to build data file" - }; + http_exit(r, KHTTP_404, "browse: Unable to build data file"); goto end; } if (!file->is_dir) { - ret = (struct http_ret) { - KHTTP_404, - "browse: Invalid data file" - }; + http_exit(r, KHTTP_404, "browse: Invalid data file"); goto end; } if (build_upload_url(r, file) == 0) { - ret = (struct http_ret) { - KHTTP_500, - "browse: Can't build upload url" - }; + http_exit(r, KHTTP_500, "browse: Can't build upload url"); goto end; } - if (build_file_list(r, file) < 0) { - ret = (struct http_ret) { - KHTTP_500, - "browse: Unable to build file list" - }; + http_exit(r, KHTTP_500, "browse: Unable to build file list"); goto end; } - /* read template */ tmpl = page_template_new(BROWSE_URL); if (tmpl == NULL) { - ret = (struct http_ret) { - KHTTP_500, - "browse: Unable to read template" - }; + http_exit(r, KHTTP_500, "browse: Unable to read template"); goto end; } - /* we have all the data we need, we can start to write output page */ http_open(r, KHTTP_200, KMIME_TEXT_HTML); @@ -383,6 +359,4 @@ end: file_free(file); file = NULL; } - - return ret; } @@ -43,13 +43,12 @@ * All parameters are required. * Returns the length of the created URL, or 0 in case of failure. */ -size_t -build_browse_url(struct kreq *, struct file *); +size_t build_browse_url(struct kreq *, struct file *); /* * Print a browse page that allows to browse through the folder hierarchy. * The KCGI request is required. */ -struct http_ret browse(struct kreq *); +void browse(struct kreq *); #endif /* BROWSE_H */ @@ -122,7 +122,7 @@ header_template_callback(size_t index, void *arg) * GET request, we print delete form */ void -delete_get(struct kreq * r, struct http_ret * ret, struct file * file) +delete_get(struct kreq * r, struct file * file) { struct khtmlreq html; struct ktemplate template; @@ -133,19 +133,13 @@ delete_get(struct kreq * r, struct http_ret * ret, struct file * file) /* action url is form submit url */ if (build_delete_url(r, file) == 0) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: Can't build delete url" - }; + http_exit(r, KHTTP_500, "delete: Can't build delete url"); goto end; } /* read template */ tmpl = page_template_new(DELETE_URL); if (tmpl == NULL) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: Unable to read template" - }; + http_exit(r, KHTTP_500, "delete: Unable to read template"); goto end; } /* print delete form */ @@ -177,7 +171,7 @@ end: * POST request, we handle delete form */ void -delete_post(struct kreq * r, struct http_ret * ret, struct file * f) +delete_post(struct kreq * r, struct file * f) { char path[PATH_MAX]; char *paths[2]; @@ -193,32 +187,22 @@ delete_post(struct kreq * r, struct http_ret * ret, struct file * f) /* prepare action url for return redirection in case of success */ parent = file_get_parent(f); if (parent == NULL || build_browse_url(r, parent) == 0) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: can't build return url" - }; + http_exit(r, KHTTP_500, "delete: can't build return url"); goto end; } - /* build file path on disk */ if (file_get_data_path(f, path, sizeof(path), NULL) <= 0) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: can't build file data path" - }; + http_exit(r, KHTTP_500, "delete: can't build file data path"); goto end; } - if (f->is_dir) { /* don't follow symlinks */ fts_opts = 0x0 | FTS_PHYSICAL; paths[0] = path; paths[1] = NULL; if ((fts = fts_open(paths, fts_opts, NULL)) == NULL) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: can't open file hierarchy" - }; + http_exit(r, KHTTP_500, + "delete: can't open file hierarchy"); goto end; } /* file and directory delete loop */ @@ -227,28 +211,22 @@ delete_post(struct kreq * r, struct http_ret * ret, struct file * f) /* halt on fts errors */ if (fi == FTS_DNR || fi == FTS_ERR || fi == FTS_NS) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: fts_read error" - }; + http_exit(r, KHTTP_500, + "delete: fts_read error"); goto end; } /* delete regular files and empty folders */ else if ((fi == FTS_DP || fi == FTS_F) && remove(ftsent->fts_path) < 0) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: failed to delete file" - }; + http_exit(r, KHTTP_500, + "delete: failed to delete file"); goto end; } } } else { if (remove(path) < 0) { - *ret = (struct http_ret) { - KHTTP_500, - "delete: failed to delete file" - }; + http_exit(r, KHTTP_500, + "delete: failed to delete file"); goto end; } } @@ -257,10 +235,6 @@ delete_post(struct kreq * r, struct http_ret * ret, struct file * f) khttp_head(r, kresps[KRESP_LOCATION], "%s", parent->action_url); http_open(r, KHTTP_303, r->mime); - *ret = (struct http_ret) { - KHTTP_303, - "" - }; end: if (parent != NULL) file_free(parent); @@ -268,28 +242,21 @@ end: fts_close(fts); } - -struct http_ret +void del(struct kreq * r) { char *path; size_t suffix_len; struct file *file; - struct http_ret ret; file = NULL; - ret = (struct http_ret) { - KHTTP_200, "" - }; /* build file corresponding to request (ie. delete) path */ suffix_len = strlen(r->suffix); if (suffix_len > 0) { if (str_concat(&path, r->path, ".", r->suffix, NULL) <= 0) { - ret = (struct http_ret) { - KHTTP_404, - "delete: Unable to build file path" - }; + http_exit(r, KHTTP_404, + "delete: Unable to build file path"); goto end; } } else { @@ -298,21 +265,17 @@ del(struct kreq * r) file = file_new(path); if (file == NULL) { - ret = (struct http_ret) { - KHTTP_404, - "delete: Unable to build data file" - }; + http_exit(r, KHTTP_404, "delete: Unable to build data file"); goto end; } /* print form or handle submission according to HTTP method */ if (r->method == KMETHOD_POST) - delete_post(r, &ret, file); + delete_post(r, file); else - delete_get(r, &ret, file); + delete_get(r, file); end: if (suffix_len > 0) free(path); file_free(file); - return ret; } @@ -49,6 +49,6 @@ build_delete_url(const struct kreq *, struct file *); * Print a delete form (http GET) or handle a delete form submission (http * POST). */ -struct http_ret del(struct kreq *); +void del(struct kreq *); #endif /* DELETE_H */ @@ -76,7 +76,7 @@ build_download_url(const struct kreq * r, struct file * file) return action_url_len; } -struct http_ret +void download(struct kreq * r) { void *buffer; @@ -85,22 +85,16 @@ download(struct kreq * r) char file_path[PATH_MAX]; char *path; size_t path_size, suffix_len; - struct http_ret ret; - /* initialize empty file and return struct to success */ + /* initialize empty file to success */ f = NULL; - ret = (struct http_ret) { - KHTTP_200, "" - }; /* build requested file path, with suffix or without */ suffix_len = strlen(r->suffix); if (suffix_len > 0) { if (str_concat(&path, r->path, ".", r->suffix, NULL) <= 0) { - ret = (struct http_ret) { - KHTTP_414, - "download: unable to build requested file path" - }; + http_exit(r, KHTTP_414, + "download: unable to build requested file path"); goto end; } } else { @@ -109,54 +103,37 @@ download(struct kreq * r) /* build file metadata */ f = file_new(path); if (f == NULL) { - ret = (struct http_ret) { - KHTTP_404, - "download: file metadata failure" - }; + http_exit(r, KHTTP_404, "download: file metadata failure"); goto end; } /* we do not support downloading folders */ if (f->is_dir) { - ret = (struct http_ret) { - KHTTP_400, - "download: can't download folder" - }; + http_exit(r, KHTTP_400, "download: can't download folder"); goto end; } /* memory map the file */ path_size = file_get_data_path(f, file_path, PATH_MAX, NULL); if (path_size == 0 || path_size >= PATH_MAX) { - ret = (struct http_ret) { - KHTTP_404, - "download: unable to build file path" - }; + http_exit(r, KHTTP_404, "download: unable to build file path"); goto end; } fd = open(file_path, O_RDONLY); if (fd < 0) { - ret = (struct http_ret) { - KHTTP_404, - "download: unable to open file" - }; + http_exit(r, KHTTP_404, "download: unable to open file"); goto end; } /* mmap does not work with empty file: st_size = 0 */ if (f->size > 0) { buffer = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, fd, 0); if (buffer == MAP_FAILED) { - ret = (struct http_ret) { - KHTTP_500, - "download: mmap failed" - }; + http_exit(r, KHTTP_500, "download: mmap failed"); goto end; } } /* write the file */ if (!http_open_file(r, KHTTP_200, f)) { - ret = (struct http_ret) { - KHTTP_500, - "download: filename url encoding failed" - }; + http_exit(r, KHTTP_500, + "download: filename url encoding failed"); goto end; } if (f->size > 0) @@ -169,5 +146,4 @@ end: if (f != NULL && f->size > 0) munmap(buffer, f->size); file_free(f); - return ret; } @@ -49,6 +49,6 @@ build_download_url(const struct kreq *, struct file *); * Return a requested file. * The KCGI request is required. */ -struct http_ret download(struct kreq *); +void download(struct kreq *); #endif /* DOWNLOAD_H */ @@ -36,14 +36,6 @@ #include "file.h" /* - * Return structure for HTTP action methods - */ -struct http_ret { - enum khttp code; - char *message; -}; - -/* * Initialize headers and start the document body with the provided http code. * All parameters are required. */ @@ -62,7 +62,6 @@ main(void) char *data_dir; enum kcgi_err parse_err; struct kreq r; - struct http_ret ret; if (kutil_openlog(LOG_FILE) == 0) http_exit(NULL, KHTTP_500, "Unable to open %s", LOG_FILE); @@ -97,16 +96,16 @@ main(void) case PAGE_BROWSE: if (r.mime != KMIME_TEXT_HTML) http_exit(&r, KHTTP_406, NULL); /* Not Acceptable */ - ret = browse(&r); + browse(&r); break; case PAGE_DOWNLOAD: - ret = download(&r); + download(&r); break; case PAGE_UPLOAD: - ret = upload(&r); + upload(&r); break; case PAGE_DELETE: - ret = del(&r); + del(&r); break; default: http_exit(&r, KHTTP_404, NULL); @@ -114,8 +113,5 @@ main(void) khttp_free(&r); - if (ret.code >= KHTTP_400) - http_exit(&r, ret.code, ret.message); - return EXIT_SUCCESS; } @@ -132,7 +132,6 @@ mime_from_ext(const char *ext) return MIME_BIN; } - const char * mime_str(enum mime mime) { @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include "browse.h" @@ -18,41 +19,163 @@ int tests_run; static char * -test_browse_invalid_traversal() +test_build_browse_url() { + size_t s; + struct file f; struct kreq r; - struct http_ret ret; - /* attempt to traverse out of DATA_DIR... */ + /* nominal case */ r = (struct kreq) { - .path = "..", + .pname = "vault", + .path = "Alice/Bob", .suffix = "", - .mime = KMIME_TEXT_HTML }; - ret = browse(&r); + f = (struct file) { + .is_dir = true, + .path = "Alice/Bob", + .action_url = NULL + }; + s = build_browse_url(&r, &f); + mu_assert("failed to build browse url", s > 0 && f.action_url != NULL); + + /* refuse to browse files */ + if (f.action_url != NULL) + free(f.action_url); + f.action_url = NULL; + f.is_dir = false; + s = build_browse_url(&r, &f); + mu_assert("allowed to browse a file", s <= 0 && f.action_url == NULL); + + return 0; +} + +static char * +test_build_download_url() +{ + size_t s; + struct file f; + struct kreq r; + + /* nominal case */ + r = (struct kreq) { + .pname = "vault", + .path = "Alice/Bob", + .suffix = "txt", + }; + f = (struct file) { + .is_dir = false, + .path = "Alice/Bob.txt", + .action_url = NULL + }; + s = build_download_url(&r, &f); + mu_assert("failed to build download url", + s > 0 && f.action_url != NULL); + + /* refuse to download directories */ + if (f.action_url != NULL) + free(f.action_url); + f.action_url = NULL; + f.is_dir = true; + s = build_download_url(&r, &f); + mu_assert("allowed to download a directory", + s <= 0 && f.action_url == NULL); + + return 0; +} + +static char * +test_build_upload_url() +{ + size_t s; + struct file f; + struct kreq r; + + /* nominal case */ + r = (struct kreq) { + .pname = "vault", + .path = "Alice/Bob", + .suffix = "", + }; + f = (struct file) { + .is_dir = true, + .path = "Alice/Bob", + .action_url = NULL + }; + s = build_upload_url(&r, &f); + mu_assert("failed to build upload url", s > 0 && f.action_url != NULL); + + /* refuse to upload to a file */ + if (f.action_url != NULL) + free(f.action_url); + f.action_url = NULL; + f.is_dir = false; + s = build_upload_url(&r, &f); + mu_assert("allowed to upload to a file", + s <= 0 && f.action_url == NULL); - /* ...should return an error */ - mu_assert("error, browse allowed invalid traversal!", - ret.code >= KHTTP_400); return 0; } static char * -test_browse_path_too_long() +test_build_delete_url() { + size_t s; + struct file f; struct kreq r; - struct http_ret ret; - /* a lengthy path should cause URL overflow... */ + /* nominal case */ r = (struct kreq) { - .path = "this/is/a/very/very/lengthy/path/that/should/overflow/the/maximum/allowed/path/length/of/PATH_MAX/well/of/course/this/limit/is/platform/dependent", + .pname = "vault", + .path = "Alice/Bob", .suffix = "", - .mime = KMIME_TEXT_HTML }; - ret = browse(&r); + f = (struct file) { + .is_dir = true, + .path = "Alice/Bob", + .action_url = NULL + }; + s = build_delete_url(&r, &f); + mu_assert("failed to build delete url", s > 0 && f.action_url != NULL); + + /* allow also to delete a file */ + if (f.action_url != NULL) + free(f.action_url); + f.action_url = NULL; + f.is_dir = false; + s = build_delete_url(&r, &f); + mu_assert("refused to delete a file", s > 0 && f.action_url != NULL); - mu_assert("error, browse allowed invalid traversal!", - ret.code >= KHTTP_400); + return 0; +} + +static char * +test_url_build() +{ + char dst[BUF_SZ], *expected; + size_t dst_len; + + expected = "/vault/browse"; + dst_len = url_build(dst, BUF_SZ, "/vault/browse", "", NULL); + mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); + mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); + + expected = "/vault/browse/hello/world"; + dst_len = url_build(dst, BUF_SZ, "/vault/browse", "hello", "world", + NULL); + mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); + mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); + + expected = "/vault/browse"; + dst_len = url_build(dst, BUF_SZ, "/vault/", "browse/", NULL); + mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); + mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); + + dst_len = url_build(dst, BUF_SZ, "", "", NULL); + mu_assert("test_url_build failed", dst_len == 0); + + dst_len = url_build(dst, BUF_SZ, NULL); + mu_assert("test_url_build failed", dst_len == 0); return 0; } @@ -61,7 +184,6 @@ test_upload_post() { char *file_content; struct kreq r; - struct http_ret ret; struct kpair fields[2]; file_content = "text file"; @@ -86,9 +208,7 @@ test_upload_post() .fieldsz = 2, .fields = fields }; - ret = upload(&r); - - mu_assert("error, POST upload failed!", ret.code <= KHTTP_400); + upload(&r); return 0; } @@ -96,16 +216,12 @@ static char * test_download() { struct kreq r; - struct http_ret ret; - r = (struct kreq) { .pname = "/vault", .path = "a", .suffix = "txt", }; - ret = download(&r); - - mu_assert("error, download failed!", ret.code <= KHTTP_400); + download(&r); return 0; } @@ -113,17 +229,13 @@ static char * test_delete_get() { struct kreq r; - struct http_ret ret; - r = (struct kreq) { .pname = "/vault", .path = "a", .suffix = "txt", .method = KMETHOD_GET, }; - ret = del(&r); - - mu_assert("error, GET delete failed!", ret.code <= KHTTP_400); + del(&r); return 0; } @@ -131,60 +243,34 @@ static char * test_delete_post() { struct kreq r; - struct http_ret ret; - r = (struct kreq) { .pname = "/vault", .path = "Folder", .suffix = "", .method = KMETHOD_POST, }; - ret = del(&r); - - mu_assert("error, POST delete failed!", ret.code <= KHTTP_400); - return 0; -} - -static char * -test_url_build() -{ - char dst[BUF_SZ], *expected; - size_t dst_len; - - expected = "/vault/browse"; - dst_len = url_build(dst, BUF_SZ, "/vault/browse", "", NULL); - mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); - mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); - - expected = "/vault/browse/hello/world"; - dst_len = url_build(dst, BUF_SZ, "/vault/browse", "hello", "world", - NULL); - mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); - mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); - - expected = "/vault/browse"; - dst_len = url_build(dst, BUF_SZ, "/vault/", "browse/", NULL); - mu_assert("test_url_build failed", dst_len > 0 && dst_len < BUF_SZ); - mu_assert("test_url_build failed", strncmp(expected, dst, BUF_SZ) == 0); - - dst_len = url_build(dst, BUF_SZ, "", "", NULL); - mu_assert("test_url_build failed", dst_len == 0); - - dst_len = url_build(dst, BUF_SZ, NULL); - mu_assert("test_url_build failed", dst_len == 0); + del(&r); return 0; } static char * all_tests() { - mu_run_test(test_browse_invalid_traversal); - mu_run_test(test_browse_path_too_long); - mu_run_test(test_url_build); + /* the following tests are for debug only */ + /* mu_run_test(test_download); mu_run_test(test_upload_post); mu_run_test(test_delete_get); mu_run_test(test_delete_post); + */ + + /* url building */ + mu_run_test(test_url_build); + mu_run_test(test_build_browse_url); + mu_run_test(test_build_download_url); + mu_run_test(test_build_upload_url); + mu_run_test(test_build_delete_url); + return 0; } @@ -121,7 +121,7 @@ header_template_callback(size_t index, void *arg) * GET request, we print upload form */ void -upload_get(struct kreq * r, struct http_ret * ret, struct file * file) +upload_get(struct kreq * r, struct file * file) { struct khtmlreq html; struct ktemplate template; @@ -132,19 +132,13 @@ upload_get(struct kreq * r, struct http_ret * ret, struct file * file) /* action url is form submit url */ if (build_upload_url(r, file) == 0) { - *ret = (struct http_ret) { - KHTTP_500, - "upload: Can't build upload url" - }; + http_exit(r, KHTTP_500, "upload: Can't build upload url"); goto end; } /* read template */ tmpl = page_template_new(UPLOAD_URL); if (tmpl == NULL) { - *ret = (struct http_ret) { - KHTTP_500, - "upload: Unable to read template" - }; + http_exit(r, KHTTP_500, "upload: Unable to read template"); goto end; } /* print upload form */ @@ -176,7 +170,7 @@ end: * POST request, we handle upload form */ void -upload_post(struct kreq * r, struct http_ret * ret, struct file * f) +upload_post(struct kreq * r, struct file * f) { char path[PATH_MAX]; FILE *to_write; @@ -184,13 +178,9 @@ upload_post(struct kreq * r, struct http_ret * ret, struct file * f) /* 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" - }; + http_exit(r, 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 @@ -200,33 +190,25 @@ upload_post(struct kreq * r, struct http_ret * ret, struct file * f) 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" - }; + http_exit(r, 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" - }; + http_exit(r, 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" - }; + http_exit(r, KHTTP_500, + "upload: error while writing file"); return; } if (fclose(to_write) != 0) { - *ret = (struct http_ret) { - KHTTP_500, - "upload: error while closing file" - }; + http_exit(r, KHTTP_500, + "upload: error while closing file"); return; } } @@ -234,41 +216,27 @@ upload_post(struct kreq * r, struct http_ret * ret, struct file * f) /* 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 +void 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" - }; + http_exit(r, 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); + upload_post(r, file); else - upload_get(r, &ret, file); + upload_get(r, file); end: file_free(file); - return ret; } @@ -49,6 +49,6 @@ 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 *); +void upload(struct kreq *); #endif /* UPLOAD_H */ |