From a0e7ddd8cdfd1ac4e752f88ee81693338a533f4e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 26 Aug 2019 19:54:21 -0700 Subject: [PATCH 01/11] better collection parsing --- Zotlabs/Lib/ASCollection.php | 81 ++++++++++++++++++++++++++++++++++ Zotlabs/Lib/Activity.php | 1 - Zotlabs/Module/Connections.php | 45 ++++++++++--------- Zotlabs/Module/Connedit.php | 53 +++++++++------------- Zotlabs/Storage/Directory.php | 6 +-- 5 files changed, 131 insertions(+), 55 deletions(-) create mode 100644 Zotlabs/Lib/ASCollection.php 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..caa6e50c1 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -319,7 +319,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'); diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index ac57ce03f..ebab7408d 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -1,20 +1,24 @@ (($searching) ? t('Connections search') . ": '" . $search . "'" : ""), '$submit' => t('Find'), '$edit' => t('Edit'), - '$cmd' => \App::$cmd, + '$cmd' => App::$cmd, '$contacts' => $contacts, '$paginate' => paginate($a), diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 4f2aa7bcd..88065aaf8 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -74,15 +74,6 @@ class Connedit extends Controller { $channel = App::get_channel(); - // TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the - // connection enable is toggled to a special autopost url and set permissions immediately, leaving - // the other form elements alone pending a manual submit of the form. The downside is that there - // will be a window of opportunity when the permissions have been set but before you've had a chance - // to review and possibly restrict them. The upside is we won't have to warn you that your connection - // can't do anything until you save the bloody form. - - $autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false); - $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", intval($contact_id), intval(local_channel()) @@ -287,33 +278,33 @@ class Connedit extends Controller { function connedit_clone(&$a) { - if(! App::$poi) - return; + if (! App::$poi) { + return; + } + $channel = App::get_channel(); - $channel = App::get_channel(); + $r = q("SELECT abook.*, xchan.* + FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel = %d and abook_id = %d LIMIT 1", + intval(local_channel()), + intval(App::$poi['abook_id']) + ); + if ($r) { + App::$poi = array_shift($r); + } - $r = q("SELECT abook.*, xchan.* - FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and abook_id = %d LIMIT 1", - intval(local_channel()), - intval(App::$poi['abook_id']) - ); - if($r) { - App::$poi = array_shift($r); - } + $clone = App::$poi; - $clone = App::$poi; + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); - unset($clone['abook_id']); - unset($clone['abook_account']); - unset($clone['abook_channel']); - - $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); - if($abconfig) - $clone['abconfig'] = $abconfig; - - Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); + $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); + if ($abconfig) { + $clone['abconfig'] = $abconfig; + } + Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ] ] ); } /* @brief Generate content of connection edit page diff --git a/Zotlabs/Storage/Directory.php b/Zotlabs/Storage/Directory.php index 063b4e627..8eef71aa2 100644 --- a/Zotlabs/Storage/Directory.php +++ b/Zotlabs/Storage/Directory.php @@ -727,14 +727,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo return $ret; } - $r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0", + $r = q("SELECT channel_id, channel_address FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0", intval(PAGE_HIDDEN) ); if ($r) { foreach ($r as $rr) { - if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) { - logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA); + if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) { + logger('found channel: ' . $rr['channel_address'], LOGGER_DATA); $ret[] = new Directory($rr['channel_address'], $auth); } } From 1de2bafa61ff239a208aeb12f98025c38f728cff Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 27 Aug 2019 22:25:06 -0700 Subject: [PATCH 02/11] improved notification links for new connections, ongoing work on onepoll and zotfeeds, reduce core usage of item.postopts --- Zotlabs/Daemon/Notifier.php | 5 -- Zotlabs/Daemon/Onepoll.php | 70 ++++++++++++++++++++++++++ Zotlabs/Lib/ActivityPub.php | 4 -- Zotlabs/Lib/Libzot.php | 90 ++-------------------------------- Zotlabs/Module/Connections.php | 4 ++ Zotlabs/Module/Ping.php | 2 +- boot.php | 2 +- include/items.php | 6 +-- 8 files changed, 82 insertions(+), 101 deletions(-) diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 4b59c6ce6..8fdf58700 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -307,11 +307,6 @@ class Notifier { 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']) ); 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/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/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/Module/Connections.php b/Zotlabs/Module/Connections.php index ebab7408d..adc2f6c24 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -85,11 +85,15 @@ class Connections extends Controller { $pending = true; break; case 'ifpending': + case intval(argv(1)): $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", intval(local_channel()) ); if ($r && $r[0]['total']) { $search_flags = " and abook_pending = 1 "; + if(intval(argv(1))) { + $search_flags .= " and abook_id = " . intval(argv(1)) . " "; + } $head = t('New'); $pending = true; App::$argv[1] = 'pending'; diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index 6ea22b02b..914030a4b 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -394,7 +394,7 @@ class Ping extends Controller { if ($r) { foreach ($r as $rr) { $local_result[] = [ - 'notify_link' => z_root() . '/connections/ifpending', + 'notify_link' => z_root() . '/connections/' . $rr['abook_id'], 'name' => $rr['xchan_name'], 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], diff --git a/boot.php b/boot.php index cc150bc70..ae4c0bb1c 100755 --- a/boot.php +++ b/boot.php @@ -48,7 +48,7 @@ require_once('include/items.php'); -define ( 'STD_VERSION', '19.8.26' ); +define ( 'STD_VERSION', '19.8.28' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1234 ); diff --git a/include/items.php b/include/items.php index f48909626..cfc1a3b52 100644 --- a/include/items.php +++ b/include/items.php @@ -3846,7 +3846,7 @@ function zot_feed($uid, $observer_hash, $arr) { $nonsys_uids = q("SELECT channel_id FROM channel WHERE channel_system = 0"); $nonsys_uids_str = ids_to_querystr($nonsys_uids,'channel_id'); - $r = q("SELECT parent, postopts FROM item + $r = q("SELECT parent FROM item WHERE uid IN ( %s ) AND item_private = 0 $item_normal @@ -3855,7 +3855,7 @@ function zot_feed($uid, $observer_hash, $arr) { ); } else { - $r = q("SELECT parent, postopts FROM item + $r = q("SELECT parent FROM item WHERE uid = %d $item_normal $sql_extra ORDER BY created ASC $limit", @@ -3869,8 +3869,6 @@ function zot_feed($uid, $observer_hash, $arr) { foreach($r as $rv) { if(array_key_exists($rv['parent'],$parents)) continue; - if(strpos($rv['postopts'],'nodeliver') !== false) - continue; $parents[$rv['parent']] = $rv; if(count($parents) > 200) break; From 86841a78a5f7b914743d24a7bed9de3f9d37feb4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 29 Aug 2019 21:19:00 -0700 Subject: [PATCH 03/11] minor fixes from osada --- Zotlabs/Lib/Share.php | 4 ++-- Zotlabs/Module/Activity.php | 2 +- Zotlabs/Module/Item.php | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) 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/Module/Activity.php b/Zotlabs/Module/Activity.php index 68d8b883c..08776e7e2 100644 --- a/Zotlabs/Module/Activity.php +++ b/Zotlabs/Module/Activity.php @@ -63,7 +63,7 @@ class Activity extends Controller { killme(); } - + goaway(z_root() . '/item/' . argv(1)); } } \ No newline at end of file diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 67f05c13c..7ca48351a 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -299,8 +299,9 @@ class Item extends Controller { // the text/html page of the item. if (argc() > 1 && argv(1) !== 'drop') { - $x = q("select uid, item_wall, llink, mid from item where mid = '%s' ", - dbesc(z_root() . '/item/' . argv(1)) + $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ", + dbesc(z_root() . '/item/' . argv(1)), + dbesc(z_root() . '/activity/' . argv(1)) ); if ($x) { foreach ($x as $xv) { From 1f160251a0c20aab162e19b3af5453389b4c3f46 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 2 Sep 2019 20:47:34 -0700 Subject: [PATCH 04/11] styling issues, fixes from Hubzilla --- Zotlabs/Module/Settings/Channel.php | 24 ++++++------------------ boot.php | 2 +- include/import.php | 12 +++++++++++- include/text.php | 2 +- view/theme/redbasic/css/style.css | 9 +++++++-- view/tpl/conv_item.tpl | 2 +- view/tpl/conv_list.tpl | 2 +- view/tpl/xchan_vcard.tpl | 2 +- 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index d516f1516..f5f8da93f 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -475,8 +475,6 @@ class Channel { $default_permcat = get_pconfig(local_channel(),'system','default_permcat','default'); - $stpl = get_markup_template('settings.tpl'); - $acl = new AccessControl($channel); $perm_defaults = $acl->get(); @@ -528,9 +526,8 @@ class Channel { $site_firehose = intval(get_config('system','site_firehose',0)) == 1; - $o .= replace_macros($stpl,array( - '$ptitle' => t('Channel Settings'), - + $o .= replace_macros(get_markup_template('settings.tpl'), [ + '$ptitle' => t('Channel Settings'), '$submit' => t('Submit'), '$baseurl' => z_root(), '$uid' => local_channel(), @@ -551,11 +548,6 @@ class Channel { '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), - '$lbl_pmacro' => t('Simple Privacy Settings:'), - '$pmacro3' => t('Very Public - extremely permissive (should be used with caution)'), - '$pmacro2' => t('Typical - default public, privacy when desired (similar to social network permissions but with improved privacy)'), - '$pmacro1' => t('Private - default private, never open or public'), - '$pmacro0' => t('Blocked - default blocked to/from everybody'), '$permiss_arr' => $permiss, '$comment_perms' => $comment_perms, @@ -640,20 +632,16 @@ class Channel { '$h_descadvn' => t('Change the behaviour of this account for special situations'), '$pagetype' => $pagetype, '$lbl_misc' => t('Miscellaneous Settings'), - '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')), - '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')), + '$photo_path' => array('photo_path', t('Default photo upload folder name'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')), + '$attach_path' => array('attach_path', t('Default file upload folder name'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')), '$menus' => $menu, '$menu_desc' => t('Personal menu to display in your channel pages'), '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), - '$firefoxshare' => t('Firefox Share $Projectname provider'), '$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no), - )); - - call_hooks('settings_form',$o); - - //$o .= '' . "\r\n"; + ]); + call_hooks('settings_form',$o); return $o; } } diff --git a/boot.php b/boot.php index ae4c0bb1c..32d7a486d 100755 --- a/boot.php +++ b/boot.php @@ -48,7 +48,7 @@ require_once('include/items.php'); -define ( 'STD_VERSION', '19.8.28' ); +define ( 'STD_VERSION', '19.9.3' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1234 ); diff --git a/include/import.php b/include/import.php index d8f4415a2..937135792 100644 --- a/include/import.php +++ b/include/import.php @@ -45,8 +45,18 @@ function import_channel($channel, $account_id, $seize, $newname = '') { dbesc($channel['channel_hash']), dbesc($channel['channel_address']) ); - if ($r && $r[0]['channel_guid'] == $channel['channel_guid'] && $r[0]['channel_pubkey'] === $channel['channel_pubkey'] && $r[0]['channel_hash'] === $channel['channel_hash']) + if ($r && $r[0]['channel_guid'] == $channel['channel_guid'] && $r[0]['channel_pubkey'] === $channel['channel_pubkey'] && $r[0]['channel_hash'] === $channel['channel_hash']) { + // do not return a dead or deleted or system channel + if ($r[0]['channel_deleted'] > NULL_DATE + || intval($r[0]['channel_removed']) + || intval($r[0]['channel_moved']) + || intval($r[0]['channel_system'])) { + logger('attempt to import to a channel that was removed. ', print_r($channel,true)); + notice( t('A channel with these settings was discovered and is not usable as it was removed or reserved for system use. Import failed.') . EOL); + return false; + } return $r[0]; + } if (($r) || (check_webbie(array($channel['channel_address'])) !== $channel['channel_address'])) { if ($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) { diff --git a/include/text.php b/include/text.php index f23c82082..b235e3938 100644 --- a/include/text.php +++ b/include/text.php @@ -1631,7 +1631,7 @@ function prepare_body(&$item,$attach = false,$opts = false) { function separate_img_links($s) { $x = preg_replace('/\\\<\/a\>/ism', - '
' . t('Link') . '',$s); + '
' . t('Link') . '
',$s); return $x; } diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index aafb0d9f2..b1326e2f3 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1,8 +1,6 @@ /** * Redbasic * - * Based on duepuntozero Friendica style - * Originally by Fabio Comuni */ @@ -31,6 +29,13 @@ html { text-decoration: none; } +a.zrl:hover { + font-weight:bold; +} + +.threadlevel { + margin-right: 0.1rem; +} body { font-size: 0.9rem; diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index 668b80733..b5f845b0e 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}}
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}} - + {{/if}}
{{$name}}
From 5991fcf319a0e1e3537eb4ad0787d5994b360165 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 3 Sep 2019 17:33:27 -0700 Subject: [PATCH 05/11] update readme --- README.md | 29 +++++++++++++++++++++++++++++ include/connections.php | 2 +- include/conversation.php | 19 ++++++++++++------- 3 files changed, 42 insertions(+), 8 deletions(-) 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/include/connections.php b/include/connections.php index 6a99973c4..984fd6fe3 100644 --- a/include/connections.php +++ b/include/connections.php @@ -140,7 +140,7 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') { return replace_macros(get_markup_template('xchan_vcard.tpl'),array( '$name' => $xchan['xchan_name'], '$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']), - '$follow' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']), + '$follow' => urlencode(($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']), '$link' => zid($xchan['xchan_url']), '$connect' => $connect, '$newwin' => (($mode === 'chanview') ? t('New window') : ''), diff --git a/include/conversation.php b/include/conversation.php index afcd15a7e..f2a964bbd 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1479,21 +1479,26 @@ function jot_collections($channel,$collections) { } function get_item_children($arr, $parent) { - $children = array(); - foreach($arr as $item) { - if($item['id'] != $item['parent']) { - if(get_config('system','thread_allow',true)) { + + $children = []; + if (! $arr) { + return $children; + } + foreach ($arr as $item) { + if (intval($item['id']) !== intval($item['parent'])) { + if (get_config('system','thread_allow',true)) { // Fallback to parent_mid if thr_parent is not set $thr_parent = $item['thr_parent']; - if($thr_parent === '') + if ($thr_parent === '') { $thr_parent = $item['parent_mid']; + } - if($thr_parent === $parent['mid']) { + if ($thr_parent === $parent['mid']) { $item['children'] = get_item_children($arr, $item); $children[] = $item; } } - else if($item['parent'] == $parent['id']) { + elseif ($item['parent'] == $parent['id']) { $children[] = $item; } } From fd541186c20aa5eb82b6ee5464096fd30af9472f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 9 Sep 2019 20:51:07 -0700 Subject: [PATCH 06/11] port zotsh to python3 --- util/zotsh/zotsh-py3.py | 313 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100755 util/zotsh/zotsh-py3.py diff --git a/util/zotsh/zotsh-py3.py b/util/zotsh/zotsh-py3.py new file mode 100755 index 000000000..7ad8edcb6 --- /dev/null +++ b/util/zotsh/zotsh-py3.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python3 + +import sys, os +import configparser +import requests +from requests.auth import HTTPBasicAuth +import easywebdav +import easywebdav.__version__ as easywebdavversion +import base64 + +__version__= "0.0.2" + +SERVER = None +USER = None +PASSWD = None +VERIFY_SSL=True + +##################################################### + +class CommandNotFound(Exception): + pass + +class ZotSH(object): + commands = ['cd','ls','exists','mkdir','mkdirs','rmdir','delete','upload','download', + 'host', 'pwd','cat', + 'lcd','lpwd', 'lls', + 'quit', 'help'] + def __init__(self, host, session=None, davclient=None): + self.sessions = {} + self.host = host + self.session = session + self.davclient = davclient + + + @property + def host(self): + return self._host + + @host.setter + def host(self, host): + self._host = host + self._hostname = host.replace("https:","").replace("/","") + + @property + def hostname(self): + return self._hostname + + @hostname.setter + def hostname(self, hostname): + self._host = "https://%s/" % (hostname) + self._hostname = hostname + + @property + def session(self): + return self._session + + @session.setter + def session(self, session): + self._session = session + self.davclient = easywebdav.connect( self.hostname, protocol='https', session=session, path="dav", verify_ssl=VERIFY_SSL) + + @property + def PS1(self): + if self.davclient is None: + return "[!]> " + return "%s:%s> " % (self.hostname, self.davclient.cwd) + + def get_host_session(self, host=None): + #~ if host is None: + #~ host = self.host + #~ if not host.startswith("https"): + #~ host = "https://%s/" % (host) + #~ if host in self.sessions: + #~ session = self.sessions[host] + #~ else: + #~ session = requests.Session() + #~ self.sessions[host] = session + #~ if not host == SERVER + #~ session.params.update({'davguest':1}) + #~ return session + + if self.session is None: + session = requests.Session() + #session.params.update({'davguest':1}) + else: + session = self.session + #session.params.update({'davguest': (not host == SERVER) }) + return session + + def do(self, command, *args): + if not command in self.commands: + raise CommandNotFound("Unknown command '%s'" % command) + + cmd = getattr(self, "cmd_%s"%command, None) + if cmd is None: + cmd = getattr(self.davclient, command) + + return cmd(*args) + + def cmd_exists(self, *args): + if (len(args)==0): + return + return self.davclient.exists(args[0]) + + def cmd_mkdir(self, *args): + if (len(args)==0): + return + return self.davclient.mkdir(args[0]) + + def cmd_mkdirs(self, *args): + if (len(args)==0): + return + return self.davclient.mkdirs(args[0]) + + def cmd_rmdir(self, *args): + if (len(args)==0): + return + return self.davclient.rmdir(args[0]) + + def cmd_delete(self, *args): + if (len(args)==0): + return + return self.davclient.delete(args[0]) + + def cmd_upload(self, *args): + if (len(args)==0): + return + args = list(args) + if (len(args)==1): + args.append(args[0]) + + return self.davclient.upload(args[0], args[1]) + + def cmd_download(self, *args): + if (len(args)==0): + return + args = list(args) + if (len(args)==1): + args.append(args[0]) + + return self.davclient.download(args[0], args[1]) + + def cmd_host(self, *args): + if (len(args)==0): + return + newhostname = args[0] + newhost = "https://%s/" % newhostname + if newhostname == "~" or newhost == SERVER: + # bach to home server + self.host = SERVER + self.session = self.get_host_session(SERVER) + return + + session_remote = self.get_host_session(newhost) + session_home = self.get_host_session(SERVER) + + bnewhost = newhost + 'dav' + bnewhost = bnewhost.encode('hex') + + r = session_home.get( + SERVER + "magic", + params={'bdest': bnewhost, 'owa': 1}, + allow_redirects=True, + verify=VERIFY_SSL ) + + self.hostname = newhostname + self.session = session_remote + + + def cmd_pwd(self, *args): + return "%s%s" % ( self.davclient.baseurl, self.davclient.cwd ) + + def cmd_ls(self, *args): + extra_args = ["-a", "-l", "-d"] + + show_hidden = "-a" in args + show_list = "-l" in args + show_only_dir = "-d" in args + args = [ a for a in args if not a in extra_args ] + + + r = self.davclient.ls(*args) + l = max([ len(str(f.size)) for f in r ] + [7,]) + + def _fmt(type, size, name): + if show_list: + return "%s %*d %s" % (type, l, f.size , name) + else: + return name + + if show_hidden : + print(_fmt('d', 0, "./")) + if self.davclient.cwd!="/": + print(_fmt('d', 0, "../")) + + for f in r: + name = f.name.replace("/dav"+self.davclient.cwd,"") + type = "-" + if name.endswith("/"): + type = "d" + if name!="": + if show_hidden or not name.startswith("."): + if not show_only_dir or type=="d": + print(_fmt(type, f.size , name)) + + def cmd_lpwd(self, *args): + return os.getcwd() + + def cmd_lcd(self, *args): + if (len(args)==0): + return + os.chdir(args[0]) + + def cmd_lls(self, *args): + for f in os.listdir(os.getcwd()): + if os.path.isdir(f): + f=f+"/" + print(f) + + def cmd_help(self, *args): + print("ZotSH",__version__) + print() + print("Commands:") + for c in self.commands: + print("\t",c) + print() + print("easywebdav", easywebdavversion.__version__, "(mod)") + print("requests", requests.__version__) + + def cmd_cat(self,*args): + if (len(args)==0): + return + rfile = args[0] + resp = self.davclient._send('GET', rfile, (200,)) + print(resp.text) + +def load_conf(): + global SERVER,USER,PASSWD,VERIFY_SSL + homedir = os.getenv("HOME") + if homedir is None: + homedir = os.path.join(os.getenv("HOMEDRIVE"), os.getenv("HOMEPATH")) + + optsfile = ".zotshrc" + if not os.path.isfile(optsfile): + optsfile = os.path.join(homedir, ".zotshrc") + + if not os.path.isfile(optsfile): + print("Please create a configuration file called '.zotshrc':") + print("[zotsh]") + print("host = https://yourhost.com/") + print("username = your_username") + print("password = your_password") + sys.exit(-1) + + config = configparser.ConfigParser() + config.read(optsfile) + SERVER = config.get('zotsh', 'host') + USER = config.get('zotsh', 'username') + PASSWD = config.get('zotsh', 'password') + if config.has_option('zotsh', 'verify_ssl'): + VERIFY_SSL = config.getboolean('zotsh', 'verify_ssl') + + +def zotsh(): + + zotsh = ZotSH( SERVER) + + session_home = zotsh.get_host_session() + + #~ #login on home server + print("loggin in...") + r = session_home.get( + SERVER + "api/account/verify_credentials", + auth=HTTPBasicAuth(USER, PASSWD), + verify=VERIFY_SSL ) + + print("Hi", r.json()['name']) + + zotsh.session = session_home + + # command loop + inputs = input(zotsh.PS1) + while (inputs != "quit"): + inputs = inputs.strip() + if len(inputs)>0: + toks = [ x.strip() for x in inputs.split(" ") ] + + command = toks[0] + args = toks[1:] + try: + ret = zotsh.do(command, *args) + except easywebdav.client.OperationFailed as e: + print(e) + except CommandNotFound as e: + print(e) + else: + if ret is not None: + print(ret) + + + inputs = input(zotsh.PS1) + + + + +if __name__=="__main__": + load_conf() + zotsh() + sys.exit() + + + + From ffc43e1c7d7a3f38a6ab6035a14bc45cde07ddc4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 9 Sep 2019 21:03:33 -0700 Subject: [PATCH 07/11] heavy lifting for the next big development effort --- Zotlabs/Daemon/Notifier.php | 236 +++++++++++++---------------- Zotlabs/Lib/Activity.php | 18 ++- Zotlabs/Lib/ActivityStreams.php | 18 ++- Zotlabs/Lib/ThreadItem.php | 39 +++-- Zotlabs/Module/Apschema.php | 1 + Zotlabs/Module/Channel.php | 2 +- Zotlabs/Module/Followers.php | 73 +++++++++ Zotlabs/Module/Following.php | 70 +++++++++ Zotlabs/Module/Id.php | 2 +- Zotlabs/Module/Inbox.php | 253 ++++++++++++++++++++++++++++++++ Zotlabs/Module/Item.php | 6 +- Zotlabs/Module/Photo.php | 2 +- Zotlabs/Module/Profile.php | 2 +- Zotlabs/Module/Siteinfo.php | 2 +- Zotlabs/Module/Webfinger.php | 27 ++-- Zotlabs/Module/Well_known.php | 43 +++--- Zotlabs/Web/WebServer.php | 27 ++-- boot.php | 4 +- include/conversation.php | 242 +++++++----------------------- include/items.php | 4 +- include/text.php | 1 + install/schema_mysql.sql | 1 + install/schema_postgres.sql | 1 + util/zotsh/zotsh.py | 2 +- view/tpl/conv_item.tpl | 2 +- 25 files changed, 660 insertions(+), 418 deletions(-) create mode 100644 Zotlabs/Module/Followers.php create mode 100644 Zotlabs/Module/Following.php create mode 100644 Zotlabs/Module/Inbox.php diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 8fdf58700..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,29 +253,29 @@ 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); @@ -310,20 +285,20 @@ class Notifier { $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 { @@ -332,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, @@ -360,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 @@ -380,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 @@ -392,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 ]; @@ -414,7 +384,7 @@ class Notifier { } else { - if($cmd === 'relay') { + if ($cmd === 'relay') { logger('owner relay (downstream delivery)'); } else { @@ -424,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; @@ -460,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; } @@ -477,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']; } } @@ -516,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, @@ -524,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 @@ -537,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; @@ -545,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. @@ -574,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; @@ -588,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']; @@ -606,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, @@ -625,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, @@ -633,7 +596,6 @@ class Notifier { 'queued' => [] ]; - ActivityPub::notifier_process($narr); call_hooks('notifier_hub',$narr); @@ -655,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( [ @@ -682,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']), @@ -698,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/Lib/Activity.php b/Zotlabs/Lib/Activity.php index caa6e50c1..cdfff9b39 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -25,7 +25,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 +146,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 +159,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); } } @@ -930,7 +935,7 @@ class Activity { ]; $ret['url'] = $p['xchan_url']; - if ($activitypub) { + if ($activitypub && $feature_complete) { if ($c) { $ret['inbox'] = z_root() . '/inbox/' . $c['channel_address']; @@ -1880,7 +1885,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']) { @@ -2344,7 +2350,7 @@ class Activity { intval($item['uid']) ); if (! $p) { - if (defined('NOMADIC')) { + if (! get_config('system','activitypub')) { return; } else { 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/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 3504bd580..c828fe0a8 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); @@ -504,8 +505,21 @@ class ThreadItem { if($observer && ($profile_addr === $observer['xchan_hash'] || $profile_addr === $observer['xchan_addr'])) { $add_top_author = false; } - if($add_top_author && (! defined('NOMADIC'))) { + if($add_top_author && (get_config('system','activitypub'))) { $result['authors'][] = $profile_addr; + if ($item['term']) { + foreach ($item['term'] as $t) { + if ($t['ttype'] == TERM_MENTION) { + if (strpos($t['term'],'@') !== false) { + $result['authors'][] = $t['term']; + } + else { + $url = ((($position = strpos($t['url'],'url=')) !== false) ? urldecode(substr($t['url'],$position+4)) : $t['url']); + $result['authors'][] = $url; + } + } + } + } } $nb_children = count($children); @@ -523,15 +537,6 @@ class ThreadItem { if(strpos($xz['body']," {{/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 }} From d93c9ccc2d18e6506615507e31f0ee8d422d10a4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 10 Sep 2019 19:31:08 -0700 Subject: [PATCH 08/11] ongoing dev --- Zotlabs/Lib/Connect.php | 18 ++++--- Zotlabs/Lib/ThreadItem.php | 24 ++++----- Zotlabs/Module/Admin/Site.php | 3 -- Zotlabs/Update/_1235.php | 29 +++++++++++ Zotlabs/Widget/Clock.php | 6 +-- Zotlabs/Widget/Newmember.php | 26 +++++----- boot.php | 2 +- include/network.php | 92 ++++++++++------------------------- 8 files changed, 95 insertions(+), 105 deletions(-) create mode 100644 Zotlabs/Update/_1235.php 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/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index c828fe0a8..4b4cbd139 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -491,22 +491,16 @@ class ThreadItem { $result = $arr['output']; - $censored = false; - - if(strpos($body['html']," + + + + + {{if $notself}} {{if $is_pending}} From 91e94ffd81307878313e2a11f3671885a15d3bc8 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 17 Sep 2019 21:25:26 -0700 Subject: [PATCH 10/11] cleanup --- Zotlabs/Lib/Activity.php | 8 +- Zotlabs/Module/Cover_photo.php | 3 +- Zotlabs/Module/Inbox.php | 4 + Zotlabs/Module/Profile_photo.php | 244 +++++++++++++++---------------- boot.php | 4 +- include/account.php | 241 ++++++++++++++++-------------- include/bbcode.php | 3 + include/connections.php | 95 +++++++----- include/event.php | 6 +- include/features.php | 2 +- 10 files changed, 319 insertions(+), 291 deletions(-) diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index a10427eb9..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; @@ -2816,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])) { @@ -2883,7 +2885,7 @@ class Activity { $event['summary'] = html2bbcode($content['summary']); if (! $event['summary']) { if ($content['name']) { - $event['summary'] = html2bbcode($content['name']); + $event['summary'] = html2plain(purify_html($content['name']),256); } } $event['description'] = html2bbcode($content['content']); diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index d15df1417..06c6c2606 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -431,8 +431,7 @@ logger('gis: ' . print_r($gis,true)); '$modalerrorlink' => t('Error getting photo link'), '$modalerroralbum' => t('Error getting album'), '$form_security_token' => get_form_security_token("cover_photo"), - /// @FIXME - yuk - '$select' => t('Select existing photo'), + '$select' => t('Select previously uploaded photo'), )); diff --git a/Zotlabs/Module/Inbox.php b/Zotlabs/Module/Inbox.php index 7990e5b80..5a1b6fff4 100644 --- a/Zotlabs/Module/Inbox.php +++ b/Zotlabs/Module/Inbox.php @@ -203,6 +203,10 @@ class Inbox extends Controller { case 'Like': case 'Dislike': case 'Announce': + case 'Accept': + case 'Reject': + case 'TentativeAccept': + case 'TentativeReject': case 'emojiReaction': // These require a resolvable object structure if (is_array($AS->obj)) { diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 08bb3ac3e..6d06bfe33 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -1,24 +1,23 @@ is_valid()) { + if ($im->is_valid()) { $im->cropImage(300,$srcX,$srcY,$srcW,$srcH); @@ -139,7 +135,7 @@ class Profile_photo extends Controller { $r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48); - if($r1 === false || $r2 === false || $r3 === false) { + if ($r1 === false || $r2 === false || $r3 === false) { // if one failed, delete them all so we can start over. notice( t('Image resize failed.') . EOL ); $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d ) ", @@ -156,7 +152,7 @@ class Profile_photo extends Controller { // If setting for the default profile, unset the profile photo flag from any other photos I own - if($is_default_profile) { + if ($is_default_profile) { $r = q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d", dbesc(z_root() . '/photo/profile/l/' . local_channel()), @@ -210,9 +206,9 @@ class Profile_photo extends Controller { photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']); $sync = attach_export_data($channel,$base_image['resource_id']); - if($sync) + if ($sync) { Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); - + } // Similarly, tell the nav bar to bypass the cache and update the avatar image. $_SESSION['reload_avatar'] = true; @@ -223,12 +219,12 @@ class Profile_photo extends Controller { Master::Summon( [ 'Directory', $channel['channel_id'] ] ); } - else + else { notice( t('Unable to process image') . EOL); + } } goaway(z_root() . '/profiles'); - return; // NOTREACHED } // A new photo was uploaded. Store it and save some important details @@ -240,7 +236,7 @@ class Profile_photo extends Controller { $smallest = 0; - if($_REQUEST['importfile']) { + if ($_REQUEST['importfile']) { $hash = $_REQUEST['importfile']; $importing = true; } @@ -249,18 +245,18 @@ class Profile_photo extends Controller { $matches = []; $partial = false; - if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { + if (array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) { $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches); - if($pm) { - logger('Content-Range: ' . print_r($matches,true)); + if ($pm) { + logger('Content-Range: ' . print_r($matches,true), LOGGER_DEBUG); $partial = true; } } - if($partial) { + if ($partial) { $x = save_chunk($channel,$matches[1],$matches[2],$matches[3]); - if($x['partial']) { + if ($x['partial']) { header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0)); json_return_and_die($result); } @@ -277,7 +273,7 @@ class Profile_photo extends Controller { } } else { - if(! array_key_exists('userfile',$_FILES)) { + if (! array_key_exists('userfile',$_FILES)) { $_FILES['userfile'] = [ 'name' => $_FILES['files']['name'], 'type' => $_FILES['files']['type'], @@ -290,27 +286,25 @@ class Profile_photo extends Controller { $res = attach_store(App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash)); - logger('attach_store: ' . print_r($res,true)); + logger('attach_store: ' . print_r($res,true), LOGGER_DEBUG); json_return_and_die([ 'message' => $hash ]); - - } - if(($res && intval($res['data']['is_photo'])) || $importing) { + if (($res && intval($res['data']['is_photo'])) || $importing) { $i = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale", dbesc($hash), intval(local_channel()) ); - if(! $i) { + if (! $i) { notice( t('Image upload failed.') . EOL ); return; } $os_storage = false; - foreach($i as $ii) { - if(intval($ii['imgscale']) < PHOTO_RES_640) { + foreach ($i as $ii) { + if (intval($ii['imgscale']) < PHOTO_RES_640) { $smallest = intval($ii['imgscale']); $os_storage = intval($ii['os_storage']); $imagedata = $ii['content']; @@ -322,12 +316,12 @@ class Profile_photo extends Controller { $imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata)); $ph = photo_factory($imagedata, $filetype); - if(! $ph->is_valid()) { + if (! $ph->is_valid()) { notice( t('Unable to process image.') . EOL ); return; } - return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); + return $this->profile_photo_crop_ui_head($ph, $hash, $smallest); // This will "fall through" to the get() method, and since // App::$data['imagecrop'] is set, it will proceed to cropping @@ -337,7 +331,6 @@ class Profile_photo extends Controller { /* @brief Generate content of profile-photo view * - * @param $a Current application * @return void * */ @@ -345,7 +338,7 @@ class Profile_photo extends Controller { function get() { - if(! local_channel()) { + if (! local_channel()) { notice( t('Permission denied.') . EOL ); return; } @@ -354,10 +347,11 @@ class Profile_photo extends Controller { $pf = 0; $newuser = false; - if(argc() == 2 && argv(1) === 'new') + if (argc() == 2 && argv(1) === 'new') { $newuser = true; + } - if(argv(1) === 'use') { + if (argv(1) === 'use') { if (argc() < 3) { notice( t('Permission denied.') . EOL ); return; @@ -365,7 +359,6 @@ class Profile_photo extends Controller { $resource_id = argv(2); - $pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0); $c = q("select id, is_default from profile where uid = %d", @@ -374,7 +367,7 @@ class Profile_photo extends Controller { $multi_profiles = true; - if(($c) && (count($c) === 1) && (intval($c[0]['is_default']))) { + if (($c) && (count($c) === 1) && (intval($c[0]['is_default']))) { $_REQUEST['profile'] = $c[0]['id']; $multi_profiles = false; } @@ -386,33 +379,34 @@ class Profile_photo extends Controller { intval(local_channel()), dbesc($resource_id) ); - if(! $r) { + if (! $r) { notice( t('Photo not available.') . EOL ); return; } $havescale = false; - foreach($r as $rr) { - if($rr['imgscale'] == PHOTO_RES_PROFILE_80) + foreach ($r as $rr) { + if ($rr['imgscale'] == PHOTO_RES_PROFILE_80) { $havescale = true; + } } // set an already loaded and cropped photo as profile photo - if($havescale) { + if ($havescale) { // unset any existing profile photos $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d", intval(PHOTO_NORMAL), intval(PHOTO_PROFILE), - intval(local_channel())); + intval(local_channel()) + ); $r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'", intval(PHOTO_PROFILE), intval(local_channel()), dbesc($resource_id) - ); + ); - $r = q("UPDATE xchan set xchan_photo_date = '%s' - where xchan_hash = '%s'", + $r = q("UPDATE xchan set xchan_photo_date = '%s' where xchan_hash = '%s'", dbesc(datetime_convert()), dbesc($channel['xchan_hash']) ); @@ -420,11 +414,11 @@ class Profile_photo extends Controller { photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']); $sync = attach_export_data($channel,$resource_id); - if($sync) + if ($sync) { Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); + } - - \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); + Master::Summon( [ 'Directory',local_channel() ] ); goaway(z_root() . '/profiles'); } @@ -433,154 +427,148 @@ class Profile_photo extends Controller { intval(local_channel()) ); - if(! $r) { + if (! $r) { notice( t('Photo not available.') . EOL ); return; } - if(intval($r[0]['os_storage'])) + if (intval($r[0]['os_storage'])) { $data = @file_get_contents(dbunescbin($r[0]['content'])); - else + } + else { $data = dbunescbin($r[0]['content']); - + } + $ph = photo_factory($data, $r[0]['mimetype']); $smallest = 0; - if($ph->is_valid()) { + if ($ph->is_valid()) { // go ahead as if we have just uploaded a new photo to crop $i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d order by imgscale", dbesc($r[0]['resource_id']), intval(local_channel()) ); - if($i) { + if ($i) { $hash = $i[0]['resource_id']; - foreach($i as $ii) { - if(intval($ii['imgscale']) < PHOTO_RES_640) { + foreach ($i as $ii) { + if (intval($ii['imgscale']) < PHOTO_RES_640) { $smallest = intval($ii['imgscale']); } } } } - if($multi_profiles) { + if ($multi_profiles) { App::$data['importfile'] = $resource_id; } else { - $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); + $this->profile_photo_crop_ui_head($ph, $hash, $smallest); } // falls through with App::$data['imagecrop'] set so we go straight to the cropping section } - // present an upload form $profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc", intval(local_channel()) ); - if($profiles) { - for($x = 0; $x < count($profiles); $x ++) { + if ($profiles) { + for ($x = 0; $x < count($profiles); $x ++) { $profiles[$x]['selected'] = false; - if($pf && $profiles[$x]['id'] == $pf) + if ($pf && $profiles[$x]['id'] == $pf) { $profiles[$x]['selected'] = true; - if((! $pf) && $profiles[$x]['is_default']) + } + if ((! $pf) && $profiles[$x]['is_default']) { $profiles[$x]['selected'] = true; + } } } $importing = ((array_key_exists('importfile',App::$data)) ? true : false); - if(! x(App::$data,'imagecrop')) { + if (! array_key_exists('imagecrop', App::$data)) { $tpl = get_markup_template('profile_photo.tpl'); - $o .= replace_macros($tpl,array( - '$user' => App::$channel['channel_address'], - '$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')), - '$importfile' => (($importing) ? App::$data['importfile'] : ''), - '$lbl_upfile' => t('Upload File:'), - '$lbl_profiles' => t('Select a profile:'), - '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')), - '$submit' => (($importing) ? t('Use') : t('Upload')), - '$profiles' => $profiles, - '$single' => ((count($profiles) == 1) ? true : false), - '$profile0' => $profiles[0], - '$embedPhotos' => t('Use a photo from your albums'), - '$embedPhotosModalTitle' => t('Use a photo from your albums'), + $o .= replace_macros($tpl, [ + '$user' => App::$channel['channel_address'], + '$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')), + '$importfile' => (($importing) ? App::$data['importfile'] : ''), + '$lbl_upfile' => t('Upload File:'), + '$lbl_profiles' => t('Select a profile:'), + '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')), + '$submit' => (($importing) ? t('Use') : t('Upload')), + '$profiles' => $profiles, + '$single' => ((count($profiles) == 1) ? true : false), + '$profile0' => $profiles[0], + '$embedPhotos' => t('Use a photo from your albums'), + '$embedPhotosModalTitle' => t('Use a photo from your albums'), '$embedPhotosModalCancel' => t('Cancel'), - '$embedPhotosModalOK' => t('OK'), - '$modalchooseimages' => t('Choose images to embed'), - '$modalchoosealbum' => t('Choose an album'), - '$modaldiffalbum' => t('Choose a different album'), - '$modalerrorlist' => t('Error getting album list'), - '$modalerrorlink' => t('Error getting photo link'), - '$modalerroralbum' => t('Error getting album'), - '$form_security_token' => get_form_security_token("profile_photo"), - '$select' => t('Select existing photo'), - )); + '$embedPhotosModalOK' => t('OK'), + '$modalchooseimages' => t('Choose images to embed'), + '$modalchoosealbum' => t('Choose an album'), + '$modaldiffalbum' => t('Choose a different album'), + '$modalerrorlist' => t('Error getting album list'), + '$modalerrorlink' => t('Error getting photo link'), + '$modalerroralbum' => t('Error getting album'), + '$form_security_token' => get_form_security_token("profile_photo"), + '$select' => t('Select previously uploaded photo'), + ]); call_hooks('profile_photo_content_end', $o); - return $o; } else { // present a cropping form - $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution']; + $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution']; $resolution = App::$data['imagecrop_resolution']; - $tpl = get_markup_template("cropbody.tpl"); - $o .= replace_macros($tpl,array( - '$filename' => $filename, - '$profile' => intval($_REQUEST['profile']), - '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'], - '$image_url' => z_root() . '/photo/' . $filename, - '$title' => t('Crop Image'), - '$desc' => t('Please adjust the image cropping for optimum viewing.'), + $o .= replace_macros(get_markup_template('cropbody.tpl'), [ + '$filename' => $filename, + '$profile' => intval($_REQUEST['profile']), + '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'], + '$image_url' => z_root() . '/photo/' . $filename, + '$title' => t('Crop Image'), + '$desc' => t('Please adjust the image cropping for optimum viewing.'), '$form_security_token' => get_form_security_token("profile_photo"), - '$done' => t('Done Editing') - )); + '$done' => t('Done Editing') + ]); return $o; } - - return; // NOTREACHED } /* @brief Generate the UI for photo-cropping * - * @param $a Current application * @param $ph Photo-Factory * @return void * */ - - - function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){ - + function profile_photo_crop_ui_head($ph, $hash, $smallest) { $max_length = get_config('system','max_image_length'); - if(! $max_length) + if (! $max_length) { $max_length = MAX_IMAGE_LENGTH; - if($max_length > 0) + } + if ($max_length > 0) { $ph->scaleImage($max_length); - + } + App::$data['width'] = $ph->getWidth(); App::$data['height'] = $ph->getHeight(); - if(App::$data['width'] < 500 || App::$data['height'] < 500) { + if (App::$data['width'] < 500 || App::$data['height'] < 500) { $ph->scaleImageUp(400); App::$data['width'] = $ph->getWidth(); App::$data['height'] = $ph->getHeight(); } - App::$data['imagecrop'] = $hash; App::$data['imagecrop_resolution'] = $smallest; - App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); + App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []); return; } - - } diff --git a/boot.php b/boot.php index 3a64398df..592eade60 100755 --- a/boot.php +++ b/boot.php @@ -48,7 +48,7 @@ require_once('include/items.php'); -define ( 'STD_VERSION', '19.9.10' ); +define ( 'STD_VERSION', '19.9.17' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1236 ); @@ -75,7 +75,7 @@ define ( 'DIRECTORY_MODE_PRIMARY', 0x0001); // There can only be *one* prima define ( 'DIRECTORY_MODE_SECONDARY', 0x0002); // All other mirror directory servers define ( 'DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub with itself as directory server. -// We will look for upstream directories whenever me make contact +// We will look for upstream directories whenever we make contact // with other sites, but if this is a new installation and isn't // a standalone hub, we need to seed the service with a starting // point to go out and find the rest of the world. diff --git a/include/account.php b/include/account.php index c3faab17a..d4aac0b4a 100644 --- a/include/account.php +++ b/include/account.php @@ -1,52 +1,49 @@ false, 'message' => ''); + $result = [ 'error' => false, 'message' => '' ]; // Caution: empty email isn't counted as an error in this function. // Check for empty value separately. - if(! strlen($email)) + if (! strlen($email)) { return $result; + } - if(! validate_email($email)) + if (! validate_email($email)) { $result['message'] .= t('Not a valid email address') . EOL; - elseif(! allowed_email($email)) + } + elseif (! allowed_email($email)) { $result['message'] = t('Your email domain is not among those allowed on this site'); + } else { $r = q("select account_email from account where account_email = '%s' limit 1", dbesc($email) ); - if($r) { + if ($r) { $result['message'] .= t('Your email address is already registered at this site.'); } } - if($result['message']) + if ($result['message']) { $result['error'] = true; + } $arr = array('email' => $email, 'result' => $result); call_hooks('check_account_email', $arr); @@ -55,54 +52,58 @@ function check_account_email($email) { } function check_account_password($password) { - $result = array('error' => false, 'message' => ''); + $result = [ 'error' => false, 'message' => '' ]; // The only validation we perform by default is pure Javascript to // check minimum length and that both entered passwords match. // Use hooked functions to perform complexity requirement checks. - $arr = array('password' => $password, 'result' => $result); + $arr = [ 'password' => $password, 'result' => $result ]; call_hooks('check_account_password', $arr); return $arr['result']; } function check_account_invite($invite_code) { - $result = array('error' => false, 'message' => ''); + $result = [ 'error' => false, 'message' => '' ]; $using_invites = get_config('system','invitation_only'); - if($using_invites) { - if(! $invite_code) { + if ($using_invites) { + if (! $invite_code) { $result['message'] .= t('An invitation is required.') . EOL; } $r = q("select * from register where hash = '%s' limit 1", dbesc($invite_code)); - if(! $r) { + if (! $r) { $result['message'] .= t('Invitation could not be verified.') . EOL; } } - if(strlen($result['message'])) + if (strlen($result['message'])) { $result['error'] = true; + } - $arr = array('invite_code' => $invite_code, 'result' => $result); + $arr = [ 'invite_code' => $invite_code, 'result' => $result ]; call_hooks('check_account_invite', $arr); return $arr['result']; } function check_account_admin($arr) { - if(is_site_admin()) + if (is_site_admin()) { return true; + } $admin_email = trim(get_config('system','admin_email')); - if(strlen($admin_email) && $admin_email === trim($arr['email'])) + if (strlen($admin_email) && $admin_email === trim($arr['email'])) { return true; + } return false; } function account_total() { $r = q("select account_id from account where true"); - if(is_array($r)) + if ($r) { return count($r); + } return false; } @@ -138,7 +139,7 @@ function create_account($arr) { // Required: { email, password } - $result = array('success' => false, 'email' => '', 'password' => '', 'message' => ''); + $result = [ 'success' => false, 'email' => '', 'password' => '', 'message' => '' ]; $invite_code = ((x($arr,'invite_code')) ? notags(trim($arr['invite_code'])) : ''); $email = ((x($arr,'email')) ? notags(punify(trim($arr['email']))) : ''); @@ -149,30 +150,25 @@ function create_account($arr) { $roles = ((x($arr,'account_roles')) ? intval($arr['account_roles']) : 0 ); $expires = ((x($arr,'expires')) ? intval($arr['expires']) : NULL_DATE); - $default_service_class = get_config('system','default_service_class'); + $default_service_class = get_config('system','default_service_class', EMPTY_STR); - if($default_service_class === false) - $default_service_class = ''; - - if((! x($email)) || (! x($password))) { + if (! ($email && $password)) { $result['message'] = t('Please enter the required information.'); return $result; } // prevent form hackery - if($roles & ACCOUNT_ROLE_ADMIN) { - $admin_result = check_account_admin($arr); - if(! $admin_result) { - $roles = 0; - } + if (($roles & ACCOUNT_ROLE_ADMIN) && (! check_account_admin($arr))) { + $roles = $roles - ACCOUNT_ROLE_ADMIN; } // allow the admin_email account to be admin, but only if it's the first account. $c = account_total(); - if (($c === 0) && (check_account_admin($arr))) + if (($c === 0) && (check_account_admin($arr))) { $roles |= ACCOUNT_ROLE_ADMIN; + } // Ensure that there is a host keypair. @@ -183,21 +179,21 @@ function create_account($arr) { } $invite_result = check_account_invite($invite_code); - if($invite_result['error']) { + if ($invite_result['error']) { $result['message'] = $invite_result['message']; return $result; } $email_result = check_account_email($email); - if($email_result['error']) { + if ($email_result['error']) { $result['message'] = $email_result['message']; return $result; } $password_result = check_account_password($password); - if($password_result['error']) { + if ($password_result['error']) { $result['message'] = $password_result['message']; return $result; } @@ -219,7 +215,7 @@ function create_account($arr) { 'account_service_class' => $default_service_class ] ); - if(! $r) { + if (! $r) { logger('create_account: DB INSERT failed.'); $result['message'] = t('Failed to store account information.'); return($result); @@ -229,7 +225,7 @@ function create_account($arr) { dbesc($email), dbesc($password_encoded) ); - if($r && count($r)) { + if ($r && count($r)) { $result['account'] = $r[0]; } else { @@ -238,12 +234,12 @@ function create_account($arr) { // Set the parent record to the current record_id if no parent was provided - if(! $parent) { + if (! $parent) { $r = q("update account set account_parent = %d where account_id = %d", intval($result['account']['account_id']), intval($result['account']['account_id']) ); - if(! $r) { + if (! $r) { logger('create_account: failed to set parent'); } $result['account']['parent'] = $result['account']['account_id']; @@ -262,19 +258,19 @@ function create_account($arr) { function verify_email_address($arr) { - if(array_key_exists('resend',$arr)) { + if (array_key_exists('resend',$arr)) { $email = $arr['email']; $a = q("select * from account where account_email = '%s' limit 1", dbesc($arr['email']) ); - if(! ($a && ($a[0]['account_flags'] & ACCOUNT_UNVERIFIED))) { + if (! ($a && ($a[0]['account_flags'] & ACCOUNT_UNVERIFIED))) { return false; } - $account = $a[0]; + $account = array_shift($a); $v = q("select * from register where uid = %d and password = 'verify' limit 1", intval($account['account_id']) ); - if($v) { + if ($v) { $hash = $v[0]['hash']; } else { @@ -317,11 +313,12 @@ function verify_email_address($arr) { pop_lang(); - if($res) + if ($res) { $delivered ++; - else + } + else { logger('send_reg_approval_email: failed to account_id: ' . $arr['account']['account_id']); - + } return $res; } @@ -333,19 +330,21 @@ function send_reg_approval_email($arr) { $r = q("select * from account where (account_roles & %d) >= 4096", intval(ACCOUNT_ROLE_ADMIN) ); - if(! ($r && count($r))) + if (! ($r && count($r))) { return false; + } - $admins = array(); + $admins = []; - foreach($r as $rr) { - if(strlen($rr['account_email'])) { - $admins[] = array('email' => $rr['account_email'], 'lang' => $rr['account_lang']); + foreach ($r as $rr) { + if (strlen($rr['account_email'])) { + $admins[] = [ 'email' => $rr['account_email'], 'lang' => $rr['account_lang'] ]; } } - if(! count($admins)) + if (! count($admins)) { return false; + } $hash = random_string(); @@ -363,20 +362,22 @@ function send_reg_approval_email($arr) { $delivered = 0; - foreach($admins as $admin) { - if(strlen($admin['lang'])) + foreach ($admins as $admin) { + if (strlen($admin['lang'])) { push_lang($admin['lang']); - else + } + else { push_lang('en'); + } - $email_msg = replace_macros(get_intltext_template('register_verify_eml.tpl'), array( + $email_msg = replace_macros(get_intltext_template('register_verify_eml.tpl'), [ '$sitename' => get_config('system','sitename'), '$siteurl' => z_root(), '$email' => $arr['email'], '$uid' => $arr['account']['account_id'], '$hash' => $hash, '$details' => $details - )); + ]); $res = z_mail( [ @@ -386,25 +387,27 @@ function send_reg_approval_email($arr) { ] ); - if($res) + if ($res) { $delivered ++; - else + } + else { logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']); - + } + pop_lang(); } - return($delivered ? true : false); + return ($delivered ? true : false); } function send_register_success_email($email,$password) { - $email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), array( + $email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), [ '$sitename' => get_config('system','sitename'), '$siteurl' => z_root(), '$email' => $email, '$password' => t('your registration password'), - )); + ]); $res = z_mail( [ @@ -414,7 +417,7 @@ function send_register_success_email($email,$password) { ] ); - return($res ? true : false); + return ($res ? true : false); } /** @@ -431,26 +434,27 @@ function account_allow($hash) { dbesc($hash) ); - if(! $register) + if (! $register) { return $ret; + } $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - if(! $account) + if (! $account) return $ret; $r = q("DELETE FROM register WHERE hash = '%s'", dbesc($register[0]['hash']) ); - $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", + $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d) > 0 and account_id = %d", intval(ACCOUNT_BLOCKED), intval(ACCOUNT_BLOCKED), intval($register[0]['uid']) ); - $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", + $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d) > 0 and account_id = %d", intval(ACCOUNT_PENDING), intval(ACCOUNT_PENDING), intval($register[0]['uid']) @@ -459,14 +463,14 @@ function account_allow($hash) { push_lang($register[0]['lang']); $email_tpl = get_intltext_template("register_open_eml.tpl"); - $email_msg = replace_macros($email_tpl, array( - '$sitename' => get_config('system','sitename'), - '$siteurl' => z_root(), - '$username' => $account[0]['account_email'], - '$email' => $account[0]['account_email'], - '$password' => '', - '$uid' => $account[0]['account_id'] - )); + $email_msg = replace_macros($email_tpl, [ + '$sitename' => get_config('system','sitename'), + '$siteurl' => z_root(), + '$username' => $account[0]['account_email'], + '$email' => $account[0]['account_email'], + '$password' => '', + '$uid' => $account[0]['account_id'] + ]); $res = z_mail( [ @@ -478,8 +482,9 @@ function account_allow($hash) { pop_lang(); - if(get_config('system','auto_channel_create')) + if (get_config('system','auto_channel_create')) { auto_channel_create($register[0]['uid']); + } if ($res) { info( t('Account approved.') . EOL ); @@ -505,15 +510,17 @@ function account_deny($hash) { dbesc($hash) ); - if(! count($register)) + if(! $register) { return false; + } $account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - if(! $account) + if (! $account) { return false; + } $r = q("DELETE FROM account WHERE account_id = %d", intval($register[0]['uid']) @@ -540,15 +547,17 @@ function account_approve($hash) { dbesc($hash) ); - if(! $register) + if (! $register) { return $ret; + } $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - if(! $account) + if (! $account) { return $ret; + } $r = q("DELETE FROM register WHERE hash = '%s' and password = 'verify'", dbesc($register[0]['hash']) @@ -576,11 +585,13 @@ function account_approve($hash) { intval($register[0]['uid']) ); - if(! $account) + if (! $account) { return $ret; + } - if(get_config('system','auto_channel_create')) + if(get_config('system','auto_channel_create')) { auto_channel_create($register[0]['uid']); + } else { $_SESSION['login_return_url'] = 'new_channel'; authenticate_success($account[0],null,true,true,false,true); @@ -612,20 +623,21 @@ function downgrade_accounts() { db_getfunc('UTC_TIMESTAMP') ); - if(! $r) + if (! $r) { return; + } $basic = get_config('system','default_service_class'); - foreach($r as $rr) { - if(($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) { + foreach ($r as $rr) { + if (($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) { $x = q("UPDATE account set account_service_class = '%s', account_expires = '%s' where account_id = %d", dbesc($basic), dbesc(NULL_DATE), intval($rr['account_id']) ); - $ret = array('account' => $rr); + $ret = [ 'account' => $rr ]; call_hooks('account_downgrade', $ret ); logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' downgraded.'); } @@ -634,7 +646,7 @@ function downgrade_accounts() { intval(ACCOUNT_EXPIRED), intval($rr['account_id']) ); - $ret = array('account' => $rr); + $ret = [ 'account' => $rr ]; call_hooks('account_downgrade', $ret); logger('downgrade_accounts: Account id ' . $rr['account_id'] . ' expired.'); } @@ -669,13 +681,14 @@ function downgrade_accounts() { function service_class_allows($uid, $property, $usage = false) { $limit = service_class_fetch($uid, $property); - if($limit === false) + if ($limit === false) { return true; // No service class set => everything is allowed - + } + $limit = engr_units_to_bytes($limit); - if($usage === false) { + if ($usage === false) { // We use negative values for not allowed properties in a subscriber plan - return ((x($limit)) ? (bool) $limit : true); + return (($limit) ? (bool) $limit : true); } else { return (((intval($usage)) < intval($limit)) ? true : false); } @@ -706,14 +719,15 @@ function account_service_class_allows($aid, $property, $usage = false) { $limit = account_service_class_fetch($aid, $property); - if($limit === false) + if ($limit === false) { return true; // No service class is set => everything is allowed - + } + $limit = engr_units_to_bytes($limit); - if($usage === false) { + if ($usage === false) { // We use negative values for not allowed properties in a subscriber plan - return ((x($limit)) ? (bool) $limit : true); + return (($limit) ? (bool) $limit : true); } else { return (((intval($usage)) < intval($limit)) ? true : false); } @@ -739,26 +753,27 @@ function account_service_class_allows($aid, $property, $usage = false) { function service_class_fetch($uid, $property) { - if($uid == local_channel()) { + if ($uid == local_channel()) { $service_class = App::$account['account_service_class']; } else { - $r = q("select account_service_class as service_class - from channel c, account a - where c.channel_account_id=a.account_id and c.channel_id= %d limit 1", - intval($uid) + $r = q("select account_service_class + from channel c, account a + where c.channel_account_id = a.account_id and c.channel_id = %d limit 1", + intval($uid) ); - if($r !== false and count($r)) { - $service_class = $r[0]['service_class']; + if ($r) { + $service_class = $r[0]['account_service_class']; } } - if(! x($service_class)) + if (! $service_class) { return false; // everything is allowed - + } $arr = get_config('service_class', $service_class); - if(! is_array($arr) || (! count($arr))) + if (! is_array($arr) || (! count($arr))) { return false; + } return((array_key_exists($property, $arr)) ? $arr[$property] : false); } diff --git a/include/bbcode.php b/include/bbcode.php index 5035dd948..ba703de3c 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1118,7 +1118,9 @@ function bbcode($Text, $options = []) { if (strpos($Text,'[/url]') !== false) { // $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '#^$1', $Text); // $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '#^$2', $Text); + $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '$1', $Text); + $Text = preg_replace("/\@(\!?)\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '@$1$3', $Text); $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$2', $Text); } @@ -1126,6 +1128,7 @@ function bbcode($Text, $options = []) { // $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '#^$1', $Text); // $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '#^$2', $Text); $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '$1', $Text); + $Text = preg_replace("/\@(\!?)\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '@$1$3', $Text); $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '$2', $Text); } diff --git a/include/connections.php b/include/connections.php index 1e65729e3..9e4b378c1 100644 --- a/include/connections.php +++ b/include/connections.php @@ -41,31 +41,37 @@ function abook_store_lowlevel($arr) { function rconnect_url($channel_id,$xchan) { - if(! $xchan) - return ''; + if (! $xchan) { + return EMPTY_STR; + } $r = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1", intval($channel_id), dbesc($xchan) ); - - if($r) - return ''; - + + // Already connected + if ($r) { + return EMPTY_STR; + } + $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($xchan) ); - if(($r) && ($r[0]['xchan_follow'])) + if (($r) && ($r[0]['xchan_follow'])) { return $r[0]['xchan_follow']; + } $r = q("select hubloc_url from hubloc where hubloc_hash = '%s' and hubloc_primary = 1 limit 1", dbesc($xchan) ); - if($r) + if ($r) { return $r[0]['hubloc_url'] . '/follow?f=&url=%s'; - return ''; + } + + return EMPTY_STR; } @@ -98,63 +104,67 @@ function abook_self($channel_id) { function vcard_from_xchan($xchan, $observer = null, $mode = '') { - if(! $xchan) { - if(App::$poi) { + if (! $xchan) { + if (App::$poi) { $xchan = App::$poi; } - elseif(is_array(App::$profile) && App::$profile['channel_hash']) { + elseif (is_array(App::$profile) && App::$profile['channel_hash']) { $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc(App::$profile['channel_hash']) ); - if($r) + if($r) { $xchan = $r[0]; + } } } - if(! $xchan) + if (! $xchan) { return; + } $connect = false; - if(local_channel()) { + if (local_channel()) { $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($xchan['xchan_hash']), intval(local_channel()) ); - if(! $r) + if (! $r) { $connect = t('Connect'); + } } // don't provide a connect button for transient or one-way identities - if(in_array($xchan['xchan_network'],['rss','anon','unknown']) || strpos($xchan['xchan_addr'],'guest:') === 0) { + if (in_array($xchan['xchan_network'],['rss','anon','unknown']) || strpos($xchan['xchan_addr'],'guest:') === 0) { $connect = false; } - if(array_key_exists('channel_id',$xchan)) + if (array_key_exists('channel_id',$xchan)) { App::$profile_uid = $xchan['channel_id']; + } $url = (($observer) ? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr'] : $xchan['xchan_url'] ); - return replace_macros(get_markup_template('xchan_vcard.tpl'),array( + return replace_macros(get_markup_template('xchan_vcard.tpl'), [ '$name' => $xchan['xchan_name'], '$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']), '$follow' => urlencode(($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']), '$link' => zid($xchan['xchan_url']), '$connect' => $connect, - '$newwin' => (($mode === 'chanview') ? t('New window') : ''), + '$newwin' => (($mode === 'chanview') ? t('New window') : EMPTY_STR), '$newtit' => t('Open the selected location in a different window or browser tab'), '$url' => $url, - )); + ]); } function abook_toggle_flag($abook,$flag) { - $field = ''; + $field = EMPTY_STR; - switch($flag) { + switch ($flag) { case ABOOK_FLAG_BLOCKED: $field = 'abook_blocked'; break; @@ -185,15 +195,15 @@ function abook_toggle_flag($abook,$flag) { default: break; } - if(! $field) + if (! $field) { return; + } $r = q("UPDATE abook set $field = (1 - $field) where abook_id = %d and abook_channel = %d", intval($abook['abook_id']), intval($abook['abook_channel']) ); - // if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days. if(($flag === ABOOK_FLAG_ARCHIVED) && (intval($abook['abook_archived']))) { @@ -224,8 +234,9 @@ function abook_toggle_flag($abook,$flag) { function mark_orphan_hubsxchans() { $dirmode = intval(get_config('system','directory_mode')); - if($dirmode == DIRECTORY_MODE_NORMAL) + if ($dirmode == DIRECTORY_MODE_NORMAL) { return; + } $r = q("update hubloc set hubloc_deleted = 1 where hubloc_deleted = 0 and hubloc_network = 'zot6' and hubloc_connected < %s - interval %s", @@ -234,7 +245,7 @@ function mark_orphan_hubsxchans() { $r = q("select hubloc_id, hubloc_hash from hubloc where hubloc_deleted = 1 and hubloc_orphancheck = 0"); - if($r) { + if ($r) { foreach($r as $rr) { // see if any other hublocs are still alive for this channel @@ -242,14 +253,13 @@ function mark_orphan_hubsxchans() { $x = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0", dbesc($rr['hubloc_hash']) ); - if($x) { + if ($x) { // yes - if the xchan was marked as an orphan, undo it $y = q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'", dbesc($rr['hubloc_hash']) ); - } else { @@ -278,7 +288,7 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) { // $channel_id is reserved for future use. - if(intval($channel_id) === 0) { + if (intval($channel_id) === 0) { if (! $xchan) { return; @@ -488,9 +498,11 @@ function random_profile() { $checkrandom = get_config('randprofile','check'); // False by default $retryrandom = intval(get_config('randprofile','retry')); - if($retryrandom == 0) $retryrandom = 5; - - for($i = 0; $i < $retryrandom; $i++) { + if ($retryrandom == 0) { + $retryrandom = 5; + } + + for ($i = 0; $i < $retryrandom; $i++) { $r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where xchan_hidden = 0 and xchan_system = 0 and @@ -500,21 +512,24 @@ function random_profile() { db_quoteinterval('30 day') ); - if(!$r) return ''; // Couldn't get a random channel - - if($checkrandom) { + if (!$r) { + return EMPTY_STR; // Couldn't get a random channel + } + if ($checkrandom) { $x = z_fetch_url($r[0]['xchan_url']); - if($x['success']) + if ($x['success']) { return $r[0]['xchan_hash']; - else + } + else { logger('Random channel turned out to be bad.'); + } } else { return $r[0]['xchan_hash']; } } - return ''; + return EMPTY_STR; } function update_vcard($arr,$vcard = null) { @@ -536,7 +551,7 @@ function update_vcard($arr,$vcard = null) { // right is to provide a form to input all the various fields and not // try to extract it from the FN. - if(! $vcard) { + if (! $vcard) { $vcard = new \Sabre\VObject\Component\VCard([ 'FN' => $fn, 'N' => array_reverse(explode(' ', $fn)) diff --git a/include/event.php b/include/event.php index c6c4436c3..b393fabbc 100644 --- a/include/event.php +++ b/include/event.php @@ -1064,7 +1064,8 @@ function event_store_item($arr, $event) { $x = [ 'type' => 'Event', 'id' => z_root() . '/event/' . $r[0]['resource_id'], - 'summary' => bbcode($arr['summary']), + 'name' => $arr['summary'], +// 'summary' => bbcode($arr['summary']), // RFC3339 Section 4.3 'startTime' => (($arr['adjust']) ? datetime_convert('UTC','UTC',$arr['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$arr['dtstart'],'Y-m-d\\TH:i:s-00:00')), 'content' => bbcode($arr['description']), @@ -1217,7 +1218,8 @@ function event_store_item($arr, $event) { $y = [ 'type' => 'Event', 'id' => z_root() . '/event/' . $event['event_hash'], - 'summary' => bbcode($arr['summary']), + 'name' => $arr['summary'], +// 'summary' => bbcode($arr['summary']), // RFC3339 Section 4.3 'startTime' => (($arr['adjust']) ? datetime_convert('UTC','UTC',$arr['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$arr['dtstart'],'Y-m-d\\TH:i:s-00:00')), 'content' => bbcode($arr['description']), diff --git a/include/features.php b/include/features.php index 9ce7813a9..ad35110ee 100644 --- a/include/features.php +++ b/include/features.php @@ -59,7 +59,7 @@ function get_features($filtered = true, $level = (-1)) { 'start_menu', t('New Member Links'), t('Display new member quick links menu'), - (($account['account_created'] > datetime_convert('','','now - 60 days')) ? true : false), + (($account['account_created'] > datetime_convert('','','now - 30 days')) ? true : false), get_config('feature_lock','start_menu'), feature_level('start_menu',1), ], From 6efbf3fb437a8b0c80262e932f752209f8271741 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 17 Sep 2019 21:27:38 -0700 Subject: [PATCH 11/11] rev update --- boot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot.php b/boot.php index 592eade60..e0d747691 100755 --- a/boot.php +++ b/boot.php @@ -48,7 +48,7 @@ require_once('include/items.php'); -define ( 'STD_VERSION', '19.9.17' ); +define ( 'STD_VERSION', '19.9.18' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1236 );