diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-07-23 00:44:13 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-11-24 02:08:42 +0100 |
| commit | 73d22e349c4f6cd36323de26b8d31eda6724b52a (patch) | |
| tree | 32e7cca5ab05a2365cfc8e2f6d565ec4244ca5dc | |
| parent | 199192b682a7880671a891b51a780b575f5a2b37 (diff) | |
| download | slcl-73d22e349c4f6cd36323de26b8d31eda6724b52a.tar.gz | |
Display thumbnails, if available
| -rw-r--r-- | main.c | 60 | ||||
| -rw-r--r-- | page.c | 133 | ||||
| -rw-r--r-- | page.h | 5 |
3 files changed, 177 insertions, 21 deletions
@@ -710,10 +710,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); @@ -990,6 +994,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, @@ -2011,6 +2017,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); @@ -2243,7 +2298,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) { @@ -338,19 +399,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; @@ -392,7 +453,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; @@ -407,12 +473,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; @@ -1129,13 +1195,12 @@ end: return ret; } -static int add_elements(const char *const root, const char *const res, - const char *const dir, struct html_node *const table, - struct element_stats *const st) +static int add_elements(const struct page_resource *const pr, + struct html_node *const table, struct element_stats *const st) { int ret = -1; struct dirent **pde = NULL; - const int n = scandir(res, &pde, NULL, alphasort); + const int n = scandir(pr->res, &pde, NULL, alphasort); if (n < 0) { @@ -1151,9 +1216,9 @@ static int add_elements(const char *const root, const char *const res, const char *const name = de->d_name; if (!strcmp(name, ".") - || (!strcmp(name, "..") && !strcmp(root, res))) + || (!strcmp(name, "..") && !strcmp(pr->root, pr->res))) continue; - else if (add_element(table, dir, res, name, true, st)) + else if (add_element(table, pr, name, true, st)) { fprintf(stderr, "%s: add_element failed\n", __func__); goto end; @@ -1220,7 +1285,7 @@ static int list_dir(const struct page_resource *const pr) fprintf(stderr, "%s: resource_layout failed\n", __func__); goto end; } - else if (add_elements(pr->root, pr->res, pr->dir, table, &st)) + else if (add_elements(pr, table, &st)) { fprintf(stderr, "%s: read_elements failed\n", __func__); goto end; @@ -1815,8 +1880,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; @@ -2232,3 +2304,30 @@ 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) +{ + struct stat sb; + + if (stat(res, &sb)) + { + if (errno == ENOENT) + 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_ISREG(m)) + { + fprintf(stderr, "%s: only regular files are supported\n", __func__); + return 1; + } + + return serve_file(r, &sb, res, true); +} @@ -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; }; @@ -50,5 +50,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 */ |
