diff options
Diffstat (limited to 'Zotlabs/Lib')
-rw-r--r-- | Zotlabs/Lib/Activity.php | 122 | ||||
-rw-r--r-- | Zotlabs/Lib/ActivityStreams.php | 2 | ||||
-rw-r--r-- | Zotlabs/Lib/Apps.php | 21 | ||||
-rw-r--r-- | Zotlabs/Lib/Cache.php | 14 | ||||
-rw-r--r-- | Zotlabs/Lib/Config.php | 87 | ||||
-rw-r--r-- | Zotlabs/Lib/JSalmon.php | 2 | ||||
-rw-r--r-- | Zotlabs/Lib/Libzot.php | 88 | ||||
-rw-r--r-- | Zotlabs/Lib/Libzotdir.php | 9 | ||||
-rw-r--r-- | Zotlabs/Lib/QueueWorker.php | 8 | ||||
-rw-r--r-- | Zotlabs/Lib/ThreadItem.php | 4 | ||||
-rw-r--r-- | Zotlabs/Lib/Zotfinger.php | 8 |
11 files changed, 232 insertions, 133 deletions
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; } |