Merge remote-tracking branch 'mike/dev' into dev

This commit is contained in:
OJ Random 2022-12-22 22:35:54 +01:00
commit d07bb40a0d
147 changed files with 3189 additions and 2707 deletions

View file

@ -4,16 +4,16 @@ namespace Code\Daemon;
use Code\Extend\Hook;
class Addon
class Addon implements DaemonInterface
{
/**
* @param $argc
* @param $argv
* @param int $argc
* @param array $argv
* @return void
* @noinspection PhpUnusedParameterInspection
*/
public function run($argc, $argv): void
public function run(int $argc, array $argv): void
{
Hook::call('daemon_addon', $argv);
}

View file

@ -7,9 +7,9 @@ use Code\Lib\Resizer;
require_once('include/photos.php');
class CacheThumb
class CacheThumb implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc != 2) {
return;

View file

@ -2,17 +2,16 @@
namespace Code\Daemon;
class Cache_embeds
class Cache_embeds implements DaemonInterface
{
/**
* @param $argc
* @param $argv
* @param int $argc
* @param array $argv
* @return void
*/
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if (! $argc == 2) {
return;
}

View file

@ -4,15 +4,15 @@ namespace Code\Daemon;
use Code\Lib\Img_cache;
class Cache_image
class Cache_image implements DaemonInterface
{
/**
* @param $argc
* @param $argv
* @param int $argc
* @param array $argv
* @return void
*/
public function run($argc, $argv): void
public function run(int $argc, array $argv): void
{
cli_startup();
logger('caching: ' . $argv[1] . ' to ' . $argv[2]);

View file

@ -4,11 +4,11 @@ namespace Code\Daemon;
use Code\Lib\Channel;
class Channel_purge
class Channel_purge implements DaemonInterface
{
/** @noinspection PhpUnusedParameterInspection */
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
cli_startup();

View file

@ -7,10 +7,10 @@ namespace Code\Daemon;
require_once('include/hubloc.php');
class Checksites
class Checksites implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
logger('checksites: start');

View file

@ -10,11 +10,11 @@ require_once('include/cli_startup.php');
require_once('include/attach.php');
require_once('include/import.php');
class Content_importer
class Content_importer implements DaemonInterface
{
/** @noinspection PhpUnusedParameterInspection */
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
cli_startup();

View file

@ -7,10 +7,15 @@ use Code\Lib\ActivityStreams;
use Code\Lib\ASCollection;
use Code\Lib\Channel;
class Convo
class Convo implements DaemonInterface
{
public function run($argc, $argv)
/**
* @param int $argc
* @param array $argv
* @return void
*/
public function run(int $argc, array $argv): void
{
logger('convo invoked: ' . print_r($argv, true));
@ -54,7 +59,9 @@ class Convo
$AS = new ActivityStreams($message, null, true);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS, true);
Activity::store($channel, $contact['abook_xchan'], $AS, $item, true, true);
if ($item) {
Activity::store($channel, $contact['abook_xchan'], $AS, $item, true, true);
}
}
}
}

View file

@ -6,13 +6,12 @@ namespace Code\Daemon;
use Code\Lib\Config;
use Code\Lib\Libsync;
use Code\Lib\Channel;
use Code\Lib\Addon;
class Cron
class Cron implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
$maxsysload = intval(get_config('system', 'maxloadavg'));

View file

@ -3,14 +3,13 @@
namespace Code\Daemon;
use Code\Lib\ServiceClass;
use Code\Lib\Libzotdir;
use Code\Lib\Libzot;
use Code\Extend\Hook;
class Cron_daily
class Cron_daily implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
logger('cron_daily: start');

View file

@ -5,10 +5,10 @@ namespace Code\Daemon;
use Code\Lib\Channel;
use Code\Extend\Hook;
class Cron_weekly
class Cron_weekly implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
/**

View file

@ -5,10 +5,10 @@
namespace Code\Daemon;
use Code\Extend\Hook;
class Cronhooks
class Cronhooks implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
logger('cronhooks: start');
@ -16,7 +16,5 @@ class Cronhooks
$d = datetime_convert();
Hook::call('cron', $d);
return;
}
}

View file

@ -0,0 +1,8 @@
<?php
namespace Code\Daemon;
interface DaemonInterface
{
public function run(int $argc, array $argv): void;
}

View file

@ -6,10 +6,10 @@ namespace Code\Daemon;
use Code\Lib\Queue;
class Deliver
class Deliver implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc < 2) {
return;

View file

@ -4,10 +4,10 @@ namespace Code\Daemon;
use Code\Extend\Hook;
class Deliver_hooks
class Deliver_hooks implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc < 2) {

View file

@ -6,10 +6,10 @@ namespace Code\Daemon;
* Daemon to remove 'item' resources in the background from a removed connection
*/
class Delxitems
class Delxitems implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
cli_startup();
@ -19,7 +19,5 @@ class Delxitems
}
remove_abook_items($argv[1], $argv[2]);
return;
}
}

View file

@ -2,15 +2,13 @@
namespace Code\Daemon;
use Code\Lib\Libzot;
use Code\Lib\Libzotdir;
use Code\Lib\Queue;
use Code\Lib\Channel;
class Directory
class Directory implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc < 2) {

View file

@ -5,10 +5,10 @@ namespace Code\Daemon;
use Code\Lib\ServiceClass;
use Code\Lib\Channel;
class Expire
class Expire implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
cli_startup();

View file

@ -10,10 +10,10 @@ require_once('include/cli_startup.php');
require_once('include/attach.php');
require_once('include/import.php');
class File_importer
class File_importer implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
cli_startup();

View file

@ -10,10 +10,10 @@ use Code\Lib\Zotfinger;
// performs zot_finger on $argv[1], which is a hex_encoded webbie/reddress
class Gprobe
class Gprobe implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc != 2) {

View file

@ -2,10 +2,10 @@
namespace Code\Daemon;
class Importdoc
class Importdoc implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
require_once('include/help.php');
@ -30,7 +30,7 @@ class Importdoc
self::update_docs_dir("$fi/*");
} else {
// don't update media content
if (strpos(z_mime_content_type($fi), 'text') === 0) {
if (str_starts_with(z_mime_content_type($fi), 'text')) {
store_doc_file($fi);
}
}

View file

@ -7,10 +7,10 @@ namespace Code\Daemon;
use Code\Lib\Libsync;
use Code\Lib\Channel;
class Importfile
class Importfile implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
logger('Importfile: ' . print_r($argv, true));
@ -50,9 +50,7 @@ class Importfile
$sync = attach_export_data($channel, $hash);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
return;
}
}

View file

@ -2,6 +2,8 @@
namespace Code\Daemon;
use Code\Lib\Config;
use Code\Lib\IConfig;
use Code\Lib\Libzot;
use Code\Lib\Queue;
use Code\Lib\Activity;
@ -74,7 +76,7 @@ require_once('include/bbcode.php');
* keychange channel_id
*
*/
class Notifier
class Notifier implements DaemonInterface
{
public static $deliveries = [];
@ -86,7 +88,7 @@ class Notifier
public static $channel = null;
public static $private = false;
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc < 3) {
@ -346,11 +348,7 @@ class Notifier
if ($m && (! intval($target_item['item_deleted']))) {
self::$encoded_item = json_decode($m, true);
} else {
self::$encoded_item = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], Activity::encode_activity($target_item, true));
self::$encoded_item = array_merge(Activity::ap_context(), Activity::encode_activity($target_item, true));
self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel);
}
@ -387,44 +385,53 @@ class Notifier
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('followup relay (upstream delivery)', LOGGER_DEBUG);
$sendto = ($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan'];
self::$recipients = [ $sendto ];
// over-ride upstream recipients if 'replyTo' was set in the parent.
if ($parent_item['replyto'] && (! $uplink)) {
logger('replyto: over-riding owner ' . $sendto, LOGGER_DEBUG);
// unserialise is a no-op if presented with data that wasn't serialised.
$ptr = unserialise($parent_item['replyto']);
if (is_string($ptr)) {
if (ActivityStreams::is_url($sendto)) {
$sendto = $ptr;
self::$recipients = [ $sendto ];
}
} elseif (is_array($ptr)) {
$sendto = [];
foreach ($ptr as $rto) {
if (is_string($rto)) {
$sendto[] = $rto;
} elseif (is_array($rto) && isset($rto['id'])) {
$sendto[] = $rto['id'];
$comment_recipient = IConfig::Get($target_item['id'], 'system', 'comment_recipient');
if ($comment_recipient) {
$sendto = $comment_recipient;
self::$recipients = [$comment_recipient];
self::$private = false;
}
else {
$sendto = ($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan'];
self::$recipients = [$sendto];
// over-ride upstream recipients if 'replyTo' was set in the parent.
if ($parent_item['replyto'] && (!$uplink)) {
logger('replyto: over-riding owner ' . $sendto, LOGGER_DEBUG);
// unserialise is a no-op if presented with data that wasn't serialised.
$ptr = unserialise($parent_item['replyto']);
if (is_string($ptr)) {
if (ActivityStreams::is_url($sendto)) {
$sendto = $ptr;
self::$recipients = [$sendto];
}
} elseif (is_array($ptr)) {
$sendto = [];
foreach ($ptr as $rto) {
if (is_string($rto)) {
$sendto[] = $rto;
} elseif (is_array($rto) && isset($rto['id'])) {
$sendto[] = $rto['id'];
}
}
self::$recipients = $sendto;
}
self::$recipients = $sendto;
}
}
logger('replyto: upstream recipients ' . print_r($sendto, true), LOGGER_DEBUG);
self::$private = true;
$upstream = true;
self::$packet_type = 'response';
$is_moderated = their_perms_contains($parent_item['uid'], $sendto, 'moderated');
if ($relay_to_owner && $thread_is_public && (! $is_moderated) && (! $question) && (! Channel::is_group($parent_item['uid']))) {
$is_moderated = their_perms_contains($parent_item['uid'], (is_array($sendto) ? $sendto[0] : $sendto), 'moderated');
$allowed_comment = $target_item['approved'] || !Config::Get('system', 'use_fep5624');
if ($relay_to_owner && $thread_is_public && $allowed_comment && (! $is_moderated) && (! $question) && (! Channel::is_group($parent_item['uid']))) {
if (get_pconfig($target_item['uid'], 'system', 'hyperdrive', true)) {
Run::Summon([ 'Notifier' , 'hyper', $item_id ]);
}
}
} else {
}
else {
if ($cmd === 'relay') {
logger('owner relay (downstream delivery)');
} else {
@ -451,7 +458,8 @@ class Notifier
}
}
if ($thread_is_public && $cmd === 'hyper') {
if ($thread_is_public && $target_item['approved'] && $cmd === 'hyper') {
self::$recipients = [];
$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 and not abook_xchan in ( '%s', '%s', '%s' ) ",
@ -465,8 +473,8 @@ class Notifier
self::$recipients[] = $rv['abook_xchan'];
}
}
self::$private = false;
} else {
}
else {
self::$private = false;
self::$recipients = collect_recipients($parent_item, self::$private);
}

View file

@ -11,10 +11,10 @@ use Code\Lib\ASCollection;
use Code\Lib\Socgraph;
use Code\Lib\PConfig;
class Onepoll
class Onepoll implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
logger('onepoll: start');

View file

@ -7,10 +7,10 @@ namespace Code\Daemon;
use Code\Lib\ServiceClass;
use Code\Lib\Addon;
class Poller
class Poller implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
$maxsysload = intval(get_config('system', 'maxloadavg'));

View file

@ -6,10 +6,10 @@ namespace Code\Daemon;
use Code\Lib as Zlib;
class Queue
class Queue implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
$queue_id = ($argc > 1) ? $argv[1] : '';

View file

@ -6,10 +6,10 @@ namespace Code\Daemon;
use Code\Extend\Hook;
class Thumbnail
class Thumbnail implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if (! ($argc == 2)) {

View file

@ -4,10 +4,10 @@
namespace Code\Daemon;
class Xchan_photo
class Xchan_photo implements DaemonInterface
{
public function run($argc, $argv)
public function run(int $argc, array $argv): void
{
if ($argc != 3) {

View file

@ -145,6 +145,7 @@ class OAuth2Storage extends Pdo
public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null, $client_name = null): bool
{
// if it exists, update it.
if ($this->getClientDetails($client_id)) {
$stmt = $this->db->prepare(sprintf('UPDATE %s SET client_secret=:client_secret, redirect_uri=:redirect_uri, grant_types=:grant_types, scope=:scope, user_id=:user_id, client_name=:client_name where client_id=:client_id', $this->config['client_table']));

View file

@ -44,7 +44,7 @@ class ASCollection
}
if (!in_array($data['type'], ['Collection', 'OrderedCollection'])) {
return false;
return;
}
if ($this->direction) {

View file

@ -229,11 +229,11 @@ class AccessList
}
public static function members($uid, $gid, $total = false, $start = 0, $records = 0): mixed
public static function members($uid, $gid, $total = false, $start = 0, $records = 0, $sqlExtra = ''): mixed
{
$ret = [];
$pager_sql = '';
$sql_extra = '';
$sql_extra = $sqlExtra;
if ($records) {
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($records), intval($start));
@ -263,7 +263,8 @@ class AccessList
$r = q(
"SELECT * FROM abook left join xchan on xchan_hash = abook_xchan
WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql",
WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0
and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql",
intval($uid)
);
if ($r) {
@ -280,7 +281,7 @@ class AccessList
"SELECT count(xchan) as total FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0
and abook_blocked = 0 and abook_pending = 0",
and abook_blocked = 0 and abook_pending = 0 $sqlExtra",
intval($gid),
intval($uid),
intval($uid)
@ -293,7 +294,7 @@ class AccessList
$r = q(
"SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC $pager_sql",
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sqlExtra ORDER BY xchan_name ASC $pager_sql",
intval($gid),
intval($uid),
intval($uid)

View file

@ -264,9 +264,7 @@ class Account {
public static function verify_email_address($arr)
{
if (array_key_exists('resend', $arr)) {
$email = $arr['email'];
$a = q(
"select * from account where account_email = '%s' limit 1",
dbesc($arr['email'])

File diff suppressed because it is too large Load diff

View file

@ -55,11 +55,7 @@ class ActivityPub
'cc' => []
];
$msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $ti);
$msg = array_merge(Activity::ap_context(), $ti);
$msg['signature'] = LDSignatures::sign($msg, $arr['channel']);
@ -107,11 +103,7 @@ class ActivityPub
// }
// }
$msg = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $ti);
$msg = array_merge(Activity::ap_context(), $ti);
$msg['signature'] = LDSignatures::sign($msg, $arr['channel']);
@ -266,11 +258,7 @@ class ActivityPub
$orig_follow_type = get_abconfig($x['sender']['channel_id'], $x['recipient']['xchan_hash'], 'activitypub', 'their_follow_type');
$msg = array_merge(
['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]],
Activity::ap_context(),
[
'id' => z_root() . '/follow/' . $x['recipient']['abook_id'] . (($orig_follow) ? '/' . md5($orig_follow) : EMPTY_STR),
'type' => (($orig_follow_type) ?: 'Follow'),
@ -341,11 +329,7 @@ class ActivityPub
}
$msg = array_merge(
['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]],
Activity::ap_context(),
[
'id' => z_root() . '/follow/' . $x['recipient']['abook_id'] . '/' . md5($accept),
'type' => 'Accept',
@ -410,11 +394,7 @@ class ActivityPub
// was never approved
$msg = array_merge(
['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]],
Activity::ap_context(),
[
'id' => z_root() . '/follow/' . $recip[0]['abook_id'] . '/' . md5($orig_activity) . '?operation=reject',
'type' => 'Reject',
@ -434,11 +414,7 @@ class ActivityPub
// send an 'unfollow'
$msg = array_merge(
['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]],
Activity::ap_context(),
[
'id' => z_root() . '/follow/' . $recip[0]['abook_id'] . (($orig_activity) ? '/' . md5($orig_activity) : EMPTY_STR) . '?operation=unfollow',
'type' => 'Undo',

View file

@ -280,7 +280,7 @@ class Channel
public static function create($arr)
{
$ret = array('success' => false);
$ret = ['success' => false];
if (! $arr['account_id']) {
$ret['message'] = t('No account identifier');
@ -313,7 +313,7 @@ class Channel
return $ret;
}
if (check_webbie(array($nick)) !== $nick) {
if (check_webbie([$nick]) !== $nick) {
$ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
return $ret;
}
@ -352,7 +352,7 @@ class Channel
}
$xchannel_type = XCHAN_TYPE_PERSON ;
if (strpos($arr['permissions_role'], 'forum') !== false || strpos($arr['permissions_role'], 'group') !== false) {
if (str_contains($arr['permissions_role'], 'forum') || str_contains($arr['permissions_role'], 'group')) {
$xchannel_type = XCHAN_TYPE_GROUP ;
}
if ($system) {
@ -589,7 +589,7 @@ class Channel
$accts = get_config('system', 'auto_follow');
if (($accts) && (! $total_identities)) {
if (! is_array($accts)) {
$accts = array($accts);
$accts = [$accts];
}
foreach ($accts as $acct) {
@ -636,7 +636,7 @@ class Channel
if ($f['success']) {
$clone = [];
foreach ($f['abook'] as $k => $v) {
if (strpos($k, 'abook_') === 0) {
if (str_starts_with($k, 'abook_')) {
$clone[$k] = $v;
}
}
@ -659,7 +659,7 @@ class Channel
public static function change_channel_keys($channel)
{
$ret = array('success' => false);
$ret = ['success' => false];
$stored = [];
@ -756,7 +756,7 @@ class Channel
);
}
xchan_change_key($oldxchan, $newxchan, $stored);
xchan_change_key($oldxchan, $newxchan);
Run::Summon([ 'Notifier', 'keychange', $channel['channel_id'] ]);
@ -767,7 +767,7 @@ class Channel
public static function change_address($channel, $new_address)
{
$ret = array('success' => false);
$ret = ['success' => false];
$old_address = $channel['channel_address'];
@ -776,7 +776,7 @@ class Channel
return $ret;
}
if (check_webbie(array($new_address)) !== $new_address) {
if (check_webbie([$new_address]) !== $new_address) {
$ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
return $ret;
}
@ -1423,7 +1423,7 @@ class Channel
if (! local_channel()) {
$r = q(
"select * from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_connected desc limit 1",
"select * from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc limit 1",
dbesc($tmp_str)
);
if (! $r) {
@ -1436,9 +1436,9 @@ class Channel
logger('Not authenticated. Invoking reverse magic-auth for ' . $tmp_str);
// try to avoid recursion - but send them home to do a proper magic auth
$query = App::$query_string;
$query = str_replace(array('?zid=','&zid='), array('?rzid=','&rzid='), $query);
$query = str_replace(['?zid=','&zid='], ['?rzid=','&rzid='], $query);
$dest = '/' . $query;
if ($r && ($r[0]['hubloc_url'] != z_root()) && (! strstr($dest, '/magic')) && (! strstr($dest, '/rmagic'))) {
if ($r && ($r[0]['hubloc_url'] != z_root()) && (!str_contains($dest, '/magic')) && (!str_contains($dest, '/rmagic'))) {
goaway($r[0]['hubloc_url'] . '/magic' . '?f=&rev=1&owa=1&bdest=' . bin2hex(z_root() . $dest));
} else {
logger(sprintf('No hubloc found for \'%s\'.', $tmp_str));
@ -1575,7 +1575,7 @@ class Channel
public static function get_online_status($nick)
{
$ret = array('result' => false);
$ret = ['result' => false];
$r = q(
"select channel_id, channel_hash from channel where channel_address = '%s' limit 1",
@ -1610,7 +1610,7 @@ class Channel
$result = false;
$r = q(
"select * from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 limit 1",
"select * from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc limit 1",
dbesc($webbie)
);
if (! $r) {
@ -1643,10 +1643,10 @@ class Channel
intval(get_account_id())
);
if ($r && count($r) > 1) {
$o = replace_macros(Theme::get_template('channel_id_select.tpl'), array(
$o = replace_macros(Theme::get_template('channel_id_select.tpl'), [
'$channels' => $r,
'$selected' => local_channel()
));
]);
return $o;
}
@ -1679,7 +1679,7 @@ class Channel
$profile_fields_basic = (($filter == 0) ? get_config('system', 'profile_fields_basic') : null);
if (! $profile_fields_basic) {
$profile_fields_basic = array('fullname','pdesc','chandesc','basic_gender','pronouns','dob','dob_tz','region','country_name','marital','sexual','homepage','hometown','keywords','about','contact');
$profile_fields_basic = ['fullname','pdesc','chandesc','basic_gender','pronouns','dob','dob_tz','region','country_name','marital','sexual','homepage','hometown','keywords','about','contact'];
}
$x = [];
@ -1698,7 +1698,7 @@ class Channel
$basic = self::get_profile_fields_basic($filter);
$profile_fields_advanced = (($filter == 0) ? get_config('system', 'profile_fields_advanced') : null);
if (! $profile_fields_advanced) {
$profile_fields_advanced = array('comms', 'address','locality','postal_code','advanced_gender', 'partner','howlong','politic','religion','likes','dislikes','interest','channels','music','book','film','tv','romance','employment','education');
$profile_fields_advanced = ['comms', 'address','locality','postal_code','advanced_gender', 'partner','howlong','politic','religion','likes','dislikes','interest','channels','music','book','film','tv','romance','employment','education'];
}
$x = [];
if ($basic) {
@ -1780,7 +1780,7 @@ class Channel
);
if ($r) {
if ($send) {
Libsync::build_sync_packet($channel_id, array('profile' => $r));
Libsync::build_sync_packet($channel_id, ['profile' => $r]);
} else {
return $r;
}
@ -1830,7 +1830,7 @@ class Channel
$arr['nickname'] = $arr['nickname'] . mt_rand(1000, 9999);
}
$arr['nickname'] = check_webbie(array($arr['nickname'], $arr['nickname'] . mt_rand(1000, 9999)));
$arr['nickname'] = check_webbie([$arr['nickname'], $arr['nickname'] . mt_rand(1000, 9999)]);
return self::create($arr);
}
@ -1861,13 +1861,13 @@ class Channel
break;
case 'array':
default:
$output = array(
$output = [
'width' => $r[0]['width'],
'height' => $r[0]['height'],
'type' => $r[0]['mimetype'],
'updated' => $r[0]['edited'],
'url' => $url
);
];
break;
}
@ -1901,19 +1901,19 @@ class Channel
$cover_width = 425;
$size = 'hz_small';
$cover_size = PHOTO_RES_COVER_425;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m'] . '?rev=' . strtotime($channel['xchan_photo_date']));
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m'] . '?rev=' . strtotime($channel['xchan_photo_date'])];
} elseif ($maxwidth <= 900) {
$width = 900;
$cover_width = 850;
$size = 'hz_medium';
$cover_size = PHOTO_RES_COVER_850;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l'] . '?rev=' . strtotime($channel['xchan_photo_date']));
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l'] . '?rev=' . strtotime($channel['xchan_photo_date'])];
} elseif ($maxwidth <= 1200) {
$width = 1200;
$cover_width = 1200;
$size = 'hz_large';
$cover_size = PHOTO_RES_COVER_1200;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l'] . '?rev=' . strtotime($channel['xchan_photo_date']));
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l'] . '?rev=' . strtotime($channel['xchan_photo_date'])];
}
// $scale = (float) $maxwidth / $width;
@ -1922,7 +1922,7 @@ class Channel
$translate = 0;
$channel['channel_addr'] = self::get_webfinger($channel);
$zcard = array('chan' => $channel);
$zcard = ['chan' => $channel];
$r = q(
"select height, width, resource_id, imgscale, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d",
@ -1938,7 +1938,7 @@ class Channel
$cover = [ 'href' => z_root() . '/' . self::get_default_cover_photo($cover_width) ];
}
$o = replace_macros(Theme::get_template('zcard.tpl'), array(
$o = replace_macros(Theme::get_template('zcard.tpl'), [
'$maxwidth' => $maxwidth,
'$scale' => $scale,
'$translate' => $translate,
@ -1946,7 +1946,7 @@ class Channel
'$cover' => $cover,
'$pphoto' => $pphoto,
'$zcard' => $zcard
));
]);
return $o;
}
@ -1978,23 +1978,23 @@ class Channel
$cover_width = 425;
$size = 'hz_small';
$cover_size = PHOTO_RES_COVER_425;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']);
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80 , 'height' => 80, 'href' => $channel['xchan_photo_m']];
} elseif ($maxwidth <= 900) {
$width = 900;
$cover_width = 850;
$size = 'hz_medium';
$cover_size = PHOTO_RES_COVER_850;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']);
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160 , 'height' => 160, 'href' => $channel['xchan_photo_l']];
} elseif ($maxwidth <= 1200) {
$width = 1200;
$cover_width = 1200;
$size = 'hz_large';
$cover_size = PHOTO_RES_COVER_1200;
$pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']);
$pphoto = ['mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300 , 'height' => 300, 'href' => $channel['xchan_photo_l']];
}
$channel['channel_addr'] = self::get_webfinger($channel);
$zcard = array('chan' => $channel);
$zcard = ['chan' => $channel];
$r = q(
"select height, width, resource_id, imgscale, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d",
@ -2158,11 +2158,11 @@ class Channel
*/
public static function remote_login()
{
$o = replace_macros(Theme::get_template('remote_login.tpl'), array(
$o = replace_macros(Theme::get_template('remote_login.tpl'), [
'$title' => t('Remote Authentication'),
'$desc' => t('Enter your channel address (e.g. channel@example.com)'),
'$submit' => t('Authenticate')
));
]);
return $o;
}

View file

@ -0,0 +1,301 @@
<?php
namespace Code\Lib;
use Code\Daemon\Run;
class CommentApproval
{
protected $channel;
protected $item;
public function __construct($channel, $item)
{
$this->channel = $channel;
$this->item = $item;
}
public function Accept()
{
$obj = $this->item['obj'];
if (! is_array($obj)) {
$obj = json_decode($obj, true);
}
// Have I approved this already?
$approvals = q("select * from item where verb = 'Accept' and obj = '%s' and uid = %d",
dbesc('"' . $obj['id'] . '"'),
dbesc($this->channel['channel_id'])
);
if ($approvals) {
return;
}
$parent = $this->get_parent();
$activity = post_activity_item(
[
'verb' => 'Accept',
'obj_type' => $obj['type'],
'obj' => $obj['id'],
'item_wall' => 1,
'allow_cid' => '',
'owner_xchan' => $this->channel['xchan_hash'],
'author_xchan' => $this->channel['xchan_hash'],
'parent_mid' => $parent,
'thr_parent' => $parent,
'uid' => $this->channel['channel_id'],
'title' => 'comment accepted'
],
deliver: false,
channel: $this->channel,
observer: $this->channel
);
if ($activity['item_id']) {
IConfig::Set($activity['item_id'], 'system', 'comment_recipient', $this->item['author_xchan']);
}
q("UPDATE item SET approved = '%s' WHERE id = %d",
dbesc(str_replace('/item/','/activity/', $activity['activity']['mid'])),
intval($activity['item_id'])
);
Run::Summon(['Notifier', 'comment_approval', $activity['item_id']]);
}
public function Reject()
{
$obj = $this->item['obj'];
if (! is_array($obj)) {
$obj = json_decode($obj, true);
}
// Have I rejected this already?
$rejections = q("select * from item where verb = 'Reject' and obj = '%s' and uid = %d",
dbesc('"' . $obj['id'] . '"'),
dbesc($this->channel['channel_id'])
);
if ($rejections) {
return;
}
$parent = $this->get_parent();
$activity = post_activity_item(
[
'verb' => 'Reject',
'obj_type' => $obj['type'],
'obj' => $obj['id'],
'item_wall' => 1,
'allow_cid' => '',
'owner_xchan' => $this->channel['xchan_hash'],
'author_xchan' => $this->channel['xchan_hash'],
'parent_mid' => $parent,
'thr_parent' => $parent,
'uid' => $this->channel['channel_id'],
'title' => 'comment rejected'
],
deliver: false,
channel: $this->channel,
observer: $this->channel
);
if ($activity['item_id']) {
IConfig::Set($activity['item_id'], 'system', 'comment_recipient', $this->item['author_xchan']);
}
q("UPDATE item SET approved = '' WHERE id = %d",
intval($activity['item_id'])
);
Run::Summon(['Notifier', 'comment_approval', $activity['item_id']]);
}
/**
* To be considered valid, the Accept activity referenced in approval MUST
* satisfy the following properties:
*
* its actor property is the authority
* its authenticity can be asserted
* its object property is the reply under consideration
* its inReplyTo property matches that of the reply under consideration
*
* In addition, if the reply is considered valid, but has no valid approval
* despite the object it is in reply to having a canReply property, the recipient MAY hide
* the reply from certain views.
*/
public static function verify($item, $channel, $approvalActivity = null)
{
if(!$approvalActivity) {
$approvalActivity = Activity::fetch($item['approved'], $channel, true);
}
if (! $approvalActivity) {
logger('no approval activity');
return false;
}
$parent_item = q("select * from item where mid = '%s'", $item['parent_mid']);
if (!$parent_item) {
logger('no parent item');
return false;
}
if ($approvalActivity instanceof ActivityStreams) {
$act = $approvalActivity;
}
else {
$act = new ActivityStreams($approvalActivity);
}
if (! $act->is_valid()) {
logger('invalid parse');
return false;
}
if (!$act->obj) {
logger('no object');
return false;
}
if ($act->type !== 'Accept') {
logger('not an accept');
return false;
}
if (!isset($act->actor)) {
logger('no actor');
return false;
}
$sender = Activity::find_best_identity($act->actor['id']);
if (!$sender || $sender !== $parent_item[0]['owner_xchan']) {
logger('no identity');
return false;
}
$comment = is_string($act->obj) ? $act->obj : $act->obj['id'];
if ($comment !== $item['mid']) {
logger('incorrect mid');
return false;
}
if(!in_array($act->parent_id, [$item['thr_parent'], $item['parent_mid']])) {
logger('wrong provenance');
logger('act: ' . $act->parent_id);
logger('item: ' . print_r($item,true));
return false;
}
logger('comment verified', LOGGER_DEBUG);
return true;
}
public static function verifyReject($item, $channel, $approvalActivity = null)
{
if(!$approvalActivity) {
$approvalActivity = Activity::fetch($item['approved'], $channel, true);
}
$parent_item = q("select * from item where mid = '%s'", $item['parent_mid']);
if (! $approvalActivity) {
return false;
}
if (!$parent_item) {
return false;
}
if ($approvalActivity instanceof ActivityStreams) {
$act = $approvalActivity;
}
else {
$act = new ActivityStreams($approvalActivity);
}
if (! $act->is_valid()) {
return false;
}
if (!$act->obj) {
return false;
}
if ($act->type !== 'Reject') {
return false;
}
if (!isset($act->actor)) {
return false;
}
$sender = Activity::find_best_identity($act->actor['id']);
if (!$sender || $sender !== $parent_item['owner_xchan']) {
return false;
}
$comment = is_string($act->obj) ? $act->obj : $act->obj['id'];
if ($comment !== $item['mid']) {
return false;
}
if(!in_array($act->parent_id, [$item['thr_parent'], $item['parent_mid']])) {
return false;
}
logger('comment verified', LOGGER_DEBUG);
return true;
}
public static function doVerify($arr, $channel, $act)
{
logger('verifying comment accept/reject', LOGGER_DEBUG);
$i = q("select * from item where mid = '%s' and uid = %d",
dbesc(is_array($arr['obj']) ? $arr['obj']['id'] : $arr['obj']),
intval($channel['channel_id'])
);
if ($i) {
if ($arr['verb'] === 'Accept' && !$i[0]['approved']) {
$valid = self::verify($i[0], $channel, $act);
if ($valid) {
self::storeApprove($arr, $channel, $arr['mid']);
Run::Summon(['Notifier', 'activity', $i[0]['id']]);
}
}
elseif ($i[0]['approved']) {
$valid = self::verifyReject($i[0], $channel, $act);
if ($valid) {
self::storeApprove($arr, $channel, '');
Run::Summon(['Notifier', 'activity', $i[0]['id']]);
}
}
return true;
}
return false;
}
public static function storeApprove($arr, $channel, $value)
{
q("update item set approved = '%s' where mid = '%s' and uid = %d",
dbesc($value),
dbesc(is_array($arr['obj']) ? $arr['obj']['id'] : $arr['obj']),
intval($channel['channel_id'])
);
$saved = q("select * from item where mid = '%s' and uid = %d",
dbesc(is_array($arr['obj']) ? $arr['obj']['id'] : $arr['obj']),
intval($channel['channel_id'])
);
if ($saved) {
// we will need to remove the object and provide an author array
// in order to re-generate the object JSON with the added approval
xchan_query($saved);
$saved[0]['obj'] = '';
q("update item set obj = '%s' where mid = '%s' and uid = '%s'",
dbesc(json_encode(Activity::encode_item($saved[0], true), JSON_UNESCAPED_SLASHES)),
dbesc(is_array($arr['obj']) ? $arr['obj']['id'] : $arr['obj']),
intval($channel['channel_id'])
);
}
$r = q(
"select * from item where mid = '%s' and uid = %d",
dbesc(is_array($arr['obj']) ? $arr['obj']['id'] : $arr['obj']),
intval($channel['channel_id'])
);
if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($channel['channel_id'], ['item' => [encode_item($sync_item[0], true)]]);
}
}
protected function get_parent()
{
$result = q("select parent_mid from item where mid = '%s'",
dbesc($this->item['parent_mid'])
);
return $result ? $result[0]['parent_mid'] : '';
}
}

View file

@ -103,6 +103,10 @@ class Enotify
$additional_mail_header = "";
if (array_key_exists('item', $params)) {
if (in_array($params['item']['verb'], ['Approve', 'Reject'])) {
pop_lang();
return;
}
require_once('include/conversation.php');
// if it's a normal item...
if (array_key_exists('verb', $params['item'])) {

View file

@ -1290,6 +1290,6 @@ class Libsync
);
}
xchan_change_key($oldxchan, $newxchan, $arr['keychange']);
xchan_change_key($oldxchan, $newxchan);
}
}

View file

@ -1304,7 +1304,7 @@ class Libzot
"select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_deleted = 0",
dbesc($AS->actor['id'])
);
if (! $r) {
if (!$r) {
// Author is unknown to this site. Perform channel discovery and try again.
$z = discover_resource($AS->actor['id']);
if ($z) {
@ -1382,19 +1382,21 @@ class Libzot
$relay = (($env['type'] === 'response') ? true : false);
$result = self::process_delivery($env['sender'], $AS, $arr, $deliveries, $relay, false, $message_request);
} elseif ($env['type'] === 'sync') {
$arr = json_decode($data, true);
logger('Channel sync received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
logger('Channel sync recipients: ' . print_r($deliveries, true), LOGGER_DATA, LOG_DEBUG);
if ($env['encoding'] === 'red') {
$result = Libsync::process_channel_sync_delivery($env['sender'], $arr, $deliveries);
} else {
logger('unsupported sync packet encoding ignored.');
}
}
}
elseif ($env['type'] === 'sync') {
$arr = json_decode($data, true);
logger('Channel sync received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
logger('Channel sync recipients: ' . print_r($deliveries, true), LOGGER_DATA, LOG_DEBUG);
if ($env['encoding'] === 'red') {
$result = Libsync::process_channel_sync_delivery($env['sender'], $arr, $deliveries);
} else {
logger('unsupported sync packet encoding ignored.');
}
}
if ($result) {
$return = array_merge($return, $result);
}
@ -1597,6 +1599,7 @@ class Libzot
{
$result = [];
$commentApproval = null;
// logger('msg_arr: ' . print_r($msg_arr,true),LOGGER_ALL);
@ -1722,13 +1725,33 @@ class Libzot
}
}
if (in_array($arr['verb'], ['Accept', 'Reject'])) {
if (CommentApproval::doVerify($arr, $channel, $act)) {
continue;
}
}
// perform pre-storage check to see if it's "likely" that this is a group or collection post
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
$perm = 'send_stream';
if (($arr['mid'] !== $arr['parent_mid']) && ($relay)) {
$perm = 'post_comments';
if ($arr['mid'] !== $arr['parent_mid']) {
if ($arr['approved']) {
$valid = CommentApproval::verify($arr, $channel);
if (!$valid) {
logger('commentApproval failed');
continue;
}
}
if ($relay) {
$perm = 'post_comments';
if (!$arr['approved'] && $arr['author_xchan'] !== $channel['channel_hash']) {
$commentApproval = new CommentApproval($channel, $arr);
}
}
}
// This is our own post, possibly coming from a channel clone
@ -1814,7 +1837,16 @@ class Libzot
}
}
if($arr['mid'] !== $arr['parent_mid'] && !$arr['approved'] && !$arr['item_wall'] && $arr['author_xchan'] !== $d && !$relay) {
$allowed = !Config::Get('system', 'use_fep5624');
}
if (!$allowed) {
if ($arr['mid'] !== $arr['parent_mid']) {
if ($commentApproval) {
$commentApproval->Reject();
}
}
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
$result[] = $DR->get();
@ -1827,28 +1859,15 @@ class Libzot
$arr['item_blocked'] = ITEM_MODERATED;
}
// 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.
// The original author won't have a token in their copy of the message
$prnt = ((str_contains($arr['parent_mid'], 'token=')) ? substr($arr['parent_mid'], 0, strpos($arr['parent_mid'], '?')) : '');
if ($commentApproval) {
$commentApproval->Accept();
}
$r = q(
"select id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
if (!$r) {
$r = q(
"select id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
dbesc($prnt),
intval($channel['channel_id'])
);
}
if ($r) {
// if this is a multi-threaded conversation, preserve the threading information
@ -1967,10 +1986,11 @@ class Libzot
continue;
} // Maybe it has been edited?
elseif ($arr['edited'] > $r[0]['edited']) {
elseif ($arr['edited'] > $r[0]['edited'] || $arr['approved'] !== $r[0]['approved']) {
$arr['id'] = $r[0]['id'];
$arr['uid'] = $channel['channel_id'];
if (post_is_importable($channel['channel_id'], $arr, $abook)) {
// ObjCache::Set($arr['mid'], $act->meta['signed_data']);
$item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
$DR->update('updated');
$result[] = $DR->get();
@ -2025,7 +2045,7 @@ class Libzot
if (str_contains($arr['body'], "#^[")) {
$arr['body'] = str_replace("#^[", "[", $arr['body']);
}
// ObjCache::Set($arr['mid'], $act->meta['signed_data']);
$item_result = item_store($arr);
if ($item_result['success']) {
$item_id = $item_result['item_id'];
@ -2990,7 +3010,7 @@ class Libzot
$ret['follow_url'] = z_root() . '/follow?f=&url=%s';
}
$permissions = get_all_perms($e['channel_id'], $ztarget_hash, false);
$permissions = get_all_perms($e['channel_id'], $ztarget_hash);
if ($ztarget_hash) {
$permissions['connected'] = false;

View file

@ -3,10 +3,7 @@
namespace Code\Lib;
use App;
use Code\Lib\Libzot;
use Code\Lib\Webfinger;
use Code\Lib\Zotfinger;
use Code\Lib\Channel;
use Code\Extend\Hook;
use Code\Render\Theme;
@ -89,12 +86,12 @@ class Libzotdir
$o = replace_macros(Theme::get_template('dir_sort_links.tpl'), [
'$header' => t('Directory Options'),
'$forumsurl' => $forumsurl,
'$safemode' => array('safemode', t('Safe Mode'), $safe_mode, '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
'$pubforums' => array('pubforums', t('Groups Only'), (($pubforums == 1) ? true : false), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 1 : 0)\''),
'$safemode' => ['safemode', t('Safe Mode'), $safe_mode, '', [t('No'), t('Yes')], ' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''],
'$pubforums' => ['pubforums', t('Groups Only'), (($pubforums == 1) ? true : false), '', [t('No'), t('Yes')], ' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 1 : 0)\''],
// '$collections' => array('collections', t('Collections Only'),(($pubforums == 2) ? true : false),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 2 : 0)\''),
'$hide_local' => $hide_local,
'$globaldir' => array('globaldir', t('This Website Only'), 1 - intval($globaldir), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
'$activedir' => array('activedir', t('Recently Updated'), intval($activedir), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&active="+(this.checked ? 1 : 0)\''),
'$globaldir' => ['globaldir', t('This Website Only'), 1 - intval($globaldir), '', [t('No'), t('Yes')], ' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''],
'$activedir' => ['activedir', t('Recently Updated'), intval($activedir), '', [t('No'), t('Yes')], ' onchange=\'window.location.href="' . $forumsurl . '&active="+(this.checked ? 1 : 0)\''],
'$covers' => (Config::Get('system','remote_cover_photos')) ? [ 'covers', t('Show cover photos'), intval($covers), t('May slow page loading'), [ t('No'), t('Yes')], ' onchange=\'window.location.href="' . $forumsurl . '&covers="+(this.checked ? 1 : 0)\''] : '',
]);

View file

@ -6,6 +6,9 @@ class ObjCache
{
public static function Get($path)
{
if (!$path) {
return '';
}
$localpath = Hashpath::path($path, 'cache/as', 2);
if (file_exists($localpath)) {
return file_get_contents($localpath);
@ -13,11 +16,17 @@ class ObjCache
return '';
}
public static function Set($path,$content) {
if (!$path) {
return;
}
$localpath = Hashpath::path($path, 'cache/as', 2);
file_put_contents($localpath, $content);
}
public static function Delete($path) {
if (!$path) {
return;
}
$localpath = Hashpath::path($path, 'cache/as', 2);
if (file_exists($localpath)) {
unlink($localpath);

View file

@ -22,10 +22,10 @@ class ThreadItem
// list of supported reaction emojis - a site can over-ride this via config system.reactions
// Deprecated. Use your operating system or a browser plugin.
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
private $toplevel = false;
private $toplevel;
private $children = [];
private $parent = null;
private $conversation = null;
private $conversation;
private $redirect_url = null;
private $owner_url = '';
private $owner_photo = '';
@ -33,7 +33,7 @@ class ThreadItem
private $owner_addr = '';
private $owner_censored = false;
private $wall_to_wall = false;
private $threaded = false;
private $threaded;
private $visiting = false;
private $channel = null;
private $display_mode = 'normal';
@ -98,11 +98,9 @@ class ThreadItem
$item = $this->get_data();
$sparkle = '';
$dropping = false;
$star = false;
$is_comment = false;
$osparkle = '';
$total_children = $this->count_descendants();
$unseen_comments = ((isset($item['real_uid']) && $item['real_uid']) ? 0 : $this->count_unseen_descendants());
$privacy_warning = false;
@ -148,7 +146,7 @@ class ThreadItem
$edlink = 'editpost';
if (local_channel() && $observer['xchan_hash'] === $item['author_xchan']) {
$edpost = array(z_root() . '/' . $edlink . '/' . $item['id'], t('Edit'));
$edpost = [z_root() . '/' . $edlink . '/' . $item['id'], t('Edit')];
} else {
$edpost = false;
}
@ -183,32 +181,32 @@ class ThreadItem
if ($dropping) {
$drop = array(
$drop = [
'dropping' => $dropping,
'delete' => t('Delete'),
);
];
} elseif (is_site_admin()) {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
if (isset($observer_is_pageowner) && $observer_is_pageowner) {
$multidrop = array(
$multidrop = [
'select' => t('Select'),
);
];
}
$filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid', $item))) ? t('Save to Folder') : false);
$large_avatar = $item['author']['xchan_photo_l'];
$profile_avatar = $item['author']['xchan_photo_m'];
$profile_link = chanlink_hash($item['author_xchan']);
$profile_name = $item['author']['xchan_name'];
$profile_addr = $item['author']['xchan_addr'] ? $item['author']['xchan_addr'] : $item['author']['xchan_url'];
$profile_addr = $item['author']['xchan_addr'] ?: $item['author']['xchan_url'];
$location = format_location($item);
$isevent = false;
$attend = null;
$canvote = false;
// process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = [ 'like', 'dislike' ];
@ -219,7 +217,7 @@ class ThreadItem
$response_verbs[] = 'attendmaybe';
if ($this->is_commentable() && $observer) {
$isevent = true;
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
$attend = [t('I will attend'), t('I will not attend'), t('I might attend')];
$undo_attend = t('Undo attendance');
}
}
@ -272,7 +270,7 @@ class ThreadItem
if (local_channel() && ($conv->get_profile_owner() == local_channel() || intval($item['item_private']) === 0)) {
$star = [
'toggle' => t('Save'),
'isstarred' => ((intval($item['item_starred'])) ? true : false),
'isstarred' => (bool) $item['item_starred']
];
}
} else {
@ -286,10 +284,10 @@ class ThreadItem
if ($conv->get_profile_owner() == local_channel()) {
$tagger = array(
$tagger = [
'tagit' => t("Add Tag"),
'classtagger' => "",
);
];
}
$has_bookmarks = false;
@ -307,8 +305,8 @@ class ThreadItem
}
if ($this->is_commentable() && $observer) {
$like = array( t('I like this'), t('Undo like'));
$dislike = array( t('I don\'t like this'), t('Undo dislike') );
$like = [t('I like this'), t('Undo like')];
$dislike = [t('I don\'t like this'), t('Undo dislike')];
}
$share = $embed = EMPTY_STR;
@ -372,7 +370,12 @@ class ThreadItem
$pinned_items = ($allowed_type ? get_pconfig($item['uid'], 'pinned', $item['item_type'], []) : []);
$pinned = ((! empty($pinned_items) && in_array($item['mid'], $pinned_items)) ? true : false);
$tmp_item = array(
$locicon = ($item['verb'] === 'Arrive') ? '<i class="fa fa-fw fa-sign-in"></i>&nbsp' : '';
if (!$locicon) {
$locicon = ($item['verb'] === 'Leave') ? '<i class="fa fa-fw fa-sign-out"></i>&nbsp' : '';
}
$tmp_item = [
'template' => $this->get_template(),
'mode' => $mode,
'item_type' => intval($item['item_type']),
@ -394,7 +397,6 @@ class ThreadItem
'undo_attend' => $undo_attend,
'consensus' => '',
'conlabels' => '',
'canvote' => $canvote,
'linktitle' => sprintf(t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
'olinktitle' => sprintf(t('View %s\'s profile - %s'), $this->get_owner_name(), (($this->get_owner_addr()) ? $this->get_owner_addr() : $this->get_owner_url())),
'llink' => $item['llink'],
@ -411,9 +413,8 @@ class ThreadItem
'myconv' => $myconv,
'name' => $profile_name,
'thumb' => $profile_avatar,
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $item['title'],
'large_avatar' => $large_avatar,
'title' => $locicon . $item['title'],
'title_tosource' => get_pconfig($conv->get_profile_owner(), 'system', 'title_tosource'),
'ago' => relative_date($item['created']),
'app' => $item['app'],
@ -500,9 +501,9 @@ class ThreadItem
'thread_level' => $thread_level,
'indentpx' => intval(get_pconfig(local_channel(), 'system', 'thread_indent_px', get_config('system', 'thread_indent_px', 0))),
'thread_max' => intval(get_config('system', 'thread_maxlevel', 20)) + 1
);
];
$arr = array('item' => $item, 'output' => $tmp_item);
$arr = ['item' => $item, 'output' => $tmp_item];
Hook::call('display_item', $arr);
$result = $arr['output'];
@ -735,8 +736,6 @@ class ThreadItem
*/
public function set_conversation($conv)
{
$previous_mode = ($this->conversation ? $this->conversation->get_mode() : '');
$this->conversation = $conv;
// Set it on our children too
@ -832,33 +831,6 @@ class ThreadItem
return $total;
}
private function label_descendants($count = 0)
{
if (! array_key_exists('sequence', $this->data)) {
if ($count) {
$count++;
}
$this->data['sequence'] = $count;
}
logger('labelled: ' . print_r($this->data, true), LOGGER_DATA);
$children = $this->get_children();
$total = count($children);
if ($total > 0) {
foreach ($children as $child) {
if (! visible_activity($child->data)) {
continue;
}
if (! array_key_exists('sequence', $this->data)) {
$count++;
$child->data['sequence'] = $count;
logger('labelled_child: ' . print_r($child->data, true), LOGGER_DATA);
}
$child->label_descendants($count);
}
}
}
private function count_unseen_descendants()
{
$children = $this->get_children();
@ -913,7 +885,7 @@ class ThreadItem
$observer = $conv->get_observer();
$arr = array('comment_buttons' => '','id' => $this->get_id());
$arr = ['comment_buttons' => '','id' => $this->get_id()];
Hook::call('comment_buttons', $arr);
$comment_buttons = $arr['comment_buttons'];
@ -922,7 +894,7 @@ class ThreadItem
$comment_box = replace_macros($template, array(
$comment_box = replace_macros($template, [
'$return_path' => '',
'$threaded' => $this->is_threaded(),
'$jsreload' => $conv->reload,
@ -950,20 +922,20 @@ class ThreadItem
'$reset' => t('Reset'),
'$indent' => $indent,
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(), get_observer_hash(), 'write_storage') && $conv->is_uploadable()),
'$feature_encrypt' => ((Apps::system_app_installed($conv->get_profile_owner(), 'Secrets')) ? true : false),
'$feature_markup' => ((Apps::system_app_installed($conv->get_profile_owner(), 'Markup')) ? true : false),
'$feature_encrypt' => Apps::system_app_installed($conv->get_profile_owner(), 'Secrets'),
'$feature_markup' => Apps::system_app_installed($conv->get_profile_owner(), 'Markup'),
'$encrypt' => t('Encrypt text'),
'$cipher' => $conv->get_cipher(),
'$sourceapp' => App::$sourcename,
'$observer' => get_observer_hash(),
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(), '', 'post_comments')) ? true : false),
'$anoncomments' => ($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(), '', 'post_comments'),
'$anonname' => [ 'anonname', t('Your full name (required)') ],
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ],
'$auto_save_draft' => $feature_auto_save_draft,
'$save' => $permanent_draft,
'$top' => $this->is_toplevel()
));
]);
return $comment_box;
}
@ -1026,7 +998,7 @@ class ThreadItem
'photo' => $child['author']['xchan_photo_m'],
'name' => $child['author']['xchan_name'],
'addr' => $child['author']['xchan_addr'],
'censored' => (($child['author']['xchan_censored'] || $child['author']['abook_censor']) ? true : false)
'censored' => $child['author']['xchan_censored'] || $child['author']['abook_censor']
];
}
if ($child['children']) {

View file

@ -150,6 +150,9 @@ class Url {
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $validate_ssl);
if (! $validate_ssl) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
}
$prx = @get_config('system', 'proxy');
if (strlen($prx)) {
@ -356,6 +359,9 @@ class Url {
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $validate_ssl);
if (! $validate_ssl) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
}
$prx = get_config('system', 'proxy');
if (strlen($prx)) {

View file

@ -277,11 +277,7 @@ class Activity extends Controller
http_status_exit(404, 'Not found');
}
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
ZlibActivity::ap_schema()
]], $i);
$x = array_merge(Activity::ap_context(), $i);
$headers = [];
$headers['Content-Type'] = 'application/x-nomad+json';

View file

@ -163,6 +163,10 @@ class Accounts
if ($users) {
for ($x = 0; $x < count($users); $x++) {
$users[$x]['account_lastlog'] = datetime_convert(to: date_default_timezone_get(), datetime: $users[$x]['account_lastlog']);
$users[$x]['account_created'] = datetime_convert(to: date_default_timezone_get(), datetime: $users[$x]['account_created']);
$users[$x]['account_expires'] = datetime_convert(to: date_default_timezone_get(), datetime: $users[$x]['account_expires']);
$channel_arr = explode(' ', $users[$x]['channels']);
if ($channel_arr) {
$linked = [];

View file

@ -40,16 +40,6 @@ class Channels
}
notice(sprintf(tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)));
}
if (x($_POST, 'page_channels_code')) {
foreach ($channels as $uid) {
q(
"UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
intval(PAGE_ALLOWCODE),
intval($uid)
);
}
notice(sprintf(tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)));
}
if (x($_POST, 'page_channels_delete')) {
foreach ($channels as $uid) {
Channel::channel_remove($uid, true);
@ -105,20 +95,6 @@ class Channels
}
break;
case "code":
{
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
$pflags = $channel[0]['channel_pageflags'] ^ PAGE_ALLOWCODE;
q(
"UPDATE channel SET channel_pageflags = %d where channel_id = %d",
intval($pflags),
intval($uid)
);
notice(sprintf((($pflags & PAGE_ALLOWCODE) ? t("Channel '%s' code allowed") : t("Channel '%s' code disallowed")), $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')') . EOL);
}
break;
default:
break;
}
@ -156,12 +132,6 @@ class Channels
$channels[$x]['blocked'] = false;
}
if ($channels[$x]['channel_pageflags'] & PAGE_ALLOWCODE) {
$channels[$x]['allowcode'] = true;
} else {
$channels[$x]['allowcode'] = false;
}
$channels[$x]['channel_link'] = z_root() . '/channel/' . $channels[$x]['channel_address'];
}
}
@ -177,8 +147,6 @@ class Channels
'$delete' => t('Delete'),
'$block' => t('Censor'),
'$unblock' => t('Uncensor'),
'$code' => t('Allow Code'),
'$uncode' => t('Disallow Code'),
'$h_channels' => t('Channel'),
'$base' => $base,
'$odir' => $odir,

View file

@ -24,6 +24,9 @@ class Security
$use_hs2019 = ((x($_POST, 'use_hs2019')) ? intval($_POST['use_hs2019']) : 0);
set_config('system', 'use_hs2019', $use_hs2019);
$use_fep5624 = ((x($_POST, 'use_fep5624')) ? intval($_POST['use_fep5624']) : 0);
set_config('system', 'use_fep5624', $use_fep5624);
$block_public_search = ((x($_POST, 'block_public_search')) ? 1 : 0);
set_config('system', 'block_public_search', $block_public_search);
@ -144,6 +147,7 @@ class Security
'$cloud_noroot' => ['cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system', 'cloud_disable_siteroot', true)), t('The cloud root directory lists all channel names which provide public files. Otherwise only the names of connections are shown.')],
'$cloud_disksize' => ['cloud_disksize', t('Show total disk space available to cloud uploads'), intval(get_config('system', 'cloud_report_disksize')), ''],
'$use_hs2019' => ['use_hs2019', t('Use hs2019 HTTP-Signature specification'), intval(get_config('system', 'use_hs2019', false)), t('This is not yet supported by many fediverse servers.')],
'$use_fep5624' => ['use_fep5624', t('Require FEP-5624 comment approvals'), intval(get_config('system', 'use_fep5624', false)), t('This is not yet supported by many fediverse servers.')],
'$thumbnail_security' => ['thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system', 'thumbnail_security', 0), t("WARNING: SVG images may contain malicious code.")],
'$inline_pdf' => ['inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system', 'inline_pdf', 0), ''],

View file

@ -11,9 +11,7 @@ class Apschema extends Controller
public function init()
{
$arr = [
'@context' => array_merge(['as' => 'https://www.w3.org/ns/activitystreams#'], Activity::ap_schema())
];
$arr = Activity::ap_context();
header('Content-Type: application/ld+json');
echo json_encode($arr, JSON_UNESCAPED_SLASHES);

View file

@ -10,6 +10,7 @@ use Code\Identity\OAuth2Server;
use Code\Identity\OAuth2Storage;
use OAuth2\Request;
use OAuth2\Response;
use OAuth2\GrantType;
use Code\Render\Theme;
@ -55,7 +56,12 @@ class Authorize extends Controller
}
$storage = new OAuth2Storage(DBA::$dba->db);
$s = new OAuth2Server($storage);
$server = new OAuth2Server($storage);
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
$server->addGrantType(new GrantType\ClientCredentials($storage));
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
$server->addGrantType(new GrantType\AuthorizationCode($storage));
// TODO: The automatic client registration protocol below should adhere more
// closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined
@ -93,7 +99,12 @@ class Authorize extends Controller
$client = $storage->getClientDetails($client_id);
logger('client: ' . print_r($client, true), LOGGER_DATA);
logger('user_id: ' . $user_id);
if (!$channel || !$user_id) {
// This is fatal, but let it fall through and send a response.
// Log it to have a record of the reason why it's going to die.
logger('not logged in');
}
if ($client) {
if (intval($client['user_id']) === 0 || intval($client['user_id']) === intval($user_id)) {
$client_found = true;
@ -106,7 +117,6 @@ class Authorize extends Controller
$grant_types = $client['grant_types'];
// Client apps are registered per channel
logger('client_id: ' . $client_id);
logger('client_secret: ' . $client_secret);
logger('redirect_uri: ' . $redirect_uri);
@ -126,14 +136,15 @@ class Authorize extends Controller
$response->setParameter('client_secret', $client['client_secret']);
// validate the authorize request
if (!$s->validateAuthorizeRequest($request, $response)) {
if (!$server->validateAuthorizeRequest($request, $response)) {
logger('oauth2 authorize validation failed');
$response->send();
killme();
}
// print the authorization code if the user has authorized your client
$is_authorized = ($_POST['authorize'] === 'allow');
$s->handleAuthorizeRequest($request, $response, $is_authorized, $user_id);
$server->handleAuthorizeRequest($request, $response, $is_authorized, $user_id);
if ($is_authorized) {
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
logger('Authorization Code: ' . $code);

View file

@ -3,6 +3,8 @@
namespace Code\Module;
use App;
use Code\Access\PermissionRoles;
use Code\Lib\AbConfig;
use Code\Web\Controller;
use Code\Lib\Libzot;
use Code\Lib\Libsync;
@ -103,11 +105,9 @@ class Connedit extends Controller
}
$autoperms = null;
$is_self = false;
if (intval($orig_record['abook_self'])) {
$autoperms = intval($_POST['autoperms']);
$is_self = true;
}
$profile_id = ((array_key_exists('profile_assign', $_POST)) ? $_POST['profile_assign'] : $orig_record['abook_profile']);
@ -228,6 +228,16 @@ class Connedit extends Controller
}
}
// Provide default "their_perms" if not provided already. .
$their_perms = AbConfig::Get($channel['channel_id'], App::$poi['abook_xchan'], 'system', 'their_perms', '');
if (! $their_perms) {
$x = PermissionRoles::role_perms('social');
$p = Permissions::FilledPerms($x['perms_connect']);
$their_perms = Permissions::serialise($p);
AbConfig::Set($channel['channel_id'], App::$poi['abook_xchan'], 'system', 'their_perms', $their_perms);
}
// Check if settings permit ("post new friend activity" is allowed, and
// friends in general or this friend in particular aren't hidden)
// and send out a new friend activity
@ -548,84 +558,84 @@ class Connedit extends Controller
}
}
$tools = array(
$tools = [
'view' => array(
'view' => [
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
'title' => sprintf(t('View %s\'s profile'), $contact['xchan_name']),
),
],
'refresh' => array(
'refresh' => [
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
'sel' => '',
'title' => t('Fetch updated permissions'),
),
],
'rephoto' => array(
'rephoto' => [
'label' => t('Refresh Photo'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto',
'sel' => '',
'title' => t('Fetch updated photo'),
),
],
'recent' => array(
'recent' => [
'label' => t('Recent Activity'),
'url' => z_root() . '/stream/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
),
],
'block' => array(
'block' => [
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked') : ''),
),
],
'ignore' => array(
'ignore' => [
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored') : ''),
),
],
'censor' => array(
'censor' => [
'label' => (intval($contact['abook_censor']) ? t('Uncensor') : t('Censor')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/censor',
'sel' => (intval($contact['abook_censor']) ? 'active' : ''),
'title' => t('Censor (or Uncensor) images from this connection'),
'info' => (intval($contact['abook_censor']) ? t('This connection is censored') : ''),
),
],
'archive' => array(
'archive' => [
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
'info' => (intval($contact['abook_archived']) ? t('This connection is archived') : ''),
),
],
'hide' => array(
'hide' => [
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden') : ''),
),
],
'delete' => array(
'delete' => [
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
),
],
);
];
if (in_array($contact['xchan_network'], [ 'zot6', 'nomad' ])) {
@ -686,11 +696,11 @@ class Connedit extends Controller
$slideval = intval($contact['abook_closeness']);
$slide = replace_macros($slider_tpl, array(
$slide = replace_macros($slider_tpl, [
'$min' => 1,
'$val' => $slideval,
'$labels' => $labels,
));
]);
}
if (Apps::system_app_installed(local_channel(), 'Content Filter')) {
@ -707,9 +717,9 @@ class Connedit extends Controller
$global_perms = Permissions::Perms();
$existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
$existing = get_all_perms(local_channel(), $contact['abook_xchan']);
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'), t('Yes')));
$unapproved = ['pending', t('Approve this connection'), '', t('Accept connection to allow communication'), [t('No'), t('Yes')]];
$multiprofs = ((Features::enabled(local_channel(), 'multi_profiles')) ? true : false);
@ -748,7 +758,7 @@ class Connedit extends Controller
$thisperm = "1";
}
$perms[] = array('perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, $yes_no, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
$perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, $yes_no, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited];
}
$current_permcat = EMPTY_STR;
@ -789,7 +799,7 @@ class Connedit extends Controller
$o .= replace_macros($tpl, [
'$header' => (($self) ? t('Connection Default Permissions') : sprintf(t('Connection: %s'), $contact['xchan_name']) . (($contact['abook_alias']) ? ' &lt;' . $contact['abook_alias'] . '&gt;' : '')),
'$autoperms' => array('autoperms', t('Apply these permissions automatically'), ((get_pconfig(local_channel(), 'system', 'autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
'$autoperms' => ['autoperms', t('Apply these permissions automatically'), ((get_pconfig(local_channel(), 'system', 'autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no],
'$permcat' => ['permcat', t('Permission role'), $current_permcat, '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>', $permcats],
'$permcat_new' => t('Add permission role'),
'$permcat_enable' => Apps::system_app_installed(local_channel(),'Roles'),
@ -811,9 +821,9 @@ class Connedit extends Controller
'$lbl_slider' => t('Slide to adjust your degree of friendship'),
'$connfilter' => Apps::system_app_installed(local_channel(), 'Content Filter'),
'$connfilter_label' => t('Custom Filter'),
'$incl' => array('abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')),
'$excl' => array('abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')),
'$alias' => array('abook_alias', t('Nickname'), $contact['abook_alias'], t('optional - allows you to search by a name that you have chosen')),
'$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')],
'$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags, $categories, /patterns/, or lang=xx, leave blank to import all posts')],
'$alias' => ['abook_alias', t('Nickname'), $contact['abook_alias'], t('optional - allows you to search by a name that you have chosen')],
'$slide' => $slide,
'$affinity' => $affinity,
'$pending_label' => t('Connection Pending Approval'),
@ -866,7 +876,7 @@ class Connedit extends Controller
'$country' => t('Country')
]);
$arr = array('contact' => $contact, 'output' => $o);
$arr = ['contact' => $contact, 'output' => $o];
Hook::call('contact_edit', $arr);

View file

@ -34,7 +34,7 @@ class Ap_probe extends Controller
}
}
$j = Activity::fetch($resource, $channel, true);
$j = Activity::fetch($resource, $channel, false,true);
if ($j) {
$html .= '<pre>' . str_replace('\\n', "\n", htmlspecialchars(json_encode($j, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT))) . '</pre>';

View file

@ -20,12 +20,16 @@ class Xchan extends Controller
if (x($_GET, 'addr')) {
$addr = trim($_GET['addr']);
$r = q(
"select * from xchan where xchan_hash like '%s%%' or xchan_addr = '%s' group by xchan_hash",
$h = q("select * from hubloc where hubloc_hash like '%s%%' or hubloc_addr = '%s'",
dbesc($addr),
dbesc($addr)
);
if ($h) {
$r = q(
"select * from xchan where xchan_hash = '%s'",
dbesc($h[0]['hubloc_hash']),
);
}
if ($r) {
foreach ($r as $rr) {

View file

@ -298,11 +298,7 @@ class Directory extends Controller
//$i = Activity::encode_actor_collection($items, 'search?' . $saved_id , 'OrderedCollection', true, count($items));
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $i);
$x = array_merge(Activity::ap_context(), $i);
$headers = [];
$headers['Content-Type'] = 'application/x-nomad+json';

View file

@ -469,7 +469,7 @@ class Display extends Controller
if ($item['item_private']) {
continue;
}
$atom .= atom_entry($item, $type, [], [], true, '', false);
$atom .= atom_entry($item, $type, [], [], true, '');
}
}

View file

@ -96,7 +96,7 @@ class Editpost extends Controller
$mentions = get_terms_oftype($item['term'], TERM_MENTION);
if ($mentions) {
foreach ($mentions as $mention) {
if (strlen($hidden_mentions) && strpos($item['body'], $mention['url']) === false ) {
if (strlen($hidden_mentions) && !str_contains($item['body'], $mention['url'])) {
$hidden_mentions .= ', ';
}
$hidden_mentions .= '@{' . $mention['url'] . '}';
@ -146,7 +146,7 @@ class Editpost extends Controller
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
'is_draft' => ((intval($item['item_unpublished'])) ? true : false),
'is_draft' => (bool)intval($item['item_unpublished']),
'parent' => (($item['mid'] === $item['parent_mid']) ? 0 : $item['parent']),
'mimetype' => $item['mimetype'],
'ptyp' => $item['obj_type'],
@ -157,7 +157,7 @@ class Editpost extends Controller
'title' => htmlspecialchars_decode($item['title'], ENT_COMPAT),
'category' => $category,
'hidden_mentions' => $hidden_mentions,
'showacl' => ((intval($item['item_unpublished'])) ? true : false),
'showacl' => (bool)intval($item['item_unpublished']),
'lockstate' => (($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) ? 'lock' : 'unlock'),
'acl' => Libacl::populate($item, true, PermissionDescription::fromGlobalPermission('view_stream'), Libacl::get_post_aclDialogDescription(), 'acl_dialog_post'),
'bang' => EMPTY_STR,
@ -167,7 +167,9 @@ class Editpost extends Controller
'collections' => $collections,
'jotnets' => true,
'hide_expire' => true,
'bbcode' => true
'bbcode' => true,
'checkin' => ($item['verb'] === 'Arrive'),
'checkout' => ($item['verb'] === 'Leave'),
];
$editor = status_editor($x);

View file

@ -94,7 +94,6 @@ class Filestorage extends Controller
public function get()
{
if (argc() > 1) {
$channel = Channel::from_username(argv(1));
}

View file

@ -29,16 +29,39 @@ class Followers extends Controller
http_status_exit(404, 'Not found');
}
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
Libprofile::load(argv(1));
$observer_hash = get_observer_hash();
$sqlExtra = '';
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'view_contacts')) {
http_status_exit(403, 'Forbidden');
if ($observer_hash) {
$sqlExtra = " AND xchan_hash = '" . dbesc($observer_hash) . "' ";
}
else {
http_status_exit(403, 'Permission denied');
}
}
$t = q(
"select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 ",
"select count(xchan_hash) as total from xchan
left join abconfig on abconfig.xchan = xchan_hash
left join abook on abook_xchan = xchan_hash
where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms'
and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0
and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $sqlExtra ",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
@ -54,7 +77,12 @@ class Followers extends Controller
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$r = q(
"select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $pager_sql",
"select * from xchan left join abconfig on abconfig.xchan = xchan_hash
left join abook on abook_xchan = xchan_hash
where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system'
and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s'
and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0
and abook_self = 0 $sqlExtra $pager_sql",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])

View file

@ -29,16 +29,39 @@ class Following extends Controller
http_status_exit(404, 'Not found');
}
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
if (!check_channelallowed($portable_id)) {
http_status_exit(403, 'Permission denied');
}
if (!check_siteallowed($sigdata['signer'])) {
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
}
Libprofile::load(argv(1));
$observer_hash = get_observer_hash();
$sqlExtra = '';
if (!perm_is_allowed($channel['channel_id'], $observer_hash, 'view_contacts')) {
http_status_exit(403, 'Forbidden');
if ($observer_hash) {
$sqlExtra = " AND xchan_hash = '" . dbesc($observer_hash) . "' ";
}
else {
http_status_exit(403, 'Permission denied');
}
}
$t = q(
"select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
"select count(xchan_hash) as total from xchan
left join abconfig on abconfig.xchan = xchan_hash
left join abook on abook_xchan = xchan_hash
where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms'
and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0
and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $sqlExtra ",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])
@ -55,7 +78,11 @@ class Following extends Controller
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$r = q(
"select * from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $pager_sql",
"select * from xchan left join abconfig on abconfig.xchan = xchan_hash
left join abook on abook_xchan = xchan_hash
where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms'
and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0
and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 $sqlExtra $pager_sql",
intval($channel['channel_id']),
intval($channel['channel_id']),
dbesc($channel['channel_hash'])

View file

@ -27,11 +27,7 @@ class Home extends Controller
Hook::call('home_init', $ret);
if (ActivityStreams::is_as_request()) {
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], Activity::encode_site());
$x = array_merge(Activity::ap_context(), Activity::encode_site());
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';

View file

@ -96,11 +96,7 @@ class Id extends Controller
http_status_exit(404, 'Not found');
}
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $i);
$x = array_merge(Activity::ap_context(), $i);
$headers = [];
$headers['Content-Type'] = 'application/x-nomad+json';

View file

@ -163,10 +163,6 @@ class Impel extends Controller
$pagetitle = strtolower(URLify::transliterate($j['pagetitle']));
}
// Verify ability to use html or php!!!
$execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
$i = q(
"select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['mid']),
@ -179,7 +175,7 @@ class Impel extends Controller
$arr['id'] = $i[0]['id'];
// don't update if it has the same timestamp as the original
if ($arr['edited'] > $i[0]['edited']) {
$x = item_store_update($arr, $execflag);
$x = item_store_update($arr);
}
} else {
if (($i) && (intval($i[0]['item_deleted']))) {
@ -190,7 +186,7 @@ class Impel extends Controller
intval(local_channel())
);
} else {
$x = item_store($arr, $execflag);
$x = item_store($arr);
}
}

View file

@ -180,8 +180,8 @@ class Import extends Controller
}
$channel = import_channel($data['channel'], $account_id, $seize, $newname);
} else {
$moving = false;
}
else {
$channel = App::get_channel();
}
@ -316,7 +316,7 @@ class Import extends Controller
if (is_array($data['hubloc'])) {
import_hublocs($channel, $data['hubloc'], $seize, $moving);
import_hublocs($channel, $data['hubloc'], $seize);
}
logger('import step 7');

View file

@ -303,11 +303,7 @@ class Item extends Controller
if (!$i) {
http_status_exit(404, 'Not found');
}
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $i);
$x = array_merge(Activity::ap_context(), $i);
$headers = [];
$headers['Content-Type'] = 'application/x-nomad+json';
@ -491,6 +487,7 @@ class Item extends Controller
$plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
$obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
$checkin = ((x($_REQUEST, 'checkin')) ? 1 : 0);
$checkout = ((x($_REQUEST, 'checkout')) ? 1 : 0);
$item_unpublished = ((isset($_REQUEST['draft'])) ? intval($_REQUEST['draft']) : 0);
@ -882,9 +879,8 @@ class Item extends Controller
$body = ((isset($_REQUEST['body'])) ? trim($_REQUEST['body']) : EMPTY_STR);
$body .= ((isset($_REQUEST['attachment'])) ? trim($_REQUEST['attachment']) : EMPTY_STR);
$postopts = '';
$allow_empty = ((array_key_exists('allow_empty', $_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
$haslocation = $lat || $lon;
$allow_empty = ((($checkin || $checkout) && $haslocation) || $_REQUEST['allow_empty']);
$private = ((isset($private) && $private) ? $private : intval($acl->is_private() || ($public_policy)));
// If this is a comment, set the permissions from the parent.
@ -932,12 +928,9 @@ class Item extends Controller
$mimetype = 'text/x-multicode';
}
$execflag = ((intval($uid) == intval($profile_uid)
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
if ($preview) {
$summary = z_input_filter($summary, $mimetype, $execflag);
$body = z_input_filter($body, $mimetype, $execflag);
$summary = z_input_filter($summary, $mimetype);
$body = z_input_filter($body, $mimetype);
}
@ -979,6 +972,9 @@ class Item extends Controller
if ($checkin) {
$verb = 'Arrive';
}
if ($checkout) {
$verb = 'Leave';
}
if (in_array($mimetype, [ 'text/bbcode', 'text/x-multicode' ])) {
// BBCODE alert: the following functions assume bbcode input
@ -1182,7 +1178,13 @@ class Item extends Controller
}
}
if ($verb === 'Arrive') {
$hook_args = ['location' => $location, 'latitude' => $lat, 'longitude' => $lon];
Hook::call('post_location', $hook_args);
$location = $hook_args['location'];
$lat = $hook_args['latitude'];
$lon = $hook_args['longitude'];
if (in_array($verb, ['Arrive', 'Leave'])) {
$body = preg_replace('/\[map=(.*?)\]/','', $body);
$body = preg_replace('/\[map\](.*?)\[\/map\]/','', $body);
@ -1616,7 +1618,7 @@ class Item extends Controller
if ($orig_post) {
$datarray['id'] = $post_id;
$x = item_store_update($datarray, $execflag);
$x = item_store_update($datarray);
if ($x['success']) {
Hook::call('after_item_store', $x['item']);
@ -1656,7 +1658,7 @@ class Item extends Controller
$post_id = 0;
}
$post = item_store($datarray, $execflag);
$post = item_store($datarray);
if ($post['success']) {
Hook::call('after_item_store', $post['item']);
@ -2038,7 +2040,7 @@ class Item extends Controller
foreach ($answers as $answer) {
if (trim($answer)) {
$ptr[] = ['name' => escape_tags($answer), 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
$ptr[] = ['name' => escape_tags(trim($answer)), 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
}
}

View file

@ -47,13 +47,12 @@ class Lists extends Controller
http_status_exit(403, 'Permission denied');
}
observer_auth($portable_id);
} elseif (Config::Get('system', 'require_authenticated_fetch', false)) {
} elseif (Config::Get('system', 'require_authenticated_fetch')) {
http_status_exit(403, 'Permission denied');
}
if (!perm_is_allowed($group['uid'], get_observer_hash(), 'view_contacts')) {
http_status_exit(403, 'Permission denied');
}
$observer_hash = get_observer_hash();
$hasPermission = perm_is_allowed($group['uid'], $observer_hash, 'view_contacts');
$channel = Channel::from_id($group['uid']);
@ -61,13 +60,20 @@ class Lists extends Controller
http_status_exit(404, 'Not found');
}
if (!$group['visible']) {
if ($channel['channel_hash'] !== get_observer_hash()) {
$sqlExtra = '';
if (!$group['visible'] || !$hasPermission) {
if ($observer_hash) {
if ($observer_hash !== $channel['channel_hash']) {
$sqlExtra = " AND xchan_hash = '" . dbesc(get_observer_hash()) . "' ";
}
}
else {
http_status_exit(403, 'Permission denied');
}
}
$total = AccessList::members($group['uid'], $group['id'], true);
$total = AccessList::members($group['uid'], $group['id'], true, sqlExtra: $sqlExtra);
if ($total) {
App::set_pager_total($total);
App::set_pager_itemspage(100);
@ -75,14 +81,15 @@ class Lists extends Controller
if (App::$pager['unset'] && $total > 100) {
$ret = Activity::paged_collection_init($total, App::$query_string);
$ret['name'] = $group['gname'];
$ret['attributedTo'] = Channel::url($channel);
} else {
$members = AccessList::members($group['uid'], $group['id'], false, App::$pager['start'], App::$pager['itemspage']);
$members = AccessList::members($group['uid'], $group['id'], false, App::$pager['start'],
App::$pager['itemspage'], sqlExtra: $sqlExtra);
$ret = Activity::encode_follow_collection($members, App::$query_string, 'OrderedCollection', $total);
$ret['name'] = $group['gname'];
$ret['attributedTo'] = Channel::url($channel);
}
if (! $sqlExtra) {
$ret['name'] = $group['gname'];
}
$ret['attributedTo'] = Channel::url($channel);
as_return_and_die($ret, $channel);
}
@ -157,7 +164,6 @@ class Lists extends Controller
goaway(z_root() . '/lists/' . argv(1) . '/' . argv(2));
}
return;
}
public function get()
@ -193,7 +199,7 @@ class Lists extends Controller
}
$tpl = Theme::get_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
return replace_macros($tpl, [
'$title' => t('Access Lists'),
'$add_new_label' => t('Create access list'),
'$new' => $new,
@ -209,8 +215,6 @@ class Lists extends Controller
'$count_label' => t('Members'),
'$entries' => $entries
]);
return $o;
}
$context = ['$submit' => t('Submit')];
@ -300,11 +304,10 @@ class Lists extends Controller
$members[] = micropro($member, true, 'mpgroup', 'card');
}
}
$o = replace_macros(Theme::get_template('listmembers.tpl'), [
return replace_macros(Theme::get_template('listmembers.tpl'), [
'$title' => t('List members'),
'$members' => $members
]);
return $o;
}
$members = AccessList::members(local_channel(), $group['id']);

View file

@ -5,7 +5,6 @@ namespace Code\Module;
use App;
use Code\Web\Controller;
use Code\Lib\Libsync;
use Code\Lib\Channel;
use Code\Daemon\Run;
use Code\Access\PermissionRoles;
@ -94,7 +93,7 @@ class Moderate extends Controller
$item['item_blocked'] = 0;
item_update_parent_commented($item);
// \Code\Lib\Activity::send_accept_activity(App::get_channel(),$item['author'], $item, $parent_item);
notice(t('Comment approved') . EOL);
} elseif ($action === 'drop') {
drop_item($post_id);
@ -118,9 +117,9 @@ class Moderate extends Controller
// Announce activity so microblog destinations will see it in their home timeline
$role = get_pconfig(local_channel(), 'system', 'permissions_role');
$rolesettings = PermissionRoles::role_perms($role);
$channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
$channel_type = $rolesettings['channel_type'] ?? 'normal';
$is_group = (($channel_type === 'group') ? true : false);
$is_group = $channel_type === 'group';
if ($is_group) {
tag_deliver(local_channel(), $post_id);
}
@ -138,7 +137,7 @@ class Moderate extends Controller
$items = [];
}
$o = conversation($items, 'moderate', false, 'traditional');
$o = conversation($items, 'moderate', false);
$o .= alt_pager(count($items));
return $o;
}

View file

@ -60,6 +60,8 @@ class Ping extends Controller
$item_normal = item_normal();
$approvals = " AND NOT verb in ('Accept','Reject') ";
if (local_channel()) {
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
$evdays = intval(get_pconfig(local_channel(), 'system', 'evdays'));
@ -169,6 +171,7 @@ class Ping extends Controller
WHERE uid = %d
AND created > '%s'
$seenstr
$approvals
$item_normal
$sql_extra",
intval($sys['channel_id']),
@ -195,6 +198,7 @@ class Ping extends Controller
AND author_xchan != '%s'
AND created > '%s'
$seenstr
$approvals
$item_normal
$sql_extra
ORDER BY created DESC
@ -207,7 +211,7 @@ class Ping extends Controller
if ($r) {
xchan_query($r);
foreach ($r as $rr) {
$rr['llink'] = str_replace('display/', 'pubstream/?f=&mid=', $rr['llink']);
$rr['llink'] = str_replace('display/', 'pubstream/', $rr['llink']);
$z = Enotify::format($rr);
if ($z) {
$local_result[] = $z;
@ -303,7 +307,7 @@ class Ping extends Controller
foreach ($t as $tt) {
$message = trim(strip_tags(bbcode($tt['msg'])));
if (strpos($message, $tt['xname']) === 0) {
if (str_starts_with($message, $tt['xname'])) {
$message = substr($message, strlen($tt['xname']) + 1);
}
@ -319,12 +323,12 @@ class Ping extends Controller
intval(local_channel())
);
$b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : gen_link_id($r[0]['thr_parent']));
$b64mid = ((str_starts_with($r[0]['thr_parent'], 'b64.')) ? $r[0]['thr_parent'] : gen_link_id($r[0]['thr_parent']));
} else {
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : gen_link_id($mid));
$b64mid = ((str_starts_with($mid, 'b64.')) ? $mid : gen_link_id($mid));
}
$notifs[] = array(
$notifs[] = [
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
'name' => $tt['xname'],
'url' => $tt['url'],
@ -334,7 +338,7 @@ class Ping extends Controller
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'),
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'),
'message' => $message
);
];
}
}
@ -353,6 +357,7 @@ class Ping extends Controller
AND author_xchan != '%s'
AND edited > '%s'
$seenstr
$approvals
$item_normal_moderate
$sql_extra
ORDER BY created DESC
@ -390,6 +395,7 @@ class Ping extends Controller
AND author_xchan != '%s'
AND edited > '%s'
$seenstr
$approvals
$item_normal_moderate
$sql_extra
ORDER BY created DESC
@ -448,7 +454,7 @@ class Ping extends Controller
);
if ($r) {
foreach ($r as $rr) {
$result[] = array(
$result[] = [
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['account_email'],
'addr' => $rr['account_email'],
@ -457,7 +463,7 @@ class Ping extends Controller
'when' => relative_date($rr['account_created']),
'hclass' => ('notify-unseen'),
'message' => t('requires approval')
);
];
}
}
@ -485,7 +491,7 @@ class Ping extends Controller
$today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false);
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
$result[] = array(
$result[] = [
'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@ -494,7 +500,7 @@ class Ping extends Controller
'when' => $when,
'hclass' => ('notify-unseen'),
'message' => t('posted an event')
);
];
}
}
@ -519,7 +525,7 @@ class Ping extends Controller
);
if ($r) {
foreach ($r as $rr) {
$result[] = array(
$result[] = [
'notify_link' => z_root() . '/sharedwithme',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
@ -528,7 +534,7 @@ class Ping extends Controller
'when' => relative_date($rr['created']),
'hclass' => ('notify-unseen'),
'message' => t('shared a file with you')
);
];
}
}
@ -604,6 +610,7 @@ class Ping extends Controller
"SELECT id, author_xchan FROM item
WHERE uid = %d and edited > '%s'
$seenstr
$approvals
$item_normal
$sql_extra ",
intval(local_channel()),
@ -611,7 +618,7 @@ class Ping extends Controller
);
if ($r) {
$arr = array('items' => $r);
$arr = ['items' => $r];
Hook::call('network_ping', $arr);
foreach ($r as $it) {
@ -633,6 +640,7 @@ class Ping extends Controller
"SELECT id, author_xchan FROM item
WHERE item_wall = 1 and uid = %d and edited > '%s'
$seenstr
$approvals
$item_normal
$sql_extra ",
intval(local_channel()),
@ -739,7 +747,7 @@ class Ping extends Controller
$result['birthdays'] = 0;
}
/*
if ($vnotify & VNOTIFY_FORUMS) {
$forums = get_forum_channels(local_channel());
@ -788,7 +796,7 @@ class Ping extends Controller
$result['forums_sub'] = $forums;
}
}
*/
// Mark all of the stream notifications seen if all three of them are caught up.
// This also resets the pconfig storage for items_seen

View file

@ -350,11 +350,7 @@ class Search extends Controller
$i = Activity::encode_item_collection($items, 'search?' . $saved_id , 'OrderedCollection', true, count($items));
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
Activity::ap_schema()
]], $i);
$x = array_merge(Activity::ap_context(), $i);
$headers = [];
$headers['Content-Type'] = 'application/x-nomad+json';

View file

@ -62,7 +62,7 @@ class Channel
PermissionLimits::Set(local_channel(), 'view_contacts', $view_contacts);
$this->publish = (((x($_POST, 'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
$username = ((x($_POST, 'username')) ? escape_tags(trim($_POST['username'])) : '');
$channel_name = ((x($_POST, 'channel_name')) ? escape_tags(trim($_POST['channel_name'])) : '');
$timezone = ((x($_POST, 'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
$defloc = ((x($_POST, 'defloc')) ? notags(trim($_POST['defloc'])) : '');
$maxreq = ((x($_POST, 'maxreq')) ? intval($_POST['maxreq']) : 0);
@ -137,9 +137,9 @@ class Channel
$name_change = false;
if ($username != $channel['channel_name']) {
if ($channel_name != $channel['channel_name']) {
$name_change = true;
$err = Zlib\Channel::validate_channelname($username);
$err = Zlib\Channel::validate_channelname($channel_name);
if ($err) {
notice($err);
return;
@ -177,7 +177,7 @@ class Channel
$r = q(
"update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s',
channel_notifyflags = %d, channel_max_friend_req = %d, channel_expire_days = %d where channel_id = %d",
dbesc($username),
dbesc($channel_name),
intval($pageflags),
dbesc($timezone),
dbesc($defloc),
@ -206,17 +206,17 @@ class Channel
// catch xchans for all protocols by matching the url
$r = q(
"update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_url = '%s'",
dbesc($username),
dbesc($channel_name),
dbesc(datetime_convert()),
dbesc(z_root() . '/channel/' . $channel['channel_address'])
);
$r = q(
"update profile set fullname = '%s' where uid = %d and is_default = 1",
dbesc($username),
dbesc($channel_name),
intval($channel['channel_id'])
);
if (Zlib\Channel::is_system($channel['channel_id'])) {
set_config('system', 'sitename', $username);
set_config('system', 'sitename', $channel_name);
}
}
@ -280,7 +280,7 @@ class Channel
// logger('permiss: ' . print_r($permiss,true));
$username = $channel['channel_name'];
$channel_name = $channel['channel_name'];
$nickname = $channel['channel_address'];
$timezone = $channel['channel_timezone'];
$notify = $channel['channel_notifyflags'];
@ -433,7 +433,7 @@ class Channel
'$form_security_token' => get_form_security_token("settings"),
'$nickname_block' => $prof_addr,
'$h_basic' => t('Basic Settings'),
'$username' => ['username', t('Full name'), $username, ''],
'$channel_name' => ['channel_name', t('Full name'), $channel_name, ''],
'$timezone' => ['timezone_select', t('Your timezone'), $timezone, t('This is important for showing the correct time on shared events'), get_timezones()],
'$defloc' => ['defloc', t('Default post location'), $defloc, t('Optional geographical location to display on your posts')],
'$allowloc' => ['allow_location', t('Obtain post location from your web browser or device'), ((get_pconfig(local_channel(), 'system', 'use_browser_location')) ? 1 : ''), '', $yes_no],

View file

@ -4,7 +4,7 @@ namespace Code\Module;
use App;
use Code\Web\Controller;
use Code\Lib\Apps;
use Code\Lib\Activity;
use Code\Lib\Libsync;
use Code\Lib\LibBlock;
use Code\Lib\Libzot;
@ -17,92 +17,66 @@ class Superblock extends Controller
public function init()
{
$handled = false;
if (!local_channel()) {
return;
}
$inline = (isset($_REQUEST['manual_block']) ? true : false);
$inline = isset($_REQUEST['manual_block']);
$reason = (!empty($_REQUEST['reason'])) ? escape_tags($_REQUEST['reason']) : '';
$type = BLOCKTYPE_CHANNEL;
$blocked = trim($_REQUEST['block']);
if (!$blocked) {
$blocked = trim($_REQUEST['blocksite']);
if ($blocked) {
$type = BLOCKTYPE_SERVER;
}
}
$m = parse_url($blocked);
if ($m['scheme'] && $m['host'] && (($type === BLOCKTYPE_SERVER) || (!$m['path']))) {
if (strcasecmp($m['host'], App::get_hostname()) === 0) {
notice(t('Blocking this site is not permitted.'));
if ($inline) {
return;
}
killme();
}
$type = BLOCKTYPE_SERVER;
$blocked = $m['host'];
}
$handled = false;
$ignored = [];
if ($blocked) {
$handled = true;
if ($type === BLOCKTYPE_CHANNEL) {
$r = q(
"select * from xchan where ( xchan_hash = '%s' or xchan_addr = '%s' or xchan_url = '%s' )",
dbesc($blocked),
dbesc($blocked),
dbesc($blocked)
);
$r = q(
"select * from xchan where ( xchan_hash = '%s' or xchan_addr = '%s' or xchan_url = '%s' )",
dbesc($blocked),
dbesc($blocked),
dbesc($blocked)
);
if (!$r) {
// not in cache - try discovery
$wf = discover_resource($blocked, '', false);
if (!$r) {
// not in cache - try discovery
$wf = discover_resource($blocked, '', false);
if (!$wf) {
notice(t('Channel not found.') . EOL);
if ($inline) {
return;
}
killme();
}
if ($wf) {
// something was discovered - find the record which was just created.
$r = q(
"select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' )",
dbesc(($wf) ? $wf : $blocked),
dbesc($blocked),
dbesc($blocked)
);
if (!$wf) {
notice(t('Channel not found.') . EOL);
if ($inline) {
return;
}
killme();
}
if ($r) {
$r = Libzot::zot_record_preferred($r, 'xchan_network');
$blocked = $r['xchan_hash'];
if ($wf) {
// something was discovered - find the record which was just created.
$r = q(
"select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' )",
dbesc($wf),
dbesc($blocked),
dbesc($blocked)
);
}
}
$bl = [
'block_channel_id' => local_channel(),
'block_entity' => $blocked,
'block_type' => $type,
'block_comment' => t('Added by Superblock')
];
if ($r) {
$r = Libzot::zot_record_preferred($r, 'xchan_network');
$blocked = $r['xchan_hash'];
LibBlock::store($bl);
$bl = [
'block_channel_id' => local_channel(),
'block_entity' => $blocked,
'block_type' => $type,
'block_comment' => t('Added by Superblock')
];
$sync = [];
LibBlock::store($bl);
$sync = [];
$sync['block'] = [LibBlock::fetch_by_entity(local_channel(), $blocked)];
$sync['block_xchan'] = [$r];
$sync['block'] = [LibBlock::fetch_by_entity(local_channel(), $blocked)];
$sync['block_xchan'] = [$r];
if ($type === BLOCKTYPE_CHANNEL) {
$z = q(
"insert into xign ( uid, xchan ) values ( %d , '%s' ) ",
intval(local_channel()),
@ -140,31 +114,23 @@ class Superblock extends Controller
$sync['xign'] = [['uid' => local_channel(), 'xchan' => $_GET['block']]];
}
Libsync::build_sync_packet(0, $sync);
}
$type = BLOCKTYPE_CHANNEL;
$unblocked = trim($_REQUEST['unblock']);
if (!$unblocked) {
$unblocked = trim($_REQUEST['unblocksite']);
} else {
$unblocked = trim($_REQUEST['unblock']);
if ($unblocked) {
$type = BLOCKTYPE_SERVER;
}
}
if ($unblocked) {
$handled = true;
if (check_form_security_token('superblock', 'sectok')) {
$r = LibBlock::fetch_by_entity(local_channel(), $unblocked);
if ($r) {
LibBlock::remove(local_channel(), $unblocked);
$handled = true;
if (check_form_security_token('superblock', 'sectok')) {
$r = LibBlock::fetch_by_entity(local_channel(), $unblocked);
if ($r) {
LibBlock::remove(local_channel(), $unblocked);
$sync = [];
$sync['block'] = [[
'block_channel_id' => local_channel(),
'block_entity' => $unblocked,
'block_type' => $type,
'deleted' => true,
]];
$sync = [];
$sync['block'] = [[
'block_channel_id' => local_channel(),
'block_entity' => $unblocked,
'block_type' => $type,
'deleted' => true,
]];
if ($type === BLOCKTYPE_CHANNEL) {
$ab = q(
"select * from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_xchan = '%s'",
intval(local_channel()),
@ -192,7 +158,65 @@ class Superblock extends Controller
intval(local_channel()),
dbesc($unblocked)
);
Libsync::build_sync_packet(0, $sync);
}
else {
return;
}
}
}
}
$type = BLOCKTYPE_SERVER;
$blocked = trim($_REQUEST['blocksite']);
if ($blocked) {
$handled = true;
$servers = Activity::get_actor_hublocs($blocked);
if ($servers) {
foreach ($servers as $server) {
$m = parse_url($server['hubloc_url']);
if ($m['scheme'] && $m['host']) {
if (strcasecmp($m['host'], App::get_hostname()) === 0) {
notice(t('Blocking this site is not permitted.'));
if ($inline) {
return;
}
killme();
}
$blocked = $m['host'];
$bl = [
'block_channel_id' => local_channel(),
'block_entity' => $blocked,
'block_type' => $type,
'block_comment' => t('Added by Superblock')
];
LibBlock::store($bl);
$sync = [];
$sync['block'] = [LibBlock::fetch_by_entity(local_channel(), $blocked)];
Libsync::build_sync_packet(0, $sync);
}
}
}
}
$unblocked = trim($_REQUEST['unblocksite']);
if ($unblocked) {
$handled = true;
if (check_form_security_token('superblock', 'sectok')) {
$r = LibBlock::fetch_by_entity(local_channel(), $unblocked);
if ($r) {
LibBlock::remove(local_channel(), $unblocked);
$sync = [];
$sync['block'] = [[
'block_channel_id' => local_channel(),
'block_entity' => $unblocked,
'block_type' => $type,
'deleted' => true,
]];
Libsync::build_sync_packet(0, $sync);
}
}
@ -204,9 +228,9 @@ class Superblock extends Controller
if ($unblocked || $inline) {
return;
}
killme();
}
}
public function get()
@ -255,7 +279,7 @@ class Superblock extends Controller
]);
return replace_macros(Theme::get_template('generic_app_settings.tpl'), [
'$addon' => array('superblock', t('Manage Blocks'), '', t('Submit')),
'$addon' => ['superblock', t('Manage Blocks'), '', t('Submit')],
'$content' => $sc
]);
}

View file

@ -9,6 +9,7 @@ use Code\Identity\OAuth2Server;
use Code\Identity\OAuth2Storage;
use OAuth2\Request;
use OAuth2\Response;
use OAuth2\GrantType;
class Token extends Controller
{
@ -38,9 +39,13 @@ class Token extends Controller
}
$storage = new OAuth2Storage(DBA::$dba->db);
$s = new OAuth2Server($storage);
$server = new OAuth2Server($storage);
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
$server->addGrantType(new GrantType\ClientCredentials($storage));
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
$server->addGrantType(new GrantType\AuthorizationCode($storage));
$request = Request::createFromGlobals();
$response = $s->handleTokenRequest($request);
$response = $server->handleTokenRequest($request);
$response->send();
killme();
}

View file

@ -27,7 +27,7 @@ class Vote extends Controller
$fetch = null;
$id = argv(1);
$response = $_REQUEST['answer'];
$response = trim($_REQUEST['answer']);
if ($id) {
$fetch = q(
@ -47,9 +47,9 @@ class Vote extends Controller
if ($obj['oneOf']) {
foreach ($obj['oneOf'] as $selection) {
// logger('selection: ' . $selection);
// logger('response: ' . $response);
if ($selection['name'] && $selection['name'] === $response) {
// logger('selection: ' . '"' . $selection['name'] . '"');
// logger('response: ' . '"' . $response . '"');
if ($selection['name'] && trim($selection['name']) === $response) {
$valid = true;
}
}
@ -58,7 +58,7 @@ class Vote extends Controller
$choices = [];
if ($obj['anyOf']) {
foreach ($obj['anyOf'] as $selection) {
$choices[] = $selection['name'];
$choices[] = trim($selection['name']);
}
foreach ($response as $res) {
if (!in_array($res, $choices)) {

View file

@ -140,7 +140,7 @@ class NomadHandler implements IHandler
// if ! $update create a linked identity
xchan_change_key($xchan, $newxchan, $data);
xchan_change_key($xchan, $newxchan);
$ret['success'] = true;
return $ret;

View file

@ -227,27 +227,27 @@ class Theme
}
}
public static function get_template($s, $root = '')
public static function get_template($filename, $root = '')
{
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
$t = App::template_engine();
if (isset(App::$override_markup_templates[$testroot][$s]["content"])) {
return App::$override_markup_templates[$testroot][$s]["content"];
if (isset(App::$override_markup_templates[$testroot][$filename]["content"])) {
return App::$override_markup_templates[$testroot][$filename]["content"];
} else {
if (isset(App::$override_markup_templates[$testroot][$s]["root"]) &&
isset(App::$override_markup_templates[$testroot][$s]["file"])) {
$s = App::$override_markup_templates[$testroot][$s]["file"];
$root = App::$override_markup_templates[$testroot][$s]["root"];
if (isset(App::$override_markup_templates[$testroot][$filename]["root"]) &&
isset(App::$override_markup_templates[$testroot][$filename]["file"])) {
$filename = App::$override_markup_templates[$testroot][$filename]["file"];
$root = App::$override_markup_templates[$testroot][$filename]["root"];
} elseif (App::$override_templateroot) {
$newroot = App::$override_templateroot.$root;
if ($newroot != '' && !str_ends_with($newroot, '/')) {
$newroot .= '/';
}
$template = $t->get_template($s, $newroot);
$template = $t->get_template($filename, $newroot);
}
$template = $t->get_template($s, $root);
$template = $t->get_template($filename, $root);
return $template;
}
}

View file

@ -63,7 +63,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$this->ext_path = $ext_path;
// remove "/cloud" from the beginning of the path
$modulename = App::$module;
$this->red_path = ((strpos($ext_path, '/' . $modulename) === 0) ? substr($ext_path, strlen($modulename) + 1) : $ext_path);
$this->red_path = ((str_starts_with($ext_path, '/' . $modulename)) ? substr($ext_path, strlen($modulename) + 1) : $ext_path);
if (!$this->red_path) {
$this->red_path = '/';
}
@ -71,9 +71,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$this->folder_hash = '';
$this->getDir();
if ($this->auth->browser) {
$this->auth->browser->set_writeable();
}
$this->auth->browser?->set_writeable();
}
private function log()
@ -184,7 +182,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
if ($ch) {
$sync = attach_export_data($ch, $this->folder_hash);
if ($sync) {
Libsync::build_sync_packet($ch['channel_id'], array('file' => array($sync)));
Libsync::build_sync_packet($ch['channel_id'], ['file' => [$sync]]);
}
}
@ -390,7 +388,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$sync = attach_export_data($channel, $hash);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
}
@ -416,14 +414,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
// folder already exists.
require_once('include/attach.php');
$result = attach_mkdir($channel, $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash, 'force' => true));
$result = attach_mkdir($channel, $this->auth->observer, ['filename' => $name, 'folder' => $this->folder_hash, 'force' => true]);
if ($result['success']) {
$sync = attach_export_data($channel, $result['data']['hash']);
logger('createDirectory: attach_export_data returns $sync:' . print_r($sync, true), LOGGER_DEBUG);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
} else {
logger('error ' . print_r($result, true), LOGGER_DEBUG);
@ -452,10 +450,10 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$channel = Channel::from_id($this->auth->owner_id);
if ($channel) {
$sync = attach_export_data($channel, $this->folder_hash, true);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
}
$sync = attach_export_data($channel, $this->folder_hash, true);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
}
}
@ -497,7 +495,17 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
return false;
}
return attach_move($this->auth->owner_id, $sourceNode->data['hash'], $this->folder_hash);
$result = attach_move($this->auth->owner_id, $sourceNode->data['hash'], $this->folder_hash);
if ($result) {
$channel = Channel::from_id($this->auth->owner_id);
if ($channel) {
$sync = attach_export_data($channel, $sourceNode->data['hash'], false);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
}
}
}
return $result;
}
@ -710,7 +718,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
);
foreach ($r as $rr) {
if (App::$module === 'cloud' && (strpos($rr['filename'], '.') === 0) && (!get_pconfig($channel_id, 'system', 'show_dot_files'))) {
if (App::$module === 'cloud' && (str_starts_with($rr['filename'], '.')) && (!get_pconfig($channel_id, 'system', 'show_dot_files'))) {
continue;
}

View file

@ -54,10 +54,10 @@ class File extends DAV\Node implements DAV\IFile {
*
* @param string $name
* @param array $data from attach table
* @param &$auth
* @param $auth
*/
public function __construct($name, $data, &$auth) {
public function __construct($name, $data, $auth) {
$this->name = $name;
$this->data = $data;
$this->auth = $auth;
@ -89,6 +89,8 @@ class File extends DAV\Node implements DAV\IFile {
throw new DAV\Exception\Forbidden('Permission denied.');
}
// attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '')
$newName = str_replace('/', '%2F', $newName);
$r = q("UPDATE attach SET filename = '%s' WHERE hash = '%s' AND id = %d",
@ -99,7 +101,7 @@ class File extends DAV\Node implements DAV\IFile {
$x = attach_syspaths($this->auth->owner_id,$this->data['hash']);
$y = q("update attach set display_path = '%s where hash = '%s' and uid = %d",
$y = q("update attach set display_path = '%s' where hash = '%s' and uid = %d",
dbesc($x['path']),
dbesc($this->data['hash']),
intval($this->auth->owner_id)

View file

@ -30,8 +30,12 @@ Class Stdio {
if ($in && $out) {
$size = self::pipe_streams($in, $out, $bufsize);
}
fclose($in);
fclose($out);
if ($in) {
fclose($in);
}
if ($out) {
fclose($out);
}
restore_error_handler();
return $size;
}

33
Code/Update/_1264.php Normal file
View file

@ -0,0 +1,33 @@
<?php
namespace Code\Update;
class _1264
{
public function run()
{
q("START TRANSACTION");
if (ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r = q("ALTER TABLE item ADD approved text NOT NULL DEFAULT ''");
} else {
$r = q("ALTER TABLE item ADD approved varchar(255) NOT NULL DEFAULT ''");
}
if ($r) {
q("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
public function verify()
{
$columns = db_columns('item');
return in_array('approved', $columns);
}
}

View file

@ -146,7 +146,7 @@ class Notifications implements WidgetInterface
];
}
$o = replace_macros(Theme::get_template('notifications_widget.tpl'), [
return replace_macros(Theme::get_template('notifications_widget.tpl'), [
'$module' => App::$module,
'$notifications' => $notifications,
'$notifications_label' => t('Notifications'),
@ -155,6 +155,5 @@ class Notifications implements WidgetInterface
'$startpage' => get_pconfig(local_channel(), 'system', 'startpage')
]);
return $o;
}
}

View file

@ -52,23 +52,20 @@ class Savedsearch implements WidgetInterface
$srchurl = App::$query_string;
$srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
$hasq = ((strpos($srchurl, '?') !== false) ? true : false);
$srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
$srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
$srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
$srchurl = str_replace(array('?f=', '&f='), array('', ''), $srchurl);
$srchurl = str_replace(['?f=', '&f='], ['', ''], $srchurl);
$hasq = ((strpos($srchurl, '?') !== false) ? true : false);
$hasamp = ((strpos($srchurl, '&') !== false) ? true : false);
$hasq = str_contains($srchurl, '?');
$hasamp = str_contains($srchurl, '&');
if (($hasamp) && (!$hasq)) {
$srchurl = substr($srchurl, 0, strpos($srchurl, '&')) . '?f=&' . substr($srchurl, strpos($srchurl, '&') + 1);
}
$o = '';
$r = q(
"select tid,term from term WHERE uid = %d and ttype = %d ",
intval(local_channel()),
@ -79,7 +76,7 @@ class Savedsearch implements WidgetInterface
if (count($r)) {
foreach ($r as $rr) {
$saved[] = array(
$saved[] = [
'id' => $rr['tid'],
'term' => $rr['term'],
'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&amp;searchremove=1&amp;search=' . urlencode($rr['term']),
@ -88,18 +85,17 @@ class Savedsearch implements WidgetInterface
'encodedterm' => urlencode($rr['term']),
'delete' => t('Remove term'),
'selected' => ($search == $rr['term']),
);
];
}
}
$tpl = Theme::get_template("saved_searches.tpl");
$o = replace_macros($tpl, array(
return replace_macros($tpl, [
'$title' => t('Saved Searches'),
'$add' => t('add'),
'$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), true),
'$saved' => $saved,
));
]);
return $o;
}
}

View file

@ -2,7 +2,6 @@
namespace Code\Widget;
use App;
use Code\Render\Theme;
@ -11,7 +10,6 @@ class Sblock implements WidgetInterface
public function widget(array $arguments): string
{
if (!local_channel()) {
return EMPTY_STR;
}

View file

@ -20,26 +20,12 @@ class Settings_menu implements WidgetInterface
$channel = App::get_channel();
$abook_self_id = 0;
// Retrieve the 'self' address book entry for use in the auto-permissions link
$role = get_pconfig(local_channel(), 'system', 'permissions_role');
$abk = q(
"select abook_id from abook where abook_channel = %d and abook_self = 1 limit 1",
intval(local_channel())
);
if ($abk) {
$abook_self_id = $abk[0]['abook_id'];
}
$x = q(
"select count(*) as total from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 ",
dbesc($channel['channel_hash'])
);
$hublocs = (($x && $x[0]['total'] > 1) ? true : false);
$hublocs = $x && $x[0]['total'] > 1;
$tabs = [
[
@ -89,14 +75,6 @@ class Settings_menu implements WidgetInterface
'selected' => ''
];
// if(Features::enabled(local_channel(),'oauth_clients')) {
// $tabs[] = array(
// 'label' => t('OAuth1 apps'),
// 'url' => z_root() . '/settings/oauth',
// 'selected' => ((argv(1) === 'oauth') ? 'active' : ''),
// );
// }
if (Apps::system_app_installed(local_channel(), 'Clients')) {
$tabs[] = [
'label' => t('Client apps'),
@ -105,41 +83,15 @@ class Settings_menu implements WidgetInterface
];
}
// if(Features::enabled(local_channel(),'access_tokens')) {
// $tabs[] = array(
// 'label' => t('Guest Access Tokens'),
// 'url' => z_root() . '/settings/tokens',
// 'selected' => ((argv(1) === 'tokens') ? 'active' : ''),
// );
// }
if(Apps::system_app_installed(local_channel(),'Roles')) {
if(Apps::system_app_installed(local_channel(),'Roles')) {
$tabs[] = [
'label' => t('Permission Roles'),
'url' => z_root() . '/settings/permcats',
'selected' => ((argv(1) === 'permcats') ? 'active' : ''),
];
}
}
// if($role === false || $role === 'custom') {
// $tabs[] = array(
// 'label' => t('Connection Default Permissions'),
// 'url' => z_root() . '/defperms',
// 'selected' => ''
// );
// }
// if(Features::enabled(local_channel(),'channel_sources')) {
// $tabs[] = array(
// 'label' => t('Channel Sources'),
// 'url' => z_root() . '/sources',
// 'selected' => ''
// );
// }
$tabtpl = Theme::get_template("generic_links_widget.tpl");
return replace_macros($tabtpl, [
return replace_macros(Theme::get_template('generic_links_widget.tpl'), [
'$title' => t('Settings'),
'$class' => 'settings-widget',
'$items' => $tabs,

View file

@ -10,14 +10,13 @@ class Site_projects implements WidgetInterface
public function widget(array $arguments): string
{
$results = [];
$query = q("select site_project, site_type, count(site_project) as total from site
where site_project != '' and site_flags != 256 and site_dead = 0 group by site_project, site_type order by site_project desc");
$query = q("select site_project, count(site_project) as total from site
where site_project != '' and site_flags != 256 and site_dead = 0 group by site_project order by site_project desc");
if ($query) {
usort($query, ['self', 'site_sort']);
foreach ($query as $rv) {
$result = [];
$result['name'] = $rv['site_project'];
$result['type'] = $rv['site_type'];
$result['cname'] = ucfirst($result['name']);
if ($rv['site_project'] === $_REQUEST['project']) {
$result['selected'] = true;
@ -26,17 +25,16 @@ class Site_projects implements WidgetInterface
$results[] = $result;
}
$output = replace_macros(Theme::get_template('site_projects.tpl'), [
return replace_macros(Theme::get_template('site_projects.tpl'), [
'$title' => t('Community Types'),
'$desc' => '',
'$all' => t('All community types'),
'base' => z_root() . '/communities',
'$sel_all' => (($_REQUEST['project']) ? false : true),
'$sel_all' => !$_REQUEST['project'],
'$terms' => $results
]);
return $output;
}
return '';
}
public static function site_sort($a, $b)

View file

@ -21,24 +21,21 @@ class Sitesearch implements WidgetInterface
$srchurl = str_replace(['?f=', '&f='], ['', ''], $srchurl);
$hasq = ((str_contains($srchurl, '?')) ? true : false);
$hasamp = ((str_contains($srchurl, '&')) ? true : false);
$hasq = str_contains($srchurl, '?');
$hasamp = str_contains($srchurl, '&');
if (($hasamp) && (!$hasq)) {
$srchurl = substr($srchurl, 0, strpos($srchurl, '&')) . '?f=&' . substr($srchurl, strpos($srchurl, '&') + 1);
}
$o = '';
$saved = [];
$tpl = Theme::get_template("sitesearch.tpl");
$o = replace_macros($tpl, [
return replace_macros($tpl, [
'$title' => t('Search'),
'$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), false),
'$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f=')),
'$saved' => $saved,
]);
return $o;
}
}

View file

@ -37,9 +37,9 @@ class Suggestedchats implements WidgetInterface
$r[$x]['xchat_url'] = zid($r[$x]['xchat_url']);
}
}
return replace_macros(Theme::get_template('bookmarkedchats.tpl'), array(
return replace_macros(Theme::get_template('bookmarkedchats.tpl'), [
'$header' => t('Suggested Chatrooms'),
'$rooms' => $r
));
]);
}
}

View file

@ -27,7 +27,7 @@ class Suggestions implements WidgetInterface
// Get two random entries from the top 20 returned.
// We'll grab the first one and the one immediately following.
// This will throw some entropy into the situation so you won't
// This will throw some entropy into the situation, so you won't
// be looking at the same two mug shots every time the widget runs
$index = ((count($r) > 2) ? mt_rand(0, count($r) - 2) : 0);
@ -52,12 +52,10 @@ class Suggestions implements WidgetInterface
];
}
$o = replace_macros(Theme::get_template('suggest_widget.tpl'), [
return replace_macros(Theme::get_template('suggest_widget.tpl'), [
'$title' => t('Suggestions'),
'$more' => t('See more...'),
'$entries' => $arguments
]);
return $o;
}
}

View file

@ -18,6 +18,8 @@ Guest Pass: Provide special guest access to private resources and media - on you
Friend Zoom: Set your degree of closeness to any connection and then interactively zoom in to filter your stream to close friends; or zoom out to see posts by casual acquaintances.
Location Services: Check-in, check-out, and search by distance
Delivery Reports: In a decentralised multi-platform world, stuff happens. Sites and networks sometimes go down. Project developers sometimes introduce bugs and incompatibilities. This allows you to determine what happened to your post or comment and where it actually went once you published it.
Failsafe: Because the best time to have a current backup of your data is 10 seconds ago. Clone your online identity and content to multiple sites using the Nomad protocol and mirror any changes in near realtime. Then if your chosen site goes down (either temporarily or permanently) or you get booted off of it for some reason, your online life doesn't have to come to an end or force you to start over. All your friends and all your content are available on any of your cloned instances - at any time.

View file

@ -4,7 +4,7 @@ This repository first went public in 2010 and spawned a number of fediverse-rela
My name is Mike. I'm retired from open source now, but building decentralised communications software is what I do; and I've been doing it since before the web existed. So this isn't a hobby or get rich scheme - it's my life's mission and this repository is where I build and test new concepts and ideas.
From day one the question was how to build a federated/decentralised communication stack that provides more control over your privacy, and respects all people and cultures - including those which have a different political bias; while allowing them to all co-exist in the same space (and without killing each other). We've come up with lots of creative soutions to the thorniest of decentralisation problems over the intervening years.
From day one the question was how to build a federated/decentralised communication stack that provides more control over your privacy, and respects all people and cultures - including those which have a different political bias; while allowing them to all co-exist in the same space (and without killing each other). We've come up with lots of creative solutions to the thorniest of decentralisation problems over the intervening years.
I'll highlight the most important ones: we implement cross-domain granular permissions and cross-domain (nomadic) identity and cross-domain single sign-on. All of these work together to provide a communications platform which is probably unlike any you have used before. It is fully decentralised, but provides many features that were previously only available from monolithic centralised systems. This is a huge distinction from many/most other fediverse projects and could represent a killer app for both the fediverse and the internet at large once adopted at scale. This is all coming to the internet anyway as it is a natural progression, except in our vision, your online existence belongs to you and not to Facebook, Twitter, Microsoft, and Google.
@ -17,11 +17,11 @@ Single sign-on works with permissions to provide access to private media content
There are hundreds of other features available; but these are the defining features which have been constant for about the last decade. At one point there were so many features that we couldn't manage them all, so we simplified. Now the interface is much more sleek and basic; and you can add apps from our free app store to provide any advanced features you desire or require.
Since 2017, every branch of this repository evolved to support communications over ActivityPub, the current web standard for social communications. This provides immediate access to (currently) around 5 million people across (currently) around a hundred different software applications. There are Twitter clones and Facebook clones and Instagram clones and YouTube clones - and we interact with all of them. In the interests of full disclosure, this repository first went public in 2010 as a decentralised Facebook alternative, but we've since turned it into something completely different and no longer care about emulating anybody or anything. We provide a communications experience with privacy mechanisms and features you simply won't find elsewhere.
Since 2017, every branch of this repository evolved to support communications over ActivityPub, the current web standard for social communications. This provides immediate access to (currently) around 6 million people across (currently) around a hundred different software applications. There are Twitter clones and Facebook clones and Instagram clones and YouTube clones - and we interact with all of them. In the interests of full disclosure, this repository first went public in 2010 as a decentralised Facebook alternative, but we've since turned it into something completely different and no longer care about emulating anybody or anything. We provide a communications experience with privacy mechanisms and features you simply won't find elsewhere.
This software will install as a fediverse server using the LAMP stack. There are also containerised installations available (i.e. https://codeberg.org/node9/streams.docker). It is regularly maintained and updated and you are welcome to help - if you want. There is no formal organisation here. Either help out or don't. Many/most of our sites are privately run on small devices for family and friends and we don't know and don't care how many exist or how many "users" are on our systems. The servers themselves require very little ongoing maintenance and we spend a lot of effort providing a level playing field for all. You have the same features and abilities no matter how big (or small) your server is.
This software will install as a fediverse server using the LAMP stack. It is regularly maintained and updated, and you are welcome to help - if you want. There are also containerised installations available (i.e. https://codeberg.org/node9/streams.docker). There is no formal organisation here. Either help out or don't. Many/most of our sites are privately run on small devices for family and friends, and we don't know and don't care how many exist or how many "users" are on our systems. The servers themselves require very little ongoing maintenance, and we spend a lot of effort providing a level playing field for all. You have the same features and abilities no matter how large (or small) your server is.
This work is dedicated and released to the public domain with no strings attached. Be advised that many others have contributed code to this repository under a number of different OSI-approved software licenses during its existence. This has no effect on any of your fundamental software freedoms; although corporate legal consultants who wish to re-appropriate our work for their employer's profit will likely find this lack of license clarity "troublesome". This is intentional.
The current name of this repository implies fluidity. As a brand or product it technically does not exist. This is also intentional. The software provides general web communications infrastructure. It's your website. Your site is your brand. Not ours.
The current name of this repository implies fluidity. As a brand or product it technically does not exist. This is also intentional.

View file

@ -26,7 +26,7 @@ use Code\Lib\Url;
const REPOSITORY_ID = 'streams';
const DB_UPDATE_VERSION = 1263;
const DB_UPDATE_VERSION = 1264;
const PROJECT_BASE = __DIR__;
const ACTIVITYPUB_ENABLED = true;
const NOMAD_PROTOCOL_VERSION = '11.0';

View file

@ -2,7 +2,7 @@
## Disclaimer
- This script does work with Debian 10 or 11 only.
- This script does work with Debian 11 only.
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation). You may use it to install more than one website on the same computer as long as you use a single webserver.
## First step: setting up your system

View file

@ -1,5 +1,7 @@
# Easy install setup script
## This installation script was provided by the community and is untested and officially unsupported. Use at your own risk. Complaints have been made that it provides the wrong PHP version for the Streams repository, which requires PHP 8.0 or above. In case of difficulty, this would be the first thing to check. If you manage to fix the issue, please submit back to the repository so we can remove this warning.
Here you will find a quick and easy way to set up a website capable of joining the fediverse, using software from the Streams repository. All you have to do is run the setup script, enter some information and the magic will happen. Check the [INSTALL.md](INSTALL.md) file for step-by-step instructions.
## Requirements

View file

@ -25,7 +25,7 @@
# under Debian Linux. It will:
# - install
# * apache or nginx webserver,
# * php (adding sury repository to get php 8.* on Debian 11 or 10),
# * php (adding sury repository to get php 8.* on Debian 11),
# * composer
# * mariadb - the database your website,
# * adminer,
@ -91,9 +91,9 @@ function check_sanity {
then
die "Debian is supported only"
fi
if [ -z "$(grep 'Linux 10\|Linux 11' /etc/issue)" ]
if [ -z "$(grep 'Linux 11' /etc/issue)" ]
then
die "Debian 11 (bullseye) or Debian 10 (buster) are supported only"
die "Debian 11 (bullseye) is supported only"
fi
}

Some files were not shown because too many files have changed in this diff Show more