/** * @brief Collects recipients. * * @param array $item * @param[out] boolean $private_envelope * @return array containing the recipients */ function collect_recipients($item, &$private_envelope) { require_once 'include/group.php'; $private_envelope = intval($item['item_private']) ? true : false; $recipients = array(); if ($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) { // it is private $allow_people = expand_acl($item['allow_cid']); $allow_groups = expand_groups(expand_acl($item['allow_gid'])); $allow_groups = filter_insecure($item['uid'], $allow_groups); $recipients = array_unique(array_merge($allow_people, $allow_groups)); // if you specifically deny somebody but haven't allowed anybody, we'll allow everybody in your // address book minus the denied connections. The post is still private and can't be seen publicly // as that would allow the denied person to see the post by logging out. if (!$item['allow_cid'] && !$item['allow_gid']) { $r = q("select * from abook where abook_channel = %d and not (abook_flags & %d)>0 ", intval($item['uid']), intval(ABOOK_FLAG_SELF | ABOOK_FLAG_PENDING | ABOOK_FLAG_ARCHIVED)); if ($r) { foreach ($r as $rr) { $recipients[] = $rr['abook_xchan']; } } } $deny_people = expand_acl($item['deny_cid']); $deny_groups = expand_groups(expand_acl($item['deny_gid'])); $deny = array_unique(array_merge($deny_people, $deny_groups)); // Don't deny anybody if nobody was allowed (e.g. they were all filtered out) // That would lead to array_diff doing the wrong thing. // This will result in a private post that won't be delivered to anybody. if ($recipients && $deny) { $recipients = array_diff($recipients, $deny); } $private_envelope = true; } else { // if the post is marked private but there are no recipients and public_policy/scope = self, // only add the author and owner as recipients. The ACL for the post may live on the hub of // a different clone. We need to get the post to that hub. // The post may be private by virtue of not being visible to anybody on the internet, // but there are no envelope recipients, so set this to false. Delivery is controlled // by the directives in $item['public_policy']. $private_envelope = false; require_once 'include/identity.php'; //$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 not (abook_flags & %d)>0 ", intval($item['uid']), intval(ABOOK_FLAG_SELF | ABOOK_FLAG_PENDING | ABOOK_FLAG_ARCHIVED)); if ($r) { // filter out restrictive public_policy settings from remote networks // which don't have this concept and will treat them as public. $policy = substr($item['public_policy'], 0, 3); foreach ($r as $rr) { switch ($policy) { case 'net': case 'aut': case 'sit': case 'any': case 'con': if ($rr['xchan_network'] != 'zot') { break; } case 'pub': case '': default: $recipients[] = $rr['abook_xchan']; break; } } } // we probably want to check that discovery channel delivery is allowed before uncommenting this. // if($policy === 'pub') // $recipients[] = $sys['xchan_hash']; } } // This is a somewhat expensive operation but important. // Don't send this item to anybody who isn't allowed to see it $recipients = check_list_permissions($item['uid'], $recipients, 'view_stream'); // remove any upstream recipients from our list. // If it is ourself we'll add it back in a second. // This should prevent complex delivery chains from getting overly complex by not // sending to anybody who is on our list of those who sent it to us. if ($item['route']) { $route = explode(',', $item['route']); if (count($route)) { $route = array_unique($route); $recipients = array_diff($recipients, $route); } } // add ourself just in case we have nomadic clones that need to get a copy. $recipients[] = $item['author_xchan']; if ($item['owner_xchan'] != $item['author_xchan']) { $recipients[] = $item['owner_xchan']; } return $recipients; }
/** * @brief Activity for files. * * @param int $channel_id * @param array $object * @param string $allow_cid * @param string $allow_gid * @param string $deny_cid * @param string $deny_gid * @param string $verb * @param boolean $no_activity */ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $notify) { require_once 'include/items.php'; $poster = get_app()->get_observer(); //if we got no object something went wrong if (!$object) { return; } //turn strings into arrays $arr_allow_cid = expand_acl($allow_cid); $arr_allow_gid = expand_acl($allow_gid); $arr_deny_cid = expand_acl($deny_cid); $arr_deny_gid = expand_acl($deny_gid); //filter out receivers which do not have permission to view filestorage $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); $is_dir = intval($object['is_dir']) ? true : false; //do not send activity for folders for now if ($is_dir) { return; } //check for recursive perms if we are in a folder if ($object['folder']) { $folder_hash = $object['folder']; $r_perms = recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash); //split up returned perms $arr_allow_cid = $r_perms['allow_cid']; $arr_allow_gid = $r_perms['allow_gid']; $arr_deny_cid = $r_perms['deny_cid']; $arr_deny_gid = $r_perms['deny_gid']; //filter out receivers which do not have permission to view filestorage $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); } $mid = item_message_id(); $arr = array(); $arr['item_wall'] = 1; $arr['item_origin'] = 1; $arr['item_unseen'] = 1; $objtype = ACTIVITY_OBJ_FILE; $private = $arr_allow_cid[0] || $arr_allow_gid[0] || $arr_deny_cid[0] || $arr_deny_gid[0] ? 1 : 0; $jsonobject = json_encode($object); //check if item for this object exists $y = q("SELECT mid FROM item WHERE verb = '%s' AND obj_type = '%s' AND resource_id = '%s' AND uid = %d LIMIT 1", dbesc(ACTIVITY_POST), dbesc($objtype), dbesc($object['hash']), intval(local_channel())); if ($y) { $update = true; $object['d_mid'] = $y[0]['mid']; //attach mid of the old object $u_jsonobject = json_encode($object); //we have got the relevant info - delete the old item before we create the new one $z = q("DELETE FROM item WHERE obj_type = '%s' AND verb = '%s' AND mid = '%s'", dbesc(ACTIVITY_OBJ_FILE), dbesc(ACTIVITY_POST), dbesc($y[0]['mid'])); } if ($update && $verb == 'post') { //send update activity and create a new one //updates should be sent to everybody with recursive perms and all eventual former allowed members ($object['allow_cid'] etc.). $u_arr_allow_cid = array_unique(array_merge($arr_allow_cid, expand_acl($object['allow_cid']))); $u_arr_allow_gid = array_unique(array_merge($arr_allow_gid, expand_acl($object['allow_gid']))); $u_arr_deny_cid = array_unique(array_merge($arr_deny_cid, expand_acl($object['deny_cid']))); $u_arr_deny_gid = array_unique(array_merge($arr_deny_gid, expand_acl($object['deny_gid']))); $u_mid = item_message_id(); $arr['aid'] = get_account_id(); $arr['uid'] = $channel_id; $arr['mid'] = $u_mid; $arr['parent_mid'] = $u_mid; $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; $arr['title'] = ''; //updates should be visible to everybody -> perms may have changed $arr['allow_cid'] = ''; $arr['allow_gid'] = ''; $arr['deny_cid'] = ''; $arr['deny_gid'] = ''; $arr['item_hidden'] = 1; $arr['item_private'] = 0; $arr['verb'] = ACTIVITY_UPDATE; $arr['obj_type'] = $objtype; $arr['object'] = $u_jsonobject; $arr['resource_id'] = $object['hash']; $arr['resource_type'] = 'attach'; $arr['body'] = ''; $post = item_store($arr); $item_id = $post['item_id']; if ($item_id) { proc_run('php', "include/notifier.php", "activity", $item_id); } call_hooks('post_local_end', $arr); $update = false; //notice( t('File activity updated') . EOL); } if (!$notify) { return; } $arr = array(); $arr['aid'] = get_account_id(); $arr['uid'] = $channel_id; $arr['mid'] = $mid; $arr['parent_mid'] = $mid; $arr['item_wall'] = 1; $arr['item_origin'] = 1; $arr['item_unseen'] = 1; $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $poster['xchan_hash']; $arr['title'] = ''; $arr['allow_cid'] = perms2str($arr_allow_cid); $arr['allow_gid'] = perms2str($arr_allow_gid); $arr['deny_cid'] = perms2str($arr_deny_cid); $arr['deny_gid'] = perms2str($arr_deny_gid); $arr['item_hidden'] = 1; $arr['item_private'] = $private; $arr['verb'] = $update ? ACTIVITY_UPDATE : ACTIVITY_POST; $arr['obj_type'] = $objtype; $arr['resource_id'] = $object['hash']; $arr['resource_type'] = 'attach'; $arr['object'] = $update ? $u_jsonobject : $jsonobject; $arr['body'] = ''; $post = item_store($arr); $item_id = $post['item_id']; if ($item_id) { proc_run('php', "include/notifier.php", "activity", $item_id); } call_hooks('post_local_end', $arr); //(($verb === 'post') ? notice( t('File activity posted') . EOL) : notice( t('File activity dropped') . EOL)); return; }