diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | Makefile.NetBSD | 2 | ||||
| -rw-r--r-- | TODO.md | 4 | ||||
| -rw-r--r-- | activitypub.c | 2 | ||||
| -rw-r--r-- | data.c | 16 | ||||
| -rw-r--r-- | html.c | 135 | ||||
| -rw-r--r-- | httpd.c | 5 | ||||
| -rw-r--r-- | snac.h | 6 | ||||
| -rw-r--r-- | xs_fcgi.h | 2 | ||||
| -rw-r--r-- | xs_httpd.h | 1 | ||||
| -rw-r--r-- | xs_url.h | 2 |
11 files changed, 142 insertions, 35 deletions
| @@ -42,7 +42,7 @@ data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \ | |||
| 42 | format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \ | 42 | format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \ |
| 43 | xs_time.h snac.h http_codes.h | 43 | xs_time.h snac.h http_codes.h |
| 44 | html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ | 44 | html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ |
| 45 | xs_time.h xs_mime.h xs_match.h xs_html.h snac.h http_codes.h | 45 | xs_time.h xs_mime.h xs_match.h xs_html.h xs_curl.h snac.h http_codes.h |
| 46 | http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ | 46 | http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ |
| 47 | snac.h http_codes.h | 47 | snac.h http_codes.h |
| 48 | httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ | 48 | httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ |
diff --git a/Makefile.NetBSD b/Makefile.NetBSD index 8883949..f4a2f55 100644 --- a/Makefile.NetBSD +++ b/Makefile.NetBSD | |||
| @@ -44,7 +44,7 @@ data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \ | |||
| 44 | format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \ | 44 | format.o: format.c xs.h xs_regex.h xs_mime.h xs_html.h xs_json.h \ |
| 45 | xs_time.h snac.h http_codes.h | 45 | xs_time.h snac.h http_codes.h |
| 46 | html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ | 46 | html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h xs_set.h xs_openssl.h \ |
| 47 | xs_time.h xs_mime.h xs_match.h xs_html.h snac.h http_codes.h | 47 | xs_time.h xs_mime.h xs_match.h xs_html.h xs_curl.h snac.h http_codes.h |
| 48 | http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ | 48 | http.o: http.c xs.h xs_io.h xs_openssl.h xs_curl.h xs_time.h xs_json.h \ |
| 49 | snac.h http_codes.h | 49 | snac.h http_codes.h |
| 50 | httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ | 50 | httpd.o: httpd.c xs.h xs_io.h xs_json.h xs_socket.h xs_unix_socket.h \ |
| @@ -348,4 +348,6 @@ Don't show image attachments which URLs are already in the post content (2.62, 2 | |||
| 348 | 348 | ||
| 349 | Add a user option to always collapse first level threads (2.62, 2024-10-28T14:50:42+0100). | 349 | Add a user option to always collapse first level threads (2.62, 2024-10-28T14:50:42+0100). |
| 350 | 350 | ||
| 351 | Add a 'disable_block_notifications' flag to server settings (2.62, 2024-10-30T16:58:16+0100). | 351 | Add a `disable_block_notifications` flag to server settings (2.62, 2024-10-30T16:58:16+0100). |
| 352 | |||
| 353 | The `strict_public_timelines` is broken, as it also applies to the private timeline (2.63, 2024-11-07T21:44:52+0100). | ||
diff --git a/activitypub.c b/activitypub.c index 96c3038..0b2fc6a 100644 --- a/activitypub.c +++ b/activitypub.c | |||
| @@ -202,7 +202,7 @@ xs_list *get_attachments(const xs_dict *msg) | |||
| 202 | else | 202 | else |
| 203 | attach = xs_dup(p); | 203 | attach = xs_dup(p); |
| 204 | 204 | ||
| 205 | if (xs_type(attach) == XSTYPE_LIST) { | 205 | if (xs_type(attach) == XSTYPE_LIST && xs_list_len(attach) == 0) { |
| 206 | /* does the message have an image? */ | 206 | /* does the message have an image? */ |
| 207 | const xs_dict *d = xs_dict_get(msg, "image"); | 207 | const xs_dict *d = xs_dict_get(msg, "image"); |
| 208 | if (xs_type(d) == XSTYPE_DICT) { | 208 | if (xs_type(d) == XSTYPE_DICT) { |
| @@ -3650,3 +3650,19 @@ t_announcement *announcement(const double after) | |||
| 3650 | 3650 | ||
| 3651 | return NULL; | 3651 | return NULL; |
| 3652 | } | 3652 | } |
| 3653 | |||
| 3654 | |||
| 3655 | xs_str *make_url(const char *href, const char *proxy) | ||
| 3656 | /* makes an URL, possibly including proxying */ | ||
| 3657 | { | ||
| 3658 | xs_str *url = NULL; | ||
| 3659 | |||
| 3660 | if (proxy && !xs_startswith(href, srv_baseurl)) { | ||
| 3661 | xs *p = xs_str_cat(xs_dup(proxy), "/proxy/"); | ||
| 3662 | url = xs_replace(href, "https:/" "/", p); | ||
| 3663 | } | ||
| 3664 | else | ||
| 3665 | url = xs_dup(href); | ||
| 3666 | |||
| 3667 | return url; | ||
| 3668 | } | ||
| @@ -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 | ||
| 44 | xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems) | 45 | xs_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 | ||
| 88 | xs_str *actor_name(xs_dict *actor) | 91 | xs_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 | ||
| 103 | xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | 106 | xs_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 | ||
| 247 | xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg) | 250 | xs_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 | ||
| 682 | static xs_html *html_user_body(snac *user, int read_only) | 685 | static 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 | ||
| 2414 | xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t) | 2428 | xs_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 | ||
| 2541 | xs_str *html_people(snac *user) | 2556 | xs_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 | ||
| 2559 | xs_str *html_notifications(snac *user, int skip, int show) | 2579 | xs_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 | ||
| 2755 | int html_get_handler(const xs_dict *req, const char *q_path, | 2780 | int 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); |
| @@ -278,6 +278,7 @@ void httpd_connection(FILE *f) | |||
| 278 | xs *q_path = NULL; | 278 | xs *q_path = NULL; |
| 279 | xs *payload = NULL; | 279 | xs *payload = NULL; |
| 280 | xs *etag = NULL; | 280 | xs *etag = NULL; |
| 281 | xs *last_modified = NULL; | ||
| 281 | int p_size = 0; | 282 | int p_size = 0; |
| 282 | const char *p; | 283 | const char *p; |
| 283 | int fcgi_id; | 284 | int fcgi_id; |
| @@ -329,7 +330,7 @@ void httpd_connection(FILE *f) | |||
| 329 | #endif /* NO_MASTODON_API */ | 330 | #endif /* NO_MASTODON_API */ |
| 330 | 331 | ||
| 331 | if (status == 0) | 332 | if (status == 0) |
| 332 | status = html_get_handler(req, q_path, &body, &b_size, &ctype, &etag); | 333 | status = html_get_handler(req, q_path, &body, &b_size, &ctype, &etag, &last_modified); |
| 333 | } | 334 | } |
| 334 | else | 335 | else |
| 335 | if (strcmp(method, "POST") == 0) { | 336 | if (strcmp(method, "POST") == 0) { |
| @@ -423,6 +424,8 @@ void httpd_connection(FILE *f) | |||
| 423 | 424 | ||
| 424 | if (!xs_is_null(etag)) | 425 | if (!xs_is_null(etag)) |
| 425 | headers = xs_dict_append(headers, "etag", etag); | 426 | headers = xs_dict_append(headers, "etag", etag); |
| 427 | if (!xs_is_null(last_modified)) | ||
| 428 | headers = xs_dict_append(headers, "last-modified", last_modified); | ||
| 426 | 429 | ||
| 427 | /* if there are any additional headers, add them */ | 430 | /* if there are any additional headers, add them */ |
| 428 | const xs_dict *more_headers = xs_dict_get(srv_config, "http_headers"); | 431 | const xs_dict *more_headers = xs_dict_get(srv_config, "http_headers"); |
| @@ -349,7 +349,9 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 349 | const char *title, const char *page, int utl, const char *error); | 349 | const char *title, const char *page, int utl, const char *error); |
| 350 | 350 | ||
| 351 | int html_get_handler(const xs_dict *req, const char *q_path, | 351 | int html_get_handler(const xs_dict *req, const char *q_path, |
| 352 | char **body, int *b_size, char **ctype, xs_str **etag); | 352 | char **body, int *b_size, char **ctype, |
| 353 | xs_str **etag, xs_str **last_modified); | ||
| 354 | |||
| 353 | int html_post_handler(const xs_dict *req, const char *q_path, | 355 | int html_post_handler(const xs_dict *req, const char *q_path, |
| 354 | char *payload, int p_size, | 356 | char *payload, int p_size, |
| 355 | char **body, int *b_size, char **ctype); | 357 | char **body, int *b_size, char **ctype); |
| @@ -407,3 +409,5 @@ typedef struct { | |||
| 407 | char *text; | 409 | char *text; |
| 408 | } t_announcement; | 410 | } t_announcement; |
| 409 | t_announcement *announcement(double after); | 411 | t_announcement *announcement(double after); |
| 412 | |||
| 413 | xs_str *make_url(const char *href, const char *proxy); | ||
| @@ -179,6 +179,8 @@ xs_dict *xs_fcgi_request(FILE *f, xs_str **payload, int *p_size, int *fcgi_id) | |||
| 179 | req = xs_dict_append(req, "method", v); | 179 | req = xs_dict_append(req, "method", v); |
| 180 | else | 180 | else |
| 181 | if (strcmp(k, "REQUEST_URI") == 0) { | 181 | if (strcmp(k, "REQUEST_URI") == 0) { |
| 182 | req = xs_dict_append(req, "raw_path", v); | ||
| 183 | |||
| 182 | xs *pnv = xs_split_n(v, "?", 1); | 184 | xs *pnv = xs_split_n(v, "?", 1); |
| 183 | 185 | ||
| 184 | /* store the path */ | 186 | /* store the path */ |
| @@ -32,6 +32,7 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size) | |||
| 32 | xs_dict *req = xs_dict_new(); | 32 | xs_dict *req = xs_dict_new(); |
| 33 | 33 | ||
| 34 | req = xs_dict_append(req, "method", xs_list_get(l2, 0)); | 34 | req = xs_dict_append(req, "method", xs_list_get(l2, 0)); |
| 35 | req = xs_dict_append(req, "raw_path", xs_list_get(l2, 1)); | ||
| 35 | req = xs_dict_append(req, "proto", xs_list_get(l2, 2)); | 36 | req = xs_dict_append(req, "proto", xs_list_get(l2, 2)); |
| 36 | 37 | ||
| 37 | { | 38 | { |
| @@ -196,7 +196,7 @@ xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *hea | |||
| 196 | if (fn != NULL) { | 196 | if (fn != NULL) { |
| 197 | /* p_var value is a list */ | 197 | /* p_var value is a list */ |
| 198 | /* if filename has no extension and content-type is image, attach extension to the filename */ | 198 | /* if filename has no extension and content-type is image, attach extension to the filename */ |
| 199 | if (strchr(fn, '.') == NULL && xs_startswith(ct, "image/")) { | 199 | if (strchr(fn, '.') == NULL && ct && xs_startswith(ct, "image/")) { |
| 200 | char *ext = strchr(ct, '/'); | 200 | char *ext = strchr(ct, '/'); |
| 201 | ext++; | 201 | ext++; |
| 202 | fn = xs_str_cat(xs_str_new(""), fn, ".", ext); | 202 | fn = xs_str_cat(xs_str_new(""), fn, ".", ext); |