aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-10-03 00:09:37 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-10-14 01:08:02 +0200
commit472b4ddbf151b44f5fc01c4c1752ce5529a0cf85 (patch)
tree623d22494bda1018e9471052603a545eb55b7572
parent1d2ce3f9c235f0b6524bbedad0b2ff0abb838888 (diff)
downloadslcl-472b4ddbf151b44f5fc01c4c1752ce5529a0cf85.tar.gz
Implement HEAD support
-rw-r--r--main.c56
-rw-r--r--page.c33
-rw-r--r--page.h1
3 files changed, 90 insertions, 0 deletions
diff --git a/main.c b/main.c
index 8a15e06..df8cd21 100644
--- a/main.c
+++ b/main.c
@@ -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},
diff --git a/page.c b/page.c
index f3856a9..02049a3 100644
--- a/page.c
+++ b/page.c
@@ -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;
+}
diff --git a/page.h b/page.h
index 01e7a0a..22658fd 100644
--- a/page.h
+++ b/page.h
@@ -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,