summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar shtrophic2025-01-24 20:38:26 +0100
committerGravatar shtrophic2025-01-24 20:38:26 +0100
commit85be7f36e12507cff7607df22ca14f8bfc00f6e2 (patch)
treee41bedab3e3b011c16d2ea6180926470cc8586aa
parentfix memory leak (diff)
parentVersion 2.69 RELEASED. (diff)
downloadsnac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.tar.gz
snac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.tar.xz
snac2-85be7f36e12507cff7607df22ca14f8bfc00f6e2.zip
Merge remote-tracking branch 'upstream/master' into curl-smtp
-rw-r--r--RELEASE_NOTES.md6
-rw-r--r--activitypub.c131
-rw-r--r--doc/snac.57
-rw-r--r--doc/snac.89
-rw-r--r--format.c47
-rw-r--r--html.c28
-rw-r--r--httpd.c2
-rw-r--r--mastoapi.c5
-rw-r--r--sandbox.c9
-rw-r--r--snac.h2
-rw-r--r--utils.c4
11 files changed, 197 insertions, 53 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index cc6866a..23a2a17 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,6 +1,6 @@
1# Release Notes 1# Release Notes
2 2
3## UNRELEASED 3## 2.69 "Yin/Yang of Love"
4 4
5Added support for subscribing to LitePub (Pleroma-style) Fediverse Relays like e.g. https://fedi-relay.gyptazy.com to improve federation. See `snac(8)` (the Administrator Manual) for more information on how to use this feature. 5Added support for subscribing to LitePub (Pleroma-style) Fediverse Relays like e.g. https://fedi-relay.gyptazy.com to improve federation. See `snac(8)` (the Administrator Manual) for more information on how to use this feature.
6 6
@@ -18,7 +18,7 @@ Fixed broken NetBSD build (missing dependency in Makefile.NetBSD).
18 18
19The user profile can now include longitude and latitude data for your current location. 19The user profile can now include longitude and latitude data for your current location.
20 20
21Mastodon API: implemented limit= on notification fetches (contributed by nowster), implemented faster min_id handling (contributed by nowster), obey the quiet public visibility set for posts. 21Mastodon API: implemented limit= on notification fetches (contributed by nowster), implemented faster min_id handling (contributed by nowster), obey the quiet public visibility set for posts, other timeline improvements (contributed by nowster).
22 22
23Reduced RSA key size for new users from 4096 to 2048. This will be friendlier to smaller machines, and everybody else out there is using 2048. 23Reduced RSA key size for new users from 4096 to 2048. This will be friendlier to smaller machines, and everybody else out there is using 2048.
24 24
@@ -26,6 +26,8 @@ If the `SNAC_BASEDIR` environment variable is defined and set to the base direct
26 26
27Fixed a bug in the generation of the top page (contributed by an-im-dugud). 27Fixed a bug in the generation of the top page (contributed by an-im-dugud).
28 28
29Added support for Markdown headers and underlining (contributed by an-im-dugud).
30
29## 2.68 31## 2.68
30 32
31Fixed regression in link verification code (contributed by nowster). 33Fixed regression in link verification code (contributed by nowster).
diff --git a/activitypub.c b/activitypub.c
index 2b10435..4cb779a 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -587,6 +587,70 @@ int is_msg_from_private_user(const xs_dict *msg)
587} 587}
588 588
589 589
590int followed_hashtag_check(snac *user, const xs_dict *msg)
591/* returns true if this message contains a hashtag followed by me */
592{
593 const xs_list *fw_tags = xs_dict_get(user->config, "followed_hashtags");
594
595 if (xs_is_list(fw_tags)) {
596 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
597
598 if (xs_is_list(tags_in_msg)) {
599 const xs_dict *te;
600
601 /* iterate the tags in the message */
602 xs_list_foreach(tags_in_msg, te) {
603 if (xs_is_dict(te)) {
604 const char *type = xs_dict_get(te, "type");
605 const char *name = xs_dict_get(te, "name");
606
607 if (xs_is_string(type) && xs_is_string(name)) {
608 if (strcmp(type, "Hashtag") == 0) {
609 xs *lc_name = xs_utf8_to_lower(name);
610
611 if (xs_list_in(fw_tags, lc_name) != -1)
612 return 1;
613 }
614 }
615 }
616 }
617 }
618 }
619
620 return 0;
621}
622
623
624void followed_hashtag_distribute(const xs_dict *msg)
625/* distribute this post to all users following the included hashtags */
626{
627 const char *id = xs_dict_get(msg, "id");
628 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
629
630 if (!xs_is_string(id) || !xs_is_list(tags_in_msg) || xs_list_len(tags_in_msg) == 0)
631 return;
632
633 srv_debug(1, xs_fmt("followed_hashtag_distribute check for %s", id));
634
635 xs *users = user_list();
636 const char *uid;
637
638 xs_list_foreach(users, uid) {
639 snac user;
640
641 if (user_open(&user, uid)) {
642 if (followed_hashtag_check(&user, msg)) {
643 timeline_add(&user, id, msg);
644
645 snac_log(&user, xs_fmt("followed hashtag in %s", id));
646 }
647
648 user_free(&user);
649 }
650 }
651}
652
653
590int is_msg_for_me(snac *snac, const xs_dict *c_msg) 654int is_msg_for_me(snac *snac, const xs_dict *c_msg)
591/* checks if this message is for me */ 655/* checks if this message is for me */
592{ 656{
@@ -602,19 +666,32 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
602 if (xs_match(type, "Like|Announce|EmojiReact")) { 666 if (xs_match(type, "Like|Announce|EmojiReact")) {
603 const char *object = xs_dict_get(c_msg, "object"); 667 const char *object = xs_dict_get(c_msg, "object");
604 668
605 if (xs_type(object) == XSTYPE_DICT) 669 if (xs_is_dict(object))
606 object = xs_dict_get(object, "id"); 670 object = xs_dict_get(object, "id");
607 671
608 /* bad object id? reject */ 672 /* bad object id? reject */
609 if (xs_type(object) != XSTYPE_STRING) 673 if (!xs_is_string(object))
610 return 0; 674 return 0;
611 675
612 /* if it's about one of our posts, accept it */ 676 /* if it's about one of our posts, accept it */
613 if (xs_startswith(object, snac->actor)) 677 if (xs_startswith(object, snac->actor))
614 return 2; 678 return 2;
615 679
616 /* if it's by someone we don't follow, reject */ 680 /* if it's by someone we follow, accept it */
617 return following_check(snac, actor); 681 if (following_check(snac, actor))
682 return 1;
683
684 /* do we follow any hashtag? */
685 if (xs_is_list(xs_dict_get(snac->config, "followed_hashtags"))) {
686 xs *obj = NULL;
687
688 /* if the admired object contains any followed hashtag, accept it */
689 if (valid_status(object_get(object, &obj)) &&
690 followed_hashtag_check(snac, obj))
691 return 7;
692 }
693
694 return 0;
618 } 695 }
619 696
620 /* if it's an Undo, it must be from someone related to us */ 697 /* if it's an Undo, it must be from someone related to us */
@@ -708,30 +785,8 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
708 } 785 }
709 786
710 /* does this message contain a tag we are following? */ 787 /* does this message contain a tag we are following? */
711 const xs_list *fw_tags = xs_dict_get(snac->config, "followed_hashtags"); 788 if (pub_msg && followed_hashtag_check(snac, msg))
712 if (pub_msg && xs_type(fw_tags) == XSTYPE_LIST) { 789 return 7;
713 const xs_list *tags_in_msg = xs_dict_get(msg, "tag");
714 if (xs_type(tags_in_msg) == XSTYPE_LIST) {
715 const xs_dict *te;
716
717 /* iterate the tags in the message */
718 xs_list_foreach(tags_in_msg, te) {
719 if (xs_type(te) == XSTYPE_DICT) {
720 const char *type = xs_dict_get(te, "type");
721 const char *name = xs_dict_get(te, "name");
722
723 if (xs_type(type) == XSTYPE_STRING && xs_type(name) == XSTYPE_STRING) {
724 if (strcmp(type, "Hashtag") == 0) {
725 xs *lc_name = xs_utf8_to_lower(name);
726
727 if (xs_list_in(fw_tags, lc_name) != -1)
728 return 7;
729 }
730 }
731 }
732 }
733 }
734 }
735 790
736 return 0; 791 return 0;
737} 792}
@@ -2277,15 +2332,23 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2277 xs *who_o = NULL; 2332 xs *who_o = NULL;
2278 2333
2279 if (valid_status(actor_request(snac, who, &who_o))) { 2334 if (valid_status(actor_request(snac, who, &who_o))) {
2280 if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED) 2335 /* don't account as such announces by our own relay */
2281 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); 2336 xs *this_relay = xs_fmt("%s/relay", srv_baseurl);
2282 else 2337
2283 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", 2338 if (strcmp(actor, this_relay) != 0) {
2284 actor, object)); 2339 if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED)
2340 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object));
2341 else
2342 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s",
2343 actor, object));
2344 }
2285 2345
2286 /* distribute the post with the actor as 'proxy' */ 2346 /* distribute the post with the actor as 'proxy' */
2287 list_distribute(snac, actor, a_msg); 2347 list_distribute(snac, actor, a_msg);
2288 2348
2349 /* distribute the post to users following these hashtags */
2350 followed_hashtag_distribute(a_msg);
2351
2289 do_notify = 1; 2352 do_notify = 1;
2290 } 2353 }
2291 else 2354 else
@@ -2300,7 +2363,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2300 } 2363 }
2301 else 2364 else
2302 if (strcmp(type, "Update") == 0) { /** **/ 2365 if (strcmp(type, "Update") == 0) { /** **/
2303 if (xs_match(utype, "Person|Service")) { /** **/ 2366 if (xs_match(utype, "Person|Service|Application")) { /** **/
2304 actor_add(actor, xs_dict_get(msg, "object")); 2367 actor_add(actor, xs_dict_get(msg, "object"));
2305 timeline_touch(snac); 2368 timeline_touch(snac);
2306 2369
diff --git a/doc/snac.5 b/doc/snac.5
index be7bfd7..3550995 100644
--- a/doc/snac.5
+++ b/doc/snac.5
@@ -24,9 +24,11 @@ A special subset of Markdown is allowed, including:
24.It bold 24.It bold
25**text between two pairs of asterisks** 25**text between two pairs of asterisks**
26.It italic 26.It italic
27*text between a pair of asterisks* 27*text between a pair of asterisks* or _between a pair of underscores_
28.It strikethrough text 28.It strikethrough text
29~~text between a pair of tildes~~ 29~~text between a pair of tildes~~
30.It underlined text
31__text between two pairs of underscores__
30.It code 32.It code
31Text `between backticks` is formatted as code. 33Text `between backticks` is formatted as code.
32.Bd -literal 34.Bd -literal
@@ -53,6 +55,9 @@ Horizonal rules can be inserted by typing three minus symbols
53alone in a line. 55alone in a line.
54.It quoted text 56.It quoted text
55Lines starting with >. 57Lines starting with >.
58.It headers
59One, two or three # at the beginning of a line plus a space plus
60some text are converted to HTML headers.
56.It user mentions 61.It user mentions
57Strings in the format @user@host are requested using the Webfinger 62Strings in the format @user@host are requested using the Webfinger
58protocol and converted to links and mentions if something reasonable 63protocol and converted to links and mentions if something reasonable
diff --git a/doc/snac.8 b/doc/snac.8
index c0e1af5..e228495 100644
--- a/doc/snac.8
+++ b/doc/snac.8
@@ -591,17 +591,20 @@ instance can subscribe to LitePub (Pleroma-style) Fediverse Relays. Doing this i
591visibility and allows following hashtags. To do this, you must create a special user named 591visibility and allows following hashtags. To do this, you must create a special user named
592relay and, from it, follow the relay actor(s) like you do with regular actor URLs. This 592relay and, from it, follow the relay actor(s) like you do with regular actor URLs. This
593special user will start receiving boosts from the relay server of posts from other instances 593special user will start receiving boosts from the relay server of posts from other instances
594also following it. It any other user of the same 594also following it. If any other user of the same
595.Nm 595.Nm
596instance follows any of the hashtags included in these boosted posts coming from the relay, 596instance follows any of the hashtags included in these boosted posts coming from the relay,
597they will received as if they were for them. 597they will be received as if they were for them.
598.Pp 598.Pp
599Example: 599Example:
600.Bd -literal -offset indent 600.Bd -literal -offset indent
601snac adduser $SNAC_BASEDIR relay # only needed once 601snac adduser $SNAC_BASEDIR relay # only needed once
602snac follow $SNAC_BASEDIR relay https://fedi-relay.gyptazy.com/actor 602snac follow $SNAC_BASEDIR relay https://relay.example.com/actor
603.Ed 603.Ed
604.Pp 604.Pp
605Users on your instance do NOT need to follow the local relay user to benefit from following
606hashtags.
607.Pp
605Please take note that subscribing to relays can increase the traffic towards your instance 608Please take note that subscribing to relays can increase the traffic towards your instance
606significantly. In any case, lowering the "Maximum days to keep posts" value for the relay 609significantly. In any case, lowering the "Maximum days to keep posts" value for the relay
607special user is recommended (e.g. setting to just 1 day). 610special user is recommended (e.g. setting to just 1 day).
diff --git a/format.c b/format.c
index 52ed3ec..e5934b8 100644
--- a/format.c
+++ b/format.c
@@ -92,6 +92,8 @@ static xs_str *format_line(const char *line, xs_list **attach)
92 "`[^`]+`" "|" 92 "`[^`]+`" "|"
93 "~~[^~]+~~" "|" 93 "~~[^~]+~~" "|"
94 "\\*\\*?\\*?[^\\*]+\\*?\\*?\\*" "|" 94 "\\*\\*?\\*?[^\\*]+\\*?\\*?\\*" "|"
95 "_[^_]+_" "|" //anzu
96 "__[^_]+__" "|" //anzu
95 "!\\[[^]]+\\]\\([^\\)]+\\)" "|" 97 "!\\[[^]]+\\]\\([^\\)]+\\)" "|"
96 "\\[[^]]+\\]\\([^\\)]+\\)" "|" 98 "\\[[^]]+\\]\\([^\\)]+\\)" "|"
97 "[a-z]+:/" "/[^[:space:]]+" "|" 99 "[a-z]+:/" "/[^[:space:]]+" "|"
@@ -127,6 +129,20 @@ static xs_str *format_line(const char *line, xs_list **attach)
127 xs *s2 = xs_fmt("<i>%s</i>", s1); 129 xs *s2 = xs_fmt("<i>%s</i>", s1);
128 s = xs_str_cat(s, s2); 130 s = xs_str_cat(s, s2);
129 } 131 }
132 //anzu - begin
133 else
134 if (xs_startswith(v, "__")) {
135 xs *s1 = xs_strip_chars_i(xs_dup(v), "_");
136 xs *s2 = xs_fmt("<u>%s</u>", s1);
137 s = xs_str_cat(s, s2);
138 }
139 else
140 if (xs_startswith(v, "_")) {
141 xs *s1 = xs_strip_chars_i(xs_dup(v), "_");
142 xs *s2 = xs_fmt("<i>%s</i>", s1);
143 s = xs_str_cat(s, s2);
144 }
145 //anzu - end
130 else 146 else
131 if (xs_startswith(v, "~~")) { 147 if (xs_startswith(v, "~~")) {
132 xs *s1 = xs_strip_chars_i(xs_dup(v), "~"); 148 xs *s1 = xs_strip_chars_i(xs_dup(v), "~");
@@ -303,6 +319,31 @@ xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag
303 continue; 319 continue;
304 } 320 }
305 321
322 //anzu - begin
323 // h1 reserved for snac?
324 if (xs_startswith(ss, "# ")) {
325 ss = xs_strip_i(xs_crop_i(ss, 2, 0));
326 s = xs_str_cat(s, "<h2>");
327 s = xs_str_cat(s, ss);
328 s = xs_str_cat(s, "</h2>");
329 continue;
330 }
331 if (xs_startswith(ss, "## ")) {
332 ss = xs_strip_i(xs_crop_i(ss, 3, 0));
333 s = xs_str_cat(s, "<h2>");
334 s = xs_str_cat(s, ss);
335 s = xs_str_cat(s, "</h2>");
336 continue;
337 }
338 if (xs_startswith(ss, "### ")) {
339 ss = xs_strip_i(xs_crop_i(ss, 4, 0));
340 s = xs_str_cat(s, "<h3>");
341 s = xs_str_cat(s, ss);
342 s = xs_str_cat(s, "</h3>");
343 continue;
344 }
345 //anzu - end
346
306 if (xs_startswith(ss, ">")) { 347 if (xs_startswith(ss, ">")) {
307 /* delete the > and subsequent spaces */ 348 /* delete the > and subsequent spaces */
308 ss = xs_strip_i(xs_crop_i(ss, 1, 0)); 349 ss = xs_strip_i(xs_crop_i(ss, 1, 0));
@@ -336,6 +377,8 @@ xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag
336 s = xs_replace_i(s, "<br><br><blockquote>", "<br><blockquote>"); 377 s = xs_replace_i(s, "<br><br><blockquote>", "<br><blockquote>");
337 s = xs_replace_i(s, "</blockquote><br>", "</blockquote>"); 378 s = xs_replace_i(s, "</blockquote><br>", "</blockquote>");
338 s = xs_replace_i(s, "</pre><br>", "</pre>"); 379 s = xs_replace_i(s, "</pre><br>", "</pre>");
380 s = xs_replace_i(s, "</h2><br>", "</h2>"); //anzu ???
381 s = xs_replace_i(s, "</h3><br>", "</h3>"); //anzu ???
339 382
340 { 383 {
341 /* traditional emoticons */ 384 /* traditional emoticons */
@@ -378,7 +421,9 @@ xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag
378 421
379const char *valid_tags[] = { 422const char *valid_tags[] = {
380 "a", "p", "br", "br/", "blockquote", "ul", "ol", "li", "cite", "small", 423 "a", "p", "br", "br/", "blockquote", "ul", "ol", "li", "cite", "small",
381 "span", "i", "b", "u", "s", "pre", "code", "em", "strong", "hr", "img", "del", "bdi", NULL 424 "span", "i", "b", "u", "s", "pre", "code", "em", "strong", "hr", "img", "del", "bdi",
425 "h2","h3", //anzu
426 NULL
382}; 427};
383 428
384xs_str *sanitize(const char *content) 429xs_str *sanitize(const char *content)
diff --git a/html.c b/html.c
index 2a02d18..3fd1e4b 100644
--- a/html.c
+++ b/html.c
@@ -1855,13 +1855,15 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
1855 } 1855 }
1856 } 1856 }
1857 } 1857 }
1858 else
1859 if (strcmp(type, "Note") == 0) {
1860 if (level == 0) {
1861 /* is the parent not here? */
1862 const char *parent = get_in_reply_to(msg);
1863 1858
1864 if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { 1859 if (user && strcmp(type, "Note") == 0) {
1860 /* is the parent not here? */
1861 const char *parent = get_in_reply_to(msg);
1862
1863 if (!xs_is_null(parent) && *parent) {
1864 xs *md5 = xs_md5_hex(parent, strlen(parent));
1865
1866 if (!timeline_here(user, md5)) {
1865 xs_html_add(post_header, 1867 xs_html_add(post_header,
1866 xs_html_tag("div", 1868 xs_html_tag("div",
1867 xs_html_attr("class", "snac-origin"), 1869 xs_html_attr("class", "snac-origin"),
@@ -2965,9 +2967,12 @@ xs_str *html_notifications(snac *user, int skip, int show)
2965 xs_html_attr("class", "snac-posts")); 2967 xs_html_attr("class", "snac-posts"));
2966 xs_html_add(body, posts); 2968 xs_html_add(body, posts);
2967 2969
2968 xs_list *p = n_list; 2970 xs_set rep;
2971 xs_set_init(&rep);
2972
2969 const xs_str *v; 2973 const xs_str *v;
2970 while (xs_list_iter(&p, &v)) { 2974
2975 xs_list_foreach(n_list, v) {
2971 xs *noti = notify_get(user, v); 2976 xs *noti = notify_get(user, v);
2972 2977
2973 if (noti == NULL) 2978 if (noti == NULL)
@@ -2988,6 +2993,11 @@ xs_str *html_notifications(snac *user, int skip, int show)
2988 2993
2989 object_get(id, &obj); 2994 object_get(id, &obj);
2990 2995
2996 const char *msg_id = NULL;
2997
2998 if (xs_is_dict(obj) && (msg_id = xs_dict_get(obj, "id")) && xs_set_add(&rep, msg_id) != 1)
2999 continue;
3000
2991 const char *actor_id = xs_dict_get(noti, "actor"); 3001 const char *actor_id = xs_dict_get(noti, "actor");
2992 xs *actor = NULL; 3002 xs *actor = NULL;
2993 3003
@@ -3101,6 +3111,8 @@ xs_str *html_notifications(snac *user, int skip, int show)
3101 } 3111 }
3102 } 3112 }
3103 3113
3114 xs_set_free(&rep);
3115
3104 if (noti_new == NULL && noti_seen == NULL) 3116 if (noti_new == NULL && noti_seen == NULL)
3105 xs_html_add(body, 3117 xs_html_add(body,
3106 xs_html_tag("h2", 3118 xs_html_tag("h2",
diff --git a/httpd.c b/httpd.c
index c13402b..e0a36b6 100644
--- a/httpd.c
+++ b/httpd.c
@@ -138,7 +138,7 @@ static xs_str *greeting_html(void)
138 while (xs_list_iter(&p, &uid)) { 138 while (xs_list_iter(&p, &uid)) {
139 snac user; 139 snac user;
140 140
141 if (user_open(&user, uid)) { 141 if (strcmp(uid, "relay") && user_open(&user, uid)) {
142 xs_html_add(ul, 142 xs_html_add(ul,
143 xs_html_tag("li", 143 xs_html_tag("li",
144 xs_html_tag("a", 144 xs_html_tag("a",
diff --git a/mastoapi.c b/mastoapi.c
index 3250a20..54b4333 100644
--- a/mastoapi.c
+++ b/mastoapi.c
@@ -1453,7 +1453,10 @@ xs_list *mastoapi_timeline(snac *user, const xs_dict *args, const char *index_fn
1453 xs *st = mastoapi_status(user, msg); 1453 xs *st = mastoapi_status(user, msg);
1454 1454
1455 if (st != NULL) { 1455 if (st != NULL) {
1456 out = xs_list_append(out, st); 1456 if (ascending)
1457 out = xs_list_insert(out, 0, st);
1458 else
1459 out = xs_list_append(out, st);
1457 cnt++; 1460 cnt++;
1458 } 1461 }
1459 1462
diff --git a/sandbox.c b/sandbox.c
index 875ae4e..5046104 100644
--- a/sandbox.c
+++ b/sandbox.c
@@ -63,15 +63,22 @@ LL_BEGIN(sbox_enter_linux_, const char* basedir, const char *address, int smtp_p
63 LANDLOCK_ACCESS_FS_REFER_COMPAT, 63 LANDLOCK_ACCESS_FS_REFER_COMPAT,
64 s = LANDLOCK_ACCESS_FS_MAKE_SOCK, 64 s = LANDLOCK_ACCESS_FS_MAKE_SOCK,
65 x = LANDLOCK_ACCESS_FS_EXECUTE; 65 x = LANDLOCK_ACCESS_FS_EXECUTE;
66 char *resolved_path = NULL;
66 67
67 LL_PATH(basedir, rf|rd|w|c); 68 LL_PATH(basedir, rf|rd|w|c);
68 LL_PATH("/tmp", rf|rd|w|c); 69 LL_PATH("/tmp", rf|rd|w|c);
69#ifndef WITHOUT_SHM 70#ifndef WITHOUT_SHM
70 LL_PATH("/dev/shm", rf|w|c ); 71 LL_PATH("/dev/shm", rf|w|c );
71#endif 72#endif
73 LL_PATH("/dev/urandom", rf );
72 LL_PATH("/etc/resolv.conf", rf ); 74 LL_PATH("/etc/resolv.conf", rf );
73 LL_PATH("/etc/hosts", rf ); 75 LL_PATH("/etc/hosts", rf );
74 LL_PATH("/etc/ssl", rf ); 76 LL_PATH("/etc/ssl", rf|rd );
77 if ((resolved_path = realpath("/etc/ssl/cert.pem", NULL))) {
78 /* some distros like cert.pem to be a symlink */
79 LL_PATH(resolved_path, rf );
80 free(resolved_path);
81 }
75 LL_PATH("/usr/share/zoneinfo", rf ); 82 LL_PATH("/usr/share/zoneinfo", rf );
76 83
77 if (mtime("/etc/pki") > 0) 84 if (mtime("/etc/pki") > 0)
diff --git a/snac.h b/snac.h
index 3db7b63..f2220a3 100644
--- a/snac.h
+++ b/snac.h
@@ -1,7 +1,7 @@
1/* snac - A simple, minimalistic ActivityPub instance */ 1/* snac - A simple, minimalistic ActivityPub instance */
2/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ 2/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */
3 3
4#define VERSION "2.69-dev" 4#define VERSION "2.69"
5 5
6#define USER_AGENT "snac/" VERSION 6#define USER_AGENT "snac/" VERSION
7 7
diff --git a/utils.c b/utils.c
index 3b0a78f..faf6d12 100644
--- a/utils.c
+++ b/utils.c
@@ -318,6 +318,10 @@ int adduser(const char *uid)
318 mkdirx(d); 318 mkdirx(d);
319 } 319 }
320 320
321 /* add a specially short data retention time for the relay */
322 if (strcmp(uid, "relay") == 0)
323 config = xs_dict_set(config, "purge_days", xs_stock(1));
324
321 xs *cfn = xs_fmt("%s/user.json", basedir); 325 xs *cfn = xs_fmt("%s/user.json", basedir);
322 326
323 if ((f = fopen(cfn, "w")) == NULL) { 327 if ((f = fopen(cfn, "w")) == NULL) {