aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Lib/Libzot.php312
-rw-r--r--include/items.php2
2 files changed, 161 insertions, 153 deletions
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index b8067bc56..265bcb376 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -1157,7 +1157,6 @@ class Libzot {
else {
$item = [];
}
-
logger($AS->debug(), LOGGER_DATA);
}
@@ -1364,11 +1363,13 @@ class Libzot {
static function find_parent_owner_hashes($env, $act) {
$r = [];
- $thread_parent = self::find_parent($env, $act);
- if ($thread_parent) {
- $uids = q("SELECT uid FROM item WHERE thr_parent = '%s' OR parent_mid = '%s'",
- dbesc($thread_parent),
- dbesc($thread_parent)
+ $parent = self::find_parent($env, $act);
+
+ if ($parent) {
+ $uids = q("SELECT uid FROM item WHERE thr_parent = '%s' OR parent_mid = '%s' OR mid = '%s'",
+ dbesc($parent),
+ dbesc($parent),
+ dbesc($parent)
);
if ($uids) {
@@ -1579,6 +1580,39 @@ class Libzot {
continue;
}
+ $arr['item_wall'] = 0;
+
+ // This is our own post, possibly coming from a channel clone
+ if ($arr['owner_xchan'] === $d) {
+ $arr['item_wall'] = 1;
+ }
+
+ if (isset($arr['item_deleted']) && $arr['item_deleted']) {
+
+ // remove_community_tag is a no-op if this isn't a community tag activity
+ // self::remove_community_tag($sender, $arr, $channel['channel_id']);
+
+ // set these just in case we need to store a fresh copy of the deleted post.
+ // This could happen if the delete got here before the original post did.
+
+ $arr['aid'] = $channel['channel_account_id'];
+ $arr['uid'] = $channel['channel_id'];
+
+ $item_id = self::delete_imported_item($sender, $act, $arr, $channel['channel_id'], $relay);
+ $DR->update(($item_id) ? 'deleted' : 'delete_failed');
+ $result[] = $DR->get();
+
+ if ($relay && $item_id) {
+ logger('process_delivery: invoking relay');
+ Master::Summon(['Notifier', 'relay', intval($item_id), 'delete']);
+ $DR->update('relayed');
+ $result[] = $DR->get();
+ }
+
+ continue;
+ }
+
+
// allow public postings to the sys channel regardless of permissions, but not
// for comments travelling upstream. Wait and catch them on the way down.
// They may have been blocked by the owner.
@@ -1605,119 +1639,23 @@ class Libzot {
}
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
- $perm = 'send_stream';
- if (($arr['mid'] !== $arr['parent_mid']) && ($relay))
- $perm = 'post_comments';
-
- // This is our own post, possibly coming from a channel clone
-
- if ($arr['owner_xchan'] == $d) {
- $arr['item_wall'] = 1;
- }
- else {
- $arr['item_wall'] = 0;
- }
-
- $friendofriend = false;
-
- if ((!$tag_delivery) && (!$local_public)) {
- $allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
-
- $permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system', 'permit_all_mentions') && i_am_mentioned($channel, $arr));
-
- if (!$allowed) {
- if ($perm === 'post_comments') {
- $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($arr['parent_mid']),
- intval($channel['channel_id'])
- );
- if ($parent) {
- $allowed = can_comment_on_post($sender, $parent[0]);
- if (!$allowed && $permit_mentions) {
- $allowed = true;
- }
-
- if (!$allowed) {
- if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') {
- $arr['item_blocked'] = ITEM_MODERATED;
- $allowed = true;
- }
- }
- }
- }
- elseif ($permit_mentions) {
- $allowed = true;
- }
-
-
- }
-
- if ($request) {
- // Conversation fetches (e.g. $request == true) take place for
- // a) new comments on expired posts
- // b) hyperdrive (friend-of-friend) conversations
- // c) Repeats of posts by others
-
-
- // over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations
- // (if hyperdrive is enabled) and repeated posts by a friend.
- // If $allowed is already true, this is probably the conversation of a direct friend or a
- // conversation fetch for a new comment on an expired post
- // Comments of all these activities are allowed and will only be rejected (later) if the parent
- // doesn't exist.
-
- if ($perm === 'send_stream') {
- if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false)) {
- $allowed = true;
- }
- }
- else {
- $allowed = true;
- }
-
- $friendofriend = true;
- }
-
- if (intval($arr['item_private']) === 2) {
- if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
- $allowed = false;
- }
- }
-
- if (!$allowed) {
- logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
- $DR->update('permission denied');
- $result[] = $DR->get();
- continue;
- }
- }
-
- // logger('item: ' . print_r($arr,true), LOGGER_DATA);
+ $perm = 'send_stream';
if ($arr['mid'] !== $arr['parent_mid']) {
- logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"');
+ if ($relay)
+ $perm = 'post_comments';
- // check source route.
- // We are only going to accept comments from this sender if the comment has the same route as the top-level-post,
- // this is so that permissions mismatches between senders apply to the entire conversation
- // As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
- // processing it is pointless.
-
- $r = q("select route, id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
+ $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
- if (!$r) {
+ if (!$parent) {
$DR->update('comment parent not found');
$result[] = $DR->get();
- if ($relay || $request || $local_public) {
- continue;
- }
-
// We don't seem to have a copy of this conversation or at least the parent
// - so request a copy of the entire conversation to date.
// Don't do this if it's a relay post as we're the ones who are supposed to
@@ -1729,28 +1667,49 @@ class Libzot {
// the top level post is unlikely to be imported and
// this is just an exercise in futility.
+ if ($relay || $request || $local_public || !perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
+ continue;
+ }
+
if ($arr['verb'] === 'Announce') {
- Activity::fetch_and_store_parents($channel, $sender, $arr, true);
+
+ // TODO: move this to background
+
+ if (!Activity::fetch_and_store_parents($channel, $sender, $arr, true)) {
+ continue;
+ }
+
+ $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($arr['parent_mid']),
+ intval($channel['channel_id'])
+ );
+
}
else {
- if (perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
- Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]);
- }
+ Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]);
continue;
}
+
}
- if ($r[0]['obj_type'] === 'Question') {
+ logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"');
+
+ // check source route.
+ // We are only going to accept comments from this sender if the comment has the same route as the top-level-post,
+ // this is so that permissions mismatches between senders apply to the entire conversation
+ // As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
+ // processing it is pointless.
+
+ if ($parent[0]['obj_type'] === 'Question') {
// route checking doesn't work correctly here because we've changed the privacy
- $r[0]['route'] = EMPTY_STR;
+ $parent[0]['route'] = EMPTY_STR;
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
if ($arr['obj_type'] === ACTIVITY_OBJ_COMMENT && $arr['title'] && (!$arr['body'])) {
$arr['obj_type'] = 'Answer';
}
}
-
- if ($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
+ if ($relay || (intval($parent[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
// reset the route in case it travelled a great distance upstream
// use our parent's route so when we go back downstream we'll match
// with whatever route our parent has.
@@ -1758,10 +1717,8 @@ class Libzot {
// but we are now getting comments via listener delivery
// and if there is no privacy on this or the parent, we don't care about the route,
// so just set the owner and route accordingly.
- $arr['route'] = $r[0]['route'];
- $arr['owner_xchan'] = $r[0]['owner_xchan'];
-
-
+ $arr['route'] = $parent[0]['route'];
+ $arr['owner_xchan'] = $parent[0]['owner_xchan'];
}
else {
@@ -1771,7 +1728,7 @@ class Libzot {
// only compare the last hop since it could have arrived at the last location any number of ways.
// Always accept empty routes and firehose items (route contains 'undefined') .
- $existing_route = explode(',', $r[0]['route']);
+ $existing_route = explode(',', $parent[0]['route']);
$routes = count($existing_route);
if ($routes) {
$last_hop = array_pop($existing_route);
@@ -1788,8 +1745,8 @@ class Libzot {
$current_route = ((isset($arr['route']) && $arr['route']) ? $arr['route'] . ',' : '') . $sender;
if ($last_hop && $last_hop != $sender) {
- logger('comment route mismatch: parent route = ' . $r[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG);
- logger('comment route mismatch: parent msg = ' . $r[0]['id'], LOGGER_DEBUG);
+ logger('comment route mismatch: parent route = ' . $parent[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG);
+ logger('comment route mismatch: parent msg = ' . $parent[0]['id'], LOGGER_DEBUG);
$DR->update('comment route mismatch');
$result[] = $DR->get();
continue;
@@ -1802,42 +1759,86 @@ class Libzot {
}
}
- // This is used to fetch allow/deny rules if either the sender
- // or owner is a connection. post_is_importable() evaluates all of them
- $abook = q("select * from abook where abook_channel = %d and ( abook_xchan = '%s' OR abook_xchan = '%s' )",
- intval($channel['channel_id']),
- dbesc($arr['owner_xchan']),
- dbesc($arr['author_xchan'])
- );
+ if (!$tag_delivery && !$local_public) {
+ $allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
- if (isset($arr['item_deleted']) && $arr['item_deleted']) {
+ $permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system', 'permit_all_mentions') && i_am_mentioned($channel, $arr));
- // remove_community_tag is a no-op if this isn't a community tag activity
- self::remove_community_tag($sender, $arr, $channel['channel_id']);
+ if (!$allowed) {
+ if ($parent && $perm === 'send_stream') {
+ // if we own the parent we will accept its comments
+ $allowed = true;
+ }
- // set these just in case we need to store a fresh copy of the deleted post.
- // This could happen if the delete got here before the original post did.
+ elseif ($parent && $perm === 'post_comments') {
+ $allowed = can_comment_on_post($sender, $parent[0]);
- $arr['aid'] = $channel['channel_account_id'];
- $arr['uid'] = $channel['channel_id'];
+ if (!$allowed && $permit_mentions) {
+ $allowed = true;
+ }
+
+ if (!$allowed) {
+ if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') {
+ $arr['item_blocked'] = ITEM_MODERATED;
+ $allowed = true;
+ }
+ }
+
+ }
+ elseif ($permit_mentions) {
+ $allowed = true;
+ }
- $item_id = self::delete_imported_item($sender, $act, $arr, $channel['channel_id'], $relay);
- $DR->update(($item_id) ? 'deleted' : 'delete_failed');
- $result[] = $DR->get();
- if ($relay && $item_id) {
- logger('process_delivery: invoking relay');
- Master::Summon(['Notifier', 'relay', intval($item_id), 'delete']);
- $DR->update('relayed');
- $result[] = $DR->get();
}
- continue;
+ if ($request) {
+ // Conversation fetches (e.g. $request == true) take place for
+ // a) new comments on expired posts
+ // b) if we received an announce
+
+
+ // over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations
+ // (if hyperdrive is enabled) and repeated posts by a friend.
+ // If $allowed is already true, this is probably the conversation of a direct friend or a
+ // conversation fetch for a new comment on an expired post
+ // Comments of all these activities are allowed and will only be rejected (later) if the parent
+ // doesn't exist.
+
+ if ($perm === 'send_stream') {
+ if ($force) {
+ $allowed = true;
+ }
+ }
+ else {
+ $allowed = true;
+ }
+ }
+
+ if (intval($arr['item_private']) === 2) {
+ if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
+ $allowed = false;
+ }
+ }
+
+ if (!$allowed) {
+ logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
+ $DR->update('permission denied');
+ $result[] = $DR->get();
+ continue;
+ }
}
+ // This is used to fetch allow/deny rules if either the sender
+ // or owner is a connection. post_is_importable() evaluates all of them
+ $abook = q("select * from abook where abook_channel = %d and ( abook_xchan = '%s' OR abook_xchan = '%s' )",
+ intval($channel['channel_id']),
+ dbesc($arr['owner_xchan']),
+ dbesc($arr['author_xchan'])
+ );
+
// reactions such as like and dislike could have an mid with /activity/ in it.
// Check for both forms in order to prevent duplicates.
-
$r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
dbesc($arr['mid']),
dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
@@ -1845,7 +1846,6 @@ class Libzot {
);
if ($r) {
-
$item_id = $r[0]['id'];
if (intval($r[0]['item_deleted'])) {
@@ -1915,7 +1915,6 @@ class Libzot {
if (post_is_importable($arr['uid'], $arr, $abook)) {
$item_result = item_store($arr);
if ($item_result['success']) {
-
$item_id = $item_result['item_id'];
if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
@@ -1957,6 +1956,7 @@ class Libzot {
// preserve conversations with which you are involved from expiration
$stored = ((isset($item_result['item'])) ? $item_result['item'] : false);
+
if ((is_array($stored)) && ($stored['id'] != $stored['parent'])
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
retain_item($stored['item']['parent']);
@@ -2320,12 +2320,20 @@ class Libzot {
// this information from the metadata should have no other discernible impact.
if (($stored['id'] != $stored['parent']) && intval($stored['item_origin'])) {
- q("update item set item_origin = 0 where id = %d and uid = %d",
- intval($stored['id']),
- intval($stored['uid'])
+ q("update item set item_origin = 0 where id = %d",
+ intval($stored['id'])
);
}
- }
+ } else {
+ if ($stored['id'] !== $stored['parent']) {
+ q(
+ "update item set commented = '%s', changed = '%s' where id = %d",
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($stored['parent'])
+ );
+ }
+ }
// Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
diff --git a/include/items.php b/include/items.php
index d628fb29e..56534c4e4 100644
--- a/include/items.php
+++ b/include/items.php
@@ -353,7 +353,7 @@ function can_comment_on_post($observer_xchan, $item) {
case 'specific':
case 'contacts':
case '':
- if(local_channel() && get_abconfig(local_channel(), (($item['verb'] === ACTIVITY_SHARE) ? $item['author_xchan'] : $item['owner_xchan']), 'their_perms', 'post_comments')) {
+ if(local_channel() && get_abconfig(local_channel(), (($item['verb'] === ACTIVITY_SHARE) ? $item['source_xchan'] : $item['owner_xchan']), 'their_perms', 'post_comments')) {
return true;
}
if(intval($item['item_wall']) && perm_is_allowed($item['uid'],$observer_xchan,'post_comments')) {