summaryrefslogtreecommitdiff
path: root/activitypub.c
diff options
context:
space:
mode:
Diffstat (limited to 'activitypub.c')
-rw-r--r--activitypub.c108
1 files changed, 88 insertions, 20 deletions
diff --git a/activitypub.c b/activitypub.c
index 2d3d903..4ed2805 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -569,14 +569,21 @@ xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
569 } 569 }
570 570
571 while (xs_list_iter(&l, &v)) { 571 while (xs_list_iter(&l, &v)) {
572 if (expand_public && strcmp(v, public_address) == 0) { 572 if (expand_public) {
573 /* iterate the followers and add them */ 573 if (strcmp(v, public_address) == 0 ||
574 xs *fwers = follower_list(snac); 574 /* check if it's a followers collection URL */
575 const char *actor; 575 (xs_type(v) == XSTYPE_STRING &&
576 576 strcmp(v, xs_fmt("%s/followers", snac->actor)) == 0) ||
577 char *p = fwers; 577 (xs_type(v) == XSTYPE_LIST &&
578 while (xs_list_iter(&p, &actor)) 578 xs_list_in(v, xs_fmt("%s/followers", snac->actor)) != -1)) {
579 xs_set_add(&rcpts, actor); 579 /* iterate the followers and add them */
580 xs *fwers = follower_list(snac);
581 const char *actor;
582
583 char *p = fwers;
584 while (xs_list_iter(&p, &actor))
585 xs_set_add(&rcpts, actor);
586 }
580 } 587 }
581 else 588 else
582 xs_set_add(&rcpts, v); 589 xs_set_add(&rcpts, v);
@@ -1840,8 +1847,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1840 xs_list *p; 1847 xs_list *p;
1841 const xs_val *v; 1848 const xs_val *v;
1842 1849
1843 /* FIXME: implement scope 3 */ 1850 const int priv = (scope == SCOPE_MENTIONED || scope == SCOPE_FOLLOWERS);
1844 int priv = scope == 1;
1845 1851
1846 if (rcpts == NULL) 1852 if (rcpts == NULL)
1847 to = xs_list_new(); 1853 to = xs_list_new();
@@ -1901,9 +1907,13 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1901 if ((v = xs_dict_get(p_msg, "conversation"))) 1907 if ((v = xs_dict_get(p_msg, "conversation")))
1902 msg = xs_dict_append(msg, "conversation", v); 1908 msg = xs_dict_append(msg, "conversation", v);
1903 1909
1904 /* if this message is public, ours will also be */ 1910 /* if this message is public or unlisted, ours will also be */
1905 if (!priv && is_msg_public(p_msg) && xs_list_in(to, public_address) == -1) 1911 const int orig_scope = get_msg_visibility(p_msg);
1912 if (!priv && orig_scope == SCOPE_PUBLIC && xs_list_in(to, public_address) == -1)
1906 to = xs_list_append(to, public_address); 1913 to = xs_list_append(to, public_address);
1914 else
1915 if (!priv && orig_scope == SCOPE_UNLISTED && xs_list_in(cc, public_address) == -1)
1916 cc = xs_list_append(cc, public_address);
1907 } 1917 }
1908 1918
1909 irt = xs_dup(in_reply_to); 1919 irt = xs_dup(in_reply_to);
@@ -1947,28 +1957,50 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1947 if (ctxt == NULL) 1957 if (ctxt == NULL)
1948 ctxt = xs_fmt("%s#ctxt", id); 1958 ctxt = xs_fmt("%s#ctxt", id);
1949 1959
1950 /* add all mentions to the cc */ 1960 /* add all mentions to the appropriate field */
1951 p = tag; 1961 p = tag;
1952 while (xs_list_iter(&p, &v)) { 1962 while (xs_list_iter(&p, &v)) {
1953 if (xs_type(v) == XSTYPE_DICT) { 1963 if (xs_type(v) == XSTYPE_DICT) {
1954 const char *t; 1964 const char *t;
1955 1965
1956 if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) { 1966 if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) {
1957 if (!xs_is_null(t = xs_dict_get(v, "href"))) 1967 if (!xs_is_null(t = xs_dict_get(v, "href"))) {
1958 cc = xs_list_append(cc, t); 1968 if (scope == SCOPE_MENTIONED) {
1969 /* for DMs, mentions go to 'to' */
1970 to = xs_list_append(to, t);
1971 } else {
1972 /* for other visibility levels, mentions go to 'cc' */
1973 cc = xs_list_append(cc, t);
1974 }
1975 }
1959 } 1976 }
1960 } 1977 }
1961 } 1978 }
1962 1979
1963 if (scope == 2) { 1980 if (scope == SCOPE_UNLISTED) {
1964 /* Mastodon's "quiet public": add public address to cc */ 1981 /* Mastodon's "quiet public": remove from to, add public address to cc */
1982 int idx;
1983 if ((idx = xs_list_in(to, public_address)) != -1)
1984 to = xs_list_del(to, idx);
1965 if (xs_list_in(cc, public_address) == -1) 1985 if (xs_list_in(cc, public_address) == -1)
1966 cc = xs_list_append(cc, public_address); 1986 cc = xs_list_append(cc, public_address);
1967 } 1987 }
1968 else 1988 else
1969 /* no recipients? must be for everybody */ 1989 if (scope == SCOPE_FOLLOWERS) {
1970 if (!priv && xs_list_len(to) == 0) 1990 /* followers-only: add followers collection to to */
1971 to = xs_list_append(to, public_address); 1991 xs *followers_url = xs_fmt("%s/followers", snac->actor);
1992 if (xs_list_in(to, followers_url) == -1)
1993 to = xs_list_append(to, followers_url);
1994 }
1995 else
1996 if (scope == SCOPE_PUBLIC) {
1997 /* public: ensure public address is in to and not in cc */
1998 int idx;
1999 if ((idx = xs_list_in(cc, public_address)) != -1)
2000 cc = xs_list_del(cc, idx);
2001 if (xs_list_in(to, public_address) == -1)
2002 to = xs_list_append(to, public_address);
2003 }
1972 2004
1973 /* delete all cc recipients that also are in the to */ 2005 /* delete all cc recipients that also are in the to */
1974 p = to; 2006 p = to;
@@ -2113,6 +2145,42 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
2113 return msg; 2145 return msg;
2114} 2146}
2115 2147
2148int get_msg_visibility(const xs_dict *msg)
2149/* determine visibility from message based on CC, TO and /followers mark */
2150{
2151 const xs_val *to = xs_dict_get(msg, "to");
2152 const xs_val *cc = xs_dict_get(msg, "cc");
2153
2154 /* check if it's unlisted (public in cc but not in to) */
2155 int pub_in_to = 0;
2156 int pub_in_cc = 0;
2157
2158 if ((xs_type(to) == XSTYPE_STRING && strcmp(to, public_address) == 0) ||
2159 (xs_type(to) == XSTYPE_LIST && xs_list_in(to, public_address) != -1))
2160 pub_in_to = 1;
2161
2162 if ((xs_type(cc) == XSTYPE_STRING && strcmp(cc, public_address) == 0) ||
2163 (xs_type(cc) == XSTYPE_LIST && xs_list_in(cc, public_address) != -1))
2164 pub_in_cc = 1;
2165
2166 if (!pub_in_to && pub_in_cc) {
2167 return SCOPE_UNLISTED;
2168 }
2169 if (pub_in_to && !pub_in_cc) {
2170 return SCOPE_PUBLIC;
2171 }
2172
2173 xs *followers_url = xs_fmt("%s/followers", xs_dict_get(msg, "attributedTo"));
2174
2175 if ((xs_type(to) == XSTYPE_STRING && strcmp(to, followers_url) == 0) ||
2176 (xs_type(to) == XSTYPE_LIST && xs_list_in(to, followers_url) != -1))
2177 return SCOPE_FOLLOWERS;
2178 else
2179 return SCOPE_MENTIONED;
2180 /* should be unreachable, someone violated the protocol. */
2181 /* better treat it as followers-only to make sure we don't leak information.*/
2182 return SCOPE_FOLLOWERS;
2183}
2116 2184
2117int update_question(snac *user, const char *id) 2185int update_question(snac *user, const char *id)
2118/* updates the poll counts */ 2186/* updates the poll counts */