summaryrefslogtreecommitdiff
path: root/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'html.c')
-rw-r--r--html.c135
1 files changed, 107 insertions, 28 deletions
diff --git a/html.c b/html.c
index 810502e..3721f0e 100644
--- a/html.c
+++ b/html.c
@@ -11,6 +11,7 @@
11#include "xs_mime.h" 11#include "xs_mime.h"
12#include "xs_match.h" 12#include "xs_match.h"
13#include "xs_html.h" 13#include "xs_html.h"
14#include "xs_curl.h"
14 15
15#include "snac.h" 16#include "snac.h"
16 17
@@ -41,7 +42,7 @@ int login(snac *snac, const xs_dict *headers)
41} 42}
42 43
43 44
44xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems) 45xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *proxy)
45/* replaces all the :shortnames: with the emojis in tag */ 46/* replaces all the :shortnames: with the emojis in tag */
46{ 47{
47 if (!xs_is_null(tag)) { 48 if (!xs_is_null(tag)) {
@@ -69,9 +70,11 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems)
69 70
70 if (n && i) { 71 if (n && i) {
71 const char *u = xs_dict_get(i, "url"); 72 const char *u = xs_dict_get(i, "url");
73 xs *url = make_url(u, proxy);
74
72 xs_html *img = xs_html_sctag("img", 75 xs_html *img = xs_html_sctag("img",
73 xs_html_attr("loading", "lazy"), 76 xs_html_attr("loading", "lazy"),
74 xs_html_attr("src", u), 77 xs_html_attr("src", url),
75 xs_html_attr("style", style)); 78 xs_html_attr("style", style));
76 79
77 xs *s1 = xs_html_render(img); 80 xs *s1 = xs_html_render(img);
@@ -85,7 +88,7 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems)
85} 88}
86 89
87 90
88xs_str *actor_name(xs_dict *actor) 91xs_str *actor_name(xs_dict *actor, const char *proxy)
89/* gets the actor name */ 92/* gets the actor name */
90{ 93{
91 const char *v; 94 const char *v;
@@ -96,12 +99,12 @@ xs_str *actor_name(xs_dict *actor)
96 } 99 }
97 } 100 }
98 101
99 return replace_shortnames(xs_html_encode(v), xs_dict_get(actor, "tag"), 1); 102 return replace_shortnames(xs_html_encode(v), xs_dict_get(actor, "tag"), 1, proxy);
100} 103}
101 104
102 105
103xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, 106xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
104 const char *udate, const char *url, int priv, int in_people) 107 const char *udate, const char *url, int priv, int in_people, const char *proxy)
105{ 108{
106 xs_html *actor_icon = xs_html_tag("p", NULL); 109 xs_html *actor_icon = xs_html_tag("p", NULL);
107 110
@@ -110,7 +113,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
110 int fwing = 0; 113 int fwing = 0;
111 int fwer = 0; 114 int fwer = 0;
112 115
113 xs *name = actor_name(actor); 116 xs *name = actor_name(actor, proxy);
114 117
115 /* get the avatar */ 118 /* get the avatar */
116 if ((v = xs_dict_get(actor, "icon")) != NULL) { 119 if ((v = xs_dict_get(actor, "icon")) != NULL) {
@@ -119,7 +122,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
119 v = xs_list_get(v, 0); 122 v = xs_list_get(v, 0);
120 123
121 if ((v = xs_dict_get(v, "url")) != NULL) 124 if ((v = xs_dict_get(v, "url")) != NULL)
122 avatar = xs_dup(v); 125 avatar = make_url(v, proxy);
123 } 126 }
124 127
125 if (avatar == NULL) 128 if (avatar == NULL)
@@ -244,7 +247,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
244} 247}
245 248
246 249
247xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg) 250xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, const char *proxy)
248{ 251{
249 xs *actor = NULL; 252 xs *actor = NULL;
250 xs_html *actor_icon = NULL; 253 xs_html *actor_icon = NULL;
@@ -264,7 +267,7 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg)
264 date = xs_dict_get(msg, "published"); 267 date = xs_dict_get(msg, "published");
265 udate = xs_dict_get(msg, "updated"); 268 udate = xs_dict_get(msg, "updated");
266 269
267 actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0); 270 actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy);
268 } 271 }
269 272
270 return actor_icon; 273 return actor_icon;
@@ -681,6 +684,11 @@ xs_html *html_user_head(snac *user, const char *desc, const char *url)
681 684
682static xs_html *html_user_body(snac *user, int read_only) 685static xs_html *html_user_body(snac *user, int read_only)
683{ 686{
687 const char *proxy = NULL;
688
689 if (user && !read_only && xs_is_true(xs_dict_get(srv_config, "proxy_media")))
690 proxy = user->actor;
691
684 xs_html *body = xs_html_tag("body", NULL); 692 xs_html *body = xs_html_tag("body", NULL);
685 693
686 /* top nav */ 694 /* top nav */
@@ -826,7 +834,7 @@ static xs_html *html_user_body(snac *user, int read_only)
826 xs *bio1 = not_really_markdown(es1, NULL, &tags); 834 xs *bio1 = not_really_markdown(es1, NULL, &tags);
827 xs *bio2 = process_tags(user, bio1, &tags); 835 xs *bio2 = process_tags(user, bio1, &tags);
828 836
829 bio2 = replace_shortnames(bio2, tags, 2); 837 bio2 = replace_shortnames(bio2, tags, 2, proxy);
830 838
831 xs_html *top_user_bio = xs_html_tag("div", 839 xs_html *top_user_bio = xs_html_tag("div",
832 xs_html_attr("class", "p-note snac-top-user-bio"), 840 xs_html_attr("class", "p-note snac-top-user-bio"),
@@ -1464,6 +1472,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1464 const char *v; 1472 const char *v;
1465 int has_title = 0; 1473 int has_title = 0;
1466 int collapse_threads = 0; 1474 int collapse_threads = 0;
1475 const char *proxy = NULL;
1476
1477 if (user && !read_only && xs_is_true(xs_dict_get(srv_config, "proxy_media")))
1478 proxy = user->actor;
1467 1479
1468 /* do not show non-public messages in the public timeline */ 1480 /* do not show non-public messages in the public timeline */
1469 if ((read_only || !user) && !is_msg_public(msg)) 1481 if ((read_only || !user) && !is_msg_public(msg))
@@ -1495,7 +1507,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1495 xs_html_tag("div", 1507 xs_html_tag("div",
1496 xs_html_attr("class", "snac-origin"), 1508 xs_html_attr("class", "snac-origin"),
1497 xs_html_text(L("follows you"))), 1509 xs_html_text(L("follows you"))),
1498 html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg))); 1510 html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg, proxy)));
1499 } 1511 }
1500 else 1512 else
1501 if (!xs_match(type, POSTLIKE_OBJECT_TYPE)) { 1513 if (!xs_match(type, POSTLIKE_OBJECT_TYPE)) {
@@ -1625,7 +1637,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1625 } 1637 }
1626 else 1638 else
1627 if (valid_status(object_get_by_md5(p, &actor_r))) { 1639 if (valid_status(object_get_by_md5(p, &actor_r))) {
1628 xs *name = actor_name(actor_r); 1640 xs *name = actor_name(actor_r, proxy);
1629 1641
1630 if (!xs_is_null(name)) { 1642 if (!xs_is_null(name)) {
1631 xs *href = NULL; 1643 xs *href = NULL;
@@ -1674,7 +1686,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1674 } 1686 }
1675 1687
1676 xs_html_add(post_header, 1688 xs_html_add(post_header,
1677 html_msg_icon(read_only ? NULL : user, actor, msg)); 1689 html_msg_icon(read_only ? NULL : user, actor, msg, proxy));
1678 1690
1679 /** post content **/ 1691 /** post content **/
1680 1692
@@ -1763,7 +1775,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1763 c = xs_str_cat(c, "<p>"); 1775 c = xs_str_cat(c, "<p>");
1764 1776
1765 /* replace the :shortnames: */ 1777 /* replace the :shortnames: */
1766 c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2); 1778 c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2, proxy);
1767 1779
1768 /* Peertube videos content is in markdown */ 1780 /* Peertube videos content is in markdown */
1769 const char *mtype = xs_dict_get(msg, "mediaType"); 1781 const char *mtype = xs_dict_get(msg, "mediaType");
@@ -1954,13 +1966,15 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1954 const xs_dict *a; 1966 const xs_dict *a;
1955 while (xs_list_next(attach, &a, &c)) { 1967 while (xs_list_next(attach, &a, &c)) {
1956 const char *type = xs_dict_get(a, "type"); 1968 const char *type = xs_dict_get(a, "type");
1957 const char *href = xs_dict_get(a, "href"); 1969 const char *o_href = xs_dict_get(a, "href");
1958 const char *name = xs_dict_get(a, "name"); 1970 const char *name = xs_dict_get(a, "name");
1959 1971
1960 /* if this image is already in the post content, skip */ 1972 /* if this image is already in the post content, skip */
1961 if (content && xs_str_in(content, href) != -1) 1973 if (content && xs_str_in(content, o_href) != -1)
1962 continue; 1974 continue;
1963 1975
1976 xs *href = make_url(o_href, proxy);
1977
1964 if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) { 1978 if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) {
1965 xs_html_add(content_attachments, 1979 xs_html_add(content_attachments,
1966 xs_html_tag("a", 1980 xs_html_tag("a",
@@ -2007,7 +2021,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
2007 xs_html_add(content_attachments, 2021 xs_html_add(content_attachments,
2008 xs_html_tag("p", 2022 xs_html_tag("p",
2009 xs_html_tag("a", 2023 xs_html_tag("a",
2010 xs_html_attr("href", href), 2024 xs_html_attr("href", o_href),
2011 xs_html_text(href)))); 2025 xs_html_text(href))));
2012 2026
2013 /* do not generate an Alt... */ 2027 /* do not generate an Alt... */
@@ -2017,10 +2031,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
2017 xs_html_add(content_attachments, 2031 xs_html_add(content_attachments,
2018 xs_html_tag("p", 2032 xs_html_tag("p",
2019 xs_html_tag("a", 2033 xs_html_tag("a",
2020 xs_html_attr("href", href), 2034 xs_html_attr("href", o_href),
2021 xs_html_text(L("Attachment")), 2035 xs_html_text(L("Attachment")),
2022 xs_html_text(": "), 2036 xs_html_text(": "),
2023 xs_html_text(href)))); 2037 xs_html_text(o_href))));
2024 2038
2025 /* do not generate an Alt... */ 2039 /* do not generate an Alt... */
2026 name = NULL; 2040 name = NULL;
@@ -2168,7 +2182,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
2168 xs_list *p = (xs_list *)list; 2182 xs_list *p = (xs_list *)list;
2169 const char *v; 2183 const char *v;
2170 double t = ftime(); 2184 double t = ftime();
2171 int hide_children = xs_is_true(xs_dict_get(srv_config, "strict_public_timelines")); 2185 int hide_children = xs_is_true(xs_dict_get(srv_config, "strict_public_timelines")) && read_only;
2172 2186
2173 xs *desc = NULL; 2187 xs *desc = NULL;
2174 xs *alternate = NULL; 2188 xs *alternate = NULL;
@@ -2411,7 +2425,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
2411} 2425}
2412 2426
2413 2427
2414xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t) 2428xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, const char *proxy)
2415{ 2429{
2416 xs_html *snac_posts; 2430 xs_html *snac_posts;
2417 xs_html *people = xs_html_tag("div", 2431 xs_html *people = xs_html_tag("div",
@@ -2437,7 +2451,8 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t)
2437 xs_html_attr("name", md5)), 2451 xs_html_attr("name", md5)),
2438 xs_html_tag("div", 2452 xs_html_tag("div",
2439 xs_html_attr("class", "snac-post-header"), 2453 xs_html_attr("class", "snac-post-header"),
2440 html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1))); 2454 html_actor_icon(snac, actor, xs_dict_get(actor, "published"),
2455 NULL, NULL, 0, 1, proxy)));
2441 2456
2442 /* content (user bio) */ 2457 /* content (user bio) */
2443 const char *c = xs_dict_get(actor, "summary"); 2458 const char *c = xs_dict_get(actor, "summary");
@@ -2540,6 +2555,11 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t)
2540 2555
2541xs_str *html_people(snac *user) 2556xs_str *html_people(snac *user)
2542{ 2557{
2558 const char *proxy = NULL;
2559
2560 if (xs_is_true(xs_dict_get(srv_config, "proxy_media")))
2561 proxy = user->actor;
2562
2543 xs *wing = following_list(user); 2563 xs *wing = following_list(user);
2544 xs *wers = follower_list(user); 2564 xs *wers = follower_list(user);
2545 2565
@@ -2548,8 +2568,8 @@ xs_str *html_people(snac *user)
2548 xs_html_add(html_user_body(user, 0), 2568 xs_html_add(html_user_body(user, 0),
2549 xs_html_tag("div", 2569 xs_html_tag("div",
2550 xs_html_attr("class", "snac-posts"), 2570 xs_html_attr("class", "snac-posts"),
2551 html_people_list(user, wing, L("People you follow"), "i"), 2571 html_people_list(user, wing, L("People you follow"), "i", proxy),
2552 html_people_list(user, wers, L("People that follow you"), "e")), 2572 html_people_list(user, wers, L("People that follow you"), "e", proxy)),
2553 html_footer())); 2573 html_footer()));
2554 2574
2555 return xs_html_render_s(html, "<!DOCTYPE html>\n"); 2575 return xs_html_render_s(html, "<!DOCTYPE html>\n");
@@ -2558,6 +2578,11 @@ xs_str *html_people(snac *user)
2558 2578
2559xs_str *html_notifications(snac *user, int skip, int show) 2579xs_str *html_notifications(snac *user, int skip, int show)
2560{ 2580{
2581 const char *proxy = NULL;
2582
2583 if (xs_is_true(xs_dict_get(srv_config, "proxy_media")))
2584 proxy = user->actor;
2585
2561 xs *n_list = notify_list(user, skip, show); 2586 xs *n_list = notify_list(user, skip, show);
2562 xs *n_time = notify_check_time(user, 0); 2587 xs *n_time = notify_check_time(user, 0);
2563 2588
@@ -2616,7 +2641,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
2616 if (!valid_status(actor_get(actor_id, &actor))) 2641 if (!valid_status(actor_get(actor_id, &actor)))
2617 continue; 2642 continue;
2618 2643
2619 xs *a_name = actor_name(actor); 2644 xs *a_name = actor_name(actor, proxy);
2620 const char *label = type; 2645 const char *label = type;
2621 2646
2622 if (strcmp(type, "Create") == 0) 2647 if (strcmp(type, "Create") == 0)
@@ -2658,7 +2683,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
2658 xs_html_add(entry, 2683 xs_html_add(entry,
2659 xs_html_tag("div", 2684 xs_html_tag("div",
2660 xs_html_attr("class", "snac-post"), 2685 xs_html_attr("class", "snac-post"),
2661 html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0))); 2686 html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy)));
2662 } 2687 }
2663 else 2688 else
2664 if (strcmp(type, "Move") == 0) { 2689 if (strcmp(type, "Move") == 0) {
@@ -2672,7 +2697,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
2672 xs_html_add(entry, 2697 xs_html_add(entry,
2673 xs_html_tag("div", 2698 xs_html_tag("div",
2674 xs_html_attr("class", "snac-post"), 2699 xs_html_attr("class", "snac-post"),
2675 html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0))); 2700 html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy)));
2676 } 2701 }
2677 } 2702 }
2678 } 2703 }
@@ -2753,7 +2778,8 @@ xs_str *html_notifications(snac *user, int skip, int show)
2753 2778
2754 2779
2755int html_get_handler(const xs_dict *req, const char *q_path, 2780int html_get_handler(const xs_dict *req, const char *q_path,
2756 char **body, int *b_size, char **ctype, xs_str **etag) 2781 char **body, int *b_size, char **ctype,
2782 xs_str **etag, xs_str **last_modified)
2757{ 2783{
2758 const char *accept = xs_dict_get(req, "accept"); 2784 const char *accept = xs_dict_get(req, "accept");
2759 int status = HTTP_STATUS_NOT_FOUND; 2785 int status = HTTP_STATUS_NOT_FOUND;
@@ -2762,6 +2788,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2762 const char *p_path; 2788 const char *p_path;
2763 int cache = 1; 2789 int cache = 1;
2764 int save = 1; 2790 int save = 1;
2791 const char *proxy = NULL;
2765 const char *v; 2792 const char *v;
2766 2793
2767 xs *l = xs_split_n(q_path, "/", 2); 2794 xs *l = xs_split_n(q_path, "/", 2);
@@ -2788,6 +2815,9 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2788 return HTTP_STATUS_NOT_FOUND; 2815 return HTTP_STATUS_NOT_FOUND;
2789 } 2816 }
2790 2817
2818 if (xs_is_true(xs_dict_get(srv_config, "proxy_media")))
2819 proxy = snac.actor;
2820
2791 /* return the RSS if requested by Accept header */ 2821 /* return the RSS if requested by Accept header */
2792 if (accept != NULL) { 2822 if (accept != NULL) {
2793 if (xs_str_in(accept, "text/xml") != -1 || 2823 if (xs_str_in(accept, "text/xml") != -1 ||
@@ -3164,6 +3194,55 @@ int html_get_handler(const xs_dict *req, const char *q_path,
3164 snac_debug(&snac, 1, xs_fmt("serving RSS")); 3194 snac_debug(&snac, 1, xs_fmt("serving RSS"));
3165 } 3195 }
3166 else 3196 else
3197 if (xs_startswith(p_path, "proxy/") && proxy) { /** remote media by proxy **/
3198 if (!login(&snac, req)) {
3199 *body = xs_dup(uid);
3200 status = HTTP_STATUS_UNAUTHORIZED;
3201 }
3202 else {
3203 /* pick the raw path (including optional ? arguments) */
3204 const char *raw_path = xs_dict_get(req, "raw_path");
3205
3206 /* skip to where the proxy/ string starts */
3207 raw_path += xs_str_in(raw_path, "proxy/");
3208
3209 xs *url = xs_replace(raw_path, "proxy/", "https:/" "/");
3210 xs *hdrs = xs_dict_new();
3211
3212 hdrs = xs_dict_append(hdrs, "user-agent", USER_AGENT);
3213
3214 const char *ims = xs_dict_get(req, "if-modified-since");
3215 const char *inm = xs_dict_get(req, "if-none-match");
3216
3217 if (ims) hdrs = xs_dict_append(hdrs, "if-modified-since", ims);
3218 if (inm) hdrs = xs_dict_append(hdrs, "if-none-match", inm);
3219
3220 xs *rsp = xs_http_request("GET", url, hdrs,
3221 NULL, 0, &status, body, b_size, 0);
3222
3223 if (valid_status(status)) {
3224 const char *ct = xs_dict_get(rsp, "content-type");
3225 const char *lm = xs_dict_get(rsp, "last-modified");
3226 const char *et = xs_dict_get(rsp, "etag");
3227
3228 if (lm) *last_modified = xs_dup(lm);
3229 if (et) *etag = xs_dup(et);
3230
3231 /* find the content-type in the static mime types,
3232 and return that value instead of ct, which will
3233 be destroyed when out of scope */
3234 for (int n = 0; xs_mime_types[n]; n += 2) {
3235 if (strcmp(ct, xs_mime_types[n + 1]) == 0) {
3236 *ctype = (char *)xs_mime_types[n + 1];
3237 break;
3238 }
3239 }
3240 }
3241
3242 snac_debug(&snac, 1, xs_fmt("Proxy for %s %d", url, status));
3243 }
3244 }
3245 else
3167 status = HTTP_STATUS_NOT_FOUND; 3246 status = HTTP_STATUS_NOT_FOUND;
3168 3247
3169 user_free(&snac); 3248 user_free(&snac);