diff --git a/README.md b/README.md index 2f000cc58..7a1f81a47 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,32 @@ ZAP Zap is an open source decentralised social network with more privacy and less drama. + +===== + +The Zot Manifesto + +You have the right to a permanent internet identity which is not associated with what server you are currently using and cannot be taken away from you by anybody, ever. + +You have the right to refuse/reject or possibly moderate comments on your posts by anybody you don't know. + +You also have the right to not allow them to comment on your posts in the first place, until such time as they have earned your trust. + +You have the right to show your photos and videos to anybody you desire and also NOT show them to anybody you desire. + +If your software does not implement these rights, you have the right to fix it or replace it. + +===== + +The Earth Manifesto + +The earth is your mother. She gave you life. Respect her or she will take it away. + +Silence is complicity. Speak. + +Those who are leading us to destruction can be stopped. + +7.5 billion people cannot be stopped. + +===== + diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 4b59c6ce6..9523521ec 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -87,19 +87,21 @@ class Notifier { static public $channel = null; static public $private = false; - static public function run($argc,$argv){ + static public function run($argc,$argv) { - if($argc < 3) + if ($argc < 3) { return; + } - logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG); + logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG, LOG_INFO); $cmd = $argv[1]; $item_id = $argv[2]; - if(! $item_id) + if (! $item_id) { return; + } self::$deliveries = []; self::$recipients = []; @@ -112,42 +114,15 @@ class Notifier { $sys = get_sys_channel(); - $mail = false; $top_level = false; $url_recipients = array(); $normal_mode = true; - - if($cmd === 'mail' || $cmd === 'single_mail') { - $normal_mode = false; - $mail = true; - self::$private = true; - $message = q("SELECT * FROM mail WHERE id = %d LIMIT 1", - intval($item_id) - ); - if(! $message) { - return; - } - xchan_mail_query($message[0]); - - self::$recipients[] = $message[0]['to_xchan']; - $item = $message[0]; - - self::$encoded_item = encode_mail($item); - - $s = q("select * from channel where channel_id = %d limit 1", - intval($item['channel_id']) - ); - if($s) - self::$channel = $s[0]; - self::$packet_type = 'mail'; - self::$encoding = 'zot'; - } - elseif($cmd === 'request') { + if ($cmd === 'request') { $xchan = $argv[3]; - if($argc < 5) { + if ($argc < 5) { return; } @@ -160,13 +135,13 @@ class Notifier { self::$encoding = 'zot'; $normal_mode = false; } - elseif($cmd === 'keychange') { + elseif ($cmd === 'keychange') { self::$channel = channelx_by_n($item_id); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id) ); - if($r) { - foreach($r as $rr) { + if ($r) { + foreach ($r as $rr) { self::$recipients[] = $rr['abook_xchan']; } } @@ -176,7 +151,7 @@ class Notifier { self::$encoding = 'zot'; $normal_mode = false; } - elseif(in_array($cmd, [ 'permissions_update', 'permissions_reject', 'permissions_accept', 'permissions_create' ])) { + elseif (in_array($cmd, [ 'permissions_update', 'permissions_reject', 'permissions_accept', 'permissions_create' ])) { // Get the (single) recipient @@ -184,61 +159,61 @@ class Notifier { intval($item_id) ); - if($r) { - $uid = $r[0]['abook_channel']; + if ($r) { + $recip = array_shift($r); + $uid = $recip['abook_channel']; // Get the sender self::$channel = channelx_by_n($uid); - if(self::$channel) { + if (self::$channel) { - $perm_update = array('sender' => self::$channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => ''); + $perm_update = [ 'sender' => self::$channel, 'recipient' => $recip, 'success' => false, 'deliveries' => '' ]; - switch($cmd) { + switch ($cmd) { case 'permissions_create': ActivityPub::permissions_create($perm_update); break; case 'permissions_accept': - ActivityPub::permissions_accept($perm_update); break; default: break; } - if(! $perm_update['success']) { + if (! $perm_update['success']) { call_hooks($cmd,$perm_update); } - if($perm_update['success']) { - if($perm_update['deliveries']) { + if ($perm_update['success']) { + if ($perm_update['deliveries']) { self::$deliveries[] = $perm_update['deliveries']; do_delivery(self::$deliveries); } return; } else { - self::$recipients[] = $r[0]['abook_xchan']; + self::$recipients[] = $recip['abook_xchan']; self::$private = false; self::$packet_type = 'refresh'; - self::$env_recips = [ $r[0]['xchan_hash'] ]; + self::$env_recips = [ $$recip['xchan_hash'] ]; } } } } - elseif($cmd === 'refresh_all') { + elseif ($cmd === 'refresh_all') { logger('notifier: refresh_all: ' . $item_id); self::$channel = channelx_by_n($item_id); $r = q("select abook_xchan from abook where abook_channel = %d", intval($item_id) ); - if($r) { - foreach($r as $rr) { + if ($r) { + foreach ($r as $rr) { self::$recipients[] = $rr['abook_xchan']; } } self::$private = false; self::$packet_type = 'refresh'; } - elseif($cmd === 'purge') { + elseif ($cmd === 'purge') { $xchan = $argv[3]; logger('notifier: purge: ' . $item_id . ' => ' . $xchan); if (! $xchan) { @@ -250,7 +225,7 @@ class Notifier { self::$private = true; self::$packet_type = 'purge'; } - elseif($cmd === 'purge_all') { + elseif ($cmd === 'purge_all') { logger('notifier: purge_all: ' . $item_id); self::$channel = channelx_by_n($item_id); @@ -278,57 +253,52 @@ class Notifier { intval($item_id) ); - if(! $r) + if (! $r) { return; + } xchan_query($r); - $r = fetch_post_tags($r); - $target_item = $r[0]; + $target_item = array_shift($r); $deleted_item = false; - if(intval($target_item['item_deleted'])) { + if (intval($target_item['item_deleted'])) { logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG); $deleted_item = true; } - if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST, ITEM_TYPE_MAIL ] )) { + if (! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) { logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG); return; } // Check for non published items, but allow an exclusion for transmitting hidden file activities - if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) || + if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) || intval($target_item['item_blocked']) || ( intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) { logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG); return; } - if(strpos($target_item['postopts'],'nodeliver') !== false) { - logger('notifier: target item is undeliverable', LOGGER_DEBUG); - return; - } - $s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", intval($target_item['uid']) ); - if($s) - self::$channel = $s[0]; + if ($s) { + self::$channel = array_shift($s); + } - if(self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) { + if (self::$channel['channel_hash'] !== $target_item['author_xchan'] && self::$channel['channel_hash'] !== $target_item['owner_xchan']) { logger("notifier: Sending channel is not owner {$target_item['owner_xchan']} or author {$target_item['author_xchan']}", LOGGER_NORMAL, LOG_WARNING); return; } $thread_is_public = false; - if($target_item['mid'] === $target_item['parent_mid']) { + if ($target_item['mid'] === $target_item['parent_mid']) { $parent_item = $target_item; $top_level_post = true; - } else { @@ -337,26 +307,28 @@ class Notifier { intval($target_item['parent']) ); - if(! $r) + if (! $r) { return; + } xchan_query($r); $r = fetch_post_tags($r); - $parent_item = $r[0]; + $parent_item = array_shift($r); $top_level_post = false; $thread_is_public = 1 - intval($parent_item['item_private']) ; } // avoid looping of discover items 12/4/2014 - if($sys && $parent_item['uid'] == $sys['channel_id']) + if ($sys && $parent_item['uid'] == $sys['channel_id']) { return; - + } $m = get_iconfig($target_item,'activitypub','signed_data'); - if($m) + if ($m) { self::$encoded_item = json_decode($m,true); + } else { self::$encoded_item = array_merge(['@context' => [ ACTIVITYSTREAMS_JSONLD_REV, @@ -365,13 +337,8 @@ class Notifier { ]], Activity::encode_activity($target_item) ); } - logger('target_item: ' . print_r($target_item,true)); - -// self::$encoded_item = encode_item($target_item); - - logger('encoded: ' . print_r(self::$encoded_item,true)); // Send comments to the owner to re-deliver to everybody in the conversation @@ -385,8 +352,6 @@ class Notifier { $relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item) && $cmd !== 'hyper') ? true : false); - - $uplink = false; // $cmd === 'relay' indicates the owner is sending it to the original recipients @@ -397,13 +362,13 @@ class Notifier { // tag_deliver'd post which needs to be sent back to the original author - if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) { + if (($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) { logger('notifier: uplink'); $uplink = true; self::$packet_type = 'response'; } - if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) { + if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) { logger('followup relay (upstream delivery)', LOGGER_DEBUG); $sendto = ($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']; self::$recipients = [ $sendto ]; @@ -419,7 +384,7 @@ class Notifier { } else { - if($cmd === 'relay') { + if ($cmd === 'relay') { logger('owner relay (downstream delivery)'); } else { @@ -429,29 +394,28 @@ class Notifier { // if our parent is a tag_delivery recipient, uplink to the original author causing // a delivery fork. - if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) { + if (($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) { // don't uplink a relayed post to the relay owner - if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) { + if ($parent_item['source_xchan'] !== $parent_item['owner_xchan']) { logger('notifier: uplinking this item'); Master::Summon(array('Notifier','uplink',$item_id)); } } - if($thread_is_public && $cmd === 'hyper') { - $rcps = []; + if ($thread_is_public && $cmd === 'hyper') { + self::$recipients = []; $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 and not abook_xchan in ( '%s', '%s', '%s' ) ", intval($target_item['uid']), dbesc($target_item['author_xchan']), dbesc($target_item['owner_xchan']), dbesc($target_item['source_xchan']) ); - if($r) { - foreach($r as $rv) { - $rcps[] = $rv['abook_xchan']; + if ($r) { + foreach ($r as $rv) { + self::$recipients[] = $rv['abook_xchan']; } } self::$private = false; - self::$recipients = $rcps; } else { self::$private = false; @@ -465,11 +429,9 @@ class Notifier { self::$recipients = array_diff(self::$recipients, [ $target_item['owner_xchan'] ]); } - // don't send deletions onward for other people's stuff - // TODO verify this is needed - copied logic from same place in old code - if(intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) { + if (intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) { logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE); return; } @@ -482,26 +444,26 @@ class Notifier { logger('encoded item: ' . print_r(self::$encoded_item,true), LOGGER_DATA, LOG_DEBUG); stringify_array_elms(self::$recipients); - if(! self::$recipients) { + if (! self::$recipients) { logger('no recipients'); return; } // logger('recipients: ' . print_r(self::$recipients,true), LOGGER_NORMAL, LOG_DEBUG); - if(! count(self::$env_recips)) + if (! count(self::$env_recips)) { self::$env_recips = ((self::$private) ? [] : null); + } - $details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")"); + $recip_list = []; + $details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan + where xchan_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ")"); - $recip_list = array(); - - if($details) { - foreach($details as $d) { - + if ($details) { + foreach ($details as $d) { $recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')'; - if(self::$private) { + if (self::$private) { self::$env_recips[] = $d['xchan_hash']; } } @@ -521,7 +483,6 @@ class Notifier { 'relay_to_owner' => $relay_to_owner, 'uplink' => $uplink, 'cmd' => $cmd, - 'mail' => $mail, 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false), 'request' => $request, 'normal_mode' => $normal_mode, @@ -529,12 +490,11 @@ class Notifier { 'queued' => [] ]; - - call_hooks('notifier_process', $narr); - if($narr['queued']) { - foreach($narr['queued'] as $pq) + if ($narr['queued']) { + foreach ($narr['queued'] as $pq) { self::$deliveries[] = $pq; + } } // notifier_process can alter the recipient list @@ -542,7 +502,7 @@ class Notifier { self::$recipients = $narr['recipients']; self::$env_recips = $narr['env_recips']; - if((self::$private) && (! self::$env_recips)) { + if ((self::$private) && (! self::$env_recips)) { // shouldn't happen logger('private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE); return; @@ -550,22 +510,19 @@ class Notifier { logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG); - - // Now we have collected recipients (except for external mentions, FIXME) + // Now we have collected recipients (except for external mentions, @FIXME) // Let's reduce this to a set of hubs; checking that the site is not dead. - $r = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ") + $hubs = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url + where hubloc_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ") and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) " ); - - if(! $r) { + if (! $hubs) { logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE); return; } - $hubs = $r; - /** * Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, * since it may have been a re-install which has not yet been detected and pruned. @@ -579,12 +536,12 @@ class Notifier { $urls = []; // array of urls to check uniqueness of hubs from other networks $hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all - foreach($hubs as $hub) { + foreach ($hubs as $hub) { - if(self::$env_recips) { - foreach(self::$env_recips as $er) { - if($hub['hubloc_hash'] === $er) { - if(! array_key_exists($hub['hubloc_site_id'], $hub_env)) { + if (self::$env_recips) { + foreach (self::$env_recips as $er) { + if ($hub['hubloc_hash'] === $er) { + if (! array_key_exists($hub['hubloc_site_id'], $hub_env)) { $hub_env[$hub['hubloc_site_id']] = []; } $hub_env[$hub['hubloc_site_id']][] = $er; @@ -593,15 +550,15 @@ class Notifier { } - if($hub['hubloc_network'] === 'zot6') { - if(! in_array($hub['hubloc_sitekey'],$keys)) { + if ($hub['hubloc_network'] === 'zot6') { + if (! in_array($hub['hubloc_sitekey'],$keys)) { $hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network']; $dhubs[] = $hub; $keys[] = $hub['hubloc_sitekey']; } } else { - if(! in_array($hub['hubloc_url'],$urls)) { + if (! in_array($hub['hubloc_url'],$urls)) { $hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network']; $dhubs[] = $hub; $urls[] = $hub['hubloc_url']; @@ -611,11 +568,13 @@ class Notifier { logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG); - foreach($dhubs as $hub) { + foreach ($dhubs as $hub) { + + logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG, LOG_DEBUG); - logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG); + // deliver to any non-zot networks - if($hub['hubloc_network'] !== 'zot6') { + if ($hub['hubloc_network'] !== 'zot6') { $narr = [ 'channel' => self::$channel, 'upstream' => $upstream, @@ -630,7 +589,6 @@ class Notifier { 'relay_to_owner' => $relay_to_owner, 'uplink' => $uplink, 'cmd' => $cmd, - 'mail' => $mail, 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false), 'request' => $request, 'normal_mode' => $normal_mode, @@ -638,7 +596,6 @@ class Notifier { 'queued' => [] ]; - ActivityPub::notifier_process($narr); call_hooks('notifier_hub',$narr); @@ -660,20 +617,21 @@ class Notifier { // Note: Legacy Hubzilla and Osada code. In Zap this should never happen. - if($cmd === 'single_mail' || $cmd === 'single_activity') { + if ($cmd === 'single_mail' || $cmd === 'single_activity') { continue; } // default: zot protocol - $hash = new_uuid(); + $hash = new_uuid(); $env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : ''); - if((self::$private) && (! $env)) { + if ((self::$private) && (! $env)) { continue; } - $packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding, ((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']); + $packet = Libzot::build_packet(self::$channel, self::$packet_type, $env, self::$encoded_item, self::$encoding, + ((self::$private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto']); Queue::insert( [ @@ -687,8 +645,9 @@ class Notifier { ); // only create delivery reports for normal undeleted items - if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) { - q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ", + if (is_array($target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) { + q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue ) + values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ", dbesc($target_item['mid']), dbesc($hub['hubloc_host']), dbesc($hub['hubloc_host']), @@ -703,17 +662,17 @@ class Notifier { self::$deliveries[] = $hash; } - if($normal_mode) { + if ($normal_mode) { + // This wastes a process if there are no delivery hooks configured, so check this before launching the new process $x = q("select * from hook where hook = 'notifier_normal'"); - if($x) { + if ($x) { Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] ); } } - if(self::$deliveries) + if (self::$deliveries) { do_delivery(self::$deliveries); - - logger('notifier: basic loop complete.', LOGGER_DEBUG); + } call_hooks('notifier_end',$target_item); diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php index b3bdf2c47..04e427c97 100644 --- a/Zotlabs/Daemon/Onepoll.php +++ b/Zotlabs/Daemon/Onepoll.php @@ -99,6 +99,76 @@ class Onepoll { if(! $responded) return; + if(defined('USE_OUTBOX')) { + + // @fixme + // This needs to be converted from zotfeed to ActivityStreams (such as an ActivityPub outbox). + // The zotfeed has serious compatibility issues between Hubzilla and Zap. + + if($contact['xchan_connurl']) { + $fetch_feed = true; + $x = null; + + // They haven't given us permission to see their stream + + $can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream')); + + if(! $can_view_stream) + $fetch_feed = false; + + // we haven't given them permission to send us their stream + + $can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream')); + + if(! $can_send_stream) + $fetch_feed = false; + + if($fetch_feed) { + + if(strpos($contact['xchan_connurl'],z_root()) === 0) { + // local channel - save a network fetch + $c = channelx_by_hash($contact['xchan_hash']); + if($c) { + $x = [ + 'success' => true, + 'body' => json_encode( [ + 'success' => true, + 'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ]) + ]) + ]; + } + } + else { + // remote fetch + + $feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']); + $feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname(); + $recurse = 0; + $x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]); + } + + logger('feed_update: ' . print_r($x,true), LOGGER_DATA); + } + + if(($x) && ($x['success'])) { + $total = 0; + logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl); + + $j = json_decode($x['body'],true); + if($j['success'] && $j['messages']) { + foreach($j['messages'] as $message) { + // process delivery here once we have parsed the AS + logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA); + $total ++; + } + logger("onepoll: $total messages processed"); + } + } + } + + + } // end USE_OUTBOX + // update the poco details for this connection if($contact['xchan_connurl']) { diff --git a/Zotlabs/Lib/ASCollection.php b/Zotlabs/Lib/ASCollection.php new file mode 100644 index 000000000..bca4322e7 --- /dev/null +++ b/Zotlabs/Lib/ASCollection.php @@ -0,0 +1,81 @@ +next to return additional pages (arrays of collection members). + * Returns an empty array when there is nothing more to return + */ + + + + +class ASCollection { + + private $url = null; + private $channel = null; + private $nextpage = null; + private $data = null; + + function __construct($url,$channel = null) { + + $this->url = $url; + $this->channel = $channel; + + $data = Activity::fetch($url,$channel); + + if (! $data) { + return false; + } + + $ptr = $data; + + if ($data['type'] === 'OrderedCollection') { + if (array_key_exists('first',$data)) { + $ptr = $data['first']; + } + } + + if ($ptr['type'] === 'OrderedCollectionPage' && $ptr['orderedItems']) { + $this->data = $ptr['orderedItems']; + } + + $this->setnext($data); + return $this->data; + } + + function next() { + + if (! $this->nextpage) { + return []; + } + $data = Activity::fetch($this->nextpage,$channel); + + if (! $data) { + return []; + } + + if ($data['type'] === 'OrderedCollectionPage' && $data['orderedItems']) { + $this->data = $data['orderedItems']; + } + + $this->setnext($data); + return $this->data; + } + + function setnext($data) { + if (array_key_exists('next',$data)) { + $this->nextpage = $data['next']; + } + elseif (array_key_exists('last',$data)) { + $this->nextpage = $data['last']; + } + } + +} \ No newline at end of file diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 3b83699af..1d5e5118d 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -9,6 +9,10 @@ use Zotlabs\Access\PermissionLimits; use Zotlabs\Daemon\Master; +require_once('include/html2bbcode.php'); +require_once('include/html2plain.php'); +require_once('include/event.php'); + class Activity { static $ACTOR_CACHE_DAYS = 3; @@ -25,7 +29,12 @@ class Activity { return self::fetch_profile($x); } if (in_array($x['type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_ARTICLE ] )) { - return self::fetch_item($x); + + // Use Mastodon-specific note and media hacks if nomadic. Else HTML. + // Eventually this needs to be passed in much further up the stack + // and base the decision on whether or not we are encoding for ActivityPub or Zot6 + + return self::fetch_item($x,((get_config('system','activitypub')) ? true : false)); } if ($x['type'] === ACTIVITY_OBJ_THING) { return self::fetch_thing($x); @@ -141,7 +150,7 @@ class Activity { } - static function fetch_item($x) { + static function fetch_item($x,$activitypub = false) { if (array_key_exists('source',$x)) { // This item is already processed and encoded @@ -154,7 +163,7 @@ class Activity { if ($r) { xchan_query($r,true); $r = fetch_post_tags($r,true); - return self::encode_item($r[0],((defined('NOMADIC')) ? false : true)); + return self::encode_item($r[0],$activitypub); } } @@ -319,7 +328,6 @@ class Activity { } $ret['attributedTo'] = $i['author']['xchan_url']; - if ($i['mid'] !== $i['parent_mid']) { $ret['inReplyTo'] = $i['thr_parent']; $cnv = get_iconfig($i['parent'],'ostatus','conversation'); @@ -931,7 +939,7 @@ class Activity { ]; $ret['url'] = $p['xchan_url']; - if ($activitypub) { + if ($activitypub && $feature_complete) { if ($c) { $ret['inbox'] = z_root() . '/inbox/' . $c['channel_address']; @@ -1881,7 +1889,8 @@ class Activity { $s['mid'] = $act->id; $s['parent_mid'] = $act->obj['id']; - + $s['replyto'] = $act->replyto; + // over-ride the object timestamp with the activity if ($act->data['published']) { @@ -2345,7 +2354,7 @@ class Activity { intval($item['uid']) ); if (! $p) { - if (defined('NOMADIC')) { + if (! get_config('system','activitypub')) { return; } else { @@ -2811,8 +2820,6 @@ class Activity { static function bb_content($content,$field) { - require_once('include/html2bbcode.php'); - require_once('include/event.php'); $ret = false; if (is_array($content[$field])) { @@ -2876,6 +2883,11 @@ class Activity { if ($event) { $event['summary'] = html2bbcode($content['summary']); + if (! $event['summary']) { + if ($content['name']) { + $event['summary'] = html2plain(purify_html($content['name']),256); + } + } $event['description'] = html2bbcode($content['content']); if ($event['summary'] && $event['dtstart']) { $content['event'] = $event; @@ -2888,9 +2900,6 @@ class Activity { } } - - - return $content; } diff --git a/Zotlabs/Lib/ActivityPub.php b/Zotlabs/Lib/ActivityPub.php index ba364f010..7f66cd893 100644 --- a/Zotlabs/Lib/ActivityPub.php +++ b/Zotlabs/Lib/ActivityPub.php @@ -29,10 +29,6 @@ class ActivityPub { return; } - if(strpos($arr['target_item']['postopts'],'nopub') !== false) { - return; - } - $signed_msg = get_iconfig($arr['target_item'],'activitypub','rawmsg'); // If we have an activity already stored with an LD-signature diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index c0c86d81e..bebe5173b 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -24,6 +24,7 @@ class ActivityStreams { public $actor = null; public $obj = null; public $tgt = null; + public $replyto = null; public $origin = null; public $owner = null; public $signer = null; @@ -83,14 +84,15 @@ class ActivityStreams { } if($this->is_valid()) { - $this->id = $this->get_property_obj('id'); - $this->type = $this->get_primary_type(); - $this->actor = $this->get_actor('actor','',''); - $this->obj = $this->get_compound_property('object'); - $this->tgt = $this->get_compound_property('target'); - $this->origin = $this->get_compound_property('origin'); - $this->recips = $this->collect_recips(); - + $this->id = $this->get_property_obj('id'); + $this->type = $this->get_primary_type(); + $this->actor = $this->get_actor('actor','',''); + $this->obj = $this->get_compound_property('object'); + $this->tgt = $this->get_compound_property('target'); + $this->origin = $this->get_compound_property('origin'); + $this->recips = $this->collect_recips(); + $this->replyto = $this->get_compound_property('replyTo'); + $this->ldsig = $this->get_compound_property('signature'); if($this->ldsig) { $this->signer = $this->get_compound_property('creator',$this->ldsig); diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php index 8f8f696b8..b12d9ab68 100644 --- a/Zotlabs/Lib/Connect.php +++ b/Zotlabs/Lib/Connect.php @@ -29,20 +29,20 @@ class Connect { $my_perms = false; $protocol = ''; - if(substr($url,0,1) === '[') { + if (substr($url,0,1) === '[') { $x = strpos($url,']'); - if($x) { + if ($x) { $protocol = substr($url,1,$x-1); $url = substr($url,$x+1); } } - if(! allowed_url($url)) { + if (! check_siteallowed($url)) { $result['message'] = t('Channel is blocked on this site.'); return $result; } - if(! $url) { + if (! $url) { $result['message'] = t('Channel location missing.'); return $result; } @@ -80,7 +80,7 @@ class Connect { // Some Hubzilla records were originally stored as activitypub. If we find one, force rediscovery // since Zap cannot connect with them. - if($r['xchan_network'] === 'activitypub') { + if($r['xchan_network'] === 'activitypub' && ! get_config('system','activitypub')) { $r = null; } } @@ -141,9 +141,15 @@ class Connect { return $result; } + if (! check_channelallowed($xchan_hash)) { + $result['message'] = t('Channel is blocked on this site.'); + logger('follow: ' . $result['message']); + return $result; + + } // Now start processing the new connection - if($r['xchan_network'] === 'activitypub') { + if($r['xchan_network'] === 'activitypub' && ! get_config('system','activitypub')) { // ActivityPub is not nomadic $result['message'] = t('Protocol not supported'); return $result; diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 12214c194..797d8196b 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1537,7 +1537,8 @@ class Libzot { * @brief * * @param array $sender - * @param array $arr + * @param ActivityStreams object $act + * @param array $msg_arr * @param array $deliveries * @param boolean $relay * @param boolean $public (optional) default false @@ -1891,8 +1892,9 @@ class Libzot { // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. - if (! intval($r[0]['item_origin'])) + if (! intval($r[0]['item_origin'])) { continue; + } } } else { @@ -2338,90 +2340,6 @@ class Libzot { return $post_id; } - static function process_mail_delivery($sender, $arr, $deliveries) { - - $result = array(); - - if ($sender != $arr['from_xchan']) { - logger('process_mail_delivery: sender is not mail author'); - return; - } - - foreach ($deliveries as $d) { - - $DR = new DReport(z_root(),$sender,$d,$arr['mid']); - - $r = q("select * from channel where channel_hash = '%s' limit 1", - dbesc($d['hash']) - ); - - if (! $r) { - $DR->update('recipient not found'); - $result[] = $DR->get(); - continue; - } - - $channel = $r[0]; - $DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>'); - - - if (! perm_is_allowed($channel['channel_id'],$sender,'post_mail')) { - - /* - * Always allow somebody to reply if you initiated the conversation. It's anti-social - * and a bit rude to send a private message to somebody and block their ability to respond. - * If you are being harrassed and want to put an end to it, delete the conversation. - */ - - $return = false; - if ($arr['parent_mid']) { - $return = q("select * from mail where mid = '%s' and channel_id = %d limit 1", - dbesc($arr['parent_mid']), - intval($channel['channel_id']) - ); - } - if (! $return) { - logger("permission denied for mail delivery {$channel['channel_id']}"); - $DR->update('permission denied'); - $result[] = $DR->get(); - continue; - } - } - - - $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1", - dbesc($arr['mid']), - intval($channel['channel_id']) - ); - if ($r) { - if (intval($arr['mail_recalled'])) { - $x = q("delete from mail where id = %d and channel_id = %d", - intval($r[0]['id']), - intval($channel['channel_id']) - ); - $DR->update('mail recalled'); - $result[] = $DR->get(); - logger('mail_recalled'); - } - else { - $DR->update('duplicate mail received'); - $result[] = $DR->get(); - logger('duplicate mail received'); - } - continue; - } - else { - $arr['account_id'] = $channel['channel_account_id']; - $arr['channel_id'] = $channel['channel_id']; - $item_id = mail_store($arr); - $DR->update('mail delivered'); - $result[] = $DR->get(); - } - } - - return $result; - } - /** * @brief Processes delivery of profile. diff --git a/Zotlabs/Lib/Share.php b/Zotlabs/Lib/Share.php index 6cf1c645c..07ce11b81 100644 --- a/Zotlabs/Lib/Share.php +++ b/Zotlabs/Lib/Share.php @@ -95,7 +95,7 @@ class Share { $is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false); if($is_photo) { $object = json_decode($this->item['obj'],true); - $photo_bb = $object['body']; + $photo_bb = (($object['source']) ? $object['source']['content'] : $object['body']); } if (strpos($this->item['body'], "[/share]") !== false) { @@ -107,7 +107,7 @@ class Share { "' portable_id='" . $this->item['author']['xchan_hash'] . "' avatar='" . $this->item['author']['xchan_photo_s'] . "' link='" . $this->item['plink'] . - "' auth='" . (($this->item['author']['network'] === 'zot') ? 'true' : 'false') . + "' auth='" . (($this->item['author']['network'] === 'zot6') ? 'true' : 'false') . "' posted='" . $this->item['created'] . "' message_id='" . $this->item['mid'] . "']"; diff --git a/Zotlabs/Lib/SuperCurl.php b/Zotlabs/Lib/SuperCurl.php deleted file mode 100644 index 462a62b36..000000000 --- a/Zotlabs/Lib/SuperCurl.php +++ /dev/null @@ -1,127 +0,0 @@ -request_data = $s; - $this->filepos = 0; - } - - public function curl_read($ch,$fh,$size) { - - if($this->filepos < 0) { - unset($fh); - return ''; - } - - $s = substr($this->request_data,$this->filepos,$size); - - if(strlen($s) < $size) - $this->filepos = (-1); - else - $this->filepos = $this->filepos + $size; - - return $s; - } - - - public function __construct($opts = array()) { - $this->set($opts); - } - - private function set($opts = array()) { - if($opts) { - foreach($opts as $k => $v) { - switch($k) { - case 'http_auth': - $this->auth = $v; - break; - case 'magicauth': - // currently experimental - $this->magicauth = $v; - \Zotlabs\Daemon\Master::Summon([ 'CurlAuth', $v ]); - break; - case 'custom': - $this->request_method = $v; - break; - case 'url': - $this->url = $v; - break; - case 'data': - $this->set_data($v); - if($v) { - $this->upload = true; - } - else { - $this->upload = false; - } - break; - case 'headers': - $this->headers = $v; - break; - default: - $this->curlopts[$k] = $v; - break; - } - } - } - } - - function exec() { - $opts = $this->curlopts; - $url = $this->url; - if($this->auth) - $opts['http_auth'] = $this->auth; - if($this->magicauth) { - $opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth; - $opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth; - $opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth)); - $c = channelx_by_n($this->magicauth); - if($c) - $url = zid($this->url,channel_reddress($c)); - } - if($this->custom) - $opts['custom'] = $this->custom; - if($this->headers) - $opts['headers'] = $this->headers; - if($this->upload) { - $opts['upload'] = true; - $opts['infile'] = $this->filehandle; - $opts['infilesize'] = strlen($this->request_data); - $opts['readfunc'] = [ $this, 'curl_read' ] ; - } - - $recurse = 0; - return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null)); - - } - - -} diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 3504bd580..3c9ccfce7 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -38,7 +38,7 @@ class ThreadItem { $this->data = $data; $this->toplevel = ($this->get_id() == $this->get_data_value('parent')); -// $this->threaded = get_config('system','thread_allow',((defined('NOMADIC')) ? false : true)); +// $this->threaded = get_config('system','thread_allow',((get_config('system','activitypub')) ? true : false)); $this->threaded = get_config('system','thread_allow',true); $observer = App::get_observer(); @@ -482,7 +482,8 @@ class ThreadItem { 'preview_lbl' => t('This is an unsaved preview'), 'wait' => t('Please wait'), 'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])), - 'thread_level' => $thread_level + 'thread_level' => $thread_level, + 'thread_max' => intval(get_config('system','thread_maxlevel',2)) + 1 ); $arr = array('item' => $item, 'output' => $tmp_item); @@ -490,22 +491,32 @@ class ThreadItem { $result = $arr['output']; - $censored = false; - - if(strpos($body['html']," + + + + + {{if $notself}} {{if $is_pending}} diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index 668b80733..d4a63806c 100755 --- a/view/tpl/conv_item.tpl +++ b/view/tpl/conv_item.tpl @@ -22,7 +22,7 @@ {{/if}} {{if $item.title && !$item.event}}
- {{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}} + {{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}
{{if ! $item.is_new}}
@@ -104,7 +104,7 @@ {{/if}} - {{if $item.comment && $item.thread_level > 1 && $item.thread_level < 3}} + {{if $item.comment && $item.thread_level > 1 && $item.thread_level < $item.thread_max }} diff --git a/view/tpl/conv_list.tpl b/view/tpl/conv_list.tpl index 9a77bf61b..9f14844ad 100755 --- a/view/tpl/conv_list.tpl +++ b/view/tpl/conv_list.tpl @@ -20,7 +20,7 @@ {{/if}} {{if $item.title && !$item.event}}
- {{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}} + {{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}{{/if}}{{/if}}
{{if ! $item.is_new}}
diff --git a/view/tpl/xchan_vcard.tpl b/view/tpl/xchan_vcard.tpl index ac796cd47..c0b5bbbf2 100755 --- a/view/tpl/xchan_vcard.tpl +++ b/view/tpl/xchan_vcard.tpl @@ -1,7 +1,7 @@
{{$name}}
{{if $connect}} -
{{$connect}}
+
{{$connect}}
{{/if}}
{{$name}}