diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-10-03 00:09:37 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-10-14 01:08:02 +0200 |
| commit | 472b4ddbf151b44f5fc01c4c1752ce5529a0cf85 (patch) | |
| tree | 623d22494bda1018e9471052603a545eb55b7572 | |
| parent | 1d2ce3f9c235f0b6524bbedad0b2ff0abb838888 (diff) | |
| download | slcl-472b4ddbf151b44f5fc01c4c1752ce5529a0cf85.tar.gz | |
Implement HEAD support
| -rw-r--r-- | main.c | 56 | ||||
| -rw-r--r-- | page.c | 33 | ||||
| -rw-r--r-- | page.h | 1 |
3 files changed, 90 insertions, 0 deletions
@@ -980,6 +980,61 @@ end: return ret; } +static int getnode_head(const struct http_payload *const p, + struct http_response *const r, void *const user) +{ + struct auth *const a = user; + + if (auth_cookie(a, &p->cookie)) + { + fprintf(stderr, "%s: auth_cookie failed\n", __func__); + return page_forbidden(r); + } + + const char *const username = p->cookie.field, + *const resource = p->resource + strlen("/user/"); + + if (path_invalid(resource)) + { + fprintf(stderr, "%s: illegal relative path %s\n", __func__, resource); + return page_forbidden(r); + } + + int ret = -1; + struct dynstr dir, root, d; + const char *const adir = auth_dir(a), + *const sep = p->resource[strlen(p->resource) - 1] != '/' ? "/" : ""; + + dynstr_init(&dir); + dynstr_init(&d); + dynstr_init(&root); + + if (!adir) + { + fprintf(stderr, "%s: auth_dir failed\n", __func__); + goto end; + } + else if (dynstr_append(&dir, "%s%s", p->resource, sep)) + { + fprintf(stderr, "%s: dynstr_append dird failed\n", __func__); + goto end; + } + else if (dynstr_append(&root, "%s/user/%s/", adir, username) + || dynstr_append(&d, "%s%s", root.str, resource)) + { + fprintf(stderr, "%s: dynstr_append failed\n", __func__); + goto end; + } + + ret = page_head_resource(r, d.str); + +end: + dynstr_free(&dir); + dynstr_free(&d); + dynstr_free(&root); + return ret; +} + static int move_file(const char *const old, const char *const new) { int ret = -1; @@ -1924,6 +1979,7 @@ static int add_urls(struct handler *const h, void *const user) {.url = "/index.html", .op = HTTP_OP_GET, .f = serve_index}, {.url = "/style.css", .op = HTTP_OP_GET, .f = serve_style}, {.url = "/user/*", .op = HTTP_OP_GET, .f = getnode}, + {.url = "/user/*", .op = HTTP_OP_HEAD, .f = getnode_head}, {.url = "/login", .op = HTTP_OP_POST, .f = login}, {.url = "/logout", .op = HTTP_OP_POST, .f = logout}, {.url = "/public/*", .op = HTTP_OP_GET, .f = getpublic}, @@ -2199,3 +2199,36 @@ end: return ret; } + +int page_head_resource(struct http_response *const r, const char *const res) +{ + struct stat sb; + + if (stat(res, &sb)) + { + if (errno == ENOENT || errno == ENOTDIR) + return page_not_found(r); + else + { + fprintf(stderr, "%s: stat(2) %s: %s\n", + __func__, res, strerror(errno)); + return -1; + } + } + + const mode_t m = sb.st_mode; + + if (!S_ISDIR(m) && !S_ISREG(m)) + { + fprintf(stderr, "%s: unexpected st_mode %jd\n", __func__, (intmax_t)m); + return -1; + } + + *r = (const struct http_response) + { + .status = HTTP_STATUS_OK, + .n = sb.st_size + }; + + return 0; +} @@ -43,6 +43,7 @@ int page_failed_login(struct http_response *r); int page_forbidden(struct http_response *r); int page_bad_request(struct http_response *r); int page_resource(const struct page_resource *r); +int page_head_resource(struct http_response *r, const char *res); int page_public(struct http_response *r, const char *res); int page_share(struct http_response *r, const char *path); int page_quota_exceeded(struct http_response *r, unsigned long long len, |
