Support unlisted public posts

This commit is contained in:
Michael 2020-03-02 07:57:23 +00:00
parent 357c0072bd
commit ca1b92bb34
29 changed files with 146 additions and 100 deletions

View File

@ -785,7 +785,7 @@ function api_item_get_user(App $a, $item)
$author_user = $status_user;
$status_user["protected"] = $item['private'] ?? 0;
$status_user["protected"] = $item['private'] == Item::PRIVATE;
if (($item['thr-parent'] ?? '') == ($item['uri'] ?? '')) {
$owner_user = api_get_user($a, $item['owner-id'] ?? null);
@ -1344,7 +1344,7 @@ function api_get_last_status($ownerId, $uid)
'author-id'=> $ownerId,
'uid' => $uid,
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'private' => false
'private' => [Item::PUBLIC, Item::UNLISTED]
];
$item = api_get_item($condition);
@ -1734,8 +1734,8 @@ function api_statuses_public_timeline($type)
$start = max(0, ($page - 1) * $count);
if ($exclude_replies && !$conversation_id) {
$condition = ["`gravity` IN (?, ?) AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
$condition = ["`gravity` IN (?, ?) AND `iid` > ? AND `private` = ? AND `wall` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `thread`.`iid` <= ?";
@ -1747,8 +1747,8 @@ function api_statuses_public_timeline($type)
$r = Item::inArray($statuses);
} else {
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND `private` = ? AND `wall` AND `item`.`origin` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `item`.`id` <= ?";
@ -1813,8 +1813,8 @@ function api_statuses_networkpublic_timeline($type)
$start = max(0, ($page - 1) * $count);
$condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `thread`.`iid` > ? AND NOT `private`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
$condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `thread`.`iid` > ? AND `private` = ?",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
$condition[0] .= " AND `thread`.`iid` <= ?";
@ -2042,7 +2042,7 @@ function api_statuses_repeat($type)
Logger::log('API: api_statuses_repeat: '.$id);
$fields = ['body', 'title', 'attach', 'tag', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
$item = Item::selectFirst($fields, ['id' => $id, 'private' => false]);
$item = Item::selectFirst($fields, ['id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED]]);
if (DBA::isResult($item) && $item['body'] != "") {
if (strpos($item['body'], "[/share]") !== false) {
@ -3007,7 +3007,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
'user' => $status_user,
'friendica_author' => $author_user,
'friendica_owner' => $owner_user,
'friendica_private' => $item['private'] == 1,
'friendica_private' => $item['private'] == Item::PRIVATE,
//'entities' => NULL,
'statusnet_html' => $converted["html"],
'statusnet_conversation_id' => $item['parent'],

View File

@ -70,7 +70,7 @@ function display_init(App $a)
// Is this item private but could be visible to the remove visitor?
if (!DBA::isResult($item) && remote_user()) {
$item = Item::selectFirst($fields, ['guid' => $a->argv[1], 'private' => 1, 'origin' => true]);
$item = Item::selectFirst($fields, ['guid' => $a->argv[1], 'private' => Item::PRIVATE, 'origin' => true]);
if (DBA::isResult($item)) {
if (!Contact::isFollower(remote_user(), $item['uid'])) {
$item = null;
@ -82,14 +82,14 @@ function display_init(App $a)
// Is it an item with uid=0?
if (!DBA::isResult($item)) {
$item = Item::selectFirstForUser(local_user(), $fields, ['guid' => $a->argv[1], 'private' => [0, 2], 'uid' => 0]);
$item = Item::selectFirstForUser(local_user(), $fields, ['guid' => $a->argv[1], 'private' => [Item::PUBLIC, Item::UNLISTED], 'uid' => 0]);
}
} elseif ($a->argc >= 3 && $nick == 'feed-item') {
$item_id = $a->argv[2];
if (substr($item_id, -5) == '.atom') {
$item_id = substr($item_id, 0, -5);
}
$item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item_id, 'private' => [0, 2], 'uid' => 0]);
$item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item_id, 'private' => [Item::PUBLIC, Item::UNLISTED], 'uid' => 0]);
}
if (!DBA::isResult($item)) {
@ -216,7 +216,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
}
if (($item_parent == 0) && remote_user()) {
$item = Item::selectFirst($fields, ['guid' => $a->argv[1], 'private' => 1, 'origin' => true]);
$item = Item::selectFirst($fields, ['guid' => $a->argv[1], 'private' => Item::PRIVATE, 'origin' => true]);
if (DBA::isResult($item) && Contact::isFollower(remote_user(), $item['uid'])) {
$item_id = $item["id"];
$item_parent = $item["parent"];
@ -225,7 +225,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
}
if ($item_parent == 0) {
$condition = ['private' => [0, 2], 'guid' => $a->argv[1], 'uid' => 0];
$condition = ['private' => [Item::PUBLIC, Item::UNLISTED], 'guid' => $a->argv[1], 'uid' => 0];
$item = Item::selectFirstForUser(local_user(), $fields, $condition);
if (DBA::isResult($item)) {
$item_id = $item["id"];
@ -241,7 +241,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
}
// We are displaying an "alternate" link if that post was public. See issue 2864
$is_public = Item::exists(['id' => $item_id, 'private' => [0, 2]]);
$is_public = Item::exists(['id' => $item_id, 'private' => [Item::PUBLIC, Item::UNLISTED]]);
if ($is_public) {
// For the atom feed the nickname doesn't matter at all, we only need the item id.
$alternate = DI::baseUrl().'/display/feed-item/'.$item_id.'.atom';

View File

@ -40,6 +40,7 @@ use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Attach;
use Friendica\Model\Config\PConfig;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\FileTag;
@ -300,7 +301,13 @@ function item_post(App $a) {
$postopts = $_REQUEST['postopts'] ?? '';
$private = ((strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny)) ? 1 : 0);
if (strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny)) {
$private = Item::PRIVATE;
} elseif (PConfig::get($profile_uid, 'system', 'unlisted')) {
$private == Item::UNLISTED;
} else {
$private == Item::PUBLIC;
}
// If this is a comment, set the permissions from the parent.

View File

@ -66,7 +66,7 @@ function lockview_content(App $a)
}
if (isset($item['private'])
&& $item['private'] == 1
&& $item['private'] == Item::PRIVATE
&& empty($item['allow_cid'])
&& empty($item['allow_gid'])
&& empty($item['deny_cid'])

View File

@ -84,7 +84,7 @@ function poke_init(App $a)
$deny_gid = $item['deny_gid'];
}
} else {
$private = (!empty($_GET['private']) ? intval($_GET['private']) : 0);
$private = (!empty($_GET['private']) ? intval($_GET['private']) : Item::PUBLIC);
$allow_cid = ($private ? '<' . $target['id']. '>' : $a->user['allow_cid']);
$allow_gid = ($private ? '' : $a->user['allow_gid']);

View File

@ -84,18 +84,12 @@ function pubsubhubbub_init(App $a) {
// fetch user from database given the nickname
$condition = ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false];
$owner = DBA::selectFirst('user', ['uid', 'hidewall', 'nickname'], $condition);
$owner = DBA::selectFirst('user', ['uid', 'nickname'], $condition);
if (!DBA::isResult($owner)) {
Logger::log('Local account not found: ' . $nick . ' - topic: ' . $hub_topic . ' - callback: ' . $hub_callback);
throw new \Friendica\Network\HTTPException\NotFoundException();
}
// abort if user's wall is supposed to be private
if ($owner['hidewall']) {
Logger::log('Local user ' . $nick . 'has chosen to hide wall, ignoring.');
throw new \Friendica\Network\HTTPException\ForbiddenException();
}
// get corresponding row from contact table
$condition = ['uid' => $owner['uid'], 'blocked' => false,
'pending' => false, 'self' => true];

View File

@ -317,6 +317,7 @@ function settings_post(App $a)
$cntunkmail = (!empty($_POST['cntunkmail']) ? intval($_POST['cntunkmail']) : 0);
$hide_friends = (($_POST['hide-friends'] == 1) ? 1: 0);
$hidewall = (($_POST['hidewall'] == 1) ? 1: 0);
$unlisted = (($_POST['unlisted'] == 1) ? 1: 0);
$email_textonly = (($_POST['email_textonly'] == 1) ? 1 : 0);
$detailed_notif = (($_POST['detailed_notif'] == 1) ? 1 : 0);
@ -414,6 +415,7 @@ function settings_post(App $a)
DI::pConfig()->set(local_user(), 'system', 'email_textonly', $email_textonly);
DI::pConfig()->set(local_user(), 'system', 'detailed_notif', $detailed_notif);
DI::pConfig()->set(local_user(), 'system', 'unlisted', $unlisted);
if ($page_flags == User::PAGE_FLAGS_PRVGROUP) {
$hidewall = 1;
@ -836,6 +838,10 @@ function settings_content(App $a)
'$field' => ['hidewall', DI::l10n()->t('Hide your profile details from anonymous viewers?'), $a->user['hidewall'], DI::l10n()->t('Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Your public posts and replies will still be accessible by other means.')],
]);
$unlisted = Renderer::replaceMacros($opt_tpl, [
'$field' => ['unlisted', DI::l10n()->t('Should public posts be unlisted?'), DI::pConfig()->get(local_user(), 'system', 'unlisted'), DI::l10n()->t('Your public posts will not appear on the community page or in search results, nor will they be transported to relay servers.')],
]);
$blockwall = Renderer::replaceMacros($opt_tpl, [
'$field' => ['blockwall', DI::l10n()->t('Allow friends to post to your profile page?'), (intval($a->user['blockwall']) ? '0' : '1'), DI::l10n()->t('Your contacts may write posts on your profile wall. These posts will be distributed to your contacts')],
]);
@ -949,6 +955,7 @@ function settings_content(App $a)
'$profile_in_net_dir' => $profile_in_net_dir,
'$hide_friends' => $hide_friends,
'$hide_wall' => $hide_wall,
'$unlisted' => $unlisted,
'$unkmail' => $unkmail,
'$cntunkmail' => ['cntunkmail', DI::l10n()->t('Maximum private messages per day from unknown people:'), $cntunkmail , DI::l10n()->t("\x28to prevent spam abuse\x29")],

View File

@ -34,7 +34,7 @@ function share_init(App $a) {
'guid', 'created', 'plink', 'title'];
$item = Item::selectFirst($fields, ['id' => $post_id]);
if (!DBA::isResult($item) || $item['private'] == 1) {
if (!DBA::isResult($item) || $item['private'] == Item::PRIVATE) {
exit();
}

View File

@ -975,6 +975,7 @@ class BBCode
Contact::getIdForURL($attributes['profile'], 0, true, $default);
$author_contact = Contact::getDetailsByURL($attributes['profile']);
$author_contact['url'] = ($author_contact['url'] ?? $attributes['profile']);
$author_contact['addr'] = ($author_contact['addr'] ?? '') ?: Protocol::getAddrFromProfileUrl($attributes['profile']);
$attributes['author'] = ($author_contact['name'] ?? '') ?: $attributes['author'];

View File

@ -113,6 +113,10 @@ class Item
Activity::FOLLOW,
Activity::ANNOUNCE];
const PUBLIC = 0;
const PRIVATE = 1;
const UNLISTED = 2;
private static $legacy_mode = null;
public static function isLegacyMode()
@ -1541,7 +1545,7 @@ class Item
$item['allow_gid'] = trim($item['allow_gid'] ?? '');
$item['deny_cid'] = trim($item['deny_cid'] ?? '');
$item['deny_gid'] = trim($item['deny_gid'] ?? '');
$item['private'] = intval($item['private'] ?? 0);
$item['private'] = intval($item['private'] ?? self::PUBLIC);
$item['body'] = trim($item['body'] ?? '');
$item['tag'] = trim($item['tag'] ?? '');
$item['attach'] = trim($item['attach'] ?? '');
@ -1737,8 +1741,8 @@ class Item
* The original author commented, but as this is a comment, the permissions
* weren't fixed up so it will still show the comment as private unless we fix it here.
*/
if ((intval($parent['forum_mode']) == 1) && $parent['private']) {
$item['private'] = 0;
if ((intval($parent['forum_mode']) == 1) && ($parent['private'] != self::PUBLIC)) {
$item['private'] = self::PUBLIC;
}
// If its a post that originated here then tag the thread as "mention"
@ -1808,7 +1812,7 @@ class Item
// ACL settings
if (strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid)) {
$private = 1;
$private = self::PRIVATE;
} else {
$private = $item['private'];
}
@ -2217,7 +2221,7 @@ class Item
// Only distribute public items from native networks
$condition = ['id' => $itemid, 'uid' => 0,
'network' => array_merge(Protocol::FEDERATED ,['']),
'visible' => true, 'deleted' => false, 'moderated' => false, 'private' => false];
'visible' => true, 'deleted' => false, 'moderated' => false, 'private' => [self::PUBLIC, self::UNLISTED]];
$item = self::selectFirst(self::ITEM_FIELDLIST, $condition);
if (!DBA::isResult($item)) {
return;
@ -2367,7 +2371,7 @@ class Item
}
// Is it a visible public post?
if (!$item["visible"] || $item["deleted"] || $item["moderated"] || $item["private"]) {
if (!$item["visible"] || $item["deleted"] || $item["moderated"] || ($item["private"] == Item::PRIVATE)) {
return;
}
@ -2558,7 +2562,7 @@ class Item
Contact::unmarkForArchival($contact);
}
$update = (!$arr['private'] && ((($arr['author-link'] ?? '') === ($arr['owner-link'] ?? '')) || ($arr["parent-uri"] === $arr["uri"])));
$update = (($arr['private'] != self::PRIVATE) && ((($arr['author-link'] ?? '') === ($arr['owner-link'] ?? '')) || ($arr["parent-uri"] === $arr["uri"])));
// Is it a forum? Then we don't care about the rules from above
if (!$update && in_array($arr["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN]) && ($arr["parent-uri"] === $arr["uri"])) {
@ -2572,7 +2576,7 @@ class Item
['id' => $arr['contact-id']]);
}
// Now do the same for the system wide contacts with uid=0
if (!$arr['private']) {
if ($arr['private'] != self::PRIVATE) {
DBA::update('contact', ['success_update' => $arr['received'], 'last-item' => $arr['received']],
['id' => $arr['owner-id']]);
@ -2753,7 +2757,7 @@ class Item
// also reset all the privacy bits to the forum default permissions
$private = ($user['allow_cid'] || $user['allow_gid'] || $user['deny_cid'] || $user['deny_gid']) ? 1 : 0;
$private = ($user['allow_cid'] || $user['allow_gid'] || $user['deny_cid'] || $user['deny_gid']) ? self::PRIVATE : self::PUBLIC;
$psid = PermissionSet::getIdFromACL(
$user['uid'],
@ -2800,7 +2804,7 @@ class Item
return false;
}
if (($contact['network'] != Protocol::FEED) && $datarray['private']) {
if (($contact['network'] != Protocol::FEED) && ($datarray['private'] == self::PRIVATE)) {
Logger::log('Not public', Logger::DEBUG);
return false;
}
@ -2838,7 +2842,7 @@ class Item
$urlpart = parse_url($datarray2['author-link']);
$datarray["app"] = $urlpart["host"];
} else {
$datarray['private'] = 0;
$datarray['private'] = self::PUBLIC;
}
}
@ -3382,7 +3386,7 @@ class Item
*
* default permissions - anonymous user
*/
$sql = " AND NOT `item`.`private`";
$sql = sprintf(" AND `item`.`private` != %d", self::PRIVATE);
// Profile owner - everything is visible
if ($local_user && ($local_user == $owner_id)) {
@ -3398,12 +3402,12 @@ class Item
$set = PermissionSet::get($owner_id, $remote_user);
if (!empty($set)) {
$sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))";
$sql_set = sprintf(" OR (`item`.`private` = %d AND `item`.`wall` AND `item`.`psid` IN (", self::PRIVATE) . implode(',', $set) . "))";
} else {
$sql_set = '';
}
$sql = " AND (NOT `item`.`private`" . $sql_set . ")";
$sql = sprintf(" AND (`item`.`private` != %d", self::PRIVATE) . $sql_set . ")";
}
return $sql;
@ -3505,7 +3509,7 @@ class Item
continue;
}
if ((local_user() == $item['uid']) && ($item['private'] == 1) && ($item['contact-id'] != $app->contact['id']) && ($item['network'] == Protocol::DFRN)) {
if ((local_user() == $item['uid']) && ($item['private'] == self::PRIVATE) && ($item['contact-id'] != $app->contact['id']) && ($item['network'] == Protocol::DFRN)) {
$img_url = 'redir/' . $item['contact-id'] . '?url=' . urlencode($mtch[1]);
$item['body'] = str_replace($mtch[0], '[img]' . $img_url . '[/img]', $item['body']);
}
@ -3683,7 +3687,7 @@ class Item
$ret["title"] = DI::l10n()->t('link to source');
}
} elseif (!empty($item['plink']) && ($item['private'] != 1)) {
} elseif (!empty($item['plink']) && ($item['private'] != self::PRIVATE)) {
$ret = [
'href' => $item['plink'],
'orig' => $item['plink'],

View File

@ -82,7 +82,7 @@ class Term
WHERE `thread`.`visible`
AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
AND NOT `thread`.`private`
AND `thread`.`private` = ?
AND t.`uid` = 0
AND t.`otype` = ?
AND t.`type` = ?
@ -91,6 +91,7 @@ class Term
GROUP BY `term`
ORDER BY `score` DESC
LIMIT ?",
Item::PUBLIC,
Term::OBJECT_TYPE_POST,
Term::HASHTAG,
$period,
@ -122,11 +123,10 @@ class Term
FROM `term` t
JOIN `item` i ON i.`id` = t.`oid` AND i.`uid` = t.`uid`
JOIN `thread` ON `thread`.`iid` = i.`id`
JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
WHERE `thread`.`visible`
AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
AND NOT `thread`.`private`
AND `thread`.`private` = ?
AND `thread`.`wall`
AND `thread`.`origin`
AND t.`otype` = ?
@ -136,6 +136,7 @@ class Term
GROUP BY `term`
ORDER BY `score` DESC
LIMIT ?",
Item::PUBLIC,
Term::OBJECT_TYPE_POST,
Term::HASHTAG,
$period,

View File

@ -301,22 +301,20 @@ class Community extends BaseModule
$values[] = $itemspage;
/// @todo Use "unsearchable" here as well (instead of "hidewall")
$r = DBA::p("SELECT `item`.`uri`, `author`.`url` AS `author-link`, `thread`.`commented` FROM `thread`
STRAIGHT_JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
AND NOT `thread`.`private` AND `thread`.`wall` AND `thread`.`origin`
AND `thread`.`private` = ? AND `thread`.`wall` AND `thread`.`origin`
$sql_accounttype
$sql_boundaries
ORDER BY `thread`.`commented` DESC
LIMIT ?", $values);
LIMIT ?", Item::PUBLIC, $values);
} elseif (self::$content == 'global') {
if (!is_null(self::$accounttype)) {
$condition = ["`uid` = ? AND NOT `author`.`unsearchable` AND NOT `owner`.`unsearchable` AND `owner`.`contact-type` = ?", 0, self::$accounttype];
$condition = ["`uid` = ? AND `private` = ? AND `owner`.`contact-type` = ?", 0, Item::PUBLIC, self::$accounttype];
} else {
$condition = ["`uid` = ? AND NOT `author`.`unsearchable` AND NOT `owner`.`unsearchable`", 0];
$condition = ["`uid` = ? AND `private` = ?", 0, Item::PUBLIC];
}
if (isset($max_id)) {

View File

@ -54,7 +54,7 @@ class Fetch extends BaseModule
'uid', 'title', 'body', 'guid', 'contact-id', 'private', 'created', 'received', 'app', 'location', 'coord', 'network',
'event-id', 'resource-id', 'author-link', 'author-avatar', 'author-name', 'plink', 'owner-link', 'attach'
];
$condition = ['wall' => true, 'private' => false, 'guid' => $guid, 'network' => [Protocol::DFRN, Protocol::DIASPORA]];
$condition = ['wall' => true, 'private' => [Item::PUBLIC, Item::UNLISTED], 'guid' => $guid, 'network' => [Protocol::DFRN, Protocol::DIASPORA]];
$item = Item::selectFirst($fields, $condition);
if (empty($item)) {
$condition = ['guid' => $guid, 'network' => [Protocol::DFRN, Protocol::DIASPORA]];

View File

@ -49,11 +49,11 @@ class Objects extends BaseModule
// At first we try the original post with that guid
// @TODO: Replace with parameter from router
$item = Item::selectFirst(['id'], ['guid' => $a->argv[1], 'origin' => true, 'private' => false]);
$item = Item::selectFirst(['id'], ['guid' => $a->argv[1], 'origin' => true, 'private' => [item::PRIVATE, Item::UNLISTED]]);
if (!DBA::isResult($item)) {
// If no original post could be found, it could possibly be a forum post, there we remove the "origin" field.
// @TODO: Replace with parameter from router
$item = Item::selectFirst(['id', 'author-link'], ['guid' => $a->argv[1], 'private' => false]);
$item = Item::selectFirst(['id', 'author-link'], ['guid' => $a->argv[1], 'private' => [item::PRIVATE, Item::UNLISTED]]);
if (!DBA::isResult($item) || !strstr($item['author-link'], DI::baseUrl()->get())) {
throw new \Friendica\Network\HTTPException\NotFoundException();
}

View File

@ -170,12 +170,12 @@ class Post
$conv = $this->getThread();
$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
$lock = ((($item['private'] == Item::PRIVATE) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
? DI::l10n()->t('Private Message')
: false);
$shareable = in_array($conv->getProfileOwner(), [0, local_user()]) && $item['private'] != 1;
$shareable = in_array($conv->getProfileOwner(), [0, local_user()]) && $item['private'] != Item::PRIVATE;
$edpost = false;

View File

@ -375,7 +375,7 @@ class Processor
Logger::warning('Unknown parent item.', ['uri' => $item['thr-parent']]);
return false;
}
if ($item_private && !$parent['private']) {
if ($item_private && ($parent['private'] == Item::PRIVATE)) {
Logger::warning('Item is private but the parent is not. Dropping.', ['item-uri' => $item['uri'], 'thr-parent' => $item['thr-parent']]);
return false;
}
@ -442,12 +442,19 @@ class Processor
}
$item['network'] = Protocol::ACTIVITYPUB;
$item['private'] = !in_array(0, $activity['receiver']);
$item['author-link'] = $activity['author'];
$item['author-id'] = Contact::getIdForURL($activity['author'], 0, true);
$item['owner-link'] = $activity['actor'];
$item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
if (in_array(0, $activity['receiver']) && !empty($activity['unlisted'])) {
$item['private'] = Item::UNLISTED;
} elseif (in_array(0, $activity['receiver'])) {
$item['private'] = Item::PUBLIC;
} else {
$item['private'] = Item::PRIVATE;
}
$isForum = false;
if (!empty($activity['thread-completion'])) {
@ -481,6 +488,10 @@ class Processor
$stored = false;
foreach ($activity['receiver'] as $receiver) {
if ($receiver == -1) {
continue;
}
$item['uid'] = $receiver;
if ($isForum) {
@ -530,7 +541,7 @@ class Processor
}
// Store send a follow request for every reshare - but only when the item had been stored
if ($stored && !$item['private'] && ($item['gravity'] == GRAVITY_PARENT) && ($item['author-link'] != $item['owner-link'])) {
if ($stored && ($item['private'] != Item::PRIVATE) && ($item['gravity'] == GRAVITY_PARENT) && ($item['author-link'] != $item['owner-link'])) {
$author = APContact::getByURL($item['owner-link'], false);
// We send automatic follow requests for reshared messages. (We don't need though for forum posts)
if ($author['type'] != 'Group') {

View File

@ -509,11 +509,12 @@ class Receiver
* @param array $activity
* @param string $actor
* @param array $tags
* @param boolean $fetch_unlisted
*
* @return array with receivers (user id)
* @throws \Exception
*/
private static function getReceivers($activity, $actor, $tags = [])
private static function getReceivers($activity, $actor, $tags = [], $fetch_unlisted = false)
{
$receivers = [];
@ -551,6 +552,11 @@ class Receiver
$receivers['uid:0'] = 0;
}
// Add receiver "-1" for unlisted posts
if ($fetch_unlisted && ($receiver == self::PUBLIC_COLLECTION) && ($element == 'as:cc')) {
$receivers['uid:-1'] = -1;
}
if (($receiver == self::PUBLIC_COLLECTION) && !empty($actor)) {
// This will most likely catch all OStatus connections to Mastodon
$condition = ['alias' => [$actor, Strings::normaliseLink($actor)], 'rel' => [Contact::SHARING, Contact::FRIEND]
@ -1022,7 +1028,9 @@ class Receiver
}
}
$object_data['receiver'] = self::getReceivers($object, $object_data['actor'], $object_data['tags']);
$object_data['receiver'] = self::getReceivers($object, $object_data['actor'], $object_data['tags'], true);
$object_data['unlisted'] = in_array(-1, $object_data['receiver']);
unset($object_data['receiver']['uid:-1']);
// Common object data:

View File

@ -173,7 +173,7 @@ class Transmitter
$public_contact = Contact::getIdForURL($owner['url'], 0, true);
$condition = ['uid' => 0, 'contact-id' => $public_contact, 'author-id' => $public_contact,
'private' => false, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'private' => [Item::PUBLIC, Item::UNLISTED], 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'deleted' => false, 'visible' => true, 'moderated' => false];
$count = DBA::count('item', $condition);
@ -401,7 +401,7 @@ class Transmitter
$terms = Term::tagArrayFromItemId($item['id'], [Term::MENTION, Term::IMPLICIT_MENTION]);
if (!$item['private']) {
if ($item['private'] != Item::PRIVATE) {
// Directly mention the original author upon a quoted reshare.
// Else just ensure that the original author receives the reshare.
$announce = self::getAnnounceArray($item);
@ -413,7 +413,12 @@ class Transmitter
$data = array_merge($data, self::fetchPermissionBlockFromConversation($item));
// Check if the item is completely public or unlisted
if ($item['private'] == Item::PUBLIC) {
$data['to'][] = ActivityPub::PUBLIC_COLLECTION;
} else {
$data['cc'][] = ActivityPub::PUBLIC_COLLECTION;
}
foreach ($terms as $term) {
$profile = APContact::getByURL($term['url'], false);
@ -467,13 +472,13 @@ class Transmitter
$data['to'][] = $profile['url'];
} else {
$data['cc'][] = $profile['url'];
if (!$item['private'] && !empty($actor_profile['followers'])) {
if (($item['private'] != Item::PRIVATE) && $item['private'] && !empty($actor_profile['followers'])) {
$data['cc'][] = $actor_profile['followers'];
}
}
} else {
// Public thread parent post always are directed to the followers
if (!$item['private'] && !$forum_mode) {
if (($item['private'] != Item::PRIVATE) && !$forum_mode) {
$data['cc'][] = $actor_profile['followers'];
}
}

View File

@ -182,7 +182,7 @@ class DFRN
// default permissions - anonymous user
$sql_extra = " AND NOT `item`.`private` ";
$sql_extra = sprintf(" AND `item`.`private` != %s ", Item::PRIVATE);
$r = q(
"SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type`
@ -234,7 +234,7 @@ class DFRN
if (!empty($set)) {
$sql_extra = " AND `item`.`psid` IN (" . implode(',', $set) .")";
} else {
$sql_extra = " AND NOT `item`.`private`";
$sql_extra = sprintf(" AND `item`.`private` != %s", Item::PRIVATE);
}
}
@ -332,7 +332,7 @@ class DFRN
if ($public_feed) {
$type = 'html';
// catch any email that's in a public conversation and make sure it doesn't leak
if ($item['private']) {
if ($item['private'] == Item::PRIVATE) {
continue;
}
} else {
@ -955,7 +955,7 @@ class DFRN
$entry->setAttribute("xmlns:statusnet", ActivityNamespace::STATUSNET);
}
if ($item['private']) {
if ($item['private'] == Item::PRIVATE) {
$body = Item::fixPrivatePhotos($item['body'], $owner['uid'], $item, $cid);
} else {
$body = $item['body'];
@ -1050,7 +1050,8 @@ class DFRN
}
if ($item['private']) {
XML::addElement($doc, $entry, "dfrn:private", ($item['private'] ? $item['private'] : 1));
// Friendica versions prior to 2020.3 can't handle "unlisted" properly. So we can only transmit public and private
XML::addElement($doc, $entry, "dfrn:private", ($item['private'] == Item::PRIVATE ? Item::PRIVATE : Item::PUBLIC));
}
if ($item['extid']) {

View File

@ -2211,7 +2211,7 @@ class Diaspora
return false;
}
$item = Item::selectFirst(['id'], ['guid' => $parent_guid, 'origin' => true, 'private' => false]);
$item = Item::selectFirst(['id'], ['guid' => $parent_guid, 'origin' => true, 'private' => [Item::PUBLIC, Item::UNLISTED]]);
if (!DBA::isResult($item)) {
Logger::log('Item not found, no origin or private: '.$parent_guid);
return false;
@ -2523,7 +2523,7 @@ class Diaspora
// Do we already have this item?
$fields = ['body', 'title', 'attach', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
'author-name', 'author-link', 'author-avatar'];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]];
$item = Item::selectFirst($fields, $condition);
if (DBA::isResult($item)) {
@ -2567,7 +2567,7 @@ class Diaspora
if ($stored) {
$fields = ['body', 'title', 'attach', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
'author-name', 'author-link', 'author-avatar'];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => false];
$condition = ['guid' => $guid, 'visible' => true, 'deleted' => false, 'private' => [Item::PUBLIC, Item::UNLISTED]];
$item = Item::selectFirst($fields, $condition);
if (DBA::isResult($item)) {
@ -2711,7 +2711,7 @@ class Diaspora
$datarray["app"] = $original_item["app"];
$datarray["plink"] = self::plink($author, $guid);
$datarray["private"] = (($public == "false") ? 1 : 0);
$datarray["private"] = (($public == "false") ? Item::PRIVATE : Item::PUBLIC);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at;
$datarray["object-type"] = $original_item["object-type"];
@ -2941,7 +2941,7 @@ class Diaspora
}
$datarray["plink"] = self::plink($author, $guid);
$datarray["private"] = (($public == "false") ? 1 : 0);
$datarray["private"] = (($public == "false") ? Item::PRIVATE : Item::PUBLIC);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at;
if (isset($address["address"])) {
@ -3245,7 +3245,7 @@ class Diaspora
private static function sendParticipation(array $contact, array $item)
{
// Don't send notifications for private postings
if ($item['private']) {
if ($item['private'] == Item::PRIVATE) {
return;
}
@ -3536,12 +3536,12 @@ class Diaspora
$myaddr = self::myHandle($owner);
$public = ($item["private"] ? "false" : "true");
$public = ($item["private"] == Item::PRIVATE ? "false" : "true");
$created = DateTimeFormat::utc($item['received'], DateTimeFormat::ATOM);
$edited = DateTimeFormat::utc($item["edited"] ?? $item["created"], DateTimeFormat::ATOM);
// Detect a share element and do a reshare
if (!$item['private'] && ($ret = self::isReshare($item["body"]))) {
if (($item['private'] != Item::PRIVATE) && ($ret = self::isReshare($item["body"]))) {
$message = ["author" => $myaddr,
"guid" => $item["guid"],
"created_at" => $created,

View File

@ -220,7 +220,7 @@ class Feed {
$header["wall"] = 0;
$header["origin"] = 0;
$header["gravity"] = GRAVITY_PARENT;
$header["private"] = 2;
$header["private"] = Item::PUBLIC;
$header["verb"] = Activity::POST;
$header["object-type"] = Activity\ObjectType::NOTE;

View File

@ -1682,7 +1682,7 @@ class OStatus
$entry = self::entryHeader($doc, $owner, $item, $toplevel);
$condition = ['uid' => $owner["uid"], 'guid' => $repeated_guid, 'private' => false,
$condition = ['uid' => $owner["uid"], 'guid' => $repeated_guid, 'private' => [Item::PUBLIC, Item::UNLISTED],
'network' => [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]];
$repeated_item = Item::selectFirst([], $condition);
if (!DBA::isResult($repeated_item)) {
@ -1827,7 +1827,7 @@ class OStatus
{
$item["id"] = $item["parent"] = 0;
$item["created"] = $item["edited"] = date("c");
$item["private"] = true;
$item["private"] = Item::PRIVATE;
$contact = Probe::uri($item['follow']);
@ -2120,7 +2120,7 @@ class OStatus
]);
}
if (!$item["private"] && !$feed_mode) {
if (($item['private'] != Item::PRIVATE) && !$feed_mode) {
XML::addElement($doc, $entry, "link", "", ["rel" => "ostatus:attention",
"href" => "http://activityschema.org/collection/public"]);
XML::addElement($doc, $entry, "link", "", ["rel" => "mentioned",
@ -2212,8 +2212,8 @@ class OStatus
$authorid = Contact::getIdForURL($owner["url"], 0, true);
$condition = ["`uid` = ? AND `received` > ? AND NOT `deleted`
AND NOT `private` AND `visible` AND `wall` AND `parent-network` IN (?, ?)",
$owner["uid"], $check_date, Protocol::OSTATUS, Protocol::DFRN];
AND `private` != ? AND `visible` AND `wall` AND `parent-network` IN (?, ?)",
$owner["uid"], $check_date, Item::PRIVATE, Protocol::OSTATUS, Protocol::DFRN];
if ($filter === 'comments') {
$condition[0] .= " AND `object-type` = ? ";

View File

@ -122,7 +122,9 @@ class JsonLD
'ostatus' => (object)['@id' => 'http://ostatus.org#', '@type' => '@id'],
'dc' => (object)['@id' => 'http://purl.org/dc/terms/', '@type' => '@id'],
'toot' => (object)['@id' => 'http://joinmastodon.org/ns#', '@type' => '@id'],
'litepub' => (object)['@id' => 'http://litepub.social/ns#', '@type' => '@id']];
'litepub' => (object)['@id' => 'http://litepub.social/ns#', '@type' => '@id'],
'sc' => (object)['@id' => 'http://schema.org#', '@type' => '@id'],
'pt' => (object)['@id' => 'https://joinpeertube.org/ns#', '@type' => '@id']];
// Preparation for adding possibly missing content to the context
if (!empty($json['@context']) && is_string($json['@context'])) {

View File

@ -176,7 +176,7 @@ class Delivery
&& empty($parent['allow_gid'])
&& empty($parent['deny_cid'])
&& empty($parent['deny_gid'])
&& !$parent["private"]) {
&& ($parent["private"] != Model\Item::PRIVATE)) {
$public_message = true;
}
}

View File

@ -151,6 +151,8 @@ class Notifier
// If this is a public conversation, notify the feed hub
$public_message = true;
$unlisted = false;
// Do a PuSH
$push_notify = false;
@ -183,6 +185,8 @@ class Notifier
Logger::info('Threaded comment', ['diaspora_delivery' => (int)$diaspora_delivery]);
}
$unlisted = $target_item['private'] == Item::UNLISTED;
// This is IMPORTANT!!!!
// We will only send a "notify owner to relay" or followup message if the referenced post
@ -245,8 +249,7 @@ class Notifier
Logger::info('Followup', ['target' => $target_id, 'guid' => $target_item['guid'], 'to' => $parent['contact-id']]);
//if (!$target_item['private'] && $target_item['wall'] &&
if (!$target_item['private'] &&
if (($target_item['private'] != Item::PRIVATE) &&
(strlen($target_item['allow_cid'].$target_item['allow_gid'].
$target_item['deny_cid'].$target_item['deny_gid']) == 0))
$push_notify = true;
@ -410,7 +413,7 @@ class Notifier
if ($public_message && !in_array($cmd, [Delivery::MAIL, Delivery::SUGGESTION]) && !$followup) {
$relay_list = [];
if ($diaspora_delivery) {
if ($diaspora_delivery && !$unlisted) {
$batch_delivery = true;
$relay_list_stmt = DBA::p(

View File

@ -657,11 +657,11 @@ class OnePoll
$datarray['owner-avatar'] = $contact['photo'];
if ($datarray['parent-uri'] === $datarray['uri']) {
$datarray['private'] = 1;
$datarray['private'] = Item::PRIVATE;
}
if (!DI::pConfig()->get($importer_uid, 'system', 'allow_public_email_replies')) {
$datarray['private'] = 1;
$datarray['private'] = Item::PRIVATE;
$datarray['allow_cid'] = '<' . $contact['id'] . '>';
}

View File

@ -51,7 +51,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1333);
define('DB_UPDATE_VERSION', 1334);
}
return [
@ -647,7 +647,7 @@ return [
"extid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"post-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Post type (personal note, bookmark, ...)"],
"global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"private" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "distribution is restricted"],
"private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "distribution is restricted"],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"moderated" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been deleted"],
@ -1294,7 +1294,7 @@ return [
"received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""],
"changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""],
"wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"private" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"moderated" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],

View File

@ -53,6 +53,8 @@
{{$hide_wall nofilter}}
{{$unlisted nofilter}}
{{$blockwall nofilter}}
{{$blocktags nofilter}}

View File

@ -89,6 +89,8 @@
{{$hide_wall nofilter}}
{{$unlisted nofilter}}
{{$blockwall nofilter}}
{{$blocktags nofilter}}