diff options
Diffstat (limited to 'Zotlabs')
49 files changed, 497 insertions, 237 deletions
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 592dd2c38..4b74a7ba9 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -300,6 +300,11 @@ class Notifier { return; } + if ($target_item['verb'] === ACTIVITY_SHARE) { + // Provide correct representation across the wire. Internally this is treated as a comment. + $target_item['parent_mid'] = $target_item['thr_parent'] = $target_item['mid']; + } + if ($target_item['mid'] === $target_item['parent_mid']) { $parent_item = $target_item; $top_level_post = true; @@ -377,7 +382,7 @@ class Notifier { if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) { logger('notifier: followup relay', LOGGER_DEBUG); - $sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']); + $sendto = (($uplink) ? $parent_item['source_xchan'] : (($parent_item['verb'] === ACTIVITY_SHARE) ? $parent_item['author_xchan'] : $parent_item['owner_xchan'])); self::$recipients = [$sendto]; self::$private = true; $upstream = true; diff --git a/Zotlabs/Daemon/Xchan_photo.php b/Zotlabs/Daemon/Xchan_photo.php new file mode 100644 index 000000000..f90d1d726 --- /dev/null +++ b/Zotlabs/Daemon/Xchan_photo.php @@ -0,0 +1,34 @@ +<?php + +/** @file */ + +namespace Zotlabs\Daemon; + +class Xchan_photo { + + static public function run($argc, $argv) { + + if ($argc != 3) { + return; + } + + $url = hex2bin($argv[1]); + $xchan = hex2bin($argv[2]); + + $photos = import_xchan_photo($url, $xchan); + if ($photos) { + $result = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", + dbescdate(datetime_convert()), + dbesc($photos[0]), + dbesc($photos[1]), + dbesc($photos[2]), + dbesc($photos[3]), + dbesc($xchan) + ); + + if (! $result) { + logger("xchan update failed for $url"); + } + } + } +} diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 992ade200..835909849 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -120,6 +120,7 @@ class Activity { } $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), false); + $start_timestamp = microtime(true); $x = z_fetch_url($url, true, $redirects, ['headers' => $h]); } @@ -142,8 +143,14 @@ class Activity { logger('returned: ' . json_encode($y, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOGGER_DEBUG); if (isset($y['type']) && ActivityStreams::is_an_actor($y['type'])) { + logger('logger_stats_data cmd:Actor_fetch' . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $url . '#' . random_string(16)); + btlogger('actor fetch'); + $y['actor_cache_date'] = datetime_convert(); XConfig::Set($y['id'], 'system', 'actor_record', $y); } + else { + logger('logger_stats_data cmd:Activity_fetch' . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $url . '#' . random_string(16)); + } return json_decode($x['body'], true); } @@ -151,6 +158,8 @@ class Activity { logger('fetch failed: ' . $url); logger($x['body']); } + + return null; } @@ -543,7 +552,7 @@ class Activity { $ret['commentPolicy'] .= 'until=' . datetime_convert('UTC', 'UTC', $i['comments_closed'], ATOM_TIME); } - $ret['attributedTo'] = $i['author']['xchan_url']; + $ret['attributedTo'] = self::encode_person($i['author'], false); if ($i['mid'] !== $i['parent_mid']) { $ret['inReplyTo'] = ((strpos($i['thr_parent'], 'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent'])); @@ -1369,7 +1378,7 @@ class Activity { // store their xchan and hubloc - self::actor_store($person_obj['id'], $person_obj); + self::actor_store($person_obj); // Find any existing abook record @@ -1600,15 +1609,7 @@ class Activity { } - static function actor_store($url, $person_obj = null, $force = false) { - - if ($person_obj === null) { - $tgt = self::fetch($url); - if (is_array($tgt) && ActivityStreams::is_an_actor($tgt['type'])) { - self::actor_store($tgt['id'], $tgt); - } - return; - } + static function actor_store($person_obj, $force = false) { if (!is_array($person_obj)) { return; @@ -1618,13 +1619,14 @@ class Activity { if (array_key_exists('movedTo',$person_obj) && $person_obj['movedTo'] && ! is_array($person_obj['movedTo'])) { $tgt = self::fetch($person_obj['movedTo']); if (is_array($tgt)) { - self::actor_store($person_obj['movedTo'],$tgt); + self::actor_store($tgt); ActivityPub::move($person_obj['id'],$tgt); } return; } */ + $url = null; $ap_hubloc = null; $hublocs = self::get_actor_hublocs($url); @@ -1645,7 +1647,7 @@ class Activity { if ($ap_hubloc) { // we already have a stored record. Determine if it needs updating. if ($ap_hubloc['hubloc_updated'] < datetime_convert('UTC', 'UTC', ' now - 3 days') || $force) { - $person_obj = self::fetch($url); + $person_obj = self::get_cached_actor($url); } else { return; @@ -1668,11 +1670,6 @@ class Activity { return; } - // store the actor record in XConfig - - // we already store this in Activity::fetch() - // XConfig::Set($url, 'system', 'actor_record', $person_obj); - $name = $person_obj['name'] ?? ''; if (!$name) { $name = $person_obj['preferredUsername'] ?? ''; @@ -1697,7 +1694,7 @@ class Activity { $webfinger_addr = escape_tags($person_obj['preferredUsername']) . '@' . $hostname; } - $icon = z_root() . '/' . get_default_profile_photo(300); + $icon = null; if (isset($person_obj['icon'])) { if (is_array($person_obj['icon'])) { if (array_key_exists('url', $person_obj['icon'])) { @@ -1807,6 +1804,9 @@ class Activity { 'xchan_addr' => $webfinger_addr, 'xchan_url' => $profile, 'xchan_name' => escape_tags($name), + 'xchan_photo_l' => z_root() . '/' . get_default_profile_photo(), + 'xchan_photo_m' => z_root() . '/' . get_default_profile_photo(80), + 'xchan_photo_s' => z_root() . '/' . get_default_profile_photo(48), 'xchan_name_date' => datetime_convert(), 'xchan_network' => 'activitypub', 'xchan_pubforum' => intval($group_actor) @@ -1846,16 +1846,9 @@ class Activity { } } - $photos = import_xchan_photo($icon, $url); - q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", - dbescdate(datetime_convert('UTC', 'UTC', $photos[5])), - dbesc($photos[0]), - dbesc($photos[1]), - dbesc($photos[2]), - dbesc($photos[3]), - dbesc($url) - ); - + if ($icon) { + Master::Summon(['Xchan_photo', bin2hex($icon), bin2hex($url)]); + } } static function create_action($channel, $observer_hash, $act) { @@ -2281,6 +2274,7 @@ class Activity { } static function decode_note($act) { + $response_activity = false; $s = []; @@ -2307,7 +2301,7 @@ class Activity { } // ensure we store the original actor - self::actor_store($act->actor['id'], $act->actor); + self::actor_store($act->actor); $s['owner_xchan'] = $act->actor['id']; $s['author_xchan'] = $act->actor['id']; @@ -2351,7 +2345,7 @@ class Activity { $s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']); } - if ($act->type === 'Invite' && $act->objprop('type') === 'Event') { + if (in_array($act->type, ['Invite', 'Create']) && $act->objprop('type') === 'Event') { $s['mid'] = $s['parent_mid'] = $act->id; } @@ -2362,6 +2356,9 @@ class Activity { $s['mid'] = $act->id; $s['uuid'] = ((!empty($act->data['diaspora:guid'])) ? $act->data['diaspora:guid'] : uuid_from_url($s['mid'])); + $s['parent_mid'] = $act->objprop('id') ?: $act->obj; + +/* if ($act->objprop('inReplyTo')) { $s['parent_mid'] = $act->objprop('inReplyTo'); } @@ -2372,7 +2369,7 @@ class Activity { logger('response activity without parent_mid or thr_parent'); return; } - +*/ // over-ride the object timestamp with the activity if (isset($act->data['published'])) { @@ -2390,30 +2387,30 @@ class Activity { } // ensure we store the original actor - self::actor_store($obj_actor['id'], $obj_actor); + self::actor_store($obj_actor); $mention = self::get_actor_bbmention($obj_actor['id']); if ($act->type === 'Like') { - $content['content'] = sprintf(t('Likes %1$s\'s %2$s'), $mention, $act->obj['type']) . "\n\n" . $content['content'] ?? ''; + $content['content'] = sprintf(t('Likes %1$s\'s %2$s'), $mention, $act->obj['type']) . EOL . EOL . ($content['content'] ?? ''); } if ($act->type === 'Dislike') { - $content['content'] = sprintf(t('Doesn\'t like %1$s\'s %2$s'), $mention, $act->obj['type']) . "\n\n" . $content['content'] ?? ''; + $content['content'] = sprintf(t('Doesn\'t like %1$s\'s %2$s'), $mention, $act->obj['type']) . EOL . EOL . ($content['content'] ?? ''); } // handle event RSVPs if (($act->objprop('type') === 'Event') || ($act->objprop('type') === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event')) { if ($act->type === 'Accept') { - $content['content'] = sprintf(t('Will attend %s\'s event'), $mention) . EOL . EOL . $content['content']; + $content['content'] = sprintf(t('Will attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? ''); } if ($act->type === 'Reject') { - $content['content'] = sprintf(t('Will not attend %s\'s event'), $mention) . EOL . EOL . $content['content']; + $content['content'] = sprintf(t('Will not attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? ''); } if ($act->type === 'TentativeAccept') { - $content['content'] = sprintf(t('May attend %s\'s event'), $mention) . EOL . EOL . $content['content']; + $content['content'] = sprintf(t('May attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? ''); } if ($act->type === 'TentativeReject') { - $content['content'] = sprintf(t('May not attend %s\'s event'), $mention) . EOL . EOL . $content['content']; + $content['content'] = sprintf(t('May not attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? ''); } } @@ -2596,11 +2593,11 @@ class Activity { if (!$response_activity) { if ($act->type === 'Announce') { $s['author_xchan'] = self::get_attributed_to_actor_url($act); - $s['mid'] = $act->obj['id']; + $s['mid'] = $act->objprop('id') ?: $act->obj; // Do not force new thread if the announce is from a group actor if ($act->actor['type'] !== 'Group') { - $s['parent_mid'] = $act->obj['id']; + $s['parent_mid'] = $act->objprop('id') ?: $act->obj; } } @@ -2903,6 +2900,10 @@ class Activity { set_iconfig($s, 'activitypub', 'recips', $act->raw_recips); } + if ($act->objprop('type') === 'Event' && $act->objprop('timezone')) { + set_iconfig($s, 'event', 'timezone', $act->objprop('timezone'), true); + } + $hookinfo = [ 'act' => $act, 's' => $s @@ -3007,7 +3008,7 @@ class Activity { $allowed = true; // reject public stream comments that weren't sent by the conversation owner - if ($is_sys_channel && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) { + if ($is_sys_channel && $item['owner_xchan'] !== $observer_hash && !$fetch_parents && empty($item['item_fetched'])) { $allowed = false; } } @@ -3143,8 +3144,6 @@ class Activity { $fetch = false; - // TODO: debug - // if (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && (PConfig::Get($channel['channel_id'],'system','hyperdrive',true) || $act->type === 'Announce')) { if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) { $fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false); } @@ -3162,7 +3161,7 @@ class Activity { return; } -/* + if ($parent[0]['parent_mid'] !== $item['parent_mid']) { $item['thr_parent'] = $item['parent_mid']; } @@ -3170,7 +3169,7 @@ class Activity { $item['thr_parent'] = $parent[0]['parent_mid']; } $item['parent_mid'] = $parent[0]['parent_mid']; -*/ + /* * @@ -3263,7 +3262,12 @@ class Activity { } } - if (is_array($x) && $x['item_id']) { + if ($x['success']) { + + if (check_item_source($channel['channel_id'], $x['item']) && in_array($x['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) { + event_addtocal($x['item_id'], $channel['channel_id']); + } + if ($is_child_node) { if ($item['owner_xchan'] === $channel['channel_hash']) { // We are the owner of this conversation, so send all received comments back downstream @@ -3384,7 +3388,7 @@ class Activity { } if (is_array($a->actor) && array_key_exists('id', $a->actor)) { - self::actor_store($a->actor['id'], $a->actor); + self::actor_store($a->actor); } $replies = null; @@ -4035,7 +4039,8 @@ class Activity { $cache_url = ((strpos($id, '#')) ? substr($id, 0, strpos($id, '#')) : $id); $actor = XConfig::Get($cache_url, 'system', 'actor_record'); - if ($actor) { + if ($actor && isset($actor['actor_cache_date']) && $actor['actor_cache_date'] > datetime_convert('UTC', 'UTC', ' now - 3 days')) { + unset($actor['actor_cache_date']); return $actor; } @@ -4050,6 +4055,25 @@ class Activity { return $hookdata['actor']; } + static function get_actor($actor_id) { + // remove fragment + $actor_id = ((strpos($actor_id, '#')) ? substr($actor_id, 0, strpos($actor_id, '#')) : $actor_id); + + $actor = self::get_cached_actor($actor_id); + + if ($actor) { + return $actor; + } + + $actor = self::fetch($actor_id); + + if ($actor) { + return $actor; + } + + return null; + } + static function get_unknown_actor($act) { // try other get_actor providers (e.g. diaspora) diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index 8b8c95ad8..4c3e3d8f8 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -351,7 +351,7 @@ class ActivityStreams { $x = $this->get_property_obj($property, $base, $namespace); if ($this->is_url($x)) { - $y = Activity::get_cached_actor($x); + $y = Activity::get_actor($x); if ($y) { return $y; } diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 497a9d299..00e65479e 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -419,11 +419,28 @@ class Apps { static public function app_render($papp, $mode = 'view') { $installed = false; - if(! $papp) + if(!$papp) { return; + } + + /** + * @hooks app_render_before + * Hook to manipulate the papp array before rendering + */ - if(! $papp['photo']) + $hookinfo = [ + 'name' => $papp['name'], + 'photo' => $papp['photo'] + ]; + + call_hooks('app_render_manipulate_photo', $hookinfo); + + // We will only allow to manipulate the photo + $papp['photo'] = $hookinfo['photo']; + + if(!$papp['photo']) { $papp['photo'] = 'icon:gear'; + } self::translate_system_apps($papp); diff --git a/Zotlabs/Lib/Cache.php b/Zotlabs/Lib/Cache.php index a5052a183..60bf64611 100644 --- a/Zotlabs/Lib/Cache.php +++ b/Zotlabs/Lib/Cache.php @@ -5,17 +5,17 @@ namespace Zotlabs\Lib; /** * cache api */ - + class Cache { - + /** * @brief Returns cached content - * + * * @param string $key * @param string $age in SQL format, default is '30 DAY' * @return string */ - + public static function get($key, $age = '') { $hash = hash('whirlpool',$key); @@ -25,12 +25,12 @@ class Cache { db_utcnow(), db_quoteinterval(($age ? $age : get_config('system','object_cache_days', '30') . ' DAY')) ); - + if ($r) return $r[0]['v']; return null; } - + public static function set($key,$value) { $hash = hash('whirlpool',$key); @@ -45,7 +45,7 @@ class Cache { dbesc($hash)); } else { - q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')", + q("INSERT INTO cache (k, v, updated) VALUES ('%s', '%s', '%s')", dbesc($hash), dbesc($value), dbesc(datetime_convert())); diff --git a/Zotlabs/Lib/Config.php b/Zotlabs/Lib/Config.php index c00b8efb6..40d5cc246 100644 --- a/Zotlabs/Lib/Config.php +++ b/Zotlabs/Lib/Config.php @@ -2,6 +2,7 @@ namespace Zotlabs\Lib; +use App; class Config { @@ -14,21 +15,44 @@ class Config { * @param string $family * The category of the configuration value */ - static public function Load($family) { - if(! array_key_exists($family, \App::$config)) - \App::$config[$family] = array(); + public static function Load($family, $recursionCounter = 0) { + if (! array_key_exists($family, App::$config)) { + App::$config[$family] = []; + } + + // We typically continue when presented with minor DB issues, + // but loading the site configuration is more important. + + // Check for query returning false and give it approx 30 seconds + // to recover if there's a problem. This is intended to fix a + // rare issue on Galera where temporary sync issues were causing + // the site encryption keys to be regenerated, which was causing + // communication issues for members. + + // This code probably belongs at the database layer, but we don't + // necessarily want to shut the site down for problematic queries + // caused by bad data. That could be used in a denial of service + // attack. Those do need to be (and they are) logged. - if(! array_key_exists('config_loaded', \App::$config[$family])) { + if (! array_key_exists('config_loaded', App::$config[$family])) { $r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family)); - if($r !== false) { - if($r) { - foreach($r as $rr) { - $k = $rr['k']; - \App::$config[$family][$k] = $rr['v']; - } + if ($r === false) { + sleep(3); + $recursionCounter ++; + if ($recursionCounter > 10) { + system_unavailable(); } - \App::$config[$family]['config_loaded'] = true; + self::Load($family, $recursionCounter); } + else { + foreach ($r as $rr) { + $k = $rr['k']; + App::$config[$family][$k] = $rr['v']; + } + App::$config[$family]['config_loaded'] = true; + } + + } } @@ -46,19 +70,19 @@ class Config { * @return mixed * Return the set value, or false if the database update failed */ - static public function Set($family, $key, $value) { + public static function Set($family, $key, $value) { // manage array value - $dbvalue = ((is_array($value)) ? serialize($value) : $value); + $dbvalue = ((is_array($value)) ? serialise($value) : $value); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); - if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) { + if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) { $ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ", dbesc($family), dbesc($key), dbesc($dbvalue) ); - if($ret) { - \App::$config[$family][$key] = $value; + if ($ret) { + App::$config[$family][$key] = $value; $ret = $value; } return $ret; @@ -70,8 +94,8 @@ class Config { dbesc($key) ); - if($ret) { - \App::$config[$family][$key] = $value; + if ($ret) { + App::$config[$family][$key] = $value; $ret = $value; } @@ -96,18 +120,21 @@ class Config { * @param string $default (optional) default false * @return mixed Return value or false on error or if not set */ - static public function Get($family, $key, $default = false) { - if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family]))) + public static function Get($family, $key, $default = false) { + if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) { self::Load($family); + } - if(array_key_exists('config_loaded', \App::$config[$family])) { - if(! array_key_exists($key, \App::$config[$family])) { + if (array_key_exists('config_loaded', App::$config[$family])) { + if (! array_key_exists($key, App::$config[$family])) { return $default; } - return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key])) - ? unserialize(\App::$config[$family][$key]) - : \App::$config[$family][$key] + + return ((! is_array(App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$family][$key])) + ? unserialize(App::$config[$family][$key]) + : App::$config[$family][$key] ); + } return $default; @@ -125,12 +152,13 @@ class Config { * The configuration key to delete * @return mixed */ - static public function Delete($family, $key) { + public static function Delete($family, $key) { $ret = false; - if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family])) - unset(\App::$config[$family][$key]); + if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) { + unset(App::$config[$family][$key]); + } $ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'", dbesc($family), @@ -153,7 +181,7 @@ class Config { * The configuration key to query * @return mixed */ - static private function get_from_storage($family,$key) { + private static function get_from_storage($family, $key) { $ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1", dbesc($family), dbesc($key) @@ -161,5 +189,4 @@ class Config { return $ret; } - } diff --git a/Zotlabs/Lib/JSalmon.php b/Zotlabs/Lib/JSalmon.php index f9fe99706..5531f791f 100644 --- a/Zotlabs/Lib/JSalmon.php +++ b/Zotlabs/Lib/JSalmon.php @@ -52,7 +52,7 @@ class JSalmon { . base64url_encode($x['alg'],true); $key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id'])); - logger('key: ' . print_r($key,true)); + logger('key: ' . print_r($key,true), LOGGER_DATA); if($key['portable_id'] && $key['public_key']) { if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) { logger('verified'); diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 032fae3fc..3f8685397 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1114,6 +1114,7 @@ class Libzot { */ static function import($arr) { + $env = $arr; $private = false; $return = []; @@ -1219,25 +1220,30 @@ class Libzot { return; } - $r = Activity::get_actor_hublocs($AS->actor['id']); + $author_url = $AS->actor['id']; + + if ($AS->type === 'Announce') { + $author_url = Activity::get_attributed_to_actor_url($AS); + } - if (! $r) { + $r = Activity::get_actor_hublocs($author_url); + + if (!$r) { // Author is unknown to this site. Perform channel discovery and try again. - $z = discover_by_webbie($AS->actor['id']); + $z = discover_by_webbie($author_url); if ($z) { - $r = Activity::get_actor_hublocs($AS->actor['id']); + $r = Activity::get_actor_hublocs($author_url); } - } - if ($r) { - $r = self::zot_record_preferred($r); - $item['author_xchan'] = $r['hubloc_hash']; + if (!$r) { + logger('Could not fetch author'); + return; + } } - if (! $item['author_xchan']) { - logger('No author!'); - return; - } + $r = self::zot_record_preferred($r); + + $item['author_xchan'] = $r['hubloc_hash']; $item['owner_xchan'] = $env['sender']; @@ -1448,7 +1454,7 @@ class Libzot { if ($act && $act->obj) { if (isset($act->obj['tag']) && is_array($act->obj['tag']) && $act->obj['tag']) { foreach ($act->obj['tag'] as $tag) { - if ($tag['type'] === 'Mention' && (strpos($tag['href'], z_root()) !== false)) { + if (isset($tag['type'], $tag['href']) && $tag['type'] === 'Mention' && (strpos($tag['href'], z_root()) !== false)) { $address = basename($tag['href']); if ($address) { $z = q("select channel_hash as hash from channel where channel_address = '%s' and channel_hash != '%s' @@ -1509,11 +1515,9 @@ class Libzot { */ static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) { - $result = []; // We've validated the sender. Now make sure that the sender is the owner or author - if (!$public) { if ($sender != $arr['owner_xchan'] && $sender != $arr['author_xchan']) { logger("Sender $sender is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}"); @@ -1634,6 +1638,13 @@ class Libzot { if (!$allowed && $permit_mentions) { $allowed = true; } + + if (!$allowed) { + if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') { + $arr['item_blocked'] = ITEM_MODERATED; + $allowed = true; + } + } } } elseif ($permit_mentions) { @@ -1642,7 +1653,6 @@ class Libzot { } if ($request) { - // Conversation fetches (e.g. $request == true) take place for // a) new comments on expired posts // b) hyperdrive (friend-of-friend) conversations @@ -1829,13 +1839,19 @@ class Libzot { if ($r) { // We already have this post. + // Dismiss its announce + if ($act->type === 'Announce') { + $DR->update('update ignored'); + $result[] = $DR->get(); + continue; + } + $item_id = $r[0]['id']; if (intval($r[0]['item_deleted'])) { // It was deleted locally. $DR->update('update ignored'); $result[] = $DR->get(); - continue; } // Maybe it has been edited? @@ -1843,17 +1859,17 @@ class Libzot { $arr['id'] = $r[0]['id']; $arr['uid'] = $channel['channel_id']; - if (post_is_importable($channel['channel_id'], $arr, $abook)) { - $item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery); - $DR->update('updated'); - $result[] = $DR->get(); - if (!$relay) { - add_source_route($item_id, $sender); - } - } else { - $DR->update('update ignored'); - $result[] = $DR->get(); - } + if (post_is_importable($channel['channel_id'], $arr, $abook)) { + $item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery); + $DR->update('updated'); + $result[] = $DR->get(); + if (!$relay) { + add_source_route($item_id, $sender); + } + } else { + $DR->update('update ignored'); + $result[] = $DR->get(); + } } else { $DR->update('update ignored'); @@ -1871,8 +1887,9 @@ class Libzot { // if it's a sourced post, call the post_local hooks as if it were // posted locally so that crosspost connectors will be triggered. + $item_source = check_item_source($arr['uid'], $arr); - if (check_item_source($arr['uid'], $arr) || ($channel['xchan_pubforum'] == 1)) { + if ($item_source || ($channel['xchan_pubforum'] == 1)) { /** * @hooks post_local * Called when an item has been posted on this machine via mod/item.php (also via API). @@ -1898,7 +1915,13 @@ class Libzot { if (post_is_importable($arr['uid'], $arr, $abook)) { $item_result = item_store($arr); if ($item_result['success']) { + $item_id = $item_result['item_id']; + + if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) { + event_addtocal($item_id, $channel['channel_id']); + } + $parr = [ 'item_id' => $item_id, 'item' => $arr, @@ -1921,7 +1944,8 @@ class Libzot { add_source_route($item_id, $sender); } } - $DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']); + + $DR->update(($item_id) ? (($item_result['item']['item_blocked'] === ITEM_MODERATED) ? 'accepted for moderation' : 'posted') : 'storage failed: ' . $item_result['message']); $result[] = $DR->get(); } else { $DR->update('post ignored'); @@ -1938,7 +1962,7 @@ class Libzot { retain_item($stored['item']['parent']); } - if ($relay && $item_id) { + if ($relay && $item_id && $stored['item_blocked'] !== ITEM_MODERATED) { logger('Invoking relay'); Master::Summon(['Notifier', 'relay', intval($item_id)]); $DR->addto_update('relayed'); @@ -2006,7 +2030,7 @@ class Libzot { // logger($AS->debug()); if(empty($AS->actor['id'])) { - logger('No actor id!'); + logger('No actor id: ' . print_r($AS, true)); continue; } diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php index 58138850c..ca3902a9e 100644 --- a/Zotlabs/Lib/Libzotdir.php +++ b/Zotlabs/Lib/Libzotdir.php @@ -362,12 +362,9 @@ class Libzotdir { self::delete_by_hash($ud['ud_hash']); } - // backwards compatibility: Libzot::import_xchan(), where self::update() is called, - // will fail with versions < 8.4 if the channel has been locally deleted. - // In this case we will update the updates record here without bumping the date - // since we could not verify if anything changed. - if (!$xc['success'] && !empty($zf['data']['deleted_locally'])) { - self::update($ud['ud_hash'], $ud['ud_addr'], false); + // if the channel was deleted - delete the entry in updates + if (!empty($zf['data']['deleted_locally'])) { + self::delete_by_hash($ud['ud_hash']); } // This is a workaround for a missing xchan_updated column diff --git a/Zotlabs/Lib/QueueWorker.php b/Zotlabs/Lib/QueueWorker.php index 1c74b42d8..68e747b0f 100644 --- a/Zotlabs/Lib/QueueWorker.php +++ b/Zotlabs/Lib/QueueWorker.php @@ -63,6 +63,8 @@ class QueueWorker { return; } + logger('queueworker_stats_summon: cmd:' . $argv[0] . ' ' . 'timestamp:' . time()); + self::qstart(); $r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')", intval($priority), @@ -299,12 +301,16 @@ class QueueWorker { $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; $argv = flatten_array_recursive($argv); $argc = count($argv); - $rnd = random_string(); + $rnd = random_string(16); logger('PROCESSING: ' . $rnd . ' ' . print_r($argv[0], true)); + $start_timestamp = microtime(true); + $cls::run($argc, $argv); + logger('logger_stats_data cmd:' . $argv[0] . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $rnd); + logger('COMPLETED: ' . $rnd); // @FIXME: Right now we assume that if we get a return, everything is OK. diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 7d2bcde56..037ddb19e 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -185,7 +185,7 @@ class ThreadItem { $filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false); - $profile_avatar = $item['author']['xchan_photo_m']; + $profile_avatar = $item['author']['xchan_photo_s']; $profile_link = chanlink_hash($item['author_xchan']); $profile_name = $item['author']['xchan_name']; @@ -874,7 +874,7 @@ class ThreadItem { if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) { $this->owner_url = chanlink_hash($this->data['owner']['xchan_hash']); - $this->owner_photo = $this->data['owner']['xchan_photo_m']; + $this->owner_photo = $this->data['owner']['xchan_photo_s']; $this->owner_name = $this->data['owner']['xchan_name']; $this->wall_to_wall = true; } diff --git a/Zotlabs/Lib/Zotfinger.php b/Zotlabs/Lib/Zotfinger.php index fa57ab56d..ccf64d6d1 100644 --- a/Zotlabs/Lib/Zotfinger.php +++ b/Zotlabs/Lib/Zotfinger.php @@ -35,9 +35,13 @@ class Zotfinger { $result = []; $redirects = 0; + + $start_timestamp = microtime(true); $x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] ); + logger('logger_stats_data cmd:Zotfinger' . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $resource . '#' . random_string(16)); + btlogger('Zotfinger'); - logger('fetch: ' . print_r($x,true)); + logger('fetch: ' . print_r($x,true), LOGGER_DATA); if (in_array(intval($x['return_code']), [ 404, 410 ]) && $recurse) { @@ -74,7 +78,7 @@ class Zotfinger { $result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true); } - logger('decrypted: ' . print_r($result,true)); + logger('decrypted: ' . print_r($result,true), LOGGER_DATA); return $result; } diff --git a/Zotlabs/Module/Admin/Accounts.php b/Zotlabs/Module/Admin/Accounts.php index 1c1911b3a..b067b4bf6 100644 --- a/Zotlabs/Module/Admin/Accounts.php +++ b/Zotlabs/Module/Admin/Accounts.php @@ -346,7 +346,7 @@ class Accounts { '$users' => $users, '$msg' => t('Message') )); - $o .= paginate($a); + $o .= paginate(); return $o; } diff --git a/Zotlabs/Module/Admin/Channels.php b/Zotlabs/Module/Admin/Channels.php index 09769a166..c6b7ad17a 100644 --- a/Zotlabs/Module/Admin/Channels.php +++ b/Zotlabs/Module/Admin/Channels.php @@ -168,7 +168,7 @@ class Channels { '$baseurl' => z_root(), '$channels' => $channels, )); - $o .= paginate($a); + $o .= paginate(); return $o; } diff --git a/Zotlabs/Module/Admin/Themes.php b/Zotlabs/Module/Admin/Themes.php index 8e72a1318..7f615afa8 100644 --- a/Zotlabs/Module/Admin/Themes.php +++ b/Zotlabs/Module/Admin/Themes.php @@ -80,10 +80,25 @@ class Themes { $this->toggle_theme($themes, $theme, $result); $s = $this->rebuild_theme_table($themes); - if($result) - info( sprintf('Theme %s enabled.', $theme)); - else - info( sprintf('Theme %s disabled.', $theme)); + + if($result) { + if (is_file("view/theme/$theme/php/config.php")){ + require_once("view/theme/$theme/php/config.php"); + if (function_exists($theme . '_theme_admin_enable')){ + call_user_func($theme . '_theme_admin_enable'); + } + } + info(sprintf('Theme %s enabled.', $theme)); + } + else { + if (is_file("view/theme/$theme/php/config.php")){ + require_once("view/theme/$theme/php/config.php"); + if (function_exists($theme . '_theme_admin_disable')){ + call_user_func($theme . '_theme_admin_disable'); + } + } + info(sprintf('Theme %s disabled.', $theme)); + } set_config('system', 'allowed_themes', $s); goaway(z_root() . '/admin/themes' ); diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php index 34f5f453d..5f72d771b 100644 --- a/Zotlabs/Module/Appman.php +++ b/Zotlabs/Module/Appman.php @@ -110,6 +110,11 @@ class Appman extends \Zotlabs\Web\Controller { dbesc($papp['guid']) ); + $sync[0]['term'] = q("select * from term where otype = %d and oid = %d", + intval(TERM_OBJ_APP), + intval($sync[0]['id']) + ); + if (intval($sync[0]['app_system'])) { Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]); } @@ -126,6 +131,11 @@ class Appman extends \Zotlabs\Web\Controller { dbesc($papp['guid']) ); + $sync[0]['term'] = q("select * from term where otype = %d and oid = %d", + intval(TERM_OBJ_APP), + intval($sync[0]['id']) + ); + if (intval($sync[0]['app_system'])) { Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]); } diff --git a/Zotlabs/Module/Blocks.php b/Zotlabs/Module/Blocks.php index e0de23fdb..84f769612 100644 --- a/Zotlabs/Module/Blocks.php +++ b/Zotlabs/Module/Blocks.php @@ -107,7 +107,7 @@ class Blocks extends \Zotlabs\Web\Controller { $x['pagetitle'] = $_REQUEST['pagetitle'] ?? ''; $a = ''; - $editor = status_editor($a,$x,false,'Blocks'); + $editor = status_editor($x, false, 'Blocks'); $r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index b6d7ff5a3..892f02d10 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -1087,7 +1087,11 @@ class Cdav extends Controller { $filters['name'] = 'VCALENDAR'; $filters['prop-filters'][0]['name'] = 'VEVENT'; + $filters['prop-filters'][0]['is-not-defined'] = null; + $filters['prop-filters'][0]['param-filters'] = null; + $filters['prop-filters'][0]['text-match'] = null; $filters['comp-filters'][0]['name'] = 'VEVENT'; + $filters['comp-filters'][0]['is-not-defined'] = null; $filters['comp-filters'][0]['time-range']['start'] = $start; $filters['comp-filters'][0]['time-range']['end'] = $end; diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 036663681..e8c3316e9 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -268,7 +268,7 @@ class Channel extends Controller { ]; $a = ''; - $o .= status_editor($a, $x, false, 'Channel'); + $o .= status_editor($x, false, 'Channel'); } // Add pinned content diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 2d36e022a..356071256 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -225,7 +225,7 @@ class Chat extends Controller { $o = ''; - $acl = new AccessList($channel); + $acl = new AccessList($channel ?? []); $channel_acl = $acl->get(); $lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock'); diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index e0f463c76..8a06ab8e0 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -409,7 +409,6 @@ class Connections extends \Zotlabs\Web\Controller { '$approve' => t('Approve'), '$cmd' => App::$cmd, '$contacts' => $contacts, - '$paginate' => paginate($a), '$abook_usage_message' => $abook_usage_message, '$group_label' => t('This is a group/forum channel') ]); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 1a1c09d7c..9e46d7620 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -2,15 +2,13 @@ namespace Zotlabs\Module; use App; +use Zotlabs\Web\Controller; -require_once("include/bbcode.php"); -require_once('include/security.php'); -require_once('include/conversation.php'); -require_once('include/acl_selectors.php'); -require_once('include/items.php'); +class Display extends Controller { + function init() { -class Display extends \Zotlabs\Web\Controller { + } function get($update = 0, $load = false) { @@ -91,7 +89,7 @@ class Display extends \Zotlabs\Web\Controller { $o .= '<div id="jot-popup">'; $a = ''; - $o .= status_editor($a,$x,false,'Display'); + $o .= status_editor($x, false, 'Display'); $o .= '</div>'; } diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php index c031f32a1..1cbb1aee2 100644 --- a/Zotlabs/Module/Editblock.php +++ b/Zotlabs/Module/Editblock.php @@ -132,7 +132,7 @@ class Editblock extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x, false, 'Editblock'); + $editor = status_editor($x, false, 'Editblock'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Block'), diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php index 50096f1a1..1a3f5614c 100644 --- a/Zotlabs/Module/Editlayout.php +++ b/Zotlabs/Module/Editlayout.php @@ -131,7 +131,7 @@ class Editlayout extends \Zotlabs\Web\Controller { 'profile_uid' => intval($owner), ); - $editor = status_editor($a, $x, false, 'Editlayout'); + $editor = status_editor($x, false, 'Editlayout'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Layout'), diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index b21c58af2..5e405bdbc 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -107,7 +107,7 @@ class Editpost extends \Zotlabs\Web\Controller { ); $a = ''; - $editor = status_editor($a, $x, false, 'Editpost'); + $editor = status_editor($x, false, 'Editpost'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php index 785eeb4ec..ab4858d63 100644 --- a/Zotlabs/Module/Editwebpage.php +++ b/Zotlabs/Module/Editwebpage.php @@ -75,7 +75,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { // Figure out which post we're editing $post_id = ((argc() > 2) ? intval(argv(2)) : 0); - + if(! $post_id) { notice( t('Item not found') . EOL); return; @@ -90,7 +90,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { return; } - // We've already figured out which item we want and whose copy we need, + // We've already figured out which item we want and whose copy we need, // so we don't need anything fancy here $sql_extra = item_permissions_sql($owner); @@ -122,13 +122,13 @@ class Editwebpage extends \Zotlabs\Web\Controller { return; } } - + $layout = $itm[0]['layout_mid']; $content = $itm[0]['body']; if($itm[0]['mimetype'] === 'text/markdown') $content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']); - + $rp = 'webpages/' . $which; $x = array( @@ -160,7 +160,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x, false, 'Editwebpage'); + $editor = status_editor($x, false, 'Editwebpage'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Webpage'), diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php index 39a30cb1a..8956ce16f 100644 --- a/Zotlabs/Module/File_upload.php +++ b/Zotlabs/Module/File_upload.php @@ -35,7 +35,7 @@ class File_upload extends \Zotlabs\Web\Controller { $_REQUEST['deny_cid'] = ((isset($_REQUEST['contact_deny'])) ? perms2str($_REQUEST['contact_deny']) : ''); $_REQUEST['deny_gid'] = ((isset($_REQUEST['group_deny'])) ? perms2str($_REQUEST['group_deny']) : ''); - if(isset($_REQUEST['filename']) && $_REQUEST['filename']) { + if(isset($_REQUEST['filename']) && strlen($_REQUEST['filename'])) { $r = attach_mkdir($channel, get_observer_hash(), $_REQUEST); if($r['success']) { $hash = $r['data']['hash']; diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 05b48f119..5c3ae9273 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -85,6 +85,7 @@ class Hq extends \Zotlabs\Web\Controller { $x = [ 'is_owner' => true, + 'profile_uid' => $channel['channel_id'], 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], @@ -104,7 +105,7 @@ class Hq extends \Zotlabs\Web\Controller { ]; $a = ''; - $o .= status_editor($a, $x, true); + $o .= status_editor($x, true, 'Hq'); } diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index b564396c9..25ccb0cbf 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -99,7 +99,7 @@ class Item extends Controller { $sql_extra = item_permissions_sql(0); if (!$i) { - $i = q("select id as item_id, uid from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1", + $i = q("select id as item_id, uid, item_private from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1", dbesc($r[0]['parent_mid']) ); } @@ -120,7 +120,10 @@ class Item extends Controller { $parents_str = ids_to_querystr($i, 'item_id'); - $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $item_normal", + // We won't need to check for privacy mismatches if the verified observer is also owner + $parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : ''); + + $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ", intval($parents_str) ); @@ -134,7 +137,7 @@ class Item extends Controller { as_return_and_die($i ,$chan); } else { - $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $item_normal ORDER BY item.id", + $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id", intval($parents_str) ); diff --git a/Zotlabs/Module/Layouts.php b/Zotlabs/Module/Layouts.php index 949f8e8ec..143e4110b 100644 --- a/Zotlabs/Module/Layouts.php +++ b/Zotlabs/Module/Layouts.php @@ -139,7 +139,7 @@ class Layouts extends \Zotlabs\Web\Controller { $x['pagetitle'] = $_REQUEST['pagetitle'] ?? ''; $a = ''; - $editor = status_editor($a,$x,false,'Layouts'); + $editor = status_editor($x, false, 'Layouts'); $r = q("select iconfig.iid, iconfig.v, mid, title, body, mimetype, created, edited, item_type from iconfig left join item on iconfig.iid = item.id diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index 5779faa19..54daf6471 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -554,7 +554,14 @@ class Like extends Controller { $arr['deny_cid'] = $deny_cid; $arr['deny_gid'] = $deny_gid; $arr['item_private'] = $private; - $arr['created'] = datetime_convert(); + + $created = datetime_convert(); + + $arr['created'] = $created; + $arr['edited'] = $created; + $arr['commented'] = $created; + $arr['received'] = $created; + $arr['changed'] = $created; call_hooks('post_local', $arr); diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index dcc209d1d..4f8e2f4e4 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -214,7 +214,7 @@ class Network extends \Zotlabs\Web\Controller { ); $a = ''; - $status_editor = status_editor($a, $x, false, 'Network'); + $status_editor = status_editor($x, false, 'Network'); $o .= $status_editor; } diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php index 4de4d32d6..e41435ecd 100644 --- a/Zotlabs/Module/Owa.php +++ b/Zotlabs/Module/Owa.php @@ -30,18 +30,32 @@ class Owa extends Controller { $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']); if ($sigblock) { $keyId = $sigblock['keyId']; + $parsed = parse_url($keyId); + if (str_starts_with($parsed['scheme'],'http')) { + unset($parsed['fragment']); + unset($parsed['query']); + $keyId = unparse_url($parsed); + } + else { + $keyId = str_replace('acct:', '', $keyId); + } if ($keyId) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash - WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC", - dbesc(str_replace('acct:', '', $keyId)), + WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') + AND hubloc_deleted = 0 AND xchan_pubkey != '' + ORDER BY hubloc_id DESC", + dbesc($keyId), + dbesc($keyId), dbesc($keyId) ); if (! $r) { $found = discover_by_webbie($keyId); + logger('found = ' . print_r($found, true)); if ($found) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash - WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ", - dbesc(str_replace('acct:', '', $keyId)), + WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ", + dbesc($keyId), + dbesc($keyId), dbesc($keyId) ); } diff --git a/Zotlabs/Module/Pdledit_gui.php b/Zotlabs/Module/Pdledit_gui.php index 45a06c00a..ebb2d558a 100644 --- a/Zotlabs/Module/Pdledit_gui.php +++ b/Zotlabs/Module/Pdledit_gui.php @@ -268,7 +268,8 @@ class Pdledit_gui extends Controller { $checkpaths = [ - 'Zotlabs/Widget/*.php' + 'Zotlabs/Widget/*.php', + 'view/theme/' . lcfirst(App::$theme_info['name']) . '/widget/*.php' ]; $addons = plugins_installed_list(); diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 68f7c55e7..6c73c411e 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -851,6 +851,10 @@ class Photos extends \Zotlabs\Web\Controller { dbesc($datum) ); + $tags = []; + $likebuttons = []; + $comments = ''; + if(! ($ph && $x)) { /* Check again - this time without specifying permissions */ @@ -981,7 +985,6 @@ class Photos extends \Zotlabs\Web\Controller { $r = conv_sort($r,'commented'); } - $tags = array(); if(x($link_item, 'term')) { $cnt = 0; foreach($link_item['term'] as $t) { @@ -1075,7 +1078,6 @@ class Photos extends \Zotlabs\Web\Controller { ]; } - $comments = ''; if(! $r) { if($observer && ($can_post || $can_comment)) { $commentbox = replace_macros($cmnt_tpl,array( @@ -1209,13 +1211,12 @@ class Photos extends \Zotlabs\Web\Controller { } } - $paginate = paginate($a); } $album_e = array($album_link,$ph[0]['album']); $like_e = $like; $dislike_e = $dislike; - + $paginate = paginate(); $response_verbs = array('like'); if(feature_enabled($owner_uid,'dislike')) diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 9d3a4f92b..08de168cb 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -40,7 +40,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false); - $mid = (($_REQUEST['mid']) ? unpack_link_id($_REQUEST['mid']) : ''); + $mid = ((isset($_REQUEST['mid'])) ? unpack_link_id($_REQUEST['mid']) : ''); if ($mid === false) { notice(t('Malformed message id.') . EOL); @@ -91,7 +91,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $o .= '<div id="jot-popup">'; $a = ''; - $o .= status_editor($a,$x,false,'Pubstream'); + $o .= status_editor($x, false, 'Pubstream'); $o .= '</div>'; } @@ -99,9 +99,6 @@ class Pubstream extends \Zotlabs\Web\Controller { nav_set_selected(t('Public Stream')); - if(!$mid) - $_SESSION['static_loadtime'] = datetime_convert(); - $maxheight = get_config('system','home_divmore_height'); if(! $maxheight) $maxheight = 400; diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index f0194fdfd..23324ee3a 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -1,7 +1,9 @@ <?php namespace Zotlabs\Module; /** @file */ +use App; use Zotlabs\Lib\Libzot; +use Zotlabs\Access\AccessList; require_once('include/acl_selectors.php'); require_once('include/crypto.php'); @@ -43,9 +45,9 @@ class Rpost extends \Zotlabs\Web\Controller { // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin // blocks them. - $url = Libzot::get_rpost_path(\App::get_observer()); + $url = Libzot::get_rpost_path(App::get_observer()); // make sure we're not looping to our own hub - if(($url) && (! stristr($url, \App::get_hostname()))) { + if(($url) && (! stristr($url, App::get_hostname()))) { foreach($_GET as $key => $arg) { if($key === 'q') continue; @@ -80,7 +82,10 @@ class Rpost extends \Zotlabs\Web\Controller { 'album' => $def_album, 'directory' => $def_attach, 'flags' => 1, // indicates temporary permissions are created - 'allow_cid' => '<' . $channel['channel_hash'] . '>' + 'allow_cid' => '<' . $channel['channel_hash'] . '>', + 'allow_gid' => '', + 'deny_cid' => '', + 'deny_gid' => '' ]); if (! $r['success']) { @@ -167,9 +172,9 @@ class Rpost extends \Zotlabs\Web\Controller { $_REQUEST['body'] = html2bbcode($_REQUEST['body']); } - $channel = \App::get_channel(); + $channel = App::get_channel(); - $acl = new \Zotlabs\Access\AccessList($channel); + $acl = new AccessList($channel); $channel_acl = $acl->get(); if(isset($_REQUEST['url']) && $_REQUEST['url']) { @@ -201,11 +206,12 @@ class Rpost extends \Zotlabs\Web\Controller { 'bbco_autocomplete' => 'bbcode', 'editor_autocomplete' => true, 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ); $a = ''; - $editor = status_editor($a,$x,false,'Rpost'); + $editor = status_editor($x, false, 'Rpost'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index ea9ae2da1..ee9692014 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -163,7 +163,8 @@ class Display { $title_tosource = get_pconfig(local_channel(),'system','title_tosource'); $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0 - $theme_config = ""; + $theme_config = null; + $schemas = null; if(($themeconfigfile = $this->get_theme_config_file($theme)) != null){ require_once($themeconfigfile); if(class_exists('\\Zotlabs\\Theme\\' . ucfirst($theme) . 'Config')) { @@ -188,7 +189,7 @@ class Display { '$uid' => local_channel(), '$theme' => (($themes) ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false), - '$schema' => array('schema', t('Select scheme'), $existing_schema, '' , $schemas), + '$schema' => (($schemas) ? array('schema', t('Select scheme'), $existing_schema, '' , $schemas) : false), '$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no), '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no), diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index c0db9978e..716f7229b 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -14,47 +14,53 @@ require_once('include/bbcode.php'); class Share extends \Zotlabs\Web\Controller { function init() { - - $post_id = ((argc() > 1) ? intval(argv(1)) : 0); - - if(! $post_id) - killme(); - - if(! local_channel()) { + + if (!intval(argv(1))) { killme(); } - $observer = App::get_observer(); + if (! local_channel()) { + killme(); + } + $observer = App::get_observer(); $channel = App::get_channel(); + $sys_channel = get_sys_channel(); $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1", - intval($post_id) + intval(argv(1)) ); - if(! $r) - killme(); - + if ($r[0]['uid'] === $sys_channel['channel_id']) { + $r = [copy_of_pubitem($channel, $r[0]['mid'])]; + } + + if(! $r) { + killme(); + } + $item_id = $r[0]['id']; - if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss')) + if ($r[0]['item_private']) { killme(); - + } + $sql_extra = item_permissions_sql($r[0]['uid']); - + $r = q("select * from item where id = %d $sql_extra", - intval($post_id) + intval($item_id) ); + if(! $r) killme(); - + /** @FIXME we only share bbcode */ - + if($r[0]['mimetype'] !== 'text/bbcode') killme(); - - xchan_query($r); - + + xchan_query($r,true); + $arr = []; $item = $r[0]; @@ -81,7 +87,7 @@ class Share extends \Zotlabs\Web\Controller { $thread_owner = $r[0]; else killme(); - + $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($item['author_xchan']) ); @@ -89,7 +95,7 @@ class Share extends \Zotlabs\Web\Controller { $item_author = $r[0]; else killme(); - + $arr['aid'] = $owner_aid; $arr['uid'] = $owner_uid; @@ -109,12 +115,12 @@ class Share extends \Zotlabs\Web\Controller { $arr['obj_type'] = $item['obj_type']; $arr['verb'] = ACTIVITY_SHARE; - $post = item_store($arr); + $post = item_store($arr); $post_id = $post['item_id']; $arr['id'] = $post_id; - + call_hooks('post_local_end', $arr); info( t('Post repeated') . EOL); @@ -128,10 +134,10 @@ class Share extends \Zotlabs\Web\Controller { Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]); } - Master::Summon([ 'Notifier','like',$post_id ]); - + Master::Summon([ 'Notifier', 'like', $post_id ]); + killme(); - + } - + } diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php index fdaab4ab8..78adf1859 100644 --- a/Zotlabs/Module/Sse_bs.php +++ b/Zotlabs/Module/Sse_bs.php @@ -7,6 +7,7 @@ use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; use Zotlabs\Lib\Enotify; use Zotlabs\Lib\XConfig; +use Zotlabs\Lib\Cache; class Sse_bs extends Controller { @@ -117,14 +118,29 @@ class Sse_bs extends Controller { function mark_read($arr) { - if(! self::$uid) - return; - $mids = []; $str = ''; + $mids_all_json = Cache::get('sse_mids_all_' . session_id()); + + if (!$mids_all_json) + $mids_all_json = '[]'; + + $mids_all = json_decode($mids_all_json, true); + foreach($arr as $a) { - $mids[] = '\'' . dbesc(unpack_link_id($a)) . '\''; + $mid_str = '\'' . dbesc(unpack_link_id($a)) . '\''; + $mids[] = $mid_str; + + if (!in_array($mid_str, $mids_all)) { + $mids_all[] = $mid_str; + } + } + + Cache::set('sse_mids_all_' . session_id(), json_encode($mids_all)); + + if(! self::$uid) { + return; } $str = implode(',', $mids); @@ -411,8 +427,9 @@ class Sse_bs extends Controller { } } - if(! isset($_SESSION['static_loadtime'])) + if(!isset($_SESSION['static_loadtime'])) { $_SESSION['static_loadtime'] = datetime_convert(); + } $limit = intval(self::$limit); $offset = self::$offset; @@ -430,6 +447,13 @@ class Sse_bs extends Controller { if(self::$xchans) $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") "; + $sql_extra3 = ''; + $sse_mids_all_json = Cache::get('sse_mids_all_' . session_id()); + if ($sse_mids_all_json) { + $sse_mids_all = json_decode($sse_mids_all_json, true); + $sql_extra3 = " AND mid NOT IN (" . protect_sprintf(implode(',', $sse_mids_all)) . ") "; + } + $uids = " AND uid IN ( " . $sys['channel_id'] . " ) "; $site_firehose = get_config('system', 'site_firehose', 0); @@ -452,10 +476,11 @@ class Sse_bs extends Controller { $item_normal $sql_extra $sql_extra2 + $sql_extra3 ORDER BY created DESC LIMIT $limit OFFSET $offset", dbescdate($_SESSION['sse_loadtime']), dbesc(self::$ob_hash), - dbescdate($_SESSION['static_loadtime']) + dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime']) ); if($items) { @@ -478,8 +503,9 @@ class Sse_bs extends Controller { AND created > '%s' $item_normal $sql_extra + $sql_extra3 AND author_xchan != '%s' LIMIT 100", - dbescdate($_SESSION['static_loadtime']), + dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime']), dbesc(self::$ob_hash) ); diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index b58c23b34..ffb0d94ea 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -204,7 +204,7 @@ class Webpages extends Controller { $x['pagetitle'] = 'home'; $a = ''; - $editor = status_editor($a,$x,false,'Webpages'); + $editor = status_editor($x, false, 'Webpages'); $pages = null; diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php index 590c1cd9c..912b4442d 100644 --- a/Zotlabs/Storage/Browser.php +++ b/Zotlabs/Storage/Browser.php @@ -209,7 +209,6 @@ class Browser extends DAV\Browser\Plugin { // upload access. system.thumbnail_security should be set to 1 if you want to include these // types - $is_creator = false; $photo_icon = ''; $preview_style = intval(get_config('system','thumbnail_security',0)); @@ -369,6 +368,7 @@ class Browser extends DAV\Browser\Plugin { '$upload' => t('Add Files'), '$is_owner' => $is_owner, '$is_admin' => is_site_admin(), + '$has_perms' => perm_is_allowed($channel_id, get_observer_hash(), 'write_storage'), '$admin_delete_label' => t('Admin Delete'), '$parentpath' => $parent_path, '$folder_parent' => $folder_parent, diff --git a/Zotlabs/Update/_1259.php b/Zotlabs/Update/_1259.php new file mode 100644 index 000000000..235ca62f9 --- /dev/null +++ b/Zotlabs/Update/_1259.php @@ -0,0 +1,30 @@ +<?php + +namespace Zotlabs\Update; + +class _1259 { + + function run() { + + dbq("START TRANSACTION"); + + + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { + $r = true; + } + + if(ACTIVE_DBTYPE == DBTYPE_MYSQL) { + $r = dbq("ALTER TABLE cache MODIFY COLUMN v MEDIUMTEXT NOT NULL"); + } + + if($r) { + dbq("COMMIT"); + return UPDATE_SUCCESS; + } + + q("ROLLBACK"); + return UPDATE_FAILED; + + } + +} diff --git a/Zotlabs/Web/HTTPSig.php b/Zotlabs/Web/HTTPSig.php index 531b18649..36a00528e 100644 --- a/Zotlabs/Web/HTTPSig.php +++ b/Zotlabs/Web/HTTPSig.php @@ -212,7 +212,8 @@ class HTTPSig { if (in_array('digest', $signed_headers)) { $result['content_signed'] = true; - $digest = explode('=', $headers['digest'], 2); + $digest = explode('=', $headers['digest'], 2); + $digest[0] = strtoupper($digest[0]); if ($digest[0] === 'SHA-256') $hashalg = 'sha256'; if ($digest[0] === 'SHA-512') @@ -324,7 +325,7 @@ class HTTPSig { } // The record wasn't in cache. Fetch it now. - $r = Activity::fetch($id); + $r = Activity::get_actor($id); $signatureAlgorithm = EMPTY_STR; if ($r) { diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php index a6a841ccb..2876fcc3c 100644 --- a/Zotlabs/Web/Router.php +++ b/Zotlabs/Web/Router.php @@ -224,7 +224,7 @@ class Router { } elseif(function_exists(App::$module . '_init')) { $func = App::$module . '_init'; - $func($a); + $func(); } } @@ -257,13 +257,13 @@ class Router { if(function_exists(str_replace('-', '_', $current_theme[0]) . '_init')) { $func = str_replace('-', '_', $current_theme[0]) . '_init'; - $func($a); + $func(); } elseif (x(App::$theme_info, 'extends') && file_exists('view/theme/' . App::$theme_info['extends'] . '/php/theme.php')) { require_once('view/theme/' . App::$theme_info['extends'] . '/php/theme.php'); if(function_exists(str_replace('-', '_', App::$theme_info['extends']) . '_init')) { $func = str_replace('-', '_', App::$theme_info['extends']) . '_init'; - $func($a); + $func(); } } @@ -275,7 +275,7 @@ class Router { } elseif(function_exists(App::$module . '_post')) { $func = App::$module . '_post'; - $func($a); + $func(); } } @@ -289,7 +289,7 @@ class Router { } elseif(function_exists(App::$module . '_content')) { $func = App::$module . '_content'; - $arr = array('content' => $func($a)); + $arr = array('content' => $func()); } } call_hooks(App::$module . '_mod_aftercontent', $arr); diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php index daaf5fb67..a8a00bda6 100644 --- a/Zotlabs/Widget/Activity_filter.php +++ b/Zotlabs/Widget/Activity_filter.php @@ -26,7 +26,7 @@ class Activity_filter { $starred_active = ''; $conv_active = ''; $tabs = []; - $cmd = \App::$cmd; + $cmd = 'network'; //\App::$cmd; if(x($_GET,'dm')) { $dm_active = (($_GET['dm'] == 1) ? 'active' : ''); diff --git a/Zotlabs/Widget/Item.php b/Zotlabs/Widget/Item.php index 9fd703dfe..6f943ffdf 100644 --- a/Zotlabs/Widget/Item.php +++ b/Zotlabs/Widget/Item.php @@ -34,7 +34,7 @@ class Item { if($arr['title']) { $r = q("select item.* from item left join iconfig on item.id = iconfig.iid where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s' - and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1", + and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra $revision limit 1", intval($channel_id), dbesc($arr['title']), intval(ITEM_TYPE_WEBPAGE) diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php index a4e632a9f..b16303be6 100644 --- a/Zotlabs/Widget/Notifications.php +++ b/Zotlabs/Widget/Notifications.php @@ -157,9 +157,11 @@ class Notifications { 'url' => 'pubstream', 'label' => t('Public stream') ], + /* 'markall' => [ 'label' => t('Mark all notifications seen') ], + */ 'filter' => [ 'posts_label' => t('Show new posts only'), 'name_label' => t('Filter by name or address') |