aboutsummaryrefslogtreecommitdiffstats
path: root/include/items.php
diff options
context:
space:
mode:
Diffstat (limited to 'include/items.php')
-rwxr-xr-xinclude/items.php156
1 files changed, 128 insertions, 28 deletions
diff --git a/include/items.php b/include/items.php
index 2cee376d0..95b696034 100755
--- a/include/items.php
+++ b/include/items.php
@@ -7,6 +7,7 @@
use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\MarkdownSoap;
use Zotlabs\Lib\MessageFilter;
+use Zotlabs\Lib\ThreadListener;
use Zotlabs\Lib\IConfig;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\AccessList;
@@ -25,7 +26,7 @@ require_once('include/permissions.php');
*
* @param array $item
* @param[out] boolean $private_envelope
- * @param boolean $include_groups
+ * @param boolean $include_groups
* @return array containing the recipients
*/
function collect_recipients($item, &$private_envelope,$include_groups = true) {
@@ -95,9 +96,24 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
//$sys = get_sys_channel();
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
- $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
+
+ $hookinfo = [
+ 'recipients' => [],
+ 'item' => $item,
+ 'private_envelope' => $private_envelope,
+ 'include_groups' => $include_groups
+ ];
+
+ call_hooks('collect_public_recipients',$hookinfo);
+
+ if ($hookinfo['recipients']) {
+ $r = $hookinfo['recipients'];
+ } else {
+ $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
intval($item['uid'])
- );
+ );
+ }
+
if($r) {
// filter out restrictive public_policy settings from remote networks
@@ -126,6 +142,22 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
// $recipients[] = $sys['xchan_hash'];
}
+
+ // Forward to thread listeners, *unless* there is even a remote hint that the item
+ // might have some privacy attached. This could be (for instance) an ActivityPub DM
+ // in the middle of a public thread. Unless we can guarantee beyond all doubt that
+ // this is public, don't allow it to go to thread listeners.
+
+ if(! intval($item['item_private'])) {
+ $r = ThreadListener::fetch_by_target($item['parent_mid']);
+ if($r) {
+ foreach($r as $rv) {
+ $recipients[] = $rv['portable_id'];
+ }
+ }
+ }
+
+
// Add the authors of any posts in this thread, if they are known to us.
// This is specifically designed to forward wall-to-wall posts to the original author,
// in case they aren't a connection but have permission to write on our wall.
@@ -395,7 +427,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
if(! $arr['mid']) {
- $arr['uuid'] = ((x($arr,'uuid')) ? $arr['uuid'] : item_message_id());
+ $arr['uuid'] = ((x($arr,'uuid')) ? $arr['uuid'] : item_message_id());
}
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : z_root() . '/item/' . $arr['uuid']);
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']);
@@ -420,7 +452,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
$arr['comment_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'],'post_comments'));
if ((! $arr['plink']) && (intval($arr['item_thread_top']))) {
- $arr['plink'] = substr(z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']),0,190);
+ $arr['plink'] = substr(z_root() . '/channel/' . $channel['channel_address'] . '/' . (filter_var($arr['mid'], FILTER_VALIDATE_URL) === false ? '?f=&mid=' : '') . urlencode($arr['mid']),0,190);
}
@@ -454,6 +486,8 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
*/
call_hooks('post_local_end', $ret['activity']);
}
+ else
+ return $ret;
if($post_id && $deliver) {
Master::Summon([ 'Notifier','activity',$post_id ]);
@@ -729,11 +763,11 @@ function get_item_elements($x,$allow_code = false) {
// check the supplied signature against the supplied content.
// Note that we will purify the content which could change it.
- $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
+ $r = q("select xchan_pubkey, xchan_network from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['author_xchan'])
);
if($r) {
- if($r[0]['xchan_pubkey']) {
+ if($r[0]['xchan_pubkey'] && $r[0]['xchan_network'] === 'zot') {
if(rsa_verify($x['body'],base64url_decode($arr['sig']),$r[0]['xchan_pubkey'])) {
$arr['item_verified'] = 1;
}
@@ -880,6 +914,16 @@ function import_author_xchan($x) {
if(array_key_exists('network',$x) && $x['network'] === 'zot')
return $y;
+ // perform zot6 discovery
+
+ if($x['url']) {
+ $y = discover_by_webbie($x['url'],'zot6');
+
+ if($y) {
+ return $y;
+ }
+ }
+
if($x['network'] === 'rss') {
$y = import_author_rss($x);
}
@@ -1591,6 +1635,14 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
'item' => $arr,
'allow_exec' => $allow_exec
];
+
+ if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
+ /* Custom items are not stored by default
+ because they require an addon to process. */
+ $d['item']['cancel']=true;
+
+ call_hooks('item_custom',$d);
+ }
/**
* @hooks item_store
* Called when item_store() stores a record of type item.
@@ -1878,11 +1930,21 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
if($parent_deleted)
$arr['item_deleted'] = 1;
- $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d and revision = %d LIMIT 1",
- dbesc($arr['mid']),
- intval($arr['uid']),
- intval($arr['revision'])
- );
+ if($arr['uuid']) {
+ $r = q("SELECT id FROM item WHERE uuid = '%s' AND uid = %d and revision = %d LIMIT 1",
+ dbesc($arr['uuid']),
+ intval($arr['uid']),
+ intval($arr['revision'])
+ );
+ }
+ else {
+ $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d and revision = %d LIMIT 1",
+ dbesc($arr['mid']),
+ intval($arr['uid']),
+ intval($arr['revision'])
+ );
+ }
+
if($r) {
logger('duplicate item ignored. ' . print_r($arr,true));
$ret['message'] = 'duplicate post.';
@@ -2016,8 +2078,20 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
*/
call_hooks('post_remote_end', $arr);
+ /**
+ * @hooks item_stored
+ * Called after new item is stored in the database.
+ * (By this time we have an item_id and other frequently needed info.)
+ */
+ call_hooks('item_stored',$arr);
+
item_update_parent_commented($arr);
+
+ if(strpos($arr['body'],'[embed]') !== false) {
+ Master::Summon([ 'Cache_embeds', $current_post ]);
+ }
+
// If _creating_ a deleted item, don't propagate it further or send out notifications.
// We need to store the item details just in case the delete came in before the original post,
// so that we have an item in the DB that's marked deleted and won't store a fresh post
@@ -2049,6 +2123,15 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
'item' => $arr,
'allow_exec' => $allow_exec
];
+
+ if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
+ /* Custom items are not stored by default
+ because they require an addon to process. */
+ $d['item']['cancel']=true;
+
+ call_hooks('item_custom_update',$d);
+ }
+
/**
* @hooks item_store_update
* Called when item_store_update() is called to update a stored item. It
@@ -2339,6 +2422,19 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
*/
call_hooks('post_remote_update_end', $arr);
+ /**
+ * @hooks item_stored_update
+ * Called after updated item is stored in the database.
+ */
+ call_hooks('item_stored_update',$arr);
+
+ if(strpos($arr['body'],'[embed]') !== false) {
+ Master::Summon([ 'Cache_embeds', $orig_post_id ]);
+ }
+
+
+
+
if($deliver) {
send_status_notifications($orig_post_id,$arr);
tag_deliver($uid,$orig_post_id);
@@ -2355,15 +2451,15 @@ function item_update_parent_commented($item) {
$update_parent = true;
- // update the commented timestamp on the parent
+ // update the commented timestamp on the parent
// - unless this is a moderated comment or a potential clone of an older item
- // which we don't wish to bring to the surface. As the queue only holds deliveries
- // for 3 days, it's suspected of being an older cloned item if the creation time
+ // which we don't wish to bring to the surface. As the queue only holds deliveries
+ // for 3 days, it's suspected of being an older cloned item if the creation time
//is older than that.
if(intval($item['item_blocked']) === ITEM_MODERATED)
$update_parent = false;
-
+
if($item['created'] < datetime_convert('','','now - 4 days'))
$update_parent = false;
@@ -2959,7 +3055,9 @@ function tgroup_check($uid, $item) {
* @param array $channel
* @param array $item
* @param int $item_id
- * @param boolean $parent
+ * @param array $parent
+ * @param boolean $edit (optional) default false
+ * @return void
*/
function start_delivery_chain($channel, $item, $item_id, $parent, $edit = false) {
@@ -2994,7 +3092,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $edit = false)
}
// This will change the author to the post owner. Useful for RSS feeds which are to be syndicated
- // to federated platforms which can't verify the identity of the author.
+ // to federated platforms which can't verify the identity of the author.
// This MAY cause you to run afoul of copyright law.
$rewrite_author = intval(get_abconfig($channel['channel_id'],$item['owner_xchan'],'system','rself'));
@@ -3507,7 +3605,7 @@ function item_expire($uid,$days,$comment_days = 7) {
if(! $comment_days)
$comment_days = 7;
-
+
// $expire_network_only = save your own wall posts
// and just expire conversations started by others
// do not enable this until we can pass bulk delete messages through zot
@@ -3808,6 +3906,8 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
intval(TERM_OBJ_POST)
);
+ ThreadListener::delete_by_target($item['mid']);
+
/** @FIXME remove notifications for this item */
return true;
@@ -4178,7 +4278,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
if($arr['mid'])
$sql_options .= " and parent_mid = '" . dbesc($arr['mid']) . "' ";
- $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE item_thread_top = 1 $sql_options $item_normal ) ";
+ $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE $item_uids and item_thread_top = 1 $sql_options $item_normal ) ";
if($arr['since_id'])
$sql_extra .= " and item.id > " . $since_id . " ";
@@ -4502,7 +4602,7 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow,
$first_access_tag = true;
foreach($linkified as $x) {
- $access_tag = $x['access_tag'];
+ $access_tag = $x['success']['access_tag'];
if(($access_tag) && (! $parent_item)) {
logger('access_tag: ' . $tag . ' ' . print_r($access_tag,true), LOGGER_DATA);
if ($first_access_tag && (! get_pconfig($profile_uid,'system','no_private_mention_acl_override'))) {
@@ -4608,7 +4708,7 @@ function sync_an_item($channel_id,$item_id) {
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
- build_sync_packet($channel_d,array('item' => array(encode_item($sync_item[0],true))));
+ build_sync_packet($channel_id, array('item' => array(encode_item($sync_item[0],true))));
}
}
@@ -4629,10 +4729,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
if(! stristr($image,z_root() . '/photo/'))
continue;
$image_uri = substr($image,strrpos($image,'/') + 1);
- if(strpos($image_uri,'-') !== false)
- $image_uri = substr($image_uri,0, strpos($image_uri,'-'));
- if(strpos($image_uri,'.') !== false)
- $image_uri = substr($image_uri,0, strpos($image_uri,'.'));
+ if(strrpos($image_uri,'-') !== false)
+ $image_uri = substr($image_uri,0, strrpos($image_uri,'-'));
+ if(strrpos($image_uri,'.') !== false)
+ $image_uri = substr($image_uri,0, strrpos($image_uri,'.'));
if(! strlen($image_uri))
continue;
$srch = '<' . $xchan_hash . '>';
@@ -4847,7 +4947,7 @@ function copy_of_pubitem($channel,$mid) {
dbesc($mid),
intval($syschan['channel_id'])
);
-
+
if($r) {
$items = fetch_post_tags($r,true);
foreach($items as $rv) {
@@ -4873,5 +4973,5 @@ function copy_of_pubitem($channel,$mid) {
}
}
- return $result;
+ return $result;
}