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 <xavi.dcr@tutanota.com>2023-11-24 02:08:42 +0100
commit73d22e349c4f6cd36323de26b8d31eda6724b52a (patch)
tree32e7cca5ab05a2365cfc8e2f6d565ec4244ca5dc
parent199192b682a7880671a891b51a780b575f5a2b37 (diff)
downloadslcl-73d22e349c4f6cd36323de26b8d31eda6724b52a.tar.gz
Display thumbnails, if available
-rw-r--r--main.c60
-rw-r--r--page.c133
-rw-r--r--page.h5
3 files changed, 177 insertions, 21 deletions
diff --git a/main.c b/main.c
index 848c94c..0e30d20 100644
--- a/main.c
+++ b/main.c
@@ -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++)
diff --git a/page.c b/page.c
index 02049a3..1ccf0a9 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)
{
@@ -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);
+}
diff --git a/page.h b/page.h
index 22658fd..d5fabc1 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;
};
@@ -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 */