aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-07-23 00:44:13 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-09-24 11:03:39 +0200
commitcb9cb0b83dc90aeee6380cdc4d2fb61d1426939c (patch)
tree20d6ce0f4896bd5caf7b9a231adece7f4795ee72
parentb9537b1d1164b9f3fbe704512b1e324c2e37beb5 (diff)
downloadslcl-cb9cb0b83dc90aeee6380cdc4d2fb61d1426939c.tar.gz
Display thumbnails, if available
-rw-r--r--main.c60
-rw-r--r--page.c147
-rw-r--r--page.h5
3 files changed, 197 insertions, 15 deletions
diff --git a/main.c b/main.c
index d56927a..3702706 100644
--- a/main.c
+++ b/main.c
@@ -729,10 +729,14 @@ static int search(const struct http_payload *const p,
const struct user_args *const args = user;
const struct auth *const a = args->a;
const char *const username = p->cookie.field, *const root = auth_dir(a);
- struct page_search s = {0};
int (*f)(struct http_response *);
char *dir = NULL;
struct dynstr userd, d, res;
+ struct page_search s =
+ {
+ .username = username,
+ .adir = root
+ };
dynstr_init(&userd);
dynstr_init(&d);
@@ -1043,6 +1047,8 @@ static int getnode(const struct http_payload *const p,
.r = r,
.args = p->args,
.n_args = p->n_args,
+ .username = username,
+ .adir = adir,
.dir = dir.str,
.root = root.str,
.res = d.str,
@@ -2077,6 +2083,55 @@ end:
return ret;
}
+static int getthumbnail(const struct http_payload *const p,
+ struct http_response *const r, void *const user)
+{
+ int ret = -1;
+ const struct user_args *const ua = user;
+ const struct auth *const a = ua->a;
+ struct dynstr d, dir;
+
+ dynstr_init(&d);
+ dynstr_init(&dir);
+
+ if (auth_cookie(a, &p->cookie))
+ {
+ fprintf(stderr, "%s: auth_cookie failed\n", __func__);
+ ret = page_forbidden(r);
+ goto end;
+ }
+
+ const char *const adir = auth_dir(a);
+
+ if (!adir)
+ {
+ fprintf(stderr, "%s: auth_dir failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_append(&d, "%s%s", adir, p->resource))
+ {
+ fprintf(stderr, "%s: dynstr_append failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_dup(&dir, &d))
+ {
+ fprintf(stderr, "%s: dynstr_dup failed\n", __func__);
+ goto end;
+ }
+ else if (page_thumbnail(r, d.str))
+ {
+ fprintf(stderr, "%s: page_public failed\n", __func__);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ dynstr_free(&d);
+ dynstr_free(&dir);
+ return ret;
+}
+
static void usage(char *const argv[])
{
fprintf(stderr, "%s [-F] [-t tmpdir] [-p port] dir\n", *argv);
@@ -2309,7 +2364,8 @@ static int add_urls(struct handler *const h, void *const user)
{.url = "/upload", .op = HTTP_OP_POST, .f = upload},
{.url = "/mkdir", .op = HTTP_OP_POST, .f = createdir},
{.url = "/confirm/rm", .op = HTTP_OP_POST, .f = confirm_rm},
- {.url = "/rm", .op = HTTP_OP_POST, .f = rm}
+ {.url = "/rm", .op = HTTP_OP_POST, .f = rm},
+ {.url = "/thumbnails/*", .op = HTTP_OP_GET, .f = getthumbnail}
};
for (size_t i = 0; i < sizeof urls / sizeof *urls; i++)
diff --git a/page.c b/page.c
index c103f4a..1966200 100644
--- a/page.c
+++ b/page.c
@@ -101,6 +101,67 @@ end:
return ret;
}
+static int prepare_thumbnail(struct html_node *const n,
+ const struct stat *const sb, const struct page_resource *const pr,
+ const char *const name, const char *const sep)
+{
+ int ret = -1;
+ struct html_node *img;
+ struct dynstr abs, rel;
+ struct stat tsb;
+
+ dynstr_init(&abs);
+ dynstr_init(&rel);
+
+ if (!S_ISREG(sb->st_mode))
+ {
+ ret = 0;
+ goto end;
+ }
+ else if (!pr->adir || !pr->username)
+ {
+ ret = 0;
+ goto end;
+ }
+ else if (dynstr_append(&rel, "/thumbnails/%s%s%s%s",
+ pr->username, pr->dir + strlen("/user"), sep, name))
+ {
+ fprintf(stderr, "%s: dynstr_append rel failed\n", __func__);
+ goto end;
+ }
+ else if (dynstr_append(&abs, "%s%s", pr->adir, rel.str))
+ {
+ fprintf(stderr, "%s: dynstr_append rel failed\n", __func__);
+ goto end;
+ }
+ else if (stat(abs.str, &tsb))
+ {
+ if (errno == ENOENT)
+ ret = 0;
+ else
+ fprintf(stderr, "%s: stat(2): %s\n", __func__, strerror(errno));
+
+ goto end;
+ }
+ else if (!(img = html_node_add_child(n, "img")))
+ {
+ fprintf(stderr, "%s: html_node_add_child failed\n", __func__);
+ goto end;
+ }
+ else if (html_node_add_attr(img, "src", rel.str))
+ {
+ fprintf(stderr, "%s: html_node_add_attr src failed\n", __func__);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ dynstr_free(&abs);
+ dynstr_free(&rel);
+ return ret;
+}
+
static int prepare_name(struct html_node *const n, struct stat *const sb,
const char *const dir, const char *const name)
{
@@ -360,19 +421,19 @@ end:
return ret;
}
-static int add_element(struct html_node *const n, const char *const dir,
- const char *const res, const char *const name, const bool chbx,
- struct element_stats *const st)
+static int add_element(struct html_node *const n,
+ const struct page_resource *const pr, const char *const name,
+ const bool chbx, struct element_stats *const st)
{
int ret = -1;
- enum {RM_CHECKBOX, NAME, SIZE, DATE, SHARE, PREVIEW, COLUMNS};
+ enum {RM_CHECKBOX, THUMBNAIL, NAME, SIZE, DATE, SHARE, PREVIEW, COLUMNS};
struct html_node *tr, *td[COLUMNS];
struct dynstr path;
- const char *const sep = res[strlen(res) - 1] != '/' ? "/" : "";
+ const char *const sep = pr->res[strlen(pr->res) - 1] != '/' ? "/" : "";
dynstr_init(&path);
- if (dynstr_append(&path, "%s%s%s", res, sep, name))
+ if (dynstr_append(&path, "%s%s%s", pr->res, sep, name))
{
fprintf(stderr, "%s: dynstr_append failed\n", __func__);
goto end;
@@ -406,7 +467,12 @@ static int add_element(struct html_node *const n, const char *const dir,
fprintf(stderr, "%s: prepare_rm_checkbox failed\n", __func__);
goto end;
}
- else if (prepare_name(td[NAME], &sb, dir, name))
+ else if (prepare_thumbnail(td[THUMBNAIL], &sb, pr, name, sep))
+ {
+ fprintf(stderr, "%s: prepare_thumbnail failed\n", __func__);
+ goto end;
+ }
+ else if (prepare_name(td[NAME], &sb, pr->dir, name))
{
fprintf(stderr, "%s: prepare_name failed\n", __func__);
goto end;
@@ -421,12 +487,12 @@ static int add_element(struct html_node *const n, const char *const dir,
fprintf(stderr, "%s: prepare_date failed\n", __func__);
goto end;
}
- else if (prepare_share(td[SHARE], &sb, dir, name))
+ else if (prepare_share(td[SHARE], &sb, pr->dir, name))
{
fprintf(stderr, "%s: prepare_date failed\n", __func__);
goto end;
}
- else if (prepare_preview(td[PREVIEW], &sb, dir, name))
+ else if (prepare_preview(td[PREVIEW], &sb, pr->dir, name))
{
fprintf(stderr, "%s: prepare_date failed\n", __func__);
goto end;
@@ -1321,7 +1387,7 @@ static int add_elements(const struct page_resource *const pr,
if (!strcmp(name, ".")
|| (!strcmp(name, "..") && !strcmp(pr->root, pr->res)))
continue;
- else if (add_element(table, pr->dir, pr->res, name, true, st))
+ else if (add_element(table, pr, name, true, st))
{
fprintf(stderr, "%s: add_element failed\n", __func__);
goto end;
@@ -2163,8 +2229,15 @@ static int add_search_results(struct html_node *const n,
for (size_t i = 0; i < s->n; i++)
{
const struct page_search_result *const r = &s->results[i];
+ const struct page_resource pr =
+ {
+ .dir = "/user/",
+ .adir = s->adir,
+ .username = s->username,
+ .res = s->root
+ };
- if (add_element(table, "/user/", s->root, r->name, false, NULL))
+ if (add_element(table, &pr, r->name, false, NULL))
{
fprintf(stderr, "%s: add_element failed\n", __func__);
return -1;
@@ -2580,3 +2653,55 @@ int page_head_resource(struct http_response *const r, const char *const res)
return 0;
}
+
+int page_thumbnail(struct http_response *const r, const char *const res)
+{
+ int ret = -1;
+ const int fd = open(res, O_RDONLY);
+ bool fdopened = false;
+ struct stat sb;
+
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ ret = page_not_found(r);
+ else
+ fprintf(stderr, "%s: open(2) %s: %s\n",
+ __func__, res, strerror(errno));
+
+ goto end;
+ }
+ else if (fstat(fd, &sb))
+ {
+ fprintf(stderr, "%s: fstat(2) %s: %s\n",
+ __func__, res, strerror(errno));
+ goto end;
+ }
+
+ const mode_t m = sb.st_mode;
+
+ if (!S_ISREG(m))
+ {
+ fprintf(stderr, "%s: only regular files are supported\n", __func__);
+ ret = 1;
+ goto end;
+ }
+ else if (serve_file(r, &sb, res, true, fd, &fdopened))
+ {
+ fprintf(stderr, "%s: serve_file failed\n", __func__);
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+
+ if (!fdopened && fd >= 0 && close(fd))
+ {
+ fprintf(stderr, "%s: close(2) %s: %s\n",
+ __func__, res, strerror(errno));
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/page.h b/page.h
index ca7f3cc..8b1e9a0 100644
--- a/page.h
+++ b/page.h
@@ -13,7 +13,7 @@ struct page_quota
struct page_resource
{
struct http_response *r;
- const char *dir, *root, *res;
+ const char *adir, *username, *dir, *root, *res;
const struct page_quota *q;
const struct http_arg *args;
size_t n_args;
@@ -26,7 +26,7 @@ struct page_search
char *name;
} *results;
- const char *root;
+ const char *root, *adir, *username;
size_t n;
bool limit_exceeded;
};
@@ -51,5 +51,6 @@ int page_quota_exceeded(struct http_response *r, unsigned long long len,
unsigned long long quota);
int page_search(struct http_response *r, const struct page_search *s);
int page_rm(struct http_response *r, const struct page_rm *rm);
+int page_thumbnail(struct http_response *r, const char *res);
#endif /* PAGE_H */