From 6097ba55cf96444aac7fb9b74295722e8e5c3810 Mon Sep 17 00:00:00 2001 From: default Date: Sun, 26 Jan 2025 17:55:36 +0100 Subject: New command-line option 'unmute'. --- main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main.c b/main.c index a57adb5..347c495 100644 --- a/main.c +++ b/main.c @@ -49,6 +49,7 @@ int usage(void) printf("unblock {basedir} {instance_url} Unblocks a full instance\n"); printf("limit {basedir} {uid} {actor} Limits an actor (drops their announces)\n"); printf("unlimit {basedir} {uid} {actor} Unlimits an actor\n"); + printf("unmute {basedir} {uid} {actor} Unmutes a previously muted actor\n"); printf("verify_links {basedir} {uid} Verifies a user's links (in the metadata)\n"); printf("search {basedir} {uid} {regex} Searches posts by content\n"); printf("export_csv {basedir} {uid} Exports data as CSV files\n"); @@ -446,6 +447,18 @@ int main(int argc, char *argv[]) return 0; } + if (strcmp(cmd, "unmute") == 0) { /** **/ + if (is_muted(&snac, url)) { + unmute(&snac, url); + + printf("%s unmuted\n", url); + } + else + printf("%s actor is not muted\n", url); + + return 0; + } + if (strcmp(cmd, "search") == 0) { /** **/ int to; -- cgit v1.2.3 From 82bcc4b465f73a5d1f2eebcf3813452bc1c37fbd Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 16:59:08 +0100 Subject: Minor optimization in timeline retrieving. Functions now receive an optional int *more, set to 1 if there are more than the 'show' requested. --- activitypub.c | 2 +- data.c | 24 ++++++++++++++++++------ html.c | 25 +++++++++++-------------- mastoapi.c | 2 +- snac.h | 4 ++-- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/activitypub.c b/activitypub.c index cade0d9..bcb733a 100644 --- a/activitypub.c +++ b/activitypub.c @@ -3081,7 +3081,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20")); /* get the public outbox or the pinned list */ - xs *elems = *p_path == 'o' ? timeline_simple_list(&snac, "public", 0, cnt) : pinned_list(&snac); + xs *elems = *p_path == 'o' ? timeline_simple_list(&snac, "public", 0, cnt, NULL) : pinned_list(&snac); xs_list_foreach(elems, v) { xs *i = NULL; diff --git a/data.c b/data.c index 40382d2..550f7cf 100644 --- a/data.c +++ b/data.c @@ -1489,16 +1489,28 @@ xs_str *user_index_fn(snac *user, const char *idx_name) } -xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show) +xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more) /* returns a timeline (with all entries) */ { xs *idx = user_index_fn(user, idx_name); - return index_list_desc(idx, skip, show); + /* if a more flag is sent, request one more */ + xs_list *lst = index_list_desc(idx, skip, show + (more != NULL ? 1 : 0)); + + if (more != NULL) { + if (xs_list_len(lst) > show) { + *more = 1; + lst = xs_list_del(lst, -1); + } + else + *more = 0; + } + + return lst; } -xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show) +xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more) /* returns a timeline (only top level entries) */ { int c_max; @@ -1510,7 +1522,7 @@ xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show) if (show > c_max) show = c_max; - xs *list = timeline_simple_list(snac, idx_name, skip, show); + xs *list = timeline_simple_list(snac, idx_name, skip, show, more); return timeline_top_level(snac, list); } @@ -2709,9 +2721,9 @@ xs_list *content_search(snac *user, const char *regex, const char *md5s[3] = {0}; int c[3] = {0}; - tls[0] = timeline_simple_list(user, "public", 0, XS_ALL); /* public */ + tls[0] = timeline_simple_list(user, "public", 0, XS_ALL, NULL); /* public */ tls[1] = timeline_instance_list(0, XS_ALL); /* instance */ - tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL) : xs_list_new(); /* private or none */ + tls[2] = priv ? timeline_simple_list(user, "private", 0, XS_ALL, NULL) : xs_list_new(); /* private or none */ /* first positioning */ for (int n = 0; n < 3; n++) diff --git a/html.c b/html.c index 3b63cfc..bd94e9f 100644 --- a/html.c +++ b/html.c @@ -3314,21 +3314,17 @@ int html_get_handler(const xs_dict *req, const char *q_path, } else { xs *list = NULL; - xs *next = NULL; + int more = 0; - if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) { - list = timeline_simple_list(&snac, "public", skip, show); - next = timeline_simple_list(&snac, "public", skip + show, 1); - } - else { - list = timeline_list(&snac, "public", skip, show); - next = timeline_list(&snac, "public", skip + show, 1); - } + if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) + list = timeline_simple_list(&snac, "public", skip, show, &more); + else + list = timeline_list(&snac, "public", skip, show, &more); xs *pins = pinned_list(&snac); pins = xs_list_cat(pins, list); - *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1, error); + *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3490,13 +3486,14 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs_dict_get(req, "if-none-match"), etag); } else { + int more = 0; + snac_debug(&snac, 1, xs_fmt("building timeline")); - xs *list = timeline_list(&snac, "private", skip, show); - xs *next = timeline_list(&snac, "private", skip + show, 1); + xs *list = timeline_list(&snac, "private", skip, show, &more); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, "/admin", 1, error); + more, NULL, "/admin", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3702,7 +3699,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20")); - xs *elems = timeline_simple_list(&snac, "public", 0, cnt); + xs *elems = timeline_simple_list(&snac, "public", 0, cnt, NULL); xs *bio = xs_dup(xs_dict_get(snac.config, "bio")); xs *rss_title = xs_fmt("%s (@%s@%s)", diff --git a/mastoapi.c b/mastoapi.c index 54b4333..3c445c2 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1676,7 +1676,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, else if (strcmp(opt, "statuses") == 0) { /** **/ /* the public list of posts of a user */ - xs *timeline = timeline_simple_list(&snac2, "public", 0, 256); + xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); xs_list *p = timeline; const xs_str *v; diff --git a/snac.h b/snac.h index 344dbaa..278e798 100644 --- a/snac.h +++ b/snac.h @@ -157,8 +157,8 @@ int timeline_here(snac *snac, const char *md5); int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg); int timeline_del(snac *snac, const char *id); xs_str *user_index_fn(snac *user, const char *idx_name); -xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show); -xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show); +xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more); +xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more); int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); int timeline_admire(snac *snac, const char *id, const char *admirer, int like); -- cgit v1.2.3 From 1766d6bf92eb433841c03ccb096c636a4c5dc968 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 20:20:40 +0100 Subject: Added a 'No more unseen posts' mark. --- data.c | 8 ++++++++ html.c | 24 ++++++++++++++++++++++++ snac.h | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/data.c b/data.c index 550f7cf..480a35b 100644 --- a/data.c +++ b/data.c @@ -1528,6 +1528,14 @@ xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int } +void timeline_add_mark(snac *user) +/* adds an "already seen" mark to the private timeline */ +{ + xs *fn = xs_fmt("%s/private.idx", user->basedir); + index_add_md5(fn, MD5_ALREADY_SEEN_MARK); +} + + xs_str *instance_index_fn(void) { return xs_fmt("%s/public.idx", srv_basedir); diff --git a/html.c b/html.c index bd94e9f..771d2af 100644 --- a/html.c +++ b/html.c @@ -2648,10 +2648,31 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_add(body, posts); + int mark_shown = 0; + while (xs_list_iter(&p, &v)) { xs *msg = NULL; int status; + /* "already seen" mark? */ + if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { + if (skip == 0 && !mark_shown) { + xs *s = xs_fmt("%s/admin#top", user->actor); + + xs_html_add(posts, + xs_html_text(L("No more unseen posts")), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", s), + xs_html_text(L("Back to top"))), + xs_html_sctag("hr", NULL)); + } + + mark_shown = 1; + + continue; + } + if (utl && user && !is_pinned_by_md5(user, v)) status = timeline_get_by_md5(user, v, &msg); else @@ -3473,6 +3494,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else { + /** the private timeline **/ double t = history_mtime(&snac, "timeline.html_"); /* if enabled by admin, return a cached page if its timestamp is: @@ -3492,6 +3514,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); + timeline_add_mark(&snac); + *body = html_timeline(&snac, list, 0, skip, show, more, NULL, "/admin", 1, error); diff --git a/snac.h b/snac.h index 278e798..6c3ccda 100644 --- a/snac.h +++ b/snac.h @@ -22,6 +22,8 @@ #define MD5_HEX_SIZE 33 +#define MD5_ALREADY_SEEN_MARK "00000000000000000000000000000000" + extern double disk_layout; extern xs_str *srv_basedir; extern xs_dict *srv_config; @@ -163,6 +165,8 @@ int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); int timeline_admire(snac *snac, const char *id, const char *admirer, int like); xs_list *timeline_top_level(snac *snac, const xs_list *list); +void timeline_add_mark(snac *user); + xs_list *local_list(snac *snac, int max); xs_str *instance_index_fn(void); xs_list *timeline_instance_list(int skip, int show); -- cgit v1.2.3 From 492b91e4e47c43d15bb828ecbe1e4195c47c31f8 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 07:42:08 +0100 Subject: Backport from xs. --- xs.h | 21 ++++++++++++++++++--- xs_match.h | 7 ++++++- xs_version.h | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/xs.h b/xs.h index 05d84f5..961425b 100644 --- a/xs.h +++ b/xs.h @@ -12,6 +12,7 @@ #include #include #include +#include typedef enum { XSTYPE_STRING = 0x02, /* C string (\0 delimited) (NOT STORED) */ @@ -142,6 +143,7 @@ void xs_data_get(void *data, const xs_data *value); void *xs_memmem(const char *haystack, int h_size, const char *needle, int n_size); unsigned int xs_hash_func(const char *data, int size); +uint64_t xs_hash64_func(const char *data, int size); #ifdef XS_ASSERT #include @@ -632,7 +634,7 @@ xs_str *xs_crop_i(xs_str *str, int start, int end) end = sz + end; /* crop from the top */ - if (end > 0 && end < sz) + if (end >= 0 && end < sz) str[end] = '\0'; /* crop from the bottom */ @@ -1487,9 +1489,8 @@ unsigned int xs_hash_func(const char *data, int size) /* a general purpose hashing function */ { unsigned int hash = 0x666; - int n; - for (n = 0; n < size; n++) { + for (int n = 0; n < size; n++) { hash ^= (unsigned char)data[n]; hash *= 111111111; } @@ -1498,6 +1499,20 @@ unsigned int xs_hash_func(const char *data, int size) } +uint64_t xs_hash64_func(const char *data, int size) +/* a general purpose hashing function (64 bit) */ +{ + uint64_t hash = 0x100; + + for (int n = 0; n < size; n++) { + hash ^= (unsigned char)data[n]; + hash *= 1111111111111111111; + } + + return hash; +} + + #endif /* XS_IMPLEMENTATION */ #endif /* _XS_H */ diff --git a/xs_match.h b/xs_match.h index 0b89ac8..76c1bf3 100644 --- a/xs_match.h +++ b/xs_match.h @@ -24,6 +24,7 @@ int xs_match(const char *str, const char *spec) retry: for (;;) { + const char *q = spec; char c = *str++; char p = *spec++; @@ -63,8 +64,12 @@ retry: spec = b_spec; str = ++b_str; } - else + else { + if (*q == '|') + spec = q; + break; + } } } } diff --git a/xs_version.h b/xs_version.h index 12f713a..7314133 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* b865e89769aedfdbc61251e94451e9d37579f52e 2025-01-12T16:17:47+01:00 */ +/* 2f43b93e9d2b63360c802e09f4c68adfef74c673 2025-01-28T07:40:50+01:00 */ -- cgit v1.2.3 From d9d2dedbc053b35aee02ba7f408e056ab03368c0 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 07:48:31 +0100 Subject: Set the CSS class snac-no-more-unseen-posts. --- html.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/html.c b/html.c index 771d2af..c27ab99 100644 --- a/html.c +++ b/html.c @@ -2660,12 +2660,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs *s = xs_fmt("%s/admin#top", user->actor); xs_html_add(posts, - xs_html_text(L("No more unseen posts")), - xs_html_text(" - "), - xs_html_tag("a", - xs_html_attr("href", s), - xs_html_text(L("Back to top"))), - xs_html_sctag("hr", NULL)); + xs_html_tag("div", + xs_html_attr("class", "snac-no-more-unseen-posts"), + xs_html_text(L("No more unseen posts")), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", s), + xs_html_text(L("Back to top"))))); } mark_shown = 1; -- cgit v1.2.3 From bf07718f02081c88b48ea18c0bd38e49e971d398 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 08:04:57 +0100 Subject: Added some default styling to CSS class snac-no-more-unseen-posts. --- doc/style.css | 1 + utils.c | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/style.css b/doc/style.css index 13cef97..546cfb3 100644 --- a/doc/style.css +++ b/doc/style.css @@ -29,6 +29,7 @@ pre { overflow-x: scroll; } .snac-list-of-lists { padding-left: 0; } .snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px; margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; } +.snac-no-more-unseen-posts { border-top: 1px solid #000; border-bottom: 1px solid #000; padding: 0.5em 0; margin: 1em 0; } @media (prefers-color-scheme: dark) { body, input, textarea { background-color: #000; color: #fff; } a { color: #7799dd } diff --git a/utils.c b/utils.c index fd00e99..eb83884 100644 --- a/utils.c +++ b/utils.c @@ -72,6 +72,7 @@ static const char *default_css = ".snac-list-of-lists { padding-left: 0; }\n" ".snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px;\n" " margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; }\n" + ".snac-no-more-unseen-posts { border-top: 1px solid #000; border-bottom: 1px solid #000; padding: 0.5em 0; margin: 1em 0; }\n" "@media (prefers-color-scheme: dark) { \n" " body, input, textarea { background-color: #000; color: #fff; }\n" " a { color: #7799dd }\n" -- cgit v1.2.3 From ca9ff0538ef4e4bc6c23d1d30d83b0879c4d5351 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 08:07:43 +0100 Subject: Some CSS tweaks. --- doc/style.css | 2 +- utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/style.css b/doc/style.css index 546cfb3..87c5598 100644 --- a/doc/style.css +++ b/doc/style.css @@ -29,7 +29,7 @@ pre { overflow-x: scroll; } .snac-list-of-lists { padding-left: 0; } .snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px; margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; } -.snac-no-more-unseen-posts { border-top: 1px solid #000; border-bottom: 1px solid #000; padding: 0.5em 0; margin: 1em 0; } +.snac-no-more-unseen-posts { border-top: 1px solid #a0a0a0; border-bottom: 1px solid #a0a0a0; padding: 0.5em 0; margin: 1em 0; } @media (prefers-color-scheme: dark) { body, input, textarea { background-color: #000; color: #fff; } a { color: #7799dd } diff --git a/utils.c b/utils.c index eb83884..946897f 100644 --- a/utils.c +++ b/utils.c @@ -72,7 +72,7 @@ static const char *default_css = ".snac-list-of-lists { padding-left: 0; }\n" ".snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px;\n" " margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; }\n" - ".snac-no-more-unseen-posts { border-top: 1px solid #000; border-bottom: 1px solid #000; padding: 0.5em 0; margin: 1em 0; }\n" + ".snac-no-more-unseen-posts { border-top: 1px solid #a0a0a0; border-bottom: 1px solid #a0a0a0; padding: 0.5em 0; margin: 1em 0; }\n" "@media (prefers-color-scheme: dark) { \n" " body, input, textarea { background-color: #000; color: #fff; }\n" " a { color: #7799dd }\n" -- cgit v1.2.3 From 8156e4f03fd730facdee8c5910b8ec810dc5835c Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 08:18:11 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 23a2a17..b9f953d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,13 @@ # Release Notes +## UNRELEASED + +Notifications are now shown in a more compact way (i.e. all reactions are shown just above your post, instead of repeating the post *ad nauseam* for every reaction). + +New command-line option `unmute` to, well, no-longer-mute an actor. + +The private timeline now includes a mark between new posts and "already seen" ones. + ## 2.69 "Yin/Yang of Love" Added 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. -- cgit v1.2.3 From 06ba1174ca7084a3d691aa8c2b552b708d04b8db Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 10:04:23 +0100 Subject: Some tweaks to the already seen mark code. --- data.c | 18 +++++++++++++++++- html.c | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/data.c b/data.c index 480a35b..7139cdf 100644 --- a/data.c +++ b/data.c @@ -1532,7 +1532,23 @@ void timeline_add_mark(snac *user) /* adds an "already seen" mark to the private timeline */ { xs *fn = xs_fmt("%s/private.idx", user->basedir); - index_add_md5(fn, MD5_ALREADY_SEEN_MARK); + char last_entry[MD5_HEX_SIZE] = ""; + FILE *f; + + /* get the last entry in the index */ + if ((f = fopen(fn, "r")) != NULL) { + index_desc_first(f, last_entry, 0); + fclose(f); + } + + /* is the last entry *not* a mark? */ + if (strcmp(last_entry, MD5_ALREADY_SEEN_MARK) != 0) { + /* add it */ + index_add_md5(fn, MD5_ALREADY_SEEN_MARK); + + /* mark as new */ + timeline_touch(user); + } } diff --git a/html.c b/html.c index c27ab99..8f8b524 100644 --- a/html.c +++ b/html.c @@ -2657,7 +2657,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, /* "already seen" mark? */ if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { if (skip == 0 && !mark_shown) { - xs *s = xs_fmt("%s/admin#top", user->actor); + xs *s = xs_fmt("%s/admin", user->actor); xs_html_add(posts, xs_html_tag("div", @@ -2665,7 +2665,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_text(L("No more unseen posts")), xs_html_text(" - "), xs_html_tag("a", - xs_html_attr("href", s), + xs_html_attr("href", s), xs_html_text(L("Back to top"))))); } -- cgit v1.2.3 From aec643838f304468af61ca2ad4e00a9e7125e53b Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 20:36:37 +0100 Subject: Deleted useless code. --- data.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/data.c b/data.c index 7139cdf..50c6121 100644 --- a/data.c +++ b/data.c @@ -1545,9 +1545,6 @@ void timeline_add_mark(snac *user) if (strcmp(last_entry, MD5_ALREADY_SEEN_MARK) != 0) { /* add it */ index_add_md5(fn, MD5_ALREADY_SEEN_MARK); - - /* mark as new */ - timeline_touch(user); } } -- cgit v1.2.3 From 4acb3f65db21b1be6c16cf017aae890bb6dd4eea Mon Sep 17 00:00:00 2001 From: default Date: Wed, 29 Jan 2025 09:24:09 +0100 Subject: Call timeline_add_mark() after history_add() for better timestamp checks. --- html.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html.c b/html.c index 8f8b524..6365afb 100644 --- a/html.c +++ b/html.c @@ -3515,8 +3515,6 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); - timeline_add_mark(&snac); - *body = html_timeline(&snac, list, 0, skip, show, more, NULL, "/admin", 1, error); @@ -3525,6 +3523,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, if (save) history_add(&snac, "timeline.html_", *body, *b_size, etag); + + timeline_add_mark(&snac); } } } -- cgit v1.2.3 From ebb3921772834bb91cf9ccacf9d34bd050efbe5e Mon Sep 17 00:00:00 2001 From: default Date: Wed, 29 Jan 2025 09:44:34 +0100 Subject: Updated README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de11b98..8d5a59d 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ This will: - [How to install snac on OpenBSD without relayd (by @antics@mastodon.nu)](https://chai.guru/pub/openbsd/snac.html). - [Setting up Snac in OpenBSD (by Yonle)](https://wiki.ircnow.org/index.php?n=Openbsd.Snac). - [How to run your own social network with snac (by Giacomo Tesio)](https://encrypted.tesio.it/2024/12/18/how-to-run-your-own-social-network.html). Includes information on how to run snac as a CGI. +- [Improving snac Performance with Nginx Proxy Cache (by Stefano Marinelli)](https://it-notes.dragas.net/2025/01/29/improving-snac-performance-with-nginx-proxy-cache/). ## Incredibly awesome CSS themes for snac -- cgit v1.2.3 From 3799a6aa60df749624a5ad09aa5c60754987a49f Mon Sep 17 00:00:00 2001 From: default Date: Thu, 30 Jan 2025 16:13:22 +0100 Subject: Updated TODO. --- TODO.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index 86c706a..045b4cc 100644 --- a/TODO.md +++ b/TODO.md @@ -14,14 +14,10 @@ Important: deleting a follower should do more that just delete the object, see h ## Wishlist -Add support for subscribing and posting to relays (see https://codeberg.org/grunfink/snac2/issues/216 for more information). - The instance timeline should also show boosts from users. Mastoapi: implement /v1/conversations. -Implement following of hashtags (this is not trivial). - Track 'Event' data types standardization; how to add plan-to-attend and similar activities (more info: https://event-federation.eu/). Friendica interacts with events via activities `Accept` (will go), `TentativeAccept` (will try to go) or `Reject` (cannot go) (`object` field as id, not object). `Undo` for any of these activities cancel (`object` as an object, not id). Implement "FEP-3b86: Activity Intents" https://codeberg.org/fediverse/fep/src/branch/main/fep/3b86/fep-3b86.md @@ -365,3 +361,7 @@ CSV import/export does not work with OpenBSD security on; document it or fix it Add support for /share?text=tt&website=url (whatever it is, see https://mastodonshare.com/ for details) (2025-01-06T18:43:52+0100). Add support for /authorize_interaction (whatever it is) (2025-01-16T14:45:28+0100). + +Implement following of hashtags (this is not trivial) (2025-01-30T16:12:16+0100). + +Add support for subscribing and posting to relays (see https://codeberg.org/grunfink/snac2/issues/216 for more information) (2025-01-30T16:12:34+0100). -- cgit v1.2.3 From e5d1fe433cdeaf4d65e13d660a7a7db696c763a9 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 30 Jan 2025 16:15:22 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b9f953d..b895801 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,7 +6,9 @@ Notifications are now shown in a more compact way (i.e. all reactions are shown New command-line option `unmute` to, well, no-longer-mute an actor. -The private timeline now includes a mark between new posts and "already seen" ones. +The private timeline now includes an approximate mark between new posts and "already seen" ones. + +Fixed a spurious 404 error in the instance root URL for some configurations. ## 2.69 "Yin/Yang of Love" -- cgit v1.2.3 From 317106fc69f8aeca023788f0e0f6768387a2cd2a Mon Sep 17 00:00:00 2001 From: default Date: Thu, 30 Jan 2025 16:32:37 +0100 Subject: Updated documentation. --- doc/snac.5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/snac.5 b/doc/snac.5 index 3550995..d873908 100644 --- a/doc/snac.5 +++ b/doc/snac.5 @@ -78,7 +78,7 @@ converted to related emojis: .Ss Accepted HTML All HTML tags in entries are neutered except the following ones: .Bd -literal -a p br blockquote ul ol li cite small +a p br blockquote ul ol li cite small h2 h3 span i b u s pre code em strong hr img del .Ed .Pp -- cgit v1.2.3 From d0c81d35cefd5ce9ba6b2c6fd0bf3091011959b5 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 31 Jan 2025 09:10:16 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b895801..337a29a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.70 Notifications are now shown in a more compact way (i.e. all reactions are shown just above your post, instead of repeating the post *ad nauseam* for every reaction). -- cgit v1.2.3 From ed6c6328a14ae486ba87a7bad273a4bd3a4056c4 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 31 Jan 2025 09:11:34 +0100 Subject: Version 2.70 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 6c3ccda..0cd6113 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.70-dev" +#define VERSION "2.70" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From 35ce3d1ecb26f7fb76858f015312b69cb9817bfb Mon Sep 17 00:00:00 2001 From: default Date: Sat, 1 Feb 2025 08:21:05 +0100 Subject: Updated documentation. --- doc/snac.1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/snac.1 b/doc/snac.1 index d33bccb..8cc032d 100644 --- a/doc/snac.1 +++ b/doc/snac.1 @@ -234,6 +234,8 @@ Purges old data from the timeline of all users. .It Cm adduser Ar basedir Op uid Adds a new user to the server. This is an interactive command; necessary information will be prompted for. +.It Cm deluser Ar basedir Ar uid +Deletes a user, unfollowing all accounts first. .It Cm resetpwd Ar basedir Ar uid Resets a user's password to a new, random one. .It Cm queue Ar basedir Ar uid -- cgit v1.2.3 From a3d4575d91680580c69855c6732c6fe8a4db5fef Mon Sep 17 00:00:00 2001 From: default Date: Sun, 2 Feb 2025 09:54:33 +0100 Subject: Updated documentation. --- doc/snac.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/snac.1 b/doc/snac.1 index 8cc032d..327e071 100644 --- a/doc/snac.1 +++ b/doc/snac.1 @@ -259,6 +259,9 @@ The rest of command line arguments are treated as media files to be attached to the post. .It Cm note_unlisted Ar basedir Ar uid Ar text Op file file ... Like the previous one, but creates an "unlisted" (or "quiet public") post. +.It Cm note_mention Ar basedir Ar uid Ar text Op file file ... +Like the previous one, but creates a post only for accounts mentioned +in the post body. .It Cm block Ar basedir Ar instance_url Blocks a full instance, given its URL or domain name. All subsequent incoming activities with identifiers from that instance will be immediately -- cgit v1.2.3 From 11d1adca7a2f3e398722f3160ac6a8061f18c31d Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Tue, 4 Feb 2025 13:09:49 +0200 Subject: Fix memory leaks Fix a memory leak on each login; the allocated OpenSSL BIOs were only freed partially. Also add a missing deallocation during server socket creation. --- xs_openssl.h | 2 +- xs_socket.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/xs_openssl.h b/xs_openssl.h index 9388691..f215bcc 100644 --- a/xs_openssl.h +++ b/xs_openssl.h @@ -83,7 +83,7 @@ xs_val *xs_base64_dec(const xs_str *data, int *size) s = xs_realloc(s, _xs_blk_size(*size + 1)); s[*size] = '\0'; - BIO_free_all(mem); + BIO_free_all(b64); return s; } diff --git a/xs_socket.h b/xs_socket.h index 6e618ba..7bf5298 100644 --- a/xs_socket.h +++ b/xs_socket.h @@ -85,6 +85,8 @@ int xs_socket_server(const char *addr, const char *serv) listen(rs, SOMAXCONN); } + freeaddrinfo(res); + #else /* WITHOUT_GETADDRINFO */ struct sockaddr_in host; -- cgit v1.2.3 From 51dc5aad0fabaa35df27bc5b112d21bc470cc212 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 13:37:47 +0100 Subject: Fixed crash. --- xs_url.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs_url.h b/xs_url.h index 3c24736..81dd668 100644 --- a/xs_url.h +++ b/xs_url.h @@ -69,7 +69,7 @@ xs_dict *xs_url_vars(const char *str) vars = xs_dict_new(); - if (str != NULL) { + if (xs_is_string(str)) { /* split by arguments */ xs *args = xs_split(str, "&"); -- cgit v1.2.3 From e1e4c0ca1ade524eb6d2585215c0b028ffaf5a8b Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 13:56:08 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 337a29a..0623f23 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,11 @@ # Release Notes +## UNRELEASED + +Fixed memory leak (contributed by inz). + +Fixed crash. + ## 2.70 Notifications are now shown in a more compact way (i.e. all reactions are shown just above your post, instead of repeating the post *ad nauseam* for every reaction). -- cgit v1.2.3 From f942acf3e987989b4898ee43b00685092127399e Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 13:57:19 +0100 Subject: Bumped version. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 0cd6113..b4852f3 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.70" +#define VERSION "2.71-dev" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From 6f2afe1ecb01ff3ff8d6f9e297ed02e0d42f8b93 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 15:07:17 +0100 Subject: Version 2.71 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index b4852f3..4618b87 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.71-dev" +#define VERSION "2.71" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From d80985746719d54ef0a63bc51c05adedb537b394 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 15:09:13 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0623f23..f39a912 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.71 Fixed memory leak (contributed by inz). -- cgit v1.2.3 From a33cdf29070a7bd0e46fc1484c98508ca959c1fa Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 16:10:52 +0100 Subject: Another crash fix. --- xs_url.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xs_url.h b/xs_url.h index 81dd668..fd320a4 100644 --- a/xs_url.h +++ b/xs_url.h @@ -23,6 +23,9 @@ xs_str *xs_url_dec(const char *str) if (sscanf(str + 1, "%02x", &i) == 1) { unsigned char uc = i; + if (!xs_is_string((char *)&uc)) + break; + s = xs_append_m(s, (char *)&uc, 1); str += 2; } -- cgit v1.2.3 From 636d026e133d874daf39a84a7702253454644926 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 16:24:21 +0100 Subject: More xs_url_dec() fixes. --- xs_url.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xs_url.h b/xs_url.h index fd320a4..8e2e243 100644 --- a/xs_url.h +++ b/xs_url.h @@ -17,6 +17,9 @@ xs_str *xs_url_dec(const char *str) xs_str *s = xs_str_new(NULL); while (*str) { + if (!xs_is_string(str)) + break; + if (*str == '%') { unsigned int i; -- cgit v1.2.3 From be9104783e75548195ec9f9661d4a3365d300f85 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 16:56:12 +0100 Subject: Don't append non-strings in xs_readline(). --- xs_io.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xs_io.h b/xs_io.h index 110b0eb..8fc5d6f 100644 --- a/xs_io.h +++ b/xs_io.h @@ -27,7 +27,8 @@ xs_str *xs_readline(FILE *f) while ((c = fgetc(f)) != EOF) { unsigned char rc = c; - s = xs_append_m(s, (char *)&rc, 1); + if (xs_is_string((char *)&rc)) + s = xs_append_m(s, (char *)&rc, 1); if (c == '\n') break; -- cgit v1.2.3 From d1d9e1397e6d7ee182316bbbb1dd0b1b9788b36f Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 17:11:43 +0100 Subject: Bumped version. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 4618b87..7b5c54c 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.71" +#define VERSION "2.72-dev" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From a2dde5dedaddb7fe91c061997e1314ba569c2edf Mon Sep 17 00:00:00 2001 From: default Date: Tue, 4 Feb 2025 17:26:47 +0100 Subject: Only split real strings in xs_split_n(). --- xs.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/xs.h b/xs.h index 961425b..b53885e 100644 --- a/xs.h +++ b/xs.h @@ -991,16 +991,20 @@ xs_str *xs_join(const xs_list *list, const char *sep) xs_list *xs_split_n(const char *str, const char *sep, int times) /* splits a string into a list upto n times */ { + xs_list *list = xs_list_new(); + + if (!xs_is_string(str) || !xs_is_string(sep)) + return list; + int sz = strlen(sep); char *ss; - xs_list *list; - - list = xs_list_new(); while (times > 0 && (ss = strstr(str, sep)) != NULL) { /* create a new string with this slice and add it to the list */ xs *s = xs_str_new_sz(str, ss - str); - list = xs_list_append(list, s); + + if (xs_is_string(s)) + list = xs_list_append(list, s); /* skip past the separator */ str = ss + sz; @@ -1009,7 +1013,8 @@ xs_list *xs_split_n(const char *str, const char *sep, int times) } /* add the rest of the string */ - list = xs_list_append(list, str); + if (xs_is_string(str)) + list = xs_list_append(list, str); return list; } -- cgit v1.2.3