diff options
author | June McEnroe <june@causal.agency> | 2021-09-22 19:43:54 +0000 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2021-09-22 19:43:54 +0000 |
commit | 6ded0a072c0e63c8062d5429deee7e988f24afe9 (patch) | |
tree | 60204a2de0bf0303e272f46b534cd32b8ccc7642 | |
parent | Remove default favicon (diff) | |
download | src-6ded0a072c0e63c8062d5429deee7e988f24afe9.tar.gz src-6ded0a072c0e63c8062d5429deee7e988f24afe9.zip |
Support HTTP PUT in up
For use by Palaver[1]. Unfortunately, at least in the current App Store version of Palaver, this doesn't work correctly with basic auth. [1]: https://palaverapp.com/guides/commands/set.html#ui-image_service
-rw-r--r-- | www/temp.causal.agency/up.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/www/temp.causal.agency/up.c b/www/temp.causal.agency/up.c index 9e7b4ff7..af45446e 100644 --- a/www/temp.causal.agency/up.c +++ b/www/temp.causal.agency/up.c @@ -45,6 +45,27 @@ static enum kcgi_err fail(struct kreq *req, enum khttp http) { || khttp_printf(req, "%s\n", khttps[http]); } +static const char *upload(const char *ext, void *ptr, size_t len) { + static char name[256]; + snprintf( + name, sizeof(name), "%jx%08x%s%s", + (intmax_t)time(NULL), arc4random(), + (ext && ext[0] != '.' ? "." : ""), (ext ? ext : "") + ); + int fd = openat(cwd, name, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd < 0) { + warn("%s", name); + return NULL; + } + ssize_t n = write(fd, ptr, len); + int error = close(fd); + if (n < 0 || error) { + warn("%s", name); + return NULL; + } + return name; +} + static enum kcgi_err handle(struct kreq *req) { if (req->page) return fail(req, KHTTP_404); @@ -83,31 +104,30 @@ static enum kcgi_err handle(struct kreq *req) { struct kpair *field = req->fieldmap[0]; if (!field || !field->valsz) return fail(req, KHTTP_400); - char name[256]; const char *ext = strrchr(field->file, '.'); - if (!ext) ext = ""; - snprintf( - name, sizeof(name), "%jx%08x%s", - (intmax_t)time(NULL), arc4random(), ext - ); - - int fd = openat(cwd, name, O_CREAT | O_EXCL | O_WRONLY, 0644); - if (fd < 0) { - warn("openat"); - return fail(req, KHTTP_507); - } - ssize_t len = write(fd, field->val, field->valsz); - int error = close(fd); - if (len < 0 || error) { - warn("write"); - return fail(req, KHTTP_507); - } + const char *name = upload(ext, field->val, field->valsz); + if (!name) return fail(req, KHTTP_507); return head(req, KHTTP_303, KMIME_TEXT_PLAIN) || khttp_head(req, kresps[KRESP_LOCATION], "/%s", name) || khttp_body(req) || khttp_puts(req, name); + } else if (req->method == KMETHOD_PUT) { + struct kpair *field = req->fields; + if (!field || !field->valsz) return fail(req, KHTTP_400); + + const char *ext = req->suffix; + if (!ext[0]) ext = strrchr(field->file, '.'); + const char *name = upload(ext, field->val, field->valsz); + if (!name) return fail(req, KHTTP_507); + + return head(req, KHTTP_200, KMIME_TEXT_PLAIN) + || khttp_body(req) + || khttp_printf( + req, "%s://%s/%s\n", kschemes[req->scheme], req->host, name + ); + } else { return fail(req, KHTTP_405); } |