diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-07-23 00:44:13 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-09-24 11:03:39 +0200 |
| commit | cb9cb0b83dc90aeee6380cdc4d2fb61d1426939c (patch) | |
| tree | 20d6ce0f4896bd5caf7b9a231adece7f4795ee72 | |
| parent | b9537b1d1164b9f3fbe704512b1e324c2e37beb5 (diff) | |
| download | slcl-cb9cb0b83dc90aeee6380cdc4d2fb61d1426939c.tar.gz | |
Display thumbnails, if available
| -rw-r--r-- | main.c | 60 | ||||
| -rw-r--r-- | page.c | 147 | ||||
| -rw-r--r-- | page.h | 5 |
3 files changed, 197 insertions, 15 deletions
@@ -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++) @@ -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; +} @@ -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 */ |
