diff options
-rw-r--r-- | Zotlabs/Daemon/Cache_query.php | 4 | ||||
-rw-r--r-- | Zotlabs/Daemon/Convo.php | 58 | ||||
-rw-r--r-- | Zotlabs/Daemon/Cron.php | 6 | ||||
-rw-r--r-- | Zotlabs/Daemon/Externals.php | 148 | ||||
-rw-r--r-- | Zotlabs/Daemon/Onepoll.php | 1 | ||||
-rw-r--r-- | Zotlabs/Lib/Activity.php | 428 | ||||
-rw-r--r-- | Zotlabs/Lib/Libsync.php | 529 | ||||
-rw-r--r-- | Zotlabs/Module/Zotfeed.php | 44 | ||||
-rwxr-xr-x | boot.php | 2 | ||||
-rw-r--r-- | include/contact_widgets.php | 2 | ||||
-rwxr-xr-x | include/items.php | 116 | ||||
-rw-r--r-- | include/taxonomy.php | 2 | ||||
-rw-r--r-- | include/text.php | 6 |
13 files changed, 922 insertions, 424 deletions
diff --git a/Zotlabs/Daemon/Cache_query.php b/Zotlabs/Daemon/Cache_query.php index 18d19cdf2..5f92ae6d0 100644 --- a/Zotlabs/Daemon/Cache_query.php +++ b/Zotlabs/Daemon/Cache_query.php @@ -24,8 +24,10 @@ class Cache_query { array_shift($argv); array_shift($argv); + + $arr = json_decode(base64_decode($argv[0]), true); - $r = call_user_func_array('q', $argv); + $r = call_user_func_array('q', $arr); if($r) Cache::set($key, serialize($r)); diff --git a/Zotlabs/Daemon/Convo.php b/Zotlabs/Daemon/Convo.php new file mode 100644 index 000000000..f7478d778 --- /dev/null +++ b/Zotlabs/Daemon/Convo.php @@ -0,0 +1,58 @@ +<?php + +namespace Zotlabs\Daemon; + +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\ASCollection; + +class Convo { + + static public function run($argc, $argv) { + + logger('convo invoked: ' . print_r($argv, true)); + + if ($argc != 4) { + return; + } + + $id = $argv[1]; + $channel_id = intval($argv[2]); + $contact_hash = $argv[3]; + + $channel = channelx_by_n($channel_id); + if (!$channel) { + return; + } + + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1", + intval($channel_id), + dbesc($contact_hash) + ); + if (!$r) { + return; + } + + $contact = array_shift($r); + + $obj = new ASCollection($id, $channel); + + $messages = $obj->get(); + + if ($messages) { + foreach ($messages as $message) { + if (is_string($message)) { + $message = Activity::fetch($message, $channel); + } + // set client flag because comments will probably just be objects and not full blown activities + // and that lets us use implied_create + $AS = new ActivityStreams($message); + if ($AS->is_valid() && is_array($AS->obj)) { + $item = Activity::decode_note($AS, true); + Activity::store($channel, $contact['abook_xchan'], $AS, $item); + } + } + } + } +} diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index cd7a710d3..2c0422ddd 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -201,7 +201,7 @@ class Cron { require_once('include/photo/photo_driver.php'); foreach ($r as $rr) { $photos = import_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash'], false, true); - $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' + q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), @@ -219,8 +219,6 @@ class Cron { if (!$disable_discover_tab) Master::Summon(array('Externals')); - $generation = 0; - $restart = false; if (($argc > 1) && ($argv[1] == 'restart')) { @@ -232,8 +230,6 @@ class Cron { reload_plugins(); - $d = datetime_convert(); - // TODO check to see if there are any cronhooks before wasting a process if (!$restart) diff --git a/Zotlabs/Daemon/Externals.php b/Zotlabs/Daemon/Externals.php index 3d6b0bd7b..064b3f71d 100644 --- a/Zotlabs/Daemon/Externals.php +++ b/Zotlabs/Daemon/Externals.php @@ -2,7 +2,10 @@ namespace Zotlabs\Daemon; -require_once('include/zot.php'); +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\ASCollection; + require_once('include/channel.php'); @@ -10,6 +13,9 @@ class Externals { static public function run($argc, $argv) { + logger('externals: start'); + + $importer = get_sys_channel(); $total = 0; $attempts = 0; @@ -27,12 +33,15 @@ class Externals { else { $randfunc = db_getfunc('RAND'); - // fixme this query does not deal with directory realms. + // fixme this query does not deal with directory realms. - $r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1", + $r = q("select site_url, site_pull from site where site_url != '%s' + and site_flags != %d and site_type = %d + and site_dead = 0 and site_project like '%s' and site_version > '5.3.1' order by $randfunc limit 1", dbesc(z_root()), intval(DIRECTORY_MODE_STANDALONE), - intval(SITE_TYPE_ZOT) + intval(SITE_TYPE_ZOT), + dbesc('hubzilla%') ); if ($r) $url = $r[0]['site_url']; @@ -57,41 +66,116 @@ class Externals { } if ($url) { - if ($r[0]['site_pull'] > NULL_DATE) - $mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day')); - else { - $days = get_config('externals', 'since_days'); - if ($days === false) - $days = 15; - $mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days')); + + $max = intval(get_config('system', 'max_imported_posts', 30)); + if (intval($max)) { + logger('externals: fetching outbox'); + + $feed_url = $url . '/zotfeed'; + $obj = new ASCollection($feed_url, $importer, 0, $max); + $messages = $obj->get(); + + if ($messages) { + foreach ($messages as $message) { + if (is_string($message)) { + $message = Activity::fetch($message, $importer); + } + $AS = new ActivityStreams($message); + if ($AS->is_valid() && is_array($AS->obj)) { + $item = Activity::decode_note($AS); + Activity::store($importer, $importer['xchan_hash'], $AS, $item, true); + $total++; + } + } + } + logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG); } + } + } + return; + + /* $total = 0; + $attempts = 0; + + logger('externals: startup', LOGGER_DEBUG); + + // pull in some public posts + + while ($total == 0 && $attempts < 3) { + $arr = ['url' => '']; + call_hooks('externals_url_select', $arr); - $feedurl = $url . '/zotfeed?f=&mindate=' . $mindate; + if ($arr['url']) { + $url = $arr['url']; + } + else { + $randfunc = db_getfunc('RAND'); + + // fixme this query does not deal with directory realms. + + $r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d and site_dead = 0 order by $randfunc limit 1", + dbesc(z_root()), + intval(DIRECTORY_MODE_STANDALONE), + intval(SITE_TYPE_ZOT) + ); + if ($r) + $url = $r[0]['site_url']; + } + + $blacklisted = false; - logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG); + if (!check_siteallowed($url)) { + logger('blacklisted site: ' . $url); + $blacklisted = true; + } + + $attempts++; - $x = z_fetch_url($feedurl); - if (($x) && ($x['success'])) { + // make sure we can eventually break out if somebody blacklists all known sites - q("update site set site_pull = '%s' where site_url = '%s'", - dbesc(datetime_convert()), - dbesc($url) - ); + if ($blacklisted) { + if ($attempts > 20) + break; + $attempts--; + continue; + } - $j = json_decode($x['body'], true); - if ($j['success'] && $j['messages']) { - $sys = get_sys_channel(); - foreach ($j['messages'] as $message) { - // on these posts, clear any route info. - $message['route'] = ''; - process_delivery(['hash' => 'undefined'], get_item_elements($message), - [['hash' => $sys['xchan_hash']]], false, true); - $total++; + if ($url) { + if ($r[0]['site_pull'] > NULL_DATE) + $mindate = urlencode(datetime_convert('', '', $r[0]['site_pull'] . ' - 1 day')); + else { + $days = get_config('externals', 'since_days'); + if ($days === false) + $days = 15; + $mindate = urlencode(datetime_convert('', '', 'now - ' . intval($days) . ' days')); + } + + $feedurl = $url . '/zotfeed?f=&mindate=' . $mindate; + + logger('externals: pulling public content from ' . $feedurl, LOGGER_DEBUG); + + $x = z_fetch_url($feedurl); + if (($x) && ($x['success'])) { + + q("update site set site_pull = '%s' where site_url = '%s'", + dbesc(datetime_convert()), + dbesc($url) + ); + + $j = json_decode($x['body'], true); + if ($j['success'] && $j['messages']) { + $sys = get_sys_channel(); + foreach ($j['messages'] as $message) { + // on these posts, clear any route info. + $message['route'] = ''; + process_delivery(['hash' => 'undefined'], get_item_elements($message), + [['hash' => $sys['xchan_hash']]], false, true); + $total++; + } + logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG); + } } - logger('externals: import_public_posts: ' . $total . ' messages imported', LOGGER_DEBUG); } - } - } - } + }*/ } } diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php index 388a78c81..568745608 100644 --- a/Zotlabs/Daemon/Onepoll.php +++ b/Zotlabs/Daemon/Onepoll.php @@ -138,7 +138,6 @@ class Onepoll { logger('fetching outbox'); $obj = new ASCollection($url, $importer, 0, $max); $messages = $obj->get(); - hz_syslog(print_r($messages,true)); if ($messages) { foreach ($messages as $message) { if (is_string($message)) { diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index aa121d98b..197409a19 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -267,7 +267,7 @@ class Activity { static function encode_item_collection($items, $id, $type, $total = 0) { - if ($total > 100) { + if ($total > 30) { $ret = [ 'id' => z_root() . '/' . $id, 'type' => $type . 'Page', @@ -300,11 +300,17 @@ class Activity { $x = []; foreach ($items as $i) { $m = get_iconfig($i['id'], 'activitypub', 'rawmsg'); - if (is_string($m)) { - $t = json_decode($m, true); + if ($m) { + if (is_string($m)) + $t = json_decode($m,true); + else + $t = $m; } else { - $t = $m; + $t = self::encode_activity($i); + } + if ($t) { + $x[] = $t; } if ($t) { $x[] = $t; @@ -2481,34 +2487,168 @@ class Activity { } - static function store($channel, $observer_hash, $act, $item, $fetch_parents = true) { + static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false) { $is_sys_channel = is_sys_channel($channel['channel_id']); + $is_child_node = false; + + // TODO: not implemented + // Pleroma scrobbles can be really noisy and contain lots of duplicate activities. Disable them by default. + /*if (($act->type === 'Listen') && ($is_sys_channel || get_pconfig($channel['channel_id'], 'system', 'allow_scrobbles', false))) { + return; + }*/ // Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field. // They are hidden in the public timeline if the public inbox is listed in the 'cc' field. // This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point. $pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false); - $is_parent = (($item['parent_mid'] && $item['parent_mid'] === $item['mid']) ? true : false); - if ($is_parent && (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream))) { + // TODO: this his handled in pubcrawl atm. + // very unpleasant and imperfect way of determining a Mastodon DM + /*if ($act->raw_recips && array_key_exists('to',$act->raw_recips) && is_array($act->raw_recips['to']) && count($act->raw_recips['to']) === 1 && $act->raw_recips['to'][0] === channel_url($channel) && ! $act->raw_recips['cc']) { + $item['item_private'] = 2; + }*/ + + // TODO: remove + // $is_parent = (($item['parent_mid'] && $item['parent_mid'] === $item['mid']) ? true : false); + + if ($item['parent_mid'] && $item['parent_mid'] !== $item['mid']) { + $is_child_node = true; + } + + $allowed = false; + + // TODO: not implemented + // $permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system','permit_all_mentions') && i_am_mentioned($channel,$item)); + + if ($is_child_node) { + $p = q("select * from item where mid = '%s' and uid = %d and item_wall = 1", + dbesc($item['parent_mid']), + intval($channel['channel_id']) + ); + if ($p) { + // check permissions against the author, not the sender + $allowed = perm_is_allowed($channel['channel_id'], $item['author_xchan'], 'post_comments'); + if ((!$allowed)/* && $permit_mentions*/) { + if ($p[0]['owner_xchan'] === $channel['channel_hash']) { + $allowed = false; + } + else { + $allowed = true; + } + } + + // TODO: not implemented + /*if (absolutely_no_comments($p[0])) { + $allowed = false; + }*/ + + if (!$allowed) { + logger('rejected comment from ' . $item['author_xchan'] . ' for ' . $channel['channel_address']); + logger('rejected: ' . print_r($item, true), LOGGER_DATA); + + // TODO: not implemented + // let the sender know we received their comment but we don't permit spam here. + // self::send_rejection_activity($channel,$item['author_xchan'],$item); + return; + } + + // TODO: not implemented + /*if (perm_is_allowed($channel['channel_id'],$item['author_xchan'],'moderated')) { + $item['item_blocked'] = ITEM_MODERATED; + }*/ + } + else { + $allowed = true; + // reject public stream comments that weren't sent by the conversation owner + if ($is_sys_channel && $pubstream && $item['owner_xchan'] !== $observer_hash) { + // TODO: check why? This would make it impossible to fetch externals via zotfeed where $observer_hash = sys channel + // $allowed = false; + } + } + + if ($p && $p[0]['obj_type'] === 'Question') { + if ($item['obj_type'] === 'Note' && $item['title'] && (!$item['content'])) { + $item['obj_type'] = 'Answer'; + } + } + } + else { + // The $item['item_fetched'] flag is set in fetch_and_store_parents(). + // In this case we should check against author permissions because sender is not owner. + if (perm_is_allowed($channel['channel_id'], (($item['item_fetched']) ? $item['author_xchan'] : $observer_hash), 'send_stream') || ($is_sys_channel && $pubstream)) { + $allowed = true; + } + // TODO: not implemented + /*if ($permit_mentions) { + $allowed = true; + }*/ + } + + // TODO: remove + /*if ($is_parent && (!perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') && !($is_sys_channel && $pubstream))) { logger('no permission'); return; + }*/ + + if (tgroup_check($channel['channel_id'], $item) && (!$is_child_node)) { + // for forum deliveries, make sure we keep a copy of the signed original + set_iconfig($item, 'activitypub', 'rawmsg', $act->raw, 1); + $allowed = true; } - if (is_array($act->obj)) { + // TODO: not implemented + /*if (intval($channel['channel_system'])) { + + if (! check_pubstream_channelallowed($observer_hash)) { + $allowed = false; + } + + // don't allow pubstream posts if the sender even has a clone on a pubstream denied site + + $h = q("select hubloc_url from hubloc where hubloc_hash = '%s'", + dbesc($observer_hash) + ); + if ($h) { + foreach ($h as $hub) { + if (! check_pubstream_siteallowed($hub['hubloc_url'])) { + $allowed = false; + break; + } + } + } + }*/ + + // TODO: not implemented + /*$blocked = LibBlock::fetch($channel['channel_id'],BLOCKTYPE_SERVER); + if ($blocked) { + foreach($blocked as $b) { + if (strpos($observer_hash,$b['block_entity']) !== false) { + $allowed = false; + } + } + }*/ + + if (!$allowed && !$force) { + logger('no permission'); + return; + } + + // TODO: remove + /*if (is_array($act->obj)) { $content = self::get_content($act->obj); } if (!$content) { logger('no content'); return; - } + }*/ $item['aid'] = $channel['channel_account_id']; $item['uid'] = $channel['channel_id']; - // Make sure we use the zot6 identity where applicable + // Some authors may be zot6 authors in which case we want to store their nomadic identity + // instead of their ActivityPub identity $item['author_xchan'] = self::find_best_identity($item['author_xchan']); $item['owner_xchan'] = self::find_best_identity($item['owner_xchan']); @@ -2543,18 +2683,35 @@ class Activity { } } - if ($act->obj['conversation']) { set_iconfig($item, 'ostatus', 'conversation', $act->obj['conversation'], 1); } // This isn't perfect but the best we can do for now. - $item['comment_policy'] = 'authenticated'; set_iconfig($item, 'activitypub', 'recips', $act->raw_recips); - if (!$is_parent) { + // TODO: inheritPrivacy should probably be set in encode activity. Zap does not do so yet - check what this is about + if (!(isset($act->data['inheritPrivacy']) && $act->data['inheritPrivacy'])) { + if ($item['item_private']) { + $item['item_restrict'] = $item['item_restrict'] & 1; + if ($is_child_node) { + $item['allow_cid'] = '<' . $channel['channel_hash'] . '>'; + $item['allow_gid'] = $item['deny_cid'] = $item['deny_gid'] = ''; + } + logger('restricted'); + } + } + + if (intval($act->sigok)) { + $item['item_verified'] = 1; + } + + $parent = null; + + // TODO: remove + /*if (!$is_parent) { $p = q("select parent_mid, id, obj_type from item where mid = '%s' and uid = %d limit 1", dbesc($item['parent_mid']), intval($item['uid']) @@ -2586,14 +2743,12 @@ class Activity { } } - if ($p[0]['obj_type'] === 'Question') { if ($item['obj_type'] === ACTIVITY_OBJ_NOTE && $item['title'] && (!$item['content'])) { $item['obj_type'] = 'Answer'; } } - if ($p[0]['parent_mid'] !== $item['parent_mid']) { $item['thr_parent'] = $item['parent_mid']; } @@ -2601,8 +2756,50 @@ class Activity { $item['thr_parent'] = $p[0]['parent_mid']; } $item['parent_mid'] = $p[0]['parent_mid']; + }*/ + + if ($is_child_node) { + + $parent = q("select * from item where mid = '%s' and uid = %d limit 1", + dbesc($item['parent_mid']), + intval($item['uid']) + ); + if (!$parent) { + if (!plugin_is_installed('pubcrawl')) { + return; + } + else { + $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 && $pubstream)) { + $fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item) : false); + } + if ($fetch) { + $parent = q("select * from item where mid = '%s' and uid = %d limit 1", + dbesc($item['parent_mid']), + intval($item['uid']) + ); + } + else { + logger('no parent'); + return; + } + } + } + + if ($parent[0]['parent_mid'] !== $item['parent_mid']) { + $item['thr_parent'] = $item['parent_mid']; + } + else { + $item['thr_parent'] = $parent[0]['parent_mid']; + } + $item['parent_mid'] = $parent[0]['parent_mid']; } + // TODO: not implemented + // self::rewrite_mentions($item); + $r = q("select id, created, edited from item where mid = '%s' and uid = %d limit 1", dbesc($item['mid']), intval($item['uid']) @@ -2620,8 +2817,51 @@ class Activity { $x = item_store($item); } + // TODO: remove + /*$r = q("select id, created, edited from item where mid = '%s' and uid = %d limit 1", + dbesc($item['mid']), + intval($item['uid']) + ); + if ($r) { + if ($item['edited'] > $r[0]['edited']) { + $item['id'] = $r[0]['id']; + $x = item_store_update($item); + } + else { + return; + } + } + else { + $x = item_store($item); + }*/ + + if ($fetch_parents && $parent && !intval($parent[0]['item_private'])) { + logger('topfetch', LOGGER_DEBUG); + // if the thread owner is a connnection, we will already receive any additional comments to their posts + // but if they are not we can try to fetch others in the background + $x = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1", + intval($channel['channel_id']), + dbesc($parent[0]['owner_xchan']) + ); + if (!$x) { + // determine if the top-level post provides a replies collection + if ($parent[0]['obj']) { + $parent[0]['obj'] = json_decode($parent[0]['obj'], true); + } + logger('topfetch: ' . print_r($parent[0], true), LOGGER_ALL); + $id = ((array_path_exists('obj/replies/id', $parent[0])) ? $parent[0]['obj']['replies']['id'] : false); + if (!$id) { + $id = ((array_path_exists('obj/replies', $parent[0]) && is_string($parent[0]['obj']['replies'])) ? $parent[0]['obj']['replies'] : false); + } + if ($id) { + Master::Summon(['Convo', $id, $channel['channel_id'], $observer_hash]); + } + } + } + if (is_array($x) && $x['item_id']) { - if ($is_parent) { + 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 Master::Summon(['Notifier', 'comment-import', $x['item_id']]); @@ -2636,10 +2876,26 @@ class Activity { sync_an_item($channel['channel_id'], $x['item_id']); } - } + // TODO: remove + /*if (is_array($x) && $x['item_id']) { + if ($is_parent) { + if ($item['owner_xchan'] === $channel['channel_hash']) { + // We are the owner of this conversation, so send all received comments back downstream + Master::Summon(['Notifier', 'comment-import', $x['item_id']]); + } + $r = q("select * from item where id = %d limit 1", + intval($x['item_id']) + ); + if ($r) { + send_status_notifications($x['item_id'], $r[0]); + } + } + sync_an_item($channel['channel_id'], $x['item_id']); + }*/ - static public function fetch_and_store_parents($channel, $item) { + } + static public function fetch_and_store_parents($channel, $observer_hash, $item) { logger('fetching parents'); $p = []; @@ -2647,42 +2903,35 @@ class Activity { $current_item = $item; while ($current_item['parent_mid'] !== $current_item['mid']) { - $n = self::fetch($current_item['parent_mid'], $channel); + $n = self::fetch($current_item['parent_mid']); if (!$n) { break; } - $a = new ActivityStreams($n); + // set client flag to convert objects to implied activities + $a = new ActivityStreams($n, null, true); + if ($a->type === 'Announce' && is_array($a->obj) + && array_key_exists('object', $a->obj) && array_key_exists('actor', $a->obj)) { + // This is a relayed/forwarded Activity (as opposed to a shared/boosted object) + // Reparse the encapsulated Activity and use that instead + logger('relayed activity', LOGGER_DEBUG); + $a = new ActivityStreams($a->obj, null, true); + } - //logger($a->debug()); + logger($a->debug(), LOGGER_DATA); if (!$a->is_valid()) { + logger('not a valid activity'); break; } - if (is_array($a->actor) && array_key_exists('id', $a->actor)) { - self::actor_store($a->actor['id'], $a->actor); + Activity::actor_store($a->actor['id'], $a->actor); } - $replies = null; - if (isset($a->obj['replies']['first']['items'])) { - $replies = $a->obj['replies']['first']['items']; - // we already have this one - array_diff($replies, [$current_item['mid']]); - } - - $item = null; - - switch ($a->type) { - case 'Create': - case 'Update': - //case 'Like': - //case 'Dislike': - case 'Announce': - $item = self::decode_note($a); - break; - default: - break; + // ActivityPub sourced items are cacheable + $item = Activity::decode_note($a); + if (!$item) { + break; } $hookinfo = [ @@ -2695,22 +2944,22 @@ class Activity { $item = $hookinfo['item']; if ($item) { + $item['item_fetched'] = 1; + array_unshift($p, [$a, $item]); - array_unshift($p, [$a, $item, $replies]); - - if ($item['parent_mid'] === $item['mid'] || count($p) > 20) { + if ($item['parent_mid'] === $item['mid'] || count($p) > 100) { break; } - } + $current_item = $item; } if ($p) { foreach ($p as $pv) { - self::store($channel, $pv[0]->actor['id'], $pv[0], $pv[1], false); - if ($pv[2]) - self::fetch_and_store_replies($channel, $pv[2]); + if ($pv[0]->is_valid()) { + Activity::store($channel, $observer_hash, $pv[0], $pv[1], false); + } } return true; } @@ -2718,6 +2967,87 @@ class Activity { return false; } + /* + static public function fetch_and_store_parents($channel, $item) { + + logger('fetching parents'); + + $p = []; + + $current_item = $item; + + while ($current_item['parent_mid'] !== $current_item['mid']) { + $n = self::fetch($current_item['parent_mid'], $channel); + if (!$n) { + break; + } + $a = new ActivityStreams($n); + + //logger($a->debug()); + + if (!$a->is_valid()) { + break; + } + + if (is_array($a->actor) && array_key_exists('id', $a->actor)) { + self::actor_store($a->actor['id'], $a->actor); + } + + $replies = null; + if (isset($a->obj['replies']['first']['items'])) { + $replies = $a->obj['replies']['first']['items']; + // we already have this one + array_diff($replies, [$current_item['mid']]); + } + + $item = null; + + switch ($a->type) { + case 'Create': + case 'Update': + //case 'Like': + //case 'Dislike': + case 'Announce': + $item = self::decode_note($a); + break; + default: + break; + + } + + $hookinfo = [ + 'a' => $a, + 'item' => $item + ]; + + call_hooks('fetch_and_store', $hookinfo); + + $item = $hookinfo['item']; + + if ($item) { + + array_unshift($p, [$a, $item, $replies]); + + if ($item['parent_mid'] === $item['mid'] || count($p) > 20) { + break; + } + + } + $current_item = $item; + } + + if ($p) { + foreach ($p as $pv) { + self::store($channel, $pv[0]->actor['id'], $pv[0], $pv[1], false); + if ($pv[2]) + self::fetch_and_store_replies($channel, $pv[2]); + } + return true; + } + + return false; + } + */ static public function fetch_and_store_replies($channel, $arr) { logger('fetching replies'); diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php index 7b968532a..e16b68cf8 100644 --- a/Zotlabs/Lib/Libsync.php +++ b/Zotlabs/Lib/Libsync.php @@ -2,9 +2,9 @@ namespace Zotlabs\Lib; -use Zotlabs\Lib\Libzot; -use Zotlabs\Lib\Queue; +use App; +use Zotlabs\Daemon\Master; class Libsync { @@ -23,21 +23,21 @@ class Libsync { logger('build_sync_packet'); - $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false); - if($keychange) { + $keychange = (($packet && array_key_exists('keychange', $packet)) ? true : false); + if ($keychange) { logger('keychange sync'); } - if(! $uid) + if (!$uid) $uid = local_channel(); - if(! $uid) + if (!$uid) return; $r = q("select * from channel where channel_id = %d limit 1", intval($uid) ); - if(! $r) + if (!$r) return; $channel = $r[0]; @@ -49,103 +49,103 @@ class Libsync { unset($channel['channel_salt']); - if(intval($channel['channel_removed'])) + if (intval($channel['channel_removed'])) return; $h = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash = '%s' and hubloc_deleted = 0", dbesc(($keychange) ? $packet['keychange']['old_hash'] : $channel['channel_hash']) ); - if(! $h) + if (!$h) return; - $synchubs = array(); + $synchubs = []; - foreach($h as $x) { - if($x['hubloc_host'] == \App::get_hostname()) + foreach ($h as $x) { + if ($x['hubloc_host'] == App::get_hostname()) continue; $y = q("select site_dead from site where site_url = '%s' limit 1", dbesc($x['hubloc_url']) ); - if((! $y) || ($y[0]['site_dead'] == 0)) + if ((!$y) || ($y[0]['site_dead'] == 0)) $synchubs[] = $x; } - if(! $synchubs) + if (!$synchubs) return; - $env_recips = [ $channel['channel_hash'] ]; + $env_recips = [$channel['channel_hash']]; - if($packet) - logger('packet: ' . print_r($packet, true),LOGGER_DATA, LOG_DEBUG); + if ($packet) + logger('packet: ' . print_r($packet, true), LOGGER_DATA, LOG_DEBUG); - $info = (($packet) ? $packet : array()); - $info['type'] = 'sync'; + $info = (($packet) ? $packet : []); + $info['type'] = 'sync'; $info['encoding'] = 'hz'; // note: not zot, this packet is very platform specific - $info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ]; + $info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root()]; - if(array_key_exists($uid,\App::$config) && array_key_exists('transient',\App::$config[$uid])) { - $settings = \App::$config[$uid]['transient']; - if($settings) { + if (array_key_exists($uid, App::$config) && array_key_exists('transient', App::$config[$uid])) { + $settings = App::$config[$uid]['transient']; + if ($settings) { $info['config'] = $settings; } } - if($channel) { - $info['channel'] = array(); - foreach($channel as $k => $v) { + if ($channel) { + $info['channel'] = []; + foreach ($channel as $k => $v) { // filter out any joined tables like xchan - if(strpos($k,'channel_') !== 0) + if (strpos($k, 'channel_') !== 0) continue; // don't pass these elements, they should not be synchronised $disallowed = [ - 'channel_id','channel_account_id','channel_primary','channel_address', - 'channel_deleted','channel_removed','channel_system' + 'channel_id', 'channel_account_id', 'channel_primary', 'channel_address', + 'channel_deleted', 'channel_removed', 'channel_system' ]; - if(! $keychange) { + if (!$keychange) { $disallowed[] = 'channel_prvkey'; } - if(in_array($k,$disallowed)) + if (in_array($k, $disallowed)) continue; $info['channel'][$k] = $v; } } - if($groups_changed) { + if ($groups_changed) { $r = q("select hash as collection, visible, deleted, gname as name from pgrp where uid = %d", intval($uid) ); - if($r) + if ($r) $info['collections'] = $r; $r = q("select pgrp.hash as collection, pgrp_member.xchan as member from pgrp left join pgrp_member on pgrp.id = pgrp_member.gid where pgrp_member.uid = %d", intval($uid) ); - if($r) + if ($r) $info['collection_members'] = $r; } - $interval = ((get_config('system','delivery_interval') !== false) - ? intval(get_config('system','delivery_interval')) : 2 ); + $interval = ((get_config('system', 'delivery_interval') !== false) + ? intval(get_config('system', 'delivery_interval')) : 2); - logger('Packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); + logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG); $total = count($synchubs); - foreach($synchubs as $hub) { + foreach ($synchubs as $hub) { $hash = random_string(); - $n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'hz',$hub['hubloc_sitekey'],$hub['site_crypto']); - Queue::insert(array( + $n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']); + Queue::insert([ 'hash' => $hash, 'account_id' => $channel['channel_account_id'], 'channel_id' => $channel['channel_id'], @@ -153,29 +153,29 @@ class Libsync { 'driver' => $hub['hubloc_network'], 'notify' => $n, 'msg' => EMPTY_STR - )); + ]); $x = q("select count(outq_hash) as total from outq where outq_delivered = 0"); - if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000))) { + if (intval($x[0]['total']) > intval(get_config('system', 'force_queue_threshold', 3000))) { logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO); Queue::update($hash); continue; } - \Zotlabs\Daemon\Master::Summon(array('Deliver', $hash)); + Master::Summon(['Deliver', $hash]); $total = $total - 1; - if($interval && $total) - @time_sleep_until(microtime(true) + (float) $interval); + if ($interval && $total) + @time_sleep_until(microtime(true) + (float)$interval); } } /** * @brief * - * @param array $sender + * @param string $sender * @param array $arr * @param array $deliveries * @return array @@ -187,16 +187,16 @@ class Libsync { $result = []; - $keychange = ((array_key_exists('keychange',$arr)) ? true : false); + $keychange = ((array_key_exists('keychange', $arr)) ? true : false); foreach ($deliveries as $d) { $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($sender) ); - $DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,'sync'); + $DR = new DReport(z_root(), $sender, $d, 'sync'); - if (! $r) { + if (!$r) { $DR->update('recipient not found'); $result[] = $DR->get(); continue; @@ -206,153 +206,152 @@ class Libsync { $DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>'); - $max_friends = service_class_fetch($channel['channel_id'],'total_channels'); - $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds'); + $max_friends = service_class_fetch($channel['channel_id'], 'total_channels'); + $max_feeds = account_service_class_fetch($channel['channel_account_id'], 'total_feeds'); - if($channel['channel_hash'] != $sender) { + if ($channel['channel_hash'] != $sender) { logger('Possible forgery. Sender ' . $sender . ' is not ' . $channel['channel_hash']); $DR->update('channel mismatch'); $result[] = $DR->get(); continue; } - if($keychange) { - self::keychange($channel,$arr); + if ($keychange) { + self::keychange($channel, $arr); continue; } // if the clone is active, so are we - if(substr($channel['channel_active'],0,10) !== substr(datetime_convert(),0,10)) { + if (substr($channel['channel_active'], 0, 10) !== substr(datetime_convert(), 0, 10)) { q("UPDATE channel set channel_active = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($channel['channel_id']) ); } - if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) { - foreach($arr['config'] as $cat => $k) { - foreach($arr['config'][$cat] as $k => $v) - set_pconfig($channel['channel_id'],$cat,$k,$v); + if (array_key_exists('config', $arr) && is_array($arr['config']) && count($arr['config'])) { + foreach ($arr['config'] as $cat => $k) { + foreach ($arr['config'][$cat] as $k => $v) + set_pconfig($channel['channel_id'], $cat, $k, $v); } } - if(array_key_exists('obj',$arr) && $arr['obj']) - sync_objs($channel,$arr['obj']); + if (array_key_exists('obj', $arr) && $arr['obj']) + sync_objs($channel, $arr['obj']); - if(array_key_exists('likes',$arr) && $arr['likes']) - import_likes($channel,$arr['likes']); + if (array_key_exists('likes', $arr) && $arr['likes']) + import_likes($channel, $arr['likes']); - if(array_key_exists('app',$arr) && $arr['app']) - sync_apps($channel,$arr['app']); + if (array_key_exists('app', $arr) && $arr['app']) + sync_apps($channel, $arr['app']); - if(array_key_exists('addressbook',$arr) && $arr['addressbook']) - sync_addressbook($channel,$arr['addressbook']); + if (array_key_exists('addressbook', $arr) && $arr['addressbook']) + sync_addressbook($channel, $arr['addressbook']); - if(array_key_exists('calendar',$arr) && $arr['calendar']) - sync_calendar($channel,$arr['calendar']); + if (array_key_exists('calendar', $arr) && $arr['calendar']) + sync_calendar($channel, $arr['calendar']); - if(array_key_exists('chatroom',$arr) && $arr['chatroom']) - sync_chatrooms($channel,$arr['chatroom']); + if (array_key_exists('chatroom', $arr) && $arr['chatroom']) + sync_chatrooms($channel, $arr['chatroom']); - if(array_key_exists('conv',$arr) && $arr['conv']) - import_conv($channel,$arr['conv']); + if (array_key_exists('conv', $arr) && $arr['conv']) + import_conv($channel, $arr['conv']); - if(array_key_exists('mail',$arr) && $arr['mail']) - sync_mail($channel,$arr['mail']); + if (array_key_exists('mail', $arr) && $arr['mail']) + sync_mail($channel, $arr['mail']); - if(array_key_exists('event',$arr) && $arr['event']) - sync_events($channel,$arr['event']); + if (array_key_exists('event', $arr) && $arr['event']) + sync_events($channel, $arr['event']); - if(array_key_exists('event_item',$arr) && $arr['event_item']) - sync_items($channel,$arr['event_item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null)); + if (array_key_exists('event_item', $arr) && $arr['event_item']) + sync_items($channel, $arr['event_item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null)); - if(array_key_exists('item',$arr) && $arr['item']) - sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null)); + if (array_key_exists('item', $arr) && $arr['item']) + sync_items($channel, $arr['item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null)); // deprecated, maintaining for a few months for upward compatibility // this should sync webpages, but the logic is a bit subtle - if(array_key_exists('item_id',$arr) && $arr['item_id']) - sync_items($channel,$arr['item_id']); + if (array_key_exists('item_id', $arr) && $arr['item_id']) + sync_items($channel, $arr['item_id']); - if(array_key_exists('menu',$arr) && $arr['menu']) - sync_menus($channel,$arr['menu']); + if (array_key_exists('menu', $arr) && $arr['menu']) + sync_menus($channel, $arr['menu']); - if(array_key_exists('file',$arr) && $arr['file']) - sync_files($channel,$arr['file']); + if (array_key_exists('file', $arr) && $arr['file']) + sync_files($channel, $arr['file']); - if(array_key_exists('wiki',$arr) && $arr['wiki']) - sync_items($channel,$arr['wiki'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null)); + if (array_key_exists('wiki', $arr) && $arr['wiki']) + sync_items($channel, $arr['wiki'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null)); - if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) { + if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) { - $remote_channel = $arr['channel']; + $remote_channel = $arr['channel']; $remote_channel['channel_id'] = $channel['channel_id']; - if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) { + if (array_key_exists('channel_pageflags', $arr['channel']) && intval($arr['channel']['channel_pageflags'])) { // Several pageflags are site-specific and cannot be sync'd. // Only allow those bits which are shareable from the remote and then // logically OR with the local flags - $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] & (PAGE_HIDDEN|PAGE_AUTOCONNECT|PAGE_APPLICATION|PAGE_PREMIUM|PAGE_ADULT); + $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] & (PAGE_HIDDEN | PAGE_AUTOCONNECT | PAGE_APPLICATION | PAGE_PREMIUM | PAGE_ADULT); $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] | $channel['channel_pageflags']; } $disallowed = [ - 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey', - 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', - 'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook', - 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall', - 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall', - 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish', + 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey', + 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', + 'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook', + 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall', + 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall', + 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish', 'channel_a_delegate' ]; - $clean = array(); - foreach($arr['channel'] as $k => $v) { - if(in_array($k,$disallowed)) + $clean = []; + foreach ($arr['channel'] as $k => $v) { + if (in_array($k, $disallowed)) continue; $clean[$k] = $v; } - if(count($clean)) { - foreach($clean as $k => $v) { - $r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) - . "' where channel_id = " . intval($channel['channel_id']) ); + if (count($clean)) { + foreach ($clean as $k => $v) { + dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id'])); } } } - if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) { + if (array_key_exists('abook', $arr) && is_array($arr['abook']) && count($arr['abook'])) { $total_friends = 0; - $total_feeds = 0; + $total_feeds = 0; $r = q("select abook_id, abook_feed from abook where abook_channel = %d", intval($channel['channel_id']) ); - if($r) { + if ($r) { // don't count yourself $total_friends = ((count($r) > 0) ? count($r) - 1 : 0); - foreach($r as $rr) - if(intval($rr['abook_feed'])) - $total_feeds ++; + foreach ($r as $rr) + if (intval($rr['abook_feed'])) + $total_feeds++; } - $disallowed = array('abook_id','abook_account','abook_channel','abook_rating','abook_rating_text','abook_not_here'); + $disallowed = ['abook_id', 'abook_account', 'abook_channel', 'abook_rating', 'abook_rating_text', 'abook_not_here']; $fields = db_columns('abook'); - foreach($arr['abook'] as $abook) { + foreach ($arr['abook'] as $abook) { $abconfig = null; - if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) + if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) $abconfig = $abook['abconfig']; - if(! array_key_exists('abook_blocked',$abook)) { + if (!array_key_exists('abook_blocked', $abook)) { // convert from redmatrix $abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001) ? 1 : 0); $abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002) ? 1 : 0); @@ -364,20 +363,20 @@ class Libsync { $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100) ? 1 : 0); } - $clean = array(); - if($abook['abook_xchan'] && $abook['entry_deleted']) { + $clean = []; + if ($abook['abook_xchan'] && $abook['entry_deleted']) { logger('Removing abook entry for ' . $abook['abook_xchan']); $r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($abook['abook_xchan']), intval($channel['channel_id']) ); - if($r) { - contact_remove($channel['channel_id'],$r[0]['abook_id']); - if($total_friends) - $total_friends --; - if(intval($r[0]['abook_feed'])) - $total_feeds --; + if ($r) { + contact_remove($channel['channel_id'], $r[0]['abook_id']); + if ($total_friends) + $total_friends--; + if (intval($r[0]['abook_feed'])) + $total_feeds--; } continue; } @@ -386,31 +385,31 @@ class Libsync { // This relies on the undocumented behaviour that red sites send xchan info with the abook // and import_author_xchan will look them up on all federated networks - if($abook['abook_xchan'] && $abook['xchan_addr']) { + if ($abook['abook_xchan'] && $abook['xchan_addr']) { $h = Libzot::get_hublocs($abook['abook_xchan']); - if(! $h) { + if (!$h) { $xhash = import_author_xchan(encode_item_xchan($abook)); - if(! $xhash) { + if (!$xhash) { logger('Import of ' . $abook['xchan_addr'] . ' failed.'); continue; } } } - foreach($abook as $k => $v) { - if(in_array($k,$disallowed) || (strpos($k,'abook') !== 0)) { + foreach ($abook as $k => $v) { + if (in_array($k, $disallowed) || (strpos($k, 'abook') !== 0)) { continue; } - if(! in_array($k,$fields)) { + if (!in_array($k, $fields)) { continue; } $clean[$k] = $v; } - if(! array_key_exists('abook_xchan',$clean)) + if (!array_key_exists('abook_xchan', $clean)) continue; - if(array_key_exists('abook_instance',$clean) && $clean['abook_instance'] && strpos($clean['abook_instance'],z_root()) === false) { + if (array_key_exists('abook_instance', $clean) && $clean['abook_instance'] && strpos($clean['abook_instance'], z_root()) === false) { $clean['abook_not_here'] = 1; } @@ -422,12 +421,12 @@ class Libsync { // make sure we have an abook entry for this xchan on this system - if(! $r) { - if($max_friends !== false && $total_friends > $max_friends) { + if (!$r) { + if ($max_friends !== false && $total_friends > $max_friends) { logger('total_channels service class limit exceeded'); continue; } - if($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) { + if ($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) { logger('total_feeds service class limit exceeded'); continue; } @@ -438,18 +437,16 @@ class Libsync { 'abook_channel' => $channel['channel_id'] ] ); - $total_friends ++; - if(intval($clean['abook_feed'])) - $total_feeds ++; + $total_friends++; + if (intval($clean['abook_feed'])) + $total_feeds++; } - if(count($clean)) { - foreach($clean as $k => $v) { - if($k == 'abook_dob') + if (count($clean)) { + foreach ($clean as $k => $v) { + if ($k == 'abook_dob') $v = dbescdate($v); - - $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) - . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); + dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); } } @@ -459,10 +456,10 @@ class Libsync { // translate_abook_perms_inbound($channel,$abook); - if($abconfig) { + if ($abconfig) { /// @fixme does not handle sync of del_abconfig - foreach($abconfig as $abc) { - set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); + foreach ($abconfig as $abc) { + set_abconfig($channel['channel_id'], $abc['xchan'], $abc['cat'], $abc['k'], $abc['v']); } } } @@ -470,21 +467,21 @@ class Libsync { // sync collections (privacy groups) oh joy... - if(array_key_exists('collections',$arr) && is_array($arr['collections']) && count($arr['collections'])) { + if (array_key_exists('collections', $arr) && is_array($arr['collections']) && count($arr['collections'])) { $x = q("select * from pgrp where uid = %d", intval($channel['channel_id']) ); - foreach($arr['collections'] as $cl) { + foreach ($arr['collections'] as $cl) { $found = false; - if($x) { - foreach($x as $y) { - if($cl['collection'] == $y['hash']) { + if ($x) { + foreach ($x as $y) { + if ($cl['collection'] == $y['hash']) { $found = true; break; } } - if($found) { - if(($y['gname'] != $cl['name']) + if ($found) { + if (($y['gname'] != $cl['name']) || ($y['visible'] != $cl['visible']) || ($y['deleted'] != $cl['deleted'])) { q("update pgrp set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d", @@ -495,15 +492,15 @@ class Libsync { intval($channel['channel_id']) ); } - if(intval($cl['deleted']) && (! intval($y['deleted']))) { + if (intval($cl['deleted']) && (!intval($y['deleted']))) { q("delete from pgrp_member where gid = %d", intval($y['id']) ); } } } - if(! $found) { - $r = q("INSERT INTO pgrp ( hash, uid, visible, deleted, gname ) + if (!$found) { + q("INSERT INTO pgrp ( hash, uid, visible, deleted, gname ) VALUES( '%s', %d, %d, %d, '%s' ) ", dbesc($cl['collection']), intval($channel['channel_id']), @@ -517,16 +514,16 @@ class Libsync { // They need to be removed by marking deleted and removing the members. // This shouldn't happen except for clones created before this function was written. - if($x) { + if ($x) { $found_local = false; - foreach($x as $y) { - foreach($arr['collections'] as $cl) { - if($cl['collection'] == $y['hash']) { + foreach ($x as $y) { + foreach ($arr['collections'] as $cl) { + if ($cl['collection'] == $y['hash']) { $found_local = true; break; } } - if(! $found_local) { + if (!$found_local) { q("delete from pgrp_member where gid = %d", intval($y['id']) ); @@ -546,38 +543,38 @@ class Libsync { // now sync the members - if(array_key_exists('collection_members', $arr) + if (array_key_exists('collection_members', $arr) && is_array($arr['collection_members']) && count($arr['collection_members'])) { // first sort into groups keyed by the group hash - $members = array(); - foreach($arr['collection_members'] as $cm) { - if(! array_key_exists($cm['collection'],$members)) - $members[$cm['collection']] = array(); + $members = []; + foreach ($arr['collection_members'] as $cm) { + if (!array_key_exists($cm['collection'], $members)) + $members[$cm['collection']] = []; $members[$cm['collection']][] = $cm['member']; } // our group list is already synchronised - if($x) { - foreach($x as $y) { + if ($x) { + foreach ($x as $y) { // for each group, loop on members list we just received - if(isset($y['hash']) && isset($members[$y['hash']])) { - foreach($members[$y['hash']] as $member) { + if (isset($y['hash']) && isset($members[$y['hash']])) { + foreach ($members[$y['hash']] as $member) { $found = false; - $z = q("select xchan from pgrp_member where gid = %d and uid = %d and xchan = '%s' limit 1", + $z = q("select xchan from pgrp_member where gid = %d and uid = %d and xchan = '%s' limit 1", intval($y['id']), intval($channel['channel_id']), dbesc($member) ); - if($z) + if ($z) $found = true; // if somebody is in the group that wasn't before - add them - if(! $found) { + if (!$found) { q("INSERT INTO pgrp_member (uid, gid, xchan) VALUES( %d, %d, '%s' ) ", intval($channel['channel_id']), @@ -593,10 +590,10 @@ class Libsync { intval($y['id']), intval($channel['channel_id']) ); - if($m) { - foreach($m as $mm) { + if ($m) { + foreach ($m as $mm) { // if the local existing member isn't in the list we just received - remove them - if(! in_array($mm['xchan'],$members[$y['hash']])) { + if (!in_array($mm['xchan'], $members[$y['hash']])) { q("delete from pgrp_member where xchan = '%s' and gid = %d and uid = %d", dbesc($mm['xchan']), intval($y['id']), @@ -610,17 +607,17 @@ class Libsync { } } - if(array_key_exists('profile',$arr) && is_array($arr['profile']) && count($arr['profile'])) { + if (array_key_exists('profile', $arr) && is_array($arr['profile']) && count($arr['profile'])) { - $disallowed = array('id','aid','uid','guid'); + $disallowed = ['id', 'aid', 'uid', 'guid']; - foreach($arr['profile'] as $profile) { + foreach ($arr['profile'] as $profile) { $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", dbesc($profile['profile_guid']), intval($channel['channel_id']) ); - if(! $x) { + if (!$x) { profile_store_lowlevel( [ 'aid' => $channel['channel_account_id'], @@ -633,24 +630,24 @@ class Libsync { dbesc($profile['profile_guid']), intval($channel['channel_id']) ); - if(! $x) + if (!$x) continue; } - $clean = array(); - foreach($profile as $k => $v) { - if(in_array($k,$disallowed)) + $clean = []; + foreach ($profile as $k => $v) { + if (in_array($k, $disallowed)) continue; - if($profile['is_default'] && in_array($k,['photo','thumb'])) + if ($profile['is_default'] && in_array($k, ['photo', 'thumb'])) continue; - if($k === 'name') + if ($k === 'name') $clean['fullname'] = $v; - elseif($k === 'with') + elseif ($k === 'with') $clean['partner'] = $v; - elseif($k === 'work') + elseif ($k === 'work') $clean['employment'] = $v; - elseif(array_key_exists($k,$x[0])) + elseif (array_key_exists($k, $x[0])) $clean[$k] = $v; /** @@ -658,7 +655,7 @@ class Libsync { * We also need to import local photos if a custom photo is selected */ - if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) { + if ((strpos($profile['thumb'], '/photo/profile/l/') !== false) || intval($profile['is_default'])) { $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; } @@ -668,11 +665,11 @@ class Libsync { } } - if(count($clean)) { - foreach($clean as $k => $v) { - $r = dbq("UPDATE profile set " . TQUOT . dbesc($k) . TQUOT . " = '" . dbesc($v) - . "' where profile_guid = '" . dbesc($profile['profile_guid']) - . "' and uid = " . intval($channel['channel_id'])); + if (count($clean)) { + foreach ($clean as $k => $v) { + dbq("UPDATE profile set " . TQUOT . dbesc($k) . TQUOT . " = '" . dbesc($v) + . "' where profile_guid = '" . dbesc($profile['profile_guid']) + . "' and uid = " . intval($channel['channel_id'])); } } } @@ -687,7 +684,7 @@ class Libsync { */ call_hooks('process_channel_sync_delivery', $addon); - $DR = new \Zotlabs\Lib\DReport(z_root(),$d,$d,'sync','channel sync delivered'); + $DR = new DReport(z_root(), $d, $d, 'sync', 'channel sync delivered'); $DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>'); @@ -708,12 +705,12 @@ class Libsync { static function sync_locations($sender, $arr, $absolute = false) { - $ret = array(); + $ret = []; - if($arr['locations']) { + if ($arr['locations']) { - if($absolute) - Libzot::check_location_move($sender['hash'],$arr['locations']); + if ($absolute) + Libzot::check_location_move($sender['hash'], $arr['locations']); $xisting = q("select * from hubloc where hubloc_hash = '%s'", dbesc($sender['hash']) @@ -722,8 +719,8 @@ class Libsync { // See if a primary is specified $has_primary = false; - foreach($arr['locations'] as $location) { - if($location['primary']) { + foreach ($arr['locations'] as $location) { + if ($location['primary']) { $has_primary = true; break; } @@ -731,32 +728,32 @@ class Libsync { // Ensure that they have one primary hub - if(! $has_primary) + if (!$has_primary) $arr['locations'][0]['primary'] = true; - foreach($arr['locations'] as $location) { - if(! Libzot::verify($location['url'],$location['url_sig'],$sender['public_key'])) { + foreach ($arr['locations'] as $location) { + if (!Libzot::verify($location['url'], $location['url_sig'], $sender['public_key'])) { logger('Unable to verify site signature for ' . $location['url']); - $ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL; + $ret['message'] .= sprintf(t('Unable to verify site signature for %s'), $location['url']) . EOL; continue; } - for($x = 0; $x < count($xisting); $x ++) { - if(($xisting[$x]['hubloc_url'] === $location['url']) + for ($x = 0; $x < count($xisting); $x++) { + if (($xisting[$x]['hubloc_url'] === $location['url']) && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) { $xisting[$x]['updated'] = true; } } - if(! $location['sitekey']) { - logger('Empty hubloc sitekey. ' . print_r($location,true)); + if (!$location['sitekey']) { + logger('Empty hubloc sitekey. ' . print_r($location, true)); continue; } // Catch some malformed entries from the past which still exist - if(strpos($location['address'],'/') !== false) - $location['address'] = substr($location['address'],0,strpos($location['address'],'/')); + if (strpos($location['address'], '/') !== false) + $location['address'] = substr($location['address'], 0, strpos($location['address'], '/')); // match as many fields as possible in case anything at all changed. @@ -773,7 +770,7 @@ class Libsync { dbesc($location['callback']), dbesc($location['sitekey']) ); - if($r) { + if ($r) { logger('Hub exists: ' . $location['url'], LOGGER_DEBUG); // update connection timestamp if this is the site we're talking to @@ -781,9 +778,9 @@ class Libsync { $current_site = false; - $t = datetime_convert('UTC','UTC','now - 15 minutes'); + $t = datetime_convert('UTC', 'UTC', 'now - 15 minutes'); - if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) { + if (array_key_exists('site', $arr) && $location['url'] == $arr['site']['url']) { q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_connected < '%s'", dbesc(datetime_convert()), dbesc(datetime_convert()), @@ -793,11 +790,11 @@ class Libsync { $current_site = true; } - if($current_site && intval($r[0]['hubloc_error'])) { + if ($current_site && intval($r[0]['hubloc_error'])) { q("update hubloc set hubloc_error = 0 where hubloc_id = %d", intval($r[0]['hubloc_id']) ); - if(intval($r[0]['hubloc_orphancheck'])) { + if (intval($r[0]['hubloc_orphancheck'])) { q("update hubloc set hubloc_orphancheck = 0 where hubloc_id = %d", intval($r[0]['hubloc_id']) ); @@ -808,60 +805,60 @@ class Libsync { } // Remove pure duplicates - if(count($r) > 1) { - for($h = 1; $h < count($r); $h ++) { + if (count($r) > 1) { + for ($h = 1; $h < count($r); $h++) { q("delete from hubloc where hubloc_id = %d", intval($r[$h]['hubloc_id']) ); - $what .= 'duplicate_hubloc_removed '; + $what .= 'duplicate_hubloc_removed '; $changed = true; } } - if(intval($r[0]['hubloc_primary']) && (! $location['primary'])) { - $m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'", + if (intval($r[0]['hubloc_primary']) && (!$location['primary'])) { + q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'", dbesc(datetime_convert()), dbesc($r[0]['hubloc_id_url']) ); $r[0]['hubloc_primary'] = intval($location['primary']); hubloc_change_primary($r[0]); - $what .= 'primary_hub '; + $what .= 'primary_hub '; $changed = true; } - elseif((! intval($r[0]['hubloc_primary'])) && ($location['primary'])) { - $m = q("update hubloc set hubloc_primary = 1, hubloc_updated = '%s' where hubloc_id = %d", + elseif ((!intval($r[0]['hubloc_primary'])) && ($location['primary'])) { + q("update hubloc set hubloc_primary = 1, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($r[0]['hubloc_id']) ); // make sure hubloc_change_primary() has current data $r[0]['hubloc_primary'] = intval($location['primary']); hubloc_change_primary($r[0]); - $what .= 'primary_hub '; + $what .= 'primary_hub '; $changed = true; } - elseif($absolute) { + elseif ($absolute) { // Absolute sync - make sure the current primary is correctly reflected in the xchan $pr = hubloc_change_primary($r[0]); - if($pr) { - $what .= 'xchan_primary '; + if ($pr) { + $what .= 'xchan_primary '; $changed = true; } } - if(intval($r[0]['hubloc_deleted']) && (! intval($location['deleted']))) { - $n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'", + if (intval($r[0]['hubloc_deleted']) && (!intval($location['deleted']))) { + q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'", dbesc(datetime_convert()), dbesc($r[0]['hubloc_id_url']) ); - $what .= 'undelete_hub '; + $what .= 'undelete_hub '; $changed = true; } - elseif((! intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) { + elseif ((!intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) { logger('deleting hubloc: ' . $r[0]['hubloc_addr']); - $n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'", + q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'", dbesc(datetime_convert()), dbesc($r[0]['hubloc_id_url']) ); - $what .= 'delete_hub '; + $what .= 'delete_hub '; $changed = true; } continue; @@ -870,8 +867,8 @@ class Libsync { // Existing hubs are dealt with. Now let's process any new ones. // New hub claiming to be primary. Make it so by removing any existing primaries. - if(intval($location['primary'])) { - $r = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_hash = '%s' and hubloc_primary = 1", + if (intval($location['primary'])) { + q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_hash = '%s' and hubloc_primary = 1", dbesc(datetime_convert()), dbesc($sender['hash']) ); @@ -879,7 +876,7 @@ class Libsync { logger('New hub: ' . $location['url']); - $r = hubloc_store_lowlevel( + hubloc_store_lowlevel( [ 'hubloc_guid' => $sender['id'], 'hubloc_guid_sig' => $sender['id_sig'], @@ -890,7 +887,7 @@ class Libsync { 'hubloc_primary' => intval($location['primary']), 'hubloc_url' => $location['url'], 'hubloc_url_sig' => $location['url_sig'], - 'hubloc_site_id' => Libzot::make_xchan_hash($location['url'],$location['sitekey']), + 'hubloc_site_id' => Libzot::make_xchan_hash($location['url'], $location['sitekey']), 'hubloc_host' => $location['host'], 'hubloc_callback' => $location['callback'], 'hubloc_sitekey' => $location['sitekey'], @@ -899,15 +896,15 @@ class Libsync { ] ); - $what .= 'newhub '; + $what .= 'newhub '; $changed = true; - if($location['primary']) { + if ($location['primary']) { $r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_sitekey = '%s'", dbesc($location['address']), dbesc($location['sitekey']) ); - if($r) { + if ($r) { $r = Libzot::zot_record_preferred($r); hubloc_change_primary($r); } @@ -916,15 +913,15 @@ class Libsync { // get rid of any hubs we have for this channel which weren't reported. - if($absolute && $xisting) { - foreach($xisting as $x) { - if(! array_key_exists('updated',$x)) { + if ($absolute && $xisting) { + foreach ($xisting as $x) { + if (!array_key_exists('updated', $x)) { logger('Deleting unreferenced hub location ' . $x['hubloc_addr']); - $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'", + q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'", dbesc(datetime_convert()), dbesc($x['hubloc_id_url']) ); - $what .= 'removed_hub '; + $what .= 'removed_hub '; $changed = true; } } @@ -935,22 +932,22 @@ class Libsync { } $ret['change_message'] = $what; - $ret['changed'] = $changed; + $ret['changed'] = $changed; return $ret; } - static function keychange($channel,$arr) { + static function keychange($channel, $arr) { // verify the keychange operation - if(! Libzot::verify($arr['channel']['channel_pubkey'],$arr['keychange']['new_sig'],$channel['channel_prvkey'])) { + if (!Libzot::verify($arr['channel']['channel_pubkey'], $arr['keychange']['new_sig'], $channel['channel_prvkey'])) { logger('sync keychange: verification failed'); return; } - $sig = Libzot::sign($channel['channel_guid'],$arr['channel']['channel_prvkey']); - $hash = Libzot::make_xchan_hash($channel['channel_guid'],$arr['channel']['channel_pubkey']); + $sig = Libzot::sign($channel['channel_guid'], $arr['channel']['channel_prvkey']); + $hash = Libzot::make_xchan_hash($channel['channel_guid'], $arr['channel']['channel_pubkey']); $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', @@ -961,16 +958,16 @@ class Libsync { dbesc($hash), intval($channel['channel_id']) ); - if(! $r) { + if (!$r) { logger('keychange sync: channel update failed'); return; - } + } $r = q("select * from channel where channel_id = %d", intval($channel['channel_id']) ); - if(! $r) { + if (!$r) { logger('keychange sync: channel retrieve failed'); return; } @@ -982,11 +979,11 @@ class Libsync { dbesc(z_root()) ); - if($h) { - foreach($h as $hv) { + if ($h) { + foreach ($h as $hv) { $hv['hubloc_guid_sig'] = $sig; $hv['hubloc_hash'] = $hash; - $hv['hubloc_url_sig'] = Libzot::sign(z_root(),$channel['channel_prvkey']); + $hv['hubloc_url_sig'] = Libzot::sign(z_root(), $channel['channel_prvkey']); hubloc_store_lowlevel($hv); } } @@ -999,12 +996,12 @@ class Libsync { dbesc($hash) ); - if(($x) && (! $check)) { + if (($x) && (!$check)) { $oldxchan = $x[0]; - foreach($x as $xv) { - $xv['xchan_guid_sig'] = $sig; - $xv['xchan_hash'] = $hash; - $xv['xchan_pubkey'] = $channel['channel_pubkey']; + foreach ($x as $xv) { + $xv['xchan_guid_sig'] = $sig; + $xv['xchan_hash'] = $hash; + $xv['xchan_pubkey'] = $channel['channel_pubkey']; xchan_store_lowlevel($xv); $newxchan = $xv; } @@ -1014,14 +1011,14 @@ class Libsync { dbesc($arr['keychange']['old_hash']) ); - if($a) { + if ($a) { q("update abook set abook_xchan = '%s' where abook_id = %d", dbesc($hash), intval($a[0]['abook_id']) ); } - xchan_change_key($oldxchan,$newxchan,$arr['keychange']); + xchan_change_key($oldxchan, $newxchan, $arr['keychange']); } diff --git a/Zotlabs/Module/Zotfeed.php b/Zotlabs/Module/Zotfeed.php index 6f4cd9fc4..17b0e3057 100644 --- a/Zotlabs/Module/Zotfeed.php +++ b/Zotlabs/Module/Zotfeed.php @@ -19,19 +19,11 @@ class Zotfeed extends Controller { killme(); } - if (argc() < 2) { - killme(); - } - - $channel = channelx_by_nick(argv(1)); + $channel = ((argv(1)) ? channelx_by_nick(argv(1)) : get_sys_channel()); if (!$channel) { killme(); } - if (intval($channel['channel_system'])) { - killme(); - } - $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR); if ($sigdata['portable_id'] && $sigdata['header_valid']) { $portable_id = $sigdata['portable_id']; @@ -60,10 +52,32 @@ class Zotfeed extends Controller { $params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : ''); $params['compat'] = 1; + if (intval($channel['channel_system'])) { + $total = zot_feed($channel['channel_id'], $observer_hash, ['total' => true]); + + if ($total) { + App::set_pager_total($total); + App::set_pager_itemspage(30); + } + + if (App::$pager['unset'] && $total > 30) { + $ret = Activity::paged_collection_init($total, App::$query_string); + + } + else { + $items = zot_feed($channel['channel_id'], $observer_hash, []); + $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total); + } + + as_return_and_die($ret, $channel); + + return; + } + $total = items_fetch( [ 'total' => true, - 'wall' => '1', + 'wall' => 1, 'datequery' => $params['end'], 'datequery2' => $params['begin'], 'direction' => dbesc($params['direction']), @@ -77,16 +91,17 @@ class Zotfeed extends Controller { if ($total) { App::set_pager_total($total); - App::set_pager_itemspage(100); + App::set_pager_itemspage(30); } - if (App::$pager['unset'] && $total > 100) { + if (App::$pager['unset'] && $total > 30) { $ret = Activity::paged_collection_init($total, App::$query_string); } else { + $items = items_fetch( [ - 'wall' => '1', + 'wall' => 1, 'datequery' => $params['end'], 'datequery2' => $params['begin'], 'records' => intval(App::$pager['itemspage']), @@ -99,8 +114,7 @@ class Zotfeed extends Controller { 'compat' => $params['compat'] ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module ); - - $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total); + $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total); } as_return_and_die($ret, $channel); @@ -50,7 +50,7 @@ require_once('include/attach.php'); require_once('include/bbcode.php'); define ( 'PLATFORM_NAME', 'hubzilla' ); -define ( 'STD_VERSION', '5.3.1' ); +define ( 'STD_VERSION', '5.3.2' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1240 ); diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 0719d4011..a5f867b0f 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -97,7 +97,7 @@ function categories_widget($baseurl,$selected = '') { dbesc(ACTIVITY_UPDATE) ]; - \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, $arr ]); + \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, base64_encode(json_encode($arr)) ]); } $r = unserialize($content); diff --git a/include/items.php b/include/items.php index 5b9bbd1f9..7229b66eb 100755 --- a/include/items.php +++ b/include/items.php @@ -4318,54 +4318,54 @@ function fetch_post_tags($items, $link = false) { */ function zot_feed($uid, $observer_hash, $arr) { - $result = array(); - $mindate = null; + $result = []; + $mindate = null; $message_id = null; - $wall = true; + $wall = true; require_once('include/security.php'); - if(array_key_exists('mindate',$arr)) { - $mindate = datetime_convert('UTC','UTC',$arr['mindate']); + if (array_key_exists('mindate', $arr)) { + $mindate = datetime_convert('UTC', 'UTC', $arr['mindate']); } - if(array_key_exists('message_id',$arr)) { + if (array_key_exists('message_id', $arr)) { $message_id = $arr['message_id']; } - if(array_key_exists('wall',$arr)) { + if (array_key_exists('wall', $arr)) { $wall = intval($arr['wall']); } - if(! $mindate) + if (!$mindate) $mindate = NULL_DATE; $mindate = dbesc($mindate); logger('zot_feed: requested for uid ' . $uid . ' from observer ' . $observer_hash, LOGGER_DEBUG); - if($message_id) - logger('message_id: ' . $message_id,LOGGER_DEBUG); + if ($message_id) + logger('message_id: ' . $message_id, LOGGER_DEBUG); - if(! perm_is_allowed($uid,$observer_hash,'view_stream')) { + if (!perm_is_allowed($uid, $observer_hash, 'view_stream')) { logger('zot_feed: permission denied.'); return $result; } - if(! is_sys_channel($uid)) - $sql_extra = item_permissions_sql($uid,$observer_hash); + if (!is_sys_channel($uid)) + $sql_extra = item_permissions_sql($uid, $observer_hash); $limit = " LIMIT 5000 "; - if($mindate > NULL_DATE) { + if ($mindate > NULL_DATE) { $sql_extra .= " and ( created > '$mindate' or changed > '$mindate' ) "; } - if($message_id) { + if ($message_id) { $sql_extra .= " and mid = '" . dbesc($message_id) . "' "; - $limit = ''; + $limit = ''; } - if($wall) { + if ($wall) { $sql_extra .= " and item_wall = 1 "; } @@ -4374,18 +4374,39 @@ function zot_feed($uid, $observer_hash, $arr) { $item_normal = item_normal(); - if(is_sys_channel($uid)) { + if (is_sys_channel($uid)) { + $nonsys_uids = q("SELECT channel_id FROM channel WHERE channel_system = 0"); + $nonsys_uids_str = ids_to_querystr($nonsys_uids, 'channel_id'); - $nonsys_uids = q("SELECT channel_id FROM channel WHERE channel_system = 0"); - $nonsys_uids_str = ids_to_querystr($nonsys_uids,'channel_id'); + if ($arr['total']) { + $items = q("SELECT count(created) AS total FROM item + WHERE uid IN ( %s ) + AND item_private = 0 + $sql_extra $item_normal", + dbesc($nonsys_uids_str) + ); + if ($items) { + return intval($items[0]['total']); + } + return 0; + } - $r = q("SELECT parent, postopts FROM item + $itemspage = (($uid) ? get_pconfig($uid, 'system', 'itemspage') : 30); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 30)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); + + $items = q("SELECT item.*, item.id AS item_id FROM item WHERE uid IN ( %s ) AND item_private = 0 - $item_normal - $sql_extra ORDER BY created ASC $limit", - intval($nonsys_uids_str) + $item_normal $sql_extra + ORDER BY item.created DESC $pager_sql", + dbesc($nonsys_uids_str) ); + + xchan_query($items); + $items = fetch_post_tags($items, true); + + return $items; } else { $r = q("SELECT parent, postopts FROM item @@ -4398,20 +4419,19 @@ function zot_feed($uid, $observer_hash, $arr) { $parents = []; - if($r) { - foreach($r as $rv) { - if(array_key_exists($rv['parent'],$parents)) + if ($r) { + foreach ($r as $rv) { + if (array_key_exists($rv['parent'], $parents)) continue; - if(strpos($rv['postopts'],'nodeliver') !== false) + if (strpos($rv['postopts'], 'nodeliver') !== false) continue; $parents[$rv['parent']] = $rv; - if(count($parents) > 200) + if (count($parents) > 200) break; } - $parents_str = ids_to_querystr($parents,'parent'); - $sys_query = ((is_sys_channel($uid)) ? $sql_extra : ''); - $item_normal = item_normal(); + $parents_str = ids_to_querystr($parents, 'parent'); + $sys_query = ((is_sys_channel($uid)) ? $sql_extra : ''); $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal $sys_query ", @@ -4419,25 +4439,24 @@ function zot_feed($uid, $observer_hash, $arr) { ); } - if($items) { + if ($items) { xchan_query($items); $items = fetch_post_tags($items); require_once('include/conversation.php'); - $items = conv_sort($items,'ascending'); + $items = conv_sort($items, 'ascending'); } else - $items = array(); + $items = []; - logger('zot_feed: number items: ' . count($items),LOGGER_DEBUG); + logger('zot_feed: number items: ' . count($items), LOGGER_DEBUG); - foreach($items as $item) + foreach ($items as $item) $result[] = encode_item($item); return $result; } - function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = CLIENT_MODE_NORMAL,$module = 'network') { $result = array('success' => false); @@ -4563,8 +4582,8 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $pager_sql = ''; } else { if(! $arr['total']) { - $itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20); - App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 10); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); } } @@ -4602,7 +4621,6 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C require_once('include/security.php'); $sql_extra .= item_permissions_sql($channel['channel_id'],$observer_hash); - if($arr['pages']) $item_restrict = " AND item_type = " . ITEM_TYPE_WEBPAGE . " "; else @@ -4616,7 +4634,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C // "New Item View" - show all items unthreaded in reverse created date order if ($arr['total']) { - $items = q("SELECT count(item.id) AS total FROM item + $items = dbq("SELECT count(item.id) AS total FROM item WHERE $item_uids $item_restrict $simple_update $sql_extra $sql_nets $sql_extra3" @@ -4627,11 +4645,11 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C return 0; } - $items = q("SELECT item.*, item.id AS item_id FROM item - WHERE $item_uids $item_restrict - $simple_update - $sql_extra $sql_nets $sql_extra3 - ORDER BY item.received DESC $pager_sql" + $items = dbq("SELECT item.*, item.id AS item_id FROM item + WHERE $item_uids $item_restrict + $simple_update + $sql_extra $sql_nets $sql_extra3 + ORDER BY item.received DESC $pager_sql" ); require_once('include/items.php'); @@ -4652,7 +4670,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C // Fetch a page full of parent items for this page - $r = q("SELECT distinct item.id AS item_id, item.$ordering FROM item + $r = dbq("SELECT distinct item.id AS item_id, item.$ordering FROM item left join abook on item.author_xchan = abook.abook_xchan WHERE $item_uids $item_restrict AND item.parent = item.id @@ -4663,7 +4681,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C } else { // update - $r = q("SELECT item.parent AS item_id FROM item + $r = dbq("SELECT item.parent AS item_id FROM item left join abook on item.author_xchan = abook.abook_xchan WHERE $item_uids $item_restrict $simple_update and (abook.abook_blocked = 0 or abook.abook_flags is null) diff --git a/include/taxonomy.php b/include/taxonomy.php index 5681db88c..88d0a9196 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -374,7 +374,7 @@ function pub_tagadelic($net,$site,$limit,$recent,$safemode,$type) { (intval($count) ? "LIMIT $count" : '') ]; - \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, $arr ]); + \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, base64_encode(json_encode($arr)) ]); } $r = unserialize($content); diff --git a/include/text.php b/include/text.php index d6b196f1e..1e08d136c 100644 --- a/include/text.php +++ b/include/text.php @@ -7,7 +7,7 @@ use Zotlabs\Lib as Zlib; use Michelf\MarkdownExtra; use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\Exception\UnsatisfiedDependencyException; +use Ramsey\Uuid\Exception\UnableToBuildUuidException; use Zotlabs\Lib\SvgSanitizer; @@ -3824,7 +3824,7 @@ function new_uuid() { try { $hash = Uuid::uuid4()->toString(); - } catch (UnsatisfiedDependencyException $e) { + } catch (UnableToBuildUuidException $e) { $hash = random_string(48); } @@ -3842,7 +3842,7 @@ function uuid_from_url($url) { try { $hash = Uuid::uuid5(Uuid::NAMESPACE_URL, $url)->toString(); - } catch (UnsatisfiedDependencyException $e) { + } catch (UnableToBuildUuidException $e) { $hash = md5($url); } return $hash; |